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  }