code.vegaprotocol.io/vega@v0.79.0/core/teams/snapshot_test.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package teams_test 17 18 import ( 19 "testing" 20 "time" 21 22 "code.vegaprotocol.io/vega/core/types" 23 vgrand "code.vegaprotocol.io/vega/libs/rand" 24 vgtest "code.vegaprotocol.io/vega/libs/test" 25 "code.vegaprotocol.io/vega/paths" 26 27 "github.com/stretchr/testify/assert" 28 "github.com/stretchr/testify/require" 29 ) 30 31 func TestTakingAndRestoringSnapshotSucceeds(t *testing.T) { 32 ctx := vgtest.VegaContext("chainid", 100) 33 34 vegaPath := paths.New(t.TempDir()) 35 now := time.Now() 36 37 te1 := newEngine(t) 38 snapshotEngine1 := newSnapshotEngine(t, vegaPath, now, te1.engine) 39 closeSnapshotEngine1 := vgtest.OnlyOnce(snapshotEngine1.Close) 40 defer closeSnapshotEngine1() 41 42 require.NoError(t, snapshotEngine1.Start(ctx)) 43 44 teamID1 := newTeamID(t) 45 referrer1 := newPartyID(t) 46 name1 := vgrand.RandomStr(5) 47 teamURL1 := "https://" + name1 + ".io" 48 avatarURL1 := "https://avatar." + name1 + ".io" 49 50 expectTeamCreatedEvent(t, te1) 51 team1CreationDate := time.Now() 52 te1.timeService.EXPECT().GetTimeNow().Return(team1CreationDate).Times(1) 53 54 require.NoError(t, te1.engine.CreateTeam(ctx, referrer1, teamID1, createTeamCmd(t, name1, teamURL1, avatarURL1))) 55 56 teamID2 := newTeamID(t) 57 referrer2 := newPartyID(t) 58 name2 := vgrand.RandomStr(5) 59 teamURL2 := "https://" + name2 + ".io" 60 avatarURL2 := "https://avatar." + name2 + ".io" 61 62 expectTeamCreatedEvent(t, te1) 63 team2CreationDate := time.Now() 64 te1.timeService.EXPECT().GetTimeNow().Return(team2CreationDate).Times(1) 65 require.NoError(t, te1.engine.CreateTeam(ctx, referrer2, teamID2, createTeamCmd(t, name2, teamURL2, avatarURL2))) 66 67 referee1 := newPartyID(t) 68 expectRefereeJoinedTeamEvent(t, te1) 69 referee1JoiningDate := time.Now() 70 te1.timeService.EXPECT().GetTimeNow().Return(referee1JoiningDate).Times(1) 71 require.NoError(t, te1.engine.JoinTeam(ctx, referee1, joinTeamCmd(t, teamID1))) 72 73 referee2 := newPartyID(t) 74 75 expectRefereeJoinedTeamEvent(t, te1) 76 referee2JoiningDate := time.Now() 77 te1.timeService.EXPECT().GetTimeNow().Return(referee2JoiningDate).Times(1) 78 require.NoError(t, te1.engine.JoinTeam(ctx, referee2, joinTeamCmd(t, teamID1))) 79 80 // This will occur on next epoch, after the snapshot. This help to ensure 81 // team switches are properly snapshot. 82 require.NoError(t, te1.engine.JoinTeam(ctx, referee2, joinTeamCmd(t, teamID2))) 83 require.True(t, te1.engine.IsTeamMember(referee2)) 84 85 referee3 := newPartyID(t) 86 87 // Closing the team2 to check the allow list is properly snapshot. 88 expectTeamUpdatedEvent(t, te1) 89 require.NoError(t, te1.engine.UpdateTeam(ctx, referrer2, teamID2, updateTeamCmd(t, name2, teamURL2, avatarURL2, true, []string{referee3.String()}))) 90 91 // Take a snapshot. 92 hash1, err := snapshotEngine1.SnapshotNow(ctx) 93 require.NoError(t, err) 94 95 expectRefereeSwitchedTeamEvent(t, te1) 96 referee2JoiningDate2 := time.Now() 97 nextEpoch(t, ctx, te1, referee2JoiningDate2) 98 99 expectRefereeJoinedTeamEvent(t, te1) 100 referee3JoiningDate := time.Now() 101 te1.timeService.EXPECT().GetTimeNow().Return(referee3JoiningDate).Times(1) 102 require.NoError(t, te1.engine.JoinTeam(ctx, referee3, joinTeamCmd(t, teamID2))) 103 104 assertEqualTeams(t, []types.Team{ 105 { 106 ID: teamID1, 107 Referrer: &types.Membership{ 108 PartyID: referrer1, 109 JoinedAt: team1CreationDate, 110 StartedAtEpoch: te1.currentEpoch - 1, 111 }, 112 Referees: []*types.Membership{ 113 { 114 PartyID: referee1, 115 JoinedAt: referee1JoiningDate, 116 StartedAtEpoch: te1.currentEpoch - 1, 117 }, 118 }, 119 Name: name1, 120 TeamURL: teamURL1, 121 AvatarURL: avatarURL1, 122 CreatedAt: team1CreationDate, 123 }, { 124 ID: teamID2, 125 Referrer: &types.Membership{ 126 PartyID: referrer2, 127 JoinedAt: team2CreationDate, 128 StartedAtEpoch: te1.currentEpoch - 1, 129 }, 130 Referees: []*types.Membership{ 131 { 132 PartyID: referee2, 133 JoinedAt: referee2JoiningDate2, 134 StartedAtEpoch: te1.currentEpoch, 135 }, 136 { 137 PartyID: referee3, 138 JoinedAt: referee3JoiningDate, 139 StartedAtEpoch: te1.currentEpoch, 140 }, 141 }, 142 Name: name2, 143 TeamURL: teamURL2, 144 AvatarURL: avatarURL2, 145 CreatedAt: team2CreationDate, 146 Closed: true, 147 AllowList: []types.PartyID{referee3}, 148 }, 149 }, te1.engine.ListTeams()) 150 151 state1 := map[string][]byte{} 152 for _, key := range te1.engine.Keys() { 153 state, additionalProvider, err := te1.engine.GetState(key) 154 require.NoError(t, err) 155 assert.Empty(t, additionalProvider) 156 state1[key] = state 157 } 158 159 closeSnapshotEngine1() 160 161 // Reload the engine using the previous snapshot. 162 163 te2 := newEngine(t) 164 snapshotEngine2 := newSnapshotEngine(t, vegaPath, now, te2.engine) 165 defer snapshotEngine2.Close() 166 167 // This triggers the state restoration from the local snapshot. 168 require.NoError(t, snapshotEngine2.Start(ctx)) 169 170 // Comparing the hash after restoration, to ensure it produces the same result. 171 hash2, _, _ := snapshotEngine2.Info() 172 require.Equal(t, hash1, hash2) 173 174 expectRefereeSwitchedTeamEvent(t, te2) 175 nextEpoch(t, ctx, te2, referee2JoiningDate2) 176 177 expectRefereeJoinedTeamEvent(t, te2) 178 te2.timeService.EXPECT().GetTimeNow().Return(referee3JoiningDate).Times(1) 179 require.NoError(t, te2.engine.JoinTeam(ctx, referee3, joinTeamCmd(t, teamID2))) 180 181 assertEqualTeams(t, []types.Team{ 182 { 183 ID: teamID1, 184 Referrer: &types.Membership{ 185 PartyID: referrer1, 186 JoinedAt: team1CreationDate, 187 StartedAtEpoch: te2.currentEpoch - 1, 188 }, 189 Referees: []*types.Membership{ 190 { 191 PartyID: referee1, 192 JoinedAt: referee1JoiningDate, 193 StartedAtEpoch: te2.currentEpoch - 1, 194 }, 195 }, 196 Name: name1, 197 TeamURL: teamURL1, 198 AvatarURL: avatarURL1, 199 CreatedAt: team1CreationDate, 200 }, { 201 ID: teamID2, 202 Referrer: &types.Membership{ 203 PartyID: referrer2, 204 JoinedAt: team2CreationDate, 205 StartedAtEpoch: te2.currentEpoch - 1, 206 }, 207 Name: name2, 208 TeamURL: teamURL2, 209 AvatarURL: avatarURL2, 210 Referees: []*types.Membership{ 211 { 212 PartyID: referee2, 213 JoinedAt: referee2JoiningDate2, 214 StartedAtEpoch: te2.currentEpoch, 215 }, 216 { 217 PartyID: referee3, 218 JoinedAt: referee3JoiningDate, 219 StartedAtEpoch: te2.currentEpoch, 220 }, 221 }, 222 CreatedAt: team2CreationDate, 223 Closed: true, 224 AllowList: []types.PartyID{referee3}, 225 }, 226 }, te2.engine.ListTeams()) 227 228 state2 := map[string][]byte{} 229 for _, key := range te2.engine.Keys() { 230 state, additionalProvider, err := te2.engine.GetState(key) 231 require.NoError(t, err) 232 assert.Empty(t, additionalProvider) 233 state2[key] = state 234 } 235 236 for key := range state1 { 237 assert.Equalf(t, state1[key], state2[key], "Key %q does not have the same data", key) 238 } 239 }