github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/common/math/big_test.go (about) 1 // This file is part of the go-sberex library. The go-sberex library is 2 // free software: you can redistribute it and/or modify it under the terms 3 // of the GNU Lesser General Public License as published by the Free 4 // Software Foundation, either version 3 of the License, or (at your option) 5 // any later version. 6 // 7 // The go-sberex library is distributed in the hope that it will be useful, 8 // but WITHOUT ANY WARRANTY; without even the implied warranty of 9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 10 // General Public License <http://www.gnu.org/licenses/> for more details. 11 12 package math 13 14 import ( 15 "bytes" 16 "encoding/hex" 17 "math/big" 18 "testing" 19 20 "github.com/Sberex/go-sberex/common" 21 ) 22 23 func TestHexOrDecimal256(t *testing.T) { 24 tests := []struct { 25 input string 26 num *big.Int 27 ok bool 28 }{ 29 {"", big.NewInt(0), true}, 30 {"0", big.NewInt(0), true}, 31 {"0x0", big.NewInt(0), true}, 32 {"12345678", big.NewInt(12345678), true}, 33 {"0x12345678", big.NewInt(0x12345678), true}, 34 {"0X12345678", big.NewInt(0x12345678), true}, 35 // Tests for leading zero behaviour: 36 {"0123456789", big.NewInt(123456789), true}, // note: not octal 37 {"00", big.NewInt(0), true}, 38 {"0x00", big.NewInt(0), true}, 39 {"0x012345678abc", big.NewInt(0x12345678abc), true}, 40 // Invalid syntax: 41 {"abcdef", nil, false}, 42 {"0xgg", nil, false}, 43 // Larger than 256 bits: 44 {"115792089237316195423570985008687907853269984665640564039457584007913129639936", nil, false}, 45 } 46 for _, test := range tests { 47 var num HexOrDecimal256 48 err := num.UnmarshalText([]byte(test.input)) 49 if (err == nil) != test.ok { 50 t.Errorf("ParseBig(%q) -> (err == nil) == %t, want %t", test.input, err == nil, test.ok) 51 continue 52 } 53 if test.num != nil && (*big.Int)(&num).Cmp(test.num) != 0 { 54 t.Errorf("ParseBig(%q) -> %d, want %d", test.input, (*big.Int)(&num), test.num) 55 } 56 } 57 } 58 59 func TestMustParseBig256(t *testing.T) { 60 defer func() { 61 if recover() == nil { 62 t.Error("MustParseBig should've panicked") 63 } 64 }() 65 MustParseBig256("ggg") 66 } 67 68 func TestBigMax(t *testing.T) { 69 a := big.NewInt(10) 70 b := big.NewInt(5) 71 72 max1 := BigMax(a, b) 73 if max1 != a { 74 t.Errorf("Expected %d got %d", a, max1) 75 } 76 77 max2 := BigMax(b, a) 78 if max2 != a { 79 t.Errorf("Expected %d got %d", a, max2) 80 } 81 } 82 83 func TestBigMin(t *testing.T) { 84 a := big.NewInt(10) 85 b := big.NewInt(5) 86 87 min1 := BigMin(a, b) 88 if min1 != b { 89 t.Errorf("Expected %d got %d", b, min1) 90 } 91 92 min2 := BigMin(b, a) 93 if min2 != b { 94 t.Errorf("Expected %d got %d", b, min2) 95 } 96 } 97 98 func TestFirstBigSet(t *testing.T) { 99 tests := []struct { 100 num *big.Int 101 ix int 102 }{ 103 {big.NewInt(0), 0}, 104 {big.NewInt(1), 0}, 105 {big.NewInt(2), 1}, 106 {big.NewInt(0x100), 8}, 107 } 108 for _, test := range tests { 109 if ix := FirstBitSet(test.num); ix != test.ix { 110 t.Errorf("FirstBitSet(b%b) = %d, want %d", test.num, ix, test.ix) 111 } 112 } 113 } 114 115 func TestPaddedBigBytes(t *testing.T) { 116 tests := []struct { 117 num *big.Int 118 n int 119 result []byte 120 }{ 121 {num: big.NewInt(0), n: 4, result: []byte{0, 0, 0, 0}}, 122 {num: big.NewInt(1), n: 4, result: []byte{0, 0, 0, 1}}, 123 {num: big.NewInt(512), n: 4, result: []byte{0, 0, 2, 0}}, 124 {num: BigPow(2, 32), n: 4, result: []byte{1, 0, 0, 0, 0}}, 125 } 126 for _, test := range tests { 127 if result := PaddedBigBytes(test.num, test.n); !bytes.Equal(result, test.result) { 128 t.Errorf("PaddedBigBytes(%d, %d) = %v, want %v", test.num, test.n, result, test.result) 129 } 130 } 131 } 132 133 func BenchmarkPaddedBigBytesLargePadding(b *testing.B) { 134 bigint := MustParseBig256("123456789123456789123456789123456789") 135 for i := 0; i < b.N; i++ { 136 PaddedBigBytes(bigint, 200) 137 } 138 } 139 140 func BenchmarkPaddedBigBytesSmallPadding(b *testing.B) { 141 bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC") 142 for i := 0; i < b.N; i++ { 143 PaddedBigBytes(bigint, 5) 144 } 145 } 146 147 func BenchmarkPaddedBigBytesSmallOnePadding(b *testing.B) { 148 bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC") 149 for i := 0; i < b.N; i++ { 150 PaddedBigBytes(bigint, 32) 151 } 152 } 153 154 func BenchmarkByteAtBrandNew(b *testing.B) { 155 bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC") 156 for i := 0; i < b.N; i++ { 157 bigEndianByteAt(bigint, 15) 158 } 159 } 160 161 func BenchmarkByteAt(b *testing.B) { 162 bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC") 163 for i := 0; i < b.N; i++ { 164 bigEndianByteAt(bigint, 15) 165 } 166 } 167 168 func BenchmarkByteAtOld(b *testing.B) { 169 170 bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC") 171 for i := 0; i < b.N; i++ { 172 PaddedBigBytes(bigint, 32) 173 } 174 } 175 176 func TestReadBits(t *testing.T) { 177 check := func(input string) { 178 want, _ := hex.DecodeString(input) 179 int, _ := new(big.Int).SetString(input, 16) 180 buf := make([]byte, len(want)) 181 ReadBits(int, buf) 182 if !bytes.Equal(buf, want) { 183 t.Errorf("have: %x\nwant: %x", buf, want) 184 } 185 } 186 check("000000000000000000000000000000000000000000000000000000FEFCF3F8F0") 187 check("0000000000012345000000000000000000000000000000000000FEFCF3F8F0") 188 check("18F8F8F1000111000110011100222004330052300000000000000000FEFCF3F8F0") 189 } 190 191 func TestU256(t *testing.T) { 192 tests := []struct{ x, y *big.Int }{ 193 {x: big.NewInt(0), y: big.NewInt(0)}, 194 {x: big.NewInt(1), y: big.NewInt(1)}, 195 {x: BigPow(2, 255), y: BigPow(2, 255)}, 196 {x: BigPow(2, 256), y: big.NewInt(0)}, 197 {x: new(big.Int).Add(BigPow(2, 256), big.NewInt(1)), y: big.NewInt(1)}, 198 // negative values 199 {x: big.NewInt(-1), y: new(big.Int).Sub(BigPow(2, 256), big.NewInt(1))}, 200 {x: big.NewInt(-2), y: new(big.Int).Sub(BigPow(2, 256), big.NewInt(2))}, 201 {x: BigPow(2, -255), y: big.NewInt(1)}, 202 } 203 for _, test := range tests { 204 if y := U256(new(big.Int).Set(test.x)); y.Cmp(test.y) != 0 { 205 t.Errorf("U256(%x) = %x, want %x", test.x, y, test.y) 206 } 207 } 208 } 209 210 func TestBigEndianByteAt(t *testing.T) { 211 tests := []struct { 212 x string 213 y int 214 exp byte 215 }{ 216 {"00", 0, 0x00}, 217 {"01", 1, 0x00}, 218 {"00", 1, 0x00}, 219 {"01", 0, 0x01}, 220 {"0000000000000000000000000000000000000000000000000000000000102030", 0, 0x30}, 221 {"0000000000000000000000000000000000000000000000000000000000102030", 1, 0x20}, 222 {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 31, 0xAB}, 223 {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 32, 0x00}, 224 {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 500, 0x00}, 225 } 226 for _, test := range tests { 227 v := new(big.Int).SetBytes(common.Hex2Bytes(test.x)) 228 actual := bigEndianByteAt(v, test.y) 229 if actual != test.exp { 230 t.Fatalf("Expected [%v] %v:th byte to be %v, was %v.", test.x, test.y, test.exp, actual) 231 } 232 233 } 234 } 235 func TestLittleEndianByteAt(t *testing.T) { 236 tests := []struct { 237 x string 238 y int 239 exp byte 240 }{ 241 {"00", 0, 0x00}, 242 {"01", 1, 0x00}, 243 {"00", 1, 0x00}, 244 {"01", 0, 0x00}, 245 {"0000000000000000000000000000000000000000000000000000000000102030", 0, 0x00}, 246 {"0000000000000000000000000000000000000000000000000000000000102030", 1, 0x00}, 247 {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 31, 0x00}, 248 {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 32, 0x00}, 249 {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 0, 0xAB}, 250 {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 1, 0xCD}, 251 {"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", 0, 0x00}, 252 {"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", 1, 0xCD}, 253 {"0000000000000000000000000000000000000000000000000000000000102030", 31, 0x30}, 254 {"0000000000000000000000000000000000000000000000000000000000102030", 30, 0x20}, 255 {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 32, 0x0}, 256 {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 31, 0xFF}, 257 {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 0xFFFF, 0x0}, 258 } 259 for _, test := range tests { 260 v := new(big.Int).SetBytes(common.Hex2Bytes(test.x)) 261 actual := Byte(v, 32, test.y) 262 if actual != test.exp { 263 t.Fatalf("Expected [%v] %v:th byte to be %v, was %v.", test.x, test.y, test.exp, actual) 264 } 265 266 } 267 } 268 269 func TestS256(t *testing.T) { 270 tests := []struct{ x, y *big.Int }{ 271 {x: big.NewInt(0), y: big.NewInt(0)}, 272 {x: big.NewInt(1), y: big.NewInt(1)}, 273 {x: big.NewInt(2), y: big.NewInt(2)}, 274 { 275 x: new(big.Int).Sub(BigPow(2, 255), big.NewInt(1)), 276 y: new(big.Int).Sub(BigPow(2, 255), big.NewInt(1)), 277 }, 278 { 279 x: BigPow(2, 255), 280 y: new(big.Int).Neg(BigPow(2, 255)), 281 }, 282 { 283 x: new(big.Int).Sub(BigPow(2, 256), big.NewInt(1)), 284 y: big.NewInt(-1), 285 }, 286 { 287 x: new(big.Int).Sub(BigPow(2, 256), big.NewInt(2)), 288 y: big.NewInt(-2), 289 }, 290 } 291 for _, test := range tests { 292 if y := S256(test.x); y.Cmp(test.y) != 0 { 293 t.Errorf("S256(%x) = %x, want %x", test.x, y, test.y) 294 } 295 } 296 } 297 298 func TestExp(t *testing.T) { 299 tests := []struct{ base, exponent, result *big.Int }{ 300 {base: big.NewInt(0), exponent: big.NewInt(0), result: big.NewInt(1)}, 301 {base: big.NewInt(1), exponent: big.NewInt(0), result: big.NewInt(1)}, 302 {base: big.NewInt(1), exponent: big.NewInt(1), result: big.NewInt(1)}, 303 {base: big.NewInt(1), exponent: big.NewInt(2), result: big.NewInt(1)}, 304 {base: big.NewInt(3), exponent: big.NewInt(144), result: MustParseBig256("507528786056415600719754159741696356908742250191663887263627442114881")}, 305 {base: big.NewInt(2), exponent: big.NewInt(255), result: MustParseBig256("57896044618658097711785492504343953926634992332820282019728792003956564819968")}, 306 } 307 for _, test := range tests { 308 if result := Exp(test.base, test.exponent); result.Cmp(test.result) != 0 { 309 t.Errorf("Exp(%d, %d) = %d, want %d", test.base, test.exponent, result, test.result) 310 } 311 } 312 }