github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/binary/integer_test.go (about) 1 package binary 2 3 import ( 4 "math" 5 "math/big" 6 "testing" 7 8 "strconv" 9 "strings" 10 11 "fmt" 12 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/require" 15 ) 16 17 func TestIsUint64SumOverflow(t *testing.T) { 18 var b uint64 = 0xdeadbeef 19 var a uint64 = math.MaxUint64 - b 20 assert.False(t, IsUint64SumOverflow(a-b, b)) 21 assert.False(t, IsUint64SumOverflow(a, b)) 22 assert.False(t, IsUint64SumOverflow(a+b, 0)) 23 assert.True(t, IsUint64SumOverflow(a, b+1)) 24 assert.True(t, IsUint64SumOverflow(a+b, 1)) 25 assert.True(t, IsUint64SumOverflow(a+1, b+1)) 26 } 27 28 func zero() *big.Int { 29 return new(big.Int) 30 } 31 32 var big2E255 = zero().Lsh(big1, 255) 33 var big2E256 = zero().Lsh(big1, 256) 34 35 func TestU256(t *testing.T) { 36 expected := big2E255 37 encoded := U256(expected) 38 assertBigIntEqual(t, expected, encoded, "Top bit set big int is fixed point") 39 40 expected = zero() 41 encoded = U256(big2E256) 42 assertBigIntEqual(t, expected, encoded, "Ceiling bit is exact overflow") 43 44 expected = zero().Sub(big2E256, big1) 45 encoded = U256(expected) 46 assertBigIntEqual(t, expected, encoded, "Max unsigned big int is fixed point") 47 48 expected = big1 49 encoded = U256(zero().Add(big2E256, big1)) 50 assertBigIntEqual(t, expected, encoded, "Overflow by one") 51 52 expected = big2E255 53 encoded = U256(zero().Add(big2E256, big2E255)) 54 assertBigIntEqual(t, expected, encoded, "Overflow by doubling") 55 56 negative := big.NewInt(-234) 57 assert.Equal(t, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16", 58 fmt.Sprintf("%X", U256(negative).Bytes()), "byte representation is twos complement") 59 60 expected, ok := zero().SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16", 16) 61 require.True(t, ok) 62 assertBigIntEqual(t, expected, U256(negative), "Bytes representation should be twos complement") 63 64 expected = zero() 65 encoded = U256(zero().Neg(big2E256)) 66 assertBigIntEqual(t, expected, encoded, "Floor bit is overflow") 67 68 expected = big2E255 69 encoded = zero().Neg(big2E255) 70 encoded = U256(encoded) 71 assertBigIntEqual(t, expected, encoded, "2**255 is Self complement") 72 73 expected = zero().Add(big2E255, big1) 74 encoded = zero().Neg(big2E255) 75 encoded = encoded.Add(encoded, big1) 76 encoded = U256(encoded) 77 assertBigIntEqual(t, expected, encoded, "") 78 } 79 80 func TestS256(t *testing.T) { 81 expected := zero().Neg(big2E255) 82 signed := S256(big2E255) 83 assertBigIntEqual(t, expected, signed, "Should be negative") 84 85 expected = zero().Sub(big2E255, big1) 86 signed = S256(expected) 87 assertBigIntEqual(t, expected, signed, "Maximum twos complement positive is fixed point") 88 89 expected = zero() 90 signed = S256(expected) 91 assertBigIntEqual(t, expected, signed, "Twos complement of zero is fixed poount") 92 } 93 94 func TestSignExtend(t *testing.T) { 95 assertSignExtend(t, 16, 8, 96 "0000 0000 1001 0000", 97 "1111 1111 1001 0000") 98 99 assertSignExtend(t, 16, 16, 100 "1001 0000", 101 "1001 0000") 102 103 assertSignExtend(t, 32, 24, 104 "0000 0000 1000 0000 1101 0011 1001 0000", 105 "1111 1111 1000 0000 1101 0011 1001 0000") 106 107 assertSignExtend(t, 32, 24, 108 "0000 0000 0000 0000 1101 0011 1001 0000", 109 "0000 0000 0000 0000 1101 0011 1001 0000") 110 111 // Here we have a stray bit set in the 4th most significant byte that gets wiped out 112 assertSignExtend(t, 32, 24, 113 "0001 0000 0000 0000 1101 0011 1001 0000", 114 "0000 0000 0000 0000 1101 0011 1001 0000") 115 assertSignExtend(t, 32, 24, 116 "0001 0000 1000 0000 1101 0011 1001 0000", 117 "1111 1111 1000 0000 1101 0011 1001 0000") 118 119 assertSignExtend(t, 32, 32, 120 "0001 0000 1000 0000 1101 0011 1001 0000", 121 "0001 0000 1000 0000 1101 0011 1001 0000") 122 123 assertSignExtend(t, 32, 32, 124 "1001 0000 1000 0000 1101 0011 1001 0000", 125 "1001 0000 1000 0000 1101 0011 1001 0000") 126 127 assertSignExtend(t, 64, 32, 128 "0000 0000 0000 0000 0000 0000 0000 0000 1001 0000 1000 0000 1101 0011 1001 0000", 129 "1111 1111 1111 1111 1111 1111 1111 1111 1001 0000 1000 0000 1101 0011 1001 0000") 130 131 assertSignExtend(t, 64, 32, 132 "0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 1000 0000 1101 0011 1001 0000", 133 "0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 1000 0000 1101 0011 1001 0000") 134 } 135 136 func TestLittleEndian(t *testing.T) { 137 x, ok := new(big.Int).SetString("234890234579042368982348972347234789897", 10) 138 require.True(t, ok) 139 y := BigIntFromLittleEndianBytes(BigIntToLittleEndianBytes(x)) 140 require.Equal(t, x.Cmp(y), 0) 141 } 142 143 func assertSignExtend(t *testing.T, extendedBits int, embeddedBits uint, inputString, expectedString string) bool { 144 input := intFromString(t, extendedBits, inputString) 145 expected := intFromString(t, extendedBits, expectedString) 146 actual := SignExtend(big.NewInt(int64(input)), embeddedBits) 147 var ret bool 148 switch extendedBits { 149 case 8: 150 ret = assert.Equal(t, uint8(expected), uint8(actual.Int64())) 151 case 16: 152 ret = assert.Equal(t, uint16(expected), uint16(actual.Int64())) 153 case 32: 154 ret = assert.Equal(t, uint32(expected), uint32(actual.Int64())) 155 case 64: 156 ret = assert.Equal(t, uint64(expected), uint64(actual.Int64())) 157 default: 158 t.Fatalf("Cannot test SignExtend for non-Go-native bit size %v", extendedBits) 159 return false 160 } 161 if !ret { 162 163 } 164 return ret 165 } 166 167 func assertBigIntEqual(t *testing.T, expected, actual *big.Int, messages ...string) bool { 168 return assert.True(t, expected.Cmp(actual) == 0, fmt.Sprintf("%s - not equal:\n%v (expected)\n%v (actual)", 169 strings.Join(messages, " "), expected, actual)) 170 } 171 172 func intFromString(t *testing.T, bitSize int, binStrings ...string) uint64 { 173 binaryString := strings.Replace(strings.Join(binStrings, ""), " ", "", -1) 174 i, err := strconv.ParseUint(binaryString, 2, bitSize) 175 require.NoError(t, err) 176 return i 177 }