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
5066d645a0
commit
1ebeff7f6f
4 changed files with 96 additions and 0 deletions
|
@ -1,6 +1,7 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
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/native/std"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/storage"
|
"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)
|
data := std.Serialize(value)
|
||||||
storage.Put(ctx, key, data)
|
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