blob: ad1bf927d13ce380033369deb8a7ea028ad20dc6 [file] [log] [blame]
Edward McFarlaned50186b2019-02-24 19:44:57 +00001// 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
5package starlark
6
7import (
8 "fmt"
9 "math"
10 "math/big"
11 "testing"
12)
13
14// TestIntOpts exercises integer arithmetic, especially at the boundaries.
15func 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 }
alandonovanc6daab62020-06-17 14:27:56 -040059 small, big := test.val.get()
60 if small < math.MinInt32 || math.MaxInt32 < small {
Edward McFarlaned50186b2019-02-24 19:44:57 +000061 t.Errorf("expected big, %d %s", i, test.val)
62 }
alandonovanc6daab62020-06-17 14:27:56 -040063 if big == nil {
Edward McFarlaned50186b2019-02-24 19:44:57 +000064 continue
65 }
alandonovanc6daab62020-06-17 14:27:56 -040066 if small != 0 {
67 t.Errorf("expected 0 small, %d %s with %d", i, test.val, small)
Edward McFarlaned50186b2019-02-24 19:44:57 +000068 }
alandonovanc6daab62020-06-17 14:27:56 -040069 if big.Cmp(left) >= 0 && big.Cmp(right) <= 0 {
Edward McFarlaned50186b2019-02-24 19:44:57 +000070 t.Errorf("expected small, %d %s", i, test.val)
71 }
72 }
73}
Germán Fuentes Capellab6d3e7f2021-01-18 02:14:59 +010074
75func 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
89func 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}