forked from TrueCloudLab/neoneo-go
6b21ad9922
Everywhere including examples, external interop APIs, bindings generators code and in other valuable places. A couple of `interface{}` usages are intentionally left in the CHANGELOG.md, documentation and tests.
216 lines
6.7 KiB
Go
216 lines
6.7 KiB
Go
package manifest
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/nspcc-dev/neo-go/internal/random"
|
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestNewPermission(t *testing.T) {
|
|
require.Panics(t, func() { NewPermission(PermissionWildcard, util.Uint160{}) })
|
|
require.Panics(t, func() { NewPermission(PermissionHash) })
|
|
require.Panics(t, func() { NewPermission(PermissionHash, 1) })
|
|
require.Panics(t, func() { NewPermission(PermissionGroup) })
|
|
require.Panics(t, func() { NewPermission(PermissionGroup, util.Uint160{}) })
|
|
}
|
|
|
|
func TestPermissionIsValid(t *testing.T) {
|
|
p := Permission{}
|
|
require.NoError(t, p.IsValid())
|
|
|
|
p.Methods.Add("")
|
|
require.Error(t, p.IsValid())
|
|
|
|
p.Methods.Value = nil
|
|
p.Methods.Add("qwerty")
|
|
require.NoError(t, p.IsValid())
|
|
|
|
p.Methods.Add("poiuyt")
|
|
require.NoError(t, p.IsValid())
|
|
|
|
p.Methods.Add("qwerty")
|
|
require.Error(t, p.IsValid())
|
|
}
|
|
|
|
func TestPermissionsAreValid(t *testing.T) {
|
|
p := Permissions{}
|
|
require.NoError(t, p.AreValid())
|
|
|
|
p = append(p, Permission{Methods: WildStrings{Value: []string{""}}})
|
|
require.Error(t, p.AreValid())
|
|
|
|
p = p[:0]
|
|
p = append(p, *NewPermission(PermissionHash, util.Uint160{1, 2, 3}))
|
|
require.NoError(t, p.AreValid())
|
|
|
|
priv0, err := keys.NewPrivateKey()
|
|
require.NoError(t, err)
|
|
priv1, err := keys.NewPrivateKey()
|
|
require.NoError(t, err)
|
|
|
|
p = append(p, *NewPermission(PermissionGroup, priv0.PublicKey()))
|
|
require.NoError(t, p.AreValid())
|
|
|
|
p = append(p, *NewPermission(PermissionGroup, priv1.PublicKey()))
|
|
require.NoError(t, p.AreValid())
|
|
|
|
p = append(p, *NewPermission(PermissionWildcard))
|
|
require.NoError(t, p.AreValid())
|
|
|
|
p = append(p, *NewPermission(PermissionHash, util.Uint160{3, 2, 1}))
|
|
require.NoError(t, p.AreValid())
|
|
|
|
p = append(p, *NewPermission(PermissionWildcard))
|
|
require.Error(t, p.AreValid())
|
|
|
|
p = append(p[:len(p)-1], *NewPermission(PermissionHash, util.Uint160{1, 2, 3}))
|
|
require.Error(t, p.AreValid())
|
|
|
|
p = append(p[:len(p)-1], *NewPermission(PermissionGroup, priv0.PublicKey()))
|
|
require.Error(t, p.AreValid())
|
|
}
|
|
|
|
func TestPermission_MarshalJSON(t *testing.T) {
|
|
t.Run("wildcard", func(t *testing.T) {
|
|
expected := NewPermission(PermissionWildcard)
|
|
expected.Methods.Restrict()
|
|
testMarshalUnmarshal(t, expected, NewPermission(PermissionWildcard))
|
|
})
|
|
|
|
t.Run("group", func(t *testing.T) {
|
|
expected := NewPermission(PermissionWildcard)
|
|
expected.Contract.Type = PermissionGroup
|
|
priv, err := keys.NewPrivateKey()
|
|
require.NoError(t, err)
|
|
expected.Contract.Value = priv.PublicKey()
|
|
expected.Methods.Add("method1")
|
|
expected.Methods.Add("method2")
|
|
testMarshalUnmarshal(t, expected, NewPermission(PermissionWildcard))
|
|
})
|
|
|
|
t.Run("hash", func(t *testing.T) {
|
|
expected := NewPermission(PermissionWildcard)
|
|
expected.Contract.Type = PermissionHash
|
|
expected.Contract.Value = random.Uint160()
|
|
testMarshalUnmarshal(t, expected, NewPermission(PermissionWildcard))
|
|
})
|
|
}
|
|
|
|
func TestPermissionDesc_MarshalJSON(t *testing.T) {
|
|
t.Run("uint160 with 0x", func(t *testing.T) {
|
|
u := random.Uint160()
|
|
s := u.StringLE()
|
|
js := []byte(fmt.Sprintf(`"0x%s"`, s))
|
|
d := new(PermissionDesc)
|
|
require.NoError(t, json.Unmarshal(js, d))
|
|
require.Equal(t, u, d.Value.(util.Uint160))
|
|
})
|
|
|
|
t.Run("invalid uint160", func(t *testing.T) {
|
|
d := new(PermissionDesc)
|
|
s := random.String(util.Uint160Size * 2)
|
|
js := []byte(fmt.Sprintf(`"ok%s"`, s))
|
|
require.Error(t, json.Unmarshal(js, d))
|
|
|
|
js = []byte(fmt.Sprintf(`"%s"`, s))
|
|
require.Error(t, json.Unmarshal(js, d))
|
|
})
|
|
|
|
t.Run("invalid public key", func(t *testing.T) {
|
|
d := new(PermissionDesc)
|
|
s := random.String(65)
|
|
s = "k" + s // not a hex
|
|
js := []byte(fmt.Sprintf(`"%s"`, s))
|
|
require.Error(t, json.Unmarshal(js, d))
|
|
})
|
|
|
|
t.Run("not a string", func(t *testing.T) {
|
|
d := new(PermissionDesc)
|
|
js := []byte(`123`)
|
|
require.Error(t, json.Unmarshal(js, d))
|
|
})
|
|
|
|
t.Run("invalid string", func(t *testing.T) {
|
|
d := new(PermissionDesc)
|
|
js := []byte(`"invalid length"`)
|
|
require.Error(t, json.Unmarshal(js, d))
|
|
})
|
|
}
|
|
|
|
func testMarshalUnmarshal(t *testing.T, expected, actual any) {
|
|
data, err := json.Marshal(expected)
|
|
require.NoError(t, err)
|
|
require.NoError(t, json.Unmarshal(data, actual))
|
|
require.Equal(t, expected, actual)
|
|
}
|
|
|
|
func TestPermission_ToStackItemFromStackItem(t *testing.T) {
|
|
t.Run("wildcard", func(t *testing.T) {
|
|
p := NewPermission(PermissionWildcard)
|
|
expected := stackitem.NewStruct([]stackitem.Item{
|
|
stackitem.Null{},
|
|
stackitem.Null{},
|
|
})
|
|
CheckToFromStackItem(t, p, expected)
|
|
})
|
|
|
|
t.Run("hash", func(t *testing.T) {
|
|
p := NewPermission(PermissionHash, util.Uint160{1, 2, 3})
|
|
p.Methods = WildStrings{Value: []string{"a"}}
|
|
expected := stackitem.NewStruct([]stackitem.Item{
|
|
stackitem.NewByteArray(util.Uint160{1, 2, 3}.BytesBE()),
|
|
stackitem.NewArray([]stackitem.Item{
|
|
stackitem.NewByteArray([]byte("a")),
|
|
}),
|
|
})
|
|
CheckToFromStackItem(t, p, expected)
|
|
})
|
|
|
|
t.Run("group", func(t *testing.T) {
|
|
pk, _ := keys.NewPrivateKey()
|
|
p := NewPermission(PermissionGroup, pk.PublicKey())
|
|
expected := stackitem.NewStruct([]stackitem.Item{
|
|
stackitem.NewByteArray(pk.PublicKey().Bytes()),
|
|
stackitem.Null{},
|
|
})
|
|
CheckToFromStackItem(t, p, expected)
|
|
})
|
|
}
|
|
|
|
type Interoperable interface {
|
|
ToStackItem() stackitem.Item
|
|
FromStackItem(stackitem.Item) error
|
|
}
|
|
|
|
func CheckToFromStackItem(t *testing.T, source Interoperable, expected stackitem.Item) {
|
|
actual := source.ToStackItem()
|
|
require.Equal(t, expected, actual)
|
|
actualSource := reflect.New(reflect.TypeOf(source).Elem()).Interface().(Interoperable)
|
|
require.NoError(t, actualSource.FromStackItem(actual))
|
|
require.Equal(t, source, actualSource)
|
|
}
|
|
|
|
func TestPermission_FromStackItemErrors(t *testing.T) {
|
|
errCases := map[string]stackitem.Item{
|
|
"not a struct": stackitem.NewArray([]stackitem.Item{}),
|
|
"invalid length": stackitem.NewStruct([]stackitem.Item{}),
|
|
"invalid contract type": stackitem.NewStruct([]stackitem.Item{stackitem.NewArray([]stackitem.Item{}), stackitem.NewBool(false)}),
|
|
"invalid contract length": stackitem.NewStruct([]stackitem.Item{stackitem.NewByteArray([]byte{1, 2, 3}), stackitem.NewBool(false)}),
|
|
"invalid contract pubkey": stackitem.NewStruct([]stackitem.Item{stackitem.NewByteArray(make([]byte, 33)), stackitem.NewBool(false)}),
|
|
"invalid methods type": stackitem.NewStruct([]stackitem.Item{stackitem.Null{}, stackitem.NewBool(false)}),
|
|
"invalid method name": stackitem.NewStruct([]stackitem.Item{stackitem.Null{}, stackitem.NewArray([]stackitem.Item{stackitem.NewArray([]stackitem.Item{})})}),
|
|
}
|
|
for name, errCase := range errCases {
|
|
t.Run(name, func(t *testing.T) {
|
|
p := new(Permission)
|
|
require.Error(t, p.FromStackItem(errCase))
|
|
})
|
|
}
|
|
}
|