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