github.com/grumpyhome/grumpy@v0.3.1-0.20201208125205-7b775405bdf1/grumpy-runtime-src/runtime/int_test.go (about) 1 // Copyright 2016 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package grumpy 16 17 import ( 18 "math/big" 19 "runtime" 20 "testing" 21 ) 22 23 func TestIntBinaryOps(t *testing.T) { 24 cases := []struct { 25 fun binaryOpFunc 26 v, w *Object 27 want *Object 28 wantExc *BaseException 29 }{ 30 {Add, NewInt(-100).ToObject(), NewInt(50).ToObject(), NewInt(-50).ToObject(), nil}, 31 {Add, newObject(ObjectType), NewInt(-100).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for +: 'object' and 'int'")}, 32 {Add, NewInt(MaxInt).ToObject(), NewInt(1).ToObject(), NewLong(new(big.Int).Add(maxIntBig, big.NewInt(1))).ToObject(), nil}, 33 {And, NewInt(-100).ToObject(), NewInt(50).ToObject(), NewInt(16).ToObject(), nil}, 34 {And, NewInt(MaxInt).ToObject(), NewInt(MinInt).ToObject(), NewInt(0).ToObject(), nil}, 35 {And, newObject(ObjectType), NewInt(-100).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for &: 'object' and 'int'")}, 36 {Div, NewInt(7).ToObject(), NewInt(3).ToObject(), NewInt(2).ToObject(), nil}, 37 {Div, NewInt(MaxInt).ToObject(), NewInt(MinInt).ToObject(), NewInt(-1).ToObject(), nil}, 38 {Div, NewInt(MinInt).ToObject(), NewInt(MaxInt).ToObject(), NewInt(-2).ToObject(), nil}, 39 {Div, NewList().ToObject(), NewInt(21).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for /: 'list' and 'int'")}, 40 {Div, NewInt(1).ToObject(), NewInt(0).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "integer division or modulo by zero")}, 41 {Div, NewInt(MinInt).ToObject(), NewInt(-1).ToObject(), NewLong(new(big.Int).Neg(minIntBig)).ToObject(), nil}, 42 {DivMod, NewInt(7).ToObject(), NewInt(3).ToObject(), NewTuple2(NewInt(2).ToObject(), NewInt(1).ToObject()).ToObject(), nil}, 43 {DivMod, NewInt(3).ToObject(), NewInt(-7).ToObject(), NewTuple2(NewInt(-1).ToObject(), NewInt(-4).ToObject()).ToObject(), nil}, 44 {DivMod, NewInt(MaxInt).ToObject(), NewInt(MinInt).ToObject(), NewTuple2(NewInt(-1).ToObject(), NewInt(-1).ToObject()).ToObject(), nil}, 45 {DivMod, NewInt(MinInt).ToObject(), NewInt(MaxInt).ToObject(), NewTuple2(NewInt(-2).ToObject(), NewInt(MaxInt-1).ToObject()).ToObject(), nil}, 46 {DivMod, NewList().ToObject(), NewInt(21).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for divmod(): 'list' and 'int'")}, 47 {DivMod, NewInt(1).ToObject(), NewInt(0).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "integer division or modulo by zero")}, 48 {DivMod, NewInt(MinInt).ToObject(), NewInt(-1).ToObject(), NewTuple2(NewLong(new(big.Int).Neg(minIntBig)).ToObject(), NewLong(big.NewInt(0)).ToObject()).ToObject(), nil}, 49 {FloorDiv, NewInt(7).ToObject(), NewInt(3).ToObject(), NewInt(2).ToObject(), nil}, 50 {FloorDiv, NewInt(MaxInt).ToObject(), NewInt(MinInt).ToObject(), NewInt(-1).ToObject(), nil}, 51 {FloorDiv, NewInt(MinInt).ToObject(), NewInt(MaxInt).ToObject(), NewInt(-2).ToObject(), nil}, 52 {FloorDiv, NewList().ToObject(), NewInt(21).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for //: 'list' and 'int'")}, 53 {FloorDiv, NewInt(1).ToObject(), NewInt(0).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "integer division or modulo by zero")}, 54 {FloorDiv, NewInt(MinInt).ToObject(), NewInt(-1).ToObject(), NewLong(new(big.Int).Neg(minIntBig)).ToObject(), nil}, 55 {LShift, NewInt(2).ToObject(), NewInt(4).ToObject(), NewInt(32).ToObject(), nil}, 56 {LShift, NewInt(-12).ToObject(), NewInt(10).ToObject(), NewInt(-12288).ToObject(), nil}, 57 {LShift, NewInt(10).ToObject(), NewInt(100).ToObject(), NewLong(new(big.Int).Lsh(big.NewInt(10), 100)).ToObject(), nil}, 58 {LShift, NewInt(2).ToObject(), NewInt(-5).ToObject(), nil, mustCreateException(ValueErrorType, "negative shift count")}, 59 {LShift, NewInt(4).ToObject(), NewFloat(3.14).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for <<: 'int' and 'float'")}, 60 {LShift, newObject(ObjectType), NewInt(4).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for <<: 'object' and 'int'")}, 61 {RShift, NewInt(87).ToObject(), NewInt(3).ToObject(), NewInt(10).ToObject(), nil}, 62 {RShift, NewInt(-101).ToObject(), NewInt(5).ToObject(), NewInt(-4).ToObject(), nil}, 63 {RShift, NewInt(12).ToObject(), NewInt(10).ToObject(), NewInt(0).ToObject(), nil}, 64 {RShift, NewInt(12).ToObject(), NewInt(-10).ToObject(), nil, mustCreateException(ValueErrorType, "negative shift count")}, 65 {RShift, NewInt(4).ToObject(), NewFloat(3.14).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for >>: 'int' and 'float'")}, 66 {RShift, newObject(ObjectType), NewInt(4).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for >>: 'object' and 'int'")}, 67 {RShift, NewInt(4).ToObject(), newObject(ObjectType), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for >>: 'int' and 'object'")}, 68 {Mod, NewInt(3).ToObject(), NewInt(-7).ToObject(), NewInt(-4).ToObject(), nil}, 69 {Mod, NewInt(MaxInt).ToObject(), NewInt(MinInt).ToObject(), NewInt(-1).ToObject(), nil}, 70 {Mod, NewInt(MinInt).ToObject(), NewInt(MaxInt).ToObject(), NewInt(MaxInt - 1).ToObject(), nil}, 71 {Mod, None, NewInt(-4).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for %: 'NoneType' and 'int'")}, 72 {Mod, NewInt(10).ToObject(), NewInt(0).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "integer division or modulo by zero")}, 73 {Mod, NewInt(MinInt).ToObject(), NewInt(-1).ToObject(), NewLong(big.NewInt(0)).ToObject(), nil}, 74 {Mul, NewInt(-1).ToObject(), NewInt(-3).ToObject(), NewInt(3).ToObject(), nil}, 75 {Mul, newObject(ObjectType), NewInt(101).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for *: 'object' and 'int'")}, 76 {Mul, NewInt(MaxInt).ToObject(), NewInt(MaxInt - 1).ToObject(), NewLong(new(big.Int).Mul(big.NewInt(MaxInt), big.NewInt(MaxInt-1))).ToObject(), nil}, 77 {Or, NewInt(-100).ToObject(), NewInt(50).ToObject(), NewInt(-66).ToObject(), nil}, 78 {Or, NewInt(MaxInt).ToObject(), NewInt(MinInt).ToObject(), NewInt(-1).ToObject(), nil}, 79 {Or, newObject(ObjectType), NewInt(-100).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for |: 'object' and 'int'")}, 80 {Pow, NewInt(2).ToObject(), NewInt(128).ToObject(), NewLong(big.NewInt(0).Exp(big.NewInt(2), big.NewInt(128), nil)).ToObject(), nil}, 81 {Pow, NewInt(2).ToObject(), newObject(ObjectType), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for **: 'int' and 'object'")}, 82 {Pow, NewInt(2).ToObject(), NewInt(-2).ToObject(), NewFloat(0.25).ToObject(), nil}, 83 {Pow, newObject(ObjectType), NewInt(2).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for **: 'object' and 'int'")}, 84 {Sub, NewInt(22).ToObject(), NewInt(18).ToObject(), NewInt(4).ToObject(), nil}, 85 {Sub, IntType.ToObject(), NewInt(42).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for -: 'type' and 'int'")}, 86 {Sub, NewInt(MinInt).ToObject(), NewInt(1).ToObject(), NewLong(new(big.Int).Sub(minIntBig, big.NewInt(1))).ToObject(), nil}, 87 {Xor, NewInt(-100).ToObject(), NewInt(50).ToObject(), NewInt(-82).ToObject(), nil}, 88 {Xor, NewInt(MaxInt).ToObject(), NewInt(MinInt).ToObject(), NewInt(-1).ToObject(), nil}, 89 {Xor, newObject(ObjectType), NewInt(-100).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for ^: 'object' and 'int'")}, 90 } 91 for _, cas := range cases { 92 testCase := invokeTestCase{args: wrapArgs(cas.v, cas.w), want: cas.want, wantExc: cas.wantExc} 93 if err := runInvokeTestCase(wrapFuncForTest(cas.fun), &testCase); err != "" { 94 t.Error(err) 95 } 96 } 97 } 98 99 func TestIntCompare(t *testing.T) { 100 cases := []invokeTestCase{ 101 {args: wrapArgs(1, 1), want: compareAllResultEq}, 102 {args: wrapArgs(309683958, 309683958), want: compareAllResultEq}, 103 {args: wrapArgs(-306, 101), want: compareAllResultLT}, 104 {args: wrapArgs(309683958, 101), want: compareAllResultGT}, 105 } 106 for _, cas := range cases { 107 if err := runInvokeTestCase(compareAll, &cas); err != "" { 108 t.Error(err) 109 } 110 } 111 } 112 113 func TestIntInvert(t *testing.T) { 114 cases := []invokeTestCase{ 115 {args: wrapArgs(2592), want: NewInt(-2593).ToObject()}, 116 {args: wrapArgs(0), want: NewInt(-1).ToObject()}, 117 {args: wrapArgs(-43), want: NewInt(42).ToObject()}, 118 {args: wrapArgs(MaxInt), want: NewInt(MinInt).ToObject()}, 119 {args: wrapArgs(MinInt), want: NewInt(MaxInt).ToObject()}, 120 } 121 for _, cas := range cases { 122 if err := runInvokeMethodTestCase(IntType, "__invert__", &cas); err != "" { 123 t.Error(err) 124 } 125 } 126 } 127 128 func TestIntNew(t *testing.T) { 129 fooType := newTestClass("Foo", []*Type{ObjectType}, newStringDict(map[string]*Object{ 130 "__int__": newBuiltinFunction("__int__", func(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) { 131 return args[0], nil 132 }).ToObject(), 133 })) 134 strictEqType := newTestClassStrictEq("StrictEq", IntType) 135 subType := newTestClass("SubType", []*Type{IntType}, newStringDict(map[string]*Object{})) 136 subTypeObject := (&Int{Object: Object{typ: subType}, value: 3}).ToObject() 137 goodSlotType := newTestClass("GoodSlot", []*Type{ObjectType}, newStringDict(map[string]*Object{ 138 "__int__": newBuiltinFunction("__int__", func(_ *Frame, _ Args, _ KWArgs) (*Object, *BaseException) { 139 return NewInt(3).ToObject(), nil 140 }).ToObject(), 141 })) 142 badSlotType := newTestClass("BadSlot", []*Type{ObjectType}, newStringDict(map[string]*Object{ 143 "__int__": newBuiltinFunction("__int__", func(_ *Frame, _ Args, _ KWArgs) (*Object, *BaseException) { 144 return newObject(ObjectType), nil 145 }).ToObject(), 146 })) 147 slotSubTypeType := newTestClass("SlotSubType", []*Type{ObjectType}, newStringDict(map[string]*Object{ 148 "__int__": newBuiltinFunction("__int__", func(_ *Frame, _ Args, _ KWArgs) (*Object, *BaseException) { 149 return subTypeObject, nil 150 }).ToObject(), 151 })) 152 cases := []invokeTestCase{ 153 {args: wrapArgs(IntType), want: NewInt(0).ToObject()}, 154 {args: wrapArgs(IntType, "123"), want: NewInt(123).ToObject()}, 155 {args: wrapArgs(IntType, " \t123"), want: NewInt(123).ToObject()}, 156 {args: wrapArgs(IntType, "123 \t"), want: NewInt(123).ToObject()}, 157 {args: wrapArgs(IntType, "FF", 16), want: NewInt(255).ToObject()}, 158 {args: wrapArgs(IntType, "0xFF", 16), want: NewInt(255).ToObject()}, 159 {args: wrapArgs(IntType, "0xE", 0), want: NewInt(14).ToObject()}, 160 {args: wrapArgs(IntType, "0b101", 0), want: NewInt(5).ToObject()}, 161 {args: wrapArgs(IntType, "0o726", 0), want: NewInt(470).ToObject()}, 162 {args: wrapArgs(IntType, "0726", 0), want: NewInt(470).ToObject()}, 163 {args: wrapArgs(IntType, "102", 0), want: NewInt(102).ToObject()}, 164 {args: wrapArgs(IntType, 42), want: NewInt(42).ToObject()}, 165 {args: wrapArgs(IntType, -3.14), want: NewInt(-3).ToObject()}, 166 {args: wrapArgs(subType, overflowLong), wantExc: mustCreateException(OverflowErrorType, "Python int too large to convert to a Go int")}, 167 {args: wrapArgs(strictEqType, 42), want: (&Int{Object{typ: strictEqType}, 42}).ToObject()}, 168 {args: wrapArgs(IntType, newObject(goodSlotType)), want: NewInt(3).ToObject()}, 169 {args: wrapArgs(IntType, newObject(badSlotType)), wantExc: mustCreateException(TypeErrorType, "__int__ returned non-int (type object)")}, 170 {args: wrapArgs(IntType, newObject(slotSubTypeType)), want: subTypeObject}, 171 {args: wrapArgs(strictEqType, newObject(goodSlotType)), want: (&Int{Object{typ: strictEqType}, 3}).ToObject()}, 172 {args: wrapArgs(strictEqType, newObject(badSlotType)), wantExc: mustCreateException(TypeErrorType, "__int__ returned non-int (type object)")}, 173 {args: wrapArgs(IntType, "0xff"), wantExc: mustCreateException(ValueErrorType, "invalid literal for int() with base 10: 0xff")}, 174 {args: wrapArgs(IntType, ""), wantExc: mustCreateException(ValueErrorType, "invalid literal for int() with base 10: ")}, 175 {args: wrapArgs(IntType, " "), wantExc: mustCreateException(ValueErrorType, "invalid literal for int() with base 10: ")}, 176 {args: wrapArgs(FloatType), wantExc: mustCreateException(TypeErrorType, "int.__new__(float): float is not a subtype of int")}, 177 {args: wrapArgs(IntType, "asldkfj", 1), wantExc: mustCreateException(ValueErrorType, "int() base must be >= 2 and <= 36")}, 178 {args: wrapArgs(IntType, "asldkfj", 37), wantExc: mustCreateException(ValueErrorType, "int() base must be >= 2 and <= 36")}, 179 {args: wrapArgs(IntType, "@#%*(#", 36), wantExc: mustCreateException(ValueErrorType, "invalid literal for int() with base 36: @#%*(#")}, 180 {args: wrapArgs(IntType, "123", overflowLong), wantExc: mustCreateException(OverflowErrorType, "Python int too large to convert to a Go int")}, 181 {args: wrapArgs(IntType, "32059823095809238509238590835"), want: NewLong(func() *big.Int { i, _ := new(big.Int).SetString("32059823095809238509238590835", 0); return i }()).ToObject()}, 182 {args: wrapArgs(IntType, newObject(ObjectType)), wantExc: mustCreateException(TypeErrorType, "int() argument must be a string or a number, not 'object'")}, 183 {args: wrapArgs(IntType, newObject(fooType)), wantExc: mustCreateException(TypeErrorType, "__int__ returned non-int (type Foo)")}, 184 {args: wrapArgs(IntType, 1, 2), wantExc: mustCreateException(TypeErrorType, "int() can't convert non-string with explicit base")}, 185 {args: wrapArgs(IntType, 1, 2, 3), wantExc: mustCreateException(TypeErrorType, "int() takes at most 2 arguments (3 given)")}, 186 {args: wrapArgs(IntType, "1", None), wantExc: mustCreateException(TypeErrorType, "an integer is required")}, 187 } 188 for _, cas := range cases { 189 if err := runInvokeMethodTestCase(IntType, "__new__", &cas); err != "" { 190 t.Error(err) 191 } 192 } 193 } 194 195 func TestIntNewInterned(t *testing.T) { 196 // Make sure small integers are interned. 197 fun := wrapFuncForTest(func(f *Frame, i *Int) (bool, *BaseException) { 198 o, raised := IntType.Call(f, wrapArgs(i.Value()), nil) 199 if raised != nil { 200 return false, raised 201 } 202 return o == i.ToObject(), nil 203 }) 204 cases := []invokeTestCase{ 205 {args: wrapArgs(-1001), want: False.ToObject()}, 206 {args: wrapArgs(0), want: True.ToObject()}, 207 {args: wrapArgs(100), want: True.ToObject()}, 208 {args: wrapArgs(120948298), want: False.ToObject()}, 209 } 210 for _, cas := range cases { 211 if err := runInvokeTestCase(fun, &cas); err != "" { 212 t.Error(err) 213 } 214 } 215 } 216 217 func BenchmarkIntNew(b *testing.B) { 218 b.Run("interned", func(b *testing.B) { 219 var ret *Object 220 for i := 0; i < b.N; i++ { 221 ret = NewInt(1).ToObject() 222 } 223 runtime.KeepAlive(ret) 224 }) 225 226 b.Run("not interned", func(b *testing.B) { 227 var ret *Object 228 for i := 0; i < b.N; i++ { 229 ret = NewInt(internedIntMax + 5).ToObject() 230 } 231 runtime.KeepAlive(ret) 232 }) 233 } 234 235 func TestIntStrRepr(t *testing.T) { 236 cases := []invokeTestCase{ 237 {args: wrapArgs(0), want: NewStr("0").ToObject()}, 238 {args: wrapArgs(-303), want: NewStr("-303").ToObject()}, 239 {args: wrapArgs(231095835), want: NewStr("231095835").ToObject()}, 240 } 241 for _, cas := range cases { 242 if err := runInvokeTestCase(wrapFuncForTest(ToStr), &cas); err != "" { 243 t.Error(err) 244 } 245 if err := runInvokeTestCase(wrapFuncForTest(Repr), &cas); err != "" { 246 t.Error(err) 247 } 248 } 249 } 250 251 func TestIntCheckedAddMul(t *testing.T) { 252 cases := []struct { 253 f func(a, b int) (int, bool) 254 a, b int 255 want int 256 wantOK bool 257 }{ 258 {intCheckedAdd, 1, 2, 3, true}, 259 {intCheckedAdd, MaxInt, -1, MaxInt - 1, true}, 260 {intCheckedAdd, MaxInt, 0, MaxInt, true}, 261 {intCheckedAdd, MaxInt, 1, 0, false}, 262 {intCheckedAdd, MinInt, -1, 0, false}, 263 {intCheckedAdd, MinInt, 0, MinInt, true}, 264 {intCheckedAdd, MinInt, 1, MinInt + 1, true}, 265 {intCheckedMul, MaxInt, 1, MaxInt, true}, 266 {intCheckedMul, MaxInt, -1, MinInt + 1, true}, 267 {intCheckedMul, MinInt, -1, 0, false}, 268 } 269 for _, cas := range cases { 270 if got, gotOK := cas.f(cas.a, cas.b); got != cas.want || gotOK != cas.wantOK { 271 t.Errorf("%s(%v, %v) = (%v, %v), want (%v, %v)", getFuncName(cas.f), cas.a, cas.b, got, gotOK, cas.want, cas.wantOK) 272 } 273 if got, gotOK := cas.f(cas.b, cas.a); got != cas.want || gotOK != cas.wantOK { 274 t.Errorf("%s(%v, %v) = (%v, %v), want (%v, %v)", getFuncName(cas.f), cas.b, cas.a, got, gotOK, cas.want, cas.wantOK) 275 } 276 } 277 } 278 279 func TestIntCheckedDivMod(t *testing.T) { 280 cases := []struct { 281 f func(a, b int) (int, divModResult) 282 a, b int 283 want int 284 wantResult divModResult 285 }{ 286 {intCheckedDiv, 872, 736, 1, divModOK}, 287 {intCheckedDiv, -320, 3, -107, divModOK}, 288 {intCheckedDiv, 7, 3, 2, divModOK}, 289 {intCheckedDiv, 7, -3, -3, divModOK}, 290 {intCheckedDiv, -7, 3, -3, divModOK}, 291 {intCheckedDiv, -7, -3, 2, divModOK}, 292 {intCheckedDiv, 3, 7, 0, divModOK}, 293 {intCheckedDiv, 3, -7, -1, divModOK}, 294 {intCheckedDiv, -3, 7, -1, divModOK}, 295 {intCheckedDiv, -3, -7, 0, divModOK}, 296 {intCheckedDiv, MaxInt, MaxInt, 1, divModOK}, 297 {intCheckedDiv, MaxInt, MinInt, -1, divModOK}, 298 {intCheckedDiv, MinInt, MaxInt, -2, divModOK}, 299 {intCheckedDiv, MinInt, MinInt, 1, divModOK}, 300 {intCheckedDiv, 22, 0, 0, divModZeroDivision}, 301 {intCheckedDiv, MinInt, -1, 0, divModOverflow}, 302 {intCheckedMod, -142, -118, -24, divModOK}, 303 {intCheckedMod, -225, 454, 229, divModOK}, 304 {intCheckedMod, 7, 3, 1, divModOK}, 305 {intCheckedMod, 7, -3, -2, divModOK}, 306 {intCheckedMod, -7, 3, 2, divModOK}, 307 {intCheckedMod, -7, -3, -1, divModOK}, 308 {intCheckedMod, 3, 7, 3, divModOK}, 309 {intCheckedMod, 3, -7, -4, divModOK}, 310 {intCheckedMod, -3, 7, 4, divModOK}, 311 {intCheckedMod, -3, -7, -3, divModOK}, 312 {intCheckedMod, MaxInt, MaxInt, 0, divModOK}, 313 {intCheckedMod, MaxInt, MinInt, -1, divModOK}, 314 {intCheckedMod, MinInt, MaxInt, MaxInt - 1, divModOK}, 315 {intCheckedMod, MinInt, MinInt, 0, divModOK}, 316 {intCheckedMod, -50, 0, 0, divModZeroDivision}, 317 {intCheckedMod, MinInt, -1, 0, divModOverflow}, 318 } 319 for _, cas := range cases { 320 if got, gotResult := cas.f(cas.a, cas.b); got != cas.want || gotResult != cas.wantResult { 321 t.Errorf("%s(%v, %v) = (%v, %v), want (%v, %v)", getFuncName(cas.f), cas.a, cas.b, got, gotResult, cas.want, cas.wantResult) 322 } 323 } 324 } 325 326 func TestIntCheckedSub(t *testing.T) { 327 cases := []struct { 328 f func(a, b int) (int, bool) 329 a, b int 330 want int 331 wantOK bool 332 }{ 333 {intCheckedSub, MaxInt, MaxInt, 0, true}, 334 {intCheckedSub, MaxInt, -1, 0, false}, 335 {intCheckedSub, MaxInt, 0, MaxInt, true}, 336 {intCheckedSub, MaxInt, 1, MaxInt - 1, true}, 337 {intCheckedSub, MinInt, -1, MinInt + 1, true}, 338 {intCheckedSub, MinInt, 0, MinInt, true}, 339 {intCheckedSub, MinInt, 1, 0, false}, 340 {intCheckedSub, MinInt, MinInt, 0, true}, 341 {intCheckedSub, -2, MaxInt, 0, false}, 342 {intCheckedSub, -1, MaxInt, MinInt, true}, 343 {intCheckedSub, 0, MaxInt, MinInt + 1, true}, 344 {intCheckedSub, -1, MinInt, MaxInt, true}, 345 {intCheckedSub, 0, MinInt, 0, false}, 346 } 347 for _, cas := range cases { 348 if got, gotOK := cas.f(cas.a, cas.b); got != cas.want || gotOK != cas.wantOK { 349 t.Errorf("%s(%v, %v) = (%v, %v), want (%v, %v)", getFuncName(cas.f), cas.a, cas.b, got, gotOK, cas.want, cas.wantOK) 350 } 351 } 352 }