github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/fvm/environment/event_emitter_test.go (about)

     1  package environment_test
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/assert"
     7  	"github.com/stretchr/testify/require"
     8  
     9  	"github.com/onflow/cadence"
    10  	"github.com/onflow/cadence/encoding/ccf"
    11  	"github.com/onflow/cadence/runtime/common"
    12  	"github.com/onflow/cadence/runtime/stdlib"
    13  
    14  	"github.com/onflow/flow-go/fvm/environment"
    15  	"github.com/onflow/flow-go/fvm/meter"
    16  	"github.com/onflow/flow-go/fvm/storage/state"
    17  	"github.com/onflow/flow-go/fvm/systemcontracts"
    18  	"github.com/onflow/flow-go/fvm/tracing"
    19  	"github.com/onflow/flow-go/model/flow"
    20  )
    21  
    22  func Test_IsServiceEvent(t *testing.T) {
    23  
    24  	chain := flow.Emulator
    25  	events := systemcontracts.ServiceEventsForChain(chain)
    26  
    27  	t.Run("correct", func(t *testing.T) {
    28  		for _, event := range events.All() {
    29  			event := cadence.Event{
    30  				EventType: &cadence.EventType{
    31  					Location: common.AddressLocation{
    32  						Address: common.MustBytesToAddress(
    33  							event.Address.Bytes()),
    34  					},
    35  					QualifiedIdentifier: event.QualifiedIdentifier(),
    36  				},
    37  			}
    38  
    39  			isServiceEvent, err := environment.IsServiceEvent(flow.EventType(event.Type().ID()), chain)
    40  			require.NoError(t, err)
    41  			assert.True(t, isServiceEvent)
    42  		}
    43  	})
    44  
    45  	t.Run("wrong chain", func(t *testing.T) {
    46  		event := cadence.Event{
    47  			EventType: &cadence.EventType{
    48  				Location: common.AddressLocation{
    49  					Address: common.MustBytesToAddress(
    50  						flow.Testnet.Chain().ServiceAddress().Bytes()),
    51  				},
    52  				QualifiedIdentifier: events.EpochCommit.QualifiedIdentifier(),
    53  			},
    54  		}
    55  
    56  		isServiceEvent, err := environment.IsServiceEvent(flow.EventType(event.Type().ID()), chain)
    57  		require.NoError(t, err)
    58  		assert.False(t, isServiceEvent)
    59  	})
    60  
    61  	t.Run("wrong type", func(t *testing.T) {
    62  		event := cadence.Event{
    63  			EventType: &cadence.EventType{
    64  				Location: common.AddressLocation{
    65  					Address: common.MustBytesToAddress(
    66  						chain.Chain().ServiceAddress().Bytes()),
    67  				},
    68  				QualifiedIdentifier: "SomeContract.SomeEvent",
    69  			},
    70  		}
    71  
    72  		isServiceEvent, err := environment.IsServiceEvent(flow.EventType(event.Type().ID()), chain)
    73  		require.NoError(t, err)
    74  		assert.False(t, isServiceEvent)
    75  	})
    76  }
    77  
    78  func Test_ScriptEventEmitter(t *testing.T) {
    79  	// scripts use the NoEventEmitter
    80  	emitter := environment.NoEventEmitter{}
    81  	err := emitter.EmitEvent(cadence.Event{})
    82  	require.NoError(t, err, "script should not error when emitting events")
    83  }
    84  
    85  func Test_EmitEvent_Limit(t *testing.T) {
    86  	t.Run("emit event - service account - within limit", func(t *testing.T) {
    87  		cadenceEvent1 := cadence.Event{
    88  			EventType: &cadence.EventType{
    89  				Location:            stdlib.FlowLocation{},
    90  				QualifiedIdentifier: "test",
    91  			},
    92  		}
    93  
    94  		event1Size := getCadenceEventPayloadByteSize(cadenceEvent1)
    95  		eventEmitter := createTestEventEmitterWithLimit(
    96  			flow.Emulator,
    97  			flow.Emulator.Chain().ServiceAddress(),
    98  			event1Size+1)
    99  
   100  		err := eventEmitter.EmitEvent(cadenceEvent1)
   101  		require.NoError(t, err)
   102  	})
   103  
   104  	t.Run("emit event - service account - exceeding limit", func(t *testing.T) {
   105  		cadenceEvent1 := cadence.Event{
   106  			EventType: &cadence.EventType{
   107  				Location:            stdlib.FlowLocation{},
   108  				QualifiedIdentifier: "test",
   109  			},
   110  		}
   111  
   112  		event1Size := getCadenceEventPayloadByteSize(cadenceEvent1)
   113  		eventEmitter := createTestEventEmitterWithLimit(
   114  			flow.Emulator,
   115  			flow.Emulator.Chain().ServiceAddress(),
   116  			event1Size-1)
   117  
   118  		err := eventEmitter.EmitEvent(cadenceEvent1)
   119  		require.NoError(t, err) // service count doesn't have limit
   120  	})
   121  
   122  	t.Run("emit event - non service account - within limit", func(t *testing.T) {
   123  		cadenceEvent1 := cadence.Event{
   124  			EventType: &cadence.EventType{
   125  				Location:            stdlib.FlowLocation{},
   126  				QualifiedIdentifier: "test",
   127  			},
   128  		}
   129  
   130  		event1Size := getCadenceEventPayloadByteSize(cadenceEvent1)
   131  		eventEmitter := createTestEventEmitterWithLimit(
   132  			flow.Emulator,
   133  			flow.Emulator.Chain().NewAddressGenerator().CurrentAddress(),
   134  			event1Size+1)
   135  
   136  		err := eventEmitter.EmitEvent(cadenceEvent1)
   137  		require.NoError(t, err)
   138  	})
   139  
   140  	t.Run("emit event - non service account - exceeding limit", func(t *testing.T) {
   141  		cadenceEvent1 := cadence.Event{
   142  			EventType: &cadence.EventType{
   143  				Location:            stdlib.FlowLocation{},
   144  				QualifiedIdentifier: "test",
   145  			},
   146  		}
   147  
   148  		event1Size := getCadenceEventPayloadByteSize(cadenceEvent1)
   149  		eventEmitter := createTestEventEmitterWithLimit(
   150  			flow.Emulator,
   151  			flow.Emulator.Chain().NewAddressGenerator().CurrentAddress(),
   152  			event1Size-1)
   153  
   154  		err := eventEmitter.EmitEvent(cadenceEvent1)
   155  		require.Error(t, err)
   156  	})
   157  }
   158  
   159  func createTestEventEmitterWithLimit(chain flow.ChainID, address flow.Address, eventEmitLimit uint64) environment.EventEmitter {
   160  	txnState := state.NewTransactionState(
   161  		nil,
   162  		state.DefaultParameters().WithMeterParameters(
   163  			meter.DefaultParameters().WithEventEmitByteLimit(eventEmitLimit),
   164  		))
   165  
   166  	return environment.NewEventEmitter(
   167  		tracing.NewTracerSpan(),
   168  		environment.NewMeter(txnState),
   169  		chain.Chain(),
   170  		environment.TransactionInfoParams{
   171  			TxId:    flow.ZeroID,
   172  			TxIndex: 0,
   173  			TxBody: &flow.TransactionBody{
   174  				Payer: address,
   175  			},
   176  		},
   177  		environment.EventEmitterParams{
   178  			EventCollectionByteSizeLimit: eventEmitLimit,
   179  			EventEncoder:                 environment.NewCadenceEventEncoder(),
   180  		},
   181  	)
   182  }
   183  
   184  func getCadenceEventPayloadByteSize(event cadence.Event) uint64 {
   185  	payload, err := ccf.Encode(event)
   186  	if err != nil {
   187  		panic(err)
   188  	}
   189  
   190  	return uint64(len(payload))
   191  }