Этот коммит содержится в:
Jesse Hallam
2022-04-19 17:06:31 -03:00
коммит произвёл GitHub
родитель 348602cf00
Коммит 5bd223c836
12 изменённых файлов: 465 добавлений и 282 удалений

Просмотреть файл

@@ -27,8 +27,6 @@ func TestPostStore(t *testing.T, ss store.Store, s SqlStore) {
t.Run("GetSingle", func(t *testing.T) { testPostStoreGetSingle(t, ss) })
t.Run("Update", func(t *testing.T) { testPostStoreUpdate(t, ss) })
t.Run("Delete", func(t *testing.T) { testPostStoreDelete(t, ss) })
t.Run("Delete1Level", func(t *testing.T) { testPostStoreDelete1Level(t, ss) })
t.Run("Delete2Level", func(t *testing.T) { testPostStoreDelete2Level(t, ss) })
t.Run("PermDelete1Level", func(t *testing.T) { testPostStorePermDelete1Level(t, ss) })
t.Run("PermDelete1Level2", func(t *testing.T) { testPostStorePermDelete1Level2(t, ss) })
t.Run("GetWithChildren", func(t *testing.T) { testPostStoreGetWithChildren(t, ss) })
@@ -317,6 +315,9 @@ func testPostStoreSaveMultiple(t *testing.T, ss store.Store) {
replyPost3.Message = NewTestId()
replyPost3.RootId = rootPost.Id
// Ensure update does not occur in the same timestamp as creation
time.Sleep(time.Millisecond)
_, _, err = ss.Post().SaveMultiple([]*model.Post{&replyPost2, &replyPost3})
require.NoError(t, err)
@@ -819,109 +820,132 @@ func testPostStoreUpdate(t *testing.T, ss store.Store) {
}
func testPostStoreDelete(t *testing.T, ss store.Store) {
o1 := &model.Post{}
o1.ChannelId = model.NewId()
o1.UserId = model.NewId()
o1.Message = model.NewRandomString(10)
deleteByID := model.NewId()
t.Run("single post, no replies", func(t *testing.T) {
// Create a post
rootPost, err := ss.Post().Save(&model.Post{
ChannelId: model.NewId(),
UserId: model.NewId(),
Message: model.NewRandomString(10),
})
require.NoError(t, err)
etag1 := ss.Post().GetEtag(o1.ChannelId, false, false)
require.Equal(t, 0, strings.Index(etag1, model.CurrentVersion+"."), "Invalid Etag")
// Verify etag generation for the channel containing the post.
etag1 := ss.Post().GetEtag(rootPost.ChannelId, false, false)
require.Equal(t, 0, strings.Index(etag1, model.CurrentVersion+"."), "Invalid Etag")
o1, err := ss.Post().Save(o1)
require.NoError(t, err)
// Verify the created post.
r1, err := ss.Post().Get(context.Background(), rootPost.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
require.NotNil(t, r1.Posts[rootPost.Id])
require.Equal(t, rootPost, r1.Posts[rootPost.Id])
r1, err := ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
require.Equal(t, r1.Posts[o1.Id].CreateAt, o1.CreateAt, "invalid returned post")
// Mark the post as deleted by the user identified with deleteByID.
deleteByID := model.NewId()
err = ss.Post().Delete(rootPost.Id, model.GetMillis(), deleteByID)
require.NoError(t, err)
err = ss.Post().Delete(o1.Id, model.GetMillis(), deleteByID)
require.NoError(t, err)
// Ensure the appropriate posts prop reflects the user deleting the post.
posts, err := ss.Post().GetPostsCreatedAt(rootPost.ChannelId, rootPost.CreateAt)
require.NoError(t, err)
require.NotEmpty(t, posts)
assert.Equal(t, deleteByID, posts[0].GetProp(model.PostPropsDeleteBy), "unexpected Props[model.PostPropsDeleteBy]")
posts, _ := ss.Post().GetPostsCreatedAt(o1.ChannelId, o1.CreateAt)
post := posts[0]
actual := post.GetProp(model.PostPropsDeleteBy)
// Verify that the post is no longer fetched by default.
_, err = ss.Post().Get(context.Background(), rootPost.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "fetching deleted post should have failed")
require.IsType(t, &store.ErrNotFound{}, err)
assert.Equal(t, deleteByID, actual, "Expected (*Post).Props[model.PostPropsDeleteBy] to be %v but got %v.", deleteByID, actual)
// Verify etag generation for the channel containing the now deleted post.
etag2 := ss.Post().GetEtag(rootPost.ChannelId, false, false)
require.Equal(t, 0, strings.Index(etag2, model.CurrentVersion+"."), "Invalid Etag")
})
r3, err := ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Missing id should have failed - PostList %v", r3)
t.Run("thread with one reply", func(t *testing.T) {
// Create a root post
rootPost, err := ss.Post().Save(&model.Post{
ChannelId: model.NewId(),
UserId: model.NewId(),
Message: NewTestId(),
})
require.NoError(t, err)
etag2 := ss.Post().GetEtag(o1.ChannelId, false, false)
require.Equal(t, 0, strings.Index(etag2, model.CurrentVersion+"."), "Invalid Etag")
}
// Reply to that root post
replyPost, err := ss.Post().Save(&model.Post{
ChannelId: rootPost.ChannelId,
UserId: model.NewId(),
Message: NewTestId(),
RootId: rootPost.Id,
})
require.NoError(t, err)
func testPostStoreDelete1Level(t *testing.T, ss store.Store) {
o1 := &model.Post{}
o1.ChannelId = model.NewId()
o1.UserId = model.NewId()
o1.Message = NewTestId()
o1, err := ss.Post().Save(o1)
require.NoError(t, err)
// Delete the root post
err = ss.Post().Delete(rootPost.Id, model.GetMillis(), "")
require.NoError(t, err)
o2 := &model.Post{}
o2.ChannelId = o1.ChannelId
o2.UserId = model.NewId()
o2.Message = NewTestId()
o2.RootId = o1.Id
o2, err = ss.Post().Save(o2)
require.NoError(t, err)
// Verify the root post deleted
_, err = ss.Post().Get(context.Background(), rootPost.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
require.IsType(t, &store.ErrNotFound{}, err)
err = ss.Post().Delete(o1.Id, model.GetMillis(), "")
require.NoError(t, err)
// Verify the reply post deleted
_, err = ss.Post().Get(context.Background(), replyPost.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
require.IsType(t, &store.ErrNotFound{}, err)
})
_, err = ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
t.Run("thread with multiple replies", func(t *testing.T) {
// Create a root post
rootPost1, err := ss.Post().Save(&model.Post{
ChannelId: model.NewId(),
UserId: model.NewId(),
Message: NewTestId(),
})
require.NoError(t, err)
_, err = ss.Post().Get(context.Background(), o2.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
}
// Reply to that root post
replyPost1, err := ss.Post().Save(&model.Post{
ChannelId: rootPost1.ChannelId,
UserId: model.NewId(),
Message: NewTestId(),
RootId: rootPost1.Id,
})
require.NoError(t, err)
func testPostStoreDelete2Level(t *testing.T, ss store.Store) {
o1 := &model.Post{}
o1.ChannelId = model.NewId()
o1.UserId = model.NewId()
o1.Message = NewTestId()
o1, err := ss.Post().Save(o1)
require.NoError(t, err)
// Reply to that root post a second time
replyPost2, err := ss.Post().Save(&model.Post{
ChannelId: rootPost1.ChannelId,
UserId: model.NewId(),
Message: NewTestId(),
RootId: rootPost1.Id,
})
require.NoError(t, err)
o2 := &model.Post{}
o2.ChannelId = o1.ChannelId
o2.UserId = model.NewId()
o2.Message = NewTestId()
o2.RootId = o1.Id
o2, err = ss.Post().Save(o2)
require.NoError(t, err)
// Create another root post in a separate channel
rootPost2, err := ss.Post().Save(&model.Post{
ChannelId: model.NewId(),
UserId: model.NewId(),
Message: NewTestId(),
})
require.NoError(t, err)
o3 := &model.Post{}
o3.ChannelId = o1.ChannelId
o3.UserId = model.NewId()
o3.Message = NewTestId()
o3.RootId = o1.Id
o3, err = ss.Post().Save(o3)
require.NoError(t, err)
// Delete the root post
err = ss.Post().Delete(rootPost1.Id, model.GetMillis(), "")
require.NoError(t, err)
o4 := &model.Post{}
o4.ChannelId = model.NewId()
o4.UserId = model.NewId()
o4.Message = NewTestId()
o4, err = ss.Post().Save(o4)
require.NoError(t, err)
// Verify the root post and replies deleted
_, err = ss.Post().Get(context.Background(), rootPost1.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
err = ss.Post().Delete(o1.Id, model.GetMillis(), "")
require.NoError(t, err)
_, err = ss.Post().Get(context.Background(), replyPost1.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
_, err = ss.Post().Get(context.Background(), o1.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
_, err = ss.Post().Get(context.Background(), replyPost2.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
_, err = ss.Post().Get(context.Background(), o2.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
_, err = ss.Post().Get(context.Background(), o3.Id, model.GetPostsOptions{}, "")
require.Error(t, err, "Deleted id should have failed")
_, err = ss.Post().Get(context.Background(), o4.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
// Verify other root posts remain undeleted.
_, err = ss.Post().Get(context.Background(), rootPost2.Id, model.GetPostsOptions{}, "")
require.NoError(t, err)
})
}
func testPostStorePermDelete1Level(t *testing.T, ss store.Store) {

Просмотреть файл

@@ -684,6 +684,12 @@ func testGetTeamsUnreadForUser(t *testing.T, ss store.Store) {
assert.Equal(t, int64(1), teamsUnread[team2.Id].ThreadMentionCount)
}
type byPostId []*model.Post
func (a byPostId) Len() int { return len(a) }
func (a byPostId) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a byPostId) Less(i, j int) bool { return a[i].Id < a[j].Id }
func testVarious(t *testing.T, ss store.Store) {
createThreadMembership := func(userID, postID string, isMention bool) {
t.Helper()
@@ -818,6 +824,16 @@ func testVarious(t *testing.T, ss store.Store) {
})
require.NoError(t, err)
postNames := map[string]string{
team1channel1post1.Id: "team1channel1post1",
team1channel1post2.Id: "team1channel1post2",
team1channel1post3.Id: "team1channel1post3",
team2channel1post1.Id: "team2channel1post1",
team2channel1post2deleted.Id: "team2channel1post2deleted",
dm1post1.Id: "dm1post1",
gm1post1.Id: "gm1post1",
}
threadStoreCreateReply(t, ss, team1channel1.Id, team1channel1post1.Id, user2ID, model.GetMillis())
threadStoreCreateReply(t, ss, team1channel1.Id, team1channel1post2.Id, user2ID, model.GetMillis())
threadStoreCreateReply(t, ss, team1channel1.Id, team1channel1post3.Id, user2ID, model.GetMillis())
@@ -845,9 +861,37 @@ func testVarious(t *testing.T, ss store.Store) {
time.Sleep(1 * time.Millisecond)
threadStoreCreateReply(t, ss, team1channel1.Id, team1channel1post2.Id, user2ID, model.GetMillis())
// Actually make team2channel1post2deleted deleted
err = ss.Post().Delete(team2channel1post2deleted.Id, model.GetMillis(), user1ID)
require.NoError(t, err)
// Re-fetch posts to ensure metadata up-to-date
allPosts := []*model.Post{
team1channel1post1,
team1channel1post2,
team1channel1post3,
team2channel1post1,
team2channel1post2deleted,
dm1post1,
gm1post1,
}
for i := range allPosts {
updatedPost, err := ss.Post().GetSingle(allPosts[i].Id, true)
require.NoError(t, err)
// Fix some inconsistencies with how the post store returns posts vs. how the
// thread store returns it.
if updatedPost.RemoteId == nil {
updatedPost.RemoteId = new(string)
}
// Also, we don't populate ReplyCount for posts when querying threads, so don't
// assert same.
updatedPost.ReplyCount = 0
updatedPost.ShallowCopy(allPosts[i])
}
t.Run("GetTotalUnreadThreads", func(t *testing.T) {
testCases := []struct {
Description string
@@ -899,27 +943,15 @@ func testVarious(t *testing.T, ss store.Store) {
{"team1, user1", user1ID, team1.Id, model.GetUserThreadsOpts{}, []*model.Post{
team1channel1post1, team1channel1post2, team1channel1post3, dm1post1, gm1post1,
}},
{"team1, user1, unread", user1ID, team1.Id, model.GetUserThreadsOpts{Unread: true}, []*model.Post{
team1channel1post2, team1channel1post3, gm1post1,
}},
{"team1, user1, deleted", user1ID, team1.Id, model.GetUserThreadsOpts{Deleted: true}, []*model.Post{
team1channel1post1, team1channel1post2, team1channel1post3, dm1post1, gm1post1, // (no deleted threads in team1)
}},
{"team1, user1, unread + deleted", user1ID, team1.Id, model.GetUserThreadsOpts{Unread: true, Deleted: true}, []*model.Post{
team1channel1post2, team1channel1post3, gm1post1, // (no deleted threads in team1)
}},
{"team2, user1", user1ID, team2.Id, model.GetUserThreadsOpts{}, []*model.Post{
team2channel1post1, dm1post1, gm1post1,
}},
{"team2, user1, unread", user1ID, team2.Id, model.GetUserThreadsOpts{Unread: true}, []*model.Post{
gm1post1, // (no unread in team2)
}},
{"team2, user1, deleted", user1ID, team2.Id, model.GetUserThreadsOpts{Deleted: true}, []*model.Post{
team2channel1post1, team2channel1post2deleted, dm1post1, gm1post1,
}},
{"team2, user1, unread + deleted", user1ID, team2.Id, model.GetUserThreadsOpts{Unread: true, Deleted: true}, []*model.Post{
team2channel1post2deleted, gm1post1,
}},
}
for _, testCase := range testCases {
@@ -962,6 +994,46 @@ func testVarious(t *testing.T, ss store.Store) {
}
})
assertThreadPosts := func(t *testing.T, threads []*model.ThreadResponse, expectedPosts []*model.Post) {
t.Helper()
actualPosts := make([]*model.Post, 0, len(threads))
actualPostNames := make([]string, 0, len(threads))
for _, thread := range threads {
actualPosts = append(actualPosts, thread.Post)
postName, ok := postNames[thread.PostId]
require.True(t, ok, "failed to find actual %s in post names", thread.PostId)
actualPostNames = append(actualPostNames, postName)
}
sort.Strings(actualPostNames)
expectedPostNames := make([]string, 0, len(expectedPosts))
for _, post := range expectedPosts {
postName, ok := postNames[post.Id]
require.True(t, ok, "failed to find expected %s in post names", post.Id)
expectedPostNames = append(expectedPostNames, postName)
}
sort.Strings(expectedPostNames)
assert.Equal(t, expectedPostNames, actualPostNames)
// Check posts themselves
sort.Sort(byPostId(expectedPosts))
sort.Sort(byPostId(actualPosts))
if assert.Len(t, actualPosts, len(expectedPosts)) {
for i := range actualPosts {
assert.Equal(t, expectedPosts[i], actualPosts[i], "mismatch comparing expected post %s with actual post %s", postNames[expectedPosts[i].Id], postNames[actualPosts[i].Id])
}
} else {
assert.Equal(t, expectedPosts, actualPosts)
}
// Check common fields between threads and posts.
for _, thread := range threads {
assert.Equal(t, thread.DeleteAt, thread.Post.DeleteAt, "expected Thread.DeleteAt == Post.DeleteAt")
}
}
t.Run("GetThreadsForUser", func(t *testing.T) {
testCases := []struct {
Description string
@@ -1005,19 +1077,7 @@ func testVarious(t *testing.T, ss store.Store) {
threads, err := ss.Thread().GetThreadsForUser(testCase.UserID, testCase.TeamID, testCase.Options)
require.NoError(t, err)
postIDs := make([]string, 0, len(threads))
for _, thread := range threads {
postIDs = append(postIDs, thread.PostId)
}
sort.Strings(postIDs)
expectedPostIDs := make([]string, 0, len(testCase.ExpectedThreads))
for _, post := range testCase.ExpectedThreads {
expectedPostIDs = append(expectedPostIDs, post.Id)
}
sort.Strings(expectedPostIDs)
assert.Equal(t, expectedPostIDs, postIDs)
assertThreadPosts(t, threads, testCase.ExpectedThreads)
})
}
})

Просмотреть файл

@@ -244,6 +244,9 @@ func testUserStoreUpdateUpdateAt(t *testing.T, ss store.Store) {
_, nErr := ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id}, -1)
require.NoError(t, nErr)
// Ensure UpdateAt has a change to be different below.
time.Sleep(1 * time.Millisecond)
_, err = ss.User().UpdateUpdateAt(u1.Id)
require.NoError(t, err)