xref: /aosp_15_r20/external/starlark-go/starlark/int_test.go (revision 4947cdc739c985f6d86941e22894f5cefe7c9e9a)
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
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		}
59		small, big := test.val.get()
60		if small < math.MinInt32 || math.MaxInt32 < small {
61			t.Errorf("expected big, %d %s", i, test.val)
62		}
63		if big == nil {
64			continue
65		}
66		if small != 0 {
67			t.Errorf("expected 0 small, %d %s with %d", i, test.val, small)
68		}
69		if big.Cmp(left) >= 0 && big.Cmp(right) <= 0 {
70			t.Errorf("expected small, %d %s", i, test.val)
71		}
72	}
73}
74
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}
103