github.com/qichengzx/mattermost-server@v4.5.1-0.20180604164826-2c75247c97d0+incompatible/store/storetest/reaction_store.go (about)

     1  // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package storetest
     5  
     6  import (
     7  	"testing"
     8  
     9  	"github.com/mattermost/mattermost-server/model"
    10  	"github.com/mattermost/mattermost-server/store"
    11  )
    12  
    13  func TestReactionStore(t *testing.T, ss store.Store) {
    14  	t.Run("ReactionSave", func(t *testing.T) { testReactionSave(t, ss) })
    15  	t.Run("ReactionDelete", func(t *testing.T) { testReactionDelete(t, ss) })
    16  	t.Run("ReactionGetForPost", func(t *testing.T) { testReactionGetForPost(t, ss) })
    17  	t.Run("ReactionDeleteAllWithEmojiName", func(t *testing.T) { testReactionDeleteAllWithEmojiName(t, ss) })
    18  	t.Run("PermanentDeleteBatch", func(t *testing.T) { testReactionStorePermanentDeleteBatch(t, ss) })
    19  }
    20  
    21  func testReactionSave(t *testing.T, ss store.Store) {
    22  	post := store.Must(ss.Post().Save(&model.Post{
    23  		ChannelId: model.NewId(),
    24  		UserId:    model.NewId(),
    25  	})).(*model.Post)
    26  	firstUpdateAt := post.UpdateAt
    27  
    28  	reaction1 := &model.Reaction{
    29  		UserId:    model.NewId(),
    30  		PostId:    post.Id,
    31  		EmojiName: model.NewId(),
    32  	}
    33  	if result := <-ss.Reaction().Save(reaction1); result.Err != nil {
    34  		t.Fatal(result.Err)
    35  	} else if saved := result.Data.(*model.Reaction); saved.UserId != reaction1.UserId ||
    36  		saved.PostId != reaction1.PostId || saved.EmojiName != reaction1.EmojiName {
    37  		t.Fatal("should've saved reaction and returned it")
    38  	}
    39  
    40  	var secondUpdateAt int64
    41  	if postList := store.Must(ss.Post().Get(reaction1.PostId)).(*model.PostList); !postList.Posts[post.Id].HasReactions {
    42  		t.Fatal("should've set HasReactions = true on post")
    43  	} else if postList.Posts[post.Id].UpdateAt == firstUpdateAt {
    44  		t.Fatal("should've marked post as updated when HasReactions changed")
    45  	} else {
    46  		secondUpdateAt = postList.Posts[post.Id].UpdateAt
    47  	}
    48  
    49  	if result := <-ss.Reaction().Save(reaction1); result.Err != nil {
    50  		t.Log(result.Err)
    51  		t.Fatal("should've allowed saving a duplicate reaction")
    52  	}
    53  
    54  	// different user
    55  	reaction2 := &model.Reaction{
    56  		UserId:    model.NewId(),
    57  		PostId:    reaction1.PostId,
    58  		EmojiName: reaction1.EmojiName,
    59  	}
    60  	if result := <-ss.Reaction().Save(reaction2); result.Err != nil {
    61  		t.Fatal(result.Err)
    62  	}
    63  
    64  	if postList := store.Must(ss.Post().Get(reaction2.PostId)).(*model.PostList); postList.Posts[post.Id].UpdateAt != secondUpdateAt {
    65  		t.Fatal("shouldn't mark as updated when HasReactions hasn't changed")
    66  	}
    67  
    68  	// different post
    69  	reaction3 := &model.Reaction{
    70  		UserId:    reaction1.UserId,
    71  		PostId:    model.NewId(),
    72  		EmojiName: reaction1.EmojiName,
    73  	}
    74  	if result := <-ss.Reaction().Save(reaction3); result.Err != nil {
    75  		t.Fatal(result.Err)
    76  	}
    77  
    78  	// different emoji
    79  	reaction4 := &model.Reaction{
    80  		UserId:    reaction1.UserId,
    81  		PostId:    reaction1.PostId,
    82  		EmojiName: model.NewId(),
    83  	}
    84  	if result := <-ss.Reaction().Save(reaction4); result.Err != nil {
    85  		t.Fatal(result.Err)
    86  	}
    87  
    88  	// invalid reaction
    89  	reaction5 := &model.Reaction{
    90  		UserId: reaction1.UserId,
    91  		PostId: reaction1.PostId,
    92  	}
    93  	if result := <-ss.Reaction().Save(reaction5); result.Err == nil {
    94  		t.Fatal("should've failed for invalid reaction")
    95  	}
    96  }
    97  
    98  func testReactionDelete(t *testing.T, ss store.Store) {
    99  	post := store.Must(ss.Post().Save(&model.Post{
   100  		ChannelId: model.NewId(),
   101  		UserId:    model.NewId(),
   102  	})).(*model.Post)
   103  
   104  	reaction := &model.Reaction{
   105  		UserId:    model.NewId(),
   106  		PostId:    post.Id,
   107  		EmojiName: model.NewId(),
   108  	}
   109  
   110  	store.Must(ss.Reaction().Save(reaction))
   111  	firstUpdateAt := store.Must(ss.Post().Get(reaction.PostId)).(*model.PostList).Posts[post.Id].UpdateAt
   112  
   113  	if result := <-ss.Reaction().Delete(reaction); result.Err != nil {
   114  		t.Fatal(result.Err)
   115  	}
   116  
   117  	if result := <-ss.Reaction().GetForPost(post.Id, false); result.Err != nil {
   118  		t.Fatal(result.Err)
   119  	} else if len(result.Data.([]*model.Reaction)) != 0 {
   120  		t.Fatal("should've deleted reaction")
   121  	}
   122  
   123  	if postList := store.Must(ss.Post().Get(post.Id)).(*model.PostList); postList.Posts[post.Id].HasReactions {
   124  		t.Fatal("should've set HasReactions = false on post")
   125  	} else if postList.Posts[post.Id].UpdateAt == firstUpdateAt {
   126  		t.Fatal("shouldn't mark as updated when HasReactions has changed after deleting reactions")
   127  	}
   128  }
   129  
   130  func testReactionGetForPost(t *testing.T, ss store.Store) {
   131  	postId := model.NewId()
   132  
   133  	userId := model.NewId()
   134  
   135  	reactions := []*model.Reaction{
   136  		{
   137  			UserId:    userId,
   138  			PostId:    postId,
   139  			EmojiName: "smile",
   140  		},
   141  		{
   142  			UserId:    model.NewId(),
   143  			PostId:    postId,
   144  			EmojiName: "smile",
   145  		},
   146  		{
   147  			UserId:    userId,
   148  			PostId:    postId,
   149  			EmojiName: "sad",
   150  		},
   151  		{
   152  			UserId:    userId,
   153  			PostId:    model.NewId(),
   154  			EmojiName: "angry",
   155  		},
   156  	}
   157  
   158  	for _, reaction := range reactions {
   159  		store.Must(ss.Reaction().Save(reaction))
   160  	}
   161  
   162  	if result := <-ss.Reaction().GetForPost(postId, false); result.Err != nil {
   163  		t.Fatal(result.Err)
   164  	} else if returned := result.Data.([]*model.Reaction); len(returned) != 3 {
   165  		t.Fatal("should've returned 3 reactions")
   166  	} else {
   167  		for _, reaction := range reactions {
   168  			found := false
   169  
   170  			for _, returnedReaction := range returned {
   171  				if returnedReaction.UserId == reaction.UserId && returnedReaction.PostId == reaction.PostId &&
   172  					returnedReaction.EmojiName == reaction.EmojiName {
   173  					found = true
   174  					break
   175  				}
   176  			}
   177  
   178  			if !found && reaction.PostId == postId {
   179  				t.Fatalf("should've returned reaction for post %v", reaction)
   180  			} else if found && reaction.PostId != postId {
   181  				t.Fatal("shouldn't have returned reaction for another post")
   182  			}
   183  		}
   184  	}
   185  
   186  	// Should return cached item
   187  	if result := <-ss.Reaction().GetForPost(postId, true); result.Err != nil {
   188  		t.Fatal(result.Err)
   189  	} else if returned := result.Data.([]*model.Reaction); len(returned) != 3 {
   190  		t.Fatal("should've returned 3 reactions")
   191  	} else {
   192  		for _, reaction := range reactions {
   193  			found := false
   194  
   195  			for _, returnedReaction := range returned {
   196  				if returnedReaction.UserId == reaction.UserId && returnedReaction.PostId == reaction.PostId &&
   197  					returnedReaction.EmojiName == reaction.EmojiName {
   198  					found = true
   199  					break
   200  				}
   201  			}
   202  
   203  			if !found && reaction.PostId == postId {
   204  				t.Fatalf("should've returned reaction for post %v", reaction)
   205  			} else if found && reaction.PostId != postId {
   206  				t.Fatal("shouldn't have returned reaction for another post")
   207  			}
   208  		}
   209  	}
   210  }
   211  
   212  func testReactionDeleteAllWithEmojiName(t *testing.T, ss store.Store) {
   213  	emojiToDelete := model.NewId()
   214  
   215  	post := store.Must(ss.Post().Save(&model.Post{
   216  		ChannelId: model.NewId(),
   217  		UserId:    model.NewId(),
   218  	})).(*model.Post)
   219  	post2 := store.Must(ss.Post().Save(&model.Post{
   220  		ChannelId: model.NewId(),
   221  		UserId:    model.NewId(),
   222  	})).(*model.Post)
   223  	post3 := store.Must(ss.Post().Save(&model.Post{
   224  		ChannelId: model.NewId(),
   225  		UserId:    model.NewId(),
   226  	})).(*model.Post)
   227  
   228  	userId := model.NewId()
   229  
   230  	reactions := []*model.Reaction{
   231  		{
   232  			UserId:    userId,
   233  			PostId:    post.Id,
   234  			EmojiName: emojiToDelete,
   235  		},
   236  		{
   237  			UserId:    model.NewId(),
   238  			PostId:    post.Id,
   239  			EmojiName: emojiToDelete,
   240  		},
   241  		{
   242  			UserId:    userId,
   243  			PostId:    post.Id,
   244  			EmojiName: "sad",
   245  		},
   246  		{
   247  			UserId:    userId,
   248  			PostId:    post2.Id,
   249  			EmojiName: "angry",
   250  		},
   251  		{
   252  			UserId:    userId,
   253  			PostId:    post3.Id,
   254  			EmojiName: emojiToDelete,
   255  		},
   256  	}
   257  
   258  	for _, reaction := range reactions {
   259  		store.Must(ss.Reaction().Save(reaction))
   260  	}
   261  
   262  	if result := <-ss.Reaction().DeleteAllWithEmojiName(emojiToDelete); result.Err != nil {
   263  		t.Fatal(result.Err)
   264  	}
   265  
   266  	// check that the reactions were deleted
   267  	if returned := store.Must(ss.Reaction().GetForPost(post.Id, false)).([]*model.Reaction); len(returned) != 1 {
   268  		t.Fatal("should've only removed reactions with emoji name")
   269  	} else {
   270  		for _, reaction := range returned {
   271  			if reaction.EmojiName == "smile" {
   272  				t.Fatal("should've removed reaction with emoji name")
   273  			}
   274  		}
   275  	}
   276  
   277  	if returned := store.Must(ss.Reaction().GetForPost(post2.Id, false)).([]*model.Reaction); len(returned) != 1 {
   278  		t.Fatal("should've only removed reactions with emoji name")
   279  	}
   280  
   281  	if returned := store.Must(ss.Reaction().GetForPost(post3.Id, false)).([]*model.Reaction); len(returned) != 0 {
   282  		t.Fatal("should've only removed reactions with emoji name")
   283  	}
   284  
   285  	// check that the posts are updated
   286  	if postList := store.Must(ss.Post().Get(post.Id)).(*model.PostList); !postList.Posts[post.Id].HasReactions {
   287  		t.Fatal("post should still have reactions")
   288  	}
   289  
   290  	if postList := store.Must(ss.Post().Get(post2.Id)).(*model.PostList); !postList.Posts[post2.Id].HasReactions {
   291  		t.Fatal("post should still have reactions")
   292  	}
   293  
   294  	if postList := store.Must(ss.Post().Get(post3.Id)).(*model.PostList); postList.Posts[post3.Id].HasReactions {
   295  		t.Fatal("post shouldn't have reactions any more")
   296  	}
   297  }
   298  
   299  func testReactionStorePermanentDeleteBatch(t *testing.T, ss store.Store) {
   300  	post := store.Must(ss.Post().Save(&model.Post{
   301  		ChannelId: model.NewId(),
   302  		UserId:    model.NewId(),
   303  	})).(*model.Post)
   304  
   305  	reactions := []*model.Reaction{
   306  		{
   307  			UserId:    model.NewId(),
   308  			PostId:    post.Id,
   309  			EmojiName: "sad",
   310  			CreateAt:  1000,
   311  		},
   312  		{
   313  			UserId:    model.NewId(),
   314  			PostId:    post.Id,
   315  			EmojiName: "sad",
   316  			CreateAt:  1500,
   317  		},
   318  		{
   319  			UserId:    model.NewId(),
   320  			PostId:    post.Id,
   321  			EmojiName: "sad",
   322  			CreateAt:  2000,
   323  		},
   324  		{
   325  			UserId:    model.NewId(),
   326  			PostId:    post.Id,
   327  			EmojiName: "sad",
   328  			CreateAt:  2000,
   329  		},
   330  	}
   331  
   332  	// Need to hang on to a reaction to delete later in order to clear the cache, as "allowFromCache" isn't honoured any more.
   333  	var lastReaction *model.Reaction
   334  	for _, reaction := range reactions {
   335  		lastReaction = store.Must(ss.Reaction().Save(reaction)).(*model.Reaction)
   336  	}
   337  
   338  	if returned := store.Must(ss.Reaction().GetForPost(post.Id, false)).([]*model.Reaction); len(returned) != 4 {
   339  		t.Fatal("expected 4 reactions")
   340  	}
   341  
   342  	store.Must(ss.Reaction().PermanentDeleteBatch(1800, 1000))
   343  
   344  	// This is to force a clear of the cache.
   345  	store.Must(ss.Reaction().Delete(lastReaction))
   346  
   347  	if returned := store.Must(ss.Reaction().GetForPost(post.Id, false)).([]*model.Reaction); len(returned) != 1 {
   348  		t.Fatalf("expected 1 reaction. Got: %v", len(returned))
   349  	}
   350  }