github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/utils/unittest/generator/events.go (about)

     1  package generator
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/onflow/cadence"
     8  	"github.com/onflow/cadence/encoding/ccf"
     9  	jsoncdc "github.com/onflow/cadence/encoding/json"
    10  	"github.com/onflow/cadence/runtime/common"
    11  	"github.com/onflow/cadence/runtime/stdlib"
    12  	"github.com/onflow/flow/protobuf/go/flow/entities"
    13  	"github.com/stretchr/testify/require"
    14  
    15  	"github.com/onflow/flow-go/fvm/evm/testutils"
    16  	"github.com/onflow/flow-go/model/flow"
    17  	"github.com/onflow/flow-go/utils/unittest"
    18  )
    19  
    20  type EventGeneratorOption func(*Events)
    21  
    22  func WithEncoding(encoding entities.EventEncodingVersion) EventGeneratorOption {
    23  	return func(g *Events) {
    24  		g.encoding = encoding
    25  	}
    26  }
    27  
    28  type Events struct {
    29  	count    uint32
    30  	ids      *Identifiers
    31  	encoding entities.EventEncodingVersion
    32  }
    33  
    34  func EventGenerator(opts ...EventGeneratorOption) *Events {
    35  	g := &Events{
    36  		count:    1,
    37  		ids:      IdentifierGenerator(),
    38  		encoding: entities.EventEncodingVersion_CCF_V0,
    39  	}
    40  
    41  	for _, opt := range opts {
    42  		opt(g)
    43  	}
    44  
    45  	return g
    46  }
    47  
    48  func (g *Events) New() flow.Event {
    49  	address, err := common.BytesToAddress(unittest.RandomAddressFixture().Bytes())
    50  	if err != nil {
    51  		panic(fmt.Sprintf("unexpected error while creating random address: %s", err))
    52  	}
    53  
    54  	location := common.NewAddressLocation(nil, address, "TestContract")
    55  	identifier := fmt.Sprintf("TestContract.FooEvent%d", g.count)
    56  	typeID := location.TypeID(nil, identifier)
    57  
    58  	testEventType := &cadence.EventType{
    59  		Location:            location,
    60  		QualifiedIdentifier: identifier,
    61  		Fields: []cadence.Field{
    62  			{
    63  				Identifier: "a",
    64  				Type:       cadence.IntType,
    65  			},
    66  			{
    67  				Identifier: "b",
    68  				Type:       cadence.StringType,
    69  			},
    70  		},
    71  	}
    72  
    73  	fooString, err := cadence.NewString("foo")
    74  	if err != nil {
    75  		panic(fmt.Sprintf("unexpected error while creating cadence string: %s", err))
    76  	}
    77  
    78  	testEvent := cadence.NewEvent(
    79  		[]cadence.Value{
    80  			cadence.NewInt(int(g.count)),
    81  			fooString,
    82  		}).WithType(testEventType)
    83  
    84  	var payload []byte
    85  	switch g.encoding {
    86  	case entities.EventEncodingVersion_CCF_V0:
    87  		payload, err = ccf.Encode(testEvent)
    88  		if err != nil {
    89  			panic(fmt.Sprintf("unexpected error while ccf encoding events: %s", err))
    90  		}
    91  	case entities.EventEncodingVersion_JSON_CDC_V0:
    92  		payload, err = jsoncdc.Encode(testEvent)
    93  		if err != nil {
    94  			panic(fmt.Sprintf("unexpected error while json encoding events: %s", err))
    95  		}
    96  	}
    97  
    98  	event := flow.Event{
    99  		Type:             flow.EventType(typeID),
   100  		TransactionID:    g.ids.New(),
   101  		TransactionIndex: g.count,
   102  		EventIndex:       g.count,
   103  		Payload:          payload,
   104  	}
   105  
   106  	g.count++
   107  
   108  	return event
   109  }
   110  
   111  // GetEventsWithEncoding generates a specified number of events with a given encoding version.
   112  func GetEventsWithEncoding(n int, version entities.EventEncodingVersion) []flow.Event {
   113  	eventGenerator := EventGenerator(WithEncoding(version))
   114  	events := make([]flow.Event, 0, n)
   115  	for i := 0; i < n; i++ {
   116  		events = append(events, eventGenerator.New())
   117  	}
   118  	return events
   119  }
   120  
   121  // GenerateAccountCreateEvent returns a mock account creation event.
   122  func GenerateAccountCreateEvent(t *testing.T, address flow.Address) flow.Event {
   123  	cadenceEvent := cadence.NewEvent(
   124  		[]cadence.Value{
   125  			cadence.NewAddress(address),
   126  		}).WithType(&cadence.EventType{
   127  		Location:            stdlib.FlowLocation{},
   128  		QualifiedIdentifier: "AccountCreated",
   129  		Fields: []cadence.Field{
   130  			{
   131  				Identifier: "address",
   132  				Type:       cadence.AddressType,
   133  			},
   134  		},
   135  	})
   136  
   137  	payload, err := ccf.Encode(cadenceEvent)
   138  	require.NoError(t, err)
   139  
   140  	event := unittest.EventFixture(
   141  		flow.EventType(cadenceEvent.EventType.Location.TypeID(nil, cadenceEvent.EventType.QualifiedIdentifier)),
   142  		0,
   143  		0,
   144  		unittest.IdentifierFixture(),
   145  		0,
   146  	)
   147  
   148  	event.Payload = payload
   149  
   150  	return event
   151  }
   152  
   153  // GenerateAccountContractEvent returns a mock account contract event.
   154  func GenerateAccountContractEvent(t *testing.T, qualifiedIdentifier string, address flow.Address) flow.Event {
   155  	contractName, err := cadence.NewString("EventContract")
   156  	require.NoError(t, err)
   157  
   158  	cadenceEvent := cadence.NewEvent(
   159  		[]cadence.Value{
   160  			cadence.NewAddress(address),
   161  			cadence.NewArray(
   162  				testutils.ConvertToCadence([]byte{111, 43, 164, 202, 220, 174, 148, 17, 253, 161, 9, 124, 237, 83, 227, 75, 115, 149, 141, 83, 129, 145, 252, 68, 122, 137, 80, 155, 89, 233, 136, 213}),
   163  			).WithType(cadence.NewConstantSizedArrayType(32, cadence.UInt8Type)),
   164  			contractName,
   165  		}).WithType(&cadence.EventType{
   166  		Location:            stdlib.FlowLocation{},
   167  		QualifiedIdentifier: qualifiedIdentifier,
   168  		Fields: []cadence.Field{
   169  			{
   170  				Identifier: "address",
   171  				Type:       cadence.AddressType,
   172  			},
   173  			{
   174  				Identifier: "codeHash",
   175  				Type:       cadence.NewConstantSizedArrayType(32, cadence.UInt8Type),
   176  			},
   177  			{
   178  				Identifier: "contract",
   179  				Type:       cadence.StringType,
   180  			},
   181  		},
   182  	})
   183  
   184  	payload, err := ccf.Encode(cadenceEvent)
   185  	require.NoError(t, err)
   186  
   187  	event := unittest.EventFixture(
   188  		flow.EventType(cadenceEvent.EventType.Location.TypeID(nil, cadenceEvent.EventType.QualifiedIdentifier)),
   189  		0,
   190  		0,
   191  		unittest.IdentifierFixture(),
   192  		0,
   193  	)
   194  
   195  	event.Payload = payload
   196  
   197  	return event
   198  }