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