github.com/koko1123/flow-go-1@v0.29.6/storage/badger/operation/events_test.go (about)

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