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  }