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  }