github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/storage/badger/operation/events_test.go (about)

     1  package operation
     2  
     3  import (
     4  	"bytes"
     5  	"testing"
     6  
     7  	"golang.org/x/exp/slices"
     8  
     9  	"github.com/dgraph-io/badger/v2"
    10  	"github.com/stretchr/testify/require"
    11  
    12  	"github.com/onflow/flow-go/model/flow"
    13  	"github.com/onflow/flow-go/utils/unittest"
    14  )
    15  
    16  // TestRetrieveEventByBlockIDTxID tests event insertion, event retrieval by block id, block id and transaction id,
    17  // and block id and event type
    18  func TestRetrieveEventByBlockIDTxID(t *testing.T) {
    19  	unittest.RunWithBadgerDB(t, func(db *badger.DB) {
    20  
    21  		// create block ids, transaction ids and event types slices
    22  		blockIDs := []flow.Identifier{flow.HashToID([]byte{0x01}), flow.HashToID([]byte{0x02})}
    23  		txIDs := []flow.Identifier{flow.HashToID([]byte{0x11}), flow.HashToID([]byte{0x12})}
    24  		eTypes := []flow.EventType{flow.EventAccountCreated, flow.EventAccountUpdated}
    25  
    26  		// create map of block id to event, tx id to event and event type to event
    27  		blockMap := make(map[string][]flow.Event)
    28  		txMap := make(map[string][]flow.Event)
    29  		typeMap := make(map[string][]flow.Event)
    30  
    31  		// initialize the maps and the db
    32  		for _, b := range blockIDs {
    33  
    34  			bEvents := make([]flow.Event, 0)
    35  
    36  			// all blocks share the same transactions
    37  			for i, tx := range txIDs {
    38  
    39  				tEvents := make([]flow.Event, 0)
    40  
    41  				// create one event for each possible event type
    42  				for j, etype := range eTypes {
    43  
    44  					eEvents := make([]flow.Event, 0)
    45  
    46  					event := unittest.EventFixture(etype, uint32(i), uint32(j), tx, 0)
    47  
    48  					// insert event into the db
    49  					err := db.Update(InsertEvent(b, event))
    50  					require.Nil(t, err)
    51  
    52  					// update event arrays in the maps
    53  					bEvents = append(bEvents, event)
    54  					tEvents = append(tEvents, event)
    55  					eEvents = append(eEvents, event)
    56  
    57  					key := b.String() + "_" + string(etype)
    58  					if _, ok := typeMap[key]; ok {
    59  						typeMap[key] = append(typeMap[key], eEvents...)
    60  					} else {
    61  						typeMap[key] = eEvents
    62  					}
    63  				}
    64  				txMap[b.String()+"_"+tx.String()] = tEvents
    65  			}
    66  			blockMap[b.String()] = bEvents
    67  		}
    68  
    69  		assertFunc := func(err error, expected []flow.Event, actual []flow.Event) {
    70  			require.NoError(t, err)
    71  			sortEvent(expected)
    72  			sortEvent(actual)
    73  			require.Equal(t, expected, actual)
    74  		}
    75  
    76  		t.Run("retrieve events by Block ID", func(t *testing.T) {
    77  			for _, b := range blockIDs {
    78  				var actualEvents = make([]flow.Event, 0)
    79  
    80  				// lookup events by block id
    81  				err := db.View(LookupEventsByBlockID(b, &actualEvents))
    82  
    83  				expectedEvents := blockMap[b.String()]
    84  				assertFunc(err, expectedEvents, actualEvents)
    85  			}
    86  		})
    87  
    88  		t.Run("retrieve events by block ID and transaction ID", func(t *testing.T) {
    89  			for _, b := range blockIDs {
    90  				for _, t := range txIDs {
    91  					var actualEvents = make([]flow.Event, 0)
    92  
    93  					//lookup events by block id and transaction id
    94  					err := db.View(RetrieveEvents(b, t, &actualEvents))
    95  
    96  					expectedEvents := txMap[b.String()+"_"+t.String()]
    97  					assertFunc(err, expectedEvents, actualEvents)
    98  				}
    99  			}
   100  		})
   101  
   102  		t.Run("retrieve events by block ID and event type", func(t *testing.T) {
   103  			for _, b := range blockIDs {
   104  				for _, et := range eTypes {
   105  					var actualEvents = make([]flow.Event, 0)
   106  
   107  					//lookup events by block id and transaction id
   108  					err := db.View(LookupEventsByBlockIDEventType(b, et, &actualEvents))
   109  
   110  					expectedEvents := typeMap[b.String()+"_"+string(et)]
   111  					assertFunc(err, expectedEvents, actualEvents)
   112  				}
   113  			}
   114  		})
   115  	})
   116  }
   117  
   118  // Event retrieval does not guarantee any order,
   119  // Hence, we a sort the events for comparing the expected and actual events.
   120  func sortEvent(events []flow.Event) {
   121  	slices.SortFunc(events, func(i, j flow.Event) int {
   122  		tComp := bytes.Compare(i.TransactionID[:], j.TransactionID[:])
   123  		if tComp != 0 {
   124  			return tComp
   125  		}
   126  		return int(i.EventIndex) - int(j.EventIndex)
   127  	})
   128  }