github.com/ontio/ontology@v1.14.4/vm/neovm/int_value_test.go (about) 1 /* 2 * Copyright (C) 2018 The ontology Authors 3 * This file is part of The ontology library. 4 * 5 * The ontology is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU Lesser General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * The ontology is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with The ontology. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 package neovm 20 21 import ( 22 "crypto/rand" 23 "encoding/binary" 24 "fmt" 25 "math" 26 "math/big" 27 "testing" 28 29 "github.com/ontio/ontology/common" 30 "github.com/ontio/ontology/vm/neovm/types" 31 "github.com/stretchr/testify/assert" 32 ) 33 34 func randInt64() *big.Int { 35 buf := make([]byte, 8) 36 _, _ = rand.Read(buf) 37 r := binary.LittleEndian.Uint64(buf) 38 right := big.NewInt(int64(r)) 39 return right 40 } 41 42 func genBBInt() (*big.Int, *big.Int) { 43 buf := make([]byte, 32) 44 _, _ = rand.Read(buf) 45 left := common.BigIntFromNeoBytes(buf) 46 _, _ = rand.Read(buf) 47 right := common.BigIntFromNeoBytes(buf) 48 return left, right 49 } 50 51 func genBLInt() (*big.Int, *big.Int) { 52 buf := make([]byte, 32) 53 _, _ = rand.Read(buf) 54 left := common.BigIntFromNeoBytes(buf) 55 right := randInt64() 56 return left, right 57 } 58 59 func genLBInt() (*big.Int, *big.Int) { 60 right, left := genBLInt() 61 return left, right 62 } 63 64 func genLLInt() (*big.Int, *big.Int) { 65 left := randInt64() 66 right := randInt64() 67 return left, right 68 } 69 70 type IntOp func(left, right *big.Int) ([]byte, error) 71 72 func compareIntOpInner(t *testing.T, left, right *big.Int, func1, func2 IntOp) { 73 74 val1, err := func1(left, right) 75 val2, err2 := func2(left, right) 76 if err != nil || err2 != nil { 77 return 78 } 79 80 assert.Equal(t, val1, val2) 81 } 82 83 func compareIntOp(t *testing.T, func1, func2 IntOp) { 84 const N = 10000 85 for i := 0; i < N; i++ { 86 left, right := genBBInt() 87 compareIntOpInner(t, left, right, func1, func2) 88 left, right = genLLInt() 89 compareIntOpInner(t, left, right, func1, func2) 90 left, right = genBLInt() 91 compareIntOpInner(t, left, right, func1, func2) 92 left, right = genLBInt() 93 compareIntOpInner(t, left, right, func1, func2) 94 } 95 } 96 97 func TestIntValue_Abs(t *testing.T) { 98 compareIntOp(t, func(left, right *big.Int) ([]byte, error) { 99 abs := big.NewInt(0).Abs(left) 100 return common.BigIntToNeoBytes(abs), nil 101 }, func(left, right *big.Int) ([]byte, error) { 102 val, err := types.IntValFromBigInt(left) 103 assert.Nil(t, err) 104 val = val.Abs() 105 106 return val.ToNeoBytes(), nil 107 }) 108 } 109 110 func TestIntValue_Other(t *testing.T) { 111 opcodes := []OpCode{MOD, AND, OR, XOR, ADD, SUB, MUL, DIV, SHL, SHR, MAX, MIN} 112 for _, opcode := range opcodes { 113 compareIntOp(t, func(left, right *big.Int) ([]byte, error) { 114 return compareFuncBigInt(left, right, opcode) 115 }, func(left, right *big.Int) ([]byte, error) { 116 return compareFuncIntValue(left, right, opcode) 117 }) 118 } 119 } 120 121 func compareFuncIntValue(left, right *big.Int, opcode OpCode) ([]byte, error) { 122 lhs, err := types.IntValFromBigInt(left) 123 if err != nil { 124 return nil, err 125 } 126 rhs, err := types.IntValFromBigInt(right) 127 if err != nil { 128 return nil, err 129 } 130 var val types.IntValue 131 switch opcode { 132 case AND: 133 val, err = lhs.And(rhs) 134 case OR: 135 val, err = lhs.Or(rhs) 136 case XOR: 137 val, err = lhs.Xor(rhs) 138 case ADD: 139 val, err = lhs.Add(rhs) 140 case SUB: 141 val, err = lhs.Sub(rhs) 142 case MUL: 143 val, err = lhs.Mul(rhs) 144 case DIV: 145 val, err = lhs.Div(rhs) 146 case MOD: 147 val, err = lhs.Mod(rhs) 148 case SHL: 149 val, err = lhs.Lsh(rhs) 150 case SHR: 151 val, err = lhs.Rsh(rhs) 152 case MIN: 153 val, err = lhs.Min(rhs) 154 case MAX: 155 val, err = lhs.Max(rhs) 156 } 157 return val.ToNeoBytes(), err 158 } 159 160 func compareFuncBigInt(left, right *big.Int, opcode OpCode) ([]byte, error) { 161 if opcode == SHL { 162 163 if right.Sign() < 0 { 164 return nil, fmt.Errorf("neg num") 165 } 166 167 if left.Sign() != 0 && right.Cmp(big.NewInt(MAX_SIZE_FOR_BIGINTEGER*8)) > 0 { 168 return nil, fmt.Errorf("the biginteger over max size 32bit") 169 } 170 171 if CheckBigInteger(new(big.Int).Lsh(left, uint(right.Int64()))) == false { 172 return nil, fmt.Errorf("the biginteger over max size 32bit") 173 } 174 } 175 nb := BigIntZip(left, right, opcode) 176 return common.BigIntToNeoBytes(nb), nil 177 } 178 179 func CheckBigInteger(value *big.Int) bool { 180 if value == nil { 181 return false 182 } 183 if len(common.BigIntToNeoBytes(value)) > MAX_SIZE_FOR_BIGINTEGER { 184 return false 185 } 186 return true 187 } 188 189 func TestRsh(t *testing.T) { 190 val := types.IntValFromInt(math.MaxInt64) 191 b := new(big.Int).SetUint64(math.MaxUint64) 192 val2, err := types.IntValFromBigInt(b) 193 assert.Nil(t, err) 194 res, err := val.Rsh(val2) 195 assert.Nil(t, err) 196 197 left := new(big.Int).SetInt64(math.MaxInt64) 198 right := new(big.Int).SetUint64(math.MaxUint64) 199 res2 := BigIntZip(left, right, SHR) 200 res22, err := types.IntValFromBigInt(res2) 201 assert.Nil(t, err) 202 assert.Equal(t, res, res22) 203 } 204 205 func TestCmp(t *testing.T) { 206 a, _ := new(big.Int).SetString("73786976294838206464", 10) 207 b, _ := new(big.Int).SetString("83786976294838206464", 10) 208 val_a, err := types.IntValFromBigInt(a) 209 assert.Nil(t, err) 210 val_b, err := types.IntValFromBigInt(b) 211 assert.Nil(t, err) 212 assert.True(t, val_a.Cmp(val_b) < 0) 213 214 res, err := types.IntValFromBigInt(big.NewInt(0).Not(a)) 215 assert.Nil(t, err) 216 assert.Equal(t, val_a.Not(), res) 217 } 218 219 func TestIntValFromNeoBytes(t *testing.T) { 220 bs := common.BigIntToNeoBytes(new(big.Int).SetUint64(math.MaxUint64)) 221 val, err := types.IntValFromNeoBytes(bs) 222 assert.Nil(t, err) 223 val2, err := types.IntValFromBigInt(new(big.Int).SetUint64(math.MaxUint64)) 224 assert.Nil(t, err) 225 assert.Equal(t, val, val2) 226 }