forked from TrueCloudLab/frostfs-contract
[#42] common: Add routines for fixed-width uint64 marshaling
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
This commit is contained in:
parent
ab0a899a28
commit
2be81b1def
4 changed files with 96 additions and 0 deletions
|
@ -1,6 +1,7 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/convert"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/native/std"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/storage"
|
||||
)
|
||||
|
@ -10,3 +11,18 @@ func SetSerialized(ctx storage.Context, key interface{}, value interface{}) {
|
|||
data := std.Serialize(value)
|
||||
storage.Put(ctx, key, data)
|
||||
}
|
||||
|
||||
// ToFixedWidth64 converts x to bytes such that numbers <= math.MaxUint64
|
||||
// have constant with of 9.
|
||||
func ToFixedWidth64(x int) []byte {
|
||||
data := convert.ToBytes(x)
|
||||
if x < 0 || len(data) >= 9 {
|
||||
return data
|
||||
}
|
||||
return append(data, make([]byte, 9-len(data))...)
|
||||
}
|
||||
|
||||
// FromFixedWidth64 is a reverse function for ToFixedWidth64.
|
||||
func FromFixedWidth64(x []byte) int {
|
||||
return convert.ToInteger(x)
|
||||
}
|
||||
|
|
61
tests/common_test.go
Normal file
61
tests/common_test.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
package tests
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/big"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/neotest"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const testdataPath = "./testdata"
|
||||
|
||||
func newTestdataInvoker(t *testing.T) *neotest.ContractInvoker {
|
||||
e := newExecutor(t)
|
||||
ctr := neotest.CompileFile(t, e.CommitteeHash, testdataPath, path.Join(testdataPath, "config.yml"))
|
||||
e.DeployContract(t, ctr, nil)
|
||||
return e.CommitteeInvoker(ctr.Hash)
|
||||
}
|
||||
|
||||
func TestEncodeU64(t *testing.T) {
|
||||
// Let's check boundary values for all bit sizes:
|
||||
var nums []uint64
|
||||
for i := 0; i < 64; i++ {
|
||||
if i != 0 {
|
||||
nums = append(nums, (1<<i)-1)
|
||||
}
|
||||
nums = append(nums, 1<<i)
|
||||
if i != 63 {
|
||||
nums = append(nums, (1<<i)+1)
|
||||
}
|
||||
}
|
||||
|
||||
c := newTestdataInvoker(t)
|
||||
for _, n := range nums {
|
||||
v, err := c.TestInvoke(t, "encode", n)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, v.Len())
|
||||
|
||||
r := v.Pop().Bytes()
|
||||
require.Equal(t, 9, len(r), "got: %x", r)
|
||||
|
||||
v, err = c.TestInvoke(t, "encodeDecode", n)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, v.Len())
|
||||
require.Equal(t, n, v.Pop().BigInt().Uint64())
|
||||
}
|
||||
|
||||
t.Run("bad cases should be handled", func(t *testing.T) {
|
||||
x := new(big.Int).SetUint64(math.MaxUint64)
|
||||
x.Add(x, big.NewInt(1))
|
||||
|
||||
nums := []*big.Int{x, big.NewInt(-1), big.NewInt(-128)}
|
||||
for _, n := range nums {
|
||||
v, err := c.TestInvoke(t, "encodeDecode", n)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, v.Pop().BigInt().Cmp(n))
|
||||
}
|
||||
})
|
||||
}
|
2
tests/testdata/config.yml
vendored
Normal file
2
tests/testdata/config.yml
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
name: "TestContract"
|
||||
safemethods: ["encodeDecode"]
|
17
tests/testdata/encode.go
vendored
Normal file
17
tests/testdata/encode.go
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
package testdata
|
||||
|
||||
import (
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/common"
|
||||
)
|
||||
|
||||
// EncodeDecode encodes x in fixed-width little-endian representation
|
||||
// and deserializes it back.
|
||||
func EncodeDecode(x int) int {
|
||||
y := common.ToFixedWidth64(x)
|
||||
return common.FromFixedWidth64(y)
|
||||
}
|
||||
|
||||
// Encode encodes x in fixed-width little-endian representation.
|
||||
func Encode(x int) []byte {
|
||||
return common.ToFixedWidth64(x)
|
||||
}
|
Loading…
Reference in a new issue