github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/store/sqlstore/upgrade_test.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package sqlstore_test 5 6 import ( 7 "testing" 8 9 "github.com/stretchr/testify/require" 10 "gotest.tools/assert" 11 12 "github.com/masterhung0112/hk_server/v5/model" 13 "github.com/masterhung0112/hk_server/v5/store" 14 "github.com/masterhung0112/hk_server/v5/store/sqlstore" 15 "github.com/masterhung0112/hk_server/v5/store/storetest" 16 ) 17 18 func TestStoreUpgradeDotRelease(t *testing.T) { 19 StoreTest(t, func(t *testing.T, ss store.Store) { 20 sqlStore := ss.(*SqlStore) 21 saveSchemaVersion(sqlStore, "5.33.1") 22 err := upgradeDatabase(sqlStore, CurrentSchemaVersion) 23 require.NoError(t, err) 24 require.Equal(t, CurrentSchemaVersion, sqlStore.GetCurrentSchemaVersion()) 25 }) 26 } 27 28 func TestStoreUpgrade(t *testing.T) { 29 storetest.StoreTest(t, func(t *testing.T, ss store.Store) { 30 sqlStore := ss.(*sqlstore.SqlStore) 31 32 t.Run("invalid currentModelVersion", func(t *testing.T) { 33 err := sqlstore.UpgradeDatabase(sqlStore, "notaversion") 34 require.EqualError(t, err, "failed to parse current model version notaversion: No Major.Minor.Patch elements found") 35 }) 36 37 t.Run("upgrade from invalid version", func(t *testing.T) { 38 sqlstore.SaveSchemaVersion(sqlStore, "invalid") 39 err := sqlstore.UpgradeDatabase(sqlStore, "5.8.0") 40 require.EqualError(t, err, "failed to parse database schema version invalid: No Major.Minor.Patch elements found") 41 require.Equal(t, "invalid", sqlStore.GetCurrentSchemaVersion()) 42 }) 43 44 t.Run("upgrade from unsupported version", func(t *testing.T) { 45 sqlstore.SaveSchemaVersion(sqlStore, "2.0.0") 46 err := sqlstore.UpgradeDatabase(sqlStore, "5.8.0") 47 require.EqualError(t, err, "Database schema version 2.0.0 is no longer supported. This Mattermost server supports automatic upgrades from schema version 3.0.0 through schema version 5.8.0. Please manually upgrade to at least version 3.0.0 before continuing.") 48 require.Equal(t, "2.0.0", sqlStore.GetCurrentSchemaVersion()) 49 }) 50 51 t.Run("upgrade from earliest supported version", func(t *testing.T) { 52 sqlstore.SaveSchemaVersion(sqlStore, sqlstore.Version300) 53 err := sqlstore.UpgradeDatabase(sqlStore, sqlstore.CurrentSchemaVersion) 54 require.NoError(t, err) 55 require.Equal(t, sqlstore.CurrentSchemaVersion, sqlStore.GetCurrentSchemaVersion()) 56 }) 57 58 t.Run("upgrade from no existing version", func(t *testing.T) { 59 sqlstore.SaveSchemaVersion(sqlStore, "") 60 err := sqlstore.UpgradeDatabase(sqlStore, sqlstore.CurrentSchemaVersion) 61 require.NoError(t, err) 62 require.Equal(t, sqlstore.CurrentSchemaVersion, sqlStore.GetCurrentSchemaVersion()) 63 }) 64 65 t.Run("upgrade schema running earlier minor version", func(t *testing.T) { 66 sqlstore.SaveSchemaVersion(sqlStore, "5.1.0") 67 err := sqlstore.UpgradeDatabase(sqlStore, "5.8.0") 68 require.NoError(t, err) 69 // Assert sqlstore.CurrentSchemaVersion, not 5.8.0, since the migrations will move 70 // past 5.8.0 regardless of the input parameter. 71 require.Equal(t, sqlstore.CurrentSchemaVersion, sqlStore.GetCurrentSchemaVersion()) 72 }) 73 74 t.Run("upgrade schema running later minor version", func(t *testing.T) { 75 sqlstore.SaveSchemaVersion(sqlStore, "5.99.0") 76 err := sqlstore.UpgradeDatabase(sqlStore, "5.8.0") 77 require.NoError(t, err) 78 require.Equal(t, "5.99.0", sqlStore.GetCurrentSchemaVersion()) 79 }) 80 81 t.Run("upgrade schema running earlier major version", func(t *testing.T) { 82 sqlstore.SaveSchemaVersion(sqlStore, "4.1.0") 83 err := sqlstore.UpgradeDatabase(sqlStore, sqlstore.CurrentSchemaVersion) 84 require.NoError(t, err) 85 require.Equal(t, sqlstore.CurrentSchemaVersion, sqlStore.GetCurrentSchemaVersion()) 86 }) 87 88 t.Run("upgrade schema running later major version", func(t *testing.T) { 89 sqlstore.SaveSchemaVersion(sqlStore, "6.0.0") 90 err := sqlstore.UpgradeDatabase(sqlStore, "5.8.0") 91 require.EqualError(t, err, "Database schema version 6.0.0 is not supported. This Mattermost server supports only >=5.8.0, <6.0.0. Please upgrade to at least version 6.0.0 before continuing.") 92 require.Equal(t, "6.0.0", sqlStore.GetCurrentSchemaVersion()) 93 }) 94 }) 95 } 96 97 func TestSaveSchemaVersion(t *testing.T) { 98 storetest.StoreTest(t, func(t *testing.T, ss store.Store) { 99 sqlStore := ss.(*sqlstore.SqlStore) 100 101 t.Run("set earliest version", func(t *testing.T) { 102 sqlstore.SaveSchemaVersion(sqlStore, sqlstore.Version300) 103 props, err := ss.System().Get() 104 require.NoError(t, err) 105 106 require.Equal(t, sqlstore.Version300, props["Version"]) 107 require.Equal(t, sqlstore.Version300, sqlStore.GetCurrentSchemaVersion()) 108 }) 109 110 t.Run("set current version", func(t *testing.T) { 111 sqlstore.SaveSchemaVersion(sqlStore, sqlstore.CurrentSchemaVersion) 112 props, err := ss.System().Get() 113 require.NoError(t, err) 114 115 require.Equal(t, sqlstore.CurrentSchemaVersion, props["Version"]) 116 require.Equal(t, sqlstore.CurrentSchemaVersion, sqlStore.GetCurrentSchemaVersion()) 117 }) 118 }) 119 } 120 121 func createChannelMemberWithLastViewAt(ss store.Store, channelId, userId string, lastViewAt int64) *model.ChannelMember { 122 m := model.ChannelMember{} 123 m.ChannelId = channelId 124 m.UserId = userId 125 m.LastViewedAt = lastViewAt 126 m.NotifyProps = model.GetDefaultChannelNotifyProps() 127 cm, _ := ss.Channel().SaveMember(&m) 128 return cm 129 } 130 func createPostWithTimestamp(ss store.Store, channelId, userId, rootId, parentId string, timestamp int64) *model.Post { 131 m := model.Post{} 132 m.CreateAt = timestamp 133 m.ChannelId = channelId 134 m.UserId = userId 135 m.RootId = rootId 136 m.ParentId = parentId 137 m.Message = "zz" + model.NewId() + "b" 138 p, _ := ss.Post().Save(&m) 139 return p 140 } 141 142 func createChannelWithLastPostAt(ss store.Store, teamId, creatorId string, lastPostAt, msgCount, rootCount int64) (*model.Channel, error) { 143 m := model.Channel{} 144 m.TeamId = teamId 145 m.TotalMsgCount = msgCount 146 m.TotalMsgCountRoot = rootCount 147 m.LastPostAt = lastPostAt 148 m.CreatorId = creatorId 149 m.DisplayName = "Name" 150 m.Name = "zz" + model.NewId() + "b" 151 m.Type = model.CHANNEL_OPEN 152 return ss.Channel().Save(&m, -1) 153 } 154 155 func TestMsgCountRootMigration(t *testing.T) { 156 type TestCaseChannel struct { 157 Name string 158 PostTimes []int64 159 ReplyTimes []int64 160 MembershipsLastViewAt []int64 161 ExpectedMembershipMsgCountRoot []int64 162 } 163 type TestTableEntry struct { 164 name string 165 data []TestCaseChannel 166 } 167 testTable := []TestTableEntry{ 168 { 169 name: "test1", 170 data: []TestCaseChannel{ 171 { 172 Name: "channel with one post", 173 PostTimes: []int64{1000}, 174 ReplyTimes: []int64{0}, 175 MembershipsLastViewAt: []int64{1}, 176 ExpectedMembershipMsgCountRoot: []int64{0}, 177 }, 178 { 179 Name: "channel with one post, read", 180 PostTimes: []int64{1000}, 181 ReplyTimes: []int64{0}, 182 MembershipsLastViewAt: []int64{1000}, 183 ExpectedMembershipMsgCountRoot: []int64{1}, 184 }, 185 { 186 Name: "with one reply, viewed after 2nd root", 187 PostTimes: []int64{1000, 2000, 3000, 4000}, 188 ReplyTimes: []int64{1001, 0, 0, 0}, 189 MembershipsLastViewAt: []int64{2001}, 190 ExpectedMembershipMsgCountRoot: []int64{0}, 191 }, 192 { 193 Name: "two replies, 3 memberships", 194 PostTimes: []int64{1000, 2000, 3000}, 195 ReplyTimes: []int64{1001, 2001, 0}, 196 MembershipsLastViewAt: []int64{2000, 5000, 0}, 197 ExpectedMembershipMsgCountRoot: []int64{0, 3, 0}, 198 }, 199 }, 200 }, 201 } 202 for _, testCase := range testTable { 203 t.Run(testCase.name, func(t *testing.T) { 204 StoreTest(t, func(t *testing.T, ss store.Store) { 205 sqlStore := ss.(*SqlStore) 206 team := createTeam(ss) 207 for _, testChannel := range testCase.data { 208 t.Run(testChannel.Name, func(t *testing.T) { 209 lastPostAt := int64(0) 210 for i := range testChannel.PostTimes { 211 if testChannel.PostTimes[i] > lastPostAt { 212 lastPostAt = testChannel.PostTimes[i] 213 } 214 if testChannel.ReplyTimes[i] > lastPostAt { 215 lastPostAt = testChannel.ReplyTimes[i] 216 } 217 } 218 channel, err := createChannelWithLastPostAt(ss, team.Id, model.NewId(), lastPostAt, int64(len(testChannel.PostTimes)+len(testChannel.ReplyTimes)), int64(len(testChannel.PostTimes))) 219 require.NoError(t, err) 220 var userIds []string 221 for _, md := range testChannel.MembershipsLastViewAt { 222 user := createUser(ss) 223 userIds = append(userIds, user.Id) 224 require.NotNil(t, user) 225 cm := createChannelMemberWithLastViewAt(ss, channel.Id, user.Id, md) 226 require.NotNil(t, cm) 227 } 228 for i, pt := range testChannel.PostTimes { 229 rt := testChannel.ReplyTimes[i] 230 post := createPostWithTimestamp(ss, channel.Id, model.NewId(), "", "", pt) 231 require.NotNil(t, post) 232 if rt > 0 { 233 reply := createPostWithTimestamp(ss, channel.Id, model.NewId(), post.Id, post.Id, rt) 234 require.NotNil(t, reply) 235 } 236 } 237 238 _, err = sqlStore.GetMaster().Exec(`ALTER TABLE Channels DROP COLUMN TotalMsgCountRoot`) 239 require.NoError(t, err) 240 _, err = sqlStore.GetMaster().Exec(`ALTER TABLE ChannelMembers DROP COLUMN MsgCountRoot`) 241 require.NoError(t, err) 242 rootCountMigration(sqlStore) 243 244 members, err := ss.Channel().GetMembersByIds(channel.Id, userIds) 245 require.NoError(t, err) 246 247 for _, m := range *members { 248 for i, uid := range userIds { 249 if m.UserId == uid { 250 assert.Equal(t, testChannel.ExpectedMembershipMsgCountRoot[i], m.MsgCountRoot) 251 break 252 } 253 } 254 } 255 256 }) 257 } 258 }) 259 }) 260 } 261 }