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 }