LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2013 The Go Authors. All rights reserved. | 1 // Copyright 2013 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package exact | 5 package exact |
6 | 6 |
7 import ( | 7 import ( |
8 "go/token" | 8 "go/token" |
9 "strings" | 9 "strings" |
10 "testing" | 10 "testing" |
11 ) | 11 ) |
12 | 12 |
13 // TODO(gri) expand this test framework | 13 // TODO(gri) expand this test framework |
14 | 14 |
15 var tests = []string{ | 15 var opTests = []string{ |
16 // unary operations | 16 // unary operations |
17 `+ 0 = 0`, | 17 `+ 0 = 0`, |
| 18 `+ ? = ?`, |
18 `- 1 = -1`, | 19 `- 1 = -1`, |
| 20 `- ? = ?`, |
19 `^ 0 = -1`, | 21 `^ 0 = -1`, |
| 22 `^ ? = ?`, |
20 | 23 |
21 `! true = false`, | 24 `! true = false`, |
22 `! false = true`, | 25 `! false = true`, |
| 26 `! ? = ?`, |
| 27 |
23 // etc. | 28 // etc. |
24 | 29 |
25 // binary operations | 30 // binary operations |
26 `"" + "" = ""`, | 31 `"" + "" = ""`, |
27 `"foo" + "" = "foo"`, | 32 `"foo" + "" = "foo"`, |
28 `"" + "bar" = "bar"`, | 33 `"" + "bar" = "bar"`, |
29 `"foo" + "bar" = "foobar"`, | 34 `"foo" + "bar" = "foobar"`, |
30 | 35 |
31 `0 + 0 = 0`, | 36 `0 + 0 = 0`, |
32 `0 + 0.1 = 0.1`, | 37 `0 + 0.1 = 0.1`, |
33 `0 + 0.1i = 0.1i`, | 38 `0 + 0.1i = 0.1i`, |
34 `0.1 + 0.9 = 1`, | 39 `0.1 + 0.9 = 1`, |
35 `1e100 + 1e100 = 2e100`, | 40 `1e100 + 1e100 = 2e100`, |
| 41 `? + 0 = ?`, |
| 42 `0 + ? = ?`, |
36 | 43 |
37 `0 - 0 = 0`, | 44 `0 - 0 = 0`, |
38 `0 - 0.1 = -0.1`, | 45 `0 - 0.1 = -0.1`, |
39 `0 - 0.1i = -0.1i`, | 46 `0 - 0.1i = -0.1i`, |
40 `1e100 - 1e100 = 0`, | 47 `1e100 - 1e100 = 0`, |
| 48 `? - 0 = ?`, |
| 49 `0 - ? = ?`, |
41 | 50 |
42 `0 * 0 = 0`, | 51 `0 * 0 = 0`, |
43 `1 * 0.1 = 0.1`, | 52 `1 * 0.1 = 0.1`, |
44 `1 * 0.1i = 0.1i`, | 53 `1 * 0.1i = 0.1i`, |
45 `1i * 1i = -1`, | 54 `1i * 1i = -1`, |
| 55 `? * 0 = ?`, |
| 56 `0 * ? = ?`, |
46 | 57 |
47 `0 / 0 = "division_by_zero"`, | 58 `0 / 0 = "division_by_zero"`, |
48 `10 / 2 = 5`, | 59 `10 / 2 = 5`, |
49 `5 / 3 = 5/3`, | 60 `5 / 3 = 5/3`, |
50 `5i / 3i = 5/3`, | 61 `5i / 3i = 5/3`, |
| 62 `? / 0 = ?`, |
| 63 `0 / ? = ?`, |
51 | 64 |
52 `0 % 0 = "runtime_error:_integer_divide_by_zero"`, // TODO(gri) should b
e the same as for / | 65 `0 % 0 = "runtime_error:_integer_divide_by_zero"`, // TODO(gri) should b
e the same as for / |
53 `10 % 3 = 1`, | 66 `10 % 3 = 1`, |
| 67 `? % 0 = ?`, |
| 68 `0 % ? = ?`, |
54 | 69 |
55 `0 & 0 = 0`, | 70 `0 & 0 = 0`, |
56 `12345 & 0 = 0`, | 71 `12345 & 0 = 0`, |
57 `0xff & 0xf = 0xf`, | 72 `0xff & 0xf = 0xf`, |
| 73 `? & 0 = ?`, |
| 74 `0 & ? = ?`, |
58 | 75 |
59 `0 | 0 = 0`, | 76 `0 | 0 = 0`, |
60 `12345 | 0 = 12345`, | 77 `12345 | 0 = 12345`, |
61 `0xb | 0xa0 = 0xab`, | 78 `0xb | 0xa0 = 0xab`, |
| 79 `? | 0 = ?`, |
| 80 `0 | ? = ?`, |
62 | 81 |
63 `0 ^ 0 = 0`, | 82 `0 ^ 0 = 0`, |
64 `1 ^ -1 = -2`, | 83 `1 ^ -1 = -2`, |
| 84 `? ^ 0 = ?`, |
| 85 `0 ^ ? = ?`, |
65 | 86 |
66 `0 &^ 0 = 0`, | 87 `0 &^ 0 = 0`, |
67 `0xf &^ 1 = 0xe`, | 88 `0xf &^ 1 = 0xe`, |
68 `1 &^ 0xf = 0`, | 89 `1 &^ 0xf = 0`, |
69 // etc. | 90 // etc. |
70 | 91 |
71 // shifts | 92 // shifts |
72 `0 << 0 = 0`, | 93 `0 << 0 = 0`, |
73 `1 << 10 = 1024`, | 94 `1 << 10 = 1024`, |
74 `0 >> 0 = 0`, | 95 `0 >> 0 = 0`, |
75 `1024 >> 10 == 1`, | 96 `1024 >> 10 == 1`, |
| 97 `? << 0 == ?`, |
| 98 `? >> 10 == ?`, |
76 // etc. | 99 // etc. |
77 | 100 |
78 // comparisons | 101 // comparisons |
79 `false == false = true`, | 102 `false == false = true`, |
80 `false == true = false`, | 103 `false == true = false`, |
81 `true == false = false`, | 104 `true == false = false`, |
82 `true == true = true`, | 105 `true == true = true`, |
83 | 106 |
84 `false != false = false`, | 107 `false != false = false`, |
85 `false != true = true`, | 108 `false != true = true`, |
(...skipping 13 matching lines...) Expand all Loading... |
99 `10 <= 10 = true`, | 122 `10 <= 10 = true`, |
100 `0 > 10 = false`, | 123 `0 > 10 = false`, |
101 `10 >= 10 = true`, | 124 `10 >= 10 = true`, |
102 | 125 |
103 `1/123456789 == 1/123456789 == true`, | 126 `1/123456789 == 1/123456789 == true`, |
104 `1/123456789 != 1/123456789 == false`, | 127 `1/123456789 != 1/123456789 == false`, |
105 `1/123456789 < 1/123456788 == true`, | 128 `1/123456789 < 1/123456788 == true`, |
106 `1/123456788 <= 1/123456789 == false`, | 129 `1/123456788 <= 1/123456789 == false`, |
107 `0.11 > 0.11 = false`, | 130 `0.11 > 0.11 = false`, |
108 `0.11 >= 0.11 = true`, | 131 `0.11 >= 0.11 = true`, |
| 132 |
| 133 `? == 0 = false`, |
| 134 `? != 0 = false`, |
| 135 `? < 10 = false`, |
| 136 `? <= 10 = false`, |
| 137 `? > 10 = false`, |
| 138 `? >= 10 = false`, |
| 139 |
| 140 `0 == ? = false`, |
| 141 `0 != ? = false`, |
| 142 `0 < ? = false`, |
| 143 `10 <= ? = false`, |
| 144 `0 > ? = false`, |
| 145 `10 >= ? = false`, |
| 146 |
109 // etc. | 147 // etc. |
110 } | 148 } |
111 | 149 |
112 func TestOps(t *testing.T) { | 150 func TestOps(t *testing.T) { |
113 » for _, test := range tests { | 151 » for _, test := range opTests { |
114 a := strings.Split(test, " ") | 152 a := strings.Split(test, " ") |
115 i := 0 // operator index | 153 i := 0 // operator index |
116 | 154 |
117 var x, x0 Value | 155 var x, x0 Value |
118 switch len(a) { | 156 switch len(a) { |
119 case 4: | 157 case 4: |
120 // unary operation | 158 // unary operation |
121 case 5: | 159 case 5: |
122 // binary operation | 160 // binary operation |
123 x, x0 = val(a[0]), val(a[0]) | 161 x, x0 = val(a[0]), val(a[0]) |
124 i = 1 | 162 i = 1 |
125 default: | 163 default: |
126 t.Errorf("invalid test case: %s", test) | 164 t.Errorf("invalid test case: %s", test) |
127 continue | 165 continue |
128 } | 166 } |
129 | 167 |
130 op, ok := optab[a[i]] | 168 op, ok := optab[a[i]] |
131 if !ok { | 169 if !ok { |
132 panic("missing optab entry for " + a[i]) | 170 panic("missing optab entry for " + a[i]) |
133 } | 171 } |
134 | 172 |
135 y, y0 := val(a[i+1]), val(a[i+1]) | 173 y, y0 := val(a[i+1]), val(a[i+1]) |
136 | 174 |
137 got := doOp(x, op, y) | 175 got := doOp(x, op, y) |
138 want := val(a[i+3]) | 176 want := val(a[i+3]) |
139 » » if !Compare(got, token.EQL, want) { | 177 » » if !eql(got, want) { |
140 t.Errorf("%s: got %s; want %s", test, got, want) | 178 t.Errorf("%s: got %s; want %s", test, got, want) |
141 } | 179 } |
142 » » if x0 != nil && !Compare(x, token.EQL, x0) { | 180 » » if x0 != nil && !eql(x, x0) { |
143 t.Errorf("%s: x changed to %s", test, x) | 181 t.Errorf("%s: x changed to %s", test, x) |
144 } | 182 } |
145 » » if !Compare(y, token.EQL, y0) { | 183 » » if !eql(y, y0) { |
146 t.Errorf("%s: y changed to %s", test, y) | 184 t.Errorf("%s: y changed to %s", test, y) |
147 } | 185 } |
148 } | 186 } |
| 187 } |
| 188 |
| 189 func eql(x, y Value) bool { |
| 190 _, ux := x.(unknownVal) |
| 191 _, uy := y.(unknownVal) |
| 192 if ux || uy { |
| 193 return ux == uy |
| 194 } |
| 195 return Compare(x, token.EQL, y) |
149 } | 196 } |
150 | 197 |
151 // ---------------------------------------------------------------------------- | 198 // ---------------------------------------------------------------------------- |
152 // Support functions | 199 // Support functions |
153 | 200 |
154 func val(lit string) Value { | 201 func val(lit string) Value { |
155 if len(lit) == 0 { | 202 if len(lit) == 0 { |
156 return MakeUnknown() | 203 return MakeUnknown() |
157 } | 204 } |
158 | 205 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 switch op { | 278 switch op { |
232 case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GTR, token.GEQ: | 279 case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GTR, token.GEQ: |
233 return MakeBool(Compare(x, op, y)) | 280 return MakeBool(Compare(x, op, y)) |
234 case token.SHL, token.SHR: | 281 case token.SHL, token.SHR: |
235 s, _ := Int64Val(y) | 282 s, _ := Int64Val(y) |
236 return Shift(x, op, uint(s)) | 283 return Shift(x, op, uint(s)) |
237 default: | 284 default: |
238 return BinaryOp(x, op, y) | 285 return BinaryOp(x, op, y) |
239 } | 286 } |
240 } | 287 } |
| 288 |
| 289 // ---------------------------------------------------------------------------- |
| 290 // Other tests |
| 291 |
| 292 var fracTests = []string{ |
| 293 "0 0 1", |
| 294 "1 1 1", |
| 295 "-1 -1 1", |
| 296 "1.2 6 5", |
| 297 "-0.991 -991 1000", |
| 298 "1e100 1e100 1", |
| 299 } |
| 300 |
| 301 func TestFractions(t *testing.T) { |
| 302 for _, test := range fracTests { |
| 303 a := strings.Split(test, " ") |
| 304 if len(a) != 3 { |
| 305 t.Errorf("invalid test case: %s", test) |
| 306 continue |
| 307 } |
| 308 |
| 309 x := val(a[0]) |
| 310 n := val(a[1]) |
| 311 d := val(a[2]) |
| 312 |
| 313 if got := Num(x); !eql(got, n) { |
| 314 t.Errorf("%s: got num = %s; want %s", test, got, n) |
| 315 } |
| 316 |
| 317 if got := Denom(x); !eql(got, d) { |
| 318 t.Errorf("%s: got denom = %s; want %s", test, got, d) |
| 319 } |
| 320 } |
| 321 } |
| 322 |
| 323 var bytesTests = []string{ |
| 324 "0", |
| 325 "1", |
| 326 "123456789", |
| 327 "123456789012345678901234567890123456789012345678901234567890", |
| 328 } |
| 329 |
| 330 func TestBytes(t *testing.T) { |
| 331 for _, test := range bytesTests { |
| 332 x := val(test) |
| 333 bytes := Bytes(x) |
| 334 |
| 335 // special case 0 |
| 336 if Sign(x) == 0 && len(bytes) != 0 { |
| 337 t.Errorf("%s: got %v; want empty byte slice", test, byte
s) |
| 338 } |
| 339 |
| 340 if n := len(bytes); n > 0 && bytes[n-1] == 0 { |
| 341 t.Errorf("%s: got %v; want no leading 0 byte", test, byt
es) |
| 342 } |
| 343 |
| 344 if got := MakeFromBytes(bytes); !eql(got, x) { |
| 345 t.Errorf("%s: got %s; want %s (bytes = %v)", test, got,
x, bytes) |
| 346 } |
| 347 } |
| 348 } |
LEFT | RIGHT |