Rob Pike | dee4db0 | 2010-06-14 15:00:19 -0700 | [diff] [blame] | 1 | // $G $F.go && $L $F.$A && ./$A.out |
| 2 | |
| 3 | // Copyright 2010 The Go Authors. All rights reserved. |
| 4 | // Use of this source code is governed by a BSD-style |
| 5 | // license that can be found in the LICENSE file. |
| 6 | |
| 7 | package main |
| 8 | |
| 9 | import ( |
| 10 | "fmt" |
| 11 | "math" |
| 12 | "strings" |
Christopher Wedgwood | 34cc011 | 2010-06-18 22:42:48 -0700 | [diff] [blame] | 13 | "syscall" |
Rob Pike | dee4db0 | 2010-06-14 15:00:19 -0700 | [diff] [blame] | 14 | ) |
| 15 | |
| 16 | type Error interface { |
| 17 | String() string |
| 18 | } |
| 19 | |
| 20 | type ErrorTest struct { |
| 21 | name string |
| 22 | fn func() |
| 23 | err string |
| 24 | } |
| 25 | |
| 26 | var ( |
| 27 | i, j, k int = 0, 0, 1 |
| 28 | i8, j8, k8 int8 = 0, 0, 1 |
| 29 | i16, j16, k16 int16 = 0, 0, 1 |
| 30 | i32, j32, k32 int32 = 0, 0, 1 |
| 31 | i64, j64, k64 int64 = 0, 0, 1 |
| 32 | |
| 33 | u, v, w uint = 0, 0, 1 |
| 34 | u8, v8, w8 uint8 = 0, 0, 1 |
| 35 | u16, v16, w16 uint16 = 0, 0, 1 |
| 36 | u32, v32, w32 uint32 = 0, 0, 1 |
| 37 | u64, v64, w64 uint64 = 0, 0, 1 |
| 38 | up, vp, wp uintptr = 0, 0, 1 |
| 39 | |
| 40 | f, g, h float = 0, 0, 1 |
| 41 | f32, g32, h32 float32 = 0, 0, 1 |
| 42 | f64, g64, h64, inf, negInf, nan float64 = 0, 0, 1, math.Inf(1), math.Inf(-1), math.NaN() |
| 43 | |
| 44 | c, d, e complex = 0+0i, 0+0i, 1+1i |
| 45 | c64, d64, e64 complex64 = 0+0i, 0+0i, 1+1i |
| 46 | c128, d128, e128 complex128 = 0+0i, 0+0i, 1+1i |
| 47 | ) |
| 48 | |
| 49 | var tmp interface{} |
| 50 | |
| 51 | // We could assign to _ but the compiler optimizes it too easily. |
| 52 | func use(v interface{}) { |
| 53 | tmp = v |
| 54 | } |
| 55 | |
| 56 | // Verify error/no error for all types. |
| 57 | var errorTests = []ErrorTest{ |
| 58 | // All integer divide by zero should error. |
| 59 | ErrorTest{ "int 0/0", func() { use(i/j) }, "divide", }, |
Russ Cox | c9172fb | 2010-06-14 18:07:17 -0700 | [diff] [blame] | 60 | ErrorTest{ "int8 0/0", func() { use(i8/j8) }, "divide", }, |
Rob Pike | dee4db0 | 2010-06-14 15:00:19 -0700 | [diff] [blame] | 61 | ErrorTest{ "int16 0/0", func() { use(i16/j16) }, "divide", }, |
| 62 | ErrorTest{ "int32 0/0", func() { use(i32/j32) }, "divide", }, |
| 63 | ErrorTest{ "int64 0/0", func() { use(i64/j64) }, "divide", }, |
| 64 | |
| 65 | ErrorTest{ "int 1/0", func() { use(k/j) }, "divide", }, |
Russ Cox | c9172fb | 2010-06-14 18:07:17 -0700 | [diff] [blame] | 66 | ErrorTest{ "int8 1/0", func() { use(k8/j8) }, "divide", }, |
Rob Pike | dee4db0 | 2010-06-14 15:00:19 -0700 | [diff] [blame] | 67 | ErrorTest{ "int16 1/0", func() { use(k16/j16) }, "divide", }, |
| 68 | ErrorTest{ "int32 1/0", func() { use(k32/j32) }, "divide", }, |
| 69 | ErrorTest{ "int64 1/0", func() { use(k64/j64) }, "divide", }, |
| 70 | |
| 71 | ErrorTest{ "uint 0/0", func() { use(u/v) }, "divide", }, |
Russ Cox | c9172fb | 2010-06-14 18:07:17 -0700 | [diff] [blame] | 72 | ErrorTest{ "uint8 0/0", func() { use(u8/v8) }, "divide", }, |
Rob Pike | dee4db0 | 2010-06-14 15:00:19 -0700 | [diff] [blame] | 73 | ErrorTest{ "uint16 0/0", func() { use(u16/v16) }, "divide", }, |
| 74 | ErrorTest{ "uint32 0/0", func() { use(u32/v32) }, "divide", }, |
| 75 | ErrorTest{ "uint64 0/0", func() { use(u64/v64) }, "divide", }, |
| 76 | ErrorTest{ "uintptr 0/0", func() { use(up/vp) }, "divide", }, |
| 77 | |
| 78 | ErrorTest{ "uint 1/0", func() { use(w/v) }, "divide", }, |
Russ Cox | c9172fb | 2010-06-14 18:07:17 -0700 | [diff] [blame] | 79 | ErrorTest{ "uint8 1/0", func() { use(w8/v8) }, "divide", }, |
Rob Pike | dee4db0 | 2010-06-14 15:00:19 -0700 | [diff] [blame] | 80 | ErrorTest{ "uint16 1/0", func() { use(w16/v16) }, "divide", }, |
| 81 | ErrorTest{ "uint32 1/0", func() { use(w32/v32) }, "divide", }, |
| 82 | ErrorTest{ "uint64 1/0", func() { use(w64/v64) }, "divide", }, |
| 83 | ErrorTest{ "uintptr 1/0", func() { use(wp/vp) }, "divide", }, |
| 84 | |
| 85 | // All floating divide by zero should not error. |
| 86 | ErrorTest{ "float 0/0", func() { use(f/g) }, "", }, |
| 87 | ErrorTest{ "float32 0/0", func() { use(f32/g32) }, "", }, |
| 88 | ErrorTest{ "float64 0/0", func() { use(f64/g64) }, "", }, |
| 89 | |
| 90 | ErrorTest{ "float 1/0", func() { use(h/g) }, "", }, |
| 91 | ErrorTest{ "float32 1/0", func() { use(h32/g32) }, "", }, |
| 92 | ErrorTest{ "float64 1/0", func() { use(h64/g64) }, "", }, |
| 93 | ErrorTest{ "float64 inf/0", func() { use(inf/g64) }, "", }, |
| 94 | ErrorTest{ "float64 -inf/0", func() { use(negInf/g64) }, "", }, |
| 95 | ErrorTest{ "float64 nan/0", func() { use(nan/g64) }, "", }, |
| 96 | |
| 97 | // All complex divide by zero should not error. |
| 98 | ErrorTest{ "complex 0/0", func() { use(c/d) }, "", }, |
| 99 | ErrorTest{ "complex64 0/0", func() { use(c64/d64) }, "", }, |
| 100 | ErrorTest{ "complex128 0/0", func() { use(c128/d128) }, "", }, |
| 101 | |
| 102 | ErrorTest{ "complex 1/0", func() { use(e/d) }, "", }, |
| 103 | ErrorTest{ "complex64 1/0", func() { use(e64/d64) }, "", }, |
| 104 | ErrorTest{ "complex128 1/0", func() { use(e128/d128) }, "", }, |
| 105 | } |
| 106 | |
| 107 | func error(fn func()) (error string) { |
| 108 | defer func() { |
| 109 | if e := recover(); e != nil { |
| 110 | error = e.(Error).String() |
| 111 | } |
| 112 | }() |
| 113 | fn() |
| 114 | return "" |
| 115 | } |
| 116 | |
| 117 | type FloatTest struct{ |
Rob Pike | dee4db0 | 2010-06-14 15:00:19 -0700 | [diff] [blame] | 118 | f, g float64 |
| 119 | out float64 |
| 120 | } |
| 121 | |
| 122 | var floatTests = []FloatTest{ |
Russ Cox | 21ff75b | 2010-06-18 15:46:00 -0700 | [diff] [blame] | 123 | FloatTest{0, 0, nan}, |
| 124 | FloatTest{nan, 0, nan}, |
| 125 | FloatTest{inf, 0, inf}, |
| 126 | FloatTest{negInf, 0, negInf}, |
Rob Pike | dee4db0 | 2010-06-14 15:00:19 -0700 | [diff] [blame] | 127 | } |
| 128 | |
| 129 | func alike(a, b float64) bool { |
| 130 | switch { |
| 131 | case math.IsNaN(a) && math.IsNaN(b): |
| 132 | return true |
| 133 | case a == b: |
| 134 | return math.Signbit(a) == math.Signbit(b) |
| 135 | } |
| 136 | return false |
| 137 | } |
| 138 | |
| 139 | func main() { |
Kai Backman | 36057e7 | 2010-07-20 15:53:16 +0300 | [diff] [blame] | 140 | bad := false |
Rob Pike | dee4db0 | 2010-06-14 15:00:19 -0700 | [diff] [blame] | 141 | for _, t := range errorTests { |
Russ Cox | 21ff75b | 2010-06-18 15:46:00 -0700 | [diff] [blame] | 142 | if t.err != "" && syscall.OS == "nacl" { |
| 143 | continue |
| 144 | } |
Rob Pike | dee4db0 | 2010-06-14 15:00:19 -0700 | [diff] [blame] | 145 | err := error(t.fn) |
| 146 | switch { |
| 147 | case t.err == "" && err == "": |
| 148 | // fine |
| 149 | case t.err != "" && err == "": |
Kai Backman | 8d76a15 | 2010-07-30 10:37:51 +0300 | [diff] [blame^] | 150 | if !bad { |
| 151 | bad = true |
| 152 | fmt.Printf("BUG\n") |
| 153 | } |
Rob Pike | dee4db0 | 2010-06-14 15:00:19 -0700 | [diff] [blame] | 154 | fmt.Printf("%s: expected %q; got no error\n", t.name, t.err) |
| 155 | case t.err == "" && err != "": |
Kai Backman | 8d76a15 | 2010-07-30 10:37:51 +0300 | [diff] [blame^] | 156 | if !bad { |
| 157 | bad = true |
| 158 | fmt.Printf("BUG\n") |
| 159 | } |
Rob Pike | dee4db0 | 2010-06-14 15:00:19 -0700 | [diff] [blame] | 160 | fmt.Printf("%s: expected no error; got %q\n", t.name, err) |
| 161 | case t.err != "" && err != "": |
Kai Backman | 8d76a15 | 2010-07-30 10:37:51 +0300 | [diff] [blame^] | 162 | if !bad { |
| 163 | bad = true |
| 164 | fmt.Printf("BUG\n") |
| 165 | } |
Rob Pike | dee4db0 | 2010-06-14 15:00:19 -0700 | [diff] [blame] | 166 | if strings.Index(err, t.err) < 0 { |
| 167 | fmt.Printf("%s: expected %q; got %q\n", t.name, t.err, err) |
| 168 | continue |
| 169 | } |
| 170 | } |
| 171 | } |
| 172 | |
| 173 | // At this point we know we don't error on the values we're testing |
| 174 | for _, t := range floatTests { |
| 175 | x := t.f/t.g |
| 176 | if !alike(x, t.out) { |
Kai Backman | 36057e7 | 2010-07-20 15:53:16 +0300 | [diff] [blame] | 177 | if !bad { |
| 178 | bad = true |
| 179 | fmt.Printf("BUG\n") |
| 180 | } |
Russ Cox | 21ff75b | 2010-06-18 15:46:00 -0700 | [diff] [blame] | 181 | fmt.Printf("%v/%v: expected %g error; got %g\n", t.f, t.g, t.out, x) |
Rob Pike | dee4db0 | 2010-06-14 15:00:19 -0700 | [diff] [blame] | 182 | } |
| 183 | } |
| 184 | } |