github.com/mattermost/mattermost-server/v5@v5.39.3/store/storetest/post_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 "context" 8 "fmt" 9 "sort" 10 "strings" 11 "testing" 12 "time" 13 14 "github.com/stretchr/testify/assert" 15 "github.com/stretchr/testify/require" 16 17 "github.com/mattermost/mattermost-server/v5/model" 18 "github.com/mattermost/mattermost-server/v5/store" 19 "github.com/mattermost/mattermost-server/v5/utils" 20 ) 21 22 func TestPostStore(t *testing.T, ss store.Store, s SqlStore) { 23 t.Run("SaveMultiple", func(t *testing.T) { testPostStoreSaveMultiple(t, ss) }) 24 t.Run("Save", func(t *testing.T) { testPostStoreSave(t, ss) }) 25 t.Run("SaveAndUpdateChannelMsgCounts", func(t *testing.T) { testPostStoreSaveChannelMsgCounts(t, ss) }) 26 t.Run("Get", func(t *testing.T) { testPostStoreGet(t, ss) }) 27 t.Run("GetSingle", func(t *testing.T) { testPostStoreGetSingle(t, ss) }) 28 t.Run("Update", func(t *testing.T) { testPostStoreUpdate(t, ss) }) 29 t.Run("Delete", func(t *testing.T) { testPostStoreDelete(t, ss) }) 30 t.Run("Delete1Level", func(t *testing.T) { testPostStoreDelete1Level(t, ss) }) 31 t.Run("Delete2Level", func(t *testing.T) { testPostStoreDelete2Level(t, ss) }) 32 t.Run("PermDelete1Level", func(t *testing.T) { testPostStorePermDelete1Level(t, ss) }) 33 t.Run("PermDelete1Level2", func(t *testing.T) { testPostStorePermDelete1Level2(t, ss) }) 34 t.Run("GetWithChildren", func(t *testing.T) { testPostStoreGetWithChildren(t, ss) }) 35 t.Run("GetPostsWithDetails", func(t *testing.T) { testPostStoreGetPostsWithDetails(t, ss) }) 36 t.Run("GetPostsBeforeAfter", func(t *testing.T) { testPostStoreGetPostsBeforeAfter(t, ss) }) 37 t.Run("GetPostsSince", func(t *testing.T) { testPostStoreGetPostsSince(t, ss) }) 38 t.Run("GetPosts", func(t *testing.T) { testPostStoreGetPosts(t, ss) }) 39 t.Run("GetPostBeforeAfter", func(t *testing.T) { testPostStoreGetPostBeforeAfter(t, ss) }) 40 t.Run("UserCountsWithPostsByDay", func(t *testing.T) { testUserCountsWithPostsByDay(t, ss) }) 41 t.Run("PostCountsByDay", func(t *testing.T) { testPostCountsByDay(t, ss) }) 42 t.Run("GetFlaggedPostsForTeam", func(t *testing.T) { testPostStoreGetFlaggedPostsForTeam(t, ss, s) }) 43 t.Run("GetFlaggedPosts", func(t *testing.T) { testPostStoreGetFlaggedPosts(t, ss) }) 44 t.Run("GetFlaggedPostsForChannel", func(t *testing.T) { testPostStoreGetFlaggedPostsForChannel(t, ss) }) 45 t.Run("GetPostsCreatedAt", func(t *testing.T) { testPostStoreGetPostsCreatedAt(t, ss) }) 46 t.Run("Overwrite", func(t *testing.T) { testPostStoreOverwrite(t, ss) }) 47 t.Run("OverwriteMultiple", func(t *testing.T) { testPostStoreOverwriteMultiple(t, ss) }) 48 t.Run("GetPostsByIds", func(t *testing.T) { testPostStoreGetPostsByIds(t, ss) }) 49 t.Run("GetPostsBatchForIndexing", func(t *testing.T) { testPostStoreGetPostsBatchForIndexing(t, ss) }) 50 t.Run("PermanentDeleteBatch", func(t *testing.T) { testPostStorePermanentDeleteBatch(t, ss) }) 51 t.Run("GetOldest", func(t *testing.T) { testPostStoreGetOldest(t, ss) }) 52 t.Run("TestGetMaxPostSize", func(t *testing.T) { testGetMaxPostSize(t, ss) }) 53 t.Run("GetParentsForExportAfter", func(t *testing.T) { testPostStoreGetParentsForExportAfter(t, ss) }) 54 t.Run("GetRepliesForExport", func(t *testing.T) { testPostStoreGetRepliesForExport(t, ss) }) 55 t.Run("GetDirectPostParentsForExportAfter", func(t *testing.T) { testPostStoreGetDirectPostParentsForExportAfter(t, ss, s) }) 56 t.Run("GetDirectPostParentsForExportAfterDeleted", func(t *testing.T) { testPostStoreGetDirectPostParentsForExportAfterDeleted(t, ss, s) }) 57 t.Run("GetDirectPostParentsForExportAfterBatched", func(t *testing.T) { testPostStoreGetDirectPostParentsForExportAfterBatched(t, ss, s) }) 58 t.Run("GetForThread", func(t *testing.T) { testPostStoreGetForThread(t, ss) }) 59 t.Run("HasAutoResponsePostByUserSince", func(t *testing.T) { testHasAutoResponsePostByUserSince(t, ss) }) 60 t.Run("GetPostsSinceForSync", func(t *testing.T) { testGetPostsSinceForSync(t, ss, s) }) 61 } 62 63 func testPostStoreSave(t *testing.T, ss store.Store) { 64 t.Run("Save post", func(t *testing.T) { 65 o1 := model.Post{} 66 o1.ChannelId = model.NewId() 67 o1.UserId = model.NewId() 68 o1.Message = "zz" + model.NewId() + "b" 69 70 p, err := ss.Post().Save(&o1) 71 require.NoError(t, err, "couldn't save item") 72 assert.Equal(t, int64(0), p.ReplyCount) 73 }) 74 75 t.Run("Save replies", func(t *testing.T) { 76 o1 := model.Post{} 77 o1.ChannelId = model.NewId() 78 o1.UserId = model.NewId() 79 o1.RootId = model.NewId() 80 o1.Message = "zz" + model.NewId() + "b" 81 82 o2 := model.Post{} 83 o2.ChannelId = model.NewId() 84 o2.UserId = model.NewId() 85 o2.RootId = o1.RootId 86 o2.Message = "zz" + model.NewId() + "b" 87 88 o3 := model.Post{} 89 o3.ChannelId = model.NewId() 90 o3.UserId = model.NewId() 91 o3.RootId = model.NewId() 92 o3.Message = "zz" + model.NewId() + "b" 93 94 p1, err := ss.Post().Save(&o1) 95 require.NoError(t, err, "couldn't save item") 96 assert.Equal(t, int64(1), p1.ReplyCount) 97 98 p2, err := ss.Post().Save(&o2) 99 require.NoError(t, err, "couldn't save item") 100 assert.Equal(t, int64(2), p2.ReplyCount) 101 102 p3, err := ss.Post().Save(&o3) 103 require.NoError(t, err, "couldn't save item") 104 assert.Equal(t, int64(1), p3.ReplyCount) 105 }) 106 107 t.Run("Try to save existing post", func(t *testing.T) { 108 o1 := model.Post{} 109 o1.ChannelId = model.NewId() 110 o1.UserId = model.NewId() 111 o1.Message = "zz" + model.NewId() + "b" 112 113 _, err := ss.Post().Save(&o1) 114 require.NoError(t, err, "couldn't save item") 115 116 _, err = ss.Post().Save(&o1) 117 require.Error(t, err, "shouldn't be able to update from save") 118 }) 119 120 t.Run("Update reply should update the UpdateAt of the root post", func(t *testing.T) { 121 rootPost := model.Post{} 122 rootPost.ChannelId = model.NewId() 123 rootPost.UserId = model.NewId() 124 rootPost.Message = "zz" + model.NewId() + "b" 125 126 _, err := ss.Post().Save(&rootPost) 127 require.NoError(t, err) 128 129 time.Sleep(2 * time.Millisecond) 130 131 replyPost := model.Post{} 132 replyPost.ChannelId = rootPost.ChannelId 133 replyPost.UserId = model.NewId() 134 replyPost.Message = "zz" + model.NewId() + "b" 135 replyPost.RootId = rootPost.Id 136 137 // We need to sleep here to be sure the post is not created during the same millisecond 138 time.Sleep(time.Millisecond) 139 _, err = ss.Post().Save(&replyPost) 140 require.NoError(t, err) 141 142 rrootPost, err := ss.Post().GetSingle(rootPost.Id, false) 143 require.NoError(t, err) 144 assert.Greater(t, rrootPost.UpdateAt, rootPost.UpdateAt) 145 }) 146 147 t.Run("Create a post should update the channel LastPostAt and the total messages count by one", func(t *testing.T) { 148 channel := model.Channel{} 149 channel.Name = "zz" + model.NewId() + "b" 150 channel.DisplayName = "zz" + model.NewId() + "b" 151 channel.Type = model.CHANNEL_OPEN 152 153 _, err := ss.Channel().Save(&channel, 100) 154 require.NoError(t, err) 155 156 post := model.Post{} 157 post.ChannelId = channel.Id 158 post.UserId = model.NewId() 159 post.Message = "zz" + model.NewId() + "b" 160 161 // We need to sleep here to be sure the post is not created during the same millisecond 162 time.Sleep(time.Millisecond) 163 _, err = ss.Post().Save(&post) 164 require.NoError(t, err) 165 166 rchannel, err := ss.Channel().Get(channel.Id, false) 167 require.NoError(t, err) 168 assert.Greater(t, rchannel.LastPostAt, channel.LastPostAt) 169 assert.Equal(t, int64(1), rchannel.TotalMsgCount) 170 171 post = model.Post{} 172 post.ChannelId = channel.Id 173 post.UserId = model.NewId() 174 post.Message = "zz" + model.NewId() + "b" 175 post.CreateAt = 5 176 177 // We need to sleep here to be sure the post is not created during the same millisecond 178 time.Sleep(time.Millisecond) 179 _, err = ss.Post().Save(&post) 180 require.NoError(t, err) 181 182 rchannel2, err := ss.Channel().Get(channel.Id, false) 183 require.NoError(t, err) 184 assert.Equal(t, rchannel.LastPostAt, rchannel2.LastPostAt) 185 assert.Equal(t, int64(2), rchannel2.TotalMsgCount) 186 187 post = model.Post{} 188 post.ChannelId = channel.Id 189 post.UserId = model.NewId() 190 post.Message = "zz" + model.NewId() + "b" 191 192 // We need to sleep here to be sure the post is not created during the same millisecond 193 time.Sleep(time.Millisecond) 194 _, err = ss.Post().Save(&post) 195 require.NoError(t, err) 196 197 rchannel3, err := ss.Channel().Get(channel.Id, false) 198 require.NoError(t, err) 199 assert.Greater(t, rchannel3.LastPostAt, rchannel2.LastPostAt) 200 assert.Equal(t, int64(3), rchannel3.TotalMsgCount) 201 }) 202 } 203 204 func testPostStoreSaveMultiple(t *testing.T, ss store.Store) { 205 p1 := model.Post{} 206 p1.ChannelId = model.NewId() 207 p1.UserId = model.NewId() 208 p1.Message = "zz" + model.NewId() + "b" 209 210 p2 := model.Post{} 211 p2.ChannelId = model.NewId() 212 p2.UserId = model.NewId() 213 p2.Message = "zz" + model.NewId() + "b" 214 215 p3 := model.Post{} 216 p3.ChannelId = model.NewId() 217 p3.UserId = model.NewId() 218 p3.Message = "zz" + model.NewId() + "b" 219 220 p4 := model.Post{} 221 p4.ChannelId = model.NewId() 222 p4.UserId = model.NewId() 223 p4.Message = "zz" + model.NewId() + "b" 224 225 t.Run("Save correctly a new set of posts", func(t *testing.T) { 226 newPosts, errIdx, err := ss.Post().SaveMultiple([]*model.Post{&p1, &p2, &p3}) 227 require.NoError(t, err) 228 require.Equal(t, -1, errIdx) 229 for _, post := range newPosts { 230 storedPost, err := ss.Post().GetSingle(post.Id, false) 231 assert.NoError(t, err) 232 assert.Equal(t, post.ChannelId, storedPost.ChannelId) 233 assert.Equal(t, post.Message, storedPost.Message) 234 assert.Equal(t, post.UserId, storedPost.UserId) 235 } 236 }) 237 238 t.Run("Save replies", func(t *testing.T) { 239 o1 := model.Post{} 240 o1.ChannelId = model.NewId() 241 o1.UserId = model.NewId() 242 o1.RootId = model.NewId() 243 o1.Message = "zz" + model.NewId() + "b" 244 245 o2 := model.Post{} 246 o2.ChannelId = model.NewId() 247 o2.UserId = model.NewId() 248 o2.RootId = o1.RootId 249 o2.Message = "zz" + model.NewId() + "b" 250 251 o3 := model.Post{} 252 o3.ChannelId = model.NewId() 253 o3.UserId = model.NewId() 254 o3.RootId = model.NewId() 255 o3.Message = "zz" + model.NewId() + "b" 256 257 o4 := model.Post{} 258 o4.ChannelId = model.NewId() 259 o4.UserId = model.NewId() 260 o4.Message = "zz" + model.NewId() + "b" 261 262 newPosts, errIdx, err := ss.Post().SaveMultiple([]*model.Post{&o1, &o2, &o3, &o4}) 263 require.NoError(t, err, "couldn't save item") 264 require.Equal(t, -1, errIdx) 265 assert.Len(t, newPosts, 4) 266 assert.Equal(t, int64(2), newPosts[0].ReplyCount) 267 assert.Equal(t, int64(2), newPosts[1].ReplyCount) 268 assert.Equal(t, int64(1), newPosts[2].ReplyCount) 269 assert.Equal(t, int64(0), newPosts[3].ReplyCount) 270 }) 271 272 t.Run("Try to save mixed, already saved and not saved posts", func(t *testing.T) { 273 newPosts, errIdx, err := ss.Post().SaveMultiple([]*model.Post{&p4, &p3}) 274 require.Error(t, err) 275 require.Equal(t, 1, errIdx) 276 require.Nil(t, newPosts) 277 storedPost, err := ss.Post().GetSingle(p3.Id, false) 278 assert.NoError(t, err) 279 assert.Equal(t, p3.ChannelId, storedPost.ChannelId) 280 assert.Equal(t, p3.Message, storedPost.Message) 281 assert.Equal(t, p3.UserId, storedPost.UserId) 282 283 storedPost, err = ss.Post().GetSingle(p4.Id, false) 284 assert.Error(t, err) 285 assert.Nil(t, storedPost) 286 }) 287 288 t.Run("Update reply should update the UpdateAt of the root post", func(t *testing.T) { 289 rootPost := model.Post{} 290 rootPost.ChannelId = model.NewId() 291 rootPost.UserId = model.NewId() 292 rootPost.Message = "zz" + model.NewId() + "b" 293 294 replyPost := model.Post{} 295 replyPost.ChannelId = rootPost.ChannelId 296 replyPost.UserId = model.NewId() 297 replyPost.Message = "zz" + model.NewId() + "b" 298 replyPost.RootId = rootPost.Id 299 300 _, _, err := ss.Post().SaveMultiple([]*model.Post{&rootPost, &replyPost}) 301 require.NoError(t, err) 302 303 rrootPost, err := ss.Post().GetSingle(rootPost.Id, false) 304 require.NoError(t, err) 305 assert.Equal(t, rrootPost.UpdateAt, rootPost.UpdateAt) 306 307 replyPost2 := model.Post{} 308 replyPost2.ChannelId = rootPost.ChannelId 309 replyPost2.UserId = model.NewId() 310 replyPost2.Message = "zz" + model.NewId() + "b" 311 replyPost2.RootId = rootPost.Id 312 313 replyPost3 := model.Post{} 314 replyPost3.ChannelId = rootPost.ChannelId 315 replyPost3.UserId = model.NewId() 316 replyPost3.Message = "zz" + model.NewId() + "b" 317 replyPost3.RootId = rootPost.Id 318 319 _, _, err = ss.Post().SaveMultiple([]*model.Post{&replyPost2, &replyPost3}) 320 require.NoError(t, err) 321 322 rrootPost2, err := ss.Post().GetSingle(rootPost.Id, false) 323 require.NoError(t, err) 324 assert.Greater(t, rrootPost2.UpdateAt, rrootPost.UpdateAt) 325 }) 326 327 t.Run("Create a post should update the channel LastPostAt and the total messages count by one", func(t *testing.T) { 328 channel := model.Channel{} 329 channel.Name = "zz" + model.NewId() + "b" 330 channel.DisplayName = "zz" + model.NewId() + "b" 331 channel.Type = model.CHANNEL_OPEN 332 333 _, err := ss.Channel().Save(&channel, 100) 334 require.NoError(t, err) 335 336 post1 := model.Post{} 337 post1.ChannelId = channel.Id 338 post1.UserId = model.NewId() 339 post1.Message = "zz" + model.NewId() + "b" 340 341 post2 := model.Post{} 342 post2.ChannelId = channel.Id 343 post2.UserId = model.NewId() 344 post2.Message = "zz" + model.NewId() + "b" 345 post2.CreateAt = 5 346 347 post3 := model.Post{} 348 post3.ChannelId = channel.Id 349 post3.UserId = model.NewId() 350 post3.Message = "zz" + model.NewId() + "b" 351 352 _, _, err = ss.Post().SaveMultiple([]*model.Post{&post1, &post2, &post3}) 353 require.NoError(t, err) 354 355 rchannel, err := ss.Channel().Get(channel.Id, false) 356 require.NoError(t, err) 357 assert.Greater(t, rchannel.LastPostAt, channel.LastPostAt) 358 assert.Equal(t, int64(3), rchannel.TotalMsgCount) 359 }) 360 } 361 362 func testPostStoreSaveChannelMsgCounts(t *testing.T, ss store.Store) { 363 c1 := &model.Channel{Name: model.NewId(), DisplayName: "posttestchannel", Type: model.CHANNEL_OPEN} 364 _, err := ss.Channel().Save(c1, 1000000) 365 require.NoError(t, err) 366 367 o1 := model.Post{} 368 o1.ChannelId = c1.Id 369 o1.UserId = model.NewId() 370 o1.Message = "zz" + model.NewId() + "b" 371 372 _, err = ss.Post().Save(&o1) 373 require.NoError(t, err) 374 375 c1, err = ss.Channel().Get(c1.Id, false) 376 require.NoError(t, err) 377 assert.Equal(t, int64(1), c1.TotalMsgCount, "Message count should update by 1") 378 379 o1.Id = "" 380 o1.Type = model.POST_ADD_TO_TEAM 381 _, err = ss.Post().Save(&o1) 382 require.NoError(t, err) 383 384 o1.Id = "" 385 o1.Type = model.POST_REMOVE_FROM_TEAM 386 _, err = ss.Post().Save(&o1) 387 require.NoError(t, err) 388 389 c1, err = ss.Channel().Get(c1.Id, false) 390 require.NoError(t, err) 391 assert.Equal(t, int64(1), c1.TotalMsgCount, "Message count should not update for team add/removed message") 392 393 oldLastPostAt := c1.LastPostAt 394 395 o2 := model.Post{} 396 o2.ChannelId = c1.Id 397 o2.UserId = model.NewId() 398 o2.Message = "zz" + model.NewId() + "b" 399 o2.CreateAt = int64(7) 400 _, err = ss.Post().Save(&o2) 401 require.NoError(t, err) 402 403 c1, err = ss.Channel().Get(c1.Id, false) 404 require.NoError(t, err) 405 assert.Equal(t, oldLastPostAt, c1.LastPostAt, "LastPostAt should not update for old message save") 406 } 407 408 func testPostStoreGet(t *testing.T, ss store.Store) { 409 o1 := &model.Post{} 410 o1.ChannelId = model.NewId() 411 o1.UserId = model.NewId() 412 o1.Message = "zz" + model.NewId() + "b" 413 414 etag1 := ss.Post().GetEtag(o1.ChannelId, false, false) 415 require.Equal(t, 0, strings.Index(etag1, model.CurrentVersion+"."), "Invalid Etag") 416 417 o1, err := ss.Post().Save(o1) 418 require.NoError(t, err) 419 420 etag2 := ss.Post().GetEtag(o1.ChannelId, false, false) 421 require.Equal(t, 0, strings.Index(etag2, fmt.Sprintf("%v.%v", model.CurrentVersion, o1.UpdateAt)), "Invalid Etag") 422 423 r1, err := ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 424 require.NoError(t, err) 425 require.Equal(t, r1.Posts[o1.Id].CreateAt, o1.CreateAt, "invalid returned post") 426 427 _, err = ss.Post().Get(context.Background(), "123", false, false, false, "") 428 require.Error(t, err, "Missing id should have failed") 429 430 _, err = ss.Post().Get(context.Background(), "", false, false, false, "") 431 require.Error(t, err, "should fail for blank post ids") 432 } 433 434 func testPostStoreGetForThread(t *testing.T, ss store.Store) { 435 o1 := &model.Post{ChannelId: model.NewId(), UserId: model.NewId(), Message: "zz" + model.NewId() + "b"} 436 o1, err := ss.Post().Save(o1) 437 require.NoError(t, err) 438 _, err = ss.Post().Save(&model.Post{ChannelId: o1.ChannelId, UserId: model.NewId(), Message: "zz" + model.NewId() + "b", RootId: o1.Id}) 439 require.NoError(t, err) 440 441 threadMembership := &model.ThreadMembership{ 442 PostId: o1.Id, 443 UserId: o1.UserId, 444 Following: true, 445 LastViewed: 0, 446 LastUpdated: 0, 447 UnreadMentions: 0, 448 } 449 _, err = ss.Thread().SaveMembership(threadMembership) 450 require.NoError(t, err) 451 r1, err := ss.Post().Get(context.Background(), o1.Id, false, true, false, o1.UserId) 452 require.NoError(t, err) 453 require.Equal(t, r1.Posts[o1.Id].CreateAt, o1.CreateAt, "invalid returned post") 454 require.True(t, *r1.Posts[o1.Id].IsFollowing) 455 } 456 457 func testPostStoreGetSingle(t *testing.T, ss store.Store) { 458 o1 := &model.Post{} 459 o1.ChannelId = model.NewId() 460 o1.UserId = model.NewId() 461 o1.Message = "zz" + model.NewId() + "b" 462 463 o2 := &model.Post{} 464 o2.ChannelId = o1.ChannelId 465 o2.UserId = o1.UserId 466 o2.Message = "zz" + model.NewId() + "c" 467 468 o1, err := ss.Post().Save(o1) 469 require.NoError(t, err) 470 471 o2, err = ss.Post().Save(o2) 472 require.NoError(t, err) 473 474 o3 := &model.Post{} 475 o3.ChannelId = o1.ChannelId 476 o3.UserId = o1.UserId 477 o3.Message = model.NewRandomString(10) 478 o3.RootId = o1.Id 479 480 o4 := &model.Post{} 481 o4.ChannelId = o1.ChannelId 482 o4.UserId = o1.UserId 483 o4.Message = model.NewRandomString(10) 484 o4.RootId = o1.Id 485 486 o3, err = ss.Post().Save(o3) 487 require.NoError(t, err) 488 489 o4, err = ss.Post().Save(o4) 490 require.NoError(t, err) 491 492 err = ss.Post().Delete(o2.Id, model.GetMillis(), o2.UserId) 493 require.NoError(t, err) 494 495 err = ss.Post().Delete(o4.Id, model.GetMillis(), o4.UserId) 496 require.NoError(t, err) 497 498 post, err := ss.Post().GetSingle(o1.Id, false) 499 require.NoError(t, err) 500 require.Equal(t, post.CreateAt, o1.CreateAt, "invalid returned post") 501 require.Equal(t, int64(1), post.ReplyCount, "wrong replyCount computed") 502 503 post, err = ss.Post().GetSingle(o2.Id, false) 504 require.Error(t, err, "should not return deleted post") 505 506 post, err = ss.Post().GetSingle(o2.Id, true) 507 require.NoError(t, err) 508 require.Equal(t, post.CreateAt, o2.CreateAt, "invalid returned post") 509 require.NotZero(t, post.DeleteAt, "DeleteAt should be non-zero") 510 require.Zero(t, post.ReplyCount, "Post without replies should return zero ReplyCount") 511 512 _, err = ss.Post().GetSingle("123", false) 513 require.Error(t, err, "Missing id should have failed") 514 } 515 516 func testPostStoreUpdate(t *testing.T, ss store.Store) { 517 o1 := &model.Post{} 518 o1.ChannelId = model.NewId() 519 o1.UserId = model.NewId() 520 o1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" 521 o1, err := ss.Post().Save(o1) 522 require.NoError(t, err) 523 524 o2 := &model.Post{} 525 o2.ChannelId = o1.ChannelId 526 o2.UserId = model.NewId() 527 o2.Message = "zz" + model.NewId() + "CCCCCCCCC" 528 o2.ParentId = o1.Id 529 o2.RootId = o1.Id 530 o2, err = ss.Post().Save(o2) 531 require.NoError(t, err) 532 533 o3 := &model.Post{} 534 o3.ChannelId = o1.ChannelId 535 o3.UserId = model.NewId() 536 o3.Message = "zz" + model.NewId() + "QQQQQQQQQQ" 537 o3, err = ss.Post().Save(o3) 538 require.NoError(t, err) 539 540 r1, err := ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 541 require.NoError(t, err) 542 ro1 := r1.Posts[o1.Id] 543 544 r2, err := ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 545 require.NoError(t, err) 546 ro2 := r2.Posts[o2.Id] 547 548 r3, err := ss.Post().Get(context.Background(), o3.Id, false, false, false, "") 549 require.NoError(t, err) 550 ro3 := r3.Posts[o3.Id] 551 552 require.Equal(t, ro1.Message, o1.Message, "Failed to save/get") 553 554 o1a := ro1.Clone() 555 o1a.Message = ro1.Message + "BBBBBBBBBB" 556 _, err = ss.Post().Update(o1a, ro1) 557 require.NoError(t, err) 558 559 r1, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 560 require.NoError(t, err) 561 562 ro1a := r1.Posts[o1.Id] 563 require.Equal(t, ro1a.Message, o1a.Message, "Failed to update/get") 564 565 o2a := ro2.Clone() 566 o2a.Message = ro2.Message + "DDDDDDD" 567 _, err = ss.Post().Update(o2a, ro2) 568 require.NoError(t, err) 569 570 r2, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 571 require.NoError(t, err) 572 ro2a := r2.Posts[o2.Id] 573 574 require.Equal(t, ro2a.Message, o2a.Message, "Failed to update/get") 575 576 o3a := ro3.Clone() 577 o3a.Message = ro3.Message + "WWWWWWW" 578 _, err = ss.Post().Update(o3a, ro3) 579 require.NoError(t, err) 580 581 r3, err = ss.Post().Get(context.Background(), o3.Id, false, false, false, "") 582 require.NoError(t, err) 583 ro3a := r3.Posts[o3.Id] 584 585 if ro3a.Message != o3a.Message { 586 require.Equal(t, ro3a.Hashtags, o3a.Hashtags, "Failed to update/get") 587 } 588 589 o4, err := ss.Post().Save(&model.Post{ 590 ChannelId: model.NewId(), 591 UserId: model.NewId(), 592 Message: model.NewId(), 593 Filenames: []string{"test"}, 594 }) 595 require.NoError(t, err) 596 597 r4, err := ss.Post().Get(context.Background(), o4.Id, false, false, false, "") 598 require.NoError(t, err) 599 ro4 := r4.Posts[o4.Id] 600 601 o4a := ro4.Clone() 602 o4a.Filenames = []string{} 603 o4a.FileIds = []string{model.NewId()} 604 _, err = ss.Post().Update(o4a, ro4) 605 require.NoError(t, err) 606 607 r4, err = ss.Post().Get(context.Background(), o4.Id, false, false, false, "") 608 require.NoError(t, err) 609 610 ro4a := r4.Posts[o4.Id] 611 require.Empty(t, ro4a.Filenames, "Failed to clear Filenames") 612 require.Len(t, ro4a.FileIds, 1, "Failed to set FileIds") 613 } 614 615 func testPostStoreDelete(t *testing.T, ss store.Store) { 616 o1 := &model.Post{} 617 o1.ChannelId = model.NewId() 618 o1.UserId = model.NewId() 619 o1.Message = "zz" + model.NewId() + "b" 620 deleteByID := model.NewId() 621 622 etag1 := ss.Post().GetEtag(o1.ChannelId, false, false) 623 require.Equal(t, 0, strings.Index(etag1, model.CurrentVersion+"."), "Invalid Etag") 624 625 o1, err := ss.Post().Save(o1) 626 require.NoError(t, err) 627 628 r1, err := ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 629 require.NoError(t, err) 630 require.Equal(t, r1.Posts[o1.Id].CreateAt, o1.CreateAt, "invalid returned post") 631 632 err = ss.Post().Delete(o1.Id, model.GetMillis(), deleteByID) 633 require.NoError(t, err) 634 635 posts, _ := ss.Post().GetPostsCreatedAt(o1.ChannelId, o1.CreateAt) 636 post := posts[0] 637 actual := post.GetProp(model.POST_PROPS_DELETE_BY) 638 639 assert.Equal(t, deleteByID, actual, "Expected (*Post).Props[model.POST_PROPS_DELETE_BY] to be %v but got %v.", deleteByID, actual) 640 641 r3, err := ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 642 require.Error(t, err, "Missing id should have failed - PostList %v", r3) 643 644 etag2 := ss.Post().GetEtag(o1.ChannelId, false, false) 645 require.Equal(t, 0, strings.Index(etag2, model.CurrentVersion+"."), "Invalid Etag") 646 } 647 648 func testPostStoreDelete1Level(t *testing.T, ss store.Store) { 649 o1 := &model.Post{} 650 o1.ChannelId = model.NewId() 651 o1.UserId = model.NewId() 652 o1.Message = "zz" + model.NewId() + "b" 653 o1, err := ss.Post().Save(o1) 654 require.NoError(t, err) 655 656 o2 := &model.Post{} 657 o2.ChannelId = o1.ChannelId 658 o2.UserId = model.NewId() 659 o2.Message = "zz" + model.NewId() + "b" 660 o2.ParentId = o1.Id 661 o2.RootId = o1.Id 662 o2, err = ss.Post().Save(o2) 663 require.NoError(t, err) 664 665 err = ss.Post().Delete(o1.Id, model.GetMillis(), "") 666 require.NoError(t, err) 667 668 _, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 669 require.Error(t, err, "Deleted id should have failed") 670 671 _, err = ss.Post().Get(context.Background(), o2.Id, false, false, false, "") 672 require.Error(t, err, "Deleted id should have failed") 673 } 674 675 func testPostStoreDelete2Level(t *testing.T, ss store.Store) { 676 o1 := &model.Post{} 677 o1.ChannelId = model.NewId() 678 o1.UserId = model.NewId() 679 o1.Message = "zz" + model.NewId() + "b" 680 o1, err := ss.Post().Save(o1) 681 require.NoError(t, err) 682 683 o2 := &model.Post{} 684 o2.ChannelId = o1.ChannelId 685 o2.UserId = model.NewId() 686 o2.Message = "zz" + model.NewId() + "b" 687 o2.ParentId = o1.Id 688 o2.RootId = o1.Id 689 o2, err = ss.Post().Save(o2) 690 require.NoError(t, err) 691 692 o3 := &model.Post{} 693 o3.ChannelId = o1.ChannelId 694 o3.UserId = model.NewId() 695 o3.Message = "zz" + model.NewId() + "b" 696 o3.ParentId = o2.Id 697 o3.RootId = o1.Id 698 o3, err = ss.Post().Save(o3) 699 require.NoError(t, err) 700 701 o4 := &model.Post{} 702 o4.ChannelId = model.NewId() 703 o4.UserId = model.NewId() 704 o4.Message = "zz" + model.NewId() + "b" 705 o4, err = ss.Post().Save(o4) 706 require.NoError(t, err) 707 708 err = ss.Post().Delete(o1.Id, model.GetMillis(), "") 709 require.NoError(t, err) 710 711 _, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 712 require.Error(t, err, "Deleted id should have failed") 713 714 _, err = ss.Post().Get(context.Background(), o2.Id, false, false, false, "") 715 require.Error(t, err, "Deleted id should have failed") 716 717 _, err = ss.Post().Get(context.Background(), o3.Id, false, false, false, "") 718 require.Error(t, err, "Deleted id should have failed") 719 720 _, err = ss.Post().Get(context.Background(), o4.Id, false, false, false, "") 721 require.NoError(t, err) 722 } 723 724 func testPostStorePermDelete1Level(t *testing.T, ss store.Store) { 725 o1 := &model.Post{} 726 o1.ChannelId = model.NewId() 727 o1.UserId = model.NewId() 728 o1.Message = "zz" + model.NewId() + "b" 729 o1, err := ss.Post().Save(o1) 730 require.NoError(t, err) 731 732 o2 := &model.Post{} 733 o2.ChannelId = o1.ChannelId 734 o2.UserId = model.NewId() 735 o2.Message = "zz" + model.NewId() + "b" 736 o2.ParentId = o1.Id 737 o2.RootId = o1.Id 738 o2, err = ss.Post().Save(o2) 739 require.NoError(t, err) 740 741 o3 := &model.Post{} 742 o3.ChannelId = model.NewId() 743 o3.UserId = model.NewId() 744 o3.Message = "zz" + model.NewId() + "b" 745 o3, err = ss.Post().Save(o3) 746 require.NoError(t, err) 747 748 err2 := ss.Post().PermanentDeleteByUser(o2.UserId) 749 require.NoError(t, err2) 750 751 _, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 752 require.NoError(t, err, "Deleted id shouldn't have failed") 753 754 _, err = ss.Post().Get(context.Background(), o2.Id, false, false, false, "") 755 require.Error(t, err, "Deleted id should have failed") 756 757 err = ss.Post().PermanentDeleteByChannel(o3.ChannelId) 758 require.NoError(t, err) 759 760 _, err = ss.Post().Get(context.Background(), o3.Id, false, false, false, "") 761 require.Error(t, err, "Deleted id should have failed") 762 } 763 764 func testPostStorePermDelete1Level2(t *testing.T, ss store.Store) { 765 o1 := &model.Post{} 766 o1.ChannelId = model.NewId() 767 o1.UserId = model.NewId() 768 o1.Message = "zz" + model.NewId() + "b" 769 o1, err := ss.Post().Save(o1) 770 require.NoError(t, err) 771 772 o2 := &model.Post{} 773 o2.ChannelId = o1.ChannelId 774 o2.UserId = model.NewId() 775 o2.Message = "zz" + model.NewId() + "b" 776 o2.ParentId = o1.Id 777 o2.RootId = o1.Id 778 o2, err = ss.Post().Save(o2) 779 require.NoError(t, err) 780 781 o3 := &model.Post{} 782 o3.ChannelId = model.NewId() 783 o3.UserId = model.NewId() 784 o3.Message = "zz" + model.NewId() + "b" 785 o3, err = ss.Post().Save(o3) 786 require.NoError(t, err) 787 788 err2 := ss.Post().PermanentDeleteByUser(o1.UserId) 789 require.NoError(t, err2) 790 791 _, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 792 require.Error(t, err, "Deleted id should have failed") 793 794 _, err = ss.Post().Get(context.Background(), o2.Id, false, false, false, "") 795 require.Error(t, err, "Deleted id should have failed") 796 797 _, err = ss.Post().Get(context.Background(), o3.Id, false, false, false, "") 798 require.NoError(t, err, "Deleted id should have failed") 799 } 800 801 func testPostStoreGetWithChildren(t *testing.T, ss store.Store) { 802 o1 := &model.Post{} 803 o1.ChannelId = model.NewId() 804 o1.UserId = model.NewId() 805 o1.Message = "zz" + model.NewId() + "b" 806 o1, err := ss.Post().Save(o1) 807 require.NoError(t, err) 808 809 o2 := &model.Post{} 810 o2.ChannelId = o1.ChannelId 811 o2.UserId = model.NewId() 812 o2.Message = "zz" + model.NewId() + "b" 813 o2.ParentId = o1.Id 814 o2.RootId = o1.Id 815 o2, err = ss.Post().Save(o2) 816 require.NoError(t, err) 817 818 o3 := &model.Post{} 819 o3.ChannelId = o1.ChannelId 820 o3.UserId = model.NewId() 821 o3.Message = "zz" + model.NewId() + "b" 822 o3.ParentId = o2.Id 823 o3.RootId = o1.Id 824 o3, err = ss.Post().Save(o3) 825 require.NoError(t, err) 826 827 pl, err := ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 828 require.NoError(t, err) 829 830 require.Len(t, pl.Posts, 3, "invalid returned post") 831 832 dErr := ss.Post().Delete(o3.Id, model.GetMillis(), "") 833 require.NoError(t, dErr) 834 835 pl, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 836 require.NoError(t, err) 837 838 require.Len(t, pl.Posts, 2, "invalid returned post") 839 840 dErr = ss.Post().Delete(o2.Id, model.GetMillis(), "") 841 require.NoError(t, dErr) 842 843 pl, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 844 require.NoError(t, err) 845 846 require.Len(t, pl.Posts, 1, "invalid returned post") 847 } 848 849 func testPostStoreGetPostsWithDetails(t *testing.T, ss store.Store) { 850 o1 := &model.Post{} 851 o1.ChannelId = model.NewId() 852 o1.UserId = model.NewId() 853 o1.Message = "zz" + model.NewId() + "b" 854 o1, err := ss.Post().Save(o1) 855 require.NoError(t, err) 856 time.Sleep(2 * time.Millisecond) 857 858 o2 := &model.Post{} 859 o2.ChannelId = o1.ChannelId 860 o2.UserId = model.NewId() 861 o2.Message = "zz" + model.NewId() + "b" 862 o2.ParentId = o1.Id 863 o2.RootId = o1.Id 864 _, err = ss.Post().Save(o2) 865 require.NoError(t, err) 866 time.Sleep(2 * time.Millisecond) 867 868 o2a := &model.Post{} 869 o2a.ChannelId = o1.ChannelId 870 o2a.UserId = model.NewId() 871 o2a.Message = "zz" + model.NewId() + "b" 872 o2a.ParentId = o1.Id 873 o2a.RootId = o1.Id 874 o2a, err = ss.Post().Save(o2a) 875 require.NoError(t, err) 876 time.Sleep(2 * time.Millisecond) 877 878 o3 := &model.Post{} 879 o3.ChannelId = o1.ChannelId 880 o3.UserId = model.NewId() 881 o3.Message = "zz" + model.NewId() + "b" 882 o3.ParentId = o1.Id 883 o3.RootId = o1.Id 884 o3, err = ss.Post().Save(o3) 885 require.NoError(t, err) 886 time.Sleep(2 * time.Millisecond) 887 888 o4 := &model.Post{} 889 o4.ChannelId = o1.ChannelId 890 o4.UserId = model.NewId() 891 o4.Message = "zz" + model.NewId() + "b" 892 o4, err = ss.Post().Save(o4) 893 require.NoError(t, err) 894 time.Sleep(2 * time.Millisecond) 895 896 o5 := &model.Post{} 897 o5.ChannelId = o1.ChannelId 898 o5.UserId = model.NewId() 899 o5.Message = "zz" + model.NewId() + "b" 900 o5.ParentId = o4.Id 901 o5.RootId = o4.Id 902 o5, err = ss.Post().Save(o5) 903 require.NoError(t, err) 904 905 r1, err := ss.Post().GetPosts(model.GetPostsOptions{ChannelId: o1.ChannelId, Page: 0, PerPage: 4}, false) 906 require.NoError(t, err) 907 908 require.Equal(t, r1.Order[0], o5.Id, "invalid order") 909 require.Equal(t, r1.Order[1], o4.Id, "invalid order") 910 require.Equal(t, r1.Order[2], o3.Id, "invalid order") 911 require.Equal(t, r1.Order[3], o2a.Id, "invalid order") 912 913 //the last 4, + o1 (o2a and o3's parent) + o2 (in same thread as o2a and o3) 914 require.Len(t, r1.Posts, 6, "wrong size") 915 916 require.Equal(t, r1.Posts[o1.Id].Message, o1.Message, "Missing parent") 917 918 r2, err := ss.Post().GetPosts(model.GetPostsOptions{ChannelId: o1.ChannelId, Page: 0, PerPage: 4}, false) 919 require.NoError(t, err) 920 921 require.Equal(t, r2.Order[0], o5.Id, "invalid order") 922 require.Equal(t, r2.Order[1], o4.Id, "invalid order") 923 require.Equal(t, r2.Order[2], o3.Id, "invalid order") 924 require.Equal(t, r2.Order[3], o2a.Id, "invalid order") 925 926 //the last 4, + o1 (o2a and o3's parent) + o2 (in same thread as o2a and o3) 927 require.Len(t, r2.Posts, 6, "wrong size") 928 929 require.Equal(t, r2.Posts[o1.Id].Message, o1.Message, "Missing parent") 930 931 // Run once to fill cache 932 _, err = ss.Post().GetPosts(model.GetPostsOptions{ChannelId: o1.ChannelId, Page: 0, PerPage: 30}, false) 933 require.NoError(t, err) 934 935 o6 := &model.Post{} 936 o6.ChannelId = o1.ChannelId 937 o6.UserId = model.NewId() 938 o6.Message = "zz" + model.NewId() + "b" 939 _, err = ss.Post().Save(o6) 940 require.NoError(t, err) 941 942 r3, err := ss.Post().GetPosts(model.GetPostsOptions{ChannelId: o1.ChannelId, Page: 0, PerPage: 30}, false) 943 require.NoError(t, err) 944 assert.Equal(t, 7, len(r3.Order)) 945 } 946 947 func testPostStoreGetPostsBeforeAfter(t *testing.T, ss store.Store) { 948 t.Run("without threads", func(t *testing.T) { 949 channelId := model.NewId() 950 userId := model.NewId() 951 952 var posts []*model.Post 953 for i := 0; i < 10; i++ { 954 post, err := ss.Post().Save(&model.Post{ 955 ChannelId: channelId, 956 UserId: userId, 957 Message: "message", 958 }) 959 require.NoError(t, err) 960 961 posts = append(posts, post) 962 963 time.Sleep(time.Millisecond) 964 } 965 966 t.Run("should return error if negative Page/PerPage options are passed", func(t *testing.T) { 967 postList, err := ss.Post().GetPostsAfter(model.GetPostsOptions{ChannelId: channelId, PostId: posts[0].Id, Page: 0, PerPage: -1}) 968 assert.Nil(t, postList) 969 assert.Error(t, err) 970 assert.IsType(t, &store.ErrInvalidInput{}, err) 971 972 postList, err = ss.Post().GetPostsAfter(model.GetPostsOptions{ChannelId: channelId, PostId: posts[0].Id, Page: -1, PerPage: 10}) 973 assert.Nil(t, postList) 974 assert.Error(t, err) 975 assert.IsType(t, &store.ErrInvalidInput{}, err) 976 }) 977 978 t.Run("should not return anything before the first post", func(t *testing.T) { 979 postList, err := ss.Post().GetPostsBefore(model.GetPostsOptions{ChannelId: channelId, PostId: posts[0].Id, Page: 0, PerPage: 10}) 980 assert.NoError(t, err) 981 982 assert.Equal(t, []string{}, postList.Order) 983 assert.Equal(t, map[string]*model.Post{}, postList.Posts) 984 }) 985 986 t.Run("should return posts before a post", func(t *testing.T) { 987 postList, err := ss.Post().GetPostsBefore(model.GetPostsOptions{ChannelId: channelId, PostId: posts[5].Id, Page: 0, PerPage: 10}) 988 assert.NoError(t, err) 989 990 assert.Equal(t, []string{posts[4].Id, posts[3].Id, posts[2].Id, posts[1].Id, posts[0].Id}, postList.Order) 991 assert.Equal(t, map[string]*model.Post{ 992 posts[0].Id: posts[0], 993 posts[1].Id: posts[1], 994 posts[2].Id: posts[2], 995 posts[3].Id: posts[3], 996 posts[4].Id: posts[4], 997 }, postList.Posts) 998 }) 999 1000 t.Run("should limit posts before", func(t *testing.T) { 1001 postList, err := ss.Post().GetPostsBefore(model.GetPostsOptions{ChannelId: channelId, PostId: posts[5].Id, PerPage: 2}) 1002 assert.NoError(t, err) 1003 1004 assert.Equal(t, []string{posts[4].Id, posts[3].Id}, postList.Order) 1005 assert.Equal(t, map[string]*model.Post{ 1006 posts[3].Id: posts[3], 1007 posts[4].Id: posts[4], 1008 }, postList.Posts) 1009 }) 1010 1011 t.Run("should not return anything after the last post", func(t *testing.T) { 1012 postList, err := ss.Post().GetPostsAfter(model.GetPostsOptions{ChannelId: channelId, PostId: posts[len(posts)-1].Id, PerPage: 10}) 1013 assert.NoError(t, err) 1014 1015 assert.Equal(t, []string{}, postList.Order) 1016 assert.Equal(t, map[string]*model.Post{}, postList.Posts) 1017 }) 1018 1019 t.Run("should return posts after a post", func(t *testing.T) { 1020 postList, err := ss.Post().GetPostsAfter(model.GetPostsOptions{ChannelId: channelId, PostId: posts[5].Id, PerPage: 10}) 1021 assert.NoError(t, err) 1022 1023 assert.Equal(t, []string{posts[9].Id, posts[8].Id, posts[7].Id, posts[6].Id}, postList.Order) 1024 assert.Equal(t, map[string]*model.Post{ 1025 posts[6].Id: posts[6], 1026 posts[7].Id: posts[7], 1027 posts[8].Id: posts[8], 1028 posts[9].Id: posts[9], 1029 }, postList.Posts) 1030 }) 1031 1032 t.Run("should limit posts after", func(t *testing.T) { 1033 postList, err := ss.Post().GetPostsAfter(model.GetPostsOptions{ChannelId: channelId, PostId: posts[5].Id, PerPage: 2}) 1034 assert.NoError(t, err) 1035 1036 assert.Equal(t, []string{posts[7].Id, posts[6].Id}, postList.Order) 1037 assert.Equal(t, map[string]*model.Post{ 1038 posts[6].Id: posts[6], 1039 posts[7].Id: posts[7], 1040 }, postList.Posts) 1041 }) 1042 }) 1043 t.Run("with threads", func(t *testing.T) { 1044 channelId := model.NewId() 1045 userId := model.NewId() 1046 1047 // This creates a series of posts that looks like: 1048 // post1 1049 // post2 1050 // post3 (in response to post1) 1051 // post4 (in response to post2) 1052 // post5 1053 // post6 (in response to post2) 1054 1055 post1, err := ss.Post().Save(&model.Post{ 1056 ChannelId: channelId, 1057 UserId: userId, 1058 Message: "message", 1059 }) 1060 post1.ReplyCount = 1 1061 require.NoError(t, err) 1062 time.Sleep(time.Millisecond) 1063 1064 post2, err := ss.Post().Save(&model.Post{ 1065 ChannelId: channelId, 1066 UserId: userId, 1067 Message: "message", 1068 }) 1069 require.NoError(t, err) 1070 post2.ReplyCount = 2 1071 time.Sleep(time.Millisecond) 1072 1073 post3, err := ss.Post().Save(&model.Post{ 1074 ChannelId: channelId, 1075 UserId: userId, 1076 ParentId: post1.Id, 1077 RootId: post1.Id, 1078 Message: "message", 1079 }) 1080 require.NoError(t, err) 1081 post3.ReplyCount = 1 1082 time.Sleep(time.Millisecond) 1083 1084 post4, err := ss.Post().Save(&model.Post{ 1085 ChannelId: channelId, 1086 UserId: userId, 1087 RootId: post2.Id, 1088 ParentId: post2.Id, 1089 Message: "message", 1090 }) 1091 require.NoError(t, err) 1092 post4.ReplyCount = 2 1093 time.Sleep(time.Millisecond) 1094 1095 post5, err := ss.Post().Save(&model.Post{ 1096 ChannelId: channelId, 1097 UserId: userId, 1098 Message: "message", 1099 }) 1100 require.NoError(t, err) 1101 time.Sleep(time.Millisecond) 1102 1103 post6, err := ss.Post().Save(&model.Post{ 1104 ChannelId: channelId, 1105 UserId: userId, 1106 ParentId: post2.Id, 1107 RootId: post2.Id, 1108 Message: "message", 1109 }) 1110 post6.ReplyCount = 2 1111 require.NoError(t, err) 1112 1113 // Adding a post to a thread changes the UpdateAt timestamp of the parent post 1114 post1.UpdateAt = post3.UpdateAt 1115 post2.UpdateAt = post6.UpdateAt 1116 1117 t.Run("should return each post and thread before a post", func(t *testing.T) { 1118 postList, err := ss.Post().GetPostsBefore(model.GetPostsOptions{ChannelId: channelId, PostId: post4.Id, PerPage: 2}) 1119 assert.NoError(t, err) 1120 1121 assert.Equal(t, []string{post3.Id, post2.Id}, postList.Order) 1122 assert.Equal(t, map[string]*model.Post{ 1123 post1.Id: post1, 1124 post2.Id: post2, 1125 post3.Id: post3, 1126 post4.Id: post4, 1127 post6.Id: post6, 1128 }, postList.Posts) 1129 }) 1130 1131 t.Run("should return each post and the root of each thread after a post", func(t *testing.T) { 1132 postList, err := ss.Post().GetPostsAfter(model.GetPostsOptions{ChannelId: channelId, PostId: post4.Id, PerPage: 2}) 1133 assert.NoError(t, err) 1134 1135 assert.Equal(t, []string{post6.Id, post5.Id}, postList.Order) 1136 assert.Equal(t, map[string]*model.Post{ 1137 post2.Id: post2, 1138 post4.Id: post4, 1139 post5.Id: post5, 1140 post6.Id: post6, 1141 }, postList.Posts) 1142 }) 1143 }) 1144 t.Run("with threads (skipFetchThreads)", func(t *testing.T) { 1145 channelId := model.NewId() 1146 userId := model.NewId() 1147 1148 // This creates a series of posts that looks like: 1149 // post1 1150 // post2 1151 // post3 (in response to post1) 1152 // post4 (in response to post2) 1153 // post5 1154 // post6 (in response to post2) 1155 1156 post1, err := ss.Post().Save(&model.Post{ 1157 ChannelId: channelId, 1158 UserId: userId, 1159 Message: "post1", 1160 }) 1161 require.NoError(t, err) 1162 post1.ReplyCount = 1 1163 time.Sleep(time.Millisecond) 1164 1165 post2, err := ss.Post().Save(&model.Post{ 1166 ChannelId: channelId, 1167 UserId: userId, 1168 Message: "post2", 1169 }) 1170 require.NoError(t, err) 1171 post2.ReplyCount = 2 1172 time.Sleep(time.Millisecond) 1173 1174 post3, err := ss.Post().Save(&model.Post{ 1175 ChannelId: channelId, 1176 UserId: userId, 1177 ParentId: post1.Id, 1178 RootId: post1.Id, 1179 Message: "post3", 1180 }) 1181 require.NoError(t, err) 1182 post3.ReplyCount = 1 1183 time.Sleep(time.Millisecond) 1184 1185 post4, err := ss.Post().Save(&model.Post{ 1186 ChannelId: channelId, 1187 UserId: userId, 1188 RootId: post2.Id, 1189 ParentId: post2.Id, 1190 Message: "post4", 1191 }) 1192 require.NoError(t, err) 1193 post4.ReplyCount = 2 1194 time.Sleep(time.Millisecond) 1195 1196 post5, err := ss.Post().Save(&model.Post{ 1197 ChannelId: channelId, 1198 UserId: userId, 1199 Message: "post5", 1200 }) 1201 require.NoError(t, err) 1202 time.Sleep(time.Millisecond) 1203 1204 post6, err := ss.Post().Save(&model.Post{ 1205 ChannelId: channelId, 1206 UserId: userId, 1207 ParentId: post2.Id, 1208 RootId: post2.Id, 1209 Message: "post6", 1210 }) 1211 post6.ReplyCount = 2 1212 require.NoError(t, err) 1213 1214 // Adding a post to a thread changes the UpdateAt timestamp of the parent post 1215 post1.UpdateAt = post3.UpdateAt 1216 post2.UpdateAt = post6.UpdateAt 1217 1218 t.Run("should return each post and thread before a post", func(t *testing.T) { 1219 postList, err := ss.Post().GetPostsBefore(model.GetPostsOptions{ChannelId: channelId, PostId: post4.Id, PerPage: 2, SkipFetchThreads: true}) 1220 assert.NoError(t, err) 1221 1222 assert.Equal(t, []string{post3.Id, post2.Id}, postList.Order) 1223 assert.Equal(t, map[string]*model.Post{ 1224 post1.Id: post1, 1225 post2.Id: post2, 1226 post3.Id: post3, 1227 }, postList.Posts) 1228 }) 1229 1230 t.Run("should return each post and thread before a post with limit", func(t *testing.T) { 1231 postList, err := ss.Post().GetPostsBefore(model.GetPostsOptions{ChannelId: channelId, PostId: post4.Id, PerPage: 1, SkipFetchThreads: true}) 1232 assert.NoError(t, err) 1233 1234 assert.Equal(t, []string{post3.Id}, postList.Order) 1235 assert.Equal(t, map[string]*model.Post{ 1236 post1.Id: post1, 1237 post3.Id: post3, 1238 }, postList.Posts) 1239 }) 1240 1241 t.Run("should return each post and the root of each thread after a post", func(t *testing.T) { 1242 postList, err := ss.Post().GetPostsAfter(model.GetPostsOptions{ChannelId: channelId, PostId: post4.Id, PerPage: 2, SkipFetchThreads: true}) 1243 assert.NoError(t, err) 1244 1245 assert.Equal(t, []string{post6.Id, post5.Id}, postList.Order) 1246 assert.Equal(t, map[string]*model.Post{ 1247 post2.Id: post2, 1248 post5.Id: post5, 1249 post6.Id: post6, 1250 }, postList.Posts) 1251 }) 1252 }) 1253 t.Run("with threads (collapsedThreads)", func(t *testing.T) { 1254 channelId := model.NewId() 1255 userId := model.NewId() 1256 1257 // This creates a series of posts that looks like: 1258 // post1 1259 // post2 1260 // post3 (in response to post1) 1261 // post4 (in response to post2) 1262 // post5 1263 // post6 (in response to post2) 1264 1265 post1, err := ss.Post().Save(&model.Post{ 1266 ChannelId: channelId, 1267 UserId: userId, 1268 Message: "post1", 1269 }) 1270 require.NoError(t, err) 1271 post1.ReplyCount = 1 1272 time.Sleep(time.Millisecond) 1273 1274 post2, err := ss.Post().Save(&model.Post{ 1275 ChannelId: channelId, 1276 UserId: userId, 1277 Message: "post2", 1278 }) 1279 require.NoError(t, err) 1280 post2.ReplyCount = 2 1281 time.Sleep(time.Millisecond) 1282 1283 post3, err := ss.Post().Save(&model.Post{ 1284 ChannelId: channelId, 1285 UserId: userId, 1286 ParentId: post1.Id, 1287 RootId: post1.Id, 1288 Message: "post3", 1289 }) 1290 require.NoError(t, err) 1291 post3.ReplyCount = 1 1292 time.Sleep(time.Millisecond) 1293 1294 post4, err := ss.Post().Save(&model.Post{ 1295 ChannelId: channelId, 1296 UserId: userId, 1297 RootId: post2.Id, 1298 ParentId: post2.Id, 1299 Message: "post4", 1300 }) 1301 require.NoError(t, err) 1302 post4.ReplyCount = 2 1303 time.Sleep(time.Millisecond) 1304 1305 post5, err := ss.Post().Save(&model.Post{ 1306 ChannelId: channelId, 1307 UserId: userId, 1308 Message: "post5", 1309 }) 1310 require.NoError(t, err) 1311 time.Sleep(time.Millisecond) 1312 1313 post6, err := ss.Post().Save(&model.Post{ 1314 ChannelId: channelId, 1315 UserId: userId, 1316 ParentId: post2.Id, 1317 RootId: post2.Id, 1318 Message: "post6", 1319 }) 1320 post6.ReplyCount = 2 1321 require.NoError(t, err) 1322 1323 // Adding a post to a thread changes the UpdateAt timestamp of the parent post 1324 post1.UpdateAt = post3.UpdateAt 1325 post2.UpdateAt = post6.UpdateAt 1326 1327 t.Run("should return each root post before a post", func(t *testing.T) { 1328 postList, err := ss.Post().GetPostsBefore(model.GetPostsOptions{ChannelId: channelId, PostId: post4.Id, PerPage: 2, CollapsedThreads: true}) 1329 assert.NoError(t, err) 1330 1331 assert.Equal(t, []string{post2.Id, post1.Id}, postList.Order) 1332 }) 1333 1334 t.Run("should return each root post before a post with limit", func(t *testing.T) { 1335 postList, err := ss.Post().GetPostsBefore(model.GetPostsOptions{ChannelId: channelId, PostId: post4.Id, PerPage: 1, CollapsedThreads: true}) 1336 assert.NoError(t, err) 1337 1338 assert.Equal(t, []string{post2.Id}, postList.Order) 1339 }) 1340 1341 t.Run("should return each root after a post", func(t *testing.T) { 1342 postList, err := ss.Post().GetPostsAfter(model.GetPostsOptions{ChannelId: channelId, PostId: post4.Id, PerPage: 2, CollapsedThreads: true}) 1343 require.NoError(t, err) 1344 1345 assert.Equal(t, []string{post5.Id}, postList.Order) 1346 }) 1347 }) 1348 } 1349 1350 func testPostStoreGetPostsSince(t *testing.T, ss store.Store) { 1351 t.Run("should return posts created after the given time", func(t *testing.T) { 1352 channelId := model.NewId() 1353 userId := model.NewId() 1354 1355 post1, err := ss.Post().Save(&model.Post{ 1356 ChannelId: channelId, 1357 UserId: userId, 1358 Message: "message", 1359 }) 1360 require.NoError(t, err) 1361 time.Sleep(time.Millisecond) 1362 1363 _, err = ss.Post().Save(&model.Post{ 1364 ChannelId: channelId, 1365 UserId: userId, 1366 Message: "message", 1367 }) 1368 require.NoError(t, err) 1369 time.Sleep(time.Millisecond) 1370 1371 post3, err := ss.Post().Save(&model.Post{ 1372 ChannelId: channelId, 1373 UserId: userId, 1374 Message: "message", 1375 }) 1376 require.NoError(t, err) 1377 time.Sleep(time.Millisecond) 1378 1379 post4, err := ss.Post().Save(&model.Post{ 1380 ChannelId: channelId, 1381 UserId: userId, 1382 Message: "message", 1383 }) 1384 require.NoError(t, err) 1385 time.Sleep(time.Millisecond) 1386 1387 post5, err := ss.Post().Save(&model.Post{ 1388 ChannelId: channelId, 1389 UserId: userId, 1390 Message: "message", 1391 RootId: post3.Id, 1392 }) 1393 require.NoError(t, err) 1394 time.Sleep(time.Millisecond) 1395 1396 post6, err := ss.Post().Save(&model.Post{ 1397 ChannelId: channelId, 1398 UserId: userId, 1399 Message: "message", 1400 RootId: post1.Id, 1401 }) 1402 require.NoError(t, err) 1403 time.Sleep(time.Millisecond) 1404 1405 postList, err := ss.Post().GetPostsSince(model.GetPostsSinceOptions{ChannelId: channelId, Time: post3.CreateAt}, false) 1406 require.NoError(t, err) 1407 1408 assert.Equal(t, []string{ 1409 post6.Id, 1410 post5.Id, 1411 post4.Id, 1412 post3.Id, 1413 post1.Id, 1414 }, postList.Order) 1415 1416 assert.Len(t, postList.Posts, 5) 1417 assert.NotNil(t, postList.Posts[post1.Id], "should return the parent post") 1418 assert.NotNil(t, postList.Posts[post3.Id]) 1419 assert.NotNil(t, postList.Posts[post4.Id]) 1420 assert.NotNil(t, postList.Posts[post5.Id]) 1421 assert.NotNil(t, postList.Posts[post6.Id]) 1422 }) 1423 1424 t.Run("should return empty list when nothing has changed", func(t *testing.T) { 1425 channelId := model.NewId() 1426 userId := model.NewId() 1427 1428 post1, err := ss.Post().Save(&model.Post{ 1429 ChannelId: channelId, 1430 UserId: userId, 1431 Message: "message", 1432 }) 1433 require.NoError(t, err) 1434 time.Sleep(time.Millisecond) 1435 1436 postList, err := ss.Post().GetPostsSince(model.GetPostsSinceOptions{ChannelId: channelId, Time: post1.CreateAt}, false) 1437 assert.NoError(t, err) 1438 1439 assert.Equal(t, []string{}, postList.Order) 1440 assert.Empty(t, postList.Posts) 1441 }) 1442 1443 t.Run("should not cache a timestamp of 0 when nothing has changed", func(t *testing.T) { 1444 ss.Post().ClearCaches() 1445 1446 channelId := model.NewId() 1447 userId := model.NewId() 1448 1449 post1, err := ss.Post().Save(&model.Post{ 1450 ChannelId: channelId, 1451 UserId: userId, 1452 Message: "message", 1453 }) 1454 require.NoError(t, err) 1455 time.Sleep(time.Millisecond) 1456 1457 // Make a request that returns no results 1458 postList, err := ss.Post().GetPostsSince(model.GetPostsSinceOptions{ChannelId: channelId, Time: post1.CreateAt}, true) 1459 require.NoError(t, err) 1460 require.Equal(t, model.NewPostList(), postList) 1461 1462 // And then ensure that it doesn't cause future requests to also return no results 1463 postList, err = ss.Post().GetPostsSince(model.GetPostsSinceOptions{ChannelId: channelId, Time: post1.CreateAt - 1}, true) 1464 require.NoError(t, err) 1465 1466 assert.Equal(t, []string{post1.Id}, postList.Order) 1467 1468 assert.Len(t, postList.Posts, 1) 1469 assert.NotNil(t, postList.Posts[post1.Id]) 1470 }) 1471 } 1472 1473 func testPostStoreGetPosts(t *testing.T, ss store.Store) { 1474 channelId := model.NewId() 1475 userId := model.NewId() 1476 1477 post1, err := ss.Post().Save(&model.Post{ 1478 ChannelId: channelId, 1479 UserId: userId, 1480 Message: "message", 1481 }) 1482 require.NoError(t, err) 1483 time.Sleep(time.Millisecond) 1484 1485 post2, err := ss.Post().Save(&model.Post{ 1486 ChannelId: channelId, 1487 UserId: userId, 1488 Message: "message", 1489 }) 1490 require.NoError(t, err) 1491 time.Sleep(time.Millisecond) 1492 1493 post3, err := ss.Post().Save(&model.Post{ 1494 ChannelId: channelId, 1495 UserId: userId, 1496 Message: "message", 1497 }) 1498 require.NoError(t, err) 1499 time.Sleep(time.Millisecond) 1500 1501 post4, err := ss.Post().Save(&model.Post{ 1502 ChannelId: channelId, 1503 UserId: userId, 1504 Message: "message", 1505 }) 1506 require.NoError(t, err) 1507 time.Sleep(time.Millisecond) 1508 1509 post5, err := ss.Post().Save(&model.Post{ 1510 ChannelId: channelId, 1511 UserId: userId, 1512 Message: "message", 1513 RootId: post3.Id, 1514 }) 1515 require.NoError(t, err) 1516 time.Sleep(time.Millisecond) 1517 1518 post6, err := ss.Post().Save(&model.Post{ 1519 ChannelId: channelId, 1520 UserId: userId, 1521 Message: "message", 1522 RootId: post1.Id, 1523 }) 1524 require.NoError(t, err) 1525 1526 t.Run("should return the last posts created in a channel", func(t *testing.T) { 1527 postList, err := ss.Post().GetPosts(model.GetPostsOptions{ChannelId: channelId, Page: 0, PerPage: 30, SkipFetchThreads: false}, false) 1528 assert.NoError(t, err) 1529 1530 assert.Equal(t, []string{ 1531 post6.Id, 1532 post5.Id, 1533 post4.Id, 1534 post3.Id, 1535 post2.Id, 1536 post1.Id, 1537 }, postList.Order) 1538 1539 assert.Len(t, postList.Posts, 6) 1540 assert.NotNil(t, postList.Posts[post1.Id]) 1541 assert.NotNil(t, postList.Posts[post2.Id]) 1542 assert.NotNil(t, postList.Posts[post3.Id]) 1543 assert.NotNil(t, postList.Posts[post4.Id]) 1544 assert.NotNil(t, postList.Posts[post5.Id]) 1545 assert.NotNil(t, postList.Posts[post6.Id]) 1546 }) 1547 1548 t.Run("should return the last posts created in a channel and the threads and the reply count must be 0", func(t *testing.T) { 1549 postList, err := ss.Post().GetPosts(model.GetPostsOptions{ChannelId: channelId, Page: 0, PerPage: 2, SkipFetchThreads: false}, false) 1550 assert.NoError(t, err) 1551 1552 assert.Equal(t, []string{ 1553 post6.Id, 1554 post5.Id, 1555 }, postList.Order) 1556 1557 assert.Len(t, postList.Posts, 4) 1558 require.NotNil(t, postList.Posts[post1.Id]) 1559 require.NotNil(t, postList.Posts[post3.Id]) 1560 require.NotNil(t, postList.Posts[post5.Id]) 1561 require.NotNil(t, postList.Posts[post6.Id]) 1562 assert.Equal(t, int64(0), postList.Posts[post1.Id].ReplyCount) 1563 assert.Equal(t, int64(0), postList.Posts[post3.Id].ReplyCount) 1564 assert.Equal(t, int64(0), postList.Posts[post5.Id].ReplyCount) 1565 assert.Equal(t, int64(0), postList.Posts[post6.Id].ReplyCount) 1566 }) 1567 1568 t.Run("should return the last posts created in a channel without the threads and the reply count must be correct", func(t *testing.T) { 1569 postList, err := ss.Post().GetPosts(model.GetPostsOptions{ChannelId: channelId, Page: 0, PerPage: 2, SkipFetchThreads: true}, false) 1570 require.NoError(t, err) 1571 1572 assert.Equal(t, []string{ 1573 post6.Id, 1574 post5.Id, 1575 }, postList.Order) 1576 1577 assert.Len(t, postList.Posts, 4) 1578 assert.NotNil(t, postList.Posts[post5.Id]) 1579 assert.NotNil(t, postList.Posts[post6.Id]) 1580 assert.Equal(t, int64(1), postList.Posts[post5.Id].ReplyCount) 1581 assert.Equal(t, int64(1), postList.Posts[post6.Id].ReplyCount) 1582 }) 1583 } 1584 1585 func testPostStoreGetPostBeforeAfter(t *testing.T, ss store.Store) { 1586 channelId := model.NewId() 1587 1588 o0 := &model.Post{} 1589 o0.ChannelId = channelId 1590 o0.UserId = model.NewId() 1591 o0.Message = "zz" + model.NewId() + "b" 1592 _, err := ss.Post().Save(o0) 1593 require.NoError(t, err) 1594 time.Sleep(2 * time.Millisecond) 1595 1596 o1 := &model.Post{} 1597 o1.ChannelId = channelId 1598 o1.Type = model.POST_JOIN_CHANNEL 1599 o1.UserId = model.NewId() 1600 o1.Message = "system_join_channel message" 1601 _, err = ss.Post().Save(o1) 1602 require.NoError(t, err) 1603 time.Sleep(2 * time.Millisecond) 1604 1605 o0a := &model.Post{} 1606 o0a.ChannelId = channelId 1607 o0a.UserId = model.NewId() 1608 o0a.Message = "zz" + model.NewId() + "b" 1609 o0a.ParentId = o1.Id 1610 o0a.RootId = o1.Id 1611 _, err = ss.Post().Save(o0a) 1612 require.NoError(t, err) 1613 time.Sleep(2 * time.Millisecond) 1614 1615 o0b := &model.Post{} 1616 o0b.ChannelId = channelId 1617 o0b.UserId = model.NewId() 1618 o0b.Message = "deleted message" 1619 o0b.ParentId = o1.Id 1620 o0b.RootId = o1.Id 1621 o0b.DeleteAt = 1 1622 _, err = ss.Post().Save(o0b) 1623 require.NoError(t, err) 1624 time.Sleep(2 * time.Millisecond) 1625 1626 otherChannelPost := &model.Post{} 1627 otherChannelPost.ChannelId = model.NewId() 1628 otherChannelPost.UserId = model.NewId() 1629 otherChannelPost.Message = "zz" + model.NewId() + "b" 1630 _, err = ss.Post().Save(otherChannelPost) 1631 require.NoError(t, err) 1632 time.Sleep(2 * time.Millisecond) 1633 1634 o2 := &model.Post{} 1635 o2.ChannelId = channelId 1636 o2.UserId = model.NewId() 1637 o2.Message = "zz" + model.NewId() + "b" 1638 _, err = ss.Post().Save(o2) 1639 require.NoError(t, err) 1640 time.Sleep(2 * time.Millisecond) 1641 1642 o2a := &model.Post{} 1643 o2a.ChannelId = channelId 1644 o2a.UserId = model.NewId() 1645 o2a.Message = "zz" + model.NewId() + "b" 1646 o2a.ParentId = o2.Id 1647 o2a.RootId = o2.Id 1648 _, err = ss.Post().Save(o2a) 1649 require.NoError(t, err) 1650 1651 rPostId1, err := ss.Post().GetPostIdBeforeTime(channelId, o0a.CreateAt, false) 1652 require.Equal(t, rPostId1, o1.Id, "should return before post o1") 1653 require.NoError(t, err) 1654 1655 rPostId1, err = ss.Post().GetPostIdAfterTime(channelId, o0b.CreateAt, false) 1656 require.Equal(t, rPostId1, o2.Id, "should return before post o2") 1657 require.NoError(t, err) 1658 1659 rPost1, err := ss.Post().GetPostAfterTime(channelId, o0b.CreateAt, false) 1660 require.Equal(t, rPost1.Id, o2.Id, "should return before post o2") 1661 require.NoError(t, err) 1662 1663 rPostId2, err := ss.Post().GetPostIdBeforeTime(channelId, o0.CreateAt, false) 1664 require.Empty(t, rPostId2, "should return no post") 1665 require.NoError(t, err) 1666 1667 rPostId2, err = ss.Post().GetPostIdAfterTime(channelId, o0.CreateAt, false) 1668 require.Equal(t, rPostId2, o1.Id, "should return before post o1") 1669 require.NoError(t, err) 1670 1671 rPost2, err := ss.Post().GetPostAfterTime(channelId, o0.CreateAt, false) 1672 require.Equal(t, rPost2.Id, o1.Id, "should return before post o1") 1673 require.NoError(t, err) 1674 1675 rPostId3, err := ss.Post().GetPostIdBeforeTime(channelId, o2a.CreateAt, false) 1676 require.Equal(t, rPostId3, o2.Id, "should return before post o2") 1677 require.NoError(t, err) 1678 1679 rPostId3, err = ss.Post().GetPostIdAfterTime(channelId, o2a.CreateAt, false) 1680 require.Empty(t, rPostId3, "should return no post") 1681 require.NoError(t, err) 1682 1683 rPost3, err := ss.Post().GetPostAfterTime(channelId, o2a.CreateAt, false) 1684 require.Empty(t, rPost3, "should return no post") 1685 require.NoError(t, err) 1686 } 1687 1688 func testUserCountsWithPostsByDay(t *testing.T, ss store.Store) { 1689 t1 := &model.Team{} 1690 t1.DisplayName = "DisplayName" 1691 t1.Name = "zz" + model.NewId() + "b" 1692 t1.Email = MakeEmail() 1693 t1.Type = model.TEAM_OPEN 1694 t1, err := ss.Team().Save(t1) 1695 require.NoError(t, err) 1696 1697 c1 := &model.Channel{} 1698 c1.TeamId = t1.Id 1699 c1.DisplayName = "Channel2" 1700 c1.Name = "zz" + model.NewId() + "b" 1701 c1.Type = model.CHANNEL_OPEN 1702 c1, nErr := ss.Channel().Save(c1, -1) 1703 require.NoError(t, nErr) 1704 1705 o1 := &model.Post{} 1706 o1.ChannelId = c1.Id 1707 o1.UserId = model.NewId() 1708 o1.CreateAt = utils.MillisFromTime(utils.Yesterday()) 1709 o1.Message = "zz" + model.NewId() + "b" 1710 o1, nErr = ss.Post().Save(o1) 1711 require.NoError(t, nErr) 1712 1713 o1a := &model.Post{} 1714 o1a.ChannelId = c1.Id 1715 o1a.UserId = model.NewId() 1716 o1a.CreateAt = o1.CreateAt 1717 o1a.Message = "zz" + model.NewId() + "b" 1718 _, nErr = ss.Post().Save(o1a) 1719 require.NoError(t, nErr) 1720 1721 o2 := &model.Post{} 1722 o2.ChannelId = c1.Id 1723 o2.UserId = model.NewId() 1724 o2.CreateAt = o1.CreateAt - (1000 * 60 * 60 * 24) 1725 o2.Message = "zz" + model.NewId() + "b" 1726 o2, nErr = ss.Post().Save(o2) 1727 require.NoError(t, nErr) 1728 1729 o2a := &model.Post{} 1730 o2a.ChannelId = c1.Id 1731 o2a.UserId = o2.UserId 1732 o2a.CreateAt = o1.CreateAt - (1000 * 60 * 60 * 24) 1733 o2a.Message = "zz" + model.NewId() + "b" 1734 _, nErr = ss.Post().Save(o2a) 1735 require.NoError(t, nErr) 1736 1737 r1, err := ss.Post().AnalyticsUserCountsWithPostsByDay(t1.Id) 1738 require.NoError(t, err) 1739 1740 row1 := r1[0] 1741 require.Equal(t, float64(2), row1.Value, "wrong value") 1742 1743 row2 := r1[1] 1744 require.Equal(t, float64(1), row2.Value, "wrong value") 1745 } 1746 1747 func testPostCountsByDay(t *testing.T, ss store.Store) { 1748 t1 := &model.Team{} 1749 t1.DisplayName = "DisplayName" 1750 t1.Name = "zz" + model.NewId() + "b" 1751 t1.Email = MakeEmail() 1752 t1.Type = model.TEAM_OPEN 1753 t1, err := ss.Team().Save(t1) 1754 require.NoError(t, err) 1755 1756 c1 := &model.Channel{} 1757 c1.TeamId = t1.Id 1758 c1.DisplayName = "Channel2" 1759 c1.Name = "zz" + model.NewId() + "b" 1760 c1.Type = model.CHANNEL_OPEN 1761 c1, nErr := ss.Channel().Save(c1, -1) 1762 require.NoError(t, nErr) 1763 1764 o1 := &model.Post{} 1765 o1.ChannelId = c1.Id 1766 o1.UserId = model.NewId() 1767 o1.CreateAt = utils.MillisFromTime(utils.Yesterday()) 1768 o1.Message = "zz" + model.NewId() + "b" 1769 o1.Hashtags = "hashtag" 1770 o1, nErr = ss.Post().Save(o1) 1771 require.NoError(t, nErr) 1772 1773 o1a := &model.Post{} 1774 o1a.ChannelId = c1.Id 1775 o1a.UserId = model.NewId() 1776 o1a.CreateAt = o1.CreateAt 1777 o1a.Message = "zz" + model.NewId() + "b" 1778 o1a.FileIds = []string{"fileId1"} 1779 _, nErr = ss.Post().Save(o1a) 1780 require.NoError(t, nErr) 1781 1782 o2 := &model.Post{} 1783 o2.ChannelId = c1.Id 1784 o2.UserId = model.NewId() 1785 o2.CreateAt = o1.CreateAt - (1000 * 60 * 60 * 24 * 2) 1786 o2.Message = "zz" + model.NewId() + "b" 1787 o2.Filenames = []string{"filename1"} 1788 o2, nErr = ss.Post().Save(o2) 1789 require.NoError(t, nErr) 1790 1791 o2a := &model.Post{} 1792 o2a.ChannelId = c1.Id 1793 o2a.UserId = o2.UserId 1794 o2a.CreateAt = o1.CreateAt - (1000 * 60 * 60 * 24 * 2) 1795 o2a.Message = "zz" + model.NewId() + "b" 1796 o2a.Hashtags = "hashtag" 1797 o2a.FileIds = []string{"fileId2"} 1798 _, nErr = ss.Post().Save(o2a) 1799 require.NoError(t, nErr) 1800 1801 bot1 := &model.Bot{ 1802 Username: "username", 1803 Description: "a bot", 1804 OwnerId: model.NewId(), 1805 UserId: model.NewId(), 1806 } 1807 _, nErr = ss.Bot().Save(bot1) 1808 require.NoError(t, nErr) 1809 1810 b1 := &model.Post{} 1811 b1.Message = "bot message one" 1812 b1.ChannelId = c1.Id 1813 b1.UserId = bot1.UserId 1814 b1.CreateAt = utils.MillisFromTime(utils.Yesterday()) 1815 _, nErr = ss.Post().Save(b1) 1816 require.NoError(t, nErr) 1817 1818 b1a := &model.Post{} 1819 b1a.Message = "bot message two" 1820 b1a.ChannelId = c1.Id 1821 b1a.UserId = bot1.UserId 1822 b1a.CreateAt = utils.MillisFromTime(utils.Yesterday()) - (1000 * 60 * 60 * 24 * 2) 1823 _, nErr = ss.Post().Save(b1a) 1824 require.NoError(t, nErr) 1825 1826 time.Sleep(1 * time.Second) 1827 1828 // summary of posts 1829 // yesterday - 2 non-bot user posts, 1 bot user post 1830 // 3 days ago - 2 non-bot user posts, 1 bot user post 1831 1832 // last 31 days, all users (including bots) 1833 postCountsOptions := &model.AnalyticsPostCountsOptions{TeamId: t1.Id, BotsOnly: false, YesterdayOnly: false} 1834 r1, err := ss.Post().AnalyticsPostCountsByDay(postCountsOptions) 1835 require.NoError(t, err) 1836 assert.Equal(t, float64(3), r1[0].Value) 1837 assert.Equal(t, float64(3), r1[1].Value) 1838 1839 // last 31 days, bots only 1840 postCountsOptions = &model.AnalyticsPostCountsOptions{TeamId: t1.Id, BotsOnly: true, YesterdayOnly: false} 1841 r1, err = ss.Post().AnalyticsPostCountsByDay(postCountsOptions) 1842 require.NoError(t, err) 1843 assert.Equal(t, float64(1), r1[0].Value) 1844 assert.Equal(t, float64(1), r1[1].Value) 1845 1846 // yesterday only, all users (including bots) 1847 postCountsOptions = &model.AnalyticsPostCountsOptions{TeamId: t1.Id, BotsOnly: false, YesterdayOnly: true} 1848 r1, err = ss.Post().AnalyticsPostCountsByDay(postCountsOptions) 1849 require.NoError(t, err) 1850 assert.Equal(t, float64(3), r1[0].Value) 1851 1852 // yesterday only, bots only 1853 postCountsOptions = &model.AnalyticsPostCountsOptions{TeamId: t1.Id, BotsOnly: true, YesterdayOnly: true} 1854 r1, err = ss.Post().AnalyticsPostCountsByDay(postCountsOptions) 1855 require.NoError(t, err) 1856 assert.Equal(t, float64(1), r1[0].Value) 1857 1858 // total 1859 r2, err := ss.Post().AnalyticsPostCount(t1.Id, false, false) 1860 require.NoError(t, err) 1861 assert.Equal(t, int64(6), r2) 1862 1863 // total across teams 1864 r2, err = ss.Post().AnalyticsPostCount("", false, false) 1865 require.NoError(t, err) 1866 assert.GreaterOrEqual(t, r2, int64(6)) 1867 1868 // total across teams with files 1869 r2, err = ss.Post().AnalyticsPostCount("", true, false) 1870 require.NoError(t, err) 1871 assert.GreaterOrEqual(t, r2, int64(3)) 1872 1873 // total across teams with hastags 1874 r2, err = ss.Post().AnalyticsPostCount("", false, true) 1875 require.NoError(t, err) 1876 assert.GreaterOrEqual(t, r2, int64(2)) 1877 1878 // total across teams with hastags and files 1879 r2, err = ss.Post().AnalyticsPostCount("", true, true) 1880 require.NoError(t, err) 1881 assert.GreaterOrEqual(t, r2, int64(1)) 1882 } 1883 1884 func testPostStoreGetFlaggedPostsForTeam(t *testing.T, ss store.Store, s SqlStore) { 1885 c1 := &model.Channel{} 1886 c1.TeamId = model.NewId() 1887 c1.DisplayName = "Channel1" 1888 c1.Name = "zz" + model.NewId() + "b" 1889 c1.Type = model.CHANNEL_OPEN 1890 c1, err := ss.Channel().Save(c1, -1) 1891 require.NoError(t, err) 1892 1893 o1 := &model.Post{} 1894 o1.ChannelId = c1.Id 1895 o1.UserId = model.NewId() 1896 o1.Message = "zz" + model.NewId() + "b" 1897 o1, err = ss.Post().Save(o1) 1898 require.NoError(t, err) 1899 time.Sleep(2 * time.Millisecond) 1900 1901 o2 := &model.Post{} 1902 o2.ChannelId = o1.ChannelId 1903 o2.UserId = model.NewId() 1904 o2.Message = "zz" + model.NewId() + "b" 1905 o2, err = ss.Post().Save(o2) 1906 require.NoError(t, err) 1907 time.Sleep(2 * time.Millisecond) 1908 1909 o3 := &model.Post{} 1910 o3.ChannelId = o1.ChannelId 1911 o3.UserId = model.NewId() 1912 o3.Message = "zz" + model.NewId() + "b" 1913 o3.DeleteAt = 1 1914 o3, err = ss.Post().Save(o3) 1915 require.NoError(t, err) 1916 time.Sleep(2 * time.Millisecond) 1917 1918 o4 := &model.Post{} 1919 o4.ChannelId = model.NewId() 1920 o4.UserId = model.NewId() 1921 o4.Message = "zz" + model.NewId() + "b" 1922 o4, err = ss.Post().Save(o4) 1923 require.NoError(t, err) 1924 time.Sleep(2 * time.Millisecond) 1925 1926 c2 := &model.Channel{} 1927 c2.DisplayName = "DMChannel1" 1928 c2.Name = "zz" + model.NewId() + "b" 1929 c2.Type = model.CHANNEL_DIRECT 1930 1931 m1 := &model.ChannelMember{} 1932 m1.ChannelId = c2.Id 1933 m1.UserId = o1.UserId 1934 m1.NotifyProps = model.GetDefaultChannelNotifyProps() 1935 1936 m2 := &model.ChannelMember{} 1937 m2.ChannelId = c2.Id 1938 m2.UserId = model.NewId() 1939 m2.NotifyProps = model.GetDefaultChannelNotifyProps() 1940 1941 c2, err = ss.Channel().SaveDirectChannel(c2, m1, m2) 1942 require.NoError(t, err) 1943 1944 o5 := &model.Post{} 1945 o5.ChannelId = c2.Id 1946 o5.UserId = m2.UserId 1947 o5.Message = "zz" + model.NewId() + "b" 1948 o5, err = ss.Post().Save(o5) 1949 require.NoError(t, err) 1950 time.Sleep(2 * time.Millisecond) 1951 1952 r1, err := ss.Post().GetFlaggedPosts(o1.ChannelId, 0, 2) 1953 require.NoError(t, err) 1954 1955 require.Empty(t, r1.Order, "should be empty") 1956 1957 preferences := model.Preferences{ 1958 { 1959 UserId: o1.UserId, 1960 Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, 1961 Name: o1.Id, 1962 Value: "true", 1963 }, 1964 } 1965 1966 err = ss.Preference().Save(&preferences) 1967 require.NoError(t, err) 1968 1969 r2, err := ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 2) 1970 require.NoError(t, err) 1971 require.Len(t, r2.Order, 1, "should have 1 post") 1972 1973 preferences = model.Preferences{ 1974 { 1975 UserId: o1.UserId, 1976 Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, 1977 Name: o2.Id, 1978 Value: "true", 1979 }, 1980 } 1981 1982 err = ss.Preference().Save(&preferences) 1983 require.NoError(t, err) 1984 1985 r3, err := ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 1) 1986 require.NoError(t, err) 1987 require.Len(t, r3.Order, 1, "should have 1 post") 1988 1989 r3, err = ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 1, 1) 1990 require.NoError(t, err) 1991 require.Len(t, r3.Order, 1, "should have 1 post") 1992 1993 r3, err = ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 1000, 10) 1994 require.NoError(t, err) 1995 require.Empty(t, r3.Order, "should be empty") 1996 1997 r4, err := ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 2) 1998 require.NoError(t, err) 1999 require.Len(t, r4.Order, 2, "should have 2 posts") 2000 2001 preferences = model.Preferences{ 2002 { 2003 UserId: o1.UserId, 2004 Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, 2005 Name: o3.Id, 2006 Value: "true", 2007 }, 2008 } 2009 2010 err = ss.Preference().Save(&preferences) 2011 require.NoError(t, err) 2012 2013 r4, err = ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 2) 2014 require.NoError(t, err) 2015 require.Len(t, r4.Order, 2, "should have 2 posts") 2016 2017 preferences = model.Preferences{ 2018 { 2019 UserId: o1.UserId, 2020 Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, 2021 Name: o4.Id, 2022 Value: "true", 2023 }, 2024 } 2025 err = ss.Preference().Save(&preferences) 2026 require.NoError(t, err) 2027 2028 r4, err = ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 2) 2029 require.NoError(t, err) 2030 require.Len(t, r4.Order, 2, "should have 2 posts") 2031 2032 r4, err = ss.Post().GetFlaggedPostsForTeam(o1.UserId, model.NewId(), 0, 2) 2033 require.NoError(t, err) 2034 require.Empty(t, r4.Order, "should have 0 posts") 2035 2036 preferences = model.Preferences{ 2037 { 2038 UserId: o1.UserId, 2039 Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, 2040 Name: o5.Id, 2041 Value: "true", 2042 }, 2043 } 2044 err = ss.Preference().Save(&preferences) 2045 require.NoError(t, err) 2046 2047 r4, err = ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 10) 2048 require.NoError(t, err) 2049 require.Len(t, r4.Order, 3, "should have 3 posts") 2050 2051 // Manually truncate Channels table until testlib can handle cleanups 2052 s.GetMaster().Exec("TRUNCATE Channels") 2053 } 2054 2055 func testPostStoreGetFlaggedPosts(t *testing.T, ss store.Store) { 2056 o1 := &model.Post{} 2057 o1.ChannelId = model.NewId() 2058 o1.UserId = model.NewId() 2059 o1.Message = "zz" + model.NewId() + "b" 2060 o1, err := ss.Post().Save(o1) 2061 require.NoError(t, err) 2062 time.Sleep(2 * time.Millisecond) 2063 2064 o2 := &model.Post{} 2065 o2.ChannelId = o1.ChannelId 2066 o2.UserId = model.NewId() 2067 o2.Message = "zz" + model.NewId() + "b" 2068 o2, err = ss.Post().Save(o2) 2069 require.NoError(t, err) 2070 time.Sleep(2 * time.Millisecond) 2071 2072 o3 := &model.Post{} 2073 o3.ChannelId = o1.ChannelId 2074 o3.UserId = model.NewId() 2075 o3.Message = "zz" + model.NewId() + "b" 2076 o3.DeleteAt = 1 2077 o3, err = ss.Post().Save(o3) 2078 require.NoError(t, err) 2079 time.Sleep(2 * time.Millisecond) 2080 2081 r1, err := ss.Post().GetFlaggedPosts(o1.UserId, 0, 2) 2082 require.NoError(t, err) 2083 require.Empty(t, r1.Order, "should be empty") 2084 2085 preferences := model.Preferences{ 2086 { 2087 UserId: o1.UserId, 2088 Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, 2089 Name: o1.Id, 2090 Value: "true", 2091 }, 2092 } 2093 2094 nErr := ss.Preference().Save(&preferences) 2095 require.NoError(t, nErr) 2096 2097 r2, err := ss.Post().GetFlaggedPosts(o1.UserId, 0, 2) 2098 require.NoError(t, err) 2099 require.Len(t, r2.Order, 1, "should have 1 post") 2100 2101 preferences = model.Preferences{ 2102 { 2103 UserId: o1.UserId, 2104 Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, 2105 Name: o2.Id, 2106 Value: "true", 2107 }, 2108 } 2109 2110 nErr = ss.Preference().Save(&preferences) 2111 require.NoError(t, nErr) 2112 2113 r3, err := ss.Post().GetFlaggedPosts(o1.UserId, 0, 1) 2114 require.NoError(t, err) 2115 require.Len(t, r3.Order, 1, "should have 1 post") 2116 2117 r3, err = ss.Post().GetFlaggedPosts(o1.UserId, 1, 1) 2118 require.NoError(t, err) 2119 require.Len(t, r3.Order, 1, "should have 1 post") 2120 2121 r3, err = ss.Post().GetFlaggedPosts(o1.UserId, 1000, 10) 2122 require.NoError(t, err) 2123 require.Empty(t, r3.Order, "should be empty") 2124 2125 r4, err := ss.Post().GetFlaggedPosts(o1.UserId, 0, 2) 2126 require.NoError(t, err) 2127 require.Len(t, r4.Order, 2, "should have 2 posts") 2128 2129 preferences = model.Preferences{ 2130 { 2131 UserId: o1.UserId, 2132 Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, 2133 Name: o3.Id, 2134 Value: "true", 2135 }, 2136 } 2137 2138 nErr = ss.Preference().Save(&preferences) 2139 require.NoError(t, nErr) 2140 2141 r4, err = ss.Post().GetFlaggedPosts(o1.UserId, 0, 2) 2142 require.NoError(t, err) 2143 require.Len(t, r4.Order, 2, "should have 2 posts") 2144 } 2145 2146 func testPostStoreGetFlaggedPostsForChannel(t *testing.T, ss store.Store) { 2147 o1 := &model.Post{} 2148 o1.ChannelId = model.NewId() 2149 o1.UserId = model.NewId() 2150 o1.Message = "zz" + model.NewId() + "b" 2151 o1, err := ss.Post().Save(o1) 2152 require.NoError(t, err) 2153 time.Sleep(2 * time.Millisecond) 2154 2155 o2 := &model.Post{} 2156 o2.ChannelId = o1.ChannelId 2157 o2.UserId = model.NewId() 2158 o2.Message = "zz" + model.NewId() + "b" 2159 o2, err = ss.Post().Save(o2) 2160 require.NoError(t, err) 2161 time.Sleep(2 * time.Millisecond) 2162 2163 // deleted post 2164 o3 := &model.Post{} 2165 o3.ChannelId = model.NewId() 2166 o3.UserId = o1.ChannelId 2167 o3.Message = "zz" + model.NewId() + "b" 2168 o3.DeleteAt = 1 2169 o3, err = ss.Post().Save(o3) 2170 require.NoError(t, err) 2171 time.Sleep(2 * time.Millisecond) 2172 2173 o4 := &model.Post{} 2174 o4.ChannelId = model.NewId() 2175 o4.UserId = model.NewId() 2176 o4.Message = "zz" + model.NewId() + "b" 2177 o4, err = ss.Post().Save(o4) 2178 require.NoError(t, err) 2179 time.Sleep(2 * time.Millisecond) 2180 2181 r, err := ss.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 0, 10) 2182 require.NoError(t, err) 2183 require.Empty(t, r.Order, "should be empty") 2184 2185 preference := model.Preference{ 2186 UserId: o1.UserId, 2187 Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, 2188 Name: o1.Id, 2189 Value: "true", 2190 } 2191 2192 nErr := ss.Preference().Save(&model.Preferences{preference}) 2193 require.NoError(t, nErr) 2194 2195 r, err = ss.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 0, 10) 2196 require.NoError(t, err) 2197 require.Len(t, r.Order, 1, "should have 1 post") 2198 2199 preference.Name = o2.Id 2200 nErr = ss.Preference().Save(&model.Preferences{preference}) 2201 require.NoError(t, nErr) 2202 2203 preference.Name = o3.Id 2204 nErr = ss.Preference().Save(&model.Preferences{preference}) 2205 require.NoError(t, nErr) 2206 2207 r, err = ss.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 0, 1) 2208 require.NoError(t, err) 2209 require.Len(t, r.Order, 1, "should have 1 post") 2210 2211 r, err = ss.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 1, 1) 2212 require.NoError(t, err) 2213 require.Len(t, r.Order, 1, "should have 1 post") 2214 2215 r, err = ss.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 1000, 10) 2216 require.NoError(t, err) 2217 require.Empty(t, r.Order, "should be empty") 2218 2219 r, err = ss.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 0, 10) 2220 require.NoError(t, err) 2221 require.Len(t, r.Order, 2, "should have 2 posts") 2222 2223 preference.Name = o4.Id 2224 nErr = ss.Preference().Save(&model.Preferences{preference}) 2225 require.NoError(t, nErr) 2226 2227 r, err = ss.Post().GetFlaggedPostsForChannel(o1.UserId, o4.ChannelId, 0, 10) 2228 require.NoError(t, err) 2229 require.Len(t, r.Order, 1, "should have 1 posts") 2230 } 2231 2232 func testPostStoreGetPostsCreatedAt(t *testing.T, ss store.Store) { 2233 createTime := model.GetMillis() + 1 2234 2235 o0 := &model.Post{} 2236 o0.ChannelId = model.NewId() 2237 o0.UserId = model.NewId() 2238 o0.Message = "zz" + model.NewId() + "b" 2239 o0.CreateAt = createTime 2240 o0, err := ss.Post().Save(o0) 2241 require.NoError(t, err) 2242 2243 o1 := &model.Post{} 2244 o1.ChannelId = o0.ChannelId 2245 o1.UserId = model.NewId() 2246 o1.Message = "zz" + model.NewId() + "b" 2247 o1.CreateAt = createTime 2248 o1, err = ss.Post().Save(o1) 2249 require.NoError(t, err) 2250 2251 o2 := &model.Post{} 2252 o2.ChannelId = o1.ChannelId 2253 o2.UserId = model.NewId() 2254 o2.Message = "zz" + model.NewId() + "b" 2255 o2.ParentId = o1.Id 2256 o2.RootId = o1.Id 2257 o2.CreateAt = createTime + 1 2258 _, err = ss.Post().Save(o2) 2259 require.NoError(t, err) 2260 2261 o3 := &model.Post{} 2262 o3.ChannelId = model.NewId() 2263 o3.UserId = model.NewId() 2264 o3.Message = "zz" + model.NewId() + "b" 2265 o3.CreateAt = createTime 2266 _, err = ss.Post().Save(o3) 2267 require.NoError(t, err) 2268 2269 r1, _ := ss.Post().GetPostsCreatedAt(o1.ChannelId, createTime) 2270 assert.Equal(t, 2, len(r1)) 2271 } 2272 2273 func testPostStoreOverwriteMultiple(t *testing.T, ss store.Store) { 2274 o1 := &model.Post{} 2275 o1.ChannelId = model.NewId() 2276 o1.UserId = model.NewId() 2277 o1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" 2278 o1, err := ss.Post().Save(o1) 2279 require.NoError(t, err) 2280 2281 o2 := &model.Post{} 2282 o2.ChannelId = o1.ChannelId 2283 o2.UserId = model.NewId() 2284 o2.Message = "zz" + model.NewId() + "CCCCCCCCC" 2285 o2.ParentId = o1.Id 2286 o2.RootId = o1.Id 2287 o2, err = ss.Post().Save(o2) 2288 require.NoError(t, err) 2289 2290 o3 := &model.Post{} 2291 o3.ChannelId = o1.ChannelId 2292 o3.UserId = model.NewId() 2293 o3.Message = "zz" + model.NewId() + "QQQQQQQQQQ" 2294 o3, err = ss.Post().Save(o3) 2295 require.NoError(t, err) 2296 2297 o4, err := ss.Post().Save(&model.Post{ 2298 ChannelId: model.NewId(), 2299 UserId: model.NewId(), 2300 Message: model.NewId(), 2301 Filenames: []string{"test"}, 2302 }) 2303 require.NoError(t, err) 2304 2305 o5, err := ss.Post().Save(&model.Post{ 2306 ChannelId: model.NewId(), 2307 UserId: model.NewId(), 2308 Message: model.NewId(), 2309 Filenames: []string{"test2", "test3"}, 2310 }) 2311 require.NoError(t, err) 2312 2313 r1, err := ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 2314 require.NoError(t, err) 2315 ro1 := r1.Posts[o1.Id] 2316 2317 r2, err := ss.Post().Get(context.Background(), o2.Id, false, false, false, "") 2318 require.NoError(t, err) 2319 ro2 := r2.Posts[o2.Id] 2320 2321 r3, err := ss.Post().Get(context.Background(), o3.Id, false, false, false, "") 2322 require.NoError(t, err) 2323 ro3 := r3.Posts[o3.Id] 2324 2325 r4, err := ss.Post().Get(context.Background(), o4.Id, false, false, false, "") 2326 require.NoError(t, err) 2327 ro4 := r4.Posts[o4.Id] 2328 2329 r5, err := ss.Post().Get(context.Background(), o5.Id, false, false, false, "") 2330 require.NoError(t, err) 2331 ro5 := r5.Posts[o5.Id] 2332 2333 require.Equal(t, ro1.Message, o1.Message, "Failed to save/get") 2334 require.Equal(t, ro2.Message, o2.Message, "Failed to save/get") 2335 require.Equal(t, ro3.Message, o3.Message, "Failed to save/get") 2336 require.Equal(t, ro4.Message, o4.Message, "Failed to save/get") 2337 require.Equal(t, ro4.Filenames, o4.Filenames, "Failed to save/get") 2338 require.Equal(t, ro5.Message, o5.Message, "Failed to save/get") 2339 require.Equal(t, ro5.Filenames, o5.Filenames, "Failed to save/get") 2340 2341 t.Run("overwrite changing message", func(t *testing.T) { 2342 o1a := ro1.Clone() 2343 o1a.Message = ro1.Message + "BBBBBBBBBB" 2344 2345 o2a := ro2.Clone() 2346 o2a.Message = ro2.Message + "DDDDDDD" 2347 2348 o3a := ro3.Clone() 2349 o3a.Message = ro3.Message + "WWWWWWW" 2350 2351 _, errIdx, err := ss.Post().OverwriteMultiple([]*model.Post{o1a, o2a, o3a}) 2352 require.NoError(t, err) 2353 require.Equal(t, -1, errIdx) 2354 2355 r1, nErr := ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 2356 require.NoError(t, nErr) 2357 ro1a := r1.Posts[o1.Id] 2358 2359 r2, nErr = ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 2360 require.NoError(t, nErr) 2361 ro2a := r2.Posts[o2.Id] 2362 2363 r3, nErr = ss.Post().Get(context.Background(), o3.Id, false, false, false, "") 2364 require.NoError(t, nErr) 2365 ro3a := r3.Posts[o3.Id] 2366 2367 assert.Equal(t, ro1a.Message, o1a.Message, "Failed to overwrite/get") 2368 assert.Equal(t, ro2a.Message, o2a.Message, "Failed to overwrite/get") 2369 assert.Equal(t, ro3a.Message, o3a.Message, "Failed to overwrite/get") 2370 }) 2371 2372 t.Run("overwrite clearing filenames", func(t *testing.T) { 2373 o4a := ro4.Clone() 2374 o4a.Filenames = []string{} 2375 o4a.FileIds = []string{model.NewId()} 2376 2377 o5a := ro5.Clone() 2378 o5a.Filenames = []string{} 2379 o5a.FileIds = []string{} 2380 2381 _, errIdx, err := ss.Post().OverwriteMultiple([]*model.Post{o4a, o5a}) 2382 require.NoError(t, err) 2383 require.Equal(t, -1, errIdx) 2384 2385 r4, nErr := ss.Post().Get(context.Background(), o4.Id, false, false, false, "") 2386 require.NoError(t, nErr) 2387 ro4a := r4.Posts[o4.Id] 2388 2389 r5, nErr = ss.Post().Get(context.Background(), o5.Id, false, false, false, "") 2390 require.NoError(t, nErr) 2391 ro5a := r5.Posts[o5.Id] 2392 2393 require.Empty(t, ro4a.Filenames, "Failed to clear Filenames") 2394 require.Len(t, ro4a.FileIds, 1, "Failed to set FileIds") 2395 require.Empty(t, ro5a.Filenames, "Failed to clear Filenames") 2396 require.Empty(t, ro5a.FileIds, "Failed to set FileIds") 2397 }) 2398 } 2399 2400 func testPostStoreOverwrite(t *testing.T, ss store.Store) { 2401 o1 := &model.Post{} 2402 o1.ChannelId = model.NewId() 2403 o1.UserId = model.NewId() 2404 o1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" 2405 o1, err := ss.Post().Save(o1) 2406 require.NoError(t, err) 2407 2408 o2 := &model.Post{} 2409 o2.ChannelId = o1.ChannelId 2410 o2.UserId = model.NewId() 2411 o2.Message = "zz" + model.NewId() + "CCCCCCCCC" 2412 o2.ParentId = o1.Id 2413 o2.RootId = o1.Id 2414 o2, err = ss.Post().Save(o2) 2415 require.NoError(t, err) 2416 2417 o3 := &model.Post{} 2418 o3.ChannelId = o1.ChannelId 2419 o3.UserId = model.NewId() 2420 o3.Message = "zz" + model.NewId() + "QQQQQQQQQQ" 2421 o3, err = ss.Post().Save(o3) 2422 require.NoError(t, err) 2423 2424 o4, err := ss.Post().Save(&model.Post{ 2425 ChannelId: model.NewId(), 2426 UserId: model.NewId(), 2427 Message: model.NewId(), 2428 Filenames: []string{"test"}, 2429 }) 2430 require.NoError(t, err) 2431 2432 r1, err := ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 2433 require.NoError(t, err) 2434 ro1 := r1.Posts[o1.Id] 2435 2436 r2, err := ss.Post().Get(context.Background(), o2.Id, false, false, false, "") 2437 require.NoError(t, err) 2438 ro2 := r2.Posts[o2.Id] 2439 2440 r3, err := ss.Post().Get(context.Background(), o3.Id, false, false, false, "") 2441 require.NoError(t, err) 2442 ro3 := r3.Posts[o3.Id] 2443 2444 r4, err := ss.Post().Get(context.Background(), o4.Id, false, false, false, "") 2445 require.NoError(t, err) 2446 ro4 := r4.Posts[o4.Id] 2447 2448 require.Equal(t, ro1.Message, o1.Message, "Failed to save/get") 2449 require.Equal(t, ro2.Message, o2.Message, "Failed to save/get") 2450 require.Equal(t, ro3.Message, o3.Message, "Failed to save/get") 2451 require.Equal(t, ro4.Message, o4.Message, "Failed to save/get") 2452 2453 t.Run("overwrite changing message", func(t *testing.T) { 2454 o1a := ro1.Clone() 2455 o1a.Message = ro1.Message + "BBBBBBBBBB" 2456 _, err = ss.Post().Overwrite(o1a) 2457 require.NoError(t, err) 2458 2459 o2a := ro2.Clone() 2460 o2a.Message = ro2.Message + "DDDDDDD" 2461 _, err = ss.Post().Overwrite(o2a) 2462 require.NoError(t, err) 2463 2464 o3a := ro3.Clone() 2465 o3a.Message = ro3.Message + "WWWWWWW" 2466 _, err = ss.Post().Overwrite(o3a) 2467 require.NoError(t, err) 2468 2469 r1, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 2470 require.NoError(t, err) 2471 ro1a := r1.Posts[o1.Id] 2472 2473 r2, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 2474 require.NoError(t, err) 2475 ro2a := r2.Posts[o2.Id] 2476 2477 r3, err = ss.Post().Get(context.Background(), o3.Id, false, false, false, "") 2478 require.NoError(t, err) 2479 ro3a := r3.Posts[o3.Id] 2480 2481 assert.Equal(t, ro1a.Message, o1a.Message, "Failed to overwrite/get") 2482 assert.Equal(t, ro2a.Message, o2a.Message, "Failed to overwrite/get") 2483 assert.Equal(t, ro3a.Message, o3a.Message, "Failed to overwrite/get") 2484 }) 2485 2486 t.Run("overwrite clearing filenames", func(t *testing.T) { 2487 o4a := ro4.Clone() 2488 o4a.Filenames = []string{} 2489 o4a.FileIds = []string{model.NewId()} 2490 _, err = ss.Post().Overwrite(o4a) 2491 require.NoError(t, err) 2492 2493 r4, err = ss.Post().Get(context.Background(), o4.Id, false, false, false, "") 2494 require.NoError(t, err) 2495 2496 ro4a := r4.Posts[o4.Id] 2497 require.Empty(t, ro4a.Filenames, "Failed to clear Filenames") 2498 require.Len(t, ro4a.FileIds, 1, "Failed to set FileIds") 2499 }) 2500 } 2501 2502 func testPostStoreGetPostsByIds(t *testing.T, ss store.Store) { 2503 o1 := &model.Post{} 2504 o1.ChannelId = model.NewId() 2505 o1.UserId = model.NewId() 2506 o1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" 2507 o1, err := ss.Post().Save(o1) 2508 require.NoError(t, err) 2509 2510 o2 := &model.Post{} 2511 o2.ChannelId = o1.ChannelId 2512 o2.UserId = model.NewId() 2513 o2.Message = "zz" + model.NewId() + "CCCCCCCCC" 2514 o2, err = ss.Post().Save(o2) 2515 require.NoError(t, err) 2516 2517 o3 := &model.Post{} 2518 o3.ChannelId = o1.ChannelId 2519 o3.UserId = model.NewId() 2520 o3.Message = "zz" + model.NewId() + "QQQQQQQQQQ" 2521 o3, err = ss.Post().Save(o3) 2522 require.NoError(t, err) 2523 2524 r1, err := ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 2525 require.NoError(t, err) 2526 ro1 := r1.Posts[o1.Id] 2527 2528 r2, err := ss.Post().Get(context.Background(), o2.Id, false, false, false, "") 2529 require.NoError(t, err) 2530 ro2 := r2.Posts[o2.Id] 2531 2532 r3, err := ss.Post().Get(context.Background(), o3.Id, false, false, false, "") 2533 require.NoError(t, err) 2534 ro3 := r3.Posts[o3.Id] 2535 2536 postIds := []string{ 2537 ro1.Id, 2538 ro2.Id, 2539 ro3.Id, 2540 } 2541 2542 posts, err := ss.Post().GetPostsByIds(postIds) 2543 require.NoError(t, err) 2544 require.Len(t, posts, 3, "Expected 3 posts in results. Got %v", len(posts)) 2545 2546 err = ss.Post().Delete(ro1.Id, model.GetMillis(), "") 2547 require.NoError(t, err) 2548 2549 posts, err = ss.Post().GetPostsByIds(postIds) 2550 require.NoError(t, err) 2551 require.Len(t, posts, 3, "Expected 3 posts in results. Got %v", len(posts)) 2552 } 2553 2554 func testPostStoreGetPostsBatchForIndexing(t *testing.T, ss store.Store) { 2555 c1 := &model.Channel{} 2556 c1.TeamId = model.NewId() 2557 c1.DisplayName = "Channel1" 2558 c1.Name = "zz" + model.NewId() + "b" 2559 c1.Type = model.CHANNEL_OPEN 2560 c1, _ = ss.Channel().Save(c1, -1) 2561 2562 c2 := &model.Channel{} 2563 c2.TeamId = model.NewId() 2564 c2.DisplayName = "Channel2" 2565 c2.Name = "zz" + model.NewId() + "b" 2566 c2.Type = model.CHANNEL_OPEN 2567 c2, _ = ss.Channel().Save(c2, -1) 2568 2569 o1 := &model.Post{} 2570 o1.ChannelId = c1.Id 2571 o1.UserId = model.NewId() 2572 o1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" 2573 o1, err := ss.Post().Save(o1) 2574 require.NoError(t, err) 2575 2576 o2 := &model.Post{} 2577 o2.ChannelId = c2.Id 2578 o2.UserId = model.NewId() 2579 o2.Message = "zz" + model.NewId() + "CCCCCCCCC" 2580 o2, err = ss.Post().Save(o2) 2581 require.NoError(t, err) 2582 2583 o3 := &model.Post{} 2584 o3.ChannelId = c1.Id 2585 o3.UserId = model.NewId() 2586 o3.ParentId = o1.Id 2587 o3.RootId = o1.Id 2588 o3.Message = "zz" + model.NewId() + "QQQQQQQQQQ" 2589 o3, err = ss.Post().Save(o3) 2590 require.NoError(t, err) 2591 2592 r, err := ss.Post().GetPostsBatchForIndexing(o1.CreateAt, model.GetMillis()+100000, 100) 2593 require.NoError(t, err) 2594 require.Len(t, r, 3, "Expected 3 posts in results. Got %v", len(r)) 2595 for _, p := range r { 2596 if p.Id == o1.Id { 2597 require.Equal(t, p.TeamId, c1.TeamId, "Unexpected team ID") 2598 require.Nil(t, p.ParentCreateAt, "Unexpected parent create at") 2599 } else if p.Id == o2.Id { 2600 require.Equal(t, p.TeamId, c2.TeamId, "Unexpected team ID") 2601 require.Nil(t, p.ParentCreateAt, "Unexpected parent create at") 2602 } else if p.Id == o3.Id { 2603 require.Equal(t, p.TeamId, c1.TeamId, "Unexpected team ID") 2604 require.Equal(t, *p.ParentCreateAt, o1.CreateAt, "Unexpected parent create at") 2605 } else { 2606 require.Fail(t, "unexpected post returned") 2607 } 2608 } 2609 } 2610 2611 func testPostStorePermanentDeleteBatch(t *testing.T, ss store.Store) { 2612 team, err := ss.Team().Save(&model.Team{ 2613 DisplayName: "DisplayName", 2614 Name: "team" + model.NewId(), 2615 Email: MakeEmail(), 2616 Type: model.TEAM_OPEN, 2617 }) 2618 require.NoError(t, err) 2619 channel, err := ss.Channel().Save(&model.Channel{ 2620 TeamId: team.Id, 2621 DisplayName: "DisplayName", 2622 Name: "channel" + model.NewId(), 2623 Type: model.CHANNEL_OPEN, 2624 }, -1) 2625 require.NoError(t, err) 2626 2627 o1 := &model.Post{} 2628 o1.ChannelId = channel.Id 2629 o1.UserId = model.NewId() 2630 o1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" 2631 o1.CreateAt = 1000 2632 o1, err = ss.Post().Save(o1) 2633 require.NoError(t, err) 2634 2635 o2 := &model.Post{} 2636 o2.ChannelId = channel.Id 2637 o2.UserId = model.NewId() 2638 o2.Message = "zz" + model.NewId() + "AAAAAAAAAAA" 2639 o2.CreateAt = 1000 2640 o2, err = ss.Post().Save(o2) 2641 require.NoError(t, err) 2642 2643 o3 := &model.Post{} 2644 o3.ChannelId = channel.Id 2645 o3.UserId = model.NewId() 2646 o3.Message = "zz" + model.NewId() + "AAAAAAAAAAA" 2647 o3.CreateAt = 100000 2648 o3, err = ss.Post().Save(o3) 2649 require.NoError(t, err) 2650 2651 _, _, err = ss.Post().PermanentDeleteBatchForRetentionPolicies(0, 2000, 1000, model.RetentionPolicyCursor{}) 2652 require.NoError(t, err) 2653 2654 _, err = ss.Post().Get(context.Background(), o1.Id, false, false, false, "") 2655 require.Error(t, err, "Should have not found post 1 after purge") 2656 2657 _, err = ss.Post().Get(context.Background(), o2.Id, false, false, false, "") 2658 require.Error(t, err, "Should have not found post 2 after purge") 2659 2660 _, err = ss.Post().Get(context.Background(), o3.Id, false, false, false, "") 2661 require.NoError(t, err, "Should have found post 3 after purge") 2662 2663 t.Run("with pagination", func(t *testing.T) { 2664 for i := 0; i < 3; i++ { 2665 _, err = ss.Post().Save(&model.Post{ 2666 ChannelId: channel.Id, 2667 UserId: model.NewId(), 2668 Message: "message", 2669 CreateAt: 1, 2670 }) 2671 require.NoError(t, err) 2672 } 2673 cursor := model.RetentionPolicyCursor{} 2674 2675 deleted, cursor, err := ss.Post().PermanentDeleteBatchForRetentionPolicies(0, 2, 2, cursor) 2676 require.NoError(t, err) 2677 require.Equal(t, int64(2), deleted) 2678 2679 deleted, _, err = ss.Post().PermanentDeleteBatchForRetentionPolicies(0, 2, 2, cursor) 2680 require.NoError(t, err) 2681 require.Equal(t, int64(1), deleted) 2682 }) 2683 2684 t.Run("with data retention policies", func(t *testing.T) { 2685 channelPolicy, err2 := ss.RetentionPolicy().Save(&model.RetentionPolicyWithTeamAndChannelIDs{ 2686 RetentionPolicy: model.RetentionPolicy{ 2687 DisplayName: "DisplayName", 2688 PostDuration: model.NewInt64(30), 2689 }, 2690 ChannelIDs: []string{channel.Id}, 2691 }) 2692 require.NoError(t, err2) 2693 post := &model.Post{ 2694 ChannelId: channel.Id, 2695 UserId: model.NewId(), 2696 Message: "message", 2697 CreateAt: 1, 2698 } 2699 post, err2 = ss.Post().Save(post) 2700 require.NoError(t, err2) 2701 2702 _, _, err2 = ss.Post().PermanentDeleteBatchForRetentionPolicies(0, 2000, 1000, model.RetentionPolicyCursor{}) 2703 require.NoError(t, err2) 2704 _, err2 = ss.Post().Get(context.Background(), post.Id, false, false, false, "") 2705 require.NoError(t, err2, "global policy should have been ignored due to granular policy") 2706 2707 nowMillis := post.CreateAt + *channelPolicy.PostDuration*24*60*60*1000 + 1 2708 _, _, err2 = ss.Post().PermanentDeleteBatchForRetentionPolicies(nowMillis, 0, 1000, model.RetentionPolicyCursor{}) 2709 require.NoError(t, err2) 2710 _, err2 = ss.Post().Get(context.Background(), post.Id, false, false, false, "") 2711 require.Error(t, err2, "post should have been deleted by channel policy") 2712 2713 // Create a team policy which is stricter than the channel policy 2714 teamPolicy, err2 := ss.RetentionPolicy().Save(&model.RetentionPolicyWithTeamAndChannelIDs{ 2715 RetentionPolicy: model.RetentionPolicy{ 2716 DisplayName: "DisplayName", 2717 PostDuration: model.NewInt64(20), 2718 }, 2719 TeamIDs: []string{team.Id}, 2720 }) 2721 require.NoError(t, err2) 2722 post.Id = "" 2723 post, err2 = ss.Post().Save(post) 2724 require.NoError(t, err2) 2725 2726 nowMillis = post.CreateAt + *teamPolicy.PostDuration*24*60*60*1000 + 1 2727 _, _, err2 = ss.Post().PermanentDeleteBatchForRetentionPolicies(nowMillis, 0, 1000, model.RetentionPolicyCursor{}) 2728 require.NoError(t, err2) 2729 _, err2 = ss.Post().Get(context.Background(), post.Id, false, false, false, "") 2730 require.NoError(t, err2, "channel policy should have overridden team policy") 2731 2732 // Delete channel policy and re-run team policy 2733 err2 = ss.RetentionPolicy().RemoveChannels(channelPolicy.ID, []string{channel.Id}) 2734 require.NoError(t, err2) 2735 2736 err2 = ss.RetentionPolicy().Delete(channelPolicy.ID) 2737 require.NoError(t, err2) 2738 2739 _, _, err2 = ss.Post().PermanentDeleteBatchForRetentionPolicies(nowMillis, 0, 1000, model.RetentionPolicyCursor{}) 2740 require.NoError(t, err2) 2741 _, err2 = ss.Post().Get(context.Background(), post.Id, false, false, false, "") 2742 require.Error(t, err2, "post should have been deleted by team policy") 2743 2744 err2 = ss.RetentionPolicy().RemoveTeams(teamPolicy.ID, []string{team.Id}) 2745 require.NoError(t, err2) 2746 2747 err2 = ss.RetentionPolicy().Delete(teamPolicy.ID) 2748 require.NoError(t, err2) 2749 }) 2750 2751 t.Run("with channel, team and global policies", func(t *testing.T) { 2752 c1 := &model.Channel{} 2753 c1.TeamId = model.NewId() 2754 c1.DisplayName = "Channel1" 2755 c1.Name = "zz" + model.NewId() + "b" 2756 c1.Type = model.CHANNEL_OPEN 2757 c1, _ = ss.Channel().Save(c1, -1) 2758 2759 c2 := &model.Channel{} 2760 c2.TeamId = model.NewId() 2761 c2.DisplayName = "Channel2" 2762 c2.Name = "zz" + model.NewId() + "b" 2763 c2.Type = model.CHANNEL_OPEN 2764 c2, _ = ss.Channel().Save(c2, -1) 2765 2766 channelPolicy, err2 := ss.RetentionPolicy().Save(&model.RetentionPolicyWithTeamAndChannelIDs{ 2767 RetentionPolicy: model.RetentionPolicy{ 2768 DisplayName: "DisplayName", 2769 PostDuration: model.NewInt64(30), 2770 }, 2771 ChannelIDs: []string{c1.Id}, 2772 }) 2773 require.NoError(t, err2) 2774 defer ss.RetentionPolicy().Delete(channelPolicy.ID) 2775 teamPolicy, err2 := ss.RetentionPolicy().Save(&model.RetentionPolicyWithTeamAndChannelIDs{ 2776 RetentionPolicy: model.RetentionPolicy{ 2777 DisplayName: "DisplayName", 2778 PostDuration: model.NewInt64(30), 2779 }, 2780 TeamIDs: []string{team.Id}, 2781 }) 2782 require.NoError(t, err2) 2783 defer ss.RetentionPolicy().Delete(teamPolicy.ID) 2784 2785 // This one should be deleted by the channel policy 2786 _, err2 = ss.Post().Save(&model.Post{ 2787 ChannelId: c1.Id, 2788 UserId: model.NewId(), 2789 Message: "message", 2790 CreateAt: 1, 2791 }) 2792 require.NoError(t, err2) 2793 // This one, by the team policy 2794 _, err2 = ss.Post().Save(&model.Post{ 2795 ChannelId: channel.Id, 2796 UserId: model.NewId(), 2797 Message: "message", 2798 CreateAt: 1, 2799 }) 2800 require.NoError(t, err2) 2801 // This one, by the global policy 2802 _, err2 = ss.Post().Save(&model.Post{ 2803 ChannelId: c2.Id, 2804 UserId: model.NewId(), 2805 Message: "message", 2806 CreateAt: 1, 2807 }) 2808 require.NoError(t, err2) 2809 2810 nowMillis := int64(1 + 30*24*60*60*1000 + 1) 2811 deleted, _, err2 := ss.Post().PermanentDeleteBatchForRetentionPolicies(nowMillis, 2, 1000, model.RetentionPolicyCursor{}) 2812 require.NoError(t, err2) 2813 require.Equal(t, int64(3), deleted) 2814 }) 2815 } 2816 2817 func testPostStoreGetOldest(t *testing.T, ss store.Store) { 2818 o0 := &model.Post{} 2819 o0.ChannelId = model.NewId() 2820 o0.UserId = model.NewId() 2821 o0.Message = "zz" + model.NewId() + "b" 2822 o0.CreateAt = 3 2823 o0, err := ss.Post().Save(o0) 2824 require.NoError(t, err) 2825 2826 o1 := &model.Post{} 2827 o1.ChannelId = o0.Id 2828 o1.UserId = model.NewId() 2829 o1.Message = "zz" + model.NewId() + "b" 2830 o1.CreateAt = 2 2831 o1, err = ss.Post().Save(o1) 2832 require.NoError(t, err) 2833 2834 o2 := &model.Post{} 2835 o2.ChannelId = o1.ChannelId 2836 o2.UserId = model.NewId() 2837 o2.Message = "zz" + model.NewId() + "b" 2838 o2.CreateAt = 1 2839 o2, err = ss.Post().Save(o2) 2840 require.NoError(t, err) 2841 2842 r1, err := ss.Post().GetOldest() 2843 2844 require.NoError(t, err) 2845 assert.EqualValues(t, o2.Id, r1.Id) 2846 } 2847 2848 func testGetMaxPostSize(t *testing.T, ss store.Store) { 2849 assert.Equal(t, model.POST_MESSAGE_MAX_RUNES_V2, ss.Post().GetMaxPostSize()) 2850 assert.Equal(t, model.POST_MESSAGE_MAX_RUNES_V2, ss.Post().GetMaxPostSize()) 2851 } 2852 2853 func testPostStoreGetParentsForExportAfter(t *testing.T, ss store.Store) { 2854 t1 := model.Team{} 2855 t1.DisplayName = "Name" 2856 t1.Name = "zz" + model.NewId() 2857 t1.Email = MakeEmail() 2858 t1.Type = model.TEAM_OPEN 2859 _, err := ss.Team().Save(&t1) 2860 require.NoError(t, err) 2861 2862 c1 := model.Channel{} 2863 c1.TeamId = t1.Id 2864 c1.DisplayName = "Channel1" 2865 c1.Name = "zz" + model.NewId() + "b" 2866 c1.Type = model.CHANNEL_OPEN 2867 _, nErr := ss.Channel().Save(&c1, -1) 2868 require.NoError(t, nErr) 2869 2870 u1 := model.User{} 2871 u1.Username = model.NewId() 2872 u1.Email = MakeEmail() 2873 u1.Nickname = model.NewId() 2874 _, err = ss.User().Save(&u1) 2875 require.NoError(t, err) 2876 2877 p1 := &model.Post{} 2878 p1.ChannelId = c1.Id 2879 p1.UserId = u1.Id 2880 p1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" 2881 p1.CreateAt = 1000 2882 p1, nErr = ss.Post().Save(p1) 2883 require.NoError(t, nErr) 2884 2885 posts, err := ss.Post().GetParentsForExportAfter(10000, strings.Repeat("0", 26)) 2886 assert.NoError(t, err) 2887 2888 found := false 2889 for _, p := range posts { 2890 if p.Id == p1.Id { 2891 found = true 2892 assert.Equal(t, p.Id, p1.Id) 2893 assert.Equal(t, p.Message, p1.Message) 2894 assert.Equal(t, p.Username, u1.Username) 2895 assert.Equal(t, p.TeamName, t1.Name) 2896 assert.Equal(t, p.ChannelName, c1.Name) 2897 } 2898 } 2899 assert.True(t, found) 2900 } 2901 2902 func testPostStoreGetRepliesForExport(t *testing.T, ss store.Store) { 2903 t1 := model.Team{} 2904 t1.DisplayName = "Name" 2905 t1.Name = "zz" + model.NewId() 2906 t1.Email = MakeEmail() 2907 t1.Type = model.TEAM_OPEN 2908 _, err := ss.Team().Save(&t1) 2909 require.NoError(t, err) 2910 2911 c1 := model.Channel{} 2912 c1.TeamId = t1.Id 2913 c1.DisplayName = "Channel1" 2914 c1.Name = "zz" + model.NewId() + "b" 2915 c1.Type = model.CHANNEL_OPEN 2916 _, nErr := ss.Channel().Save(&c1, -1) 2917 require.NoError(t, nErr) 2918 2919 u1 := model.User{} 2920 u1.Email = MakeEmail() 2921 u1.Nickname = model.NewId() 2922 _, err = ss.User().Save(&u1) 2923 require.NoError(t, err) 2924 2925 p1 := &model.Post{} 2926 p1.ChannelId = c1.Id 2927 p1.UserId = u1.Id 2928 p1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" 2929 p1.CreateAt = 1000 2930 p1, nErr = ss.Post().Save(p1) 2931 require.NoError(t, nErr) 2932 2933 p2 := &model.Post{} 2934 p2.ChannelId = c1.Id 2935 p2.UserId = u1.Id 2936 p2.Message = "zz" + model.NewId() + "AAAAAAAAAAA" 2937 p2.CreateAt = 1001 2938 p2.ParentId = p1.Id 2939 p2.RootId = p1.Id 2940 p2, nErr = ss.Post().Save(p2) 2941 require.NoError(t, nErr) 2942 2943 r1, err := ss.Post().GetRepliesForExport(p1.Id) 2944 assert.NoError(t, err) 2945 2946 assert.Len(t, r1, 1) 2947 2948 reply1 := r1[0] 2949 assert.Equal(t, reply1.Id, p2.Id) 2950 assert.Equal(t, reply1.Message, p2.Message) 2951 assert.Equal(t, reply1.Username, u1.Username) 2952 2953 // Checking whether replies by deleted user are exported 2954 u1.DeleteAt = 1002 2955 _, err = ss.User().Update(&u1, false) 2956 require.NoError(t, err) 2957 2958 r1, err = ss.Post().GetRepliesForExport(p1.Id) 2959 assert.NoError(t, err) 2960 2961 assert.Len(t, r1, 1) 2962 2963 reply1 = r1[0] 2964 assert.Equal(t, reply1.Id, p2.Id) 2965 assert.Equal(t, reply1.Message, p2.Message) 2966 assert.Equal(t, reply1.Username, u1.Username) 2967 2968 } 2969 2970 func testPostStoreGetDirectPostParentsForExportAfter(t *testing.T, ss store.Store, s SqlStore) { 2971 teamId := model.NewId() 2972 2973 o1 := model.Channel{} 2974 o1.TeamId = teamId 2975 o1.DisplayName = "Name" 2976 o1.Name = "zz" + model.NewId() + "b" 2977 o1.Type = model.CHANNEL_DIRECT 2978 2979 u1 := &model.User{} 2980 u1.Email = MakeEmail() 2981 u1.Nickname = model.NewId() 2982 _, err := ss.User().Save(u1) 2983 require.NoError(t, err) 2984 _, nErr := ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id}, -1) 2985 require.NoError(t, nErr) 2986 2987 u2 := &model.User{} 2988 u2.Email = MakeEmail() 2989 u2.Nickname = model.NewId() 2990 _, err = ss.User().Save(u2) 2991 require.NoError(t, err) 2992 _, nErr = ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id}, -1) 2993 require.NoError(t, nErr) 2994 2995 m1 := model.ChannelMember{} 2996 m1.ChannelId = o1.Id 2997 m1.UserId = u1.Id 2998 m1.NotifyProps = model.GetDefaultChannelNotifyProps() 2999 3000 m2 := model.ChannelMember{} 3001 m2.ChannelId = o1.Id 3002 m2.UserId = u2.Id 3003 m2.NotifyProps = model.GetDefaultChannelNotifyProps() 3004 3005 ss.Channel().SaveDirectChannel(&o1, &m1, &m2) 3006 3007 p1 := &model.Post{} 3008 p1.ChannelId = o1.Id 3009 p1.UserId = u1.Id 3010 p1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" 3011 p1.CreateAt = 1000 3012 p1, nErr = ss.Post().Save(p1) 3013 require.NoError(t, nErr) 3014 3015 r1, nErr := ss.Post().GetDirectPostParentsForExportAfter(10000, strings.Repeat("0", 26)) 3016 assert.NoError(t, nErr) 3017 3018 assert.Equal(t, p1.Message, r1[0].Message) 3019 3020 // Manually truncate Channels table until testlib can handle cleanups 3021 s.GetMaster().Exec("TRUNCATE Channels") 3022 } 3023 3024 func testPostStoreGetDirectPostParentsForExportAfterDeleted(t *testing.T, ss store.Store, s SqlStore) { 3025 teamId := model.NewId() 3026 3027 o1 := model.Channel{} 3028 o1.TeamId = teamId 3029 o1.DisplayName = "Name" 3030 o1.Name = "zz" + model.NewId() + "b" 3031 o1.Type = model.CHANNEL_DIRECT 3032 3033 u1 := &model.User{} 3034 u1.DeleteAt = 1 3035 u1.Email = MakeEmail() 3036 u1.Nickname = model.NewId() 3037 _, err := ss.User().Save(u1) 3038 require.NoError(t, err) 3039 _, nErr := ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id}, -1) 3040 require.NoError(t, nErr) 3041 3042 u2 := &model.User{} 3043 u2.DeleteAt = 1 3044 u2.Email = MakeEmail() 3045 u2.Nickname = model.NewId() 3046 _, err = ss.User().Save(u2) 3047 require.NoError(t, err) 3048 _, nErr = ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id}, -1) 3049 require.NoError(t, nErr) 3050 3051 m1 := model.ChannelMember{} 3052 m1.ChannelId = o1.Id 3053 m1.UserId = u1.Id 3054 m1.NotifyProps = model.GetDefaultChannelNotifyProps() 3055 3056 m2 := model.ChannelMember{} 3057 m2.ChannelId = o1.Id 3058 m2.UserId = u2.Id 3059 m2.NotifyProps = model.GetDefaultChannelNotifyProps() 3060 3061 ss.Channel().SaveDirectChannel(&o1, &m1, &m2) 3062 3063 o1.DeleteAt = 1 3064 nErr = ss.Channel().SetDeleteAt(o1.Id, 1, 1) 3065 assert.NoError(t, nErr) 3066 3067 p1 := &model.Post{} 3068 p1.ChannelId = o1.Id 3069 p1.UserId = u1.Id 3070 p1.Message = "zz" + model.NewId() + "BBBBBBBBBBBB" 3071 p1.CreateAt = 1000 3072 p1, nErr = ss.Post().Save(p1) 3073 require.NoError(t, nErr) 3074 3075 o1a := p1.Clone() 3076 o1a.DeleteAt = 1 3077 o1a.Message = p1.Message + "BBBBBBBBBB" 3078 _, nErr = ss.Post().Update(o1a, p1) 3079 require.NoError(t, nErr) 3080 3081 r1, nErr := ss.Post().GetDirectPostParentsForExportAfter(10000, strings.Repeat("0", 26)) 3082 assert.NoError(t, nErr) 3083 3084 assert.Equal(t, 0, len(r1)) 3085 3086 // Manually truncate Channels table until testlib can handle cleanups 3087 s.GetMaster().Exec("TRUNCATE Channels") 3088 } 3089 3090 func testPostStoreGetDirectPostParentsForExportAfterBatched(t *testing.T, ss store.Store, s SqlStore) { 3091 teamId := model.NewId() 3092 3093 o1 := model.Channel{} 3094 o1.TeamId = teamId 3095 o1.DisplayName = "Name" 3096 o1.Name = "zz" + model.NewId() + "b" 3097 o1.Type = model.CHANNEL_DIRECT 3098 3099 var postIds []string 3100 for i := 0; i < 150; i++ { 3101 u1 := &model.User{} 3102 u1.Email = MakeEmail() 3103 u1.Nickname = model.NewId() 3104 _, err := ss.User().Save(u1) 3105 require.NoError(t, err) 3106 _, nErr := ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id}, -1) 3107 require.NoError(t, nErr) 3108 3109 u2 := &model.User{} 3110 u2.Email = MakeEmail() 3111 u2.Nickname = model.NewId() 3112 _, err = ss.User().Save(u2) 3113 require.NoError(t, err) 3114 _, nErr = ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id}, -1) 3115 require.NoError(t, nErr) 3116 3117 m1 := model.ChannelMember{} 3118 m1.ChannelId = o1.Id 3119 m1.UserId = u1.Id 3120 m1.NotifyProps = model.GetDefaultChannelNotifyProps() 3121 3122 m2 := model.ChannelMember{} 3123 m2.ChannelId = o1.Id 3124 m2.UserId = u2.Id 3125 m2.NotifyProps = model.GetDefaultChannelNotifyProps() 3126 3127 ss.Channel().SaveDirectChannel(&o1, &m1, &m2) 3128 3129 p1 := &model.Post{} 3130 p1.ChannelId = o1.Id 3131 p1.UserId = u1.Id 3132 p1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" 3133 p1.CreateAt = 1000 3134 p1, nErr = ss.Post().Save(p1) 3135 require.NoError(t, nErr) 3136 postIds = append(postIds, p1.Id) 3137 } 3138 sort.Slice(postIds, func(i, j int) bool { return postIds[i] < postIds[j] }) 3139 3140 // Get all posts 3141 r1, err := ss.Post().GetDirectPostParentsForExportAfter(10000, strings.Repeat("0", 26)) 3142 assert.NoError(t, err) 3143 assert.Equal(t, len(postIds), len(r1)) 3144 var exportedPostIds []string 3145 for i := range r1 { 3146 exportedPostIds = append(exportedPostIds, r1[i].Id) 3147 } 3148 sort.Slice(exportedPostIds, func(i, j int) bool { return exportedPostIds[i] < exportedPostIds[j] }) 3149 assert.ElementsMatch(t, postIds, exportedPostIds) 3150 3151 // Get 100 3152 r1, err = ss.Post().GetDirectPostParentsForExportAfter(100, strings.Repeat("0", 26)) 3153 assert.NoError(t, err) 3154 assert.Equal(t, 100, len(r1)) 3155 exportedPostIds = []string{} 3156 for i := range r1 { 3157 exportedPostIds = append(exportedPostIds, r1[i].Id) 3158 } 3159 sort.Slice(exportedPostIds, func(i, j int) bool { return exportedPostIds[i] < exportedPostIds[j] }) 3160 assert.ElementsMatch(t, postIds[:100], exportedPostIds) 3161 3162 // Manually truncate Channels table until testlib can handle cleanups 3163 s.GetMaster().Exec("TRUNCATE Channels") 3164 } 3165 3166 func testHasAutoResponsePostByUserSince(t *testing.T, ss store.Store) { 3167 t.Run("should return posts created after the given time", func(t *testing.T) { 3168 channelId := model.NewId() 3169 userId := model.NewId() 3170 3171 _, err := ss.Post().Save(&model.Post{ 3172 ChannelId: channelId, 3173 UserId: userId, 3174 Message: "message", 3175 }) 3176 require.NoError(t, err) 3177 // We need to sleep because SendAutoResponseIfNecessary 3178 // runs in a goroutine. 3179 time.Sleep(time.Millisecond) 3180 3181 post2, err := ss.Post().Save(&model.Post{ 3182 ChannelId: channelId, 3183 UserId: userId, 3184 Message: "message", 3185 }) 3186 require.NoError(t, err) 3187 time.Sleep(time.Millisecond) 3188 3189 post3, err := ss.Post().Save(&model.Post{ 3190 ChannelId: channelId, 3191 UserId: userId, 3192 Message: "auto response message", 3193 Type: model.POST_AUTO_RESPONDER, 3194 }) 3195 require.NoError(t, err) 3196 time.Sleep(time.Millisecond) 3197 3198 exists, err := ss.Post().HasAutoResponsePostByUserSince(model.GetPostsSinceOptions{ChannelId: channelId, Time: post2.CreateAt}, userId) 3199 require.NoError(t, err) 3200 assert.True(t, exists) 3201 3202 err = ss.Post().Delete(post3.Id, time.Now().Unix(), userId) 3203 require.NoError(t, err) 3204 3205 exists, err = ss.Post().HasAutoResponsePostByUserSince(model.GetPostsSinceOptions{ChannelId: channelId, Time: post2.CreateAt}, userId) 3206 require.NoError(t, err) 3207 assert.False(t, exists) 3208 }) 3209 } 3210 3211 func testGetPostsSinceForSync(t *testing.T, ss store.Store, s SqlStore) { 3212 // create some posts. 3213 channelID := model.NewId() 3214 remoteID := model.NewString(model.NewId()) 3215 first := model.GetMillis() 3216 3217 data := []*model.Post{ 3218 {Id: model.NewId(), ChannelId: channelID, UserId: model.NewId(), Message: "test post 0"}, 3219 {Id: model.NewId(), ChannelId: channelID, UserId: model.NewId(), Message: "test post 1"}, 3220 {Id: model.NewId(), ChannelId: channelID, UserId: model.NewId(), Message: "test post 2"}, 3221 {Id: model.NewId(), ChannelId: channelID, UserId: model.NewId(), Message: "test post 3", RemoteId: remoteID}, 3222 {Id: model.NewId(), ChannelId: channelID, UserId: model.NewId(), Message: "test post 4", RemoteId: remoteID}, 3223 {Id: model.NewId(), ChannelId: channelID, UserId: model.NewId(), Message: "test post 5", RemoteId: remoteID}, 3224 {Id: model.NewId(), ChannelId: channelID, UserId: model.NewId(), Message: "test post 6", RemoteId: remoteID}, 3225 {Id: model.NewId(), ChannelId: channelID, UserId: model.NewId(), Message: "test post 7"}, 3226 {Id: model.NewId(), ChannelId: channelID, UserId: model.NewId(), Message: "test post 8", DeleteAt: model.GetMillis()}, 3227 {Id: model.NewId(), ChannelId: channelID, UserId: model.NewId(), Message: "test post 9", DeleteAt: model.GetMillis()}, 3228 } 3229 3230 for i, p := range data { 3231 p.UpdateAt = first + (int64(i) * 300000) 3232 if p.RemoteId == nil { 3233 p.RemoteId = model.NewString(model.NewId()) 3234 } 3235 _, err := ss.Post().Save(p) 3236 require.NoError(t, err, "couldn't save post") 3237 } 3238 3239 t.Run("Invalid channel id", func(t *testing.T) { 3240 opt := model.GetPostsSinceForSyncOptions{ 3241 ChannelId: model.NewId(), 3242 } 3243 cursor := model.GetPostsSinceForSyncCursor{} 3244 posts, cursorOut, err := ss.Post().GetPostsSinceForSync(opt, cursor, 100) 3245 require.NoError(t, err) 3246 require.Empty(t, posts, "should return zero posts") 3247 require.Equal(t, cursor, cursorOut) 3248 }) 3249 3250 t.Run("Get by channel, exclude remotes, exclude deleted", func(t *testing.T) { 3251 opt := model.GetPostsSinceForSyncOptions{ 3252 ChannelId: channelID, 3253 ExcludeRemoteId: *remoteID, 3254 } 3255 cursor := model.GetPostsSinceForSyncCursor{} 3256 posts, _, err := ss.Post().GetPostsSinceForSync(opt, cursor, 100) 3257 require.NoError(t, err) 3258 3259 require.ElementsMatch(t, getPostIds(data[0:3], data[7]), getPostIds(posts)) 3260 }) 3261 3262 t.Run("Include deleted", func(t *testing.T) { 3263 opt := model.GetPostsSinceForSyncOptions{ 3264 ChannelId: channelID, 3265 IncludeDeleted: true, 3266 } 3267 cursor := model.GetPostsSinceForSyncCursor{} 3268 posts, _, err := ss.Post().GetPostsSinceForSync(opt, cursor, 100) 3269 require.NoError(t, err) 3270 3271 require.ElementsMatch(t, getPostIds(data), getPostIds(posts)) 3272 }) 3273 3274 t.Run("Limit and cursor", func(t *testing.T) { 3275 opt := model.GetPostsSinceForSyncOptions{ 3276 ChannelId: channelID, 3277 } 3278 cursor := model.GetPostsSinceForSyncCursor{} 3279 posts1, cursor, err := ss.Post().GetPostsSinceForSync(opt, cursor, 5) 3280 require.NoError(t, err) 3281 require.Len(t, posts1, 5, "should get 5 posts") 3282 3283 posts2, _, err := ss.Post().GetPostsSinceForSync(opt, cursor, 5) 3284 require.NoError(t, err) 3285 require.Len(t, posts2, 3, "should get 3 posts") 3286 3287 require.ElementsMatch(t, getPostIds(data[0:8]), getPostIds(posts1, posts2...)) 3288 }) 3289 3290 t.Run("UpdateAt collisions", func(t *testing.T) { 3291 // this test requires all the UpdateAt timestamps to be the same. 3292 args := map[string]interface{}{"UpdateAt": model.GetMillis()} 3293 result, err := s.GetMaster().Exec("UPDATE Posts SET UpdateAt = :UpdateAt", args) 3294 require.NoError(t, err) 3295 rows, err := result.RowsAffected() 3296 require.NoError(t, err) 3297 require.Greater(t, rows, int64(0)) 3298 3299 opt := model.GetPostsSinceForSyncOptions{ 3300 ChannelId: channelID, 3301 } 3302 cursor := model.GetPostsSinceForSyncCursor{} 3303 posts1, cursor, err := ss.Post().GetPostsSinceForSync(opt, cursor, 5) 3304 require.NoError(t, err) 3305 require.Len(t, posts1, 5, "should get 5 posts") 3306 3307 posts2, _, err := ss.Post().GetPostsSinceForSync(opt, cursor, 5) 3308 require.NoError(t, err) 3309 require.Len(t, posts2, 3, "should get 3 posts") 3310 3311 require.ElementsMatch(t, getPostIds(data[0:8]), getPostIds(posts1, posts2...)) 3312 }) 3313 } 3314 3315 func getPostIds(posts []*model.Post, morePosts ...*model.Post) []string { 3316 ids := make([]string, 0, len(posts)+len(morePosts)) 3317 for _, p := range posts { 3318 ids = append(ids, p.Id) 3319 } 3320 for _, p := range morePosts { 3321 ids = append(ids, p.Id) 3322 } 3323 return ids 3324 }