Edward McFarlane | d50186b | 2019-02-24 19:44:57 +0000 | [diff] [blame] | 1 | // Copyright 2017 The Bazel Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
| 5 | package starlark |
| 6 | |
| 7 | import ( |
| 8 | "fmt" |
| 9 | "math" |
| 10 | "math/big" |
| 11 | "testing" |
| 12 | ) |
| 13 | |
| 14 | // TestIntOpts exercises integer arithmetic, especially at the boundaries. |
| 15 | func TestIntOpts(t *testing.T) { |
| 16 | f := MakeInt64 |
| 17 | left, right := big.NewInt(math.MinInt32), big.NewInt(math.MaxInt32) |
| 18 | |
| 19 | for i, test := range []struct { |
| 20 | val Int |
| 21 | want string |
| 22 | }{ |
| 23 | // Add |
| 24 | {f(math.MaxInt32).Add(f(1)), "80000000"}, |
| 25 | {f(math.MinInt32).Add(f(-1)), "-80000001"}, |
| 26 | // Mul |
| 27 | {f(math.MaxInt32).Mul(f(math.MaxInt32)), "3fffffff00000001"}, |
| 28 | {f(math.MinInt32).Mul(f(math.MinInt32)), "4000000000000000"}, |
| 29 | {f(math.MaxUint32).Mul(f(math.MaxUint32)), "fffffffe00000001"}, |
| 30 | {f(math.MinInt32).Mul(f(-1)), "80000000"}, |
| 31 | // Div |
| 32 | {f(math.MinInt32).Div(f(-1)), "80000000"}, |
| 33 | {f(1 << 31).Div(f(2)), "40000000"}, |
| 34 | // And |
| 35 | {f(math.MaxInt32).And(f(math.MaxInt32)), "7fffffff"}, |
| 36 | {f(math.MinInt32).And(f(math.MinInt32)), "-80000000"}, |
| 37 | {f(1 << 33).And(f(1 << 32)), "0"}, |
| 38 | // Mod |
| 39 | {f(1 << 32).Mod(f(2)), "0"}, |
| 40 | // Or |
| 41 | {f(1 << 32).Or(f(0)), "100000000"}, |
| 42 | {f(math.MaxInt32).Or(f(0)), "7fffffff"}, |
| 43 | {f(math.MaxUint32).Or(f(0)), "ffffffff"}, |
| 44 | {f(math.MinInt32).Or(f(math.MinInt32)), "-80000000"}, |
| 45 | // Xor |
| 46 | {f(math.MinInt32).Xor(f(-1)), "7fffffff"}, |
| 47 | // Not |
| 48 | {f(math.MinInt32).Not(), "7fffffff"}, |
| 49 | {f(math.MaxInt32).Not(), "-80000000"}, |
| 50 | // Shift |
| 51 | {f(1).Lsh(31), "80000000"}, |
| 52 | {f(1).Lsh(32), "100000000"}, |
| 53 | {f(math.MaxInt32 + 1).Rsh(1), "40000000"}, |
| 54 | {f(math.MinInt32 * 2).Rsh(1), "-80000000"}, |
| 55 | } { |
| 56 | if got := fmt.Sprintf("%x", test.val); got != test.want { |
| 57 | t.Errorf("%d equals %s, want %s", i, got, test.want) |
| 58 | } |
alandonovan | c6daab6 | 2020-06-17 14:27:56 -0400 | [diff] [blame] | 59 | small, big := test.val.get() |
| 60 | if small < math.MinInt32 || math.MaxInt32 < small { |
Edward McFarlane | d50186b | 2019-02-24 19:44:57 +0000 | [diff] [blame] | 61 | t.Errorf("expected big, %d %s", i, test.val) |
| 62 | } |
alandonovan | c6daab6 | 2020-06-17 14:27:56 -0400 | [diff] [blame] | 63 | if big == nil { |
Edward McFarlane | d50186b | 2019-02-24 19:44:57 +0000 | [diff] [blame] | 64 | continue |
| 65 | } |
alandonovan | c6daab6 | 2020-06-17 14:27:56 -0400 | [diff] [blame] | 66 | if small != 0 { |
| 67 | t.Errorf("expected 0 small, %d %s with %d", i, test.val, small) |
Edward McFarlane | d50186b | 2019-02-24 19:44:57 +0000 | [diff] [blame] | 68 | } |
alandonovan | c6daab6 | 2020-06-17 14:27:56 -0400 | [diff] [blame] | 69 | if big.Cmp(left) >= 0 && big.Cmp(right) <= 0 { |
Edward McFarlane | d50186b | 2019-02-24 19:44:57 +0000 | [diff] [blame] | 70 | t.Errorf("expected small, %d %s", i, test.val) |
| 71 | } |
| 72 | } |
| 73 | } |
Germán Fuentes Capella | b6d3e7f | 2021-01-18 02:14:59 +0100 | [diff] [blame] | 74 | |
| 75 | func TestImmutabilityMakeBigInt(t *testing.T) { |
| 76 | // use max int64 for the test |
| 77 | expect := int64(^uint64(0) >> 1) |
| 78 | |
| 79 | mutint := big.NewInt(expect) |
| 80 | value := MakeBigInt(mutint) |
| 81 | mutint.Set(big.NewInt(1)) |
| 82 | |
| 83 | got, _ := value.Int64() |
| 84 | if got != expect { |
| 85 | t.Errorf("expected %d, got %d", expect, got) |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | func TestImmutabilityBigInt(t *testing.T) { |
| 90 | // use 1 and max int64 for the test |
| 91 | for _, expect := range []int64{1, int64(^uint64(0) >> 1)} { |
| 92 | value := MakeBigInt(big.NewInt(expect)) |
| 93 | |
| 94 | bigint := value.BigInt() |
| 95 | bigint.Set(big.NewInt(2)) |
| 96 | |
| 97 | got, _ := value.Int64() |
| 98 | if got != expect { |
| 99 | t.Errorf("expected %d, got %d", expect, got) |
| 100 | } |
| 101 | } |
| 102 | } |