github.com/Tri-stone/burrow@v0.25.0/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 var big2E257 = zero().Lsh(big1, 257) 35 36 func TestU256(t *testing.T) { 37 expected := big2E255 38 encoded := U256(expected) 39 assertBigIntEqual(t, expected, encoded, "Top bit set big int is fixed point") 40 41 expected = zero() 42 encoded = U256(big2E256) 43 assertBigIntEqual(t, expected, encoded, "Ceiling bit is exact overflow") 44 45 expected = zero().Sub(big2E256, big1) 46 encoded = U256(expected) 47 assertBigIntEqual(t, expected, encoded, "Max unsigned big int is fixed point") 48 49 expected = big1 50 encoded = U256(zero().Add(big2E256, big1)) 51 assertBigIntEqual(t, expected, encoded, "Overflow by one") 52 53 expected = big2E255 54 encoded = U256(zero().Add(big2E256, big2E255)) 55 assertBigIntEqual(t, expected, encoded, "Overflow by doubling") 56 57 negative := big.NewInt(-234) 58 assert.Equal(t, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16", 59 fmt.Sprintf("%X", U256(negative).Bytes()), "byte representation is twos complement") 60 61 expected, ok := zero().SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16", 16) 62 require.True(t, ok) 63 assertBigIntEqual(t, expected, U256(negative), "Bytes representation should be twos complement") 64 65 expected = zero() 66 encoded = U256(zero().Neg(big2E256)) 67 assertBigIntEqual(t, expected, encoded, "Floor bit is overflow") 68 69 expected = big2E255 70 encoded = zero().Neg(big2E255) 71 encoded = U256(encoded) 72 assertBigIntEqual(t, expected, encoded, "2**255 is Self complement") 73 74 expected = zero().Add(big2E255, big1) 75 encoded = zero().Neg(big2E255) 76 encoded = encoded.Add(encoded, big1) 77 encoded = U256(encoded) 78 assertBigIntEqual(t, expected, encoded, "") 79 } 80 81 func TestS256(t *testing.T) { 82 expected := zero().Neg(big2E255) 83 signed := S256(big2E255) 84 assertBigIntEqual(t, expected, signed, "Should be negative") 85 86 expected = zero().Sub(big2E255, big1) 87 signed = S256(expected) 88 assertBigIntEqual(t, expected, signed, "Maximum twos complement positive is fixed point") 89 90 expected = zero() 91 signed = S256(expected) 92 assertBigIntEqual(t, expected, signed, "Twos complement of zero is fixed poount") 93 94 // Technically undefined but let's not let that stop us 95 expected = zero().Sub(big2E257, big2E256) 96 signed = S256(big2E257) 97 assertBigIntEqual(t, expected, signed, "Out of twos complement bounds") 98 } 99 100 func TestPutUint64BE(t *testing.T) { 101 bs := make([]byte, 8) 102 PutUint64BE(bs, 245343) 103 assert.Equal(t, "000000000003BE5F", fmt.Sprintf("%X", bs)) 104 } 105 106 func TestSignExtend(t *testing.T) { 107 assertSignExtend(t, 16, 0, 108 "0000 0000 1001 0000", 109 "1111 1111 1001 0000") 110 111 assertSignExtend(t, 16, 1, 112 "1001 0000", 113 "1001 0000") 114 115 assertSignExtend(t, 32, 2, 116 "0000 0000 1000 0000 1101 0011 1001 0000", 117 "1111 1111 1000 0000 1101 0011 1001 0000") 118 119 assertSignExtend(t, 32, 2, 120 "0000 0000 0000 0000 1101 0011 1001 0000", 121 "0000 0000 0000 0000 1101 0011 1001 0000") 122 123 // Here we have a stray bit set in the 4th most significant byte that gets wiped out 124 assertSignExtend(t, 32, 2, 125 "0001 0000 0000 0000 1101 0011 1001 0000", 126 "0000 0000 0000 0000 1101 0011 1001 0000") 127 assertSignExtend(t, 32, 2, 128 "0001 0000 1000 0000 1101 0011 1001 0000", 129 "1111 1111 1000 0000 1101 0011 1001 0000") 130 131 assertSignExtend(t, 32, 3, 132 "0001 0000 1000 0000 1101 0011 1001 0000", 133 "0001 0000 1000 0000 1101 0011 1001 0000") 134 135 assertSignExtend(t, 32, 3, 136 "1001 0000 1000 0000 1101 0011 1001 0000", 137 "1001 0000 1000 0000 1101 0011 1001 0000") 138 139 assertSignExtend(t, 64, 3, 140 "0000 0000 0000 0000 0000 0000 0000 0000 1001 0000 1000 0000 1101 0011 1001 0000", 141 "1111 1111 1111 1111 1111 1111 1111 1111 1001 0000 1000 0000 1101 0011 1001 0000") 142 143 assertSignExtend(t, 64, 3, 144 "0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 1000 0000 1101 0011 1001 0000", 145 "0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 1000 0000 1101 0011 1001 0000") 146 } 147 148 func assertSignExtend(t *testing.T, bitSize int, bytesBack uint64, inputString, expectedString string) bool { 149 input := intFromString(t, bitSize, inputString) 150 expected := intFromString(t, bitSize, expectedString) 151 //actual := SignExtend(big.NewInt(bytesBack), big.NewInt(int64(input))) 152 actual := SignExtend(bytesBack, big.NewInt(int64(input))) 153 var ret bool 154 switch bitSize { 155 case 8: 156 ret = assert.Equal(t, uint8(expected), uint8(actual.Int64())) 157 case 16: 158 ret = assert.Equal(t, uint16(expected), uint16(actual.Int64())) 159 case 32: 160 ret = assert.Equal(t, uint32(expected), uint32(actual.Int64())) 161 case 64: 162 ret = assert.Equal(t, uint64(expected), uint64(actual.Int64())) 163 default: 164 t.Fatalf("Cannot test SignExtend for non-Go-native bit size %v", bitSize) 165 return false 166 } 167 if !ret { 168 169 } 170 return ret 171 } 172 173 func assertBigIntEqual(t *testing.T, expected, actual *big.Int, messages ...string) bool { 174 return assert.True(t, expected.Cmp(actual) == 0, fmt.Sprintf("%s - not equal:\n%v (expected)\n%v (actual)", 175 strings.Join(messages, " "), expected, actual)) 176 } 177 178 func intFromString(t *testing.T, bitSize int, binStrings ...string) uint64 { 179 binaryString := strings.Replace(strings.Join(binStrings, ""), " ", "", -1) 180 i, err := strconv.ParseUint(binaryString, 2, bitSize) 181 require.NoError(t, err) 182 return i 183 }