forked from TrueCloudLab/neoneo-go
smartcontract: add test for user-defined extended event types configuration
config_extended.yml contains an example of user-defined configuration file with extended event types. User-defined event types are allowed to be named and complicated, i.e. properly support extended types notation. Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
This commit is contained in:
parent
a0d991a500
commit
3e2755e66d
6 changed files with 1288 additions and 5 deletions
|
@ -379,14 +379,24 @@ func TestAssistedRPCBindings(t *testing.T) {
|
||||||
app := cli.NewApp()
|
app := cli.NewApp()
|
||||||
app.Commands = NewCommands()
|
app.Commands = NewCommands()
|
||||||
|
|
||||||
var checkBinding = func(source string) {
|
var checkBinding = func(source string, suffix ...string) {
|
||||||
t.Run(source, func(t *testing.T) {
|
testName := source
|
||||||
|
if len(suffix) != 0 {
|
||||||
|
testName += suffix[0]
|
||||||
|
}
|
||||||
|
t.Run(testName, func(t *testing.T) {
|
||||||
|
configFile := filepath.Join(source, "config.yml")
|
||||||
|
expectedFile := filepath.Join(source, "rpcbindings.out")
|
||||||
|
if len(suffix) != 0 {
|
||||||
|
configFile = filepath.Join(source, "config"+suffix[0]+".yml")
|
||||||
|
expectedFile = filepath.Join(source, "rpcbindings"+suffix[0]+".out")
|
||||||
|
}
|
||||||
manifestF := filepath.Join(tmpDir, "manifest.json")
|
manifestF := filepath.Join(tmpDir, "manifest.json")
|
||||||
bindingF := filepath.Join(tmpDir, "binding.yml")
|
bindingF := filepath.Join(tmpDir, "binding.yml")
|
||||||
nefF := filepath.Join(tmpDir, "out.nef")
|
nefF := filepath.Join(tmpDir, "out.nef")
|
||||||
require.NoError(t, app.Run([]string{"", "contract", "compile",
|
require.NoError(t, app.Run([]string{"", "contract", "compile",
|
||||||
"--in", source,
|
"--in", source,
|
||||||
"--config", filepath.Join(source, "config.yml"),
|
"--config", configFile,
|
||||||
"--manifest", manifestF,
|
"--manifest", manifestF,
|
||||||
"--bindings", bindingF,
|
"--bindings", bindingF,
|
||||||
"--out", nefF,
|
"--out", nefF,
|
||||||
|
@ -402,7 +412,6 @@ func TestAssistedRPCBindings(t *testing.T) {
|
||||||
data, err := os.ReadFile(outFile)
|
data, err := os.ReadFile(outFile)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
data = bytes.ReplaceAll(data, []byte("\r"), []byte{}) // Windows.
|
data = bytes.ReplaceAll(data, []byte("\r"), []byte{}) // Windows.
|
||||||
expectedFile := filepath.Join(source, "rpcbindings.out")
|
|
||||||
if rewriteExpectedOutputs {
|
if rewriteExpectedOutputs {
|
||||||
require.NoError(t, os.WriteFile(expectedFile, data, os.ModePerm))
|
require.NoError(t, os.WriteFile(expectedFile, data, os.ModePerm))
|
||||||
} else {
|
} else {
|
||||||
|
@ -417,6 +426,7 @@ func TestAssistedRPCBindings(t *testing.T) {
|
||||||
checkBinding(filepath.Join("testdata", "types"))
|
checkBinding(filepath.Join("testdata", "types"))
|
||||||
checkBinding(filepath.Join("testdata", "structs"))
|
checkBinding(filepath.Join("testdata", "structs"))
|
||||||
checkBinding(filepath.Join("testdata", "notifications"))
|
checkBinding(filepath.Join("testdata", "notifications"))
|
||||||
|
checkBinding(filepath.Join("testdata", "notifications"), "_extended")
|
||||||
|
|
||||||
require.False(t, rewriteExpectedOutputs)
|
require.False(t, rewriteExpectedOutputs)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,4 +12,8 @@ events:
|
||||||
- name: "SomeStruct"
|
- name: "SomeStruct"
|
||||||
parameters:
|
parameters:
|
||||||
- name: s
|
- name: s
|
||||||
type: Struct
|
type: Struct
|
||||||
|
- name: "SomeArray"
|
||||||
|
parameters:
|
||||||
|
- name: a
|
||||||
|
type: Array
|
47
cli/smartcontract/testdata/notifications/config_extended.yml
vendored
Normal file
47
cli/smartcontract/testdata/notifications/config_extended.yml
vendored
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
name: "Notifications"
|
||||||
|
sourceurl: https://github.com/nspcc-dev/neo-go/
|
||||||
|
events:
|
||||||
|
- name: "! complicated name %$#"
|
||||||
|
parameters:
|
||||||
|
- name: ! complicated param @#$%
|
||||||
|
type: String
|
||||||
|
- name: "SomeMap"
|
||||||
|
parameters:
|
||||||
|
- name: m
|
||||||
|
type: Map
|
||||||
|
extendedtype:
|
||||||
|
base: Map
|
||||||
|
key: Integer
|
||||||
|
value:
|
||||||
|
base: Map
|
||||||
|
key: String
|
||||||
|
value:
|
||||||
|
base: Array
|
||||||
|
value:
|
||||||
|
base: Hash160
|
||||||
|
- name: "SomeStruct"
|
||||||
|
parameters:
|
||||||
|
- name: s
|
||||||
|
type: Struct
|
||||||
|
extendedtype:
|
||||||
|
base: Struct
|
||||||
|
name: crazyStruct
|
||||||
|
- name: "SomeArray"
|
||||||
|
parameters:
|
||||||
|
- name: a
|
||||||
|
type: Array
|
||||||
|
extendedtype:
|
||||||
|
base: Array
|
||||||
|
value:
|
||||||
|
base: Array
|
||||||
|
value:
|
||||||
|
base: Integer
|
||||||
|
namedtypes:
|
||||||
|
crazyStruct:
|
||||||
|
base: Struct
|
||||||
|
name: crazyStruct
|
||||||
|
fields:
|
||||||
|
- field: I
|
||||||
|
base: Integer
|
||||||
|
- field: B
|
||||||
|
base: Boolean
|
|
@ -19,3 +19,7 @@ func Struct() {
|
||||||
B bool
|
B bool
|
||||||
}{I: 123, B: true})
|
}{I: 123, B: true})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Array() {
|
||||||
|
runtime.Notify("SomeArray", [][]int{})
|
||||||
|
}
|
||||||
|
|
|
@ -92,6 +92,11 @@ type SomeStructEvent struct {
|
||||||
S []any
|
S []any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SomeArrayEvent represents "SomeArray" event emitted by the contract.
|
||||||
|
type SomeArrayEvent struct {
|
||||||
|
A []any
|
||||||
|
}
|
||||||
|
|
||||||
// Actor is used by Contract to call state-changing methods.
|
// Actor is used by Contract to call state-changing methods.
|
||||||
type Actor interface {
|
type Actor interface {
|
||||||
MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error)
|
MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error)
|
||||||
|
@ -112,6 +117,28 @@ func New(actor Actor) *Contract {
|
||||||
return &Contract{actor}
|
return &Contract{actor}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Array creates a transaction invoking `array` method of the contract.
|
||||||
|
// This transaction is signed and immediately sent to the network.
|
||||||
|
// The values returned are its hash, ValidUntilBlock value and error if any.
|
||||||
|
func (c *Contract) Array() (util.Uint256, uint32, error) {
|
||||||
|
return c.actor.SendCall(Hash, "array")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArrayTransaction creates a transaction invoking `array` method of the contract.
|
||||||
|
// This transaction is signed, but not sent to the network, instead it's
|
||||||
|
// returned to the caller.
|
||||||
|
func (c *Contract) ArrayTransaction() (*transaction.Transaction, error) {
|
||||||
|
return c.actor.MakeCall(Hash, "array")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArrayUnsigned creates a transaction invoking `array` method of the contract.
|
||||||
|
// This transaction is not signed, it's simply returned to the caller.
|
||||||
|
// Any fields of it that do not affect fees can be changed (ValidUntilBlock,
|
||||||
|
// Nonce), fee values (NetworkFee, SystemFee) can be increased as well.
|
||||||
|
func (c *Contract) ArrayUnsigned() (*transaction.Transaction, error) {
|
||||||
|
return c.actor.MakeUnsignedCall(Hash, "array", nil)
|
||||||
|
}
|
||||||
|
|
||||||
// CrazyMap creates a transaction invoking `crazyMap` method of the contract.
|
// CrazyMap creates a transaction invoking `crazyMap` method of the contract.
|
||||||
// This transaction is signed and immediately sent to the network.
|
// This transaction is signed and immediately sent to the network.
|
||||||
// The values returned are its hash, ValidUntilBlock value and error if any.
|
// The values returned are its hash, ValidUntilBlock value and error if any.
|
||||||
|
@ -936,3 +963,68 @@ func (e *SomeStructEvent) FromStackItem(item *stackitem.Array) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SomeArrayEventsFromApplicationLog retrieves a set of all emitted events
|
||||||
|
// with "SomeArray" name from the provided ApplicationLog.
|
||||||
|
func SomeArrayEventsFromApplicationLog(log *result.ApplicationLog) ([]*SomeArrayEvent, error) {
|
||||||
|
if log == nil {
|
||||||
|
return nil, errors.New("nil application log")
|
||||||
|
}
|
||||||
|
|
||||||
|
var res []*SomeArrayEvent
|
||||||
|
for i, ex := range log.Executions {
|
||||||
|
for j, e := range ex.Events {
|
||||||
|
if e.Name != "SomeArray" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
event := new(SomeArrayEvent)
|
||||||
|
err := event.FromStackItem(e.Item)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to deserialize SomeArrayEvent from stackitem (execution %d, event %d): %w", i, j, err)
|
||||||
|
}
|
||||||
|
res = append(res, event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromStackItem converts provided stackitem.Array to SomeArrayEvent and
|
||||||
|
// returns an error if so.
|
||||||
|
func (e *SomeArrayEvent) FromStackItem(item *stackitem.Array) error {
|
||||||
|
if item == nil {
|
||||||
|
return errors.New("nil item")
|
||||||
|
}
|
||||||
|
arr, ok := item.Value().([]stackitem.Item)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("not an array")
|
||||||
|
}
|
||||||
|
if len(arr) != 1 {
|
||||||
|
return errors.New("wrong number of structure elements")
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
index = -1
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
index++
|
||||||
|
e.A, err = func (item stackitem.Item) ([]any, error) {
|
||||||
|
arr, ok := item.Value().([]stackitem.Item)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("not an array")
|
||||||
|
}
|
||||||
|
res := make([]any, len(arr))
|
||||||
|
for i := range res {
|
||||||
|
res[i], err = arr[i].Value(), error(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("item %d: %w", i, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
} (arr[index])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("field A: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
1126
cli/smartcontract/testdata/notifications/rpcbindings_extended.out
vendored
Executable file
1126
cli/smartcontract/testdata/notifications/rpcbindings_extended.out
vendored
Executable file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue