github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/encoding/fixedn/fixed8_test.go (about)

     1  package fixedn
     2  
     3  import (
     4  	"encoding/json"
     5  	"math"
     6  	"strconv"
     7  	"testing"
     8  
     9  	"github.com/nspcc-dev/neo-go/internal/testserdes"
    10  	"github.com/stretchr/testify/assert"
    11  	"gopkg.in/yaml.v3"
    12  )
    13  
    14  func TestFixed8FromInt64(t *testing.T) {
    15  	values := []int64{9000, 100000000, 5, 10945, -42}
    16  
    17  	for _, val := range values {
    18  		assert.Equal(t, Fixed8(val*decimals), Fixed8FromInt64(val))
    19  		assert.Equal(t, val, Fixed8FromInt64(val).IntegralValue())
    20  		assert.Equal(t, int32(0), Fixed8FromInt64(val).FractionalValue())
    21  	}
    22  }
    23  
    24  func TestFixed8Add(t *testing.T) {
    25  	a := Fixed8FromInt64(1)
    26  	b := Fixed8FromInt64(2)
    27  
    28  	c := a.Add(b)
    29  	expected := int64(3)
    30  	assert.Equal(t, strconv.FormatInt(expected, 10), c.String())
    31  }
    32  
    33  func TestFixed8Sub(t *testing.T) {
    34  	a := Fixed8FromInt64(42)
    35  	b := Fixed8FromInt64(34)
    36  
    37  	c := a.Sub(b)
    38  	assert.Equal(t, int64(8), c.IntegralValue())
    39  	assert.Equal(t, int32(0), c.FractionalValue())
    40  }
    41  
    42  func TestFixed8FromFloat(t *testing.T) {
    43  	inputs := []float64{12.98, 23.87654333, 100.654322, 456789.12345665, -3.14159265}
    44  
    45  	for _, val := range inputs {
    46  		assert.Equal(t, Fixed8(val*decimals), Fixed8FromFloat(val))
    47  		assert.Equal(t, val, Fixed8FromFloat(val).FloatValue())
    48  		trunc := math.Trunc(val)
    49  		rem := (val - trunc) * decimals
    50  		assert.Equal(t, int64(trunc), Fixed8FromFloat(val).IntegralValue())
    51  		assert.Equal(t, int32(math.Round(rem)), Fixed8FromFloat(val).FractionalValue())
    52  	}
    53  }
    54  
    55  func TestFixed8FromString(t *testing.T) {
    56  	// Fixed8FromString works correctly with integers
    57  	ivalues := []string{"9000", "100000000", "5", "10945", "20.45", "0.00000001", "-42"}
    58  	for _, val := range ivalues {
    59  		n, err := Fixed8FromString(val)
    60  		assert.Nil(t, err)
    61  		assert.Equal(t, val, n.String())
    62  	}
    63  
    64  	// Fixed8FromString parses number with maximal precision
    65  	val := "123456789.12345678"
    66  	n, err := Fixed8FromString(val)
    67  	assert.Nil(t, err)
    68  	assert.Equal(t, Fixed8(12345678912345678), n)
    69  
    70  	// Fixed8FromString parses number with non-maximal precision
    71  	val = "901.2341"
    72  	n, err = Fixed8FromString(val)
    73  	assert.Nil(t, err)
    74  	assert.Equal(t, Fixed8(90123410000), n)
    75  
    76  	// Fixed8FromString with errors
    77  	val = "90n1"
    78  	_, err = Fixed8FromString(val)
    79  	assert.Error(t, err)
    80  
    81  	val = "90.1s"
    82  	_, err = Fixed8FromString(val)
    83  	assert.Error(t, err)
    84  }
    85  
    86  func TestSatoshi(t *testing.T) {
    87  	satoshif8 := Satoshi()
    88  	assert.Equal(t, "0.00000001", satoshif8.String())
    89  }
    90  
    91  func TestFixed8UnmarshalJSON(t *testing.T) {
    92  	var testCases = []float64{
    93  		123.45,
    94  		-123.45,
    95  	}
    96  
    97  	for _, fl := range testCases {
    98  		str := strconv.FormatFloat(fl, 'g', -1, 64)
    99  		expected, _ := Fixed8FromString(str)
   100  
   101  		// UnmarshalJSON should decode floats
   102  		var u1 Fixed8
   103  		s, _ := json.Marshal(fl)
   104  		assert.Nil(t, json.Unmarshal(s, &u1))
   105  		assert.Equal(t, expected, u1)
   106  
   107  		// UnmarshalJSON should decode strings
   108  		var u2 Fixed8
   109  		s, _ = json.Marshal(str)
   110  		assert.Nil(t, json.Unmarshal(s, &u2))
   111  		assert.Equal(t, expected, u2)
   112  	}
   113  
   114  	errorCases := []string{
   115  		`"123.u"`,
   116  		"13.j",
   117  	}
   118  
   119  	for _, tc := range errorCases {
   120  		var u Fixed8
   121  		assert.Error(t, u.UnmarshalJSON([]byte(tc)))
   122  	}
   123  }
   124  
   125  func TestFixed8_Unmarshal(t *testing.T) {
   126  	var expected = Fixed8(223719420)
   127  	var cases = []string{"2.2371942", `"2.2371942"`} // this easily gives 223719419 if interpreted as float
   128  
   129  	for _, c := range cases {
   130  		var u1, u2 Fixed8
   131  		assert.Nil(t, json.Unmarshal([]byte(c), &u1))
   132  		assert.Equal(t, expected, u1)
   133  		assert.Nil(t, yaml.Unmarshal([]byte(c), &u2))
   134  		assert.Equal(t, expected, u2)
   135  	}
   136  }
   137  
   138  func TestFixed8_MarshalJSON(t *testing.T) {
   139  	u, err := Fixed8FromString("123.4")
   140  	assert.NoError(t, err)
   141  
   142  	s, err := json.Marshal(u)
   143  	assert.NoError(t, err)
   144  	assert.Equal(t, []byte(`"123.4"`), s)
   145  }
   146  
   147  func TestFixed8_UnmarshalYAML(t *testing.T) {
   148  	u, err := Fixed8FromString("123.4")
   149  	assert.NoError(t, err)
   150  
   151  	s, err := yaml.Marshal(u)
   152  	assert.NoError(t, err)
   153  	assert.Equal(t, []byte("\"123.4\"\n"), s) // yaml marshaler inserts LF at the end
   154  
   155  	var f Fixed8
   156  	assert.NoError(t, yaml.Unmarshal([]byte(`"123.4"`), &f))
   157  	assert.Equal(t, u, f)
   158  }
   159  
   160  func TestFixed8_Arith(t *testing.T) {
   161  	u1 := Fixed8FromInt64(3)
   162  	u2 := Fixed8FromInt64(8)
   163  
   164  	assert.True(t, u1.LessThan(u2))
   165  	assert.True(t, u2.GreaterThan(u1))
   166  	assert.True(t, u1.Equal(u1))
   167  	assert.NotZero(t, u1.CompareTo(u2))
   168  	assert.Zero(t, u1.CompareTo(u1))
   169  	assert.EqualValues(t, Fixed8(2), u2.Div(3))
   170  }
   171  
   172  func TestFixed8_Serializable(t *testing.T) {
   173  	a := Fixed8(0x0102030405060708)
   174  
   175  	testserdes.EncodeDecodeBinary(t, &a, new(Fixed8))
   176  }