github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/store/storetest/channel_member_history_store.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package storetest 5 6 import ( 7 "testing" 8 9 "math" 10 11 "github.com/mattermost/mattermost-server/v5/model" 12 "github.com/mattermost/mattermost-server/v5/store" 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/require" 15 ) 16 17 func TestChannelMemberHistoryStore(t *testing.T, ss store.Store) { 18 t.Run("TestLogJoinEvent", func(t *testing.T) { testLogJoinEvent(t, ss) }) 19 t.Run("TestLogLeaveEvent", func(t *testing.T) { testLogLeaveEvent(t, ss) }) 20 t.Run("TestGetUsersInChannelAtChannelMemberHistory", func(t *testing.T) { testGetUsersInChannelAtChannelMemberHistory(t, ss) }) 21 t.Run("TestGetUsersInChannelAtChannelMembers", func(t *testing.T) { testGetUsersInChannelAtChannelMembers(t, ss) }) 22 t.Run("TestPermanentDeleteBatch", func(t *testing.T) { testPermanentDeleteBatch(t, ss) }) 23 } 24 25 func testLogJoinEvent(t *testing.T, ss store.Store) { 26 // create a test channel 27 ch := model.Channel{ 28 TeamId: model.NewId(), 29 DisplayName: "Display " + model.NewId(), 30 Name: "zz" + model.NewId() + "b", 31 Type: model.CHANNEL_OPEN, 32 } 33 channel, err := ss.Channel().Save(&ch, -1) 34 require.Nil(t, err) 35 36 // and a test user 37 user := model.User{ 38 Email: MakeEmail(), 39 Nickname: model.NewId(), 40 Username: model.NewId(), 41 } 42 userPtr, err := ss.User().Save(&user) 43 require.Nil(t, err) 44 user = *userPtr 45 46 // log a join event 47 err = ss.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()) 48 assert.Nil(t, err) 49 } 50 51 func testLogLeaveEvent(t *testing.T, ss store.Store) { 52 // create a test channel 53 ch := model.Channel{ 54 TeamId: model.NewId(), 55 DisplayName: "Display " + model.NewId(), 56 Name: "zz" + model.NewId() + "b", 57 Type: model.CHANNEL_OPEN, 58 } 59 channel, err := ss.Channel().Save(&ch, -1) 60 require.Nil(t, err) 61 62 // and a test user 63 user := model.User{ 64 Email: MakeEmail(), 65 Nickname: model.NewId(), 66 Username: model.NewId(), 67 } 68 userPtr, err := ss.User().Save(&user) 69 require.Nil(t, err) 70 user = *userPtr 71 72 // log a join event, followed by a leave event 73 err = ss.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()) 74 assert.Nil(t, err) 75 76 err = ss.ChannelMemberHistory().LogLeaveEvent(user.Id, channel.Id, model.GetMillis()) 77 assert.Nil(t, err) 78 } 79 80 func testGetUsersInChannelAtChannelMemberHistory(t *testing.T, ss store.Store) { 81 // create a test channel 82 ch := &model.Channel{ 83 TeamId: model.NewId(), 84 DisplayName: "Display " + model.NewId(), 85 Name: "zz" + model.NewId() + "b", 86 Type: model.CHANNEL_OPEN, 87 } 88 channel, err := ss.Channel().Save(ch, -1) 89 require.Nil(t, err) 90 91 // and a test user 92 user := model.User{ 93 Email: MakeEmail(), 94 Nickname: model.NewId(), 95 Username: model.NewId(), 96 } 97 userPtr, err := ss.User().Save(&user) 98 require.Nil(t, err) 99 user = *userPtr 100 101 // the user was previously in the channel a long time ago, before the export period starts 102 // the existence of this record makes it look like the MessageExport feature has been active for awhile, and prevents 103 // us from looking in the ChannelMembers table for data that isn't found in the ChannelMemberHistory table 104 leaveTime := model.GetMillis() - 20000 105 joinTime := leaveTime - 10000 106 err = ss.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, joinTime) 107 require.Nil(t, err) 108 err = ss.ChannelMemberHistory().LogLeaveEvent(user.Id, channel.Id, leaveTime) 109 require.Nil(t, err) 110 111 // log a join event 112 leaveTime = model.GetMillis() 113 joinTime = leaveTime - 10000 114 err = ss.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, joinTime) 115 require.Nil(t, err) 116 117 // case 1: user joins and leaves the channel before the export period begins 118 channelMembers, err := ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime-500, joinTime-100, channel.Id) 119 require.Nil(t, err) 120 assert.Empty(t, channelMembers) 121 122 // case 2: user joins the channel after the export period begins, but has not yet left the channel when the export period ends 123 channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime-100, joinTime+500, channel.Id) 124 require.Nil(t, err) 125 assert.Len(t, channelMembers, 1) 126 assert.Equal(t, channel.Id, channelMembers[0].ChannelId) 127 assert.Equal(t, user.Id, channelMembers[0].UserId) 128 assert.Equal(t, user.Email, channelMembers[0].UserEmail) 129 assert.Equal(t, user.Username, channelMembers[0].Username) 130 assert.Equal(t, joinTime, channelMembers[0].JoinTime) 131 assert.Nil(t, channelMembers[0].LeaveTime) 132 133 // case 3: user joins the channel before the export period begins, but has not yet left the channel when the export period ends 134 channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime+100, joinTime+500, channel.Id) 135 require.Nil(t, err) 136 assert.Len(t, channelMembers, 1) 137 assert.Equal(t, channel.Id, channelMembers[0].ChannelId) 138 assert.Equal(t, user.Id, channelMembers[0].UserId) 139 assert.Equal(t, user.Email, channelMembers[0].UserEmail) 140 assert.Equal(t, user.Username, channelMembers[0].Username) 141 assert.Equal(t, joinTime, channelMembers[0].JoinTime) 142 assert.Nil(t, channelMembers[0].LeaveTime) 143 144 // add a leave time for the user 145 err = ss.ChannelMemberHistory().LogLeaveEvent(user.Id, channel.Id, leaveTime) 146 require.Nil(t, err) 147 148 // case 4: user joins the channel before the export period begins, but has not yet left the channel when the export period ends 149 channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime+100, leaveTime-100, channel.Id) 150 require.Nil(t, err) 151 assert.Len(t, channelMembers, 1) 152 assert.Equal(t, channel.Id, channelMembers[0].ChannelId) 153 assert.Equal(t, user.Id, channelMembers[0].UserId) 154 assert.Equal(t, user.Email, channelMembers[0].UserEmail) 155 assert.Equal(t, user.Username, channelMembers[0].Username) 156 assert.Equal(t, joinTime, channelMembers[0].JoinTime) 157 assert.Equal(t, leaveTime, *channelMembers[0].LeaveTime) 158 159 // case 5: user joins the channel after the export period begins, and leaves the channel before the export period ends 160 channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime-100, leaveTime+100, channel.Id) 161 require.Nil(t, err) 162 assert.Len(t, channelMembers, 1) 163 assert.Equal(t, channel.Id, channelMembers[0].ChannelId) 164 assert.Equal(t, user.Id, channelMembers[0].UserId) 165 assert.Equal(t, user.Email, channelMembers[0].UserEmail) 166 assert.Equal(t, user.Username, channelMembers[0].Username) 167 assert.Equal(t, joinTime, channelMembers[0].JoinTime) 168 assert.Equal(t, leaveTime, *channelMembers[0].LeaveTime) 169 170 // case 6: user has joined and left the channel long before the export period begins 171 channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(leaveTime+100, leaveTime+200, channel.Id) 172 require.Nil(t, err) 173 assert.Empty(t, channelMembers) 174 } 175 176 func testGetUsersInChannelAtChannelMembers(t *testing.T, ss store.Store) { 177 // create a test channel 178 channel := &model.Channel{ 179 TeamId: model.NewId(), 180 DisplayName: "Display " + model.NewId(), 181 Name: "zz" + model.NewId() + "b", 182 Type: model.CHANNEL_OPEN, 183 } 184 channel, err := ss.Channel().Save(channel, -1) 185 require.Nil(t, err) 186 187 // and a test user 188 user := model.User{ 189 Email: MakeEmail(), 190 Nickname: model.NewId(), 191 Username: model.NewId(), 192 } 193 userPtr, err := ss.User().Save(&user) 194 require.Nil(t, err) 195 user = *userPtr 196 197 // clear any existing ChannelMemberHistory data that might interfere with our test 198 var tableDataTruncated = false 199 for !tableDataTruncated { 200 var count int64 201 count, err = ss.ChannelMemberHistory().PermanentDeleteBatch(model.GetMillis(), 1000) 202 require.Nil(t, err, "Failed to truncate ChannelMemberHistory contents") 203 tableDataTruncated = count == int64(0) 204 } 205 206 // in this test, we're pretending that Message Export was not activated during the export period, so there's no data 207 // available in the ChannelMemberHistory table. Instead, we'll fall back to the ChannelMembers table for a rough approximation 208 joinTime := int64(1000) 209 leaveTime := joinTime + 5000 210 _, err = ss.Channel().SaveMember(&model.ChannelMember{ 211 ChannelId: channel.Id, 212 UserId: user.Id, 213 NotifyProps: model.GetDefaultChannelNotifyProps(), 214 }) 215 require.Nil(t, err) 216 217 // in every single case, the user will be included in the export, because ChannelMembers says they were in the channel at some point in 218 // the past, even though the time that they were actually in the channel doesn't necessarily overlap with the export period 219 220 // case 1: user joins and leaves the channel before the export period begins 221 channelMembers, err := ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime-500, joinTime-100, channel.Id) 222 require.Nil(t, err) 223 assert.Len(t, channelMembers, 1) 224 assert.Equal(t, channel.Id, channelMembers[0].ChannelId) 225 assert.Equal(t, user.Id, channelMembers[0].UserId) 226 assert.Equal(t, user.Email, channelMembers[0].UserEmail) 227 assert.Equal(t, user.Username, channelMembers[0].Username) 228 assert.Equal(t, joinTime-500, channelMembers[0].JoinTime) 229 assert.Equal(t, joinTime-100, *channelMembers[0].LeaveTime) 230 231 // case 2: user joins the channel after the export period begins, but has not yet left the channel when the export period ends 232 channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime-100, joinTime+500, channel.Id) 233 require.Nil(t, err) 234 assert.Len(t, channelMembers, 1) 235 assert.Equal(t, channel.Id, channelMembers[0].ChannelId) 236 assert.Equal(t, user.Id, channelMembers[0].UserId) 237 assert.Equal(t, user.Email, channelMembers[0].UserEmail) 238 assert.Equal(t, user.Username, channelMembers[0].Username) 239 assert.Equal(t, joinTime-100, channelMembers[0].JoinTime) 240 assert.Equal(t, joinTime+500, *channelMembers[0].LeaveTime) 241 242 // case 3: user joins the channel before the export period begins, but has not yet left the channel when the export period ends 243 channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime+100, joinTime+500, channel.Id) 244 require.Nil(t, err) 245 assert.Len(t, channelMembers, 1) 246 assert.Equal(t, channel.Id, channelMembers[0].ChannelId) 247 assert.Equal(t, user.Id, channelMembers[0].UserId) 248 assert.Equal(t, user.Email, channelMembers[0].UserEmail) 249 assert.Equal(t, user.Username, channelMembers[0].Username) 250 assert.Equal(t, joinTime+100, channelMembers[0].JoinTime) 251 assert.Equal(t, joinTime+500, *channelMembers[0].LeaveTime) 252 253 // case 4: user joins the channel before the export period begins, but has not yet left the channel when the export period ends 254 channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime+100, leaveTime-100, channel.Id) 255 require.Nil(t, err) 256 assert.Len(t, channelMembers, 1) 257 assert.Equal(t, channel.Id, channelMembers[0].ChannelId) 258 assert.Equal(t, user.Id, channelMembers[0].UserId) 259 assert.Equal(t, user.Email, channelMembers[0].UserEmail) 260 assert.Equal(t, user.Username, channelMembers[0].Username) 261 assert.Equal(t, joinTime+100, channelMembers[0].JoinTime) 262 assert.Equal(t, leaveTime-100, *channelMembers[0].LeaveTime) 263 264 // case 5: user joins the channel after the export period begins, and leaves the channel before the export period ends 265 channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime-100, leaveTime+100, channel.Id) 266 require.Nil(t, err) 267 assert.Len(t, channelMembers, 1) 268 assert.Equal(t, channel.Id, channelMembers[0].ChannelId) 269 assert.Equal(t, user.Id, channelMembers[0].UserId) 270 assert.Equal(t, user.Email, channelMembers[0].UserEmail) 271 assert.Equal(t, user.Username, channelMembers[0].Username) 272 assert.Equal(t, joinTime-100, channelMembers[0].JoinTime) 273 assert.Equal(t, leaveTime+100, *channelMembers[0].LeaveTime) 274 275 // case 6: user has joined and left the channel long before the export period begins 276 channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(leaveTime+100, leaveTime+200, channel.Id) 277 require.Nil(t, err) 278 assert.Len(t, channelMembers, 1) 279 assert.Equal(t, channel.Id, channelMembers[0].ChannelId) 280 assert.Equal(t, user.Id, channelMembers[0].UserId) 281 assert.Equal(t, user.Email, channelMembers[0].UserEmail) 282 assert.Equal(t, user.Username, channelMembers[0].Username) 283 assert.Equal(t, leaveTime+100, channelMembers[0].JoinTime) 284 assert.Equal(t, leaveTime+200, *channelMembers[0].LeaveTime) 285 } 286 287 func testPermanentDeleteBatch(t *testing.T, ss store.Store) { 288 // create a test channel 289 channel := &model.Channel{ 290 TeamId: model.NewId(), 291 DisplayName: "Display " + model.NewId(), 292 Name: "zz" + model.NewId() + "b", 293 Type: model.CHANNEL_OPEN, 294 } 295 channel, err := ss.Channel().Save(channel, -1) 296 require.Nil(t, err) 297 298 // and two test users 299 user := model.User{ 300 Email: MakeEmail(), 301 Nickname: model.NewId(), 302 Username: model.NewId(), 303 } 304 userPtr, err := ss.User().Save(&user) 305 require.Nil(t, err) 306 user = *userPtr 307 308 user2 := model.User{ 309 Email: MakeEmail(), 310 Nickname: model.NewId(), 311 Username: model.NewId(), 312 } 313 user2Ptr, err := ss.User().Save(&user2) 314 require.Nil(t, err) 315 user2 = *user2Ptr 316 317 // user1 joins and leaves the channel 318 leaveTime := model.GetMillis() 319 joinTime := leaveTime - 10000 320 err = ss.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, joinTime) 321 require.Nil(t, err) 322 err = ss.ChannelMemberHistory().LogLeaveEvent(user.Id, channel.Id, leaveTime) 323 require.Nil(t, err) 324 325 // user2 joins the channel but never leaves 326 err = ss.ChannelMemberHistory().LogJoinEvent(user2.Id, channel.Id, joinTime) 327 require.Nil(t, err) 328 329 // in between the join time and the leave time, both users were members of the channel 330 channelMembers, err := ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime+10, leaveTime-10, channel.Id) 331 require.Nil(t, err) 332 assert.Len(t, channelMembers, 2) 333 334 // the permanent delete should delete at least one record 335 rowsDeleted, err := ss.ChannelMemberHistory().PermanentDeleteBatch(leaveTime, math.MaxInt64) 336 require.Nil(t, err) 337 assert.NotEqual(t, int64(0), rowsDeleted) 338 339 // after the delete, there should be one less member in the channel 340 channelMembers, err = ss.ChannelMemberHistory().GetUsersInChannelDuring(joinTime+10, leaveTime-10, channel.Id) 341 require.Nil(t, err) 342 assert.Len(t, channelMembers, 1) 343 assert.Equal(t, user2.Id, channelMembers[0].UserId) 344 }