github.com/ari-anchor/sei-tendermint@v0.0.0-20230519144642-dc826b7b56bb/scripts/scmigrate/migrate_test.go (about) 1 package scmigrate 2 3 import ( 4 "bytes" 5 "context" 6 "math/rand" 7 "testing" 8 9 "github.com/gogo/protobuf/proto" 10 dbm "github.com/tendermint/tm-db" 11 12 "github.com/ari-anchor/sei-tendermint/types" 13 ) 14 15 func appendRandomMigrations(in []toMigrate, num int) []toMigrate { 16 if in == nil { 17 in = []toMigrate{} 18 } 19 20 for i := 0; i < num; i++ { 21 height := rand.Int63() 22 if height <= 0 { 23 continue 24 } 25 in = append(in, toMigrate{commit: &types.Commit{Height: height}}) 26 } 27 return in 28 } 29 30 func assertWellOrderedMigrations(t *testing.T, testData []toMigrate) { 31 t.Run("ValuesDescend", func(t *testing.T) { 32 for idx := range testData { 33 height := testData[idx].commit.Height 34 if idx == 0 { 35 continue 36 } 37 prev := testData[idx-1].commit.Height 38 if prev < height { 39 t.Fatal("height decreased in sort order") 40 } 41 } 42 }) 43 t.Run("EarliestIsZero", func(t *testing.T) { 44 earliestHeight := testData[len(testData)-1].commit.Height 45 if earliestHeight != 0 { 46 t.Fatalf("the earliest height is not 0: %d", earliestHeight) 47 } 48 }) 49 } 50 51 func getLatestHeight(data []toMigrate) int64 { 52 var out int64 53 54 for _, d := range data { 55 if d.commit.Height >= out { 56 out = d.commit.Height 57 } 58 } 59 60 return out 61 } 62 63 func insertTestData(t *testing.T, db dbm.DB, data []toMigrate) { 64 t.Helper() 65 66 batch := db.NewBatch() 67 68 for idx, val := range data { 69 payload, err := proto.Marshal(val.commit.ToProto()) 70 if err != nil { 71 t.Fatal(err) 72 } 73 74 if err := batch.Set(makeKeyFromPrefix(prefixSeenCommit, int64(idx)), payload); err != nil { 75 t.Fatal(err) 76 } 77 } 78 if err := batch.WriteSync(); err != nil { 79 t.Fatal(err) 80 } 81 if err := batch.Close(); err != nil { 82 t.Fatal(err) 83 } 84 } 85 86 func TestMigrations(t *testing.T) { 87 t.Run("Sort", func(t *testing.T) { 88 t.Run("HandCraftedData", func(t *testing.T) { 89 testData := []toMigrate{ 90 {commit: &types.Commit{Height: 100}}, 91 {commit: &types.Commit{Height: 0}}, 92 {commit: &types.Commit{Height: 8}}, 93 {commit: &types.Commit{Height: 1}}, 94 } 95 96 sortMigrations(testData) 97 assertWellOrderedMigrations(t, testData) 98 }) 99 t.Run("RandomGeneratedData", func(t *testing.T) { 100 testData := []toMigrate{{commit: &types.Commit{Height: 0}}} 101 102 testData = appendRandomMigrations(testData, 10000) 103 104 sortMigrations(testData) 105 assertWellOrderedMigrations(t, testData) 106 }) 107 }) 108 t.Run("InvalidMigrations", func(t *testing.T) { 109 if _, err := makeToMigrate(nil); err == nil { 110 t.Fatal("should error for nil migrations") 111 } 112 if _, err := makeToMigrate([]byte{}); err == nil { 113 t.Fatal("should error for empty migrations") 114 } 115 if _, err := makeToMigrate([]byte("invalid")); err == nil { 116 t.Fatal("should error for empty migrations") 117 } 118 }) 119 120 t.Run("GetSeenCommits", func(t *testing.T) { 121 ctx, cancel := context.WithCancel(context.Background()) 122 defer cancel() 123 124 db := dbm.NewMemDB() 125 data := appendRandomMigrations([]toMigrate{}, 100) 126 insertTestData(t, db, data) 127 commits, err := getAllSeenCommits(ctx, db) 128 if err != nil { 129 t.Fatal(err) 130 } 131 if len(commits) != len(data) { 132 t.Log("inputs", len(data)) 133 t.Log("commits", len(commits)) 134 t.Fatal("migrations not found in database") 135 } 136 }) 137 t.Run("Integration", func(t *testing.T) { 138 ctx, cancel := context.WithCancel(context.Background()) 139 defer cancel() 140 141 db := dbm.NewMemDB() 142 data := appendRandomMigrations([]toMigrate{}, 1000) 143 insertTestData(t, db, data) 144 145 latestHeight := getLatestHeight(data) 146 for _, test := range []string{"Migration", "Idempotency"} { 147 // run the test twice to make sure that it's 148 // safe to rerun 149 t.Run(test, func(t *testing.T) { 150 if err := Migrate(ctx, db); err != nil { 151 t.Fatalf("Migration failed: %v", err) 152 } 153 154 post, err := getAllSeenCommits(ctx, db) 155 if err != nil { 156 t.Fatalf("Fetching seen commits: %v", err) 157 } 158 159 if len(post) != 1 { 160 t.Fatalf("Wrong number of commits: got %d, wanted 1", len(post)) 161 } 162 163 wantKey := makeKeyFromPrefix(prefixSeenCommit) 164 if !bytes.Equal(post[0].key, wantKey) { 165 t.Errorf("Seen commit key: got %x, want %x", post[0].key, wantKey) 166 } 167 if got := post[0].commit.Height; got != latestHeight { 168 t.Fatalf("Wrong commit height after migration: got %d, wanted %d", got, latestHeight) 169 } 170 }) 171 } 172 }) 173 174 }