From 70e5f00241473c27a3008959ce08832c75e76ba8 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 6 Oct 2017 11:08:59 -0700 Subject: store/storetest package (#7588) * prerequisites * storetest package --- store/constants.go | 2 + store/sqlstore/audit_store_test.go | 82 +- store/sqlstore/channel_store_test.go | 1988 +--------------------- store/sqlstore/cluster_discovery_store_test.go | 194 +-- store/sqlstore/command_store_test.go | 251 +-- store/sqlstore/command_webhook_store_test.go | 57 +- store/sqlstore/compliance_store_test.go | 310 +--- store/sqlstore/emoji_store_test.go | 170 +- store/sqlstore/file_info_store_test.go | 294 +--- store/sqlstore/job_store_test.go | 508 +----- store/sqlstore/license_store_test.go | 49 +- store/sqlstore/oauth_store_test.go | 438 +---- store/sqlstore/post_store_test.go | 1695 +------------------ store/sqlstore/preference_store.go | 8 +- store/sqlstore/preference_store_test.go | 558 +------ store/sqlstore/reaction_store_test.go | 346 +--- store/sqlstore/session_store_test.go | 250 +-- store/sqlstore/status_store_test.go | 99 +- store/sqlstore/store_test.go | 134 +- store/sqlstore/system_store_test.go | 49 +- store/sqlstore/team_store_test.go | 1020 +----------- store/sqlstore/upgrade_test.go | 40 +- store/sqlstore/user_access_token_store_test.go | 81 +- store/sqlstore/user_store_test.go | 2096 +----------------------- store/sqlstore/webhook_store_test.go | 508 +----- store/storetest/audit_store.go | 91 + store/storetest/channel_store.go | 1967 ++++++++++++++++++++++ store/storetest/cluster_discovery_store.go | 200 +++ store/storetest/command_store.go | 251 +++ store/storetest/command_webhook_store.go | 68 + store/storetest/compliance_store.go | 318 ++++ store/storetest/emoji_store.go | 175 ++ store/storetest/file_info_store.go | 296 ++++ store/storetest/job_store.go | 507 ++++++ store/storetest/license_store.go | 56 + store/storetest/oauth_store.go | 435 +++++ store/storetest/post_store.go | 1684 +++++++++++++++++++ store/storetest/preference_store.go | 447 +++++ store/storetest/reaction_store.go | 350 ++++ store/storetest/session_store.go | 250 +++ store/storetest/status_store.go | 106 ++ store/storetest/system_store.go | 58 + store/storetest/team_store.go | 1010 ++++++++++++ store/storetest/user_access_token_store.go | 89 + store/storetest/user_store.go | 2074 +++++++++++++++++++++++ store/storetest/webhook_store.go | 507 ++++++ 46 files changed, 11095 insertions(+), 11071 deletions(-) create mode 100644 store/storetest/audit_store.go create mode 100644 store/storetest/channel_store.go create mode 100644 store/storetest/cluster_discovery_store.go create mode 100644 store/storetest/command_store.go create mode 100644 store/storetest/command_webhook_store.go create mode 100644 store/storetest/compliance_store.go create mode 100644 store/storetest/emoji_store.go create mode 100644 store/storetest/file_info_store.go create mode 100644 store/storetest/job_store.go create mode 100644 store/storetest/license_store.go create mode 100644 store/storetest/oauth_store.go create mode 100644 store/storetest/post_store.go create mode 100644 store/storetest/preference_store.go create mode 100644 store/storetest/reaction_store.go create mode 100644 store/storetest/session_store.go create mode 100644 store/storetest/status_store.go create mode 100644 store/storetest/system_store.go create mode 100644 store/storetest/team_store.go create mode 100644 store/storetest/user_access_token_store.go create mode 100644 store/storetest/user_store.go create mode 100644 store/storetest/webhook_store.go (limited to 'store') diff --git a/store/constants.go b/store/constants.go index 52d399168..f541c9747 100644 --- a/store/constants.go +++ b/store/constants.go @@ -12,4 +12,6 @@ const ( USER_SEARCH_OPTION_NAMES_ONLY_NO_FULL_NAME = "names_only_no_full_name" USER_SEARCH_OPTION_ALL_NO_FULL_NAME = "all_no_full_name" USER_SEARCH_OPTION_ALLOW_INACTIVE = "allow_inactive" + + FEATURE_TOGGLE_PREFIX = "feature_enabled_" ) diff --git a/store/sqlstore/audit_store_test.go b/store/sqlstore/audit_store_test.go index 4378c13e5..e840ad58e 100644 --- a/store/sqlstore/audit_store_test.go +++ b/store/sqlstore/audit_store_test.go @@ -5,86 +5,10 @@ package sqlstore import ( "testing" - "time" - "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store" + "github.com/mattermost/mattermost-server/store/storetest" ) -func TestSqlAuditStore(t *testing.T) { - ss := Setup() - - audit := &model.Audit{UserId: model.NewId(), IpAddress: "ipaddress", Action: "Action"} - store.Must(ss.Audit().Save(audit)) - time.Sleep(100 * time.Millisecond) - store.Must(ss.Audit().Save(audit)) - time.Sleep(100 * time.Millisecond) - store.Must(ss.Audit().Save(audit)) - time.Sleep(100 * time.Millisecond) - audit.ExtraInfo = "extra" - time.Sleep(100 * time.Millisecond) - store.Must(ss.Audit().Save(audit)) - - time.Sleep(100 * time.Millisecond) - - c := ss.Audit().Get(audit.UserId, 0, 100) - result := <-c - audits := result.Data.(model.Audits) - - if len(audits) != 4 { - t.Fatal("Failed to save and retrieve 4 audit logs") - } - - if audits[0].ExtraInfo != "extra" { - t.Fatal("Failed to save property for extra info") - } - - c = ss.Audit().Get("missing", 0, 100) - result = <-c - audits = result.Data.(model.Audits) - - if len(audits) != 0 { - t.Fatal("Should have returned empty because user_id is missing") - } - - c = ss.Audit().Get("", 0, 100) - result = <-c - audits = result.Data.(model.Audits) - - if len(audits) < 4 { - t.Fatal("Failed to save and retrieve 4 audit logs") - } - - if r2 := <-ss.Audit().PermanentDeleteByUser(audit.UserId); r2.Err != nil { - t.Fatal(r2.Err) - } -} - -func TestAuditStorePermanentDeleteBatch(t *testing.T) { - ss := Setup() - - a1 := &model.Audit{UserId: model.NewId(), IpAddress: "ipaddress", Action: "Action"} - store.Must(ss.Audit().Save(a1)) - time.Sleep(10 * time.Millisecond) - a2 := &model.Audit{UserId: a1.UserId, IpAddress: "ipaddress", Action: "Action"} - store.Must(ss.Audit().Save(a2)) - time.Sleep(10 * time.Millisecond) - cutoff := model.GetMillis() - time.Sleep(10 * time.Millisecond) - a3 := &model.Audit{UserId: a1.UserId, IpAddress: "ipaddress", Action: "Action"} - store.Must(ss.Audit().Save(a3)) - - if r := <-ss.Audit().Get(a1.UserId, 0, 100); len(r.Data.(model.Audits)) != 3 { - t.Fatal("Expected 3 audits. Got ", len(r.Data.(model.Audits))) - } - - store.Must(ss.Audit().PermanentDeleteBatch(cutoff, 1000000)) - - if r := <-ss.Audit().Get(a1.UserId, 0, 100); len(r.Data.(model.Audits)) != 1 { - t.Fatal("Expected 1 audit. Got ", len(r.Data.(model.Audits))) - } - - if r2 := <-ss.Audit().PermanentDeleteByUser(a1.UserId); r2.Err != nil { - t.Fatal(r2.Err) - } +func TestAuditStore(t *testing.T) { + StoreTest(t, storetest.TestAuditStore) } diff --git a/store/sqlstore/channel_store_test.go b/store/sqlstore/channel_store_test.go index 886852583..8e5ad5f0f 100644 --- a/store/sqlstore/channel_store_test.go +++ b/store/sqlstore/channel_store_test.go @@ -5,1992 +5,10 @@ package sqlstore import ( "testing" - "time" - "github.com/stretchr/testify/assert" - - "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store" + "github.com/mattermost/mattermost-server/store/storetest" ) -func TestChannelStoreSave(t *testing.T) { - ss := Setup() - - teamId := model.NewId() - - o1 := model.Channel{} - o1.TeamId = teamId - o1.DisplayName = "Name" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_OPEN - - if err := (<-ss.Channel().Save(&o1)).Err; err != nil { - t.Fatal("couldn't save item", err) - } - - if err := (<-ss.Channel().Save(&o1)).Err; err == nil { - t.Fatal("shouldn't be able to update from save") - } - - o1.Id = "" - if err := (<-ss.Channel().Save(&o1)).Err; err == nil { - t.Fatal("should be unique name") - } - - o1.Id = "" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_DIRECT - if err := (<-ss.Channel().Save(&o1)).Err; err == nil { - t.Fatal("Should not be able to save direct channel") - } -} - -func TestChannelStoreSaveDirectChannel(t *testing.T) { - ss := Setup() - - teamId := model.NewId() - - o1 := model.Channel{} - o1.TeamId = teamId - o1.DisplayName = "Name" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_DIRECT - - u1 := &model.User{} - u1.Email = model.NewId() - u1.Nickname = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) - - u2 := &model.User{} - u2.Email = model.NewId() - u2.Nickname = model.NewId() - store.Must(ss.User().Save(u2)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id})) - - m1 := model.ChannelMember{} - m1.ChannelId = o1.Id - m1.UserId = u1.Id - m1.NotifyProps = model.GetDefaultChannelNotifyProps() - - m2 := model.ChannelMember{} - m2.ChannelId = o1.Id - m2.UserId = u2.Id - m2.NotifyProps = model.GetDefaultChannelNotifyProps() - - if err := (<-ss.Channel().SaveDirectChannel(&o1, &m1, &m2)).Err; err != nil { - t.Fatal("couldn't save direct channel", err) - } - - members := (<-ss.Channel().GetMembers(o1.Id, 0, 100)).Data.(*model.ChannelMembers) - if len(*members) != 2 { - t.Fatal("should have saved 2 members") - } - - if err := (<-ss.Channel().SaveDirectChannel(&o1, &m1, &m2)).Err; err == nil { - t.Fatal("shouldn't be able to update from save") - } - - // Attempt to save a direct channel that already exists - o1a := model.Channel{ - TeamId: o1.TeamId, - DisplayName: o1.DisplayName, - Name: o1.Name, - Type: o1.Type, - } - - if result := <-ss.Channel().SaveDirectChannel(&o1a, &m1, &m2); result.Err == nil { - t.Fatal("should've failed to save a duplicate direct channel") - } else if result.Err.Id != store.CHANNEL_EXISTS_ERROR { - t.Fatal("should've returned CHANNEL_EXISTS_ERROR") - } else if returned := result.Data.(*model.Channel); returned.Id != o1.Id { - t.Fatal("should've returned original channel when saving a duplicate direct channel") - } - - // Attempt to save a non-direct channel - o1.Id = "" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_OPEN - if err := (<-ss.Channel().SaveDirectChannel(&o1, &m1, &m2)).Err; err == nil { - t.Fatal("Should not be able to save non-direct channel") - } -} - -func TestChannelStoreCreateDirectChannel(t *testing.T) { - ss := Setup() - - u1 := &model.User{} - u1.Email = model.NewId() - u1.Nickname = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) - - u2 := &model.User{} - u2.Email = model.NewId() - u2.Nickname = model.NewId() - store.Must(ss.User().Save(u2)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id})) - - res := <-ss.Channel().CreateDirectChannel(u1.Id, u2.Id) - if res.Err != nil { - t.Fatal("couldn't create direct channel", res.Err) - } - - c1 := res.Data.(*model.Channel) - - members := (<-ss.Channel().GetMembers(c1.Id, 0, 100)).Data.(*model.ChannelMembers) - if len(*members) != 2 { - t.Fatal("should have saved 2 members") - } -} - -func TestChannelStoreUpdate(t *testing.T) { - ss := Setup() - - o1 := model.Channel{} - o1.TeamId = model.NewId() - o1.DisplayName = "Name" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o1)) - - o2 := model.Channel{} - o2.TeamId = o1.TeamId - o2.DisplayName = "Name" - o2.Name = "zz" + model.NewId() + "b" - o2.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o2)) - - time.Sleep(100 * time.Millisecond) - - if err := (<-ss.Channel().Update(&o1)).Err; err != nil { - t.Fatal(err) - } - - o1.Id = "missing" - if err := (<-ss.Channel().Update(&o1)).Err; err == nil { - t.Fatal("Update should have failed because of missing key") - } - - o1.Id = model.NewId() - if err := (<-ss.Channel().Update(&o1)).Err; err == nil { - t.Fatal("Update should have faile because id change") - } - - o2.Name = o1.Name - if err := (<-ss.Channel().Update(&o2)).Err; err == nil { - t.Fatal("Update should have failed because of existing name") - } -} - -func TestGetChannelUnread(t *testing.T) { - ss := Setup() - - teamId1 := model.NewId() - teamId2 := model.NewId() - - uid := model.NewId() - m1 := &model.TeamMember{TeamId: teamId1, UserId: uid} - m2 := &model.TeamMember{TeamId: teamId2, UserId: uid} - store.Must(ss.Team().SaveMember(m1)) - store.Must(ss.Team().SaveMember(m2)) - notifyPropsModel := model.GetDefaultChannelNotifyProps() - - // Setup Channel 1 - c1 := &model.Channel{TeamId: m1.TeamId, Name: model.NewId(), DisplayName: "Downtown", Type: model.CHANNEL_OPEN, TotalMsgCount: 100} - store.Must(ss.Channel().Save(c1)) - cm1 := &model.ChannelMember{ChannelId: c1.Id, UserId: m1.UserId, NotifyProps: notifyPropsModel, MsgCount: 90} - store.Must(ss.Channel().SaveMember(cm1)) - - // Setup Channel 2 - c2 := &model.Channel{TeamId: m2.TeamId, Name: model.NewId(), DisplayName: "Cultural", Type: model.CHANNEL_OPEN, TotalMsgCount: 100} - store.Must(ss.Channel().Save(c2)) - cm2 := &model.ChannelMember{ChannelId: c2.Id, UserId: m2.UserId, NotifyProps: notifyPropsModel, MsgCount: 90, MentionCount: 5} - store.Must(ss.Channel().SaveMember(cm2)) - - // Check for Channel 1 - if resp := <-ss.Channel().GetChannelUnread(c1.Id, uid); resp.Err != nil { - t.Fatal(resp.Err) - } else { - ch := resp.Data.(*model.ChannelUnread) - if c1.Id != ch.ChannelId { - t.Fatal("wrong channel id") - } - - if teamId1 != ch.TeamId { - t.Fatal("wrong team id for channel 1") - } - - if ch.NotifyProps == nil { - t.Fatal("wrong props for channel 1") - } - - if ch.MentionCount != 0 { - t.Fatal("wrong MentionCount for channel 1") - } - - if ch.MsgCount != 10 { - t.Fatal("wrong MsgCount for channel 1") - } - } - - // Check for Channel 2 - if resp2 := <-ss.Channel().GetChannelUnread(c2.Id, uid); resp2.Err != nil { - t.Fatal(resp2.Err) - } else { - ch2 := resp2.Data.(*model.ChannelUnread) - if c2.Id != ch2.ChannelId { - t.Fatal("wrong channel id") - } - - if teamId2 != ch2.TeamId { - t.Fatal("wrong team id") - } - - if ch2.MentionCount != 5 { - t.Fatal("wrong MentionCount for channel 2") - } - - if ch2.MsgCount != 10 { - t.Fatal("wrong MsgCount for channel 2") - } - } -} - -func TestChannelStoreGet(t *testing.T) { - ss := Setup() - - o1 := model.Channel{} - o1.TeamId = model.NewId() - o1.DisplayName = "Name" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o1)) - - if r1 := <-ss.Channel().Get(o1.Id, false); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.Channel).ToJson() != o1.ToJson() { - t.Fatal("invalid returned channel") - } - } - - if err := (<-ss.Channel().Get("", false)).Err; err == nil { - t.Fatal("Missing id should have failed") - } - - u1 := &model.User{} - u1.Email = model.NewId() - u1.Nickname = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) - - u2 := model.User{} - u2.Email = model.NewId() - u2.Nickname = model.NewId() - store.Must(ss.User().Save(&u2)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id})) - - o2 := model.Channel{} - o2.TeamId = model.NewId() - o2.DisplayName = "Direct Name" - o2.Name = "zz" + model.NewId() + "b" - o2.Type = model.CHANNEL_DIRECT - - m1 := model.ChannelMember{} - m1.ChannelId = o2.Id - m1.UserId = u1.Id - m1.NotifyProps = model.GetDefaultChannelNotifyProps() - - m2 := model.ChannelMember{} - m2.ChannelId = o2.Id - m2.UserId = u2.Id - m2.NotifyProps = model.GetDefaultChannelNotifyProps() - - store.Must(ss.Channel().SaveDirectChannel(&o2, &m1, &m2)) - - if r2 := <-ss.Channel().Get(o2.Id, false); r2.Err != nil { - t.Fatal(r2.Err) - } else { - if r2.Data.(*model.Channel).ToJson() != o2.ToJson() { - t.Fatal("invalid returned channel") - } - } - - if r4 := <-ss.Channel().Get(o2.Id, true); r4.Err != nil { - t.Fatal(r4.Err) - } else { - if r4.Data.(*model.Channel).ToJson() != o2.ToJson() { - t.Fatal("invalid returned channel") - } - } - - if r3 := <-ss.Channel().GetAll(o1.TeamId); r3.Err != nil { - t.Fatal(r3.Err) - } else { - channels := r3.Data.([]*model.Channel) - if len(channels) == 0 { - t.Fatal("too little") - } - } - - if r3 := <-ss.Channel().GetTeamChannels(o1.TeamId); r3.Err != nil { - t.Fatal(r3.Err) - } else { - channels := r3.Data.(*model.ChannelList) - if len(*channels) == 0 { - t.Fatal("too little") - } - } -} - -func TestChannelStoreGetForPost(t *testing.T) { - ss := Setup() - - o1 := store.Must(ss.Channel().Save(&model.Channel{ - TeamId: model.NewId(), - DisplayName: "Name", - Name: "zz" + model.NewId() + "b", - Type: model.CHANNEL_OPEN, - })).(*model.Channel) - - p1 := store.Must(ss.Post().Save(&model.Post{ - UserId: model.NewId(), - ChannelId: o1.Id, - Message: "test", - })).(*model.Post) - - if r1 := <-ss.Channel().GetForPost(p1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else if r1.Data.(*model.Channel).Id != o1.Id { - t.Fatal("incorrect channel returned") - } -} - -func TestSqlChannelStoreRestore(t *testing.T) { - ss := Setup() - - o1 := model.Channel{} - o1.TeamId = model.NewId() - o1.DisplayName = "Channel1" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o1)) - - if r := <-ss.Channel().Delete(o1.Id, model.GetMillis()); r.Err != nil { - t.Fatal(r.Err) - } - - if r := <-ss.Channel().Get(o1.Id, false); r.Data.(*model.Channel).DeleteAt == 0 { - t.Fatal("should have been deleted") - } - - if r := <-ss.Channel().Restore(o1.Id, model.GetMillis()); r.Err != nil { - t.Fatal(r.Err) - } - - if r := <-ss.Channel().Get(o1.Id, false); r.Data.(*model.Channel).DeleteAt != 0 { - t.Fatal("should have been restored") - } - -} - -func TestChannelStoreDelete(t *testing.T) { - ss := Setup() - - o1 := model.Channel{} - o1.TeamId = model.NewId() - o1.DisplayName = "Channel1" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o1)) - - o2 := model.Channel{} - o2.TeamId = o1.TeamId - o2.DisplayName = "Channel2" - o2.Name = "zz" + model.NewId() + "b" - o2.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o2)) - - o3 := model.Channel{} - o3.TeamId = o1.TeamId - o3.DisplayName = "Channel3" - o3.Name = "zz" + model.NewId() + "b" - o3.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o3)) - - o4 := model.Channel{} - o4.TeamId = o1.TeamId - o4.DisplayName = "Channel4" - o4.Name = "zz" + model.NewId() + "b" - o4.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o4)) - - m1 := model.ChannelMember{} - m1.ChannelId = o1.Id - m1.UserId = model.NewId() - m1.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m1)) - - m2 := model.ChannelMember{} - m2.ChannelId = o2.Id - m2.UserId = m1.UserId - m2.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m2)) - - if r := <-ss.Channel().Delete(o1.Id, model.GetMillis()); r.Err != nil { - t.Fatal(r.Err) - } - - if r := <-ss.Channel().Get(o1.Id, false); r.Data.(*model.Channel).DeleteAt == 0 { - t.Fatal("should have been deleted") - } - - if r := <-ss.Channel().Delete(o3.Id, model.GetMillis()); r.Err != nil { - t.Fatal(r.Err) - } - - cresult := <-ss.Channel().GetChannels(o1.TeamId, m1.UserId) - list := cresult.Data.(*model.ChannelList) - - if len(*list) != 1 { - t.Fatal("invalid number of channels") - } - - cresult = <-ss.Channel().GetMoreChannels(o1.TeamId, m1.UserId, 0, 100) - list = cresult.Data.(*model.ChannelList) - - if len(*list) != 1 { - t.Fatal("invalid number of channels") - } - - <-ss.Channel().PermanentDelete(o2.Id) - - cresult = <-ss.Channel().GetChannels(o1.TeamId, m1.UserId) - t.Log(cresult.Err) - if cresult.Err.Id != "store.sql_channel.get_channels.not_found.app_error" { - t.Fatal("no channels should be found") - } - - if r := <-ss.Channel().PermanentDeleteByTeam(o1.TeamId); r.Err != nil { - t.Fatal(r.Err) - } -} - -func TestChannelStoreGetByName(t *testing.T) { - ss := Setup() - - o1 := model.Channel{} - o1.TeamId = model.NewId() - o1.DisplayName = "Name" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o1)) - - r1 := <-ss.Channel().GetByName(o1.TeamId, o1.Name, true) - if r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.Channel).ToJson() != o1.ToJson() { - t.Fatal("invalid returned channel") - } - } - - if err := (<-ss.Channel().GetByName(o1.TeamId, "", true)).Err; err == nil { - t.Fatal("Missing id should have failed") - } - - if r1 := <-ss.Channel().GetByName(o1.TeamId, o1.Name, false); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.Channel).ToJson() != o1.ToJson() { - t.Fatal("invalid returned channel") - } - } - - if err := (<-ss.Channel().GetByName(o1.TeamId, "", false)).Err; err == nil { - t.Fatal("Missing id should have failed") - } - - store.Must(ss.Channel().Delete(r1.Data.(*model.Channel).Id, model.GetMillis())) - - if err := (<-ss.Channel().GetByName(o1.TeamId, "", false)).Err; err == nil { - t.Fatal("Deleted channel should not be returned by GetByName()") - } -} - -func TestChannelStoreGetDeletedByName(t *testing.T) { - ss := Setup() - - o1 := model.Channel{} - o1.TeamId = model.NewId() - o1.DisplayName = "Name" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_OPEN - o1.DeleteAt = model.GetMillis() - store.Must(ss.Channel().Save(&o1)) - - if r1 := <-ss.Channel().GetDeletedByName(o1.TeamId, o1.Name); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.Channel).ToJson() != o1.ToJson() { - t.Fatal("invalid returned channel") - } - } - - if err := (<-ss.Channel().GetDeletedByName(o1.TeamId, "")).Err; err == nil { - t.Fatal("Missing id should have failed") - } -} - -func TestChannelStoreGetDeleted(t *testing.T) { - ss := Setup() - - o1 := model.Channel{} - o1.TeamId = model.NewId() - o1.DisplayName = "Channel1" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_OPEN - o1.DeleteAt = model.GetMillis() - store.Must(ss.Channel().Save(&o1)) - - cresult := <-ss.Channel().GetDeleted(o1.TeamId, 0, 100) - if cresult.Err != nil { - t.Fatal(cresult.Err) - } - list := cresult.Data.(*model.ChannelList) - - if len(*list) != 1 { - t.Fatal("wrong list") - } - - if (*list)[0].Name != o1.Name { - t.Fatal("missing channel") - } - - o2 := model.Channel{} - o2.TeamId = o1.TeamId - o2.DisplayName = "Channel2" - o2.Name = "zz" + model.NewId() + "b" - o2.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o2)) - - cresult = <-ss.Channel().GetDeleted(o1.TeamId, 0, 100) - if cresult.Err != nil { - t.Fatal(cresult.Err) - } - list = cresult.Data.(*model.ChannelList) - - if len(*list) != 1 { - t.Fatal("wrong list") - } - - o3 := model.Channel{} - o3.TeamId = o1.TeamId - o3.DisplayName = "Channel3" - o3.Name = "zz" + model.NewId() + "b" - o3.Type = model.CHANNEL_OPEN - o3.DeleteAt = model.GetMillis() - store.Must(ss.Channel().Save(&o3)) - - cresult = <-ss.Channel().GetDeleted(o1.TeamId, 0, 100) - if cresult.Err != nil { - t.Fatal(cresult.Err) - } - list = cresult.Data.(*model.ChannelList) - - if len(*list) != 2 { - t.Fatal("wrong list length") - } - - cresult = <-ss.Channel().GetDeleted(o1.TeamId, 0, 1) - if cresult.Err != nil { - t.Fatal(cresult.Err) - } - list = cresult.Data.(*model.ChannelList) - - if len(*list) != 1 { - t.Fatal("wrong list length") - } - - cresult = <-ss.Channel().GetDeleted(o1.TeamId, 1, 1) - if cresult.Err != nil { - t.Fatal(cresult.Err) - } - list = cresult.Data.(*model.ChannelList) - - if len(*list) != 1 { - t.Fatal("wrong list length") - } - -} - -func TestChannelMemberStore(t *testing.T) { - ss := Setup() - - c1 := model.Channel{} - c1.TeamId = model.NewId() - c1.DisplayName = "NameName" - c1.Name = "zz" + model.NewId() + "b" - c1.Type = model.CHANNEL_OPEN - c1 = *store.Must(ss.Channel().Save(&c1)).(*model.Channel) - - c1t1 := (<-ss.Channel().Get(c1.Id, false)).Data.(*model.Channel) - t1 := c1t1.ExtraUpdateAt - - u1 := model.User{} - u1.Email = model.NewId() - u1.Nickname = model.NewId() - store.Must(ss.User().Save(&u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) - - u2 := model.User{} - u2.Email = model.NewId() - u2.Nickname = model.NewId() - store.Must(ss.User().Save(&u2)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id})) - - o1 := model.ChannelMember{} - o1.ChannelId = c1.Id - o1.UserId = u1.Id - o1.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&o1)) - - o2 := model.ChannelMember{} - o2.ChannelId = c1.Id - o2.UserId = u2.Id - o2.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&o2)) - - c1t2 := (<-ss.Channel().Get(c1.Id, false)).Data.(*model.Channel) - t2 := c1t2.ExtraUpdateAt - - if t2 <= t1 { - t.Fatal("Member update time incorrect") - } - - count := (<-ss.Channel().GetMemberCount(o1.ChannelId, true)).Data.(int64) - if count != 2 { - t.Fatal("should have saved 2 members") - } - - count = (<-ss.Channel().GetMemberCount(o1.ChannelId, true)).Data.(int64) - if count != 2 { - t.Fatal("should have saved 2 members") - } - - if ss.Channel().GetMemberCountFromCache(o1.ChannelId) != 2 { - t.Fatal("should have saved 2 members") - } - - if ss.Channel().GetMemberCountFromCache("junk") != 0 { - t.Fatal("should have saved 0 members") - } - - count = (<-ss.Channel().GetMemberCount(o1.ChannelId, false)).Data.(int64) - if count != 2 { - t.Fatal("should have saved 2 members") - } - - store.Must(ss.Channel().RemoveMember(o2.ChannelId, o2.UserId)) - - count = (<-ss.Channel().GetMemberCount(o1.ChannelId, false)).Data.(int64) - if count != 1 { - t.Fatal("should have removed 1 member") - } - - c1t3 := (<-ss.Channel().Get(c1.Id, false)).Data.(*model.Channel) - t3 := c1t3.ExtraUpdateAt - - if t3 <= t2 || t3 <= t1 { - t.Fatal("Member update time incorrect on delete") - } - - member := (<-ss.Channel().GetMember(o1.ChannelId, o1.UserId)).Data.(*model.ChannelMember) - if member.ChannelId != o1.ChannelId { - t.Fatal("should have go member") - } - - if err := (<-ss.Channel().SaveMember(&o1)).Err; err == nil { - t.Fatal("Should have been a duplicate") - } - - c1t4 := (<-ss.Channel().Get(c1.Id, false)).Data.(*model.Channel) - t4 := c1t4.ExtraUpdateAt - if t4 != t3 { - t.Fatal("Should not update time upon failure") - } -} - -func TestChannelDeleteMemberStore(t *testing.T) { - ss := Setup() - - c1 := model.Channel{} - c1.TeamId = model.NewId() - c1.DisplayName = "NameName" - c1.Name = "zz" + model.NewId() + "b" - c1.Type = model.CHANNEL_OPEN - c1 = *store.Must(ss.Channel().Save(&c1)).(*model.Channel) - - c1t1 := (<-ss.Channel().Get(c1.Id, false)).Data.(*model.Channel) - t1 := c1t1.ExtraUpdateAt - - u1 := model.User{} - u1.Email = model.NewId() - u1.Nickname = model.NewId() - store.Must(ss.User().Save(&u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) - - u2 := model.User{} - u2.Email = model.NewId() - u2.Nickname = model.NewId() - store.Must(ss.User().Save(&u2)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id})) - - o1 := model.ChannelMember{} - o1.ChannelId = c1.Id - o1.UserId = u1.Id - o1.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&o1)) - - o2 := model.ChannelMember{} - o2.ChannelId = c1.Id - o2.UserId = u2.Id - o2.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&o2)) - - c1t2 := (<-ss.Channel().Get(c1.Id, false)).Data.(*model.Channel) - t2 := c1t2.ExtraUpdateAt - - if t2 <= t1 { - t.Fatal("Member update time incorrect") - } - - count := (<-ss.Channel().GetMemberCount(o1.ChannelId, false)).Data.(int64) - if count != 2 { - t.Fatal("should have saved 2 members") - } - - store.Must(ss.Channel().PermanentDeleteMembersByUser(o2.UserId)) - - count = (<-ss.Channel().GetMemberCount(o1.ChannelId, false)).Data.(int64) - if count != 1 { - t.Fatal("should have removed 1 member") - } - - if r1 := <-ss.Channel().PermanentDeleteMembersByChannel(o1.ChannelId); r1.Err != nil { - t.Fatal(r1.Err) - } - - count = (<-ss.Channel().GetMemberCount(o1.ChannelId, false)).Data.(int64) - if count != 0 { - t.Fatal("should have removed all members") - } -} - -func TestChannelStoreGetChannels(t *testing.T) { - ss := Setup() - - o2 := model.Channel{} - o2.TeamId = model.NewId() - o2.DisplayName = "Channel2" - o2.Name = "zz" + model.NewId() + "b" - o2.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o2)) - - o1 := model.Channel{} - o1.TeamId = model.NewId() - o1.DisplayName = "Channel1" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o1)) - - m1 := model.ChannelMember{} - m1.ChannelId = o1.Id - m1.UserId = model.NewId() - m1.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m1)) - - m2 := model.ChannelMember{} - m2.ChannelId = o1.Id - m2.UserId = model.NewId() - m2.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m2)) - - m3 := model.ChannelMember{} - m3.ChannelId = o2.Id - m3.UserId = model.NewId() - m3.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m3)) - - cresult := <-ss.Channel().GetChannels(o1.TeamId, m1.UserId) - list := cresult.Data.(*model.ChannelList) - - if (*list)[0].Id != o1.Id { - t.Fatal("missing channel") - } - - acresult := <-ss.Channel().GetAllChannelMembersForUser(m1.UserId, false) - ids := acresult.Data.(map[string]string) - if _, ok := ids[o1.Id]; !ok { - t.Fatal("missing channel") - } - - acresult2 := <-ss.Channel().GetAllChannelMembersForUser(m1.UserId, true) - ids2 := acresult2.Data.(map[string]string) - if _, ok := ids2[o1.Id]; !ok { - t.Fatal("missing channel") - } - - acresult3 := <-ss.Channel().GetAllChannelMembersForUser(m1.UserId, true) - ids3 := acresult3.Data.(map[string]string) - if _, ok := ids3[o1.Id]; !ok { - t.Fatal("missing channel") - } - - if !ss.Channel().IsUserInChannelUseCache(m1.UserId, o1.Id) { - t.Fatal("missing channel") - } - - if ss.Channel().IsUserInChannelUseCache(m1.UserId, o2.Id) { - t.Fatal("missing channel") - } - - if ss.Channel().IsUserInChannelUseCache(m1.UserId, "blahblah") { - t.Fatal("missing channel") - } - - if ss.Channel().IsUserInChannelUseCache("blahblah", "blahblah") { - t.Fatal("missing channel") - } - - ss.Channel().InvalidateAllChannelMembersForUser(m1.UserId) -} - -func TestChannelStoreGetMoreChannels(t *testing.T) { - ss := Setup() - - o1 := model.Channel{} - o1.TeamId = model.NewId() - o1.DisplayName = "Channel1" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o1)) - - o2 := model.Channel{} - o2.TeamId = model.NewId() - o2.DisplayName = "Channel2" - o2.Name = "zz" + model.NewId() + "b" - o2.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o2)) - - m1 := model.ChannelMember{} - m1.ChannelId = o1.Id - m1.UserId = model.NewId() - m1.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m1)) - - m2 := model.ChannelMember{} - m2.ChannelId = o1.Id - m2.UserId = model.NewId() - m2.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m2)) - - m3 := model.ChannelMember{} - m3.ChannelId = o2.Id - m3.UserId = model.NewId() - m3.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m3)) - - o3 := model.Channel{} - o3.TeamId = o1.TeamId - o3.DisplayName = "ChannelA" - o3.Name = "zz" + model.NewId() + "b" - o3.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o3)) - - o4 := model.Channel{} - o4.TeamId = o1.TeamId - o4.DisplayName = "ChannelB" - o4.Name = "zz" + model.NewId() + "b" - o4.Type = model.CHANNEL_PRIVATE - store.Must(ss.Channel().Save(&o4)) - - o5 := model.Channel{} - o5.TeamId = o1.TeamId - o5.DisplayName = "ChannelC" - o5.Name = "zz" + model.NewId() + "b" - o5.Type = model.CHANNEL_PRIVATE - store.Must(ss.Channel().Save(&o5)) - - cresult := <-ss.Channel().GetMoreChannels(o1.TeamId, m1.UserId, 0, 100) - if cresult.Err != nil { - t.Fatal(cresult.Err) - } - list := cresult.Data.(*model.ChannelList) - - if len(*list) != 1 { - t.Fatal("wrong list") - } - - if (*list)[0].Name != o3.Name { - t.Fatal("missing channel") - } - - o6 := model.Channel{} - o6.TeamId = o1.TeamId - o6.DisplayName = "ChannelA" - o6.Name = "zz" + model.NewId() + "b" - o6.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o6)) - - cresult = <-ss.Channel().GetMoreChannels(o1.TeamId, m1.UserId, 0, 100) - list = cresult.Data.(*model.ChannelList) - - if len(*list) != 2 { - t.Fatal("wrong list length") - } - - cresult = <-ss.Channel().GetMoreChannels(o1.TeamId, m1.UserId, 0, 1) - list = cresult.Data.(*model.ChannelList) - - if len(*list) != 1 { - t.Fatal("wrong list length") - } - - cresult = <-ss.Channel().GetMoreChannels(o1.TeamId, m1.UserId, 1, 1) - list = cresult.Data.(*model.ChannelList) - - if len(*list) != 1 { - t.Fatal("wrong list length") - } - - if r1 := <-ss.Channel().AnalyticsTypeCount(o1.TeamId, model.CHANNEL_OPEN); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(int64) != 3 { - t.Log(r1.Data) - t.Fatal("wrong value") - } - } - - if r1 := <-ss.Channel().AnalyticsTypeCount(o1.TeamId, model.CHANNEL_PRIVATE); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(int64) != 2 { - t.Log(r1.Data) - t.Fatal("wrong value") - } - } -} - -func TestChannelStoreGetPublicChannelsForTeam(t *testing.T) { - ss := Setup() - - o1 := model.Channel{} - o1.TeamId = model.NewId() - o1.DisplayName = "OpenChannel1Team1" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o1)) - - o2 := model.Channel{} - o2.TeamId = model.NewId() - o2.DisplayName = "OpenChannel1Team2" - o2.Name = "zz" + model.NewId() + "b" - o2.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o2)) - - o3 := model.Channel{} - o3.TeamId = o1.TeamId - o3.DisplayName = "PrivateChannel1Team1" - o3.Name = "zz" + model.NewId() + "b" - o3.Type = model.CHANNEL_PRIVATE - store.Must(ss.Channel().Save(&o3)) - - cresult := <-ss.Channel().GetPublicChannelsForTeam(o1.TeamId, 0, 100) - if cresult.Err != nil { - t.Fatal(cresult.Err) - } - list := cresult.Data.(*model.ChannelList) - - if len(*list) != 1 { - t.Fatal("wrong list") - } - - if (*list)[0].Name != o1.Name { - t.Fatal("missing channel") - } - - o4 := model.Channel{} - o4.TeamId = o1.TeamId - o4.DisplayName = "OpenChannel2Team1" - o4.Name = "zz" + model.NewId() + "b" - o4.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o4)) - - cresult = <-ss.Channel().GetPublicChannelsForTeam(o1.TeamId, 0, 100) - list = cresult.Data.(*model.ChannelList) - - if len(*list) != 2 { - t.Fatal("wrong list length") - } - - cresult = <-ss.Channel().GetPublicChannelsForTeam(o1.TeamId, 0, 1) - list = cresult.Data.(*model.ChannelList) - - if len(*list) != 1 { - t.Fatal("wrong list length") - } - - cresult = <-ss.Channel().GetPublicChannelsForTeam(o1.TeamId, 1, 1) - list = cresult.Data.(*model.ChannelList) - - if len(*list) != 1 { - t.Fatal("wrong list length") - } - - if r1 := <-ss.Channel().AnalyticsTypeCount(o1.TeamId, model.CHANNEL_OPEN); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(int64) != 2 { - t.Log(r1.Data) - t.Fatal("wrong value") - } - } - - if r1 := <-ss.Channel().AnalyticsTypeCount(o1.TeamId, model.CHANNEL_PRIVATE); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(int64) != 1 { - t.Log(r1.Data) - t.Fatal("wrong value") - } - } -} - -func TestChannelStoreGetPublicChannelsByIdsForTeam(t *testing.T) { - ss := Setup() - - teamId1 := model.NewId() - - oc1 := model.Channel{} - oc1.TeamId = teamId1 - oc1.DisplayName = "OpenChannel1Team1" - oc1.Name = "zz" + model.NewId() + "b" - oc1.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&oc1)) - - oc2 := model.Channel{} - oc2.TeamId = model.NewId() - oc2.DisplayName = "OpenChannel2TeamOther" - oc2.Name = "zz" + model.NewId() + "b" - oc2.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&oc2)) - - pc3 := model.Channel{} - pc3.TeamId = teamId1 - pc3.DisplayName = "PrivateChannel3Team1" - pc3.Name = "zz" + model.NewId() + "b" - pc3.Type = model.CHANNEL_PRIVATE - store.Must(ss.Channel().Save(&pc3)) - - cids := []string{oc1.Id} - cresult := <-ss.Channel().GetPublicChannelsByIdsForTeam(teamId1, cids) - list := cresult.Data.(*model.ChannelList) - - if len(*list) != 1 { - t.Fatal("should return 1 channel") - } - - if (*list)[0].Id != oc1.Id { - t.Fatal("missing channel") - } - - cids = append(cids, oc2.Id) - cids = append(cids, model.NewId()) - cids = append(cids, pc3.Id) - cresult = <-ss.Channel().GetPublicChannelsByIdsForTeam(teamId1, cids) - list = cresult.Data.(*model.ChannelList) - - if len(*list) != 1 { - t.Fatal("should return 1 channel") - } - - oc4 := model.Channel{} - oc4.TeamId = teamId1 - oc4.DisplayName = "OpenChannel4Team1" - oc4.Name = "zz" + model.NewId() + "b" - oc4.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&oc4)) - - cids = append(cids, oc4.Id) - cresult = <-ss.Channel().GetPublicChannelsByIdsForTeam(teamId1, cids) - list = cresult.Data.(*model.ChannelList) - - if len(*list) != 2 { - t.Fatal("should return 2 channels") - } - - if (*list)[0].Id != oc1.Id { - t.Fatal("missing channel") - } - - if (*list)[1].Id != oc4.Id { - t.Fatal("missing channel") - } - - cids = cids[:0] - cids = append(cids, model.NewId()) - cresult = <-ss.Channel().GetPublicChannelsByIdsForTeam(teamId1, cids) - list = cresult.Data.(*model.ChannelList) - - if len(*list) != 0 { - t.Fatal("should not return a channel") - } -} - -func TestChannelStoreGetChannelCounts(t *testing.T) { - ss := Setup() - - o2 := model.Channel{} - o2.TeamId = model.NewId() - o2.DisplayName = "Channel2" - o2.Name = "zz" + model.NewId() + "b" - o2.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o2)) - - o1 := model.Channel{} - o1.TeamId = model.NewId() - o1.DisplayName = "Channel1" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o1)) - - m1 := model.ChannelMember{} - m1.ChannelId = o1.Id - m1.UserId = model.NewId() - m1.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m1)) - - m2 := model.ChannelMember{} - m2.ChannelId = o1.Id - m2.UserId = model.NewId() - m2.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m2)) - - m3 := model.ChannelMember{} - m3.ChannelId = o2.Id - m3.UserId = model.NewId() - m3.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m3)) - - cresult := <-ss.Channel().GetChannelCounts(o1.TeamId, m1.UserId) - counts := cresult.Data.(*model.ChannelCounts) - - if len(counts.Counts) != 1 { - t.Fatal("wrong number of counts") - } - - if len(counts.UpdateTimes) != 1 { - t.Fatal("wrong number of update times") - } -} - -func TestChannelStoreGetMembersForUser(t *testing.T) { - ss := Setup() - - t1 := model.Team{} - t1.DisplayName = "Name" - t1.Name = model.NewId() - t1.Email = model.NewId() + "@nowhere.com" - t1.Type = model.TEAM_OPEN - store.Must(ss.Team().Save(&t1)) - - o1 := model.Channel{} - o1.TeamId = t1.Id - o1.DisplayName = "Channel1" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o1)) - - o2 := model.Channel{} - o2.TeamId = o1.TeamId - o2.DisplayName = "Channel2" - o2.Name = "zz" + model.NewId() + "b" - o2.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o2)) - - m1 := model.ChannelMember{} - m1.ChannelId = o1.Id - m1.UserId = model.NewId() - m1.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m1)) - - m2 := model.ChannelMember{} - m2.ChannelId = o2.Id - m2.UserId = m1.UserId - m2.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m2)) - - cresult := <-ss.Channel().GetMembersForUser(o1.TeamId, m1.UserId) - members := cresult.Data.(*model.ChannelMembers) - - // no unread messages - if len(*members) != 2 { - t.Fatal("wrong number of members") - } -} - -func TestChannelStoreUpdateLastViewedAt(t *testing.T) { - ss := Setup() - - o1 := model.Channel{} - o1.TeamId = model.NewId() - o1.DisplayName = "Channel1" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_OPEN - o1.TotalMsgCount = 25 - o1.LastPostAt = 12345 - store.Must(ss.Channel().Save(&o1)) - - m1 := model.ChannelMember{} - m1.ChannelId = o1.Id - m1.UserId = model.NewId() - m1.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m1)) - - o2 := model.Channel{} - o2.TeamId = model.NewId() - o2.DisplayName = "Channel1" - o2.Name = "zz" + model.NewId() + "c" - o2.Type = model.CHANNEL_OPEN - o2.TotalMsgCount = 26 - o2.LastPostAt = 123456 - store.Must(ss.Channel().Save(&o2)) - - m2 := model.ChannelMember{} - m2.ChannelId = o2.Id - m2.UserId = m1.UserId - m2.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m2)) - - if result := <-ss.Channel().UpdateLastViewedAt([]string{m1.ChannelId}, m1.UserId); result.Err != nil { - t.Fatal("failed to update", result.Err) - } else if result.Data.(map[string]int64)[o1.Id] != o1.LastPostAt { - t.Fatal("last viewed at time incorrect") - } - - if result := <-ss.Channel().UpdateLastViewedAt([]string{m1.ChannelId, m2.ChannelId}, m1.UserId); result.Err != nil { - t.Fatal("failed to update", result.Err) - } else if result.Data.(map[string]int64)[o2.Id] != o2.LastPostAt { - t.Fatal("last viewed at time incorrect") - } - - rm1 := store.Must(ss.Channel().GetMember(m1.ChannelId, m1.UserId)).(*model.ChannelMember) - assert.Equal(t, rm1.LastViewedAt, o1.LastPostAt) - assert.Equal(t, rm1.LastUpdateAt, o1.LastPostAt) - assert.Equal(t, rm1.MsgCount, o1.TotalMsgCount) - - rm2 := store.Must(ss.Channel().GetMember(m2.ChannelId, m2.UserId)).(*model.ChannelMember) - assert.Equal(t, rm2.LastViewedAt, o2.LastPostAt) - assert.Equal(t, rm2.LastUpdateAt, o2.LastPostAt) - assert.Equal(t, rm2.MsgCount, o2.TotalMsgCount) - - if result := <-ss.Channel().UpdateLastViewedAt([]string{m1.ChannelId}, "missing id"); result.Err != nil { - t.Fatal("failed to update") - } -} - -func TestChannelStoreIncrementMentionCount(t *testing.T) { - ss := Setup() - - o1 := model.Channel{} - o1.TeamId = model.NewId() - o1.DisplayName = "Channel1" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_OPEN - o1.TotalMsgCount = 25 - store.Must(ss.Channel().Save(&o1)) - - m1 := model.ChannelMember{} - m1.ChannelId = o1.Id - m1.UserId = model.NewId() - m1.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m1)) - - err := (<-ss.Channel().IncrementMentionCount(m1.ChannelId, m1.UserId)).Err - if err != nil { - t.Fatal("failed to update") - } - - err = (<-ss.Channel().IncrementMentionCount(m1.ChannelId, "missing id")).Err - if err != nil { - t.Fatal("failed to update") - } - - err = (<-ss.Channel().IncrementMentionCount("missing id", m1.UserId)).Err - if err != nil { - t.Fatal("failed to update") - } - - err = (<-ss.Channel().IncrementMentionCount("missing id", "missing id")).Err - if err != nil { - t.Fatal("failed to update") - } -} - -func TestUpdateChannelMember(t *testing.T) { - ss := Setup() - - userId := model.NewId() - - c1 := &model.Channel{ - TeamId: model.NewId(), - DisplayName: model.NewId(), - Name: model.NewId(), - Type: model.CHANNEL_OPEN, - } - store.Must(ss.Channel().Save(c1)) - - m1 := &model.ChannelMember{ - ChannelId: c1.Id, - UserId: userId, - NotifyProps: model.GetDefaultChannelNotifyProps(), - } - store.Must(ss.Channel().SaveMember(m1)) - - m1.NotifyProps["test"] = "sometext" - if result := <-ss.Channel().UpdateMember(m1); result.Err != nil { - t.Fatal(result.Err) - } - - m1.UserId = "" - if result := <-ss.Channel().UpdateMember(m1); result.Err == nil { - t.Fatal("bad user id - should fail") - } -} - -func TestGetMember(t *testing.T) { - ss := Setup() - - userId := model.NewId() - - c1 := &model.Channel{ - TeamId: model.NewId(), - DisplayName: model.NewId(), - Name: model.NewId(), - Type: model.CHANNEL_OPEN, - } - store.Must(ss.Channel().Save(c1)) - - c2 := &model.Channel{ - TeamId: c1.TeamId, - DisplayName: model.NewId(), - Name: model.NewId(), - Type: model.CHANNEL_OPEN, - } - store.Must(ss.Channel().Save(c2)) - - m1 := &model.ChannelMember{ - ChannelId: c1.Id, - UserId: userId, - NotifyProps: model.GetDefaultChannelNotifyProps(), - } - store.Must(ss.Channel().SaveMember(m1)) - - m2 := &model.ChannelMember{ - ChannelId: c2.Id, - UserId: userId, - NotifyProps: model.GetDefaultChannelNotifyProps(), - } - store.Must(ss.Channel().SaveMember(m2)) - - if result := <-ss.Channel().GetMember(model.NewId(), userId); result.Err == nil { - t.Fatal("should've failed to get member for non-existant channel") - } - - if result := <-ss.Channel().GetMember(c1.Id, model.NewId()); result.Err == nil { - t.Fatal("should've failed to get member for non-existant user") - } - - if result := <-ss.Channel().GetMember(c1.Id, userId); result.Err != nil { - t.Fatal("shouldn't have errored when getting member", result.Err) - } else if member := result.Data.(*model.ChannelMember); member.ChannelId != c1.Id { - t.Fatal("should've gotten member of channel 1") - } else if member.UserId != userId { - t.Fatal("should've gotten member for user") - } - - if result := <-ss.Channel().GetMember(c2.Id, userId); result.Err != nil { - t.Fatal("shouldn't have errored when getting member", result.Err) - } else if member := result.Data.(*model.ChannelMember); member.ChannelId != c2.Id { - t.Fatal("should've gotten member of channel 2") - } else if member.UserId != userId { - t.Fatal("should've gotten member for user") - } - - if result := <-ss.Channel().GetAllChannelMembersNotifyPropsForChannel(c2.Id, false); result.Err != nil { - t.Fatal(result.Err) - } else { - props := result.Data.(map[string]model.StringMap) - if len(props) == 0 { - t.Fatal("should not be empty") - } - } - - if result := <-ss.Channel().GetAllChannelMembersNotifyPropsForChannel(c2.Id, true); result.Err != nil { - t.Fatal(result.Err) - } else { - props := result.Data.(map[string]model.StringMap) - if len(props) == 0 { - t.Fatal("should not be empty") - } - } - - ss.Channel().InvalidateCacheForChannelMembersNotifyProps(c2.Id) -} - -func TestChannelStoreGetMemberForPost(t *testing.T) { - ss := Setup() - - o1 := store.Must(ss.Channel().Save(&model.Channel{ - TeamId: model.NewId(), - DisplayName: "Name", - Name: "zz" + model.NewId() + "b", - Type: model.CHANNEL_OPEN, - })).(*model.Channel) - - m1 := store.Must(ss.Channel().SaveMember(&model.ChannelMember{ - ChannelId: o1.Id, - UserId: model.NewId(), - NotifyProps: model.GetDefaultChannelNotifyProps(), - })).(*model.ChannelMember) - - p1 := store.Must(ss.Post().Save(&model.Post{ - UserId: model.NewId(), - ChannelId: o1.Id, - Message: "test", - })).(*model.Post) - - if r1 := <-ss.Channel().GetMemberForPost(p1.Id, m1.UserId); r1.Err != nil { - t.Fatal(r1.Err) - } else if r1.Data.(*model.ChannelMember).ToJson() != m1.ToJson() { - t.Fatal("invalid returned channel member") - } - - if r2 := <-ss.Channel().GetMemberForPost(p1.Id, model.NewId()); r2.Err == nil { - t.Fatal("shouldn't have returned a member") - } -} - -func TestGetMemberCount(t *testing.T) { - ss := Setup() - - teamId := model.NewId() - - c1 := model.Channel{ - TeamId: teamId, - DisplayName: "Channel1", - Name: "zz" + model.NewId() + "b", - Type: model.CHANNEL_OPEN, - } - store.Must(ss.Channel().Save(&c1)) - - c2 := model.Channel{ - TeamId: teamId, - DisplayName: "Channel2", - Name: "zz" + model.NewId() + "b", - Type: model.CHANNEL_OPEN, - } - store.Must(ss.Channel().Save(&c2)) - - u1 := &model.User{ - Email: model.NewId(), - DeleteAt: 0, - } - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) - - m1 := model.ChannelMember{ - ChannelId: c1.Id, - UserId: u1.Id, - NotifyProps: model.GetDefaultChannelNotifyProps(), - } - store.Must(ss.Channel().SaveMember(&m1)) - - if result := <-ss.Channel().GetMemberCount(c1.Id, false); result.Err != nil { - t.Fatalf("failed to get member count: %v", result.Err) - } else if result.Data.(int64) != 1 { - t.Fatalf("got incorrect member count %v", result.Data) - } - - u2 := model.User{ - Email: model.NewId(), - DeleteAt: 0, - } - store.Must(ss.User().Save(&u2)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id})) - - m2 := model.ChannelMember{ - ChannelId: c1.Id, - UserId: u2.Id, - NotifyProps: model.GetDefaultChannelNotifyProps(), - } - store.Must(ss.Channel().SaveMember(&m2)) - - if result := <-ss.Channel().GetMemberCount(c1.Id, false); result.Err != nil { - t.Fatalf("failed to get member count: %v", result.Err) - } else if result.Data.(int64) != 2 { - t.Fatalf("got incorrect member count %v", result.Data) - } - - // make sure members of other channels aren't counted - u3 := model.User{ - Email: model.NewId(), - DeleteAt: 0, - } - store.Must(ss.User().Save(&u3)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u3.Id})) - - m3 := model.ChannelMember{ - ChannelId: c2.Id, - UserId: u3.Id, - NotifyProps: model.GetDefaultChannelNotifyProps(), - } - store.Must(ss.Channel().SaveMember(&m3)) - - if result := <-ss.Channel().GetMemberCount(c1.Id, false); result.Err != nil { - t.Fatalf("failed to get member count: %v", result.Err) - } else if result.Data.(int64) != 2 { - t.Fatalf("got incorrect member count %v", result.Data) - } - - // make sure inactive users aren't counted - u4 := &model.User{ - Email: model.NewId(), - DeleteAt: 10000, - } - store.Must(ss.User().Save(u4)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u4.Id})) - - m4 := model.ChannelMember{ - ChannelId: c1.Id, - UserId: u4.Id, - NotifyProps: model.GetDefaultChannelNotifyProps(), - } - store.Must(ss.Channel().SaveMember(&m4)) - - if result := <-ss.Channel().GetMemberCount(c1.Id, false); result.Err != nil { - t.Fatalf("failed to get member count: %v", result.Err) - } else if result.Data.(int64) != 2 { - t.Fatalf("got incorrect member count %v", result.Data) - } -} - -func TestUpdateExtrasByUser(t *testing.T) { - ss := Setup() - - teamId := model.NewId() - - c1 := model.Channel{ - TeamId: teamId, - DisplayName: "Channel1", - Name: "zz" + model.NewId() + "b", - Type: model.CHANNEL_OPEN, - } - store.Must(ss.Channel().Save(&c1)) - - c2 := model.Channel{ - TeamId: teamId, - DisplayName: "Channel2", - Name: "zz" + model.NewId() + "b", - Type: model.CHANNEL_OPEN, - } - store.Must(ss.Channel().Save(&c2)) - - u1 := &model.User{ - Email: model.NewId(), - DeleteAt: 0, - } - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) - - m1 := model.ChannelMember{ - ChannelId: c1.Id, - UserId: u1.Id, - NotifyProps: model.GetDefaultChannelNotifyProps(), - } - store.Must(ss.Channel().SaveMember(&m1)) - - u1.DeleteAt = model.GetMillis() - store.Must(ss.User().Update(u1, true)) - - if result := <-ss.Channel().ExtraUpdateByUser(u1.Id, u1.DeleteAt); result.Err != nil { - t.Fatalf("failed to update extras by user: %v", result.Err) - } - - u1.DeleteAt = 0 - store.Must(ss.User().Update(u1, true)) - - if result := <-ss.Channel().ExtraUpdateByUser(u1.Id, u1.DeleteAt); result.Err != nil { - t.Fatalf("failed to update extras by user: %v", result.Err) - } -} - -func TestChannelStoreSearchMore(t *testing.T) { - ss := Setup() - - o1 := model.Channel{} - o1.TeamId = model.NewId() - o1.DisplayName = "ChannelA" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o1)) - - o2 := model.Channel{} - o2.TeamId = model.NewId() - o2.DisplayName = "Channel2" - o2.Name = "zz" + model.NewId() + "b" - o2.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o2)) - - m1 := model.ChannelMember{} - m1.ChannelId = o1.Id - m1.UserId = model.NewId() - m1.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m1)) - - m2 := model.ChannelMember{} - m2.ChannelId = o1.Id - m2.UserId = model.NewId() - m2.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m2)) - - m3 := model.ChannelMember{} - m3.ChannelId = o2.Id - m3.UserId = model.NewId() - m3.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m3)) - - o3 := model.Channel{} - o3.TeamId = o1.TeamId - o3.DisplayName = "ChannelA" - o3.Name = "zz" + model.NewId() + "b" - o3.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o3)) - - o4 := model.Channel{} - o4.TeamId = o1.TeamId - o4.DisplayName = "ChannelB" - o4.Name = "zz" + model.NewId() + "b" - o4.Type = model.CHANNEL_PRIVATE - store.Must(ss.Channel().Save(&o4)) - - o5 := model.Channel{} - o5.TeamId = o1.TeamId - o5.DisplayName = "ChannelC" - o5.Name = "zz" + model.NewId() + "b" - o5.Type = model.CHANNEL_PRIVATE - store.Must(ss.Channel().Save(&o5)) - - if result := <-ss.Channel().SearchMore(m1.UserId, o1.TeamId, "ChannelA"); result.Err != nil { - t.Fatal(result.Err) - } else { - channels := result.Data.(*model.ChannelList) - if len(*channels) == 0 { - t.Fatal("should not be empty") - } - - if (*channels)[0].Name != o3.Name { - t.Fatal("wrong channel returned") - } - } - - if result := <-ss.Channel().SearchMore(m1.UserId, o1.TeamId, o4.Name); result.Err != nil { - t.Fatal(result.Err) - } else { - channels := result.Data.(*model.ChannelList) - if len(*channels) != 0 { - t.Fatal("should be empty") - } - } - - if result := <-ss.Channel().SearchMore(m1.UserId, o1.TeamId, o3.Name); result.Err != nil { - t.Fatal(result.Err) - } else { - channels := result.Data.(*model.ChannelList) - if len(*channels) == 0 { - t.Fatal("should not be empty") - } - - if (*channels)[0].Name != o3.Name { - t.Fatal("wrong channel returned") - } - } - -} - -func TestChannelStoreSearchInTeam(t *testing.T) { - ss := Setup() - - o1 := model.Channel{} - o1.TeamId = model.NewId() - o1.DisplayName = "ChannelA" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o1)) - - o2 := model.Channel{} - o2.TeamId = model.NewId() - o2.DisplayName = "Channel2" - o2.Name = "zz" + model.NewId() + "b" - o2.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o2)) - - m1 := model.ChannelMember{} - m1.ChannelId = o1.Id - m1.UserId = model.NewId() - m1.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m1)) - - m2 := model.ChannelMember{} - m2.ChannelId = o1.Id - m2.UserId = model.NewId() - m2.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m2)) - - m3 := model.ChannelMember{} - m3.ChannelId = o2.Id - m3.UserId = model.NewId() - m3.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m3)) - - o3 := model.Channel{} - o3.TeamId = o1.TeamId - o3.DisplayName = "ChannelA" - o3.Name = "zz" + model.NewId() + "b" - o3.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o3)) - - o4 := model.Channel{} - o4.TeamId = o1.TeamId - o4.DisplayName = "ChannelB" - o4.Name = "zz" + model.NewId() + "b" - o4.Type = model.CHANNEL_PRIVATE - store.Must(ss.Channel().Save(&o4)) - - o5 := model.Channel{} - o5.TeamId = o1.TeamId - o5.DisplayName = "ChannelC" - o5.Name = "zz" + model.NewId() + "b" - o5.Type = model.CHANNEL_PRIVATE - store.Must(ss.Channel().Save(&o5)) - - if result := <-ss.Channel().SearchInTeam(o1.TeamId, "ChannelA"); result.Err != nil { - t.Fatal(result.Err) - } else { - channels := result.Data.(*model.ChannelList) - if len(*channels) != 2 { - t.Fatal("wrong length") - } - } - - if result := <-ss.Channel().SearchInTeam(o1.TeamId, ""); result.Err != nil { - t.Fatal(result.Err) - } else { - channels := result.Data.(*model.ChannelList) - if len(*channels) == 0 { - t.Fatal("should not be empty") - } - } - - if result := <-ss.Channel().SearchInTeam(o1.TeamId, "blargh"); result.Err != nil { - t.Fatal(result.Err) - } else { - channels := result.Data.(*model.ChannelList) - if len(*channels) != 0 { - t.Fatal("should be empty") - } - } -} - -func TestChannelStoreGetMembersByIds(t *testing.T) { - ss := Setup() - - o1 := model.Channel{} - o1.TeamId = model.NewId() - o1.DisplayName = "ChannelA" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o1)) - - m1 := &model.ChannelMember{ChannelId: o1.Id, UserId: model.NewId(), NotifyProps: model.GetDefaultChannelNotifyProps()} - store.Must(ss.Channel().SaveMember(m1)) - - if r := <-ss.Channel().GetMembersByIds(m1.ChannelId, []string{m1.UserId}); r.Err != nil { - t.Fatal(r.Err) - } else { - rm1 := (*r.Data.(*model.ChannelMembers))[0] - - if rm1.ChannelId != m1.ChannelId { - t.Fatal("bad team id") - } - - if rm1.UserId != m1.UserId { - t.Fatal("bad user id") - } - } - - m2 := &model.ChannelMember{ChannelId: o1.Id, UserId: model.NewId(), NotifyProps: model.GetDefaultChannelNotifyProps()} - store.Must(ss.Channel().SaveMember(m2)) - - if r := <-ss.Channel().GetMembersByIds(m1.ChannelId, []string{m1.UserId, m2.UserId, model.NewId()}); r.Err != nil { - t.Fatal(r.Err) - } else { - rm := (*r.Data.(*model.ChannelMembers)) - - if len(rm) != 2 { - t.Fatal("return wrong number of results") - } - } - - if r := <-ss.Channel().GetMembersByIds(m1.ChannelId, []string{}); r.Err == nil { - t.Fatal("empty user ids - should have failed") - } -} - -func TestChannelStoreAnalyticsDeletedTypeCount(t *testing.T) { - ss := Setup() - - o1 := model.Channel{} - o1.TeamId = model.NewId() - o1.DisplayName = "ChannelA" - o1.Name = "zz" + model.NewId() + "b" - o1.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o1)) - - o2 := model.Channel{} - o2.TeamId = model.NewId() - o2.DisplayName = "Channel2" - o2.Name = "zz" + model.NewId() + "b" - o2.Type = model.CHANNEL_OPEN - store.Must(ss.Channel().Save(&o2)) - - p3 := model.Channel{} - p3.TeamId = model.NewId() - p3.DisplayName = "Channel3" - p3.Name = "zz" + model.NewId() + "b" - p3.Type = model.CHANNEL_PRIVATE - store.Must(ss.Channel().Save(&p3)) - - u1 := &model.User{} - u1.Email = model.NewId() - u1.Nickname = model.NewId() - store.Must(ss.User().Save(u1)) - - u2 := &model.User{} - u2.Email = model.NewId() - u2.Nickname = model.NewId() - store.Must(ss.User().Save(u2)) - - var d4 *model.Channel - if result := <-ss.Channel().CreateDirectChannel(u1.Id, u2.Id); result.Err != nil { - t.Fatalf(result.Err.Error()) - } else { - d4 = result.Data.(*model.Channel) - } - - var openStartCount int64 - if result := <-ss.Channel().AnalyticsDeletedTypeCount("", "O"); result.Err != nil { - t.Fatal(result.Err.Error()) - } else { - openStartCount = result.Data.(int64) - } - - var privateStartCount int64 - if result := <-ss.Channel().AnalyticsDeletedTypeCount("", "P"); result.Err != nil { - t.Fatal(result.Err.Error()) - } else { - privateStartCount = result.Data.(int64) - } - - var directStartCount int64 - if result := <-ss.Channel().AnalyticsDeletedTypeCount("", "D"); result.Err != nil { - t.Fatal(result.Err.Error()) - } else { - directStartCount = result.Data.(int64) - } - - store.Must(ss.Channel().Delete(o1.Id, model.GetMillis())) - store.Must(ss.Channel().Delete(o2.Id, model.GetMillis())) - store.Must(ss.Channel().Delete(p3.Id, model.GetMillis())) - store.Must(ss.Channel().Delete(d4.Id, model.GetMillis())) - - if result := <-ss.Channel().AnalyticsDeletedTypeCount("", "O"); result.Err != nil { - t.Fatal(result.Err.Error()) - } else { - if result.Data.(int64) != openStartCount+2 { - t.Fatalf("Wrong open channel deleted count.") - } - } - - if result := <-ss.Channel().AnalyticsDeletedTypeCount("", "P"); result.Err != nil { - t.Fatal(result.Err.Error()) - } else { - if result.Data.(int64) != privateStartCount+1 { - t.Fatalf("Wrong private channel deleted count.") - } - } - - if result := <-ss.Channel().AnalyticsDeletedTypeCount("", "D"); result.Err != nil { - t.Fatal(result.Err.Error()) - } else { - if result.Data.(int64) != directStartCount+1 { - t.Fatalf("Wrong direct channel deleted count.") - } - } -} - -func TestChannelStoreGetPinnedPosts(t *testing.T) { - ss := Setup() - - o1 := store.Must(ss.Channel().Save(&model.Channel{ - TeamId: model.NewId(), - DisplayName: "Name", - Name: "zz" + model.NewId() + "b", - Type: model.CHANNEL_OPEN, - })).(*model.Channel) - - p1 := store.Must(ss.Post().Save(&model.Post{ - UserId: model.NewId(), - ChannelId: o1.Id, - Message: "test", - IsPinned: true, - })).(*model.Post) - - if r1 := <-ss.Channel().GetPinnedPosts(o1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else if r1.Data.(*model.PostList).Posts[p1.Id] == nil { - t.Fatal("didn't return relevant pinned posts") - } - - o2 := store.Must(ss.Channel().Save(&model.Channel{ - TeamId: model.NewId(), - DisplayName: "Name", - Name: "zz" + model.NewId() + "b", - Type: model.CHANNEL_OPEN, - })).(*model.Channel) - - store.Must(ss.Post().Save(&model.Post{ - UserId: model.NewId(), - ChannelId: o2.Id, - Message: "test", - })) - - if r2 := <-ss.Channel().GetPinnedPosts(o2.Id); r2.Err != nil { - t.Fatal(r2.Err) - } else if len(r2.Data.(*model.PostList).Posts) != 0 { - t.Fatal("wasn't supposed to return posts") - } +func TestChannelStore(t *testing.T) { + StoreTest(t, storetest.TestChannelStore) } diff --git a/store/sqlstore/cluster_discovery_store_test.go b/store/sqlstore/cluster_discovery_store_test.go index ce361d59d..b6503ccb8 100644 --- a/store/sqlstore/cluster_discovery_store_test.go +++ b/store/sqlstore/cluster_discovery_store_test.go @@ -6,197 +6,9 @@ package sqlstore import ( "testing" - "time" - - "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store" + "github.com/mattermost/mattermost-server/store/storetest" ) -func TestSqlClusterDiscoveryStore(t *testing.T) { - ss := Setup() - - discovery := &model.ClusterDiscovery{ - ClusterName: "cluster_name", - Hostname: "hostname" + model.NewId(), - Type: "test_test", - } - - if result := <-ss.ClusterDiscovery().Save(discovery); result.Err != nil { - t.Fatal(result.Err) - } - - if result := <-ss.ClusterDiscovery().Cleanup(); result.Err != nil { - t.Fatal(result.Err) - } -} - -func TestSqlClusterDiscoveryStoreDelete(t *testing.T) { - ss := Setup() - - discovery := &model.ClusterDiscovery{ - ClusterName: "cluster_name", - Hostname: "hostname" + model.NewId(), - Type: "test_test", - } - - if result := <-ss.ClusterDiscovery().Save(discovery); result.Err != nil { - t.Fatal(result.Err) - } - - if result := <-ss.ClusterDiscovery().Delete(discovery); result.Err != nil { - t.Fatal(result.Err) - } -} - -func TestSqlClusterDiscoveryStoreLastPing(t *testing.T) { - ss := Setup() - - discovery := &model.ClusterDiscovery{ - ClusterName: "cluster_name_lastPing", - Hostname: "hostname" + model.NewId(), - Type: "test_test_lastPing" + model.NewId(), - } - - if result := <-ss.ClusterDiscovery().Save(discovery); result.Err != nil { - t.Fatal(result.Err) - } - - if result := <-ss.ClusterDiscovery().SetLastPingAt(discovery); result.Err != nil { - t.Fatal(result.Err) - } - - ttime := model.GetMillis() - - time.Sleep(1 * time.Second) - - if result := <-ss.ClusterDiscovery().SetLastPingAt(discovery); result.Err != nil { - t.Fatal(result.Err) - } - - if result := <-ss.ClusterDiscovery().GetAll(discovery.Type, "cluster_name_lastPing"); result.Err != nil { - t.Fatal(result.Err) - } else { - list := result.Data.([]*model.ClusterDiscovery) - - if len(list) != 1 { - t.Fatal("should only be 1 items") - return - } - - if list[0].LastPingAt-ttime < 500 { - t.Fatal("failed to set time") - } - } - - discovery2 := &model.ClusterDiscovery{ - ClusterName: "cluster_name_missing", - Hostname: "hostname" + model.NewId(), - Type: "test_test_missing", - } - - if result := <-ss.ClusterDiscovery().SetLastPingAt(discovery2); result.Err != nil { - t.Fatal(result.Err) - } -} - -func TestSqlClusterDiscoveryStoreExists(t *testing.T) { - ss := Setup() - - discovery := &model.ClusterDiscovery{ - ClusterName: "cluster_name_Exists", - Hostname: "hostname" + model.NewId(), - Type: "test_test_Exists" + model.NewId(), - } - - if result := <-ss.ClusterDiscovery().Save(discovery); result.Err != nil { - t.Fatal(result.Err) - } - - if result := <-ss.ClusterDiscovery().Exists(discovery); result.Err != nil { - t.Fatal(result.Err) - } else { - val := result.Data.(bool) - if !val { - t.Fatal("should be true") - } - } - - discovery.ClusterName = "cluster_name_Exists2" - - if result := <-ss.ClusterDiscovery().Exists(discovery); result.Err != nil { - t.Fatal(result.Err) - } else { - val := result.Data.(bool) - if val { - t.Fatal("should be true") - } - } -} - -func TestSqlClusterDiscoveryGetStore(t *testing.T) { - ss := Setup() - - testType1 := model.NewId() - - discovery1 := &model.ClusterDiscovery{ - ClusterName: "cluster_name", - Hostname: "hostname1", - Type: testType1, - } - store.Must(ss.ClusterDiscovery().Save(discovery1)) - - discovery2 := &model.ClusterDiscovery{ - ClusterName: "cluster_name", - Hostname: "hostname2", - Type: testType1, - } - store.Must(ss.ClusterDiscovery().Save(discovery2)) - - discovery3 := &model.ClusterDiscovery{ - ClusterName: "cluster_name", - Hostname: "hostname3", - Type: testType1, - CreateAt: 1, - LastPingAt: 1, - } - store.Must(ss.ClusterDiscovery().Save(discovery3)) - - testType2 := model.NewId() - - discovery4 := &model.ClusterDiscovery{ - ClusterName: "cluster_name", - Hostname: "hostname1", - Type: testType2, - } - store.Must(ss.ClusterDiscovery().Save(discovery4)) - - if result := <-ss.ClusterDiscovery().GetAll(testType1, "cluster_name"); result.Err != nil { - t.Fatal(result.Err) - } else { - list := result.Data.([]*model.ClusterDiscovery) - - if len(list) != 2 { - t.Fatal("Should only have returned 2") - } - } - - if result := <-ss.ClusterDiscovery().GetAll(testType2, "cluster_name"); result.Err != nil { - t.Fatal(result.Err) - } else { - list := result.Data.([]*model.ClusterDiscovery) - - if len(list) != 1 { - t.Fatal("Should only have returned 1") - } - } - - if result := <-ss.ClusterDiscovery().GetAll(model.NewId(), "cluster_name"); result.Err != nil { - t.Fatal(result.Err) - } else { - list := result.Data.([]*model.ClusterDiscovery) - - if len(list) != 0 { - t.Fatal("shouldn't be any") - } - } +func TestClusterDiscoveryStore(t *testing.T) { + StoreTest(t, storetest.TestClusterDiscoveryStore) } diff --git a/store/sqlstore/command_store_test.go b/store/sqlstore/command_store_test.go index 407eae72e..ee8c00082 100644 --- a/store/sqlstore/command_store_test.go +++ b/store/sqlstore/command_store_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. package sqlstore @@ -6,252 +6,9 @@ package sqlstore import ( "testing" - "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store" + "github.com/mattermost/mattermost-server/store/storetest" ) -func TestCommandStoreSave(t *testing.T) { - ss := Setup() - - o1 := model.Command{} - o1.CreatorId = model.NewId() - o1.Method = model.COMMAND_METHOD_POST - o1.TeamId = model.NewId() - o1.URL = "http://nowhere.com/" - o1.Trigger = "trigger" - - if err := (<-ss.Command().Save(&o1)).Err; err != nil { - t.Fatal("couldn't save item", err) - } - - if err := (<-ss.Command().Save(&o1)).Err; err == nil { - t.Fatal("shouldn't be able to update from save") - } -} - -func TestCommandStoreGet(t *testing.T) { - ss := Setup() - - o1 := &model.Command{} - o1.CreatorId = model.NewId() - o1.Method = model.COMMAND_METHOD_POST - o1.TeamId = model.NewId() - o1.URL = "http://nowhere.com/" - o1.Trigger = "trigger" - - o1 = (<-ss.Command().Save(o1)).Data.(*model.Command) - - if r1 := <-ss.Command().Get(o1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.Command).CreateAt != o1.CreateAt { - t.Fatal("invalid returned command") - } - } - - if err := (<-ss.Command().Get("123")).Err; err == nil { - t.Fatal("Missing id should have failed") - } -} - -func TestCommandStoreGetByTeam(t *testing.T) { - ss := Setup() - - o1 := &model.Command{} - o1.CreatorId = model.NewId() - o1.Method = model.COMMAND_METHOD_POST - o1.TeamId = model.NewId() - o1.URL = "http://nowhere.com/" - o1.Trigger = "trigger" - - o1 = (<-ss.Command().Save(o1)).Data.(*model.Command) - - if r1 := <-ss.Command().GetByTeam(o1.TeamId); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.([]*model.Command)[0].CreateAt != o1.CreateAt { - t.Fatal("invalid returned command") - } - } - - if result := <-ss.Command().GetByTeam("123"); result.Err != nil { - t.Fatal(result.Err) - } else { - if len(result.Data.([]*model.Command)) != 0 { - t.Fatal("no commands should have returned") - } - } -} - -func TestCommandStoreGetByTrigger(t *testing.T) { - ss := Setup() - - o1 := &model.Command{} - o1.CreatorId = model.NewId() - o1.Method = model.COMMAND_METHOD_POST - o1.TeamId = model.NewId() - o1.URL = "http://nowhere.com/" - o1.Trigger = "trigger1" - - o2 := &model.Command{} - o2.CreatorId = model.NewId() - o2.Method = model.COMMAND_METHOD_POST - o2.TeamId = model.NewId() - o2.URL = "http://nowhere.com/" - o2.Trigger = "trigger1" - - o1 = (<-ss.Command().Save(o1)).Data.(*model.Command) - o2 = (<-ss.Command().Save(o2)).Data.(*model.Command) - - if r1 := <-ss.Command().GetByTrigger(o1.TeamId, o1.Trigger); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.Command).Id != o1.Id { - t.Fatal("invalid returned command") - } - } - - store.Must(ss.Command().Delete(o1.Id, model.GetMillis())) - - if result := <-ss.Command().GetByTrigger(o1.TeamId, o1.Trigger); result.Err == nil { - t.Fatal("no commands should have returned") - } -} - -func TestCommandStoreDelete(t *testing.T) { - ss := Setup() - - o1 := &model.Command{} - o1.CreatorId = model.NewId() - o1.Method = model.COMMAND_METHOD_POST - o1.TeamId = model.NewId() - o1.URL = "http://nowhere.com/" - o1.Trigger = "trigger" - - o1 = (<-ss.Command().Save(o1)).Data.(*model.Command) - - if r1 := <-ss.Command().Get(o1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.Command).CreateAt != o1.CreateAt { - t.Fatal("invalid returned command") - } - } - - if r2 := <-ss.Command().Delete(o1.Id, model.GetMillis()); r2.Err != nil { - t.Fatal(r2.Err) - } - - if r3 := (<-ss.Command().Get(o1.Id)); r3.Err == nil { - t.Log(r3.Data) - t.Fatal("Missing id should have failed") - } -} - -func TestCommandStoreDeleteByTeam(t *testing.T) { - ss := Setup() - - o1 := &model.Command{} - o1.CreatorId = model.NewId() - o1.Method = model.COMMAND_METHOD_POST - o1.TeamId = model.NewId() - o1.URL = "http://nowhere.com/" - o1.Trigger = "trigger" - - o1 = (<-ss.Command().Save(o1)).Data.(*model.Command) - - if r1 := <-ss.Command().Get(o1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.Command).CreateAt != o1.CreateAt { - t.Fatal("invalid returned command") - } - } - - if r2 := <-ss.Command().PermanentDeleteByTeam(o1.TeamId); r2.Err != nil { - t.Fatal(r2.Err) - } - - if r3 := (<-ss.Command().Get(o1.Id)); r3.Err == nil { - t.Log(r3.Data) - t.Fatal("Missing id should have failed") - } -} - -func TestCommandStoreDeleteByUser(t *testing.T) { - ss := Setup() - - o1 := &model.Command{} - o1.CreatorId = model.NewId() - o1.Method = model.COMMAND_METHOD_POST - o1.TeamId = model.NewId() - o1.URL = "http://nowhere.com/" - o1.Trigger = "trigger" - - o1 = (<-ss.Command().Save(o1)).Data.(*model.Command) - - if r1 := <-ss.Command().Get(o1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.Command).CreateAt != o1.CreateAt { - t.Fatal("invalid returned command") - } - } - - if r2 := <-ss.Command().PermanentDeleteByUser(o1.CreatorId); r2.Err != nil { - t.Fatal(r2.Err) - } - - if r3 := (<-ss.Command().Get(o1.Id)); r3.Err == nil { - t.Log(r3.Data) - t.Fatal("Missing id should have failed") - } -} - -func TestCommandStoreUpdate(t *testing.T) { - ss := Setup() - - o1 := &model.Command{} - o1.CreatorId = model.NewId() - o1.Method = model.COMMAND_METHOD_POST - o1.TeamId = model.NewId() - o1.URL = "http://nowhere.com/" - o1.Trigger = "trigger" - - o1 = (<-ss.Command().Save(o1)).Data.(*model.Command) - - o1.Token = model.NewId() - - if r2 := <-ss.Command().Update(o1); r2.Err != nil { - t.Fatal(r2.Err) - } -} - -func TestCommandCount(t *testing.T) { - ss := Setup() - - o1 := &model.Command{} - o1.CreatorId = model.NewId() - o1.Method = model.COMMAND_METHOD_POST - o1.TeamId = model.NewId() - o1.URL = "http://nowhere.com/" - o1.Trigger = "trigger" - - o1 = (<-ss.Command().Save(o1)).Data.(*model.Command) - - if r1 := <-ss.Command().AnalyticsCommandCount(""); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(int64) == 0 { - t.Fatal("should be at least 1 command") - } - } - - if r2 := <-ss.Command().AnalyticsCommandCount(o1.TeamId); r2.Err != nil { - t.Fatal(r2.Err) - } else { - if r2.Data.(int64) != 1 { - t.Fatal("should be 1 command") - } - } +func TestCommandStore(t *testing.T) { + StoreTest(t, storetest.TestCommandStore) } diff --git a/store/sqlstore/command_webhook_store_test.go b/store/sqlstore/command_webhook_store_test.go index cc286757f..5460e2f59 100644 --- a/store/sqlstore/command_webhook_store_test.go +++ b/store/sqlstore/command_webhook_store_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. package sqlstore @@ -6,60 +6,9 @@ package sqlstore import ( "testing" - "net/http" - - "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store/storetest" ) func TestCommandWebhookStore(t *testing.T) { - ss := Setup() - - cws := ss.CommandWebhook() - - h1 := &model.CommandWebhook{} - h1.CommandId = model.NewId() - h1.UserId = model.NewId() - h1.ChannelId = model.NewId() - h1 = (<-cws.Save(h1)).Data.(*model.CommandWebhook) - - if r1 := <-cws.Get(h1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if *r1.Data.(*model.CommandWebhook) != *h1 { - t.Fatal("invalid returned webhook") - } - } - - if err := (<-cws.Get("123")).Err; err.StatusCode != http.StatusNotFound { - t.Fatal("Should have set the status as not found for missing id") - } - - h2 := &model.CommandWebhook{} - h2.CreateAt = model.GetMillis() - 2*model.COMMAND_WEBHOOK_LIFETIME - h2.CommandId = model.NewId() - h2.UserId = model.NewId() - h2.ChannelId = model.NewId() - h2 = (<-cws.Save(h2)).Data.(*model.CommandWebhook) - - if err := (<-cws.Get(h2.Id)).Err; err == nil || err.StatusCode != http.StatusNotFound { - t.Fatal("Should have set the status as not found for expired webhook") - } - - cws.Cleanup() - - if err := (<-cws.Get(h1.Id)).Err; err != nil { - t.Fatal("Should have no error getting unexpired webhook") - } - - if err := (<-cws.Get(h2.Id)).Err; err.StatusCode != http.StatusNotFound { - t.Fatal("Should have set the status as not found for expired webhook") - } - - if err := (<-cws.TryUse(h1.Id, 1)).Err; err != nil { - t.Fatal("Should be able to use webhook once") - } - - if err := (<-cws.TryUse(h1.Id, 1)).Err; err == nil || err.StatusCode != http.StatusBadRequest { - t.Fatal("Should be able to use webhook once") - } + StoreTest(t, storetest.TestCommandWebhookStore) } diff --git a/store/sqlstore/compliance_store_test.go b/store/sqlstore/compliance_store_test.go index 16d5e18b3..c4e0b480c 100644 --- a/store/sqlstore/compliance_store_test.go +++ b/store/sqlstore/compliance_store_test.go @@ -5,314 +5,10 @@ package sqlstore import ( "testing" - "time" - "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store" + "github.com/mattermost/mattermost-server/store/storetest" ) -func TestSqlComplianceStore(t *testing.T) { - ss := Setup() - - compliance1 := &model.Compliance{Desc: "Audit for federal subpoena case #22443", UserId: model.NewId(), Status: model.COMPLIANCE_STATUS_FAILED, StartAt: model.GetMillis() - 1, EndAt: model.GetMillis() + 1, Type: model.COMPLIANCE_TYPE_ADHOC} - store.Must(ss.Compliance().Save(compliance1)) - time.Sleep(100 * time.Millisecond) - - compliance2 := &model.Compliance{Desc: "Audit for federal subpoena case #11458", UserId: model.NewId(), Status: model.COMPLIANCE_STATUS_RUNNING, StartAt: model.GetMillis() - 1, EndAt: model.GetMillis() + 1, Type: model.COMPLIANCE_TYPE_ADHOC} - store.Must(ss.Compliance().Save(compliance2)) - time.Sleep(100 * time.Millisecond) - - c := ss.Compliance().GetAll(0, 1000) - result := <-c - compliances := result.Data.(model.Compliances) - - if compliances[0].Status != model.COMPLIANCE_STATUS_RUNNING && compliance2.Id != compliances[0].Id { - t.Fatal() - } - - compliance2.Status = model.COMPLIANCE_STATUS_FAILED - store.Must(ss.Compliance().Update(compliance2)) - - c = ss.Compliance().GetAll(0, 1000) - result = <-c - compliances = result.Data.(model.Compliances) - - if compliances[0].Status != model.COMPLIANCE_STATUS_FAILED && compliance2.Id != compliances[0].Id { - t.Fatal() - } - - c = ss.Compliance().GetAll(0, 1) - result = <-c - compliances = result.Data.(model.Compliances) - - if len(compliances) != 1 { - t.Fatal("should only have returned 1") - } - - c = ss.Compliance().GetAll(1, 1) - result = <-c - compliances = result.Data.(model.Compliances) - - if len(compliances) != 1 { - t.Fatal("should only have returned 1") - } - - rc2 := (<-ss.Compliance().Get(compliance2.Id)).Data.(*model.Compliance) - if rc2.Status != compliance2.Status { - t.Fatal() - } -} - -func TestComplianceExport(t *testing.T) { - ss := Setup() - - time.Sleep(100 * time.Millisecond) - - t1 := &model.Team{} - t1.DisplayName = "DisplayName" - t1.Name = "zz" + model.NewId() + "b" - t1.Email = model.NewId() + "@nowhere.com" - t1.Type = model.TEAM_OPEN - t1 = store.Must(ss.Team().Save(t1)).(*model.Team) - - u1 := &model.User{} - u1.Email = model.NewId() - u1.Username = model.NewId() - u1 = store.Must(ss.User().Save(u1)).(*model.User) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: t1.Id, UserId: u1.Id})) - - u2 := &model.User{} - u2.Email = model.NewId() - u2.Username = model.NewId() - u2 = store.Must(ss.User().Save(u2)).(*model.User) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: t1.Id, UserId: u2.Id})) - - c1 := &model.Channel{} - c1.TeamId = t1.Id - c1.DisplayName = "Channel2" - c1.Name = "zz" + model.NewId() + "b" - c1.Type = model.CHANNEL_OPEN - c1 = store.Must(ss.Channel().Save(c1)).(*model.Channel) - - o1 := &model.Post{} - o1.ChannelId = c1.Id - o1.UserId = u1.Id - o1.CreateAt = model.GetMillis() - o1.Message = "zz" + model.NewId() + "b" - o1 = store.Must(ss.Post().Save(o1)).(*model.Post) - - o1a := &model.Post{} - o1a.ChannelId = c1.Id - o1a.UserId = u1.Id - o1a.CreateAt = o1.CreateAt + 10 - o1a.Message = "zz" + model.NewId() + "b" - o1a = store.Must(ss.Post().Save(o1a)).(*model.Post) - - o2 := &model.Post{} - o2.ChannelId = c1.Id - o2.UserId = u1.Id - o2.CreateAt = o1.CreateAt + 20 - o2.Message = "zz" + model.NewId() + "b" - o2 = store.Must(ss.Post().Save(o2)).(*model.Post) - - o2a := &model.Post{} - o2a.ChannelId = c1.Id - o2a.UserId = u2.Id - o2a.CreateAt = o1.CreateAt + 30 - o2a.Message = "zz" + model.NewId() + "b" - o2a = store.Must(ss.Post().Save(o2a)).(*model.Post) - - time.Sleep(100 * time.Millisecond) - - cr1 := &model.Compliance{Desc: "test" + model.NewId(), StartAt: o1.CreateAt - 1, EndAt: o2a.CreateAt + 1} - if r1 := <-ss.Compliance().ComplianceExport(cr1); r1.Err != nil { - t.Fatal(r1.Err) - } else { - cposts := r1.Data.([]*model.CompliancePost) - - if len(cposts) != 4 { - t.Fatal("return wrong results length") - } - - if cposts[0].PostId != o1.Id { - t.Fatal("Wrong sort") - } - - if cposts[3].PostId != o2a.Id { - t.Fatal("Wrong sort") - } - } - - cr2 := &model.Compliance{Desc: "test" + model.NewId(), StartAt: o1.CreateAt - 1, EndAt: o2a.CreateAt + 1, Emails: u2.Email} - if r1 := <-ss.Compliance().ComplianceExport(cr2); r1.Err != nil { - t.Fatal(r1.Err) - } else { - cposts := r1.Data.([]*model.CompliancePost) - - if len(cposts) != 1 { - t.Fatal("return wrong results length") - } - - if cposts[0].PostId != o2a.Id { - t.Fatal("Wrong sort") - } - } - - cr3 := &model.Compliance{Desc: "test" + model.NewId(), StartAt: o1.CreateAt - 1, EndAt: o2a.CreateAt + 1, Emails: u2.Email + ", " + u1.Email} - if r1 := <-ss.Compliance().ComplianceExport(cr3); r1.Err != nil { - t.Fatal(r1.Err) - } else { - cposts := r1.Data.([]*model.CompliancePost) - - if len(cposts) != 4 { - t.Fatal("return wrong results length") - } - - if cposts[0].PostId != o1.Id { - t.Fatal("Wrong sort") - } - - if cposts[3].PostId != o2a.Id { - t.Fatal("Wrong sort") - } - } - - cr4 := &model.Compliance{Desc: "test" + model.NewId(), StartAt: o1.CreateAt - 1, EndAt: o2a.CreateAt + 1, Keywords: o2a.Message} - if r1 := <-ss.Compliance().ComplianceExport(cr4); r1.Err != nil { - t.Fatal(r1.Err) - } else { - cposts := r1.Data.([]*model.CompliancePost) - - if len(cposts) != 1 { - t.Fatal("return wrong results length") - } - - if cposts[0].PostId != o2a.Id { - t.Fatal("Wrong sort") - } - } - - cr5 := &model.Compliance{Desc: "test" + model.NewId(), StartAt: o1.CreateAt - 1, EndAt: o2a.CreateAt + 1, Keywords: o2a.Message + " " + o1.Message} - if r1 := <-ss.Compliance().ComplianceExport(cr5); r1.Err != nil { - t.Fatal(r1.Err) - } else { - cposts := r1.Data.([]*model.CompliancePost) - - if len(cposts) != 2 { - t.Fatal("return wrong results length") - } - - if cposts[0].PostId != o1.Id { - t.Fatal("Wrong sort") - } - } - - cr6 := &model.Compliance{Desc: "test" + model.NewId(), StartAt: o1.CreateAt - 1, EndAt: o2a.CreateAt + 1, Emails: u2.Email + ", " + u1.Email, Keywords: o2a.Message + " " + o1.Message} - if r1 := <-ss.Compliance().ComplianceExport(cr6); r1.Err != nil { - t.Fatal(r1.Err) - } else { - cposts := r1.Data.([]*model.CompliancePost) - - if len(cposts) != 2 { - t.Fatal("return wrong results length") - } - - if cposts[0].PostId != o1.Id { - t.Fatal("Wrong sort") - } - - if cposts[1].PostId != o2a.Id { - t.Fatal("Wrong sort") - } - } -} - -func TestComplianceExportDirectMessages(t *testing.T) { - ss := Setup() - - time.Sleep(100 * time.Millisecond) - - t1 := &model.Team{} - t1.DisplayName = "DisplayName" - t1.Name = "zz" + model.NewId() + "b" - t1.Email = model.NewId() + "@nowhere.com" - t1.Type = model.TEAM_OPEN - t1 = store.Must(ss.Team().Save(t1)).(*model.Team) - - u1 := &model.User{} - u1.Email = model.NewId() - u1.Username = model.NewId() - u1 = store.Must(ss.User().Save(u1)).(*model.User) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: t1.Id, UserId: u1.Id})) - - u2 := &model.User{} - u2.Email = model.NewId() - u2.Username = model.NewId() - u2 = store.Must(ss.User().Save(u2)).(*model.User) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: t1.Id, UserId: u2.Id})) - - c1 := &model.Channel{} - c1.TeamId = t1.Id - c1.DisplayName = "Channel2" - c1.Name = "zz" + model.NewId() + "b" - c1.Type = model.CHANNEL_OPEN - c1 = store.Must(ss.Channel().Save(c1)).(*model.Channel) - - cDM := store.Must(ss.Channel().CreateDirectChannel(u1.Id, u2.Id)).(*model.Channel) - - o1 := &model.Post{} - o1.ChannelId = c1.Id - o1.UserId = u1.Id - o1.CreateAt = model.GetMillis() - o1.Message = "zz" + model.NewId() + "b" - o1 = store.Must(ss.Post().Save(o1)).(*model.Post) - - o1a := &model.Post{} - o1a.ChannelId = c1.Id - o1a.UserId = u1.Id - o1a.CreateAt = o1.CreateAt + 10 - o1a.Message = "zz" + model.NewId() + "b" - o1a = store.Must(ss.Post().Save(o1a)).(*model.Post) - - o2 := &model.Post{} - o2.ChannelId = c1.Id - o2.UserId = u1.Id - o2.CreateAt = o1.CreateAt + 20 - o2.Message = "zz" + model.NewId() + "b" - o2 = store.Must(ss.Post().Save(o2)).(*model.Post) - - o2a := &model.Post{} - o2a.ChannelId = c1.Id - o2a.UserId = u2.Id - o2a.CreateAt = o1.CreateAt + 30 - o2a.Message = "zz" + model.NewId() + "b" - o2a = store.Must(ss.Post().Save(o2a)).(*model.Post) - - o3 := &model.Post{} - o3.ChannelId = cDM.Id - o3.UserId = u1.Id - o3.CreateAt = o1.CreateAt + 40 - o3.Message = "zz" + model.NewId() + "b" - o3 = store.Must(ss.Post().Save(o3)).(*model.Post) - - time.Sleep(100 * time.Millisecond) - - cr1 := &model.Compliance{Desc: "test" + model.NewId(), StartAt: o1.CreateAt - 1, EndAt: o3.CreateAt + 1, Emails: u1.Email} - if r1 := <-ss.Compliance().ComplianceExport(cr1); r1.Err != nil { - t.Fatal(r1.Err) - } else { - cposts := r1.Data.([]*model.CompliancePost) - - if len(cposts) != 4 { - t.Fatal("return wrong results length") - } - - if cposts[0].PostId != o1.Id { - t.Fatal("Wrong sort") - } - - if cposts[len(cposts)-1].PostId != o3.Id { - t.Fatal("Wrong sort") - } - } +func TestComplianceStore(t *testing.T) { + StoreTest(t, storetest.TestComplianceStore) } diff --git a/store/sqlstore/emoji_store_test.go b/store/sqlstore/emoji_store_test.go index 9754e2b47..6f5f1cc52 100644 --- a/store/sqlstore/emoji_store_test.go +++ b/store/sqlstore/emoji_store_test.go @@ -1,176 +1,14 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. package sqlstore import ( "testing" - "time" - "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store" + "github.com/mattermost/mattermost-server/store/storetest" ) -func TestEmojiSaveDelete(t *testing.T) { - ss := Setup() - - emoji1 := &model.Emoji{ - CreatorId: model.NewId(), - Name: model.NewId(), - } - - if result := <-ss.Emoji().Save(emoji1); result.Err != nil { - t.Fatal(result.Err) - } - - if len(emoji1.Id) != 26 { - t.Fatal("should've set id for emoji") - } - - emoji2 := model.Emoji{ - CreatorId: model.NewId(), - Name: emoji1.Name, - } - if result := <-ss.Emoji().Save(&emoji2); result.Err == nil { - t.Fatal("shouldn't be able to save emoji with duplicate name") - } - - if result := <-ss.Emoji().Delete(emoji1.Id, time.Now().Unix()); result.Err != nil { - t.Fatal(result.Err) - } - - if result := <-ss.Emoji().Save(&emoji2); result.Err != nil { - t.Fatal("should be able to save emoji with duplicate name now that original has been deleted", result.Err) - } - - if result := <-ss.Emoji().Delete(emoji2.Id, time.Now().Unix()+1); result.Err != nil { - t.Fatal(result.Err) - } -} - -func TestEmojiGet(t *testing.T) { - ss := Setup() - - emojis := []model.Emoji{ - { - CreatorId: model.NewId(), - Name: model.NewId(), - }, - { - CreatorId: model.NewId(), - Name: model.NewId(), - }, - { - CreatorId: model.NewId(), - Name: model.NewId(), - }, - } - - for i, emoji := range emojis { - emojis[i] = *store.Must(ss.Emoji().Save(&emoji)).(*model.Emoji) - } - defer func() { - for _, emoji := range emojis { - store.Must(ss.Emoji().Delete(emoji.Id, time.Now().Unix())) - } - }() - - for _, emoji := range emojis { - if result := <-ss.Emoji().Get(emoji.Id, false); result.Err != nil { - t.Fatalf("failed to get emoji with id %v: %v", emoji.Id, result.Err) - } - } - - for _, emoji := range emojis { - if result := <-ss.Emoji().Get(emoji.Id, true); result.Err != nil { - t.Fatalf("failed to get emoji with id %v: %v", emoji.Id, result.Err) - } - } - - for _, emoji := range emojis { - if result := <-ss.Emoji().Get(emoji.Id, true); result.Err != nil { - t.Fatalf("failed to get emoji with id %v: %v", emoji.Id, result.Err) - } - } -} - -func TestEmojiGetByName(t *testing.T) { - ss := Setup() - - emojis := []model.Emoji{ - { - CreatorId: model.NewId(), - Name: model.NewId(), - }, - { - CreatorId: model.NewId(), - Name: model.NewId(), - }, - { - CreatorId: model.NewId(), - Name: model.NewId(), - }, - } - - for i, emoji := range emojis { - emojis[i] = *store.Must(ss.Emoji().Save(&emoji)).(*model.Emoji) - } - defer func() { - for _, emoji := range emojis { - store.Must(ss.Emoji().Delete(emoji.Id, time.Now().Unix())) - } - }() - - for _, emoji := range emojis { - if result := <-ss.Emoji().GetByName(emoji.Name); result.Err != nil { - t.Fatalf("failed to get emoji with name %v: %v", emoji.Name, result.Err) - } - } -} - -func TestEmojiGetList(t *testing.T) { - ss := Setup() - - emojis := []model.Emoji{ - { - CreatorId: model.NewId(), - Name: model.NewId(), - }, - { - CreatorId: model.NewId(), - Name: model.NewId(), - }, - { - CreatorId: model.NewId(), - Name: model.NewId(), - }, - } - - for i, emoji := range emojis { - emojis[i] = *store.Must(ss.Emoji().Save(&emoji)).(*model.Emoji) - } - defer func() { - for _, emoji := range emojis { - store.Must(ss.Emoji().Delete(emoji.Id, time.Now().Unix())) - } - }() - - if result := <-ss.Emoji().GetList(0, 100); result.Err != nil { - t.Fatal(result.Err) - } else { - for _, emoji := range emojis { - found := false - - for _, savedEmoji := range result.Data.([]*model.Emoji) { - if emoji.Id == savedEmoji.Id { - found = true - break - } - } - - if !found { - t.Fatalf("failed to get emoji with id %v", emoji.Id) - } - } - } +func TestEmojiStore(t *testing.T) { + StoreTest(t, storetest.TestEmojiStore) } diff --git a/store/sqlstore/file_info_store_test.go b/store/sqlstore/file_info_store_test.go index 8ddf34e19..c1295ee54 100644 --- a/store/sqlstore/file_info_store_test.go +++ b/store/sqlstore/file_info_store_test.go @@ -1,300 +1,14 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. package sqlstore import ( - "fmt" "testing" - "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store" + "github.com/mattermost/mattermost-server/store/storetest" ) -func TestFileInfoSaveGet(t *testing.T) { - ss := Setup() - - info := &model.FileInfo{ - CreatorId: model.NewId(), - Path: "file.txt", - } - - if result := <-ss.FileInfo().Save(info); result.Err != nil { - t.Fatal(result.Err) - } else if returned := result.Data.(*model.FileInfo); len(returned.Id) == 0 { - t.Fatal("should've assigned an id to FileInfo") - } else { - info = returned - } - defer func() { - <-ss.FileInfo().PermanentDelete(info.Id) - }() - - if result := <-ss.FileInfo().Get(info.Id); result.Err != nil { - t.Fatal(result.Err) - } else if returned := result.Data.(*model.FileInfo); returned.Id != info.Id { - t.Log(info) - t.Log(returned) - t.Fatal("should've returned correct FileInfo") - } - - info2 := store.Must(ss.FileInfo().Save(&model.FileInfo{ - CreatorId: model.NewId(), - Path: "file.txt", - DeleteAt: 123, - })).(*model.FileInfo) - - if result := <-ss.FileInfo().Get(info2.Id); result.Err == nil { - t.Fatal("shouldn't have gotten deleted file") - } - defer func() { - <-ss.FileInfo().PermanentDelete(info2.Id) - }() -} - -func TestFileInfoSaveGetByPath(t *testing.T) { - ss := Setup() - - info := &model.FileInfo{ - CreatorId: model.NewId(), - Path: fmt.Sprintf("%v/file.txt", model.NewId()), - } - - if result := <-ss.FileInfo().Save(info); result.Err != nil { - t.Fatal(result.Err) - } else if returned := result.Data.(*model.FileInfo); len(returned.Id) == 0 { - t.Fatal("should've assigned an id to FileInfo") - } else { - info = returned - } - defer func() { - <-ss.FileInfo().PermanentDelete(info.Id) - }() - - if result := <-ss.FileInfo().GetByPath(info.Path); result.Err != nil { - t.Fatal(result.Err) - } else if returned := result.Data.(*model.FileInfo); returned.Id != info.Id { - t.Log(info) - t.Log(returned) - t.Fatal("should've returned correct FileInfo") - } - - info2 := store.Must(ss.FileInfo().Save(&model.FileInfo{ - CreatorId: model.NewId(), - Path: "file.txt", - DeleteAt: 123, - })).(*model.FileInfo) - - if result := <-ss.FileInfo().GetByPath(info2.Id); result.Err == nil { - t.Fatal("shouldn't have gotten deleted file") - } - defer func() { - <-ss.FileInfo().PermanentDelete(info2.Id) - }() -} - -func TestFileInfoGetForPost(t *testing.T) { - ss := Setup() - - userId := model.NewId() - postId := model.NewId() - - infos := []*model.FileInfo{ - { - PostId: postId, - CreatorId: userId, - Path: "file.txt", - }, - { - PostId: postId, - CreatorId: userId, - Path: "file.txt", - }, - { - PostId: postId, - CreatorId: userId, - Path: "file.txt", - DeleteAt: 123, - }, - { - PostId: model.NewId(), - CreatorId: userId, - Path: "file.txt", - }, - } - - for i, info := range infos { - infos[i] = store.Must(ss.FileInfo().Save(info)).(*model.FileInfo) - defer func(id string) { - <-ss.FileInfo().PermanentDelete(id) - }(infos[i].Id) - } - - if result := <-ss.FileInfo().GetForPost(postId, true, false); result.Err != nil { - t.Fatal(result.Err) - } else if returned := result.Data.([]*model.FileInfo); len(returned) != 2 { - t.Fatal("should've returned exactly 2 file infos") - } - - if result := <-ss.FileInfo().GetForPost(postId, false, false); result.Err != nil { - t.Fatal(result.Err) - } else if returned := result.Data.([]*model.FileInfo); len(returned) != 2 { - t.Fatal("should've returned exactly 2 file infos") - } - - if result := <-ss.FileInfo().GetForPost(postId, true, true); result.Err != nil { - t.Fatal(result.Err) - } else if returned := result.Data.([]*model.FileInfo); len(returned) != 2 { - t.Fatal("should've returned exactly 2 file infos") - } -} - -func TestFileInfoAttachToPost(t *testing.T) { - ss := Setup() - - userId := model.NewId() - postId := model.NewId() - - info1 := store.Must(ss.FileInfo().Save(&model.FileInfo{ - CreatorId: userId, - Path: "file.txt", - })).(*model.FileInfo) - defer func() { - <-ss.FileInfo().PermanentDelete(info1.Id) - }() - - if len(info1.PostId) != 0 { - t.Fatal("file shouldn't have a PostId") - } - - if result := <-ss.FileInfo().AttachToPost(info1.Id, postId); result.Err != nil { - t.Fatal(result.Err) - } else { - info1 = store.Must(ss.FileInfo().Get(info1.Id)).(*model.FileInfo) - } - - if len(info1.PostId) == 0 { - t.Fatal("file should now have a PostId") - } - - info2 := store.Must(ss.FileInfo().Save(&model.FileInfo{ - CreatorId: userId, - Path: "file.txt", - })).(*model.FileInfo) - defer func() { - <-ss.FileInfo().PermanentDelete(info2.Id) - }() - - if result := <-ss.FileInfo().AttachToPost(info2.Id, postId); result.Err != nil { - t.Fatal(result.Err) - } else { - info2 = store.Must(ss.FileInfo().Get(info2.Id)).(*model.FileInfo) - } - - if result := <-ss.FileInfo().GetForPost(postId, true, false); result.Err != nil { - t.Fatal(result.Err) - } else if infos := result.Data.([]*model.FileInfo); len(infos) != 2 { - t.Fatal("should've returned exactly 2 file infos") - } -} - -func TestFileInfoDeleteForPost(t *testing.T) { - ss := Setup() - - userId := model.NewId() - postId := model.NewId() - - infos := []*model.FileInfo{ - { - PostId: postId, - CreatorId: userId, - Path: "file.txt", - }, - { - PostId: postId, - CreatorId: userId, - Path: "file.txt", - }, - { - PostId: postId, - CreatorId: userId, - Path: "file.txt", - DeleteAt: 123, - }, - { - PostId: model.NewId(), - CreatorId: userId, - Path: "file.txt", - }, - } - - for i, info := range infos { - infos[i] = store.Must(ss.FileInfo().Save(info)).(*model.FileInfo) - defer func(id string) { - <-ss.FileInfo().PermanentDelete(id) - }(infos[i].Id) - } - - if result := <-ss.FileInfo().DeleteForPost(postId); result.Err != nil { - t.Fatal(result.Err) - } - - if infos := store.Must(ss.FileInfo().GetForPost(postId, true, false)).([]*model.FileInfo); len(infos) != 0 { - t.Fatal("shouldn't have returned any file infos") - } -} - -func TestFileInfoPermanentDelete(t *testing.T) { - ss := Setup() - - info := store.Must(ss.FileInfo().Save(&model.FileInfo{ - PostId: model.NewId(), - CreatorId: model.NewId(), - Path: "file.txt", - })).(*model.FileInfo) - - if result := <-ss.FileInfo().PermanentDelete(info.Id); result.Err != nil { - t.Fatal(result.Err) - } -} - -func TestFileInfoPermanentDeleteBatch(t *testing.T) { - ss := Setup() - - postId := model.NewId() - - store.Must(ss.FileInfo().Save(&model.FileInfo{ - PostId: postId, - CreatorId: model.NewId(), - Path: "file.txt", - CreateAt: 1000, - })) - - store.Must(ss.FileInfo().Save(&model.FileInfo{ - PostId: postId, - CreatorId: model.NewId(), - Path: "file.txt", - CreateAt: 1200, - })) - - store.Must(ss.FileInfo().Save(&model.FileInfo{ - PostId: postId, - CreatorId: model.NewId(), - Path: "file.txt", - CreateAt: 2000, - })) - - if result := <-ss.FileInfo().GetForPost(postId, true, false); result.Err != nil { - t.Fatal(result.Err) - } else if len(result.Data.([]*model.FileInfo)) != 3 { - t.Fatal("Expected 3 fileInfos") - } - - store.Must(ss.FileInfo().PermanentDeleteBatch(1500, 1000)) - - if result := <-ss.FileInfo().GetForPost(postId, true, false); result.Err != nil { - t.Fatal(result.Err) - } else if len(result.Data.([]*model.FileInfo)) != 1 { - t.Fatal("Expected 3 fileInfos") - } +func TestFileInfoStore(t *testing.T) { + StoreTest(t, storetest.TestFileInfoStore) } diff --git a/store/sqlstore/job_store_test.go b/store/sqlstore/job_store_test.go index 38686c4e5..f917c8647 100644 --- a/store/sqlstore/job_store_test.go +++ b/store/sqlstore/job_store_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. package sqlstore @@ -6,509 +6,9 @@ package sqlstore import ( "testing" - "time" - - "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store" - "github.com/stretchr/testify/assert" + "github.com/mattermost/mattermost-server/store/storetest" ) -func TestJobSaveGet(t *testing.T) { - ss := Setup() - - job := &model.Job{ - Id: model.NewId(), - Type: model.NewId(), - Status: model.NewId(), - Data: map[string]string{ - "Processed": "0", - "Total": "12345", - "LastProcessed": "abcd", - }, - } - - if result := <-ss.Job().Save(job); result.Err != nil { - t.Fatal(result.Err) - } - - defer func() { - <-ss.Job().Delete(job.Id) - }() - - if result := <-ss.Job().Get(job.Id); result.Err != nil { - t.Fatal(result.Err) - } else if received := result.Data.(*model.Job); received.Id != job.Id { - t.Fatal("received incorrect job after save") - } else if received.Data["Total"] != "12345" { - t.Fatal("data field was not retrieved successfully:", received.Data) - } -} - -func TestJobGetAllByType(t *testing.T) { - ss := Setup() - - jobType := model.NewId() - - jobs := []*model.Job{ - { - Id: model.NewId(), - Type: jobType, - }, - { - Id: model.NewId(), - Type: jobType, - }, - { - Id: model.NewId(), - Type: model.NewId(), - }, - } - - for _, job := range jobs { - store.Must(ss.Job().Save(job)) - defer ss.Job().Delete(job.Id) - } - - if result := <-ss.Job().GetAllByType(jobType); result.Err != nil { - t.Fatal(result.Err) - } else if received := result.Data.([]*model.Job); len(received) != 2 { - t.Fatal("received wrong number of jobs") - } else if received[0].Id != jobs[0].Id && received[1].Id != jobs[0].Id { - t.Fatal("should've received first jobs") - } else if received[0].Id != jobs[1].Id && received[1].Id != jobs[1].Id { - t.Fatal("should've received second jobs") - } -} - -func TestJobGetAllByTypePage(t *testing.T) { - ss := Setup() - - jobType := model.NewId() - - jobs := []*model.Job{ - { - Id: model.NewId(), - Type: jobType, - CreateAt: 1000, - }, - { - Id: model.NewId(), - Type: jobType, - CreateAt: 999, - }, - { - Id: model.NewId(), - Type: jobType, - CreateAt: 1001, - }, - { - Id: model.NewId(), - Type: model.NewId(), - CreateAt: 1002, - }, - } - - for _, job := range jobs { - store.Must(ss.Job().Save(job)) - defer ss.Job().Delete(job.Id) - } - - if result := <-ss.Job().GetAllByTypePage(jobType, 0, 2); result.Err != nil { - t.Fatal(result.Err) - } else if received := result.Data.([]*model.Job); len(received) != 2 { - t.Fatal("received wrong number of jobs") - } else if received[0].Id != jobs[2].Id { - t.Fatal("should've received newest job first") - } else if received[1].Id != jobs[0].Id { - t.Fatal("should've received second newest job second") - } - - if result := <-ss.Job().GetAllByTypePage(jobType, 2, 2); result.Err != nil { - t.Fatal(result.Err) - } else if received := result.Data.([]*model.Job); len(received) != 1 { - t.Fatal("received wrong number of jobs") - } else if received[0].Id != jobs[1].Id { - t.Fatal("should've received oldest job last") - } -} - -func TestJobGetAllPage(t *testing.T) { - ss := Setup() - - jobType := model.NewId() - createAtTime := model.GetMillis() - - jobs := []*model.Job{ - { - Id: model.NewId(), - Type: jobType, - CreateAt: createAtTime + 1, - }, - { - Id: model.NewId(), - Type: jobType, - CreateAt: createAtTime, - }, - { - Id: model.NewId(), - Type: jobType, - CreateAt: createAtTime + 2, - }, - } - - for _, job := range jobs { - store.Must(ss.Job().Save(job)) - defer ss.Job().Delete(job.Id) - } - - if result := <-ss.Job().GetAllPage(0, 2); result.Err != nil { - t.Fatal(result.Err) - } else if received := result.Data.([]*model.Job); len(received) != 2 { - t.Fatal("received wrong number of jobs") - } else if received[0].Id != jobs[2].Id { - t.Fatal("should've received newest job first") - } else if received[1].Id != jobs[0].Id { - t.Fatal("should've received second newest job second") - } - - if result := <-ss.Job().GetAllPage(2, 2); result.Err != nil { - t.Fatal(result.Err) - } else if received := result.Data.([]*model.Job); len(received) < 1 { - t.Fatal("received wrong number of jobs") - } else if received[0].Id != jobs[1].Id { - t.Fatal("should've received oldest job last") - } -} - -func TestJobGetAllByStatus(t *testing.T) { - ss := Setup() - - jobType := model.NewId() - status := model.NewId() - - jobs := []*model.Job{ - { - Id: model.NewId(), - Type: jobType, - CreateAt: 1000, - Status: status, - Data: map[string]string{ - "test": "data", - }, - }, - { - Id: model.NewId(), - Type: jobType, - CreateAt: 999, - Status: status, - }, - { - Id: model.NewId(), - Type: jobType, - CreateAt: 1001, - Status: status, - }, - { - Id: model.NewId(), - Type: jobType, - CreateAt: 1002, - Status: model.NewId(), - }, - } - - for _, job := range jobs { - store.Must(ss.Job().Save(job)) - defer ss.Job().Delete(job.Id) - } - - if result := <-ss.Job().GetAllByStatus(status); result.Err != nil { - t.Fatal(result.Err) - } else if received := result.Data.([]*model.Job); len(received) != 3 { - t.Fatal("received wrong number of jobs") - } else if received[0].Id != jobs[1].Id || received[1].Id != jobs[0].Id || received[2].Id != jobs[2].Id { - t.Fatal("should've received jobs ordered by CreateAt time") - } else if received[1].Data["test"] != "data" { - t.Fatal("should've received job data field back as saved") - } -} - -func TestJobStoreGetNewestJobByStatusAndType(t *testing.T) { - ss := Setup() - - jobType1 := model.NewId() - jobType2 := model.NewId() - status1 := model.NewId() - status2 := model.NewId() - - jobs := []*model.Job{ - { - Id: model.NewId(), - Type: jobType1, - CreateAt: 1001, - Status: status1, - }, - { - Id: model.NewId(), - Type: jobType1, - CreateAt: 1000, - Status: status1, - }, - { - Id: model.NewId(), - Type: jobType2, - CreateAt: 1003, - Status: status1, - }, - { - Id: model.NewId(), - Type: jobType1, - CreateAt: 1004, - Status: status2, - }, - } - - for _, job := range jobs { - store.Must(ss.Job().Save(job)) - defer ss.Job().Delete(job.Id) - } - - result := <-ss.Job().GetNewestJobByStatusAndType(status1, jobType1) - assert.Nil(t, result.Err) - assert.EqualValues(t, jobs[0].Id, result.Data.(*model.Job).Id) - - result = <-ss.Job().GetNewestJobByStatusAndType(model.NewId(), model.NewId()) - assert.Nil(t, result.Err) - assert.Nil(t, result.Data.(*model.Job)) -} - -func TestJobStoreGetCountByStatusAndType(t *testing.T) { - ss := Setup() - - jobType1 := model.NewId() - jobType2 := model.NewId() - status1 := model.NewId() - status2 := model.NewId() - - jobs := []*model.Job{ - { - Id: model.NewId(), - Type: jobType1, - CreateAt: 1000, - Status: status1, - }, - { - Id: model.NewId(), - Type: jobType1, - CreateAt: 999, - Status: status1, - }, - { - Id: model.NewId(), - Type: jobType2, - CreateAt: 1001, - Status: status1, - }, - { - Id: model.NewId(), - Type: jobType1, - CreateAt: 1002, - Status: status2, - }, - } - - for _, job := range jobs { - store.Must(ss.Job().Save(job)) - defer ss.Job().Delete(job.Id) - } - - result := <-ss.Job().GetCountByStatusAndType(status1, jobType1) - assert.Nil(t, result.Err) - assert.EqualValues(t, 2, result.Data.(int64)) - - result = <-ss.Job().GetCountByStatusAndType(status2, jobType2) - assert.Nil(t, result.Err) - assert.EqualValues(t, 0, result.Data.(int64)) - - result = <-ss.Job().GetCountByStatusAndType(status1, jobType2) - assert.Nil(t, result.Err) - assert.EqualValues(t, 1, result.Data.(int64)) - - result = <-ss.Job().GetCountByStatusAndType(status2, jobType1) - assert.Nil(t, result.Err) - assert.EqualValues(t, 1, result.Data.(int64)) -} - -func TestJobUpdateOptimistically(t *testing.T) { - ss := Setup() - - job := &model.Job{ - Id: model.NewId(), - Type: model.JOB_TYPE_DATA_RETENTION, - CreateAt: model.GetMillis(), - Status: model.JOB_STATUS_PENDING, - } - - if result := <-ss.Job().Save(job); result.Err != nil { - t.Fatal(result.Err) - } - defer ss.Job().Delete(job.Id) - - job.LastActivityAt = model.GetMillis() - job.Status = model.JOB_STATUS_IN_PROGRESS - job.Progress = 50 - job.Data = map[string]string{ - "Foo": "Bar", - } - - if result := <-ss.Job().UpdateOptimistically(job, model.JOB_STATUS_SUCCESS); result.Err != nil { - if result.Data.(bool) { - t.Fatal("should have failed due to incorrect old status") - } - } - - time.Sleep(2 * time.Millisecond) - - if result := <-ss.Job().UpdateOptimistically(job, model.JOB_STATUS_PENDING); result.Err != nil { - t.Fatal(result.Err) - } else { - if !result.Data.(bool) { - t.Fatal("Should have successfully updated") - } - - var updatedJob *model.Job - - if result := <-ss.Job().Get(job.Id); result.Err != nil { - t.Fatal(result.Err) - } else { - updatedJob = result.Data.(*model.Job) - } - - if updatedJob.Type != job.Type || updatedJob.CreateAt != job.CreateAt || updatedJob.Status != job.Status || updatedJob.LastActivityAt <= job.LastActivityAt || updatedJob.Progress != job.Progress || updatedJob.Data["Foo"] != job.Data["Foo"] { - t.Fatal("Some update property was not as expected") - } - } - -} - -func TestJobUpdateStatusUpdateStatusOptimistically(t *testing.T) { - ss := Setup() - - job := &model.Job{ - Id: model.NewId(), - Type: model.JOB_TYPE_DATA_RETENTION, - CreateAt: model.GetMillis(), - Status: model.JOB_STATUS_SUCCESS, - } - - var lastUpdateAt int64 - if result := <-ss.Job().Save(job); result.Err != nil { - t.Fatal(result.Err) - } else { - lastUpdateAt = result.Data.(*model.Job).LastActivityAt - } - - defer ss.Job().Delete(job.Id) - - time.Sleep(2 * time.Millisecond) - - if result := <-ss.Job().UpdateStatus(job.Id, model.JOB_STATUS_PENDING); result.Err != nil { - t.Fatal(result.Err) - } else { - received := result.Data.(*model.Job) - if received.Status != model.JOB_STATUS_PENDING { - t.Fatal("status wasn't updated") - } - if received.LastActivityAt <= lastUpdateAt { - t.Fatal("lastActivityAt wasn't updated") - } - lastUpdateAt = received.LastActivityAt - } - - time.Sleep(2 * time.Millisecond) - - if result := <-ss.Job().UpdateStatusOptimistically(job.Id, model.JOB_STATUS_IN_PROGRESS, model.JOB_STATUS_SUCCESS); result.Err != nil { - t.Fatal(result.Err) - } else { - if result.Data.(bool) { - t.Fatal("should be false due to incorrect original status") - } - } - - if result := <-ss.Job().Get(job.Id); result.Err != nil { - t.Fatal(result.Err) - } else { - received := result.Data.(*model.Job) - if received.Status != model.JOB_STATUS_PENDING { - t.Fatal("should still be pending") - } - if received.LastActivityAt != lastUpdateAt { - t.Fatal("last activity at shouldn't have changed") - } - } - - time.Sleep(2 * time.Millisecond) - - if result := <-ss.Job().UpdateStatusOptimistically(job.Id, model.JOB_STATUS_PENDING, model.JOB_STATUS_IN_PROGRESS); result.Err != nil { - t.Fatal(result.Err) - } else { - if !result.Data.(bool) { - t.Fatal("should have succeeded") - } - } - - var startAtSet int64 - if result := <-ss.Job().Get(job.Id); result.Err != nil { - t.Fatal(result.Err) - } else { - received := result.Data.(*model.Job) - if received.Status != model.JOB_STATUS_IN_PROGRESS { - t.Fatal("should be in progress") - } - if received.StartAt == 0 { - t.Fatal("received should have start at set") - } - if received.LastActivityAt <= lastUpdateAt { - t.Fatal("lastActivityAt wasn't updated") - } - lastUpdateAt = received.LastActivityAt - startAtSet = received.StartAt - } - - time.Sleep(2 * time.Millisecond) - - if result := <-ss.Job().UpdateStatusOptimistically(job.Id, model.JOB_STATUS_IN_PROGRESS, model.JOB_STATUS_SUCCESS); result.Err != nil { - t.Fatal(result.Err) - } else { - if !result.Data.(bool) { - t.Fatal("should have succeeded") - } - } - - if result := <-ss.Job().Get(job.Id); result.Err != nil { - t.Fatal(result.Err) - } else { - received := result.Data.(*model.Job) - if received.Status != model.JOB_STATUS_SUCCESS { - t.Fatal("should be success status") - } - if received.StartAt != startAtSet { - t.Fatal("startAt should not have changed") - } - if received.LastActivityAt <= lastUpdateAt { - t.Fatal("lastActivityAt wasn't updated") - } - lastUpdateAt = received.LastActivityAt - } -} - -func TestJobDelete(t *testing.T) { - ss := Setup() - - job := store.Must(ss.Job().Save(&model.Job{ - Id: model.NewId(), - })).(*model.Job) - - if result := <-ss.Job().Delete(job.Id); result.Err != nil { - t.Fatal(result.Err) - } +func TestJobStore(t *testing.T) { + StoreTest(t, storetest.TestJobStore) } diff --git a/store/sqlstore/license_store_test.go b/store/sqlstore/license_store_test.go index 99b13a423..2ab8d4a54 100644 --- a/store/sqlstore/license_store_test.go +++ b/store/sqlstore/license_store_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. package sqlstore @@ -6,50 +6,9 @@ package sqlstore import ( "testing" - "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store" + "github.com/mattermost/mattermost-server/store/storetest" ) -func TestLicenseStoreSave(t *testing.T) { - ss := Setup() - - l1 := model.LicenseRecord{} - l1.Id = model.NewId() - l1.Bytes = "junk" - - if err := (<-ss.License().Save(&l1)).Err; err != nil { - t.Fatal("couldn't save license record", err) - } - - if err := (<-ss.License().Save(&l1)).Err; err != nil { - t.Fatal("shouldn't fail on trying to save existing license record", err) - } - - l1.Id = "" - - if err := (<-ss.License().Save(&l1)).Err; err == nil { - t.Fatal("should fail on invalid license", err) - } -} - -func TestLicenseStoreGet(t *testing.T) { - ss := Setup() - - l1 := model.LicenseRecord{} - l1.Id = model.NewId() - l1.Bytes = "junk" - - store.Must(ss.License().Save(&l1)) - - if r := <-ss.License().Get(l1.Id); r.Err != nil { - t.Fatal("couldn't get license", r.Err) - } else { - if r.Data.(*model.LicenseRecord).Bytes != l1.Bytes { - t.Fatal("license bytes didn't match") - } - } - - if err := (<-ss.License().Get("missing")).Err; err == nil { - t.Fatal("should fail on get license", err) - } +func TestLicenseStore(t *testing.T) { + StoreTest(t, storetest.TestLicenseStore) } diff --git a/store/sqlstore/oauth_store_test.go b/store/sqlstore/oauth_store_test.go index b79414abf..10a0897cb 100644 --- a/store/sqlstore/oauth_store_test.go +++ b/store/sqlstore/oauth_store_test.go @@ -6,441 +6,9 @@ package sqlstore import ( "testing" - "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store" + "github.com/mattermost/mattermost-server/store/storetest" ) -func TestOAuthStoreSaveApp(t *testing.T) { - ss := Setup() - - a1 := model.OAuthApp{} - a1.CreatorId = model.NewId() - a1.CallbackUrls = []string{"https://nowhere.com"} - a1.Homepage = "https://nowhere.com" - - // Try to save an app that already has an Id - a1.Id = model.NewId() - if err := (<-ss.OAuth().SaveApp(&a1)).Err; err == nil { - t.Fatal("Should have failed, cannot add an OAuth app cannot be save with an Id, it has to be updated") - } - - // Try to save an Invalid App - a1.Id = "" - if err := (<-ss.OAuth().SaveApp(&a1)).Err; err == nil { - t.Fatal("Should have failed, app should be invalid cause it doesn' have a name set") - } - - // Save the app - a1.Id = "" - a1.Name = "TestApp" + model.NewId() - if err := (<-ss.OAuth().SaveApp(&a1)).Err; err != nil { - t.Fatal(err) - } -} - -func TestOAuthStoreGetApp(t *testing.T) { - ss := Setup() - - a1 := model.OAuthApp{} - a1.CreatorId = model.NewId() - a1.Name = "TestApp" + model.NewId() - a1.CallbackUrls = []string{"https://nowhere.com"} - a1.Homepage = "https://nowhere.com" - store.Must(ss.OAuth().SaveApp(&a1)) - - // Lets try to get and app that does not exists - if err := (<-ss.OAuth().GetApp("fake0123456789abcderfgret1")).Err; err == nil { - t.Fatal("Should have failed. App does not exists") - } - - if err := (<-ss.OAuth().GetApp(a1.Id)).Err; err != nil { - t.Fatal(err) - } - - // Lets try and get the app from a user that hasn't created any apps - if result := (<-ss.OAuth().GetAppByUser("fake0123456789abcderfgret1", 0, 1000)); result.Err == nil { - if len(result.Data.([]*model.OAuthApp)) > 0 { - t.Fatal("Should have failed. Fake user hasn't created any apps") - } - } else { - t.Fatal(result.Err) - } - - if err := (<-ss.OAuth().GetAppByUser(a1.CreatorId, 0, 1000)).Err; err != nil { - t.Fatal(err) - } - - if err := (<-ss.OAuth().GetApps(0, 1000)).Err; err != nil { - t.Fatal(err) - } -} - -func TestOAuthStoreUpdateApp(t *testing.T) { - ss := Setup() - - a1 := model.OAuthApp{} - a1.CreatorId = model.NewId() - a1.Name = "TestApp" + model.NewId() - a1.CallbackUrls = []string{"https://nowhere.com"} - a1.Homepage = "https://nowhere.com" - store.Must(ss.OAuth().SaveApp(&a1)) - - // temporarily save the created app id - id := a1.Id - - a1.CreateAt = 1 - a1.ClientSecret = "pwd" - a1.CreatorId = "12345678901234567890123456" - - // Lets update the app by removing the name - a1.Name = "" - if result := <-ss.OAuth().UpdateApp(&a1); result.Err == nil { - t.Fatal("Should have failed. App name is not set") - } - - // Lets not find the app that we are trying to update - a1.Id = "fake0123456789abcderfgret1" - a1.Name = "NewName" - if result := <-ss.OAuth().UpdateApp(&a1); result.Err == nil { - t.Fatal("Should have failed. Not able to find the app") - } - - a1.Id = id - if result := <-ss.OAuth().UpdateApp(&a1); result.Err != nil { - t.Fatal(result.Err) - } else { - ua1 := (result.Data.([2]*model.OAuthApp)[0]) - if ua1.Name != "NewName" { - t.Fatal("name did not update") - } - if ua1.CreateAt == 1 { - t.Fatal("create at should not have updated") - } - if ua1.CreatorId == "12345678901234567890123456" { - t.Fatal("creator id should not have updated") - } - } -} - -func TestOAuthStoreSaveAccessData(t *testing.T) { - ss := Setup() - - a1 := model.AccessData{} - a1.ClientId = model.NewId() - a1.UserId = model.NewId() - - // Lets try and save an incomplete access data - if err := (<-ss.OAuth().SaveAccessData(&a1)).Err; err == nil { - t.Fatal("Should have failed. Access data needs the token") - } - - a1.Token = model.NewId() - a1.RefreshToken = model.NewId() - a1.RedirectUri = "http://example.com" - - if err := (<-ss.OAuth().SaveAccessData(&a1)).Err; err != nil { - t.Fatal(err) - } -} - -func TestOAuthUpdateAccessData(t *testing.T) { - ss := Setup() - - a1 := model.AccessData{} - a1.ClientId = model.NewId() - a1.UserId = model.NewId() - a1.Token = model.NewId() - a1.RefreshToken = model.NewId() - a1.ExpiresAt = model.GetMillis() - a1.RedirectUri = "http://example.com" - store.Must(ss.OAuth().SaveAccessData(&a1)) - - //Try to update to invalid Refresh Token - refreshToken := a1.RefreshToken - a1.RefreshToken = model.NewId() + "123" - if err := (<-ss.OAuth().UpdateAccessData(&a1)).Err; err == nil { - t.Fatal("Should have failed with invalid token") - } - - //Try to update to invalid RedirectUri - a1.RefreshToken = model.NewId() - a1.RedirectUri = "" - if err := (<-ss.OAuth().UpdateAccessData(&a1)).Err; err == nil { - t.Fatal("Should have failed with invalid Redirect URI") - } - - // Should update fine - a1.RedirectUri = "http://example.com" - if result := <-ss.OAuth().UpdateAccessData(&a1); result.Err != nil { - t.Fatal(result.Err) - } else { - ra1 := result.Data.(*model.AccessData) - if ra1.RefreshToken == refreshToken { - t.Fatal("refresh tokens didn't match") - } - } -} - -func TestOAuthStoreGetAccessData(t *testing.T) { - ss := Setup() - - a1 := model.AccessData{} - a1.ClientId = model.NewId() - a1.UserId = model.NewId() - a1.Token = model.NewId() - a1.RefreshToken = model.NewId() - a1.ExpiresAt = model.GetMillis() - a1.RedirectUri = "http://example.com" - store.Must(ss.OAuth().SaveAccessData(&a1)) - - if err := (<-ss.OAuth().GetAccessData("invalidToken")).Err; err == nil { - t.Fatal("Should have failed. There is no data with an invalid token") - } - - if result := <-ss.OAuth().GetAccessData(a1.Token); result.Err != nil { - t.Fatal(result.Err) - } else { - ra1 := result.Data.(*model.AccessData) - if a1.Token != ra1.Token { - t.Fatal("tokens didn't match") - } - } - - if err := (<-ss.OAuth().GetPreviousAccessData(a1.UserId, a1.ClientId)).Err; err != nil { - t.Fatal(err) - } - - if err := (<-ss.OAuth().GetPreviousAccessData("user", "junk")).Err; err != nil { - t.Fatal(err) - } - - // Try to get the Access data using an invalid refresh token - if err := (<-ss.OAuth().GetAccessDataByRefreshToken(a1.Token)).Err; err == nil { - t.Fatal("Should have failed. There is no data with an invalid token") - } - - // Get the Access Data using the refresh token - if result := <-ss.OAuth().GetAccessDataByRefreshToken(a1.RefreshToken); result.Err != nil { - t.Fatal(result.Err) - } else { - ra1 := result.Data.(*model.AccessData) - if a1.RefreshToken != ra1.RefreshToken { - t.Fatal("tokens didn't match") - } - } -} - -func TestOAuthStoreRemoveAccessData(t *testing.T) { - ss := Setup() - - a1 := model.AccessData{} - a1.ClientId = model.NewId() - a1.UserId = model.NewId() - a1.Token = model.NewId() - a1.RefreshToken = model.NewId() - a1.RedirectUri = "http://example.com" - store.Must(ss.OAuth().SaveAccessData(&a1)) - - if err := (<-ss.OAuth().RemoveAccessData(a1.Token)).Err; err != nil { - t.Fatal(err) - } - - if result := (<-ss.OAuth().GetPreviousAccessData(a1.UserId, a1.ClientId)); result.Err != nil { - } else { - if result.Data != nil { - t.Fatal("did not delete access token") - } - } -} - -func TestOAuthStoreSaveAuthData(t *testing.T) { - ss := Setup() - - a1 := model.AuthData{} - a1.ClientId = model.NewId() - a1.UserId = model.NewId() - a1.Code = model.NewId() - a1.RedirectUri = "http://example.com" - if err := (<-ss.OAuth().SaveAuthData(&a1)).Err; err != nil { - t.Fatal(err) - } -} - -func TestOAuthStoreGetAuthData(t *testing.T) { - ss := Setup() - - a1 := model.AuthData{} - a1.ClientId = model.NewId() - a1.UserId = model.NewId() - a1.Code = model.NewId() - a1.RedirectUri = "http://example.com" - store.Must(ss.OAuth().SaveAuthData(&a1)) - - if err := (<-ss.OAuth().GetAuthData(a1.Code)).Err; err != nil { - t.Fatal(err) - } -} - -func TestOAuthStoreRemoveAuthData(t *testing.T) { - ss := Setup() - - a1 := model.AuthData{} - a1.ClientId = model.NewId() - a1.UserId = model.NewId() - a1.Code = model.NewId() - a1.RedirectUri = "http://example.com" - store.Must(ss.OAuth().SaveAuthData(&a1)) - - if err := (<-ss.OAuth().RemoveAuthData(a1.Code)).Err; err != nil { - t.Fatal(err) - } - - if err := (<-ss.OAuth().GetAuthData(a1.Code)).Err; err == nil { - t.Fatal("should have errored - auth code removed") - } -} - -func TestOAuthStoreRemoveAuthDataByUser(t *testing.T) { - ss := Setup() - - a1 := model.AuthData{} - a1.ClientId = model.NewId() - a1.UserId = model.NewId() - a1.Code = model.NewId() - a1.RedirectUri = "http://example.com" - store.Must(ss.OAuth().SaveAuthData(&a1)) - - if err := (<-ss.OAuth().PermanentDeleteAuthDataByUser(a1.UserId)).Err; err != nil { - t.Fatal(err) - } -} - -func TestOAuthGetAuthorizedApps(t *testing.T) { - ss := Setup() - - a1 := model.OAuthApp{} - a1.CreatorId = model.NewId() - a1.Name = "TestApp" + model.NewId() - a1.CallbackUrls = []string{"https://nowhere.com"} - a1.Homepage = "https://nowhere.com" - store.Must(ss.OAuth().SaveApp(&a1)) - - // Lets try and get an Authorized app for a user who hasn't authorized it - if result := <-ss.OAuth().GetAuthorizedApps("fake0123456789abcderfgret1", 0, 1000); result.Err == nil { - if len(result.Data.([]*model.OAuthApp)) > 0 { - t.Fatal("Should have failed. Fake user hasn't authorized the app") - } - } else { - t.Fatal(result.Err) - } - - // allow the app - p := model.Preference{} - p.UserId = a1.CreatorId - p.Category = model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP - p.Name = a1.Id - p.Value = "true" - store.Must(ss.Preference().Save(&model.Preferences{p})) - - if result := <-ss.OAuth().GetAuthorizedApps(a1.CreatorId, 0, 1000); result.Err != nil { - t.Fatal(result.Err) - } else { - apps := result.Data.([]*model.OAuthApp) - if len(apps) == 0 { - t.Fatal("It should have return apps") - } - } -} - -func TestOAuthGetAccessDataByUserForApp(t *testing.T) { - ss := Setup() - - a1 := model.OAuthApp{} - a1.CreatorId = model.NewId() - a1.Name = "TestApp" + model.NewId() - a1.CallbackUrls = []string{"https://nowhere.com"} - a1.Homepage = "https://nowhere.com" - store.Must(ss.OAuth().SaveApp(&a1)) - - // allow the app - p := model.Preference{} - p.UserId = a1.CreatorId - p.Category = model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP - p.Name = a1.Id - p.Value = "true" - store.Must(ss.Preference().Save(&model.Preferences{p})) - - if result := <-ss.OAuth().GetAuthorizedApps(a1.CreatorId, 0, 1000); result.Err != nil { - t.Fatal(result.Err) - } else { - apps := result.Data.([]*model.OAuthApp) - if len(apps) == 0 { - t.Fatal("It should have return apps") - } - } - - // save the token - ad1 := model.AccessData{} - ad1.ClientId = a1.Id - ad1.UserId = a1.CreatorId - ad1.Token = model.NewId() - ad1.RefreshToken = model.NewId() - ad1.RedirectUri = "http://example.com" - - if err := (<-ss.OAuth().SaveAccessData(&ad1)).Err; err != nil { - t.Fatal(err) - } - - if result := <-ss.OAuth().GetAccessDataByUserForApp(a1.CreatorId, a1.Id); result.Err != nil { - t.Fatal(result.Err) - } else { - accessData := result.Data.([]*model.AccessData) - if len(accessData) == 0 { - t.Fatal("It should have return access data") - } - } -} - -func TestOAuthStoreDeleteApp(t *testing.T) { - ss := Setup() - - a1 := model.OAuthApp{} - a1.CreatorId = model.NewId() - a1.Name = "TestApp" + model.NewId() - a1.CallbackUrls = []string{"https://nowhere.com"} - a1.Homepage = "https://nowhere.com" - store.Must(ss.OAuth().SaveApp(&a1)) - - // delete a non-existent app - if err := (<-ss.OAuth().DeleteApp("fakeclientId")).Err; err != nil { - t.Fatal(err) - } - - s1 := model.Session{} - s1.UserId = model.NewId() - s1.Token = model.NewId() - s1.IsOAuth = true - - store.Must(ss.Session().Save(&s1)) - - ad1 := model.AccessData{} - ad1.ClientId = a1.Id - ad1.UserId = a1.CreatorId - ad1.Token = s1.Token - ad1.RefreshToken = model.NewId() - ad1.RedirectUri = "http://example.com" - - store.Must(ss.OAuth().SaveAccessData(&ad1)) - - if err := (<-ss.OAuth().DeleteApp(a1.Id)).Err; err != nil { - t.Fatal(err) - } - - if err := (<-ss.Session().Get(s1.Token)).Err; err == nil { - t.Fatal("should error - session should be deleted") - } - - if err := (<-ss.OAuth().GetAccessData(s1.Token)).Err; err == nil { - t.Fatal("should error - access data should be deleted") - } +func TestOAuthStore(t *testing.T) { + StoreTest(t, storetest.TestOAuthStore) } diff --git a/store/sqlstore/post_store_test.go b/store/sqlstore/post_store_test.go index aa70f1fc7..9c2313608 100644 --- a/store/sqlstore/post_store_test.go +++ b/store/sqlstore/post_store_test.go @@ -4,1700 +4,11 @@ package sqlstore import ( - "fmt" - "strings" "testing" - "time" - "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store" - "github.com/mattermost/mattermost-server/utils" + "github.com/mattermost/mattermost-server/store/storetest" ) -func TestPostStoreSave(t *testing.T) { - ss := Setup() - - o1 := model.Post{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "b" - - if err := (<-ss.Post().Save(&o1)).Err; err != nil { - t.Fatal("couldn't save item", err) - } - - if err := (<-ss.Post().Save(&o1)).Err; err == nil { - t.Fatal("shouldn't be able to update from save") - } -} - -func TestPostStoreGet(t *testing.T) { - ss := Setup() - - o1 := &model.Post{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "b" - - etag1 := (<-ss.Post().GetEtag(o1.ChannelId, false)).Data.(string) - if strings.Index(etag1, model.CurrentVersion+".") != 0 { - t.Fatal("Invalid Etag") - } - - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - - etag2 := (<-ss.Post().GetEtag(o1.ChannelId, false)).Data.(string) - if strings.Index(etag2, fmt.Sprintf("%v.%v", model.CurrentVersion, o1.UpdateAt)) != 0 { - t.Fatal("Invalid Etag") - } - - if r1 := <-ss.Post().Get(o1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.PostList).Posts[o1.Id].CreateAt != o1.CreateAt { - t.Fatal("invalid returned post") - } - } - - if err := (<-ss.Post().Get("123")).Err; err == nil { - t.Fatal("Missing id should have failed") - } - - if err := (<-ss.Post().Get("")).Err; err == nil { - t.Fatal("should fail for blank post ids") - } -} - -func TestPostStoreGetSingle(t *testing.T) { - ss := Setup() - - o1 := &model.Post{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "b" - - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - - if r1 := <-ss.Post().GetSingle(o1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.Post).CreateAt != o1.CreateAt { - t.Fatal("invalid returned post") - } - } - - if err := (<-ss.Post().GetSingle("123")).Err; err == nil { - t.Fatal("Missing id should have failed") - } -} - -func TestGetEtagCache(t *testing.T) { - ss := Setup() - o1 := &model.Post{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "b" - - etag1 := (<-ss.Post().GetEtag(o1.ChannelId, true)).Data.(string) - if strings.Index(etag1, model.CurrentVersion+".") != 0 { - t.Fatal("Invalid Etag") - } - - // This one should come from the cache - etag2 := (<-ss.Post().GetEtag(o1.ChannelId, true)).Data.(string) - if strings.Index(etag2, model.CurrentVersion+".") != 0 { - t.Fatal("Invalid Etag") - } - - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - - // We have not invalidated the cache so this should be the same as above - etag3 := (<-ss.Post().GetEtag(o1.ChannelId, true)).Data.(string) - if strings.Index(etag3, etag2) != 0 { - t.Fatal("Invalid Etag") - } - - ss.Post().InvalidateLastPostTimeCache(o1.ChannelId) - - // Invalidated cache so we should get a good result - etag4 := (<-ss.Post().GetEtag(o1.ChannelId, true)).Data.(string) - if strings.Index(etag4, fmt.Sprintf("%v.%v", model.CurrentVersion, o1.UpdateAt)) != 0 { - t.Fatal("Invalid Etag") - } -} - -func TestPostStoreUpdate(t *testing.T) { - ss := Setup() - - o1 := &model.Post{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - - o2 := &model.Post{} - o2.ChannelId = o1.ChannelId - o2.UserId = model.NewId() - o2.Message = "zz" + model.NewId() + "CCCCCCCCC" - o2.ParentId = o1.Id - o2.RootId = o1.Id - o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) - - o3 := &model.Post{} - o3.ChannelId = o1.ChannelId - o3.UserId = model.NewId() - o3.Message = "zz" + model.NewId() + "QQQQQQQQQQ" - o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) - - ro1 := (<-ss.Post().Get(o1.Id)).Data.(*model.PostList).Posts[o1.Id] - ro2 := (<-ss.Post().Get(o1.Id)).Data.(*model.PostList).Posts[o2.Id] - ro3 := (<-ss.Post().Get(o3.Id)).Data.(*model.PostList).Posts[o3.Id] - - if ro1.Message != o1.Message { - t.Fatal("Failed to save/get") - } - - o1a := &model.Post{} - *o1a = *ro1 - o1a.Message = ro1.Message + "BBBBBBBBBB" - if result := <-ss.Post().Update(o1a, ro1); result.Err != nil { - t.Fatal(result.Err) - } - - ro1a := (<-ss.Post().Get(o1.Id)).Data.(*model.PostList).Posts[o1.Id] - - if ro1a.Message != o1a.Message { - t.Fatal("Failed to update/get") - } - - o2a := &model.Post{} - *o2a = *ro2 - o2a.Message = ro2.Message + "DDDDDDD" - if result := <-ss.Post().Update(o2a, ro2); result.Err != nil { - t.Fatal(result.Err) - } - - ro2a := (<-ss.Post().Get(o1.Id)).Data.(*model.PostList).Posts[o2.Id] - - if ro2a.Message != o2a.Message { - t.Fatal("Failed to update/get") - } - - o3a := &model.Post{} - *o3a = *ro3 - o3a.Message = ro3.Message + "WWWWWWW" - if result := <-ss.Post().Update(o3a, ro3); result.Err != nil { - t.Fatal(result.Err) - } - - ro3a := (<-ss.Post().Get(o3.Id)).Data.(*model.PostList).Posts[o3.Id] - - if ro3a.Message != o3a.Message && ro3a.Hashtags != o3a.Hashtags { - t.Fatal("Failed to update/get") - } - - o4 := store.Must(ss.Post().Save(&model.Post{ - ChannelId: model.NewId(), - UserId: model.NewId(), - Message: model.NewId(), - Filenames: []string{"test"}, - })).(*model.Post) - - ro4 := (<-ss.Post().Get(o4.Id)).Data.(*model.PostList).Posts[o4.Id] - - o4a := &model.Post{} - *o4a = *ro4 - o4a.Filenames = []string{} - o4a.FileIds = []string{model.NewId()} - if result := <-ss.Post().Update(o4a, ro4); result.Err != nil { - t.Fatal(result.Err) - } - - if ro4a := store.Must(ss.Post().Get(o4.Id)).(*model.PostList).Posts[o4.Id]; len(ro4a.Filenames) != 0 { - t.Fatal("Failed to clear Filenames") - } else if len(ro4a.FileIds) != 1 { - t.Fatal("Failed to set FileIds") - } -} - -func TestPostStoreDelete(t *testing.T) { - ss := Setup() - - o1 := &model.Post{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "b" - - etag1 := (<-ss.Post().GetEtag(o1.ChannelId, false)).Data.(string) - if strings.Index(etag1, model.CurrentVersion+".") != 0 { - t.Fatal("Invalid Etag") - } - - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - - if r1 := <-ss.Post().Get(o1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.PostList).Posts[o1.Id].CreateAt != o1.CreateAt { - t.Fatal("invalid returned post") - } - } - - if r2 := <-ss.Post().Delete(o1.Id, model.GetMillis()); r2.Err != nil { - t.Fatal(r2.Err) - } - - if r3 := (<-ss.Post().Get(o1.Id)); r3.Err == nil { - t.Log(r3.Data) - t.Fatal("Missing id should have failed") - } - - etag2 := (<-ss.Post().GetEtag(o1.ChannelId, false)).Data.(string) - if strings.Index(etag2, model.CurrentVersion+".") != 0 { - t.Fatal("Invalid Etag") - } -} - -func TestPostStoreDelete1Level(t *testing.T) { - ss := Setup() - - o1 := &model.Post{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "b" - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - - o2 := &model.Post{} - o2.ChannelId = o1.ChannelId - o2.UserId = model.NewId() - o2.Message = "zz" + model.NewId() + "b" - o2.ParentId = o1.Id - o2.RootId = o1.Id - o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) - - if r2 := <-ss.Post().Delete(o1.Id, model.GetMillis()); r2.Err != nil { - t.Fatal(r2.Err) - } - - if r3 := (<-ss.Post().Get(o1.Id)); r3.Err == nil { - t.Fatal("Deleted id should have failed") - } - - if r4 := (<-ss.Post().Get(o2.Id)); r4.Err == nil { - t.Fatal("Deleted id should have failed") - } -} - -func TestPostStoreDelete2Level(t *testing.T) { - ss := Setup() - - o1 := &model.Post{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "b" - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - - o2 := &model.Post{} - o2.ChannelId = o1.ChannelId - o2.UserId = model.NewId() - o2.Message = "zz" + model.NewId() + "b" - o2.ParentId = o1.Id - o2.RootId = o1.Id - o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) - - o3 := &model.Post{} - o3.ChannelId = o1.ChannelId - o3.UserId = model.NewId() - o3.Message = "zz" + model.NewId() + "b" - o3.ParentId = o2.Id - o3.RootId = o1.Id - o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) - - o4 := &model.Post{} - o4.ChannelId = model.NewId() - o4.UserId = model.NewId() - o4.Message = "zz" + model.NewId() + "b" - o4 = (<-ss.Post().Save(o4)).Data.(*model.Post) - - if r2 := <-ss.Post().Delete(o1.Id, model.GetMillis()); r2.Err != nil { - t.Fatal(r2.Err) - } - - if r3 := (<-ss.Post().Get(o1.Id)); r3.Err == nil { - t.Fatal("Deleted id should have failed") - } - - if r4 := (<-ss.Post().Get(o2.Id)); r4.Err == nil { - t.Fatal("Deleted id should have failed") - } - - if r5 := (<-ss.Post().Get(o3.Id)); r5.Err == nil { - t.Fatal("Deleted id should have failed") - } - - if r6 := <-ss.Post().Get(o4.Id); r6.Err != nil { - t.Fatal(r6.Err) - } -} - -func TestPostStorePermDelete1Level(t *testing.T) { - ss := Setup() - - o1 := &model.Post{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "b" - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - - o2 := &model.Post{} - o2.ChannelId = o1.ChannelId - o2.UserId = model.NewId() - o2.Message = "zz" + model.NewId() + "b" - o2.ParentId = o1.Id - o2.RootId = o1.Id - o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) - - o3 := &model.Post{} - o3.ChannelId = model.NewId() - o3.UserId = model.NewId() - o3.Message = "zz" + model.NewId() + "b" - o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) - - if r2 := <-ss.Post().PermanentDeleteByUser(o2.UserId); r2.Err != nil { - t.Fatal(r2.Err) - } - - if r3 := (<-ss.Post().Get(o1.Id)); r3.Err != nil { - t.Fatal("Deleted id shouldn't have failed") - } - - if r4 := (<-ss.Post().Get(o2.Id)); r4.Err == nil { - t.Fatal("Deleted id should have failed") - } - - if r2 := <-ss.Post().PermanentDeleteByChannel(o3.ChannelId); r2.Err != nil { - t.Fatal(r2.Err) - } - - if r3 := (<-ss.Post().Get(o3.Id)); r3.Err == nil { - t.Fatal("Deleted id should have failed") - } -} - -func TestPostStorePermDelete1Level2(t *testing.T) { - ss := Setup() - - o1 := &model.Post{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "b" - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - - o2 := &model.Post{} - o2.ChannelId = o1.ChannelId - o2.UserId = model.NewId() - o2.Message = "zz" + model.NewId() + "b" - o2.ParentId = o1.Id - o2.RootId = o1.Id - o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) - - o3 := &model.Post{} - o3.ChannelId = model.NewId() - o3.UserId = model.NewId() - o3.Message = "zz" + model.NewId() + "b" - o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) - - if r2 := <-ss.Post().PermanentDeleteByUser(o1.UserId); r2.Err != nil { - t.Fatal(r2.Err) - } - - if r3 := (<-ss.Post().Get(o1.Id)); r3.Err == nil { - t.Fatal("Deleted id should have failed") - } - - if r4 := (<-ss.Post().Get(o2.Id)); r4.Err == nil { - t.Fatal("Deleted id should have failed") - } - - if r5 := (<-ss.Post().Get(o3.Id)); r5.Err != nil { - t.Fatal("Deleted id shouldn't have failed") - } -} - -func TestPostStoreGetWithChildren(t *testing.T) { - ss := Setup() - - o1 := &model.Post{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "b" - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - - o2 := &model.Post{} - o2.ChannelId = o1.ChannelId - o2.UserId = model.NewId() - o2.Message = "zz" + model.NewId() + "b" - o2.ParentId = o1.Id - o2.RootId = o1.Id - o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) - - o3 := &model.Post{} - o3.ChannelId = o1.ChannelId - o3.UserId = model.NewId() - o3.Message = "zz" + model.NewId() + "b" - o3.ParentId = o2.Id - o3.RootId = o1.Id - o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) - - if r1 := <-ss.Post().Get(o1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else { - pl := r1.Data.(*model.PostList) - if len(pl.Posts) != 3 { - t.Fatal("invalid returned post") - } - } - - store.Must(ss.Post().Delete(o3.Id, model.GetMillis())) - - if r2 := <-ss.Post().Get(o1.Id); r2.Err != nil { - t.Fatal(r2.Err) - } else { - pl := r2.Data.(*model.PostList) - if len(pl.Posts) != 2 { - t.Fatal("invalid returned post") - } - } - - store.Must(ss.Post().Delete(o2.Id, model.GetMillis())) - - if r3 := <-ss.Post().Get(o1.Id); r3.Err != nil { - t.Fatal(r3.Err) - } else { - pl := r3.Data.(*model.PostList) - if len(pl.Posts) != 1 { - t.Fatal("invalid returned post") - } - } -} - -func TestPostStoreGetPostsWtihDetails(t *testing.T) { - ss := Setup() - - o1 := &model.Post{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "b" - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o2 := &model.Post{} - o2.ChannelId = o1.ChannelId - o2.UserId = model.NewId() - o2.Message = "zz" + model.NewId() + "b" - o2.ParentId = o1.Id - o2.RootId = o1.Id - o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o2a := &model.Post{} - o2a.ChannelId = o1.ChannelId - o2a.UserId = model.NewId() - o2a.Message = "zz" + model.NewId() + "b" - o2a.ParentId = o1.Id - o2a.RootId = o1.Id - o2a = (<-ss.Post().Save(o2a)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o3 := &model.Post{} - o3.ChannelId = o1.ChannelId - o3.UserId = model.NewId() - o3.Message = "zz" + model.NewId() + "b" - o3.ParentId = o1.Id - o3.RootId = o1.Id - o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o4 := &model.Post{} - o4.ChannelId = o1.ChannelId - o4.UserId = model.NewId() - o4.Message = "zz" + model.NewId() + "b" - o4 = (<-ss.Post().Save(o4)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o5 := &model.Post{} - o5.ChannelId = o1.ChannelId - o5.UserId = model.NewId() - o5.Message = "zz" + model.NewId() + "b" - o5.ParentId = o4.Id - o5.RootId = o4.Id - o5 = (<-ss.Post().Save(o5)).Data.(*model.Post) - - r1 := (<-ss.Post().GetPosts(o1.ChannelId, 0, 4, false)).Data.(*model.PostList) - - if r1.Order[0] != o5.Id { - t.Fatal("invalid order") - } - - if r1.Order[1] != o4.Id { - t.Fatal("invalid order") - } - - if r1.Order[2] != o3.Id { - t.Fatal("invalid order") - } - - if r1.Order[3] != o2a.Id { - t.Fatal("invalid order") - } - - if len(r1.Posts) != 6 { //the last 4, + o1 (o2a and o3's parent) + o2 (in same thread as o2a and o3) - t.Fatal("wrong size") - } - - if r1.Posts[o1.Id].Message != o1.Message { - t.Fatal("Missing parent") - } - - r2 := (<-ss.Post().GetPosts(o1.ChannelId, 0, 4, true)).Data.(*model.PostList) - - if r2.Order[0] != o5.Id { - t.Fatal("invalid order") - } - - if r2.Order[1] != o4.Id { - t.Fatal("invalid order") - } - - if r2.Order[2] != o3.Id { - t.Fatal("invalid order") - } - - if r2.Order[3] != o2a.Id { - t.Fatal("invalid order") - } - - if len(r2.Posts) != 6 { //the last 4, + o1 (o2a and o3's parent) + o2 (in same thread as o2a and o3) - t.Fatal("wrong size") - } - - if r2.Posts[o1.Id].Message != o1.Message { - t.Fatal("Missing parent") - } -} - -func TestPostStoreGetPostsBeforeAfter(t *testing.T) { - ss := Setup() - o0 := &model.Post{} - o0.ChannelId = model.NewId() - o0.UserId = model.NewId() - o0.Message = "zz" + model.NewId() + "b" - o0 = (<-ss.Post().Save(o0)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o1 := &model.Post{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "b" - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o2 := &model.Post{} - o2.ChannelId = o1.ChannelId - o2.UserId = model.NewId() - o2.Message = "zz" + model.NewId() + "b" - o2.ParentId = o1.Id - o2.RootId = o1.Id - o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o2a := &model.Post{} - o2a.ChannelId = o1.ChannelId - o2a.UserId = model.NewId() - o2a.Message = "zz" + model.NewId() + "b" - o2a.ParentId = o1.Id - o2a.RootId = o1.Id - o2a = (<-ss.Post().Save(o2a)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o3 := &model.Post{} - o3.ChannelId = o1.ChannelId - o3.UserId = model.NewId() - o3.Message = "zz" + model.NewId() + "b" - o3.ParentId = o1.Id - o3.RootId = o1.Id - o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o4 := &model.Post{} - o4.ChannelId = o1.ChannelId - o4.UserId = model.NewId() - o4.Message = "zz" + model.NewId() + "b" - o4 = (<-ss.Post().Save(o4)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o5 := &model.Post{} - o5.ChannelId = o1.ChannelId - o5.UserId = model.NewId() - o5.Message = "zz" + model.NewId() + "b" - o5.ParentId = o4.Id - o5.RootId = o4.Id - o5 = (<-ss.Post().Save(o5)).Data.(*model.Post) - - r1 := (<-ss.Post().GetPostsBefore(o1.ChannelId, o1.Id, 4, 0)).Data.(*model.PostList) - - if len(r1.Posts) != 0 { - t.Fatal("Wrong size") - } - - r2 := (<-ss.Post().GetPostsAfter(o1.ChannelId, o1.Id, 4, 0)).Data.(*model.PostList) - - if r2.Order[0] != o4.Id { - t.Fatal("invalid order") - } - - if r2.Order[1] != o3.Id { - t.Fatal("invalid order") - } - - if r2.Order[2] != o2a.Id { - t.Fatal("invalid order") - } - - if r2.Order[3] != o2.Id { - t.Fatal("invalid order") - } - - if len(r2.Posts) != 5 { - t.Fatal("wrong size") - } - - r3 := (<-ss.Post().GetPostsBefore(o3.ChannelId, o3.Id, 2, 0)).Data.(*model.PostList) - - if r3.Order[0] != o2a.Id { - t.Fatal("invalid order") - } - - if r3.Order[1] != o2.Id { - t.Fatal("invalid order") - } - - if len(r3.Posts) != 3 { - t.Fatal("wrong size") - } - - if r3.Posts[o1.Id].Message != o1.Message { - t.Fatal("Missing parent") - } -} - -func TestPostStoreGetPostsSince(t *testing.T) { - ss := Setup() - o0 := &model.Post{} - o0.ChannelId = model.NewId() - o0.UserId = model.NewId() - o0.Message = "zz" + model.NewId() + "b" - o0 = (<-ss.Post().Save(o0)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o1 := &model.Post{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "b" - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o2 := &model.Post{} - o2.ChannelId = o1.ChannelId - o2.UserId = model.NewId() - o2.Message = "zz" + model.NewId() + "b" - o2.ParentId = o1.Id - o2.RootId = o1.Id - o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o2a := &model.Post{} - o2a.ChannelId = o1.ChannelId - o2a.UserId = model.NewId() - o2a.Message = "zz" + model.NewId() + "b" - o2a.ParentId = o1.Id - o2a.RootId = o1.Id - o2a = (<-ss.Post().Save(o2a)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o3 := &model.Post{} - o3.ChannelId = o1.ChannelId - o3.UserId = model.NewId() - o3.Message = "zz" + model.NewId() + "b" - o3.ParentId = o1.Id - o3.RootId = o1.Id - o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o4 := &model.Post{} - o4.ChannelId = o1.ChannelId - o4.UserId = model.NewId() - o4.Message = "zz" + model.NewId() + "b" - o4 = (<-ss.Post().Save(o4)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o5 := &model.Post{} - o5.ChannelId = o1.ChannelId - o5.UserId = model.NewId() - o5.Message = "zz" + model.NewId() + "b" - o5.ParentId = o4.Id - o5.RootId = o4.Id - o5 = (<-ss.Post().Save(o5)).Data.(*model.Post) - - r1 := (<-ss.Post().GetPostsSince(o1.ChannelId, o1.CreateAt, false)).Data.(*model.PostList) - - if r1.Order[0] != o5.Id { - t.Fatal("invalid order") - } - - if r1.Order[1] != o4.Id { - t.Fatal("invalid order") - } - - if r1.Order[2] != o3.Id { - t.Fatal("invalid order") - } - - if r1.Order[3] != o2a.Id { - t.Fatal("invalid order") - } - - if len(r1.Posts) != 6 { - t.Fatal("wrong size") - } - - if r1.Posts[o1.Id].Message != o1.Message { - t.Fatal("Missing parent") - } - - r2 := (<-ss.Post().GetPostsSince(o1.ChannelId, o5.UpdateAt, true)).Data.(*model.PostList) - - if len(r2.Order) != 0 { - t.Fatal("wrong size ", len(r2.Posts)) - } -} - -func TestPostStoreSearch(t *testing.T) { - ss := Setup() - - teamId := model.NewId() - userId := model.NewId() - - c1 := &model.Channel{} - c1.TeamId = teamId - c1.DisplayName = "Channel1" - c1.Name = "zz" + model.NewId() + "b" - c1.Type = model.CHANNEL_OPEN - c1 = (<-ss.Channel().Save(c1)).Data.(*model.Channel) - - m1 := model.ChannelMember{} - m1.ChannelId = c1.Id - m1.UserId = userId - m1.NotifyProps = model.GetDefaultChannelNotifyProps() - store.Must(ss.Channel().SaveMember(&m1)) - - c2 := &model.Channel{} - c2.TeamId = teamId - c2.DisplayName = "Channel1" - c2.Name = "zz" + model.NewId() + "b" - c2.Type = model.CHANNEL_OPEN - c2 = (<-ss.Channel().Save(c2)).Data.(*model.Channel) - - o1 := &model.Post{} - o1.ChannelId = c1.Id - o1.UserId = model.NewId() - o1.Message = "corey mattermost new york" - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - - o1a := &model.Post{} - o1a.ChannelId = c1.Id - o1a.UserId = model.NewId() - o1a.Message = "corey mattermost new york" - o1a.Type = model.POST_JOIN_CHANNEL - o1a = (<-ss.Post().Save(o1a)).Data.(*model.Post) - - o2 := &model.Post{} - o2.ChannelId = c1.Id - o2.UserId = model.NewId() - o2.Message = "New Jersey is where John is from" - o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) - - o3 := &model.Post{} - o3.ChannelId = c2.Id - o3.UserId = model.NewId() - o3.Message = "New Jersey is where John is from corey new york" - o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) - - o4 := &model.Post{} - o4.ChannelId = c1.Id - o4.UserId = model.NewId() - o4.Hashtags = "#hashtag" - o4.Message = "(message)blargh" - o4 = (<-ss.Post().Save(o4)).Data.(*model.Post) - - o5 := &model.Post{} - o5.ChannelId = c1.Id - o5.UserId = model.NewId() - o5.Hashtags = "#secret #howdy" - o5 = (<-ss.Post().Save(o5)).Data.(*model.Post) - - r1 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "corey", IsHashtag: false})).Data.(*model.PostList) - if len(r1.Order) != 1 || r1.Order[0] != o1.Id { - t.Fatal("returned wrong search result") - } - - r3 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "new", IsHashtag: false})).Data.(*model.PostList) - if len(r3.Order) != 2 || (r3.Order[0] != o1.Id && r3.Order[1] != o1.Id) { - t.Fatal("returned wrong search result") - } - - r4 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "john", IsHashtag: false})).Data.(*model.PostList) - if len(r4.Order) != 1 || r4.Order[0] != o2.Id { - t.Fatal("returned wrong search result") - } - - r5 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "matter*", IsHashtag: false})).Data.(*model.PostList) - if len(r5.Order) != 1 || r5.Order[0] != o1.Id { - t.Fatal("returned wrong search result") - } - - r6 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "#hashtag", IsHashtag: true})).Data.(*model.PostList) - if len(r6.Order) != 1 || r6.Order[0] != o4.Id { - t.Fatal("returned wrong search result") - } - - r7 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "#secret", IsHashtag: true})).Data.(*model.PostList) - if len(r7.Order) != 1 || r7.Order[0] != o5.Id { - t.Fatal("returned wrong search result") - } - - r8 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "@thisshouldmatchnothing", IsHashtag: true})).Data.(*model.PostList) - if len(r8.Order) != 0 { - t.Fatal("returned wrong search result") - } - - r9 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "mattermost jersey", IsHashtag: false})).Data.(*model.PostList) - if len(r9.Order) != 0 { - t.Fatal("returned wrong search result") - } - - r9a := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "corey new york", IsHashtag: false})).Data.(*model.PostList) - if len(r9a.Order) != 1 { - t.Fatal("returned wrong search result") - } - - r10 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "matter* jer*", IsHashtag: false})).Data.(*model.PostList) - if len(r10.Order) != 0 { - t.Fatal("returned wrong search result") - } - - r11 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "message blargh", IsHashtag: false})).Data.(*model.PostList) - if len(r11.Order) != 1 { - t.Fatal("returned wrong search result") - } - - r12 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "blargh>", IsHashtag: false})).Data.(*model.PostList) - if len(r12.Order) != 1 { - t.Fatal("returned wrong search result") - } - - r13 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "Jersey corey", IsHashtag: false, OrTerms: true})).Data.(*model.PostList) - if len(r13.Order) != 2 { - t.Fatal("returned wrong search result") - } -} - -func TestUserCountsWithPostsByDay(t *testing.T) { - ss := Setup() - - t1 := &model.Team{} - t1.DisplayName = "DisplayName" - t1.Name = "zz" + model.NewId() + "b" - t1.Email = model.NewId() + "@nowhere.com" - t1.Type = model.TEAM_OPEN - t1 = store.Must(ss.Team().Save(t1)).(*model.Team) - - c1 := &model.Channel{} - c1.TeamId = t1.Id - c1.DisplayName = "Channel2" - c1.Name = "zz" + model.NewId() + "b" - c1.Type = model.CHANNEL_OPEN - c1 = store.Must(ss.Channel().Save(c1)).(*model.Channel) - - o1 := &model.Post{} - o1.ChannelId = c1.Id - o1.UserId = model.NewId() - o1.CreateAt = utils.MillisFromTime(utils.Yesterday()) - o1.Message = "zz" + model.NewId() + "b" - o1 = store.Must(ss.Post().Save(o1)).(*model.Post) - - o1a := &model.Post{} - o1a.ChannelId = c1.Id - o1a.UserId = model.NewId() - o1a.CreateAt = o1.CreateAt - o1a.Message = "zz" + model.NewId() + "b" - o1a = store.Must(ss.Post().Save(o1a)).(*model.Post) - - o2 := &model.Post{} - o2.ChannelId = c1.Id - o2.UserId = model.NewId() - o2.CreateAt = o1.CreateAt - (1000 * 60 * 60 * 24) - o2.Message = "zz" + model.NewId() + "b" - o2 = store.Must(ss.Post().Save(o2)).(*model.Post) - - o2a := &model.Post{} - o2a.ChannelId = c1.Id - o2a.UserId = o2.UserId - o2a.CreateAt = o1.CreateAt - (1000 * 60 * 60 * 24) - o2a.Message = "zz" + model.NewId() + "b" - o2a = store.Must(ss.Post().Save(o2a)).(*model.Post) - - if r1 := <-ss.Post().AnalyticsUserCountsWithPostsByDay(t1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else { - row1 := r1.Data.(model.AnalyticsRows)[0] - if row1.Value != 2 { - t.Fatal("wrong value") - } - - row2 := r1.Data.(model.AnalyticsRows)[1] - if row2.Value != 1 { - t.Fatal("wrong value") - } - } -} - -func TestPostCountsByDay(t *testing.T) { - ss := Setup() - - t1 := &model.Team{} - t1.DisplayName = "DisplayName" - t1.Name = "zz" + model.NewId() + "b" - t1.Email = model.NewId() + "@nowhere.com" - t1.Type = model.TEAM_OPEN - t1 = store.Must(ss.Team().Save(t1)).(*model.Team) - - c1 := &model.Channel{} - c1.TeamId = t1.Id - c1.DisplayName = "Channel2" - c1.Name = "zz" + model.NewId() + "b" - c1.Type = model.CHANNEL_OPEN - c1 = store.Must(ss.Channel().Save(c1)).(*model.Channel) - - o1 := &model.Post{} - o1.ChannelId = c1.Id - o1.UserId = model.NewId() - o1.CreateAt = utils.MillisFromTime(utils.Yesterday()) - o1.Message = "zz" + model.NewId() + "b" - o1 = store.Must(ss.Post().Save(o1)).(*model.Post) - - o1a := &model.Post{} - o1a.ChannelId = c1.Id - o1a.UserId = model.NewId() - o1a.CreateAt = o1.CreateAt - o1a.Message = "zz" + model.NewId() + "b" - o1a = store.Must(ss.Post().Save(o1a)).(*model.Post) - - o2 := &model.Post{} - o2.ChannelId = c1.Id - o2.UserId = model.NewId() - o2.CreateAt = o1.CreateAt - (1000 * 60 * 60 * 24 * 2) - o2.Message = "zz" + model.NewId() + "b" - o2 = store.Must(ss.Post().Save(o2)).(*model.Post) - - o2a := &model.Post{} - o2a.ChannelId = c1.Id - o2a.UserId = o2.UserId - o2a.CreateAt = o1.CreateAt - (1000 * 60 * 60 * 24 * 2) - o2a.Message = "zz" + model.NewId() + "b" - o2a = store.Must(ss.Post().Save(o2a)).(*model.Post) - - time.Sleep(1 * time.Second) - - if r1 := <-ss.Post().AnalyticsPostCountsByDay(t1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else { - row1 := r1.Data.(model.AnalyticsRows)[0] - if row1.Value != 2 { - t.Fatal(row1) - } - - row2 := r1.Data.(model.AnalyticsRows)[1] - if row2.Value != 2 { - t.Fatal("wrong value") - } - } - - if r1 := <-ss.Post().AnalyticsPostCount(t1.Id, false, false); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(int64) != 4 { - t.Fatal("wrong value") - } - } -} - -func TestPostStoreGetFlaggedPostsForTeam(t *testing.T) { - ss := Setup() - - c1 := &model.Channel{} - c1.TeamId = model.NewId() - c1.DisplayName = "Channel1" - c1.Name = "zz" + model.NewId() + "b" - c1.Type = model.CHANNEL_OPEN - c1 = store.Must(ss.Channel().Save(c1)).(*model.Channel) - - o1 := &model.Post{} - o1.ChannelId = c1.Id - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "b" - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o2 := &model.Post{} - o2.ChannelId = o1.ChannelId - o2.UserId = model.NewId() - o2.Message = "zz" + model.NewId() + "b" - o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o3 := &model.Post{} - o3.ChannelId = o1.ChannelId - o3.UserId = model.NewId() - o3.Message = "zz" + model.NewId() + "b" - o3.DeleteAt = 1 - o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o4 := &model.Post{} - o4.ChannelId = model.NewId() - o4.UserId = model.NewId() - o4.Message = "zz" + model.NewId() + "b" - o4 = (<-ss.Post().Save(o4)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - c2 := &model.Channel{} - c2.DisplayName = "DMChannel1" - c2.Name = "zz" + model.NewId() + "b" - c2.Type = model.CHANNEL_DIRECT - - m1 := &model.ChannelMember{} - m1.ChannelId = c2.Id - m1.UserId = o1.UserId - m1.NotifyProps = model.GetDefaultChannelNotifyProps() - - m2 := &model.ChannelMember{} - m2.ChannelId = c2.Id - m2.UserId = model.NewId() - m2.NotifyProps = model.GetDefaultChannelNotifyProps() - - c2 = store.Must(ss.Channel().SaveDirectChannel(c2, m1, m2)).(*model.Channel) - - o5 := &model.Post{} - o5.ChannelId = c2.Id - o5.UserId = m2.UserId - o5.Message = "zz" + model.NewId() + "b" - o5 = (<-ss.Post().Save(o5)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - r1 := (<-ss.Post().GetFlaggedPosts(o1.ChannelId, 0, 2)).Data.(*model.PostList) - - if len(r1.Order) != 0 { - t.Fatal("should be empty") - } - - preferences := model.Preferences{ - { - UserId: o1.UserId, - Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, - Name: o1.Id, - Value: "true", - }, - } - - store.Must(ss.Preference().Save(&preferences)) - - r2 := (<-ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 2)).Data.(*model.PostList) - - if len(r2.Order) != 1 { - t.Fatal("should have 1 post") - } - - preferences = model.Preferences{ - { - UserId: o1.UserId, - Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, - Name: o2.Id, - Value: "true", - }, - } - - store.Must(ss.Preference().Save(&preferences)) - - r3 := (<-ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 1)).Data.(*model.PostList) - - if len(r3.Order) != 1 { - t.Fatal("should have 1 post") - } - - r3 = (<-ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 1, 1)).Data.(*model.PostList) - - if len(r3.Order) != 1 { - t.Fatal("should have 1 post") - } - - r3 = (<-ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 1000, 10)).Data.(*model.PostList) - - if len(r3.Order) != 0 { - t.Fatal("should be empty") - } - - r4 := (<-ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 2)).Data.(*model.PostList) - - if len(r4.Order) != 2 { - t.Fatal("should have 2 posts") - } - - preferences = model.Preferences{ - { - UserId: o1.UserId, - Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, - Name: o3.Id, - Value: "true", - }, - } - - store.Must(ss.Preference().Save(&preferences)) - - r4 = (<-ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 2)).Data.(*model.PostList) - - if len(r4.Order) != 2 { - t.Fatal("should have 2 posts") - } - - preferences = model.Preferences{ - { - UserId: o1.UserId, - Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, - Name: o4.Id, - Value: "true", - }, - } - store.Must(ss.Preference().Save(&preferences)) - - r4 = (<-ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 2)).Data.(*model.PostList) - - if len(r4.Order) != 2 { - t.Fatal("should have 2 posts") - } - - r4 = (<-ss.Post().GetFlaggedPostsForTeam(o1.UserId, model.NewId(), 0, 2)).Data.(*model.PostList) - - if len(r4.Order) != 0 { - t.Fatal("should have 0 posts") - } - - preferences = model.Preferences{ - { - UserId: o1.UserId, - Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, - Name: o5.Id, - Value: "true", - }, - } - store.Must(ss.Preference().Save(&preferences)) - - r4 = (<-ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 10)).Data.(*model.PostList) - - if len(r4.Order) != 3 { - t.Fatal("should have 3 posts") - } -} - -func TestPostStoreGetFlaggedPosts(t *testing.T) { - ss := Setup() - - o1 := &model.Post{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "b" - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o2 := &model.Post{} - o2.ChannelId = o1.ChannelId - o2.UserId = model.NewId() - o2.Message = "zz" + model.NewId() + "b" - o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o3 := &model.Post{} - o3.ChannelId = o1.ChannelId - o3.UserId = model.NewId() - o3.Message = "zz" + model.NewId() + "b" - o3.DeleteAt = 1 - o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - r1 := (<-ss.Post().GetFlaggedPosts(o1.UserId, 0, 2)).Data.(*model.PostList) - - if len(r1.Order) != 0 { - t.Fatal("should be empty") - } - - preferences := model.Preferences{ - { - UserId: o1.UserId, - Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, - Name: o1.Id, - Value: "true", - }, - } - - store.Must(ss.Preference().Save(&preferences)) - - r2 := (<-ss.Post().GetFlaggedPosts(o1.UserId, 0, 2)).Data.(*model.PostList) - - if len(r2.Order) != 1 { - t.Fatal("should have 1 post") - } - - preferences = model.Preferences{ - { - UserId: o1.UserId, - Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, - Name: o2.Id, - Value: "true", - }, - } - - store.Must(ss.Preference().Save(&preferences)) - - r3 := (<-ss.Post().GetFlaggedPosts(o1.UserId, 0, 1)).Data.(*model.PostList) - - if len(r3.Order) != 1 { - t.Fatal("should have 1 post") - } - - r3 = (<-ss.Post().GetFlaggedPosts(o1.UserId, 1, 1)).Data.(*model.PostList) - - if len(r3.Order) != 1 { - t.Fatal("should have 1 post") - } - - r3 = (<-ss.Post().GetFlaggedPosts(o1.UserId, 1000, 10)).Data.(*model.PostList) - - if len(r3.Order) != 0 { - t.Fatal("should be empty") - } - - r4 := (<-ss.Post().GetFlaggedPosts(o1.UserId, 0, 2)).Data.(*model.PostList) - - if len(r4.Order) != 2 { - t.Fatal("should have 2 posts") - } - - preferences = model.Preferences{ - { - UserId: o1.UserId, - Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, - Name: o3.Id, - Value: "true", - }, - } - - store.Must(ss.Preference().Save(&preferences)) - - r4 = (<-ss.Post().GetFlaggedPosts(o1.UserId, 0, 2)).Data.(*model.PostList) - - if len(r4.Order) != 2 { - t.Fatal("should have 2 posts") - } -} - -func TestPostStoreGetFlaggedPostsForChannel(t *testing.T) { - ss := Setup() - - o1 := &model.Post{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "b" - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o2 := &model.Post{} - o2.ChannelId = o1.ChannelId - o2.UserId = model.NewId() - o2.Message = "zz" + model.NewId() + "b" - o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - // deleted post - o3 := &model.Post{} - o3.ChannelId = model.NewId() - o3.UserId = o1.ChannelId - o3.Message = "zz" + model.NewId() + "b" - o3.DeleteAt = 1 - o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o4 := &model.Post{} - o4.ChannelId = model.NewId() - o4.UserId = model.NewId() - o4.Message = "zz" + model.NewId() + "b" - o4 = (<-ss.Post().Save(o4)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - r := (<-ss.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 0, 10)).Data.(*model.PostList) - - if len(r.Order) != 0 { - t.Fatal("should be empty") - } - - preference := model.Preference{ - UserId: o1.UserId, - Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, - Name: o1.Id, - Value: "true", - } - - store.Must(ss.Preference().Save(&model.Preferences{preference})) - - r = (<-ss.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 0, 10)).Data.(*model.PostList) - - if len(r.Order) != 1 { - t.Fatal("should have 1 post") - } - - preference.Name = o2.Id - store.Must(ss.Preference().Save(&model.Preferences{preference})) - - preference.Name = o3.Id - store.Must(ss.Preference().Save(&model.Preferences{preference})) - - r = (<-ss.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 0, 1)).Data.(*model.PostList) - - if len(r.Order) != 1 { - t.Fatal("should have 1 post") - } - - r = (<-ss.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 1, 1)).Data.(*model.PostList) - - if len(r.Order) != 1 { - t.Fatal("should have 1 post") - } - - r = (<-ss.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 1000, 10)).Data.(*model.PostList) - - if len(r.Order) != 0 { - t.Fatal("should be empty") - } - - r = (<-ss.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 0, 10)).Data.(*model.PostList) - - if len(r.Order) != 2 { - t.Fatal("should have 2 posts") - } - - preference.Name = o4.Id - store.Must(ss.Preference().Save(&model.Preferences{preference})) - - r = (<-ss.Post().GetFlaggedPostsForChannel(o1.UserId, o4.ChannelId, 0, 10)).Data.(*model.PostList) - - if len(r.Order) != 1 { - t.Fatal("should have 1 post") - } -} - -func TestPostStoreGetPostsCreatedAt(t *testing.T) { - ss := Setup() - - createTime := model.GetMillis() - - o0 := &model.Post{} - o0.ChannelId = model.NewId() - o0.UserId = model.NewId() - o0.Message = "zz" + model.NewId() + "b" - o0.CreateAt = createTime - o0 = (<-ss.Post().Save(o0)).Data.(*model.Post) - - o1 := &model.Post{} - o1.ChannelId = o0.Id - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "b" - o0.CreateAt = createTime - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o2 := &model.Post{} - o2.ChannelId = o1.ChannelId - o2.UserId = model.NewId() - o2.Message = "zz" + model.NewId() + "b" - o2.ParentId = o1.Id - o2.RootId = o1.Id - o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - o3 := &model.Post{} - o3.ChannelId = model.NewId() - o3.UserId = model.NewId() - o3.Message = "zz" + model.NewId() + "b" - o3.CreateAt = createTime - o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) - time.Sleep(2 * time.Millisecond) - - r1 := (<-ss.Post().GetPostsCreatedAt(o1.ChannelId, createTime)).Data.([]*model.Post) - - if len(r1) != 2 { - t.Fatalf("Got the wrong number of posts.") - } -} - -func TestPostStoreOverwrite(t *testing.T) { - ss := Setup() - - o1 := &model.Post{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - - o2 := &model.Post{} - o2.ChannelId = o1.ChannelId - o2.UserId = model.NewId() - o2.Message = "zz" + model.NewId() + "CCCCCCCCC" - o2.ParentId = o1.Id - o2.RootId = o1.Id - o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) - - o3 := &model.Post{} - o3.ChannelId = o1.ChannelId - o3.UserId = model.NewId() - o3.Message = "zz" + model.NewId() + "QQQQQQQQQQ" - o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) - - ro1 := (<-ss.Post().Get(o1.Id)).Data.(*model.PostList).Posts[o1.Id] - ro2 := (<-ss.Post().Get(o1.Id)).Data.(*model.PostList).Posts[o2.Id] - ro3 := (<-ss.Post().Get(o3.Id)).Data.(*model.PostList).Posts[o3.Id] - - if ro1.Message != o1.Message { - t.Fatal("Failed to save/get") - } - - o1a := &model.Post{} - *o1a = *ro1 - o1a.Message = ro1.Message + "BBBBBBBBBB" - if result := <-ss.Post().Overwrite(o1a); result.Err != nil { - t.Fatal(result.Err) - } - - ro1a := (<-ss.Post().Get(o1.Id)).Data.(*model.PostList).Posts[o1.Id] - - if ro1a.Message != o1a.Message { - t.Fatal("Failed to overwrite/get") - } - - o2a := &model.Post{} - *o2a = *ro2 - o2a.Message = ro2.Message + "DDDDDDD" - if result := <-ss.Post().Overwrite(o2a); result.Err != nil { - t.Fatal(result.Err) - } - - ro2a := (<-ss.Post().Get(o1.Id)).Data.(*model.PostList).Posts[o2.Id] - - if ro2a.Message != o2a.Message { - t.Fatal("Failed to overwrite/get") - } - - o3a := &model.Post{} - *o3a = *ro3 - o3a.Message = ro3.Message + "WWWWWWW" - if result := <-ss.Post().Overwrite(o3a); result.Err != nil { - t.Fatal(result.Err) - } - - ro3a := (<-ss.Post().Get(o3.Id)).Data.(*model.PostList).Posts[o3.Id] - - if ro3a.Message != o3a.Message && ro3a.Hashtags != o3a.Hashtags { - t.Fatal("Failed to overwrite/get") - } - - o4 := store.Must(ss.Post().Save(&model.Post{ - ChannelId: model.NewId(), - UserId: model.NewId(), - Message: model.NewId(), - Filenames: []string{"test"}, - })).(*model.Post) - - ro4 := (<-ss.Post().Get(o4.Id)).Data.(*model.PostList).Posts[o4.Id] - - o4a := &model.Post{} - *o4a = *ro4 - o4a.Filenames = []string{} - o4a.FileIds = []string{model.NewId()} - if result := <-ss.Post().Overwrite(o4a); result.Err != nil { - t.Fatal(result.Err) - } - - if ro4a := store.Must(ss.Post().Get(o4.Id)).(*model.PostList).Posts[o4.Id]; len(ro4a.Filenames) != 0 { - t.Fatal("Failed to clear Filenames") - } else if len(ro4a.FileIds) != 1 { - t.Fatal("Failed to set FileIds") - } -} - -func TestPostStoreGetPostsByIds(t *testing.T) { - ss := Setup() - - o1 := &model.Post{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - - o2 := &model.Post{} - o2.ChannelId = o1.ChannelId - o2.UserId = model.NewId() - o2.Message = "zz" + model.NewId() + "CCCCCCCCC" - o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) - - o3 := &model.Post{} - o3.ChannelId = o1.ChannelId - o3.UserId = model.NewId() - o3.Message = "zz" + model.NewId() + "QQQQQQQQQQ" - o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) - - ro1 := (<-ss.Post().Get(o1.Id)).Data.(*model.PostList).Posts[o1.Id] - ro2 := (<-ss.Post().Get(o2.Id)).Data.(*model.PostList).Posts[o2.Id] - ro3 := (<-ss.Post().Get(o3.Id)).Data.(*model.PostList).Posts[o3.Id] - - postIds := []string{ - ro1.Id, - ro2.Id, - ro3.Id, - } - - if ro4 := store.Must(ss.Post().GetPostsByIds(postIds)).([]*model.Post); len(ro4) != 3 { - t.Fatalf("Expected 3 posts in results. Got %v", len(ro4)) - } - - store.Must(ss.Post().Delete(ro1.Id, model.GetMillis())) - - if ro5 := store.Must(ss.Post().GetPostsByIds(postIds)).([]*model.Post); len(ro5) != 2 { - t.Fatalf("Expected 2 posts in results. Got %v", len(ro5)) - } -} - -func TestPostStoreGetPostsBatchForIndexing(t *testing.T) { - ss := Setup() - - c1 := &model.Channel{} - c1.TeamId = model.NewId() - c1.DisplayName = "Channel1" - c1.Name = "zz" + model.NewId() + "b" - c1.Type = model.CHANNEL_OPEN - c1 = (<-ss.Channel().Save(c1)).Data.(*model.Channel) - - c2 := &model.Channel{} - c2.TeamId = model.NewId() - c2.DisplayName = "Channel2" - c2.Name = "zz" + model.NewId() + "b" - c2.Type = model.CHANNEL_OPEN - c2 = (<-ss.Channel().Save(c2)).Data.(*model.Channel) - - o1 := &model.Post{} - o1.ChannelId = c1.Id - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - - o2 := &model.Post{} - o2.ChannelId = c2.Id - o2.UserId = model.NewId() - o2.Message = "zz" + model.NewId() + "CCCCCCCCC" - o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) - - o3 := &model.Post{} - o3.ChannelId = c1.Id - o3.UserId = model.NewId() - o3.ParentId = o1.Id - o3.RootId = o1.Id - o3.Message = "zz" + model.NewId() + "QQQQQQQQQQ" - o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) - - if r := store.Must(ss.Post().GetPostsBatchForIndexing(o1.CreateAt, 100)).([]*model.PostForIndexing); len(r) != 3 { - t.Fatalf("Expected 3 posts in results. Got %v", len(r)) - } else { - for _, p := range r { - if p.Id == o1.Id { - if p.TeamId != c1.TeamId { - t.Fatalf("Unexpected team ID") - } - if p.ParentCreateAt != nil { - t.Fatalf("Unexpected parent create at") - } - } else if p.Id == o2.Id { - if p.TeamId != c2.TeamId { - t.Fatalf("Unexpected team ID") - } - if p.ParentCreateAt != nil { - t.Fatalf("Unexpected parent create at") - } - } else if p.Id == o3.Id { - if p.TeamId != c1.TeamId { - t.Fatalf("Unexpected team ID") - } - if *p.ParentCreateAt != o1.CreateAt { - t.Fatalf("Unexpected parent create at") - } - } else { - t.Fatalf("unexpected post returned") - } - } - } -} - -func TestPostStorePermanentDeleteBatch(t *testing.T) { - ss := Setup() - - o1 := &model.Post{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" - o1.CreateAt = 1000 - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - - o2 := &model.Post{} - o2.ChannelId = model.NewId() - o2.UserId = model.NewId() - o2.Message = "zz" + model.NewId() + "AAAAAAAAAAA" - o2.CreateAt = 1000 - o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) - - o3 := &model.Post{} - o3.ChannelId = model.NewId() - o3.UserId = model.NewId() - o3.Message = "zz" + model.NewId() + "AAAAAAAAAAA" - o3.CreateAt = 100000 - o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) - - store.Must(ss.Post().PermanentDeleteBatch(2000, 1000)) - - if p := <-ss.Post().Get(o1.Id); p.Err == nil { - t.Fatalf("Should have not found post 1 after purge") - } - - if p := <-ss.Post().Get(o2.Id); p.Err == nil { - t.Fatalf("Should have not found post 2 after purge") - } - - if p := <-ss.Post().Get(o3.Id); p.Err != nil { - t.Fatalf("Should have found post 3 after purge") - } +func TestPostStore(t *testing.T) { + StoreTest(t, storetest.TestPostStore) } diff --git a/store/sqlstore/preference_store.go b/store/sqlstore/preference_store.go index 6765a74f8..ddd1fc268 100644 --- a/store/sqlstore/preference_store.go +++ b/store/sqlstore/preference_store.go @@ -18,10 +18,6 @@ type SqlPreferenceStore struct { SqlStore } -const ( - FEATURE_TOGGLE_PREFIX = "feature_enabled_" -) - func NewSqlPreferenceStore(sqlStore SqlStore) store.PreferenceStore { s := &SqlPreferenceStore{sqlStore} @@ -50,7 +46,7 @@ func (s SqlPreferenceStore) DeleteUnusedFeatures() { WHERE Category = :Category AND Value = :Value - AND Name LIKE '` + FEATURE_TOGGLE_PREFIX + `%'` + AND Name LIKE '` + store.FEATURE_TOGGLE_PREFIX + `%'` queryParams := map[string]string{ "Category": model.PREFERENCE_CATEGORY_ADVANCED_SETTINGS, @@ -246,7 +242,7 @@ func (s SqlPreferenceStore) IsFeatureEnabled(feature, userId string) store.Store WHERE UserId = :UserId AND Category = :Category - AND Name = :Name`, map[string]interface{}{"UserId": userId, "Category": model.PREFERENCE_CATEGORY_ADVANCED_SETTINGS, "Name": FEATURE_TOGGLE_PREFIX + feature}); err != nil { + AND Name = :Name`, map[string]interface{}{"UserId": userId, "Category": model.PREFERENCE_CATEGORY_ADVANCED_SETTINGS, "Name": store.FEATURE_TOGGLE_PREFIX + feature}); err != nil { result.Err = model.NewAppError("SqlPreferenceStore.IsFeatureEnabled", "store.sql_preference.is_feature_enabled.app_error", nil, err.Error(), http.StatusInternalServerError) } else { result.Data = value == "true" diff --git a/store/sqlstore/preference_store_test.go b/store/sqlstore/preference_store_test.go index ff415038d..0d0f9978d 100644 --- a/store/sqlstore/preference_store_test.go +++ b/store/sqlstore/preference_store_test.go @@ -6,512 +6,74 @@ package sqlstore import ( "testing" - "github.com/stretchr/testify/assert" - "github.com/mattermost/mattermost-server/model" "github.com/mattermost/mattermost-server/store" + "github.com/mattermost/mattermost-server/store/storetest" ) -func TestPreferenceSave(t *testing.T) { - ss := Setup() - - id := model.NewId() - - preferences := model.Preferences{ - { - UserId: id, - Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, - Name: model.NewId(), - Value: "value1a", - }, - { - UserId: id, - Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, - Name: model.NewId(), - Value: "value1b", - }, - } - if count := store.Must(ss.Preference().Save(&preferences)); count != 2 { - t.Fatal("got incorrect number of rows saved") - } - - for _, preference := range preferences { - if data := store.Must(ss.Preference().Get(preference.UserId, preference.Category, preference.Name)).(model.Preference); preference != data { - t.Fatal("got incorrect preference after first Save") - } - } - - preferences[0].Value = "value2a" - preferences[1].Value = "value2b" - if count := store.Must(ss.Preference().Save(&preferences)); count != 2 { - t.Fatal("got incorrect number of rows saved") - } - - for _, preference := range preferences { - if data := store.Must(ss.Preference().Get(preference.UserId, preference.Category, preference.Name)).(model.Preference); preference != data { - t.Fatal("got incorrect preference after second Save") - } - } -} - -func TestPreferenceGet(t *testing.T) { - ss := Setup() - - userId := model.NewId() - category := model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW - name := model.NewId() - - preferences := model.Preferences{ - { - UserId: userId, - Category: category, - Name: name, - }, - { - UserId: userId, - Category: category, - Name: model.NewId(), - }, - { - UserId: userId, - Category: model.NewId(), - Name: name, - }, - { - UserId: model.NewId(), - Category: category, - Name: name, - }, - } - - store.Must(ss.Preference().Save(&preferences)) - - if result := <-ss.Preference().Get(userId, category, name); result.Err != nil { - t.Fatal(result.Err) - } else if data := result.Data.(model.Preference); data != preferences[0] { - t.Fatal("got incorrect preference") - } - - // make sure getting a missing preference fails - if result := <-ss.Preference().Get(model.NewId(), model.NewId(), model.NewId()); result.Err == nil { - t.Fatal("no error on getting a missing preference") - } -} - -func TestPreferenceGetCategory(t *testing.T) { - ss := Setup() - - userId := model.NewId() - category := model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW - name := model.NewId() - - preferences := model.Preferences{ - { - UserId: userId, - Category: category, - Name: name, - }, - // same user/category, different name - { - UserId: userId, - Category: category, - Name: model.NewId(), - }, - // same user/name, different category - { - UserId: userId, - Category: model.NewId(), - Name: name, - }, - // same name/category, different user - { - UserId: model.NewId(), - Category: category, - Name: name, - }, - } - - store.Must(ss.Preference().Save(&preferences)) - - if result := <-ss.Preference().GetCategory(userId, category); result.Err != nil { - t.Fatal(result.Err) - } else if data := result.Data.(model.Preferences); len(data) != 2 { - t.Fatal("got the wrong number of preferences") - } else if !((data[0] == preferences[0] && data[1] == preferences[1]) || (data[0] == preferences[1] && data[1] == preferences[0])) { - t.Fatal("got incorrect preferences") - } - - // make sure getting a missing preference category doesn't fail - if result := <-ss.Preference().GetCategory(model.NewId(), model.NewId()); result.Err != nil { - t.Fatal(result.Err) - } else if data := result.Data.(model.Preferences); len(data) != 0 { - t.Fatal("shouldn't have got any preferences") - } -} - -func TestPreferenceGetAll(t *testing.T) { - ss := Setup() - - userId := model.NewId() - category := model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW - name := model.NewId() - - preferences := model.Preferences{ - { - UserId: userId, - Category: category, - Name: name, - }, - // same user/category, different name - { - UserId: userId, - Category: category, - Name: model.NewId(), - }, - // same user/name, different category - { - UserId: userId, - Category: model.NewId(), - Name: name, - }, - // same name/category, different user - { - UserId: model.NewId(), - Category: category, - Name: name, - }, - } - - store.Must(ss.Preference().Save(&preferences)) - - if result := <-ss.Preference().GetAll(userId); result.Err != nil { - t.Fatal(result.Err) - } else if data := result.Data.(model.Preferences); len(data) != 3 { - t.Fatal("got the wrong number of preferences") - } else { - for i := 0; i < 3; i++ { - if data[0] != preferences[i] && data[1] != preferences[i] && data[2] != preferences[i] { - t.Fatal("got incorrect preferences") - } - } - } -} - -func TestPreferenceDeleteByUser(t *testing.T) { - ss := Setup() - - userId := model.NewId() - category := model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW - name := model.NewId() - - preferences := model.Preferences{ - { - UserId: userId, - Category: category, - Name: name, - }, - // same user/category, different name - { - UserId: userId, - Category: category, - Name: model.NewId(), - }, - // same user/name, different category - { - UserId: userId, - Category: model.NewId(), - Name: name, - }, - // same name/category, different user - { - UserId: model.NewId(), - Category: category, - Name: name, - }, - } - - store.Must(ss.Preference().Save(&preferences)) - - if result := <-ss.Preference().PermanentDeleteByUser(userId); result.Err != nil { - t.Fatal(result.Err) - } -} - -func TestIsFeatureEnabled(t *testing.T) { - ss := Setup() - - feature1 := "testFeat1" - feature2 := "testFeat2" - feature3 := "testFeat3" - - userId := model.NewId() - category := model.PREFERENCE_CATEGORY_ADVANCED_SETTINGS - - features := model.Preferences{ - { - UserId: userId, - Category: category, - Name: FEATURE_TOGGLE_PREFIX + feature1, - Value: "true", - }, - { - UserId: userId, - Category: category, - Name: model.NewId(), - Value: "false", - }, - { - UserId: userId, - Category: model.NewId(), - Name: FEATURE_TOGGLE_PREFIX + feature1, - Value: "false", - }, - { - UserId: model.NewId(), - Category: category, - Name: FEATURE_TOGGLE_PREFIX + feature2, - Value: "false", - }, - { - UserId: model.NewId(), - Category: category, - Name: FEATURE_TOGGLE_PREFIX + feature3, - Value: "foobar", - }, - } - - store.Must(ss.Preference().Save(&features)) - - if result := <-ss.Preference().IsFeatureEnabled(feature1, userId); result.Err != nil { - t.Fatal(result.Err) - } else if data := result.Data.(bool); data != true { - t.Fatalf("got incorrect setting for feature1, %v=%v", true, data) - } - - if result := <-ss.Preference().IsFeatureEnabled(feature2, userId); result.Err != nil { - t.Fatal(result.Err) - } else if data := result.Data.(bool); data != false { - t.Fatalf("got incorrect setting for feature2, %v=%v", false, data) - } - - // make sure we get false if something different than "true" or "false" has been saved to database - if result := <-ss.Preference().IsFeatureEnabled(feature3, userId); result.Err != nil { - t.Fatal(result.Err) - } else if data := result.Data.(bool); data != false { - t.Fatalf("got incorrect setting for feature3, %v=%v", false, data) - } - - // make sure false is returned if a non-existent feature is queried - if result := <-ss.Preference().IsFeatureEnabled("someOtherFeature", userId); result.Err != nil { - t.Fatal(result.Err) - } else if data := result.Data.(bool); data != false { - t.Fatalf("got incorrect setting for non-existent feature 'someOtherFeature', %v=%v", false, data) - } +func TestPreferenceStore(t *testing.T) { + StoreTest(t, storetest.TestPreferenceStore) } func TestDeleteUnusedFeatures(t *testing.T) { - ss := Setup() - - userId1 := model.NewId() - userId2 := model.NewId() - category := model.PREFERENCE_CATEGORY_ADVANCED_SETTINGS - feature1 := "feature1" - feature2 := "feature2" - - features := model.Preferences{ - { - UserId: userId1, - Category: category, - Name: FEATURE_TOGGLE_PREFIX + feature1, - Value: "true", - }, - { - UserId: userId2, - Category: category, - Name: FEATURE_TOGGLE_PREFIX + feature1, - Value: "false", - }, - { - UserId: userId1, - Category: category, - Name: FEATURE_TOGGLE_PREFIX + feature2, - Value: "false", - }, - { - UserId: userId2, - Category: category, - Name: FEATURE_TOGGLE_PREFIX + feature2, - Value: "true", - }, - } - - store.Must(ss.Preference().Save(&features)) - - ss.Preference().(*SqlPreferenceStore).DeleteUnusedFeatures() - - //make sure features with value "false" have actually been deleted from the database - if val, err := ss.Preference().(*SqlPreferenceStore).GetReplica().SelectInt(`SELECT COUNT(*) - FROM Preferences - WHERE Category = :Category - AND Value = :Val - AND Name LIKE '`+FEATURE_TOGGLE_PREFIX+`%'`, map[string]interface{}{"Category": model.PREFERENCE_CATEGORY_ADVANCED_SETTINGS, "Val": "false"}); err != nil { - t.Fatal(err) - } else if val != 0 { - t.Fatalf("Found %d features with value 'false', expected all to be deleted", val) - } - // - // make sure features with value "true" remain saved - if val, err := ss.Preference().(*SqlPreferenceStore).GetReplica().SelectInt(`SELECT COUNT(*) - FROM Preferences - WHERE Category = :Category - AND Value = :Val - AND Name LIKE '`+FEATURE_TOGGLE_PREFIX+`%'`, map[string]interface{}{"Category": model.PREFERENCE_CATEGORY_ADVANCED_SETTINGS, "Val": "true"}); err != nil { - t.Fatal(err) - } else if val == 0 { - t.Fatalf("Found %d features with value 'true', expected to find at least %d features", val, 2) - } -} - -func TestPreferenceDelete(t *testing.T) { - ss := Setup() - - preference := model.Preference{ - UserId: model.NewId(), - Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, - Name: model.NewId(), - Value: "value1a", - } - - store.Must(ss.Preference().Save(&model.Preferences{preference})) - - if prefs := store.Must(ss.Preference().GetAll(preference.UserId)).(model.Preferences); len([]model.Preference(prefs)) != 1 { - t.Fatal("should've returned 1 preference") - } - - if result := <-ss.Preference().Delete(preference.UserId, preference.Category, preference.Name); result.Err != nil { - t.Fatal(result.Err) - } - - if prefs := store.Must(ss.Preference().GetAll(preference.UserId)).(model.Preferences); len([]model.Preference(prefs)) != 0 { - t.Fatal("should've returned no preferences") - } -} - -func TestPreferenceDeleteCategory(t *testing.T) { - ss := Setup() - - category := model.NewId() - userId := model.NewId() - - preference1 := model.Preference{ - UserId: userId, - Category: category, - Name: model.NewId(), - Value: "value1a", - } - - preference2 := model.Preference{ - UserId: userId, - Category: category, - Name: model.NewId(), - Value: "value1a", - } - - store.Must(ss.Preference().Save(&model.Preferences{preference1, preference2})) - - if prefs := store.Must(ss.Preference().GetAll(userId)).(model.Preferences); len([]model.Preference(prefs)) != 2 { - t.Fatal("should've returned 2 preferences") - } - - if result := <-ss.Preference().DeleteCategory(userId, category); result.Err != nil { - t.Fatal(result.Err) - } - - if prefs := store.Must(ss.Preference().GetAll(userId)).(model.Preferences); len([]model.Preference(prefs)) != 0 { - t.Fatal("should've returned no preferences") - } -} - -func TestPreferenceDeleteCategoryAndName(t *testing.T) { - ss := Setup() - - category := model.NewId() - name := model.NewId() - userId := model.NewId() - userId2 := model.NewId() - - preference1 := model.Preference{ - UserId: userId, - Category: category, - Name: name, - Value: "value1a", - } - - preference2 := model.Preference{ - UserId: userId2, - Category: category, - Name: name, - Value: "value1a", - } - - store.Must(ss.Preference().Save(&model.Preferences{preference1, preference2})) - - if prefs := store.Must(ss.Preference().GetAll(userId)).(model.Preferences); len([]model.Preference(prefs)) != 1 { - t.Fatal("should've returned 1 preference") - } - - if prefs := store.Must(ss.Preference().GetAll(userId2)).(model.Preferences); len([]model.Preference(prefs)) != 1 { - t.Fatal("should've returned 1 preference") - } - - if result := <-ss.Preference().DeleteCategoryAndName(category, name); result.Err != nil { - t.Fatal(result.Err) - } - - if prefs := store.Must(ss.Preference().GetAll(userId)).(model.Preferences); len([]model.Preference(prefs)) != 0 { - t.Fatal("should've returned no preferences") - } - - if prefs := store.Must(ss.Preference().GetAll(userId2)).(model.Preferences); len([]model.Preference(prefs)) != 0 { - t.Fatal("should've returned no preferences") - } -} - -func TestPreferenceCleanupFlagsBatch(t *testing.T) { - ss := Setup() - - category := model.PREFERENCE_CATEGORY_FLAGGED_POST - userId := model.NewId() - - o1 := &model.Post{} - o1.ChannelId = model.NewId() - o1.UserId = userId - o1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" - o1.CreateAt = 1000 - o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) - - preference1 := model.Preference{ - UserId: userId, - Category: category, - Name: o1.Id, - Value: "true", - } - - preference2 := model.Preference{ - UserId: userId, - Category: category, - Name: model.NewId(), - Value: "true", - } - - store.Must(ss.Preference().Save(&model.Preferences{preference1, preference2})) + StoreTest(t, func(t *testing.T, ss store.Store) { + userId1 := model.NewId() + userId2 := model.NewId() + category := model.PREFERENCE_CATEGORY_ADVANCED_SETTINGS + feature1 := "feature1" + feature2 := "feature2" + + features := model.Preferences{ + { + UserId: userId1, + Category: category, + Name: store.FEATURE_TOGGLE_PREFIX + feature1, + Value: "true", + }, + { + UserId: userId2, + Category: category, + Name: store.FEATURE_TOGGLE_PREFIX + feature1, + Value: "false", + }, + { + UserId: userId1, + Category: category, + Name: store.FEATURE_TOGGLE_PREFIX + feature2, + Value: "false", + }, + { + UserId: userId2, + Category: category, + Name: store.FEATURE_TOGGLE_PREFIX + feature2, + Value: "true", + }, + } - result := <-ss.Preference().CleanupFlagsBatch(10000) - assert.Nil(t, result.Err) + store.Must(ss.Preference().Save(&features)) - result = <-ss.Preference().Get(userId, category, preference1.Name) - assert.Nil(t, result.Err) + ss.Preference().(*SqlPreferenceStore).DeleteUnusedFeatures() - result = <-ss.Preference().Get(userId, category, preference2.Name) - assert.NotNil(t, result.Err) + //make sure features with value "false" have actually been deleted from the database + if val, err := ss.Preference().(*SqlPreferenceStore).GetReplica().SelectInt(`SELECT COUNT(*) + FROM Preferences + WHERE Category = :Category + AND Value = :Val + AND Name LIKE '`+store.FEATURE_TOGGLE_PREFIX+`%'`, map[string]interface{}{"Category": model.PREFERENCE_CATEGORY_ADVANCED_SETTINGS, "Val": "false"}); err != nil { + t.Fatal(err) + } else if val != 0 { + t.Fatalf("Found %d features with value 'false', expected all to be deleted", val) + } + // + // make sure features with value "true" remain saved + if val, err := ss.Preference().(*SqlPreferenceStore).GetReplica().SelectInt(`SELECT COUNT(*) + FROM Preferences + WHERE Category = :Category + AND Value = :Val + AND Name LIKE '`+store.FEATURE_TOGGLE_PREFIX+`%'`, map[string]interface{}{"Category": model.PREFERENCE_CATEGORY_ADVANCED_SETTINGS, "Val": "true"}); err != nil { + t.Fatal(err) + } else if val == 0 { + t.Fatalf("Found %d features with value 'true', expected to find at least %d features", val, 2) + } + }) } diff --git a/store/sqlstore/reaction_store_test.go b/store/sqlstore/reaction_store_test.go index 28338307b..69c272937 100644 --- a/store/sqlstore/reaction_store_test.go +++ b/store/sqlstore/reaction_store_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. package sqlstore @@ -6,347 +6,9 @@ package sqlstore import ( "testing" - "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store" + "github.com/mattermost/mattermost-server/store/storetest" ) -func TestReactionSave(t *testing.T) { - ss := Setup() - - post := store.Must(ss.Post().Save(&model.Post{ - ChannelId: model.NewId(), - UserId: model.NewId(), - })).(*model.Post) - firstUpdateAt := post.UpdateAt - - reaction1 := &model.Reaction{ - UserId: model.NewId(), - PostId: post.Id, - EmojiName: model.NewId(), - } - if result := <-ss.Reaction().Save(reaction1); result.Err != nil { - t.Fatal(result.Err) - } else if saved := result.Data.(*model.Reaction); saved.UserId != reaction1.UserId || - saved.PostId != reaction1.PostId || saved.EmojiName != reaction1.EmojiName { - t.Fatal("should've saved reaction and returned it") - } - - var secondUpdateAt int64 - if postList := store.Must(ss.Post().Get(reaction1.PostId)).(*model.PostList); !postList.Posts[post.Id].HasReactions { - t.Fatal("should've set HasReactions = true on post") - } else if postList.Posts[post.Id].UpdateAt == firstUpdateAt { - t.Fatal("should've marked post as updated when HasReactions changed") - } else { - secondUpdateAt = postList.Posts[post.Id].UpdateAt - } - - if result := <-ss.Reaction().Save(reaction1); result.Err != nil { - t.Log(result.Err) - t.Fatal("should've allowed saving a duplicate reaction") - } - - // different user - reaction2 := &model.Reaction{ - UserId: model.NewId(), - PostId: reaction1.PostId, - EmojiName: reaction1.EmojiName, - } - if result := <-ss.Reaction().Save(reaction2); result.Err != nil { - t.Fatal(result.Err) - } - - if postList := store.Must(ss.Post().Get(reaction2.PostId)).(*model.PostList); postList.Posts[post.Id].UpdateAt != secondUpdateAt { - t.Fatal("shouldn't mark as updated when HasReactions hasn't changed") - } - - // different post - reaction3 := &model.Reaction{ - UserId: reaction1.UserId, - PostId: model.NewId(), - EmojiName: reaction1.EmojiName, - } - if result := <-ss.Reaction().Save(reaction3); result.Err != nil { - t.Fatal(result.Err) - } - - // different emoji - reaction4 := &model.Reaction{ - UserId: reaction1.UserId, - PostId: reaction1.PostId, - EmojiName: model.NewId(), - } - if result := <-ss.Reaction().Save(reaction4); result.Err != nil { - t.Fatal(result.Err) - } - - // invalid reaction - reaction5 := &model.Reaction{ - UserId: reaction1.UserId, - PostId: reaction1.PostId, - } - if result := <-ss.Reaction().Save(reaction5); result.Err == nil { - t.Fatal("should've failed for invalid reaction") - } -} - -func TestReactionDelete(t *testing.T) { - ss := Setup() - - post := store.Must(ss.Post().Save(&model.Post{ - ChannelId: model.NewId(), - UserId: model.NewId(), - })).(*model.Post) - - reaction := &model.Reaction{ - UserId: model.NewId(), - PostId: post.Id, - EmojiName: model.NewId(), - } - - store.Must(ss.Reaction().Save(reaction)) - firstUpdateAt := store.Must(ss.Post().Get(reaction.PostId)).(*model.PostList).Posts[post.Id].UpdateAt - - if result := <-ss.Reaction().Delete(reaction); result.Err != nil { - t.Fatal(result.Err) - } - - if result := <-ss.Reaction().GetForPost(post.Id, false); result.Err != nil { - t.Fatal(result.Err) - } else if len(result.Data.([]*model.Reaction)) != 0 { - t.Fatal("should've deleted reaction") - } - - if postList := store.Must(ss.Post().Get(post.Id)).(*model.PostList); postList.Posts[post.Id].HasReactions { - t.Fatal("should've set HasReactions = false on post") - } else if postList.Posts[post.Id].UpdateAt == firstUpdateAt { - t.Fatal("shouldn't mark as updated when HasReactions has changed after deleting reactions") - } -} - -func TestReactionGetForPost(t *testing.T) { - ss := Setup() - - postId := model.NewId() - - userId := model.NewId() - - reactions := []*model.Reaction{ - { - UserId: userId, - PostId: postId, - EmojiName: "smile", - }, - { - UserId: model.NewId(), - PostId: postId, - EmojiName: "smile", - }, - { - UserId: userId, - PostId: postId, - EmojiName: "sad", - }, - { - UserId: userId, - PostId: model.NewId(), - EmojiName: "angry", - }, - } - - for _, reaction := range reactions { - store.Must(ss.Reaction().Save(reaction)) - } - - if result := <-ss.Reaction().GetForPost(postId, false); result.Err != nil { - t.Fatal(result.Err) - } else if returned := result.Data.([]*model.Reaction); len(returned) != 3 { - t.Fatal("should've returned 3 reactions") - } else { - for _, reaction := range reactions { - found := false - - for _, returnedReaction := range returned { - if returnedReaction.UserId == reaction.UserId && returnedReaction.PostId == reaction.PostId && - returnedReaction.EmojiName == reaction.EmojiName { - found = true - break - } - } - - if !found && reaction.PostId == postId { - t.Fatalf("should've returned reaction for post %v", reaction) - } else if found && reaction.PostId != postId { - t.Fatal("shouldn't have returned reaction for another post") - } - } - } - - // Should return cached item - if result := <-ss.Reaction().GetForPost(postId, true); result.Err != nil { - t.Fatal(result.Err) - } else if returned := result.Data.([]*model.Reaction); len(returned) != 3 { - t.Fatal("should've returned 3 reactions") - } else { - for _, reaction := range reactions { - found := false - - for _, returnedReaction := range returned { - if returnedReaction.UserId == reaction.UserId && returnedReaction.PostId == reaction.PostId && - returnedReaction.EmojiName == reaction.EmojiName { - found = true - break - } - } - - if !found && reaction.PostId == postId { - t.Fatalf("should've returned reaction for post %v", reaction) - } else if found && reaction.PostId != postId { - t.Fatal("shouldn't have returned reaction for another post") - } - } - } -} - -func TestReactionDeleteAllWithEmojiName(t *testing.T) { - ss := Setup() - - emojiToDelete := model.NewId() - - post := store.Must(ss.Post().Save(&model.Post{ - ChannelId: model.NewId(), - UserId: model.NewId(), - })).(*model.Post) - post2 := store.Must(ss.Post().Save(&model.Post{ - ChannelId: model.NewId(), - UserId: model.NewId(), - })).(*model.Post) - post3 := store.Must(ss.Post().Save(&model.Post{ - ChannelId: model.NewId(), - UserId: model.NewId(), - })).(*model.Post) - - userId := model.NewId() - - reactions := []*model.Reaction{ - { - UserId: userId, - PostId: post.Id, - EmojiName: emojiToDelete, - }, - { - UserId: model.NewId(), - PostId: post.Id, - EmojiName: emojiToDelete, - }, - { - UserId: userId, - PostId: post.Id, - EmojiName: "sad", - }, - { - UserId: userId, - PostId: post2.Id, - EmojiName: "angry", - }, - { - UserId: userId, - PostId: post3.Id, - EmojiName: emojiToDelete, - }, - } - - for _, reaction := range reactions { - store.Must(ss.Reaction().Save(reaction)) - } - - if result := <-ss.Reaction().DeleteAllWithEmojiName(emojiToDelete); result.Err != nil { - t.Fatal(result.Err) - } - - // check that the reactions were deleted - if returned := store.Must(ss.Reaction().GetForPost(post.Id, false)).([]*model.Reaction); len(returned) != 1 { - t.Fatal("should've only removed reactions with emoji name") - } else { - for _, reaction := range returned { - if reaction.EmojiName == "smile" { - t.Fatal("should've removed reaction with emoji name") - } - } - } - - if returned := store.Must(ss.Reaction().GetForPost(post2.Id, false)).([]*model.Reaction); len(returned) != 1 { - t.Fatal("should've only removed reactions with emoji name") - } - - if returned := store.Must(ss.Reaction().GetForPost(post3.Id, false)).([]*model.Reaction); len(returned) != 0 { - t.Fatal("should've only removed reactions with emoji name") - } - - // check that the posts are updated - if postList := store.Must(ss.Post().Get(post.Id)).(*model.PostList); !postList.Posts[post.Id].HasReactions { - t.Fatal("post should still have reactions") - } - - if postList := store.Must(ss.Post().Get(post2.Id)).(*model.PostList); !postList.Posts[post2.Id].HasReactions { - t.Fatal("post should still have reactions") - } - - if postList := store.Must(ss.Post().Get(post3.Id)).(*model.PostList); postList.Posts[post3.Id].HasReactions { - t.Fatal("post shouldn't have reactions any more") - } -} - -func TestReactionStorePermanentDeleteBatch(t *testing.T) { - ss := Setup() - - post := store.Must(ss.Post().Save(&model.Post{ - ChannelId: model.NewId(), - UserId: model.NewId(), - })).(*model.Post) - - reactions := []*model.Reaction{ - { - UserId: model.NewId(), - PostId: post.Id, - EmojiName: "sad", - CreateAt: 1000, - }, - { - UserId: model.NewId(), - PostId: post.Id, - EmojiName: "sad", - CreateAt: 1500, - }, - { - UserId: model.NewId(), - PostId: post.Id, - EmojiName: "sad", - CreateAt: 2000, - }, - { - UserId: model.NewId(), - PostId: post.Id, - EmojiName: "sad", - CreateAt: 2000, - }, - } - - // Need to hang on to a reaction to delete later in order to clear the cache, as "allowFromCache" isn't honoured any more. - var lastReaction *model.Reaction - for _, reaction := range reactions { - lastReaction = store.Must(ss.Reaction().Save(reaction)).(*model.Reaction) - } - - if returned := store.Must(ss.Reaction().GetForPost(post.Id, false)).([]*model.Reaction); len(returned) != 4 { - t.Fatal("expected 4 reactions") - } - - store.Must(ss.Reaction().PermanentDeleteBatch(1800, 1000)) - - // This is to force a clear of the cache. - store.Must(ss.Reaction().Delete(lastReaction)) - - if returned := store.Must(ss.Reaction().GetForPost(post.Id, false)).([]*model.Reaction); len(returned) != 1 { - t.Fatalf("expected 1 reaction. Got: %v", len(returned)) - } +func TestReactionStore(t *testing.T) { + StoreTest(t, storetest.TestReactionStore) } diff --git a/store/sqlstore/session_store_test.go b/store/sqlstore/session_store_test.go index 1eed17b51..c84d4248c 100644 --- a/store/sqlstore/session_store_test.go +++ b/store/sqlstore/session_store_test.go @@ -6,253 +6,9 @@ package sqlstore import ( "testing" - "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store" + "github.com/mattermost/mattermost-server/store/storetest" ) -func TestSessionStoreSave(t *testing.T) { - ss := Setup() - - s1 := model.Session{} - s1.UserId = model.NewId() - - if err := (<-ss.Session().Save(&s1)).Err; err != nil { - t.Fatal(err) - } -} - -func TestSessionGet(t *testing.T) { - ss := Setup() - - s1 := model.Session{} - s1.UserId = model.NewId() - store.Must(ss.Session().Save(&s1)) - - s2 := model.Session{} - s2.UserId = s1.UserId - store.Must(ss.Session().Save(&s2)) - - s3 := model.Session{} - s3.UserId = s1.UserId - s3.ExpiresAt = 1 - store.Must(ss.Session().Save(&s3)) - - if rs1 := (<-ss.Session().Get(s1.Id)); rs1.Err != nil { - t.Fatal(rs1.Err) - } else { - if rs1.Data.(*model.Session).Id != s1.Id { - t.Fatal("should match") - } - } - - if rs2 := (<-ss.Session().GetSessions(s1.UserId)); rs2.Err != nil { - t.Fatal(rs2.Err) - } else { - if len(rs2.Data.([]*model.Session)) != 2 { - t.Fatal("should match len") - } - } -} - -func TestSessionGetWithDeviceId(t *testing.T) { - ss := Setup() - - s1 := model.Session{} - s1.UserId = model.NewId() - s1.ExpiresAt = model.GetMillis() + 10000 - store.Must(ss.Session().Save(&s1)) - - s2 := model.Session{} - s2.UserId = s1.UserId - s2.DeviceId = model.NewId() - s2.ExpiresAt = model.GetMillis() + 10000 - store.Must(ss.Session().Save(&s2)) - - s3 := model.Session{} - s3.UserId = s1.UserId - s3.ExpiresAt = 1 - s3.DeviceId = model.NewId() - store.Must(ss.Session().Save(&s3)) - - if rs1 := (<-ss.Session().GetSessionsWithActiveDeviceIds(s1.UserId)); rs1.Err != nil { - t.Fatal(rs1.Err) - } else { - if len(rs1.Data.([]*model.Session)) != 1 { - t.Fatal("should match len") - } - } -} - -func TestSessionRemove(t *testing.T) { - ss := Setup() - - s1 := model.Session{} - s1.UserId = model.NewId() - store.Must(ss.Session().Save(&s1)) - - if rs1 := (<-ss.Session().Get(s1.Id)); rs1.Err != nil { - t.Fatal(rs1.Err) - } else { - if rs1.Data.(*model.Session).Id != s1.Id { - t.Fatal("should match") - } - } - - store.Must(ss.Session().Remove(s1.Id)) - - if rs2 := (<-ss.Session().Get(s1.Id)); rs2.Err == nil { - t.Fatal("should have been removed") - } -} - -func TestSessionRemoveAll(t *testing.T) { - ss := Setup() - - s1 := model.Session{} - s1.UserId = model.NewId() - store.Must(ss.Session().Save(&s1)) - - if rs1 := (<-ss.Session().Get(s1.Id)); rs1.Err != nil { - t.Fatal(rs1.Err) - } else { - if rs1.Data.(*model.Session).Id != s1.Id { - t.Fatal("should match") - } - } - - store.Must(ss.Session().RemoveAllSessions()) - - if rs2 := (<-ss.Session().Get(s1.Id)); rs2.Err == nil { - t.Fatal("should have been removed") - } -} - -func TestSessionRemoveByUser(t *testing.T) { - ss := Setup() - - s1 := model.Session{} - s1.UserId = model.NewId() - store.Must(ss.Session().Save(&s1)) - - if rs1 := (<-ss.Session().Get(s1.Id)); rs1.Err != nil { - t.Fatal(rs1.Err) - } else { - if rs1.Data.(*model.Session).Id != s1.Id { - t.Fatal("should match") - } - } - - store.Must(ss.Session().PermanentDeleteSessionsByUser(s1.UserId)) - - if rs2 := (<-ss.Session().Get(s1.Id)); rs2.Err == nil { - t.Fatal("should have been removed") - } -} - -func TestSessionRemoveToken(t *testing.T) { - ss := Setup() - - s1 := model.Session{} - s1.UserId = model.NewId() - store.Must(ss.Session().Save(&s1)) - - if rs1 := (<-ss.Session().Get(s1.Id)); rs1.Err != nil { - t.Fatal(rs1.Err) - } else { - if rs1.Data.(*model.Session).Id != s1.Id { - t.Fatal("should match") - } - } - - store.Must(ss.Session().Remove(s1.Token)) - - if rs2 := (<-ss.Session().Get(s1.Id)); rs2.Err == nil { - t.Fatal("should have been removed") - } - - if rs3 := (<-ss.Session().GetSessions(s1.UserId)); rs3.Err != nil { - t.Fatal(rs3.Err) - } else { - if len(rs3.Data.([]*model.Session)) != 0 { - t.Fatal("should match len") - } - } -} - -func TestSessionUpdateDeviceId(t *testing.T) { - ss := Setup() - - s1 := model.Session{} - s1.UserId = model.NewId() - store.Must(ss.Session().Save(&s1)) - - if rs1 := (<-ss.Session().UpdateDeviceId(s1.Id, model.PUSH_NOTIFY_APPLE+":1234567890", s1.ExpiresAt)); rs1.Err != nil { - t.Fatal(rs1.Err) - } - - s2 := model.Session{} - s2.UserId = model.NewId() - store.Must(ss.Session().Save(&s2)) - - if rs2 := (<-ss.Session().UpdateDeviceId(s2.Id, model.PUSH_NOTIFY_APPLE+":1234567890", s1.ExpiresAt)); rs2.Err != nil { - t.Fatal(rs2.Err) - } -} - -func TestSessionUpdateDeviceId2(t *testing.T) { - ss := Setup() - - s1 := model.Session{} - s1.UserId = model.NewId() - store.Must(ss.Session().Save(&s1)) - - if rs1 := (<-ss.Session().UpdateDeviceId(s1.Id, model.PUSH_NOTIFY_APPLE_REACT_NATIVE+":1234567890", s1.ExpiresAt)); rs1.Err != nil { - t.Fatal(rs1.Err) - } - - s2 := model.Session{} - s2.UserId = model.NewId() - store.Must(ss.Session().Save(&s2)) - - if rs2 := (<-ss.Session().UpdateDeviceId(s2.Id, model.PUSH_NOTIFY_APPLE_REACT_NATIVE+":1234567890", s1.ExpiresAt)); rs2.Err != nil { - t.Fatal(rs2.Err) - } -} - -func TestSessionStoreUpdateLastActivityAt(t *testing.T) { - ss := Setup() - - s1 := model.Session{} - s1.UserId = model.NewId() - store.Must(ss.Session().Save(&s1)) - - if err := (<-ss.Session().UpdateLastActivityAt(s1.Id, 1234567890)).Err; err != nil { - t.Fatal(err) - } - - if r1 := <-ss.Session().Get(s1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.Session).LastActivityAt != 1234567890 { - t.Fatal("LastActivityAt not updated correctly") - } - } - -} - -func TestSessionCount(t *testing.T) { - ss := Setup() - - s1 := model.Session{} - s1.UserId = model.NewId() - s1.ExpiresAt = model.GetMillis() + 100000 - store.Must(ss.Session().Save(&s1)) - - if r1 := <-ss.Session().AnalyticsSessionCount(); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(int64) == 0 { - t.Fatal("should have at least 1 session") - } - } +func TestSessionStore(t *testing.T) { + StoreTest(t, storetest.TestSessionStore) } diff --git a/store/sqlstore/status_store_test.go b/store/sqlstore/status_store_test.go index 92374ff7a..ddfedeb18 100644 --- a/store/sqlstore/status_store_test.go +++ b/store/sqlstore/status_store_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. package sqlstore @@ -6,100 +6,9 @@ package sqlstore import ( "testing" - "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store" + "github.com/mattermost/mattermost-server/store/storetest" ) -func TestSqlStatusStore(t *testing.T) { - ss := Setup() - - status := &model.Status{UserId: model.NewId(), Status: model.STATUS_ONLINE, Manual: false, LastActivityAt: 0, ActiveChannel: ""} - - if err := (<-ss.Status().SaveOrUpdate(status)).Err; err != nil { - t.Fatal(err) - } - - status.LastActivityAt = 10 - - if err := (<-ss.Status().SaveOrUpdate(status)).Err; err != nil { - t.Fatal(err) - } - - if err := (<-ss.Status().Get(status.UserId)).Err; err != nil { - t.Fatal(err) - } - - status2 := &model.Status{UserId: model.NewId(), Status: model.STATUS_AWAY, Manual: false, LastActivityAt: 0, ActiveChannel: ""} - if err := (<-ss.Status().SaveOrUpdate(status2)).Err; err != nil { - t.Fatal(err) - } - - status3 := &model.Status{UserId: model.NewId(), Status: model.STATUS_OFFLINE, Manual: false, LastActivityAt: 0, ActiveChannel: ""} - if err := (<-ss.Status().SaveOrUpdate(status3)).Err; err != nil { - t.Fatal(err) - } - - if result := <-ss.Status().GetOnlineAway(); result.Err != nil { - t.Fatal(result.Err) - } else { - statuses := result.Data.([]*model.Status) - for _, status := range statuses { - if status.Status == model.STATUS_OFFLINE { - t.Fatal("should not have returned offline statuses") - } - } - } - - if result := <-ss.Status().GetOnline(); result.Err != nil { - t.Fatal(result.Err) - } else { - statuses := result.Data.([]*model.Status) - for _, status := range statuses { - if status.Status != model.STATUS_ONLINE { - t.Fatal("should not have returned offline statuses") - } - } - } - - if result := <-ss.Status().GetByIds([]string{status.UserId, "junk"}); result.Err != nil { - t.Fatal(result.Err) - } else { - statuses := result.Data.([]*model.Status) - if len(statuses) != 1 { - t.Fatal("should only have 1 status") - } - } - - if err := (<-ss.Status().ResetAll()).Err; err != nil { - t.Fatal(err) - } - - if result := <-ss.Status().Get(status.UserId); result.Err != nil { - t.Fatal(result.Err) - } else { - status := result.Data.(*model.Status) - if status.Status != model.STATUS_OFFLINE { - t.Fatal("should be offline") - } - } - - if result := <-ss.Status().UpdateLastActivityAt(status.UserId, 10); result.Err != nil { - t.Fatal(result.Err) - } -} - -func TestActiveUserCount(t *testing.T) { - ss := Setup() - - status := &model.Status{UserId: model.NewId(), Status: model.STATUS_ONLINE, Manual: false, LastActivityAt: model.GetMillis(), ActiveChannel: ""} - store.Must(ss.Status().SaveOrUpdate(status)) - - if result := <-ss.Status().GetTotalActiveUsersCount(); result.Err != nil { - t.Fatal(result.Err) - } else { - count := result.Data.(int64) - if count <= 0 { - t.Fatal() - } - } +func TestStatusStore(t *testing.T) { + StoreTest(t, storetest.TestStatusStore) } diff --git a/store/sqlstore/store_test.go b/store/sqlstore/store_test.go index 0f306a475..605c73b6a 100644 --- a/store/sqlstore/store_test.go +++ b/store/sqlstore/store_test.go @@ -4,13 +4,15 @@ package sqlstore import ( + "testing" + "github.com/mattermost/mattermost-server/store" "github.com/mattermost/mattermost-server/utils" ) var sqlStore store.Store -func Setup() store.Store { +func StoreTest(t *testing.T, f func(*testing.T, store.Store)) { if sqlStore == nil { utils.TranslationsPreInit() utils.LoadConfig("config.json") @@ -19,133 +21,5 @@ func Setup() store.Store { sqlStore.MarkSystemRanUnitTests() } - return sqlStore -} - -/* -func TestSqlStore1(t *testing.T) { - utils.TranslationsPreInit() - utils.LoadConfig("config.json") - utils.Cfg.SqlSettings.Trace = true - - store := NewSqlStore() - ss.Close() - - utils.Cfg.SqlSettings.DataSourceReplicas = []string{utils.Cfg.SqlSettings.DataSource} - - store = NewSqlStore() - ss.TotalMasterDbConnections() - ss.TotalReadDbConnections() - ss.Close() - - utils.LoadConfig("config.json") -} - -func TestAlertDbCmds(t *testing.T) { - ss := Setup() - - sqlStore := store.(SqlStore) - - if !sqlStore.DoesTableExist("Systems") { - t.Fatal("Failed table exists") - } - - if sqlStore.DoesColumnExist("Systems", "Test") { - t.Fatal("Column should not exist") - } - - if !sqlStore.CreateColumnIfNotExists("Systems", "Test", "VARCHAR(50)", "VARCHAR(50)", "") { - t.Fatal("Failed to create column") - } - - maxLen := sqlStore.GetMaxLengthOfColumnIfExists("Systems", "Test") - - if maxLen != "50" { - t.Fatal("Failed to get max length found " + maxLen) - } - - if !sqlStore.AlterColumnTypeIfExists("Systems", "Test", "VARCHAR(25)", "VARCHAR(25)") { - t.Fatal("failed to alter column size") - } - - maxLen2 := sqlStore.GetMaxLengthOfColumnIfExists("Systems", "Test") - - if maxLen2 != "25" { - t.Fatal("Failed to get max length") - } - - if !sqlStore.RenameColumnIfExists("Systems", "Test", "Test1", "VARCHAR(25)") { - t.Fatal("Failed to rename column") - } - - if sqlStore.DoesColumnExist("Systems", "Test") { - t.Fatal("Column should not exist") - } - - if !sqlStore.DoesColumnExist("Systems", "Test1") { - t.Fatal("Column should exist") - } - - sqlStore.CreateIndexIfNotExists("idx_systems_test1", "Systems", "Test1") - sqlStore.RemoveIndexIfExists("idx_systems_test1", "Systems") - - sqlStore.CreateFullTextIndexIfNotExists("idx_systems_test1", "Systems", "Test1") - sqlStore.RemoveIndexIfExists("idx_systems_test1", "Systems") - - if !sqlStore.RemoveColumnIfExists("Systems", "Test1") { - t.Fatal("Failed to remove columns") - } - - if sqlStore.DoesColumnExist("Systems", "Test1") { - t.Fatal("Column should not exist") - } -} - -func TestCreateIndexIfNotExists(t *testing.T) { - ss := Setup() - - sqlStore := store.(SqlStore) - - defer sqlStore.RemoveColumnIfExists("Systems", "Test") - if !sqlStore.CreateColumnIfNotExists("Systems", "Test", "VARCHAR(50)", "VARCHAR(50)", "") { - t.Fatal("Failed to create test column") - } - - defer sqlStore.RemoveIndexIfExists("idx_systems_create_index_test", "Systems") - if !sqlStore.CreateIndexIfNotExists("idx_systems_create_index_test", "Systems", "Test") { - t.Fatal("Should've created test index") - } - - if sqlStore.CreateIndexIfNotExists("idx_systems_create_index_test", "Systems", "Test") { - t.Fatal("Shouldn't have created index that already exists") - } -} - -func TestRemoveIndexIfExists(t *testing.T) { - ss := Setup() - - sqlStore := store.(SqlStore) - - defer sqlStore.RemoveColumnIfExists("Systems", "Test") - if !sqlStore.CreateColumnIfNotExists("Systems", "Test", "VARCHAR(50)", "VARCHAR(50)", "") { - t.Fatal("Failed to create test column") - } - - if sqlStore.RemoveIndexIfExists("idx_systems_remove_index_test", "Systems") { - t.Fatal("Should've failed to remove index that doesn't exist") - } - - defer sqlStore.RemoveIndexIfExists("idx_systems_remove_index_test", "Systems") - if !sqlStore.CreateIndexIfNotExists("idx_systems_remove_index_test", "Systems", "Test") { - t.Fatal("Should've created test index") - } - - if !sqlStore.RemoveIndexIfExists("idx_systems_remove_index_test", "Systems") { - t.Fatal("Should've removed index that exists") - } - - if sqlStore.RemoveIndexIfExists("idx_systems_remove_index_test", "Systems") { - t.Fatal("Should've failed to remove index that was already removed") - } + f(t, sqlStore) } -*/ diff --git a/store/sqlstore/system_store_test.go b/store/sqlstore/system_store_test.go index 3a0b593d9..e9793caf2 100644 --- a/store/sqlstore/system_store_test.go +++ b/store/sqlstore/system_store_test.go @@ -6,52 +6,9 @@ package sqlstore import ( "testing" - "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store" + "github.com/mattermost/mattermost-server/store/storetest" ) -func TestSqlSystemStore(t *testing.T) { - ss := Setup() - - system := &model.System{Name: model.NewId(), Value: "value"} - store.Must(ss.System().Save(system)) - - result := <-ss.System().Get() - systems := result.Data.(model.StringMap) - - if systems[system.Name] != system.Value { - t.Fatal() - } - - system.Value = "value2" - store.Must(ss.System().Update(system)) - - result2 := <-ss.System().Get() - systems2 := result2.Data.(model.StringMap) - - if systems2[system.Name] != system.Value { - t.Fatal() - } - - result3 := <-ss.System().GetByName(system.Name) - rsystem := result3.Data.(*model.System) - if rsystem.Value != system.Value { - t.Fatal() - } -} - -func TestSqlSystemStoreSaveOrUpdate(t *testing.T) { - ss := Setup() - - system := &model.System{Name: model.NewId(), Value: "value"} - - if err := (<-ss.System().SaveOrUpdate(system)).Err; err != nil { - t.Fatal(err) - } - - system.Value = "value2" - - if r := <-ss.System().SaveOrUpdate(system); r.Err != nil { - t.Fatal(r.Err) - } +func TestSystemStore(t *testing.T) { + StoreTest(t, storetest.TestSystemStore) } diff --git a/store/sqlstore/team_store_test.go b/store/sqlstore/team_store_test.go index 9ba9da97a..6618285c4 100644 --- a/store/sqlstore/team_store_test.go +++ b/store/sqlstore/team_store_test.go @@ -5,1024 +5,10 @@ package sqlstore import ( "testing" - "time" - "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store" - "github.com/mattermost/mattermost-server/utils" + "github.com/mattermost/mattermost-server/store/storetest" ) -func TestTeamStoreSave(t *testing.T) { - ss := Setup() - - o1 := model.Team{} - o1.DisplayName = "DisplayName" - o1.Name = "z-z-z" + model.NewId() + "b" - o1.Email = model.NewId() + "@nowhere.com" - o1.Type = model.TEAM_OPEN - - if err := (<-ss.Team().Save(&o1)).Err; err != nil { - t.Fatal("couldn't save item", err) - } - - if err := (<-ss.Team().Save(&o1)).Err; err == nil { - t.Fatal("shouldn't be able to update from save") - } - - o1.Id = "" - if err := (<-ss.Team().Save(&o1)).Err; err == nil { - t.Fatal("should be unique domain") - } -} - -func TestTeamStoreUpdate(t *testing.T) { - ss := Setup() - - o1 := model.Team{} - o1.DisplayName = "DisplayName" - o1.Name = "z-z-z" + model.NewId() + "b" - o1.Email = model.NewId() + "@nowhere.com" - o1.Type = model.TEAM_OPEN - if err := (<-ss.Team().Save(&o1)).Err; err != nil { - t.Fatal(err) - } - - time.Sleep(100 * time.Millisecond) - - if err := (<-ss.Team().Update(&o1)).Err; err != nil { - t.Fatal(err) - } - - o1.Id = "missing" - if err := (<-ss.Team().Update(&o1)).Err; err == nil { - t.Fatal("Update should have failed because of missing key") - } - - o1.Id = model.NewId() - if err := (<-ss.Team().Update(&o1)).Err; err == nil { - t.Fatal("Update should have faile because id change") - } -} - -func TestTeamStoreUpdateDisplayName(t *testing.T) { - ss := Setup() - - o1 := &model.Team{} - o1.DisplayName = "Display Name" - o1.Name = "z-z-z" + model.NewId() + "b" - o1.Email = model.NewId() + "@nowhere.com" - o1.Type = model.TEAM_OPEN - o1 = (<-ss.Team().Save(o1)).Data.(*model.Team) - - newDisplayName := "NewDisplayName" - - if err := (<-ss.Team().UpdateDisplayName(newDisplayName, o1.Id)).Err; err != nil { - t.Fatal(err) - } - - ro1 := (<-ss.Team().Get(o1.Id)).Data.(*model.Team) - if ro1.DisplayName != newDisplayName { - t.Fatal("DisplayName not updated") - } -} - -func TestTeamStoreGet(t *testing.T) { - ss := Setup() - - o1 := model.Team{} - o1.DisplayName = "DisplayName" - o1.Name = "z-z-z" + model.NewId() + "b" - o1.Email = model.NewId() + "@nowhere.com" - o1.Type = model.TEAM_OPEN - store.Must(ss.Team().Save(&o1)) - - if r1 := <-ss.Team().Get(o1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.Team).ToJson() != o1.ToJson() { - t.Fatal("invalid returned team") - } - } - - if err := (<-ss.Team().Get("")).Err; err == nil { - t.Fatal("Missing id should have failed") - } -} - -func TestTeamStoreGetByName(t *testing.T) { - ss := Setup() - - o1 := model.Team{} - o1.DisplayName = "DisplayName" - o1.Name = "z-z-z" + model.NewId() + "b" - o1.Email = model.NewId() + "@nowhere.com" - o1.Type = model.TEAM_OPEN - - if err := (<-ss.Team().Save(&o1)).Err; err != nil { - t.Fatal(err) - } - - if r1 := <-ss.Team().GetByName(o1.Name); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.Team).ToJson() != o1.ToJson() { - t.Fatal("invalid returned team") - } - } - - if err := (<-ss.Team().GetByName("")).Err; err == nil { - t.Fatal("Missing id should have failed") - } -} - -func TestTeamStoreSearchByName(t *testing.T) { - ss := Setup() - - o1 := model.Team{} - o1.DisplayName = "DisplayName" - var name = "zzz" + model.NewId() - o1.Name = name + "b" - o1.Email = model.NewId() + "@nowhere.com" - o1.Type = model.TEAM_OPEN - - if err := (<-ss.Team().Save(&o1)).Err; err != nil { - t.Fatal(err) - } - - if r1 := <-ss.Team().SearchByName(name); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.([]*model.Team)[0].ToJson() != o1.ToJson() { - t.Fatal("invalid returned team") - } - } -} - -func TestTeamStoreSearchAll(t *testing.T) { - ss := Setup() - - o1 := model.Team{} - o1.DisplayName = "ADisplayName" + model.NewId() - o1.Name = "zz" + model.NewId() + "a" - o1.Email = model.NewId() + "@nowhere.com" - o1.Type = model.TEAM_OPEN - - if err := (<-ss.Team().Save(&o1)).Err; err != nil { - t.Fatal(err) - } - - p2 := model.Team{} - p2.DisplayName = "BDisplayName" + model.NewId() - p2.Name = "b" + model.NewId() + "b" - p2.Email = model.NewId() + "@nowhere.com" - p2.Type = model.TEAM_INVITE - - if err := (<-ss.Team().Save(&p2)).Err; err != nil { - t.Fatal(err) - } - - r1 := <-ss.Team().SearchAll(o1.Name) - if r1.Err != nil { - t.Fatal(r1.Err) - } - if len(r1.Data.([]*model.Team)) != 1 { - t.Fatal("should have returned 1 team") - } - if r1.Data.([]*model.Team)[0].ToJson() != o1.ToJson() { - t.Fatal("invalid returned team") - } - - r1 = <-ss.Team().SearchAll(p2.DisplayName) - if r1.Err != nil { - t.Fatal(r1.Err) - } - if len(r1.Data.([]*model.Team)) != 1 { - t.Fatal("should have returned 1 team") - } - if r1.Data.([]*model.Team)[0].ToJson() != p2.ToJson() { - t.Fatal("invalid returned team") - } - - r1 = <-ss.Team().SearchAll("junk") - if r1.Err != nil { - t.Fatal(r1.Err) - } - if len(r1.Data.([]*model.Team)) != 0 { - t.Fatal("should have not returned a team") - } -} - -func TestTeamStoreSearchOpen(t *testing.T) { - ss := Setup() - - o1 := model.Team{} - o1.DisplayName = "ADisplayName" + model.NewId() - o1.Name = "zz" + model.NewId() + "a" - o1.Email = model.NewId() + "@nowhere.com" - o1.Type = model.TEAM_OPEN - o1.AllowOpenInvite = true - - if err := (<-ss.Team().Save(&o1)).Err; err != nil { - t.Fatal(err) - } - - o2 := model.Team{} - o2.DisplayName = "ADisplayName" + model.NewId() - o2.Name = "zz" + model.NewId() + "a" - o2.Email = model.NewId() + "@nowhere.com" - o2.Type = model.TEAM_OPEN - o2.AllowOpenInvite = false - - if err := (<-ss.Team().Save(&o2)).Err; err != nil { - t.Fatal(err) - } - - p2 := model.Team{} - p2.DisplayName = "BDisplayName" + model.NewId() - p2.Name = "b" + model.NewId() + "b" - p2.Email = model.NewId() + "@nowhere.com" - p2.Type = model.TEAM_INVITE - p2.AllowOpenInvite = true - - if err := (<-ss.Team().Save(&p2)).Err; err != nil { - t.Fatal(err) - } - - r1 := <-ss.Team().SearchOpen(o1.Name) - if r1.Err != nil { - t.Fatal(r1.Err) - } - if len(r1.Data.([]*model.Team)) != 1 { - t.Fatal("should have returned 1 team") - } - if r1.Data.([]*model.Team)[0].ToJson() != o1.ToJson() { - t.Fatal("invalid returned team") - } - - r1 = <-ss.Team().SearchOpen(o1.DisplayName) - if r1.Err != nil { - t.Fatal(r1.Err) - } - if len(r1.Data.([]*model.Team)) != 1 { - t.Fatal("should have returned 1 team") - } - if r1.Data.([]*model.Team)[0].ToJson() != o1.ToJson() { - t.Fatal("invalid returned team") - } - - r1 = <-ss.Team().SearchOpen(p2.Name) - if r1.Err != nil { - t.Fatal(r1.Err) - } - if len(r1.Data.([]*model.Team)) != 0 { - t.Fatal("should have not returned a team") - } - - r1 = <-ss.Team().SearchOpen(p2.DisplayName) - if r1.Err != nil { - t.Fatal(r1.Err) - } - if len(r1.Data.([]*model.Team)) != 0 { - t.Fatal("should have not returned a team") - } - - r1 = <-ss.Team().SearchOpen("junk") - if r1.Err != nil { - t.Fatal(r1.Err) - } - if len(r1.Data.([]*model.Team)) != 0 { - t.Fatal("should have not returned a team") - } - - r1 = <-ss.Team().SearchOpen(o2.DisplayName) - if r1.Err != nil { - t.Fatal(r1.Err) - } - if len(r1.Data.([]*model.Team)) != 0 { - t.Fatal("should have not returned a team") - } -} - -func TestTeamStoreGetByIniviteId(t *testing.T) { - ss := Setup() - - o1 := model.Team{} - o1.DisplayName = "DisplayName" - o1.Name = "z-z-z" + model.NewId() + "b" - o1.Email = model.NewId() + "@nowhere.com" - o1.Type = model.TEAM_OPEN - o1.InviteId = model.NewId() - - if err := (<-ss.Team().Save(&o1)).Err; err != nil { - t.Fatal(err) - } - - o2 := model.Team{} - o2.DisplayName = "DisplayName" - o2.Name = "zz" + model.NewId() + "b" - o2.Email = model.NewId() + "@nowhere.com" - o2.Type = model.TEAM_OPEN - - if err := (<-ss.Team().Save(&o2)).Err; err != nil { - t.Fatal(err) - } - - if r1 := <-ss.Team().GetByInviteId(o1.InviteId); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.Team).ToJson() != o1.ToJson() { - t.Fatal("invalid returned team") - } - } - - o2.InviteId = "" - <-ss.Team().Update(&o2) - - if r1 := <-ss.Team().GetByInviteId(o2.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.Team).Id != o2.Id { - t.Fatal("invalid returned team") - } - } - - if err := (<-ss.Team().GetByInviteId("")).Err; err == nil { - t.Fatal("Missing id should have failed") - } -} - -func TestTeamStoreByUserId(t *testing.T) { - ss := Setup() - - o1 := &model.Team{} - o1.DisplayName = "DisplayName" - o1.Name = "z-z-z" + model.NewId() + "b" - o1.Email = model.NewId() + "@nowhere.com" - o1.Type = model.TEAM_OPEN - o1.InviteId = model.NewId() - o1 = store.Must(ss.Team().Save(o1)).(*model.Team) - - m1 := &model.TeamMember{TeamId: o1.Id, UserId: model.NewId()} - store.Must(ss.Team().SaveMember(m1)) - - if r1 := <-ss.Team().GetTeamsByUserId(m1.UserId); r1.Err != nil { - t.Fatal(r1.Err) - } else { - teams := r1.Data.([]*model.Team) - if len(teams) == 0 { - t.Fatal("Should return a team") - } - - if teams[0].Id != o1.Id { - t.Fatal("should be a member") - } - - } -} - -func TestGetAllTeamListing(t *testing.T) { - ss := Setup() - - o1 := model.Team{} - o1.DisplayName = "DisplayName" - o1.Name = "z-z-z" + model.NewId() + "b" - o1.Email = model.NewId() + "@nowhere.com" - o1.Type = model.TEAM_OPEN - o1.AllowOpenInvite = true - store.Must(ss.Team().Save(&o1)) - - o2 := model.Team{} - o2.DisplayName = "DisplayName" - o2.Name = "zz" + model.NewId() + "b" - o2.Email = model.NewId() + "@nowhere.com" - o2.Type = model.TEAM_OPEN - store.Must(ss.Team().Save(&o2)) - - o3 := model.Team{} - o3.DisplayName = "DisplayName" - o3.Name = "z-z-z" + model.NewId() + "b" - o3.Email = model.NewId() + "@nowhere.com" - o3.Type = model.TEAM_INVITE - o3.AllowOpenInvite = true - store.Must(ss.Team().Save(&o3)) - - o4 := model.Team{} - o4.DisplayName = "DisplayName" - o4.Name = "zz" + model.NewId() + "b" - o4.Email = model.NewId() + "@nowhere.com" - o4.Type = model.TEAM_INVITE - store.Must(ss.Team().Save(&o4)) - - if r1 := <-ss.Team().GetAllTeamListing(); r1.Err != nil { - t.Fatal(r1.Err) - } else { - teams := r1.Data.([]*model.Team) - - for _, team := range teams { - if !team.AllowOpenInvite { - t.Fatal("should have returned team with AllowOpenInvite as true") - } - } - - if len(teams) == 0 { - t.Fatal("failed team listing") - } - } -} - -func TestGetAllTeamPageListing(t *testing.T) { - ss := Setup() - - o1 := model.Team{} - o1.DisplayName = "DisplayName" - o1.Name = "z-z-z" + model.NewId() + "b" - o1.Email = model.NewId() + "@nowhere.com" - o1.Type = model.TEAM_OPEN - o1.AllowOpenInvite = true - store.Must(ss.Team().Save(&o1)) - - o2 := model.Team{} - o2.DisplayName = "DisplayName" - o2.Name = "zz" + model.NewId() + "b" - o2.Email = model.NewId() + "@nowhere.com" - o2.Type = model.TEAM_OPEN - o2.AllowOpenInvite = false - store.Must(ss.Team().Save(&o2)) - - o3 := model.Team{} - o3.DisplayName = "DisplayName" - o3.Name = "z-z-z" + model.NewId() + "b" - o3.Email = model.NewId() + "@nowhere.com" - o3.Type = model.TEAM_INVITE - o3.AllowOpenInvite = true - store.Must(ss.Team().Save(&o3)) - - o4 := model.Team{} - o4.DisplayName = "DisplayName" - o4.Name = "zz" + model.NewId() + "b" - o4.Email = model.NewId() + "@nowhere.com" - o4.Type = model.TEAM_INVITE - o4.AllowOpenInvite = false - store.Must(ss.Team().Save(&o4)) - - if r1 := <-ss.Team().GetAllTeamPageListing(0, 10); r1.Err != nil { - t.Fatal(r1.Err) - } else { - teams := r1.Data.([]*model.Team) - - for _, team := range teams { - if !team.AllowOpenInvite { - t.Fatal("should have returned team with AllowOpenInvite as true") - } - } - - if len(teams) > 10 { - t.Fatal("should have returned max of 10 teams") - } - } - - o5 := model.Team{} - o5.DisplayName = "DisplayName" - o5.Name = "z-z-z" + model.NewId() + "b" - o5.Email = model.NewId() + "@nowhere.com" - o5.Type = model.TEAM_OPEN - o5.AllowOpenInvite = true - store.Must(ss.Team().Save(&o5)) - - if r1 := <-ss.Team().GetAllTeamPageListing(0, 4); r1.Err != nil { - t.Fatal(r1.Err) - } else { - teams := r1.Data.([]*model.Team) - - for _, team := range teams { - if !team.AllowOpenInvite { - t.Fatal("should have returned team with AllowOpenInvite as true") - } - } - - if len(teams) > 4 { - t.Fatal("should have returned max of 4 teams") - } - } - - if r1 := <-ss.Team().GetAllTeamPageListing(1, 1); r1.Err != nil { - t.Fatal(r1.Err) - } else { - teams := r1.Data.([]*model.Team) - - for _, team := range teams { - if !team.AllowOpenInvite { - t.Fatal("should have returned team with AllowOpenInvite as true") - } - } - - if len(teams) > 1 { - t.Fatal("should have returned max of 1 team") - } - } -} - -func TestDelete(t *testing.T) { - ss := Setup() - - o1 := model.Team{} - o1.DisplayName = "DisplayName" - o1.Name = "z-z-z" + model.NewId() + "b" - o1.Email = model.NewId() + "@nowhere.com" - o1.Type = model.TEAM_OPEN - o1.AllowOpenInvite = true - store.Must(ss.Team().Save(&o1)) - - o2 := model.Team{} - o2.DisplayName = "DisplayName" - o2.Name = "zz" + model.NewId() + "b" - o2.Email = model.NewId() + "@nowhere.com" - o2.Type = model.TEAM_OPEN - store.Must(ss.Team().Save(&o2)) - - if r1 := <-ss.Team().PermanentDelete(o1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } -} - -func TestTeamCount(t *testing.T) { - ss := Setup() - - o1 := model.Team{} - o1.DisplayName = "DisplayName" - o1.Name = "z-z-z" + model.NewId() + "b" - o1.Email = model.NewId() + "@nowhere.com" - o1.Type = model.TEAM_OPEN - o1.AllowOpenInvite = true - store.Must(ss.Team().Save(&o1)) - - if r1 := <-ss.Team().AnalyticsTeamCount(); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(int64) == 0 { - t.Fatal("should be at least 1 team") - } - } -} - -func TestTeamMembers(t *testing.T) { - ss := Setup() - - teamId1 := model.NewId() - teamId2 := model.NewId() - - m1 := &model.TeamMember{TeamId: teamId1, UserId: model.NewId()} - m2 := &model.TeamMember{TeamId: teamId1, UserId: model.NewId()} - m3 := &model.TeamMember{TeamId: teamId2, UserId: model.NewId()} - - if r1 := <-ss.Team().SaveMember(m1); r1.Err != nil { - t.Fatal(r1.Err) - } - - store.Must(ss.Team().SaveMember(m2)) - store.Must(ss.Team().SaveMember(m3)) - - if r1 := <-ss.Team().GetMembers(teamId1, 0, 100); r1.Err != nil { - t.Fatal(r1.Err) - } else { - ms := r1.Data.([]*model.TeamMember) - - if len(ms) != 2 { - t.Fatal() - } - } - - if r1 := <-ss.Team().GetMembers(teamId2, 0, 100); r1.Err != nil { - t.Fatal(r1.Err) - } else { - ms := r1.Data.([]*model.TeamMember) - - if len(ms) != 1 { - t.Fatal() - } - - if ms[0].UserId != m3.UserId { - t.Fatal() - - } - } - - if r1 := <-ss.Team().GetTeamsForUser(m1.UserId); r1.Err != nil { - t.Fatal(r1.Err) - } else { - ms := r1.Data.([]*model.TeamMember) - - if len(ms) != 1 { - t.Fatal() - } - - if ms[0].TeamId != m1.TeamId { - t.Fatal() - - } - } - - if r1 := <-ss.Team().RemoveMember(teamId1, m1.UserId); r1.Err != nil { - t.Fatal(r1.Err) - } - - if r1 := <-ss.Team().GetMembers(teamId1, 0, 100); r1.Err != nil { - t.Fatal(r1.Err) - } else { - ms := r1.Data.([]*model.TeamMember) - - if len(ms) != 1 { - t.Fatal() - } - - if ms[0].UserId != m2.UserId { - t.Fatal() - - } - } - - store.Must(ss.Team().SaveMember(m1)) - - if r1 := <-ss.Team().RemoveAllMembersByTeam(teamId1); r1.Err != nil { - t.Fatal(r1.Err) - } - - if r1 := <-ss.Team().GetMembers(teamId1, 0, 100); r1.Err != nil { - t.Fatal(r1.Err) - } else { - ms := r1.Data.([]*model.TeamMember) - - if len(ms) != 0 { - t.Fatal() - } - } - - uid := model.NewId() - m4 := &model.TeamMember{TeamId: teamId1, UserId: uid} - m5 := &model.TeamMember{TeamId: teamId2, UserId: uid} - store.Must(ss.Team().SaveMember(m4)) - store.Must(ss.Team().SaveMember(m5)) - - if r1 := <-ss.Team().GetTeamsForUser(uid); r1.Err != nil { - t.Fatal(r1.Err) - } else { - ms := r1.Data.([]*model.TeamMember) - - if len(ms) != 2 { - t.Fatal() - } - } - - if r1 := <-ss.Team().RemoveAllMembersByUser(uid); r1.Err != nil { - t.Fatal(r1.Err) - } - - if r1 := <-ss.Team().GetTeamsForUser(m1.UserId); r1.Err != nil { - t.Fatal(r1.Err) - } else { - ms := r1.Data.([]*model.TeamMember) - - if len(ms) != 0 { - t.Fatal() - } - } -} - -func TestSaveTeamMemberMaxMembers(t *testing.T) { - ss := Setup() - - MaxUsersPerTeam := *utils.Cfg.TeamSettings.MaxUsersPerTeam - defer func() { - *utils.Cfg.TeamSettings.MaxUsersPerTeam = MaxUsersPerTeam - }() - *utils.Cfg.TeamSettings.MaxUsersPerTeam = 5 - - team := store.Must(ss.Team().Save(&model.Team{ - DisplayName: "DisplayName", - Name: "z-z-z" + model.NewId() + "b", - Type: model.TEAM_OPEN, - })).(*model.Team) - defer func() { - <-ss.Team().PermanentDelete(team.Id) - }() - - userIds := make([]string, *utils.Cfg.TeamSettings.MaxUsersPerTeam) - - for i := 0; i < *utils.Cfg.TeamSettings.MaxUsersPerTeam; i++ { - userIds[i] = store.Must(ss.User().Save(&model.User{ - Username: model.NewId(), - Email: model.NewId(), - })).(*model.User).Id - - defer func(userId string) { - <-ss.User().PermanentDelete(userId) - }(userIds[i]) - - store.Must(ss.Team().SaveMember(&model.TeamMember{ - TeamId: team.Id, - UserId: userIds[i], - })) - - defer func(userId string) { - <-ss.Team().RemoveMember(team.Id, userId) - }(userIds[i]) - } - - if result := <-ss.Team().GetTotalMemberCount(team.Id); result.Err != nil { - t.Fatal(result.Err) - } else if count := result.Data.(int64); int(count) != *utils.Cfg.TeamSettings.MaxUsersPerTeam { - t.Fatalf("should start with 5 team members, had %v instead", count) - } - - newUserId := store.Must(ss.User().Save(&model.User{ - Username: model.NewId(), - Email: model.NewId(), - })).(*model.User).Id - defer func() { - <-ss.User().PermanentDelete(newUserId) - }() - - if result := <-ss.Team().SaveMember(&model.TeamMember{ - TeamId: team.Id, - UserId: newUserId, - }); result.Err == nil { - t.Fatal("shouldn't be able to save member when at maximum members per team") - } - - if result := <-ss.Team().GetTotalMemberCount(team.Id); result.Err != nil { - t.Fatal(result.Err) - } else if count := result.Data.(int64); int(count) != *utils.Cfg.TeamSettings.MaxUsersPerTeam { - t.Fatalf("should still have 5 team members, had %v instead", count) - } - - // Leaving the team from the UI sets DeleteAt instead of using TeamStore.RemoveMember - store.Must(ss.Team().UpdateMember(&model.TeamMember{ - TeamId: team.Id, - UserId: userIds[0], - DeleteAt: 1234, - })) - - if result := <-ss.Team().GetTotalMemberCount(team.Id); result.Err != nil { - t.Fatal(result.Err) - } else if count := result.Data.(int64); int(count) != *utils.Cfg.TeamSettings.MaxUsersPerTeam-1 { - t.Fatalf("should now only have 4 team members, had %v instead", count) - } - - if result := <-ss.Team().SaveMember(&model.TeamMember{TeamId: team.Id, UserId: newUserId}); result.Err != nil { - t.Fatal("should've been able to save new member after deleting one", result.Err) - } else { - defer func(userId string) { - <-ss.Team().RemoveMember(team.Id, userId) - }(newUserId) - } - - if result := <-ss.Team().GetTotalMemberCount(team.Id); result.Err != nil { - t.Fatal(result.Err) - } else if count := result.Data.(int64); int(count) != *utils.Cfg.TeamSettings.MaxUsersPerTeam { - t.Fatalf("should have 5 team members again, had %v instead", count) - } - - // Deactivating a user should make them stop counting against max members - user2 := store.Must(ss.User().Get(userIds[1])).(*model.User) - user2.DeleteAt = 1234 - store.Must(ss.User().Update(user2, true)) - - newUserId2 := store.Must(ss.User().Save(&model.User{ - Username: model.NewId(), - Email: model.NewId(), - })).(*model.User).Id - if result := <-ss.Team().SaveMember(&model.TeamMember{TeamId: team.Id, UserId: newUserId2}); result.Err != nil { - t.Fatal("should've been able to save new member after deleting one", result.Err) - } else { - defer func(userId string) { - <-ss.Team().RemoveMember(team.Id, userId) - }(newUserId2) - } -} - -func TestGetTeamMember(t *testing.T) { - ss := Setup() - - teamId1 := model.NewId() - - m1 := &model.TeamMember{TeamId: teamId1, UserId: model.NewId()} - store.Must(ss.Team().SaveMember(m1)) - - if r := <-ss.Team().GetMember(m1.TeamId, m1.UserId); r.Err != nil { - t.Fatal(r.Err) - } else { - rm1 := r.Data.(*model.TeamMember) - - if rm1.TeamId != m1.TeamId { - t.Fatal("bad team id") - } - - if rm1.UserId != m1.UserId { - t.Fatal("bad user id") - } - } - - if r := <-ss.Team().GetMember(m1.TeamId, ""); r.Err == nil { - t.Fatal("empty user id - should have failed") - } - - if r := <-ss.Team().GetMember("", m1.UserId); r.Err == nil { - t.Fatal("empty team id - should have failed") - } -} - -func TestGetTeamMembersByIds(t *testing.T) { - ss := Setup() - - teamId1 := model.NewId() - - m1 := &model.TeamMember{TeamId: teamId1, UserId: model.NewId()} - store.Must(ss.Team().SaveMember(m1)) - - if r := <-ss.Team().GetMembersByIds(m1.TeamId, []string{m1.UserId}); r.Err != nil { - t.Fatal(r.Err) - } else { - rm1 := r.Data.([]*model.TeamMember)[0] - - if rm1.TeamId != m1.TeamId { - t.Fatal("bad team id") - } - - if rm1.UserId != m1.UserId { - t.Fatal("bad user id") - } - } - - m2 := &model.TeamMember{TeamId: teamId1, UserId: model.NewId()} - store.Must(ss.Team().SaveMember(m2)) - - if r := <-ss.Team().GetMembersByIds(m1.TeamId, []string{m1.UserId, m2.UserId, model.NewId()}); r.Err != nil { - t.Fatal(r.Err) - } else { - rm := r.Data.([]*model.TeamMember) - - if len(rm) != 2 { - t.Fatal("return wrong number of results") - } - } - - if r := <-ss.Team().GetMembersByIds(m1.TeamId, []string{}); r.Err == nil { - t.Fatal("empty user ids - should have failed") - } -} - -func TestTeamStoreMemberCount(t *testing.T) { - ss := Setup() - - u1 := &model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - - u2 := &model.User{} - u2.Email = model.NewId() - u2.DeleteAt = 1 - store.Must(ss.User().Save(u2)) - - teamId1 := model.NewId() - m1 := &model.TeamMember{TeamId: teamId1, UserId: u1.Id} - store.Must(ss.Team().SaveMember(m1)) - - m2 := &model.TeamMember{TeamId: teamId1, UserId: u2.Id} - store.Must(ss.Team().SaveMember(m2)) - - if result := <-ss.Team().GetTotalMemberCount(teamId1); result.Err != nil { - t.Fatal(result.Err) - } else { - if result.Data.(int64) != 2 { - t.Fatal("wrong count") - } - } - - if result := <-ss.Team().GetActiveMemberCount(teamId1); result.Err != nil { - t.Fatal(result.Err) - } else { - if result.Data.(int64) != 1 { - t.Fatal("wrong count") - } - } - - m3 := &model.TeamMember{TeamId: teamId1, UserId: model.NewId()} - store.Must(ss.Team().SaveMember(m3)) - - if result := <-ss.Team().GetTotalMemberCount(teamId1); result.Err != nil { - t.Fatal(result.Err) - } else { - if result.Data.(int64) != 2 { - t.Fatal("wrong count") - } - } - - if result := <-ss.Team().GetActiveMemberCount(teamId1); result.Err != nil { - t.Fatal(result.Err) - } else { - if result.Data.(int64) != 1 { - t.Fatal("wrong count") - } - } -} - -func TestGetChannelUnreadsForAllTeams(t *testing.T) { - ss := Setup() - - teamId1 := model.NewId() - teamId2 := model.NewId() - - uid := model.NewId() - m1 := &model.TeamMember{TeamId: teamId1, UserId: uid} - m2 := &model.TeamMember{TeamId: teamId2, UserId: uid} - store.Must(ss.Team().SaveMember(m1)) - store.Must(ss.Team().SaveMember(m2)) - - c1 := &model.Channel{TeamId: m1.TeamId, Name: model.NewId(), DisplayName: "Town Square", Type: model.CHANNEL_OPEN, TotalMsgCount: 100} - store.Must(ss.Channel().Save(c1)) - c2 := &model.Channel{TeamId: m2.TeamId, Name: model.NewId(), DisplayName: "Town Square", Type: model.CHANNEL_OPEN, TotalMsgCount: 100} - store.Must(ss.Channel().Save(c2)) - - cm1 := &model.ChannelMember{ChannelId: c1.Id, UserId: m1.UserId, NotifyProps: model.GetDefaultChannelNotifyProps(), MsgCount: 90} - store.Must(ss.Channel().SaveMember(cm1)) - cm2 := &model.ChannelMember{ChannelId: c2.Id, UserId: m2.UserId, NotifyProps: model.GetDefaultChannelNotifyProps(), MsgCount: 90} - store.Must(ss.Channel().SaveMember(cm2)) - - if r1 := <-ss.Team().GetChannelUnreadsForAllTeams("", uid); r1.Err != nil { - t.Fatal(r1.Err) - } else { - ms := r1.Data.([]*model.ChannelUnread) - membersMap := make(map[string]bool) - for i := range ms { - id := ms[i].TeamId - if _, ok := membersMap[id]; !ok { - membersMap[id] = true - } - } - if len(membersMap) != 2 { - t.Fatal("Should be the unreads for all the teams") - } - - if ms[0].MsgCount != 10 { - t.Fatal("subtraction failed") - } - } - - if r2 := <-ss.Team().GetChannelUnreadsForAllTeams(teamId1, uid); r2.Err != nil { - t.Fatal(r2.Err) - } else { - ms := r2.Data.([]*model.ChannelUnread) - membersMap := make(map[string]bool) - for i := range ms { - id := ms[i].TeamId - if _, ok := membersMap[id]; !ok { - membersMap[id] = true - } - } - - if len(membersMap) != 1 { - t.Fatal("Should be the unreads for just one team") - } - - if ms[0].MsgCount != 10 { - t.Fatal("subtraction failed") - } - } - - if r1 := <-ss.Team().RemoveAllMembersByUser(uid); r1.Err != nil { - t.Fatal(r1.Err) - } -} - -func TestGetChannelUnreadsForTeam(t *testing.T) { - ss := Setup() - - teamId1 := model.NewId() - - uid := model.NewId() - m1 := &model.TeamMember{TeamId: teamId1, UserId: uid} - store.Must(ss.Team().SaveMember(m1)) - - c1 := &model.Channel{TeamId: m1.TeamId, Name: model.NewId(), DisplayName: "Town Square", Type: model.CHANNEL_OPEN, TotalMsgCount: 100} - store.Must(ss.Channel().Save(c1)) - c2 := &model.Channel{TeamId: m1.TeamId, Name: model.NewId(), DisplayName: "Town Square", Type: model.CHANNEL_OPEN, TotalMsgCount: 100} - store.Must(ss.Channel().Save(c2)) - - cm1 := &model.ChannelMember{ChannelId: c1.Id, UserId: m1.UserId, NotifyProps: model.GetDefaultChannelNotifyProps(), MsgCount: 90} - store.Must(ss.Channel().SaveMember(cm1)) - cm2 := &model.ChannelMember{ChannelId: c2.Id, UserId: m1.UserId, NotifyProps: model.GetDefaultChannelNotifyProps(), MsgCount: 90} - store.Must(ss.Channel().SaveMember(cm2)) - - if r1 := <-ss.Team().GetChannelUnreadsForTeam(m1.TeamId, m1.UserId); r1.Err != nil { - t.Fatal(r1.Err) - } else { - ms := r1.Data.([]*model.ChannelUnread) - if len(ms) != 2 { - t.Fatal("wrong length") - } - - if ms[0].MsgCount != 10 { - t.Fatal("subtraction failed") - } - } +func TestTeamStore(t *testing.T) { + StoreTest(t, storetest.TestTeamStore) } diff --git a/store/sqlstore/upgrade_test.go b/store/sqlstore/upgrade_test.go index d8d6a9e9d..7c3b2f124 100644 --- a/store/sqlstore/upgrade_test.go +++ b/store/sqlstore/upgrade_test.go @@ -11,31 +11,31 @@ import ( ) func TestStoreUpgrade(t *testing.T) { - ss := Setup() + StoreTest(t, func(t *testing.T, ss store.Store) { + saveSchemaVersion(ss.(*store.LayeredStore).DatabaseLayer.(SqlStore), VERSION_3_0_0) + UpgradeDatabase(ss.(*store.LayeredStore).DatabaseLayer.(SqlStore)) - saveSchemaVersion(ss.(*store.LayeredStore).DatabaseLayer.(SqlStore), VERSION_3_0_0) - UpgradeDatabase(ss.(*store.LayeredStore).DatabaseLayer.(SqlStore)) - - saveSchemaVersion(ss.(*store.LayeredStore).DatabaseLayer.(SqlStore), "") - UpgradeDatabase(ss.(*store.LayeredStore).DatabaseLayer.(SqlStore)) + saveSchemaVersion(ss.(*store.LayeredStore).DatabaseLayer.(SqlStore), "") + UpgradeDatabase(ss.(*store.LayeredStore).DatabaseLayer.(SqlStore)) + }) } func TestSaveSchemaVersion(t *testing.T) { - ss := Setup() - - saveSchemaVersion(ss.(*store.LayeredStore).DatabaseLayer.(SqlStore), VERSION_3_0_0) - if result := <-ss.System().Get(); result.Err != nil { - t.Fatal(result.Err) - } else { - props := result.Data.(model.StringMap) - if props["Version"] != VERSION_3_0_0 { - t.Fatal("version not updated") + StoreTest(t, func(t *testing.T, ss store.Store) { + saveSchemaVersion(ss.(*store.LayeredStore).DatabaseLayer.(SqlStore), VERSION_3_0_0) + if result := <-ss.System().Get(); result.Err != nil { + t.Fatal(result.Err) + } else { + props := result.Data.(model.StringMap) + if props["Version"] != VERSION_3_0_0 { + t.Fatal("version not updated") + } } - } - if ss.(*store.LayeredStore).DatabaseLayer.(SqlStore).GetCurrentSchemaVersion() != VERSION_3_0_0 { - t.Fatal("version not updated") - } + if ss.(*store.LayeredStore).DatabaseLayer.(SqlStore).GetCurrentSchemaVersion() != VERSION_3_0_0 { + t.Fatal("version not updated") + } - saveSchemaVersion(ss.(*store.LayeredStore).DatabaseLayer.(SqlStore), model.CurrentVersion) + saveSchemaVersion(ss.(*store.LayeredStore).DatabaseLayer.(SqlStore), model.CurrentVersion) + }) } diff --git a/store/sqlstore/user_access_token_store_test.go b/store/sqlstore/user_access_token_store_test.go index 74ce53b64..4bca12ccc 100644 --- a/store/sqlstore/user_access_token_store_test.go +++ b/store/sqlstore/user_access_token_store_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. package sqlstore @@ -6,82 +6,9 @@ package sqlstore import ( "testing" - "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store" + "github.com/mattermost/mattermost-server/store/storetest" ) -func TestUserAccessTokenSaveGetDelete(t *testing.T) { - ss := Setup() - - uat := &model.UserAccessToken{ - Token: model.NewId(), - UserId: model.NewId(), - Description: "testtoken", - } - - s1 := model.Session{} - s1.UserId = uat.UserId - s1.Token = uat.Token - - store.Must(ss.Session().Save(&s1)) - - if result := <-ss.UserAccessToken().Save(uat); result.Err != nil { - t.Fatal(result.Err) - } - - if result := <-ss.UserAccessToken().Get(uat.Id); result.Err != nil { - t.Fatal(result.Err) - } else if received := result.Data.(*model.UserAccessToken); received.Token != uat.Token { - t.Fatal("received incorrect token after save") - } - - if result := <-ss.UserAccessToken().GetByToken(uat.Token); result.Err != nil { - t.Fatal(result.Err) - } else if received := result.Data.(*model.UserAccessToken); received.Token != uat.Token { - t.Fatal("received incorrect token after save") - } - - if result := <-ss.UserAccessToken().GetByToken("notarealtoken"); result.Err == nil { - t.Fatal("should have failed on bad token") - } - - if result := <-ss.UserAccessToken().GetByUser(uat.UserId, 0, 100); result.Err != nil { - t.Fatal(result.Err) - } else if received := result.Data.([]*model.UserAccessToken); len(received) != 1 { - t.Fatal("received incorrect number of tokens after save") - } - - if result := <-ss.UserAccessToken().Delete(uat.Id); result.Err != nil { - t.Fatal(result.Err) - } - - if err := (<-ss.Session().Get(s1.Token)).Err; err == nil { - t.Fatal("should error - session should be deleted") - } - - if err := (<-ss.UserAccessToken().GetByToken(s1.Token)).Err; err == nil { - t.Fatal("should error - access token should be deleted") - } - - s2 := model.Session{} - s2.UserId = uat.UserId - s2.Token = uat.Token - - store.Must(ss.Session().Save(&s2)) - - if result := <-ss.UserAccessToken().Save(uat); result.Err != nil { - t.Fatal(result.Err) - } - - if result := <-ss.UserAccessToken().DeleteAllForUser(uat.UserId); result.Err != nil { - t.Fatal(result.Err) - } - - if err := (<-ss.Session().Get(s2.Token)).Err; err == nil { - t.Fatal("should error - session should be deleted") - } - - if err := (<-ss.UserAccessToken().GetByToken(s2.Token)).Err; err == nil { - t.Fatal("should error - access token should be deleted") - } +func TestUserAccessTokenStore(t *testing.T) { + StoreTest(t, storetest.TestUserAccessTokenStore) } diff --git a/store/sqlstore/user_store_test.go b/store/sqlstore/user_store_test.go index 646d785f7..37d169c90 100644 --- a/store/sqlstore/user_store_test.go +++ b/store/sqlstore/user_store_test.go @@ -4,2101 +4,11 @@ package sqlstore import ( - "strings" "testing" - "time" - "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store" + "github.com/mattermost/mattermost-server/store/storetest" ) -func TestUserStoreSave(t *testing.T) { - ss := Setup() - - teamId := model.NewId() - - u1 := model.User{} - u1.Email = model.NewId() - u1.Username = model.NewId() - - if err := (<-ss.User().Save(&u1)).Err; err != nil { - t.Fatal("couldn't save user", err) - } - - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) - - if err := (<-ss.User().Save(&u1)).Err; err == nil { - t.Fatal("shouldn't be able to update user from save") - } - - u1.Id = "" - if err := (<-ss.User().Save(&u1)).Err; err == nil { - t.Fatal("should be unique email") - } - - u1.Email = "" - if err := (<-ss.User().Save(&u1)).Err; err == nil { - t.Fatal("should be unique username") - } - - u1.Email = strings.Repeat("0123456789", 20) - u1.Username = "" - if err := (<-ss.User().Save(&u1)).Err; err == nil { - t.Fatal("should be unique username") - } - - for i := 0; i < 49; i++ { - u1.Id = "" - u1.Email = model.NewId() - u1.Username = model.NewId() - if err := (<-ss.User().Save(&u1)).Err; err != nil { - t.Fatal("couldn't save item", err) - } - - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) - } - - u1.Id = "" - u1.Email = model.NewId() - u1.Username = model.NewId() - if err := (<-ss.User().Save(&u1)).Err; err != nil { - t.Fatal("couldn't save item", err) - } - - if err := (<-ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})).Err; err == nil { - t.Fatal("should be the limit") - } - -} - -func TestUserStoreUpdate(t *testing.T) { - ss := Setup() - - u1 := &model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) - - u2 := &model.User{} - u2.Email = model.NewId() - u2.AuthService = "ldap" - store.Must(ss.User().Save(u2)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id})) - - time.Sleep(100 * time.Millisecond) - - if err := (<-ss.User().Update(u1, false)).Err; err != nil { - t.Fatal(err) - } - - u1.Id = "missing" - if err := (<-ss.User().Update(u1, false)).Err; err == nil { - t.Fatal("Update should have failed because of missing key") - } - - u1.Id = model.NewId() - if err := (<-ss.User().Update(u1, false)).Err; err == nil { - t.Fatal("Update should have faile because id change") - } - - u2.Email = model.NewId() - if err := (<-ss.User().Update(u2, false)).Err; err == nil { - t.Fatal("Update should have failed because you can't modify AD/LDAP fields") - } - - u3 := &model.User{} - u3.Email = model.NewId() - oldEmail := u3.Email - u3.AuthService = "gitlab" - store.Must(ss.User().Save(u3)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u3.Id})) - - u3.Email = model.NewId() - if result := <-ss.User().Update(u3, false); result.Err != nil { - t.Fatal("Update should not have failed") - } else { - newUser := result.Data.([2]*model.User)[0] - if newUser.Email != oldEmail { - t.Fatal("Email should not have been updated as the update is not trusted") - } - } - - if result := <-ss.User().Update(u3, true); result.Err != nil { - t.Fatal("Update should not have failed") - } else { - newUser := result.Data.([2]*model.User)[0] - if newUser.Email != u3.Email { - t.Fatal("Email should have been updated as the update is trusted") - } - } - - if result := <-ss.User().UpdateLastPictureUpdate(u1.Id); result.Err != nil { - t.Fatal("Update should not have failed") - } -} - -func TestUserStoreUpdateUpdateAt(t *testing.T) { - ss := Setup() - - u1 := &model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) - - time.Sleep(10 * time.Millisecond) - - if err := (<-ss.User().UpdateUpdateAt(u1.Id)).Err; err != nil { - t.Fatal(err) - } - - if r1 := <-ss.User().Get(u1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.User).UpdateAt <= u1.UpdateAt { - t.Fatal("UpdateAt not updated correctly") - } - } - -} - -func TestUserStoreUpdateFailedPasswordAttempts(t *testing.T) { - ss := Setup() - - u1 := &model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) - - if err := (<-ss.User().UpdateFailedPasswordAttempts(u1.Id, 3)).Err; err != nil { - t.Fatal(err) - } - - if r1 := <-ss.User().Get(u1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.User).FailedAttempts != 3 { - t.Fatal("FailedAttempts not updated correctly") - } - } - -} - -func TestUserStoreGet(t *testing.T) { - ss := Setup() - - u1 := &model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) - - if r1 := <-ss.User().Get(u1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.User).ToJson() != u1.ToJson() { - t.Fatal("invalid returned user") - } - } - - if err := (<-ss.User().Get("")).Err; err == nil { - t.Fatal("Missing id should have failed") - } -} - -func TestUserCount(t *testing.T) { - ss := Setup() - - u1 := &model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) - - if result := <-ss.User().GetTotalUsersCount(); result.Err != nil { - t.Fatal(result.Err) - } else { - count := result.Data.(int64) - if count <= 0 { - t.Fatal() - } - } -} - -func TestGetAllUsingAuthService(t *testing.T) { - ss := Setup() - - u1 := &model.User{} - u1.Email = model.NewId() - u1.AuthService = "someservice" - store.Must(ss.User().Save(u1)) - - u2 := &model.User{} - u2.Email = model.NewId() - u2.AuthService = "someservice" - store.Must(ss.User().Save(u2)) - - if r1 := <-ss.User().GetAllUsingAuthService(u1.AuthService); r1.Err != nil { - t.Fatal(r1.Err) - } else { - users := r1.Data.([]*model.User) - if len(users) < 2 { - t.Fatal("invalid returned users") - } - } -} - -func TestUserStoreGetAllProfiles(t *testing.T) { - ss := Setup() - - u1 := &model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - - u2 := &model.User{} - u2.Email = model.NewId() - store.Must(ss.User().Save(u2)) - - if r1 := <-ss.User().GetAllProfiles(0, 100); r1.Err != nil { - t.Fatal(r1.Err) - } else { - users := r1.Data.([]*model.User) - if len(users) < 2 { - t.Fatal("invalid returned users") - } - } - - if r2 := <-ss.User().GetAllProfiles(0, 1); r2.Err != nil { - t.Fatal(r2.Err) - } else { - users := r2.Data.([]*model.User) - if len(users) != 1 { - t.Fatal("invalid returned users, limit did not work") - } - } - - if r2 := <-ss.User().GetAll(); r2.Err != nil { - t.Fatal(r2.Err) - } else { - users := r2.Data.([]*model.User) - if len(users) < 2 { - t.Fatal("invalid returned users") - } - } - - etag := "" - if r2 := <-ss.User().GetEtagForAllProfiles(); r2.Err != nil { - t.Fatal(r2.Err) - } else { - etag = r2.Data.(string) - } - - u3 := &model.User{} - u3.Email = model.NewId() - store.Must(ss.User().Save(u3)) - - if r2 := <-ss.User().GetEtagForAllProfiles(); r2.Err != nil { - t.Fatal(r2.Err) - } else { - if etag == r2.Data.(string) { - t.Fatal("etags should not match") - } - } -} - -func TestUserStoreGetProfiles(t *testing.T) { - ss := Setup() - - teamId := model.NewId() - - u1 := &model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) - - u2 := &model.User{} - u2.Email = model.NewId() - store.Must(ss.User().Save(u2)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id})) - - if r1 := <-ss.User().GetProfiles(teamId, 0, 100); r1.Err != nil { - t.Fatal(r1.Err) - } else { - users := r1.Data.([]*model.User) - if len(users) != 2 { - t.Fatal("invalid returned users") - } - - found := false - for _, u := range users { - if u.Id == u1.Id { - found = true - } - } - - if !found { - t.Fatal("missing user") - } - } - - if r2 := <-ss.User().GetProfiles("123", 0, 100); r2.Err != nil { - t.Fatal(r2.Err) - } else { - if len(r2.Data.([]*model.User)) != 0 { - t.Fatal("should have returned empty map") - } - } - - etag := "" - if r2 := <-ss.User().GetEtagForProfiles(teamId); r2.Err != nil { - t.Fatal(r2.Err) - } else { - etag = r2.Data.(string) - } - - u3 := &model.User{} - u3.Email = model.NewId() - store.Must(ss.User().Save(u3)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u3.Id})) - - if r2 := <-ss.User().GetEtagForProfiles(teamId); r2.Err != nil { - t.Fatal(r2.Err) - } else { - if etag == r2.Data.(string) { - t.Fatal("etags should not match") - } - } -} - -func TestUserStoreGetProfilesInChannel(t *testing.T) { - ss := Setup() - - teamId := model.NewId() - - u1 := &model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) - - u2 := &model.User{} - u2.Email = model.NewId() - store.Must(ss.User().Save(u2)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id})) - - c1 := model.Channel{} - c1.TeamId = teamId - c1.DisplayName = "Profiles in channel" - c1.Name = "profiles-" + model.NewId() - c1.Type = model.CHANNEL_OPEN - - c2 := model.Channel{} - c2.TeamId = teamId - c2.DisplayName = "Profiles in private" - c2.Name = "profiles-" + model.NewId() - c2.Type = model.CHANNEL_PRIVATE - - store.Must(ss.Channel().Save(&c1)) - store.Must(ss.Channel().Save(&c2)) - - m1 := model.ChannelMember{} - m1.ChannelId = c1.Id - m1.UserId = u1.Id - m1.NotifyProps = model.GetDefaultChannelNotifyProps() - - m2 := model.ChannelMember{} - m2.ChannelId = c1.Id - m2.UserId = u2.Id - m2.NotifyProps = model.GetDefaultChannelNotifyProps() - - m3 := model.ChannelMember{} - m3.ChannelId = c2.Id - m3.UserId = u1.Id - m3.NotifyProps = model.GetDefaultChannelNotifyProps() - - store.Must(ss.Channel().SaveMember(&m1)) - store.Must(ss.Channel().SaveMember(&m2)) - store.Must(ss.Channel().SaveMember(&m3)) - - if r1 := <-ss.User().GetProfilesInChannel(c1.Id, 0, 100); r1.Err != nil { - t.Fatal(r1.Err) - } else { - users := r1.Data.([]*model.User) - if len(users) != 2 { - t.Fatal("invalid returned users") - } - - found := false - for _, u := range users { - if u.Id == u1.Id { - found = true - } - } - - if !found { - t.Fatal("missing user") - } - } - - if r2 := <-ss.User().GetProfilesInChannel(c2.Id, 0, 1); r2.Err != nil { - t.Fatal(r2.Err) - } else { - if len(r2.Data.([]*model.User)) != 1 { - t.Fatal("should have returned only 1 user") - } - } -} - -func TestUserStoreGetProfilesWithoutTeam(t *testing.T) { - ss := Setup() - - teamId := model.NewId() - - // These usernames need to appear in the first 100 users for this to work - - u1 := &model.User{} - u1.Username = "a000000000" + model.NewId() - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) - defer ss.User().PermanentDelete(u1.Id) - - u2 := &model.User{} - u2.Username = "a000000001" + model.NewId() - u2.Email = model.NewId() - store.Must(ss.User().Save(u2)) - defer ss.User().PermanentDelete(u2.Id) - - if r1 := <-ss.User().GetProfilesWithoutTeam(0, 100); r1.Err != nil { - t.Fatal(r1.Err) - } else { - users := r1.Data.([]*model.User) - - found1 := false - found2 := false - for _, u := range users { - if u.Id == u1.Id { - found1 = true - } else if u.Id == u2.Id { - found2 = true - } - } - - if found1 { - t.Fatal("shouldn't have returned user on team") - } else if !found2 { - t.Fatal("should've returned user without any teams") - } - } -} - -func TestUserStoreGetAllProfilesInChannel(t *testing.T) { - ss := Setup() - - teamId := model.NewId() - - u1 := &model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) - - u2 := &model.User{} - u2.Email = model.NewId() - store.Must(ss.User().Save(u2)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id})) - - c1 := model.Channel{} - c1.TeamId = teamId - c1.DisplayName = "Profiles in channel" - c1.Name = "profiles-" + model.NewId() - c1.Type = model.CHANNEL_OPEN - - c2 := model.Channel{} - c2.TeamId = teamId - c2.DisplayName = "Profiles in private" - c2.Name = "profiles-" + model.NewId() - c2.Type = model.CHANNEL_PRIVATE - - store.Must(ss.Channel().Save(&c1)) - store.Must(ss.Channel().Save(&c2)) - - m1 := model.ChannelMember{} - m1.ChannelId = c1.Id - m1.UserId = u1.Id - m1.NotifyProps = model.GetDefaultChannelNotifyProps() - - m2 := model.ChannelMember{} - m2.ChannelId = c1.Id - m2.UserId = u2.Id - m2.NotifyProps = model.GetDefaultChannelNotifyProps() - - m3 := model.ChannelMember{} - m3.ChannelId = c2.Id - m3.UserId = u1.Id - m3.NotifyProps = model.GetDefaultChannelNotifyProps() - - store.Must(ss.Channel().SaveMember(&m1)) - store.Must(ss.Channel().SaveMember(&m2)) - store.Must(ss.Channel().SaveMember(&m3)) - - if r1 := <-ss.User().GetAllProfilesInChannel(c1.Id, false); r1.Err != nil { - t.Fatal(r1.Err) - } else { - users := r1.Data.(map[string]*model.User) - if len(users) != 2 { - t.Fatal("invalid returned users") - } - - if users[u1.Id].Id != u1.Id { - t.Fatal("invalid returned user") - } - } - - if r2 := <-ss.User().GetAllProfilesInChannel(c2.Id, false); r2.Err != nil { - t.Fatal(r2.Err) - } else { - if len(r2.Data.(map[string]*model.User)) != 1 { - t.Fatal("should have returned empty map") - } - } - - if r2 := <-ss.User().GetAllProfilesInChannel(c2.Id, true); r2.Err != nil { - t.Fatal(r2.Err) - } else { - if len(r2.Data.(map[string]*model.User)) != 1 { - t.Fatal("should have returned empty map") - } - } - - if r2 := <-ss.User().GetAllProfilesInChannel(c2.Id, true); r2.Err != nil { - t.Fatal(r2.Err) - } else { - if len(r2.Data.(map[string]*model.User)) != 1 { - t.Fatal("should have returned empty map") - } - } - - ss.User().InvalidateProfilesInChannelCacheByUser(u1.Id) - ss.User().InvalidateProfilesInChannelCache(c2.Id) -} - -func TestUserStoreGetProfilesNotInChannel(t *testing.T) { - ss := Setup() - - teamId := model.NewId() - - u1 := &model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) - - u2 := &model.User{} - u2.Email = model.NewId() - store.Must(ss.User().Save(u2)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id})) - - c1 := model.Channel{} - c1.TeamId = teamId - c1.DisplayName = "Profiles in channel" - c1.Name = "profiles-" + model.NewId() - c1.Type = model.CHANNEL_OPEN - - c2 := model.Channel{} - c2.TeamId = teamId - c2.DisplayName = "Profiles in private" - c2.Name = "profiles-" + model.NewId() - c2.Type = model.CHANNEL_PRIVATE - - store.Must(ss.Channel().Save(&c1)) - store.Must(ss.Channel().Save(&c2)) - - if r1 := <-ss.User().GetProfilesNotInChannel(teamId, c1.Id, 0, 100); r1.Err != nil { - t.Fatal(r1.Err) - } else { - users := r1.Data.([]*model.User) - if len(users) != 2 { - t.Fatal("invalid returned users") - } - - found := false - for _, u := range users { - if u.Id == u1.Id { - found = true - } - } - - if !found { - t.Fatal("missing user") - } - } - - if r2 := <-ss.User().GetProfilesNotInChannel(teamId, c2.Id, 0, 100); r2.Err != nil { - t.Fatal(r2.Err) - } else { - if len(r2.Data.([]*model.User)) != 2 { - t.Fatal("invalid returned users") - } - } - - m1 := model.ChannelMember{} - m1.ChannelId = c1.Id - m1.UserId = u1.Id - m1.NotifyProps = model.GetDefaultChannelNotifyProps() - - m2 := model.ChannelMember{} - m2.ChannelId = c1.Id - m2.UserId = u2.Id - m2.NotifyProps = model.GetDefaultChannelNotifyProps() - - m3 := model.ChannelMember{} - m3.ChannelId = c2.Id - m3.UserId = u1.Id - m3.NotifyProps = model.GetDefaultChannelNotifyProps() - - store.Must(ss.Channel().SaveMember(&m1)) - store.Must(ss.Channel().SaveMember(&m2)) - store.Must(ss.Channel().SaveMember(&m3)) - - if r1 := <-ss.User().GetProfilesNotInChannel(teamId, c1.Id, 0, 100); r1.Err != nil { - t.Fatal(r1.Err) - } else { - users := r1.Data.([]*model.User) - if len(users) != 0 { - t.Fatal("invalid returned users") - } - } - - if r2 := <-ss.User().GetProfilesNotInChannel(teamId, c2.Id, 0, 100); r2.Err != nil { - t.Fatal(r2.Err) - } else { - if len(r2.Data.([]*model.User)) != 1 { - t.Fatal("should have had 1 user not in channel") - } - } -} - -func TestUserStoreGetProfilesByIds(t *testing.T) { - ss := Setup() - - teamId := model.NewId() - - u1 := &model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) - - u2 := &model.User{} - u2.Email = model.NewId() - store.Must(ss.User().Save(u2)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id})) - - if r1 := <-ss.User().GetProfileByIds([]string{u1.Id}, false); r1.Err != nil { - t.Fatal(r1.Err) - } else { - users := r1.Data.([]*model.User) - if len(users) != 1 { - t.Fatal("invalid returned users") - } - - found := false - for _, u := range users { - if u.Id == u1.Id { - found = true - } - } - - if !found { - t.Fatal("missing user") - } - } - - if r1 := <-ss.User().GetProfileByIds([]string{u1.Id}, true); r1.Err != nil { - t.Fatal(r1.Err) - } else { - users := r1.Data.([]*model.User) - if len(users) != 1 { - t.Fatal("invalid returned users") - } - - found := false - for _, u := range users { - if u.Id == u1.Id { - found = true - } - } - - if !found { - t.Fatal("missing user") - } - } - - if r1 := <-ss.User().GetProfileByIds([]string{u1.Id, u2.Id}, true); r1.Err != nil { - t.Fatal(r1.Err) - } else { - users := r1.Data.([]*model.User) - if len(users) != 2 { - t.Fatal("invalid returned users") - } - - found := false - for _, u := range users { - if u.Id == u1.Id { - found = true - } - } - - if !found { - t.Fatal("missing user") - } - } - - if r1 := <-ss.User().GetProfileByIds([]string{u1.Id, u2.Id}, true); r1.Err != nil { - t.Fatal(r1.Err) - } else { - users := r1.Data.([]*model.User) - if len(users) != 2 { - t.Fatal("invalid returned users") - } - - found := false - for _, u := range users { - if u.Id == u1.Id { - found = true - } - } - - if !found { - t.Fatal("missing user") - } - } - - if r1 := <-ss.User().GetProfileByIds([]string{u1.Id, u2.Id}, false); r1.Err != nil { - t.Fatal(r1.Err) - } else { - users := r1.Data.([]*model.User) - if len(users) != 2 { - t.Fatal("invalid returned users") - } - - found := false - for _, u := range users { - if u.Id == u1.Id { - found = true - } - } - - if !found { - t.Fatal("missing user") - } - } - - if r1 := <-ss.User().GetProfileByIds([]string{u1.Id}, false); r1.Err != nil { - t.Fatal(r1.Err) - } else { - users := r1.Data.([]*model.User) - if len(users) != 1 { - t.Fatal("invalid returned users") - } - - found := false - for _, u := range users { - if u.Id == u1.Id { - found = true - } - } - - if !found { - t.Fatal("missing user") - } - } - - if r2 := <-ss.User().GetProfiles("123", 0, 100); r2.Err != nil { - t.Fatal(r2.Err) - } else { - if len(r2.Data.([]*model.User)) != 0 { - t.Fatal("should have returned empty array") - } - } -} - -func TestUserStoreGetProfilesByUsernames(t *testing.T) { - ss := Setup() - - teamId := model.NewId() - - u1 := &model.User{} - u1.Email = model.NewId() - u1.Username = "username1" + model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) - - u2 := &model.User{} - u2.Email = model.NewId() - u2.Username = "username2" + model.NewId() - store.Must(ss.User().Save(u2)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id})) - - if r1 := <-ss.User().GetProfilesByUsernames([]string{u1.Username, u2.Username}, teamId); r1.Err != nil { - t.Fatal(r1.Err) - } else { - users := r1.Data.([]*model.User) - if len(users) != 2 { - t.Fatal("invalid returned users") - } - - if users[0].Id != u1.Id && users[1].Id != u1.Id { - t.Fatal("invalid returned user 1") - } - - if users[0].Id != u2.Id && users[1].Id != u2.Id { - t.Fatal("invalid returned user 2") - } - } - - if r1 := <-ss.User().GetProfilesByUsernames([]string{u1.Username}, teamId); r1.Err != nil { - t.Fatal(r1.Err) - } else { - users := r1.Data.([]*model.User) - if len(users) != 1 { - t.Fatal("invalid returned users") - } - - if users[0].Id != u1.Id { - t.Fatal("invalid returned user") - } - } - - team2Id := model.NewId() - - u3 := &model.User{} - u3.Email = model.NewId() - u3.Username = "username3" + model.NewId() - store.Must(ss.User().Save(u3)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: team2Id, UserId: u3.Id})) - - if r1 := <-ss.User().GetProfilesByUsernames([]string{u1.Username, u3.Username}, ""); r1.Err != nil { - t.Fatal(r1.Err) - } else { - users := r1.Data.([]*model.User) - if len(users) != 2 { - t.Fatal("invalid returned users") - } - - if users[0].Id != u1.Id && users[1].Id != u1.Id { - t.Fatal("invalid returned user 1") - } - - if users[0].Id != u3.Id && users[1].Id != u3.Id { - t.Fatal("invalid returned user 3") - } - } - - if r1 := <-ss.User().GetProfilesByUsernames([]string{u1.Username, u3.Username}, teamId); r1.Err != nil { - t.Fatal(r1.Err) - } else { - users := r1.Data.([]*model.User) - if len(users) != 1 { - t.Fatal("invalid returned users") - } - - if users[0].Id != u1.Id { - t.Fatal("invalid returned user") - } - } -} - -func TestUserStoreGetSystemAdminProfiles(t *testing.T) { - ss := Setup() - - teamId := model.NewId() - - u1 := &model.User{} - u1.Email = model.NewId() - u1.Roles = model.ROLE_SYSTEM_USER.Id + " " + model.ROLE_SYSTEM_ADMIN.Id - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) - - u2 := &model.User{} - u2.Email = model.NewId() - store.Must(ss.User().Save(u2)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id})) - - if r1 := <-ss.User().GetSystemAdminProfiles(); r1.Err != nil { - t.Fatal(r1.Err) - } else { - users := r1.Data.(map[string]*model.User) - if len(users) <= 0 { - t.Fatal("invalid returned system admin users") - } - } -} - -func TestUserStoreGetByEmail(t *testing.T) { - ss := Setup() - - teamid := model.NewId() - - u1 := &model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamid, UserId: u1.Id})) - - if err := (<-ss.User().GetByEmail(u1.Email)).Err; err != nil { - t.Fatal(err) - } - - if err := (<-ss.User().GetByEmail("")).Err; err == nil { - t.Fatal("Should have failed because of missing email") - } -} - -func TestUserStoreGetByAuthData(t *testing.T) { - ss := Setup() - - teamId := model.NewId() - - auth := "123" + model.NewId() - - u1 := &model.User{} - u1.Email = model.NewId() - u1.AuthData = &auth - u1.AuthService = "service" - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) - - if err := (<-ss.User().GetByAuth(u1.AuthData, u1.AuthService)).Err; err != nil { - t.Fatal(err) - } - - rauth := "" - if err := (<-ss.User().GetByAuth(&rauth, "")).Err; err == nil { - t.Fatal("Should have failed because of missing auth data") - } -} - -func TestUserStoreGetByUsername(t *testing.T) { - ss := Setup() - - teamId := model.NewId() - - u1 := &model.User{} - u1.Email = model.NewId() - u1.Username = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) - - if err := (<-ss.User().GetByUsername(u1.Username)).Err; err != nil { - t.Fatal(err) - } - - if err := (<-ss.User().GetByUsername("")).Err; err == nil { - t.Fatal("Should have failed because of missing username") - } -} - -func TestUserStoreGetForLogin(t *testing.T) { - ss := Setup() - - auth := model.NewId() - - u1 := &model.User{ - Email: model.NewId(), - Username: model.NewId(), - AuthService: model.USER_AUTH_SERVICE_GITLAB, - AuthData: &auth, - } - store.Must(ss.User().Save(u1)) - - auth2 := model.NewId() - - u2 := &model.User{ - Email: model.NewId(), - Username: model.NewId(), - AuthService: model.USER_AUTH_SERVICE_LDAP, - AuthData: &auth2, - } - store.Must(ss.User().Save(u2)) - - if result := <-ss.User().GetForLogin(u1.Username, true, true, true); result.Err != nil { - t.Fatal("Should have gotten user by username", result.Err) - } else if result.Data.(*model.User).Id != u1.Id { - t.Fatal("Should have gotten user1 by username") - } - - if result := <-ss.User().GetForLogin(u1.Email, true, true, true); result.Err != nil { - t.Fatal("Should have gotten user by email", result.Err) - } else if result.Data.(*model.User).Id != u1.Id { - t.Fatal("Should have gotten user1 by email") - } - - if result := <-ss.User().GetForLogin(*u2.AuthData, true, true, true); result.Err != nil { - t.Fatal("Should have gotten user by AD/LDAP AuthData", result.Err) - } else if result.Data.(*model.User).Id != u2.Id { - t.Fatal("Should have gotten user2 by AD/LDAP AuthData") - } - - // prevent getting user by AuthData when they're not an LDAP user - if result := <-ss.User().GetForLogin(*u1.AuthData, true, true, true); result.Err == nil { - t.Fatal("Should not have gotten user by non-AD/LDAP AuthData") - } - - // prevent getting user when different login methods are disabled - if result := <-ss.User().GetForLogin(u1.Username, false, true, true); result.Err == nil { - t.Fatal("Should have failed to get user1 by username") - } - - if result := <-ss.User().GetForLogin(u1.Email, true, false, true); result.Err == nil { - t.Fatal("Should have failed to get user1 by email") - } - - if result := <-ss.User().GetForLogin(*u2.AuthData, true, true, false); result.Err == nil { - t.Fatal("Should have failed to get user3 by AD/LDAP AuthData") - } - - auth3 := model.NewId() - - // test a special case where two users will have conflicting login information so we throw a special error - u3 := &model.User{ - Email: model.NewId(), - Username: model.NewId(), - AuthService: model.USER_AUTH_SERVICE_LDAP, - AuthData: &auth3, - } - store.Must(ss.User().Save(u3)) - - u4 := &model.User{ - Email: model.NewId(), - Username: model.NewId(), - AuthService: model.USER_AUTH_SERVICE_LDAP, - AuthData: &u3.Username, - } - store.Must(ss.User().Save(u4)) - - if err := (<-ss.User().GetForLogin(u3.Username, true, true, true)).Err; err == nil { - t.Fatal("Should have failed to get users with conflicting login information") - } -} - -func TestUserStoreUpdatePassword(t *testing.T) { - ss := Setup() - - teamId := model.NewId() - - u1 := &model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) - - hashedPassword := model.HashPassword("newpwd") - - if err := (<-ss.User().UpdatePassword(u1.Id, hashedPassword)).Err; err != nil { - t.Fatal(err) - } - - if r1 := <-ss.User().GetByEmail(u1.Email); r1.Err != nil { - t.Fatal(r1.Err) - } else { - user := r1.Data.(*model.User) - if user.Password != hashedPassword { - t.Fatal("Password was not updated correctly") - } - } -} - -func TestUserStoreDelete(t *testing.T) { - ss := Setup() - - u1 := &model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) - - if err := (<-ss.User().PermanentDelete(u1.Id)).Err; err != nil { - t.Fatal(err) - } -} - -func TestUserStoreUpdateAuthData(t *testing.T) { - ss := Setup() - - teamId := model.NewId() - - u1 := &model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) - - service := "someservice" - authData := model.NewId() - - if err := (<-ss.User().UpdateAuthData(u1.Id, service, &authData, "", true)).Err; err != nil { - t.Fatal(err) - } - - if r1 := <-ss.User().GetByEmail(u1.Email); r1.Err != nil { - t.Fatal(r1.Err) - } else { - user := r1.Data.(*model.User) - if user.AuthService != service { - t.Fatal("AuthService was not updated correctly") - } - if *user.AuthData != authData { - t.Fatal("AuthData was not updated correctly") - } - if user.Password != "" { - t.Fatal("Password was not cleared properly") - } - } -} - -func TestUserUnreadCount(t *testing.T) { - ss := Setup() - - teamId := model.NewId() - - c1 := model.Channel{} - c1.TeamId = teamId - c1.DisplayName = "Unread Messages" - c1.Name = "unread-messages-" + model.NewId() - c1.Type = model.CHANNEL_OPEN - - c2 := model.Channel{} - c2.TeamId = teamId - c2.DisplayName = "Unread Direct" - c2.Name = "unread-direct-" + model.NewId() - c2.Type = model.CHANNEL_DIRECT - - u1 := &model.User{} - u1.Username = "user1" + model.NewId() - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) - - u2 := &model.User{} - u2.Email = model.NewId() - u2.Username = "user2" + model.NewId() - store.Must(ss.User().Save(u2)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id})) - - if err := (<-ss.Channel().Save(&c1)).Err; err != nil { - t.Fatal("couldn't save item", err) - } - - m1 := model.ChannelMember{} - m1.ChannelId = c1.Id - m1.UserId = u1.Id - m1.NotifyProps = model.GetDefaultChannelNotifyProps() - - m2 := model.ChannelMember{} - m2.ChannelId = c1.Id - m2.UserId = u2.Id - m2.NotifyProps = model.GetDefaultChannelNotifyProps() - - store.Must(ss.Channel().SaveMember(&m1)) - store.Must(ss.Channel().SaveMember(&m2)) - - m1.ChannelId = c2.Id - m2.ChannelId = c2.Id - - if err := (<-ss.Channel().SaveDirectChannel(&c2, &m1, &m2)).Err; err != nil { - t.Fatal("couldn't save direct channel", err) - } - - p1 := model.Post{} - p1.ChannelId = c1.Id - p1.UserId = u1.Id - p1.Message = "this is a message for @" + u2.Username - - // Post one message with mention to open channel - store.Must(ss.Post().Save(&p1)) - store.Must(ss.Channel().IncrementMentionCount(c1.Id, u2.Id)) - - // Post 2 messages without mention to direct channel - p2 := model.Post{} - p2.ChannelId = c2.Id - p2.UserId = u1.Id - p2.Message = "first message" - store.Must(ss.Post().Save(&p2)) - store.Must(ss.Channel().IncrementMentionCount(c2.Id, u2.Id)) - - p3 := model.Post{} - p3.ChannelId = c2.Id - p3.UserId = u1.Id - p3.Message = "second message" - store.Must(ss.Post().Save(&p3)) - store.Must(ss.Channel().IncrementMentionCount(c2.Id, u2.Id)) - - badge := (<-ss.User().GetUnreadCount(u2.Id)).Data.(int64) - if badge != 3 { - t.Fatal("should have 3 unread messages") - } - - badge = (<-ss.User().GetUnreadCountForChannel(u2.Id, c1.Id)).Data.(int64) - if badge != 1 { - t.Fatal("should have 1 unread messages for that channel") - } - - badge = (<-ss.User().GetUnreadCountForChannel(u2.Id, c2.Id)).Data.(int64) - if badge != 2 { - t.Fatal("should have 2 unread messages for that channel") - } -} - -func TestUserStoreUpdateMfaSecret(t *testing.T) { - ss := Setup() - - u1 := model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(&u1)) - - time.Sleep(100 * time.Millisecond) - - if err := (<-ss.User().UpdateMfaSecret(u1.Id, "12345")).Err; err != nil { - t.Fatal(err) - } - - // should pass, no update will occur though - if err := (<-ss.User().UpdateMfaSecret("junk", "12345")).Err; err != nil { - t.Fatal(err) - } -} - -func TestUserStoreUpdateMfaActive(t *testing.T) { - ss := Setup() - - u1 := model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(&u1)) - - time.Sleep(100 * time.Millisecond) - - if err := (<-ss.User().UpdateMfaActive(u1.Id, true)).Err; err != nil { - t.Fatal(err) - } - - if err := (<-ss.User().UpdateMfaActive(u1.Id, false)).Err; err != nil { - t.Fatal(err) - } - - // should pass, no update will occur though - if err := (<-ss.User().UpdateMfaActive("junk", true)).Err; err != nil { - t.Fatal(err) - } -} - -func TestUserStoreGetRecentlyActiveUsersForTeam(t *testing.T) { - ss := Setup() - - u1 := &model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Status().SaveOrUpdate(&model.Status{UserId: u1.Id, Status: model.STATUS_ONLINE, Manual: false, LastActivityAt: model.GetMillis(), ActiveChannel: ""})) - tid := model.NewId() - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: tid, UserId: u1.Id})) - - if r1 := <-ss.User().GetRecentlyActiveUsersForTeam(tid, 0, 100); r1.Err != nil { - t.Fatal(r1.Err) - } -} - -func TestUserStoreGetNewUsersForTeam(t *testing.T) { - ss := Setup() - - u1 := &model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Status().SaveOrUpdate(&model.Status{UserId: u1.Id, Status: model.STATUS_ONLINE, Manual: false, LastActivityAt: model.GetMillis(), ActiveChannel: ""})) - tid := model.NewId() - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: tid, UserId: u1.Id})) - - if r1 := <-ss.User().GetNewUsersForTeam(tid, 0, 100); r1.Err != nil { - t.Fatal(r1.Err) - } -} - -func TestUserStoreSearch(t *testing.T) { - ss := Setup() - - u1 := &model.User{} - u1.Username = "jimbo" + model.NewId() - u1.FirstName = "Tim" - u1.LastName = "Bill" - u1.Nickname = "Rob" - u1.Email = "harold" + model.NewId() + "@simulator.amazonses.com" - store.Must(ss.User().Save(u1)) - - u2 := &model.User{} - u2.Username = "jim-bobby" + model.NewId() - u2.Email = model.NewId() - store.Must(ss.User().Save(u2)) - - u3 := &model.User{} - u3.Username = "jimbo" + model.NewId() - u3.Email = model.NewId() - u3.DeleteAt = 1 - store.Must(ss.User().Save(u3)) - - u5 := &model.User{} - u5.Username = "yu" + model.NewId() - u5.FirstName = "En" - u5.LastName = "Yu" - u5.Nickname = "enyu" - u5.Email = model.NewId() + "@simulator.amazonses.com" - store.Must(ss.User().Save(u5)) - - u6 := &model.User{} - u6.Username = "underscore" + model.NewId() - u6.FirstName = "Du_" - u6.LastName = "_DE" - u6.Nickname = "lodash" - u6.Email = model.NewId() + "@simulator.amazonses.com" - store.Must(ss.User().Save(u6)) - - tid := model.NewId() - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: tid, UserId: u1.Id})) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: tid, UserId: u2.Id})) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: tid, UserId: u3.Id})) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: tid, UserId: u5.Id})) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: tid, UserId: u6.Id})) - - searchOptions := map[string]bool{} - searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true - - if r1 := <-ss.User().Search(tid, "jimb", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found1 := false - found2 := false - for _, profile := range profiles { - if profile.Id == u1.Id { - found1 = true - } - - if profile.Id == u3.Id { - found2 = true - } - } - - if !found1 { - t.Fatal("should have found user") - } - - if found2 { - t.Fatal("should not have found inactive user") - } - } - - if r1 := <-ss.User().Search(tid, "en", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found1 := false - for _, profile := range profiles { - if profile.Id == u5.Id { - found1 = true - } - } - - if !found1 { - t.Fatal("should have found user") - } - } - - searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = false - - if r1 := <-ss.User().Search(tid, u1.Email, searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found1 := false - for _, profile := range profiles { - if profile.Id == u1.Id { - found1 = true - } - } - - if !found1 { - t.Fatal("should have found user") - } - } - - searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true - - // * should be treated as a space - if r1 := <-ss.User().Search(tid, "jimb*", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found1 := false - found2 := false - for _, profile := range profiles { - if profile.Id == u1.Id { - found1 = true - } - - if profile.Id == u3.Id { - found2 = true - } - } - - if !found1 { - t.Fatal("should have found user") - } - - if found2 { - t.Fatal("should not have found inactive user") - } - } - - if r1 := <-ss.User().Search(tid, "harol", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found1 := false - for _, profile := range profiles { - if profile.Id == u1.Id { - found1 = true - } - } - - if found1 { - t.Fatal("should not have found user") - } - } - - // % should be escaped and searched for. - if r1 := <-ss.User().Search(tid, "h%", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - if len(profiles) != 0 { - t.Fatal("shouldn't have found anything") - } - } - - // "_" should be properly escaped and searched for. - if r1 := <-ss.User().Search(tid, "h_", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - if len(profiles) != 0 { - t.Fatal("shouldn't have found anything") - } - } - if r1 := <-ss.User().Search(tid, "Du_", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found6 := false - for _, profile := range profiles { - if profile.Id == u6.Id { - found6 = true - } - } - - if !found6 { - t.Fatal("should have found user") - } - } - if r1 := <-ss.User().Search(tid, "_dE", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found6 := false - for _, profile := range profiles { - if profile.Id == u6.Id { - found6 = true - } - } - - if !found6 { - t.Fatal("should have found user") - } - } - - searchOptions[store.USER_SEARCH_OPTION_ALLOW_INACTIVE] = true - - if r1 := <-ss.User().Search(tid, "jimb", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found1 := false - found2 := false - for _, profile := range profiles { - if profile.Id == u1.Id { - found1 = true - } - - if profile.Id == u3.Id { - found2 = true - } - } - - if !found1 { - t.Fatal("should have found user") - } - - if !found2 { - t.Fatal("should have found inactive user") - } - } - - searchOptions[store.USER_SEARCH_OPTION_ALLOW_INACTIVE] = false - - if r1 := <-ss.User().Search(tid, "jimb", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found := false - for _, profile := range profiles { - if profile.Id == u1.Id { - found = true - break - } - } - - if !found { - t.Fatal("should have found user") - } - } - - if r1 := <-ss.User().Search("", "jimb", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found := false - for _, profile := range profiles { - if profile.Id == u1.Id { - found = true - break - } - } - - if !found { - t.Fatal("should have found user") - } - } - - if r1 := <-ss.User().Search("", "jim-bobb", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found := false - for _, profile := range profiles { - t.Log(profile.Username) - if profile.Id == u2.Id { - found = true - break - } - } - - if !found { - t.Fatal("should have found user") - } - } - - if r1 := <-ss.User().Search(tid, "", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } - - c1 := model.Channel{} - c1.TeamId = tid - c1.DisplayName = "NameName" - c1.Name = "zz" + model.NewId() + "b" - c1.Type = model.CHANNEL_OPEN - c1 = *store.Must(ss.Channel().Save(&c1)).(*model.Channel) - - if r1 := <-ss.User().SearchNotInChannel(tid, c1.Id, "jimb", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found := false - for _, profile := range profiles { - if profile.Id == u1.Id { - found = true - break - } - } - - if !found { - t.Fatal("should have found user") - } - } - - if r1 := <-ss.User().SearchNotInChannel("", c1.Id, "jimb", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found := false - for _, profile := range profiles { - if profile.Id == u1.Id { - found = true - break - } - } - - if !found { - t.Fatal("should have found user") - } - } - - if r1 := <-ss.User().SearchNotInChannel("junk", c1.Id, "jimb", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found := false - for _, profile := range profiles { - if profile.Id == u1.Id { - found = true - break - } - } - - if found { - t.Fatal("should not have found user") - } - } - - if r1 := <-ss.User().SearchInChannel(c1.Id, "jimb", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found := false - for _, profile := range profiles { - if profile.Id == u1.Id { - found = true - break - } - } - - if found { - t.Fatal("should not have found user") - } - } - - store.Must(ss.Channel().SaveMember(&model.ChannelMember{ChannelId: c1.Id, UserId: u1.Id, NotifyProps: model.GetDefaultChannelNotifyProps()})) - - if r1 := <-ss.User().SearchInChannel(c1.Id, "jimb", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found := false - for _, profile := range profiles { - if profile.Id == u1.Id { - found = true - break - } - } - - if !found { - t.Fatal("should have found user") - } - } - - searchOptions = map[string]bool{} - - if r1 := <-ss.User().Search(tid, "harol", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found1 := false - for _, profile := range profiles { - if profile.Id == u1.Id { - found1 = true - } - } - - if !found1 { - t.Fatal("should have found user") - } - } - - if r1 := <-ss.User().Search(tid, "Tim", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found := false - for _, profile := range profiles { - if profile.Id == u1.Id { - found = true - break - } - } - - if !found { - t.Fatal("should have found user") - } - } - - if r1 := <-ss.User().Search(tid, "Bill", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found := false - for _, profile := range profiles { - if profile.Id == u1.Id { - found = true - break - } - } - - if !found { - t.Fatal("should have found user") - } - } - - if r1 := <-ss.User().Search(tid, "Rob", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found := false - for _, profile := range profiles { - if profile.Id == u1.Id { - found = true - break - } - } - - if !found { - t.Fatal("should have found user") - } - } - - // Search Users not in Team. - u4 := &model.User{} - u4.Username = "simon" + model.NewId() - u4.Email = model.NewId() - u4.DeleteAt = 0 - store.Must(ss.User().Save(u4)) - - if r1 := <-ss.User().SearchNotInTeam(tid, "simo", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found := false - for _, profile := range profiles { - if profile.Id == u4.Id { - found = true - break - } - } - - if !found { - t.Fatal("should have found user") - } - } - - if r1 := <-ss.User().SearchNotInTeam(tid, "jimb", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found := false - for _, profile := range profiles { - if profile.Id == u1.Id { - found = true - break - } - } - - if found { - t.Fatal("should not have found user") - } - } - - // Check SearchNotInTeam finds previously deleted team members. - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: tid, UserId: u4.Id})) - - if r1 := <-ss.User().SearchNotInTeam(tid, "simo", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found := false - for _, profile := range profiles { - if profile.Id == u4.Id { - found = true - break - } - } - - if found { - t.Fatal("should not have found user") - } - } - - store.Must(ss.Team().UpdateMember(&model.TeamMember{TeamId: tid, UserId: u4.Id, DeleteAt: model.GetMillis() - 1000})) - if r1 := <-ss.User().SearchNotInTeam(tid, "simo", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - found := false - for _, profile := range profiles { - if profile.Id == u4.Id { - found = true - break - } - } - - if !found { - t.Fatal("should have found user") - } - } -} - -func TestUserStoreSearchWithoutTeam(t *testing.T) { - ss := Setup() - - u1 := &model.User{} - u1.Username = "jimbo" + model.NewId() - u1.FirstName = "Tim" - u1.LastName = "Bill" - u1.Nickname = "Rob" - u1.Email = "harold" + model.NewId() + "@simulator.amazonses.com" - store.Must(ss.User().Save(u1)) - - u2 := &model.User{} - u2.Username = "jim-bobby" + model.NewId() - u2.Email = model.NewId() - store.Must(ss.User().Save(u2)) - - u3 := &model.User{} - u3.Username = "jimbo" + model.NewId() - u3.Email = model.NewId() - u3.DeleteAt = 1 - store.Must(ss.User().Save(u3)) - - tid := model.NewId() - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: tid, UserId: u3.Id})) - - searchOptions := map[string]bool{} - searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true - - if r1 := <-ss.User().SearchWithoutTeam("", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } - - if r1 := <-ss.User().SearchWithoutTeam("jim", searchOptions); r1.Err != nil { - t.Fatal(r1.Err) - } else { - profiles := r1.Data.([]*model.User) - - found1 := false - found2 := false - found3 := false - - for _, profile := range profiles { - if profile.Id == u1.Id { - found1 = true - } else if profile.Id == u2.Id { - found2 = true - } else if profile.Id == u3.Id { - found3 = true - } - } - - if !found1 { - t.Fatal("should have found user1") - } else if !found2 { - t.Fatal("should have found user2") - } else if found3 { - t.Fatal("should not have found user3") - } - } -} - -func TestUserStoreAnalyticsGetInactiveUsersCount(t *testing.T) { - ss := Setup() - - u1 := &model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - - var count int64 - - if result := <-ss.User().AnalyticsGetInactiveUsersCount(); result.Err != nil { - t.Fatal(result.Err) - } else { - count = result.Data.(int64) - } - - u2 := &model.User{} - u2.Email = model.NewId() - u2.DeleteAt = model.GetMillis() - store.Must(ss.User().Save(u2)) - - if result := <-ss.User().AnalyticsGetInactiveUsersCount(); result.Err != nil { - t.Fatal(result.Err) - } else { - newCount := result.Data.(int64) - if count != newCount-1 { - t.Fatal("Expected 1 more inactive users but found otherwise.", count, newCount) - } - } -} - -func TestUserStoreAnalyticsGetSystemAdminCount(t *testing.T) { - ss := Setup() - - var countBefore int64 - if result := <-ss.User().AnalyticsGetSystemAdminCount(); result.Err != nil { - t.Fatal(result.Err) - } else { - countBefore = result.Data.(int64) - } - - u1 := model.User{} - u1.Email = model.NewId() - u1.Username = model.NewId() - u1.Roles = "system_user system_admin" - - u2 := model.User{} - u2.Email = model.NewId() - u2.Username = model.NewId() - - if err := (<-ss.User().Save(&u1)).Err; err != nil { - t.Fatal("couldn't save user", err) - } - - if err := (<-ss.User().Save(&u2)).Err; err != nil { - t.Fatal("couldn't save user", err) - } - - if result := <-ss.User().AnalyticsGetSystemAdminCount(); result.Err != nil { - t.Fatal(result.Err) - } else { - // We expect to find 1 more system admin than there was at the start of this test function. - if count := result.Data.(int64); count != countBefore+1 { - t.Fatal("Did not get the expected number of system admins. Expected, got: ", countBefore+1, count) - } - } -} - -func TestUserStoreGetProfilesNotInTeam(t *testing.T) { - ss := Setup() - - teamId := model.NewId() - - u1 := &model.User{} - u1.Email = model.NewId() - store.Must(ss.User().Save(u1)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) - store.Must(ss.User().UpdateUpdateAt(u1.Id)) - - u2 := &model.User{} - u2.Email = model.NewId() - store.Must(ss.User().Save(u2)) - store.Must(ss.User().UpdateUpdateAt(u2.Id)) - - var initialUsersNotInTeam int - var etag1, etag2, etag3 string - - if er1 := <-ss.User().GetEtagForProfilesNotInTeam(teamId); er1.Err != nil { - t.Fatal(er1.Err) - } else { - etag1 = er1.Data.(string) - } - - if r1 := <-ss.User().GetProfilesNotInTeam(teamId, 0, 100000); r1.Err != nil { - t.Fatal(r1.Err) - } else { - users := r1.Data.([]*model.User) - initialUsersNotInTeam = len(users) - if initialUsersNotInTeam < 1 { - t.Fatalf("Should be at least 1 user not in the team") - } - - found := false - for _, u := range users { - if u.Id == u2.Id { - found = true - } - if u.Id == u1.Id { - t.Fatalf("Should not have found user1") - } - } - - if !found { - t.Fatal("missing user2") - } - } - - time.Sleep(time.Millisecond * 10) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id})) - store.Must(ss.User().UpdateUpdateAt(u2.Id)) - - if er2 := <-ss.User().GetEtagForProfilesNotInTeam(teamId); er2.Err != nil { - t.Fatal(er2.Err) - } else { - etag2 = er2.Data.(string) - if etag1 == etag2 { - t.Fatalf("etag should have changed") - } - } - - if r2 := <-ss.User().GetProfilesNotInTeam(teamId, 0, 100000); r2.Err != nil { - t.Fatal(r2.Err) - } else { - users := r2.Data.([]*model.User) - - if len(users) != initialUsersNotInTeam-1 { - t.Fatalf("Should be one less user not in team") - } - - for _, u := range users { - if u.Id == u2.Id { - t.Fatalf("Should not have found user2") - } - if u.Id == u1.Id { - t.Fatalf("Should not have found user1") - } - } - } - - time.Sleep(time.Millisecond * 10) - store.Must(ss.Team().RemoveMember(teamId, u1.Id)) - store.Must(ss.Team().RemoveMember(teamId, u2.Id)) - store.Must(ss.User().UpdateUpdateAt(u1.Id)) - store.Must(ss.User().UpdateUpdateAt(u2.Id)) - - if er3 := <-ss.User().GetEtagForProfilesNotInTeam(teamId); er3.Err != nil { - t.Fatal(er3.Err) - } else { - etag3 = er3.Data.(string) - t.Log(etag3) - if etag1 == etag3 || etag3 == etag2 { - t.Fatalf("etag should have changed") - } - } - - if r3 := <-ss.User().GetProfilesNotInTeam(teamId, 0, 100000); r3.Err != nil { - t.Fatal(r3.Err) - } else { - users := r3.Data.([]*model.User) - found1, found2 := false, false - for _, u := range users { - if u.Id == u2.Id { - found2 = true - } - if u.Id == u1.Id { - found1 = true - } - } - - if !found1 || !found2 { - t.Fatal("missing user1 or user2") - } - } - - time.Sleep(time.Millisecond * 10) - u3 := &model.User{} - u3.Email = model.NewId() - store.Must(ss.User().Save(u3)) - store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u3.Id})) - store.Must(ss.User().UpdateUpdateAt(u3.Id)) - - if er4 := <-ss.User().GetEtagForProfilesNotInTeam(teamId); er4.Err != nil { - t.Fatal(er4.Err) - } else { - etag4 := er4.Data.(string) - t.Log(etag4) - if etag4 != etag3 { - t.Fatalf("etag should be the same") - } - } +func TestUserStore(t *testing.T) { + StoreTest(t, storetest.TestUserStore) } diff --git a/store/sqlstore/webhook_store_test.go b/store/sqlstore/webhook_store_test.go index 0e6c265ec..56e9ab023 100644 --- a/store/sqlstore/webhook_store_test.go +++ b/store/sqlstore/webhook_store_test.go @@ -5,512 +5,10 @@ package sqlstore import ( "testing" - "time" - "net/http" - - "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store/storetest" ) -func TestWebhookStoreSaveIncoming(t *testing.T) { - ss := Setup() - o1 := buildIncomingWebhook() - - if err := (<-ss.Webhook().SaveIncoming(o1)).Err; err != nil { - t.Fatal("couldn't save item", err) - } - - if err := (<-ss.Webhook().SaveIncoming(o1)).Err; err == nil { - t.Fatal("shouldn't be able to update from save") - } -} - -func TestWebhookStoreUpdateIncoming(t *testing.T) { - ss := Setup() - o1 := buildIncomingWebhook() - o1 = (<-ss.Webhook().SaveIncoming(o1)).Data.(*model.IncomingWebhook) - previousUpdatedAt := o1.UpdateAt - - o1.DisplayName = "TestHook" - time.Sleep(10 * time.Millisecond) - - if result := (<-ss.Webhook().UpdateIncoming(o1)); result.Err != nil { - t.Fatal("updation of incoming hook failed", result.Err) - } else { - if result.Data.(*model.IncomingWebhook).UpdateAt == previousUpdatedAt { - t.Fatal("should have updated the UpdatedAt of the hook") - } - - if result.Data.(*model.IncomingWebhook).DisplayName != "TestHook" { - t.Fatal("display name is not updated") - } - } -} - -func TestWebhookStoreGetIncoming(t *testing.T) { - ss := Setup() - - o1 := buildIncomingWebhook() - o1 = (<-ss.Webhook().SaveIncoming(o1)).Data.(*model.IncomingWebhook) - - if r1 := <-ss.Webhook().GetIncoming(o1.Id, false); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.IncomingWebhook).CreateAt != o1.CreateAt { - t.Fatal("invalid returned webhook") - } - } - - if r1 := <-ss.Webhook().GetIncoming(o1.Id, true); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.IncomingWebhook).CreateAt != o1.CreateAt { - t.Fatal("invalid returned webhook") - } - } - - if err := (<-ss.Webhook().GetIncoming("123", false)).Err; err == nil { - t.Fatal("Missing id should have failed") - } - - if err := (<-ss.Webhook().GetIncoming("123", true)).Err; err == nil { - t.Fatal("Missing id should have failed") - } - - if err := (<-ss.Webhook().GetIncoming("123", true)).Err; err.StatusCode != http.StatusNotFound { - t.Fatal("Should have set the status as not found for missing id") - } -} - -func TestWebhookStoreGetIncomingList(t *testing.T) { - ss := Setup() - - o1 := &model.IncomingWebhook{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.TeamId = model.NewId() - - o1 = (<-ss.Webhook().SaveIncoming(o1)).Data.(*model.IncomingWebhook) - - if r1 := <-ss.Webhook().GetIncomingList(0, 1000); r1.Err != nil { - t.Fatal(r1.Err) - } else { - found := false - hooks := r1.Data.([]*model.IncomingWebhook) - for _, hook := range hooks { - if hook.Id == o1.Id { - found = true - } - } - if !found { - t.Fatal("missing webhook") - } - } - - if result := <-ss.Webhook().GetIncomingList(0, 1); result.Err != nil { - t.Fatal(result.Err) - } else { - if len(result.Data.([]*model.IncomingWebhook)) != 1 { - t.Fatal("only 1 should be returned") - } - } -} - -func TestWebhookStoreGetIncomingByTeam(t *testing.T) { - ss := Setup() - o1 := buildIncomingWebhook() - - o1 = (<-ss.Webhook().SaveIncoming(o1)).Data.(*model.IncomingWebhook) - - if r1 := <-ss.Webhook().GetIncomingByTeam(o1.TeamId, 0, 100); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.([]*model.IncomingWebhook)[0].CreateAt != o1.CreateAt { - t.Fatal("invalid returned webhook") - } - } - - if result := <-ss.Webhook().GetIncomingByTeam("123", 0, 100); result.Err != nil { - t.Fatal(result.Err) - } else { - if len(result.Data.([]*model.IncomingWebhook)) != 0 { - t.Fatal("no webhooks should have returned") - } - } -} - -func TestWebhookStoreDeleteIncoming(t *testing.T) { - ss := Setup() - o1 := buildIncomingWebhook() - - o1 = (<-ss.Webhook().SaveIncoming(o1)).Data.(*model.IncomingWebhook) - - if r1 := <-ss.Webhook().GetIncoming(o1.Id, true); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.IncomingWebhook).CreateAt != o1.CreateAt { - t.Fatal("invalid returned webhook") - } - } - - if r2 := <-ss.Webhook().DeleteIncoming(o1.Id, model.GetMillis()); r2.Err != nil { - t.Fatal(r2.Err) - } - - if r3 := (<-ss.Webhook().GetIncoming(o1.Id, true)); r3.Err == nil { - t.Log(r3.Data) - t.Fatal("Missing id should have failed") - } -} - -func TestWebhookStoreDeleteIncomingByChannel(t *testing.T) { - ss := Setup() - o1 := buildIncomingWebhook() - - o1 = (<-ss.Webhook().SaveIncoming(o1)).Data.(*model.IncomingWebhook) - - if r1 := <-ss.Webhook().GetIncoming(o1.Id, true); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.IncomingWebhook).CreateAt != o1.CreateAt { - t.Fatal("invalid returned webhook") - } - } - - if r2 := <-ss.Webhook().PermanentDeleteIncomingByChannel(o1.ChannelId); r2.Err != nil { - t.Fatal(r2.Err) - } - - if r3 := (<-ss.Webhook().GetIncoming(o1.Id, true)); r3.Err == nil { - t.Log(r3.Data) - t.Fatal("Missing id should have failed") - } -} - -func TestWebhookStoreDeleteIncomingByUser(t *testing.T) { - ss := Setup() - o1 := buildIncomingWebhook() - - o1 = (<-ss.Webhook().SaveIncoming(o1)).Data.(*model.IncomingWebhook) - - if r1 := <-ss.Webhook().GetIncoming(o1.Id, true); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.IncomingWebhook).CreateAt != o1.CreateAt { - t.Fatal("invalid returned webhook") - } - } - - if r2 := <-ss.Webhook().PermanentDeleteIncomingByUser(o1.UserId); r2.Err != nil { - t.Fatal(r2.Err) - } - - if r3 := (<-ss.Webhook().GetIncoming(o1.Id, true)); r3.Err == nil { - t.Log(r3.Data) - t.Fatal("Missing id should have failed") - } -} - -func buildIncomingWebhook() *model.IncomingWebhook { - o1 := &model.IncomingWebhook{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.TeamId = model.NewId() - - return o1 -} - -func TestWebhookStoreSaveOutgoing(t *testing.T) { - ss := Setup() - - o1 := model.OutgoingWebhook{} - o1.ChannelId = model.NewId() - o1.CreatorId = model.NewId() - o1.TeamId = model.NewId() - o1.CallbackURLs = []string{"http://nowhere.com/"} - - if err := (<-ss.Webhook().SaveOutgoing(&o1)).Err; err != nil { - t.Fatal("couldn't save item", err) - } - - if err := (<-ss.Webhook().SaveOutgoing(&o1)).Err; err == nil { - t.Fatal("shouldn't be able to update from save") - } -} - -func TestWebhookStoreGetOutgoing(t *testing.T) { - ss := Setup() - - o1 := &model.OutgoingWebhook{} - o1.ChannelId = model.NewId() - o1.CreatorId = model.NewId() - o1.TeamId = model.NewId() - o1.CallbackURLs = []string{"http://nowhere.com/"} - - o1 = (<-ss.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook) - - if r1 := <-ss.Webhook().GetOutgoing(o1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.OutgoingWebhook).CreateAt != o1.CreateAt { - t.Fatal("invalid returned webhook") - } - } - - if err := (<-ss.Webhook().GetOutgoing("123")).Err; err == nil { - t.Fatal("Missing id should have failed") - } -} - -func TestWebhookStoreGetOutgoingList(t *testing.T) { - ss := Setup() - - o1 := &model.OutgoingWebhook{} - o1.ChannelId = model.NewId() - o1.CreatorId = model.NewId() - o1.TeamId = model.NewId() - o1.CallbackURLs = []string{"http://nowhere.com/"} - - o1 = (<-ss.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook) - - o2 := &model.OutgoingWebhook{} - o2.ChannelId = model.NewId() - o2.CreatorId = model.NewId() - o2.TeamId = model.NewId() - o2.CallbackURLs = []string{"http://nowhere.com/"} - - o2 = (<-ss.Webhook().SaveOutgoing(o2)).Data.(*model.OutgoingWebhook) - - if r1 := <-ss.Webhook().GetOutgoingList(0, 1000); r1.Err != nil { - t.Fatal(r1.Err) - } else { - hooks := r1.Data.([]*model.OutgoingWebhook) - found1 := false - found2 := false - - for _, hook := range hooks { - if hook.CreateAt != o1.CreateAt { - found1 = true - } - - if hook.CreateAt != o2.CreateAt { - found2 = true - } - } - - if !found1 { - t.Fatal("missing hook1") - } - if !found2 { - t.Fatal("missing hook2") - } - } - - if result := <-ss.Webhook().GetOutgoingList(0, 2); result.Err != nil { - t.Fatal(result.Err) - } else { - if len(result.Data.([]*model.OutgoingWebhook)) != 2 { - t.Fatal("wrong number of hooks returned") - } - } -} - -func TestWebhookStoreGetOutgoingByChannel(t *testing.T) { - ss := Setup() - - o1 := &model.OutgoingWebhook{} - o1.ChannelId = model.NewId() - o1.CreatorId = model.NewId() - o1.TeamId = model.NewId() - o1.CallbackURLs = []string{"http://nowhere.com/"} - - o1 = (<-ss.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook) - - if r1 := <-ss.Webhook().GetOutgoingByChannel(o1.ChannelId, 0, 100); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.([]*model.OutgoingWebhook)[0].CreateAt != o1.CreateAt { - t.Fatal("invalid returned webhook") - } - } - - if result := <-ss.Webhook().GetOutgoingByChannel("123", -1, -1); result.Err != nil { - t.Fatal(result.Err) - } else { - if len(result.Data.([]*model.OutgoingWebhook)) != 0 { - t.Fatal("no webhooks should have returned") - } - } -} - -func TestWebhookStoreGetOutgoingByTeam(t *testing.T) { - ss := Setup() - - o1 := &model.OutgoingWebhook{} - o1.ChannelId = model.NewId() - o1.CreatorId = model.NewId() - o1.TeamId = model.NewId() - o1.CallbackURLs = []string{"http://nowhere.com/"} - - o1 = (<-ss.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook) - - if r1 := <-ss.Webhook().GetOutgoingByTeam(o1.TeamId, 0, 100); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.([]*model.OutgoingWebhook)[0].CreateAt != o1.CreateAt { - t.Fatal("invalid returned webhook") - } - } - - if result := <-ss.Webhook().GetOutgoingByTeam("123", -1, -1); result.Err != nil { - t.Fatal(result.Err) - } else { - if len(result.Data.([]*model.OutgoingWebhook)) != 0 { - t.Fatal("no webhooks should have returned") - } - } -} - -func TestWebhookStoreDeleteOutgoing(t *testing.T) { - ss := Setup() - - o1 := &model.OutgoingWebhook{} - o1.ChannelId = model.NewId() - o1.CreatorId = model.NewId() - o1.TeamId = model.NewId() - o1.CallbackURLs = []string{"http://nowhere.com/"} - - o1 = (<-ss.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook) - - if r1 := <-ss.Webhook().GetOutgoing(o1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.OutgoingWebhook).CreateAt != o1.CreateAt { - t.Fatal("invalid returned webhook") - } - } - - if r2 := <-ss.Webhook().DeleteOutgoing(o1.Id, model.GetMillis()); r2.Err != nil { - t.Fatal(r2.Err) - } - - if r3 := (<-ss.Webhook().GetOutgoing(o1.Id)); r3.Err == nil { - t.Log(r3.Data) - t.Fatal("Missing id should have failed") - } -} - -func TestWebhookStoreDeleteOutgoingByChannel(t *testing.T) { - ss := Setup() - - o1 := &model.OutgoingWebhook{} - o1.ChannelId = model.NewId() - o1.CreatorId = model.NewId() - o1.TeamId = model.NewId() - o1.CallbackURLs = []string{"http://nowhere.com/"} - - o1 = (<-ss.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook) - - if r1 := <-ss.Webhook().GetOutgoing(o1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.OutgoingWebhook).CreateAt != o1.CreateAt { - t.Fatal("invalid returned webhook") - } - } - - if r2 := <-ss.Webhook().PermanentDeleteOutgoingByChannel(o1.ChannelId); r2.Err != nil { - t.Fatal(r2.Err) - } - - if r3 := (<-ss.Webhook().GetOutgoing(o1.Id)); r3.Err == nil { - t.Log(r3.Data) - t.Fatal("Missing id should have failed") - } -} - -func TestWebhookStoreDeleteOutgoingByUser(t *testing.T) { - ss := Setup() - - o1 := &model.OutgoingWebhook{} - o1.ChannelId = model.NewId() - o1.CreatorId = model.NewId() - o1.TeamId = model.NewId() - o1.CallbackURLs = []string{"http://nowhere.com/"} - - o1 = (<-ss.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook) - - if r1 := <-ss.Webhook().GetOutgoing(o1.Id); r1.Err != nil { - t.Fatal(r1.Err) - } else { - if r1.Data.(*model.OutgoingWebhook).CreateAt != o1.CreateAt { - t.Fatal("invalid returned webhook") - } - } - - if r2 := <-ss.Webhook().PermanentDeleteOutgoingByUser(o1.CreatorId); r2.Err != nil { - t.Fatal(r2.Err) - } - - if r3 := (<-ss.Webhook().GetOutgoing(o1.Id)); r3.Err == nil { - t.Log(r3.Data) - t.Fatal("Missing id should have failed") - } -} - -func TestWebhookStoreUpdateOutgoing(t *testing.T) { - ss := Setup() - - o1 := &model.OutgoingWebhook{} - o1.ChannelId = model.NewId() - o1.CreatorId = model.NewId() - o1.TeamId = model.NewId() - o1.CallbackURLs = []string{"http://nowhere.com/"} - - o1 = (<-ss.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook) - - o1.Token = model.NewId() - - if r2 := <-ss.Webhook().UpdateOutgoing(o1); r2.Err != nil { - t.Fatal(r2.Err) - } -} - -func TestWebhookStoreCountIncoming(t *testing.T) { - ss := Setup() - - o1 := &model.IncomingWebhook{} - o1.ChannelId = model.NewId() - o1.UserId = model.NewId() - o1.TeamId = model.NewId() - - o1 = (<-ss.Webhook().SaveIncoming(o1)).Data.(*model.IncomingWebhook) - - if r := <-ss.Webhook().AnalyticsIncomingCount(""); r.Err != nil { - t.Fatal(r.Err) - } else { - if r.Data.(int64) == 0 { - t.Fatal("should have at least 1 incoming hook") - } - } -} - -func TestWebhookStoreCountOutgoing(t *testing.T) { - ss := Setup() - - o1 := &model.OutgoingWebhook{} - o1.ChannelId = model.NewId() - o1.CreatorId = model.NewId() - o1.TeamId = model.NewId() - o1.CallbackURLs = []string{"http://nowhere.com/"} - - o1 = (<-ss.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook) - - if r := <-ss.Webhook().AnalyticsOutgoingCount(""); r.Err != nil { - t.Fatal(r.Err) - } else { - if r.Data.(int64) == 0 { - t.Fatal("should have at least 1 outgoing hook") - } - } +func TestWebhookStore(t *testing.T) { + StoreTest(t, storetest.TestWebhookStore) } diff --git a/store/storetest/audit_store.go b/store/storetest/audit_store.go new file mode 100644 index 000000000..2e107dba8 --- /dev/null +++ b/store/storetest/audit_store.go @@ -0,0 +1,91 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "testing" + "time" + + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" +) + +func TestAuditStore(t *testing.T, ss store.Store) { + t.Run("", func(t *testing.T) { testAuditStore(t, ss) }) + t.Run("PermanentDeleteBatch", func(t *testing.T) { testAuditStorePermanentDeleteBatch(t, ss) }) +} + +func testAuditStore(t *testing.T, ss store.Store) { + audit := &model.Audit{UserId: model.NewId(), IpAddress: "ipaddress", Action: "Action"} + store.Must(ss.Audit().Save(audit)) + time.Sleep(100 * time.Millisecond) + store.Must(ss.Audit().Save(audit)) + time.Sleep(100 * time.Millisecond) + store.Must(ss.Audit().Save(audit)) + time.Sleep(100 * time.Millisecond) + audit.ExtraInfo = "extra" + time.Sleep(100 * time.Millisecond) + store.Must(ss.Audit().Save(audit)) + + time.Sleep(100 * time.Millisecond) + + c := ss.Audit().Get(audit.UserId, 0, 100) + result := <-c + audits := result.Data.(model.Audits) + + if len(audits) != 4 { + t.Fatal("Failed to save and retrieve 4 audit logs") + } + + if audits[0].ExtraInfo != "extra" { + t.Fatal("Failed to save property for extra info") + } + + c = ss.Audit().Get("missing", 0, 100) + result = <-c + audits = result.Data.(model.Audits) + + if len(audits) != 0 { + t.Fatal("Should have returned empty because user_id is missing") + } + + c = ss.Audit().Get("", 0, 100) + result = <-c + audits = result.Data.(model.Audits) + + if len(audits) < 4 { + t.Fatal("Failed to save and retrieve 4 audit logs") + } + + if r2 := <-ss.Audit().PermanentDeleteByUser(audit.UserId); r2.Err != nil { + t.Fatal(r2.Err) + } +} + +func testAuditStorePermanentDeleteBatch(t *testing.T, ss store.Store) { + a1 := &model.Audit{UserId: model.NewId(), IpAddress: "ipaddress", Action: "Action"} + store.Must(ss.Audit().Save(a1)) + time.Sleep(10 * time.Millisecond) + a2 := &model.Audit{UserId: a1.UserId, IpAddress: "ipaddress", Action: "Action"} + store.Must(ss.Audit().Save(a2)) + time.Sleep(10 * time.Millisecond) + cutoff := model.GetMillis() + time.Sleep(10 * time.Millisecond) + a3 := &model.Audit{UserId: a1.UserId, IpAddress: "ipaddress", Action: "Action"} + store.Must(ss.Audit().Save(a3)) + + if r := <-ss.Audit().Get(a1.UserId, 0, 100); len(r.Data.(model.Audits)) != 3 { + t.Fatal("Expected 3 audits. Got ", len(r.Data.(model.Audits))) + } + + store.Must(ss.Audit().PermanentDeleteBatch(cutoff, 1000000)) + + if r := <-ss.Audit().Get(a1.UserId, 0, 100); len(r.Data.(model.Audits)) != 1 { + t.Fatal("Expected 1 audit. Got ", len(r.Data.(model.Audits))) + } + + if r2 := <-ss.Audit().PermanentDeleteByUser(a1.UserId); r2.Err != nil { + t.Fatal(r2.Err) + } +} diff --git a/store/storetest/channel_store.go b/store/storetest/channel_store.go new file mode 100644 index 000000000..53d81bdc0 --- /dev/null +++ b/store/storetest/channel_store.go @@ -0,0 +1,1967 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" +) + +func TestChannelStore(t *testing.T, ss store.Store) { + t.Run("Save", func(t *testing.T) { testChannelStoreSave(t, ss) }) + t.Run("SaveDirectChannel", func(t *testing.T) { testChannelStoreSaveDirectChannel(t, ss) }) + t.Run("CreateDirectChannel", func(t *testing.T) { testChannelStoreCreateDirectChannel(t, ss) }) + t.Run("Update", func(t *testing.T) { testChannelStoreUpdate(t, ss) }) + t.Run("GetChannelUnread", func(t *testing.T) { testGetChannelUnread(t, ss) }) + t.Run("Get", func(t *testing.T) { testChannelStoreGet(t, ss) }) + t.Run("GetForPost", func(t *testing.T) { testChannelStoreGetForPost(t, ss) }) + t.Run("Restore", func(t *testing.T) { testChannelStoreRestore(t, ss) }) + t.Run("Delete", func(t *testing.T) { testChannelStoreDelete(t, ss) }) + t.Run("GetByName", func(t *testing.T) { testChannelStoreGetByName(t, ss) }) + t.Run("GetDeletedByName", func(t *testing.T) { testChannelStoreGetDeletedByName(t, ss) }) + t.Run("GetDeleted", func(t *testing.T) { testChannelStoreGetDeleted(t, ss) }) + t.Run("ChannelMemberStore", func(t *testing.T) { testChannelMemberStore(t, ss) }) + t.Run("ChannelDeleteMemberStore", func(t *testing.T) { testChannelDeleteMemberStore(t, ss) }) + t.Run("GetChannels", func(t *testing.T) { testChannelStoreGetChannels(t, ss) }) + t.Run("GetMoreChannels", func(t *testing.T) { testChannelStoreGetMoreChannels(t, ss) }) + t.Run("GetPublicChannelsForTeam", func(t *testing.T) { testChannelStoreGetPublicChannelsForTeam(t, ss) }) + t.Run("GetPublicChannelsByIdsForTeam", func(t *testing.T) { testChannelStoreGetPublicChannelsByIdsForTeam(t, ss) }) + t.Run("GetChannelCounts", func(t *testing.T) { testChannelStoreGetChannelCounts(t, ss) }) + t.Run("GetMembersForUser", func(t *testing.T) { testChannelStoreGetMembersForUser(t, ss) }) + t.Run("UpdateLastViewedAt", func(t *testing.T) { testChannelStoreUpdateLastViewedAt(t, ss) }) + t.Run("IncrementMentionCount", func(t *testing.T) { testChannelStoreIncrementMentionCount(t, ss) }) + t.Run("UpdateChannelMember", func(t *testing.T) { testUpdateChannelMember(t, ss) }) + t.Run("GetMember", func(t *testing.T) { testGetMember(t, ss) }) + t.Run("GetMemberForPost", func(t *testing.T) { testChannelStoreGetMemberForPost(t, ss) }) + t.Run("GetMemberCount", func(t *testing.T) { testGetMemberCount(t, ss) }) + t.Run("UpdateExtrasByUser", func(t *testing.T) { testUpdateExtrasByUser(t, ss) }) + t.Run("SearchMore", func(t *testing.T) { testChannelStoreSearchMore(t, ss) }) + t.Run("SearchInTeam", func(t *testing.T) { testChannelStoreSearchInTeam(t, ss) }) + t.Run("GetMembersByIds", func(t *testing.T) { testChannelStoreGetMembersByIds(t, ss) }) + t.Run("AnalyticsDeletedTypeCount", func(t *testing.T) { testChannelStoreAnalyticsDeletedTypeCount(t, ss) }) + t.Run("GetPinnedPosts", func(t *testing.T) { testChannelStoreGetPinnedPosts(t, ss) }) +} + +func testChannelStoreSave(t *testing.T, ss store.Store) { + teamId := model.NewId() + + o1 := model.Channel{} + o1.TeamId = teamId + o1.DisplayName = "Name" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_OPEN + + if err := (<-ss.Channel().Save(&o1)).Err; err != nil { + t.Fatal("couldn't save item", err) + } + + if err := (<-ss.Channel().Save(&o1)).Err; err == nil { + t.Fatal("shouldn't be able to update from save") + } + + o1.Id = "" + if err := (<-ss.Channel().Save(&o1)).Err; err == nil { + t.Fatal("should be unique name") + } + + o1.Id = "" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_DIRECT + if err := (<-ss.Channel().Save(&o1)).Err; err == nil { + t.Fatal("Should not be able to save direct channel") + } +} + +func testChannelStoreSaveDirectChannel(t *testing.T, ss store.Store) { + teamId := model.NewId() + + o1 := model.Channel{} + o1.TeamId = teamId + o1.DisplayName = "Name" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_DIRECT + + u1 := &model.User{} + u1.Email = model.NewId() + u1.Nickname = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) + + u2 := &model.User{} + u2.Email = model.NewId() + u2.Nickname = model.NewId() + store.Must(ss.User().Save(u2)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id})) + + m1 := model.ChannelMember{} + m1.ChannelId = o1.Id + m1.UserId = u1.Id + m1.NotifyProps = model.GetDefaultChannelNotifyProps() + + m2 := model.ChannelMember{} + m2.ChannelId = o1.Id + m2.UserId = u2.Id + m2.NotifyProps = model.GetDefaultChannelNotifyProps() + + if err := (<-ss.Channel().SaveDirectChannel(&o1, &m1, &m2)).Err; err != nil { + t.Fatal("couldn't save direct channel", err) + } + + members := (<-ss.Channel().GetMembers(o1.Id, 0, 100)).Data.(*model.ChannelMembers) + if len(*members) != 2 { + t.Fatal("should have saved 2 members") + } + + if err := (<-ss.Channel().SaveDirectChannel(&o1, &m1, &m2)).Err; err == nil { + t.Fatal("shouldn't be able to update from save") + } + + // Attempt to save a direct channel that already exists + o1a := model.Channel{ + TeamId: o1.TeamId, + DisplayName: o1.DisplayName, + Name: o1.Name, + Type: o1.Type, + } + + if result := <-ss.Channel().SaveDirectChannel(&o1a, &m1, &m2); result.Err == nil { + t.Fatal("should've failed to save a duplicate direct channel") + } else if result.Err.Id != store.CHANNEL_EXISTS_ERROR { + t.Fatal("should've returned CHANNEL_EXISTS_ERROR") + } else if returned := result.Data.(*model.Channel); returned.Id != o1.Id { + t.Fatal("should've returned original channel when saving a duplicate direct channel") + } + + // Attempt to save a non-direct channel + o1.Id = "" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_OPEN + if err := (<-ss.Channel().SaveDirectChannel(&o1, &m1, &m2)).Err; err == nil { + t.Fatal("Should not be able to save non-direct channel") + } +} + +func testChannelStoreCreateDirectChannel(t *testing.T, ss store.Store) { + u1 := &model.User{} + u1.Email = model.NewId() + u1.Nickname = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) + + u2 := &model.User{} + u2.Email = model.NewId() + u2.Nickname = model.NewId() + store.Must(ss.User().Save(u2)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id})) + + res := <-ss.Channel().CreateDirectChannel(u1.Id, u2.Id) + if res.Err != nil { + t.Fatal("couldn't create direct channel", res.Err) + } + + c1 := res.Data.(*model.Channel) + + members := (<-ss.Channel().GetMembers(c1.Id, 0, 100)).Data.(*model.ChannelMembers) + if len(*members) != 2 { + t.Fatal("should have saved 2 members") + } +} + +func testChannelStoreUpdate(t *testing.T, ss store.Store) { + o1 := model.Channel{} + o1.TeamId = model.NewId() + o1.DisplayName = "Name" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o1)) + + o2 := model.Channel{} + o2.TeamId = o1.TeamId + o2.DisplayName = "Name" + o2.Name = "zz" + model.NewId() + "b" + o2.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o2)) + + time.Sleep(100 * time.Millisecond) + + if err := (<-ss.Channel().Update(&o1)).Err; err != nil { + t.Fatal(err) + } + + o1.Id = "missing" + if err := (<-ss.Channel().Update(&o1)).Err; err == nil { + t.Fatal("Update should have failed because of missing key") + } + + o1.Id = model.NewId() + if err := (<-ss.Channel().Update(&o1)).Err; err == nil { + t.Fatal("Update should have faile because id change") + } + + o2.Name = o1.Name + if err := (<-ss.Channel().Update(&o2)).Err; err == nil { + t.Fatal("Update should have failed because of existing name") + } +} + +func testGetChannelUnread(t *testing.T, ss store.Store) { + teamId1 := model.NewId() + teamId2 := model.NewId() + + uid := model.NewId() + m1 := &model.TeamMember{TeamId: teamId1, UserId: uid} + m2 := &model.TeamMember{TeamId: teamId2, UserId: uid} + store.Must(ss.Team().SaveMember(m1)) + store.Must(ss.Team().SaveMember(m2)) + notifyPropsModel := model.GetDefaultChannelNotifyProps() + + // Setup Channel 1 + c1 := &model.Channel{TeamId: m1.TeamId, Name: model.NewId(), DisplayName: "Downtown", Type: model.CHANNEL_OPEN, TotalMsgCount: 100} + store.Must(ss.Channel().Save(c1)) + cm1 := &model.ChannelMember{ChannelId: c1.Id, UserId: m1.UserId, NotifyProps: notifyPropsModel, MsgCount: 90} + store.Must(ss.Channel().SaveMember(cm1)) + + // Setup Channel 2 + c2 := &model.Channel{TeamId: m2.TeamId, Name: model.NewId(), DisplayName: "Cultural", Type: model.CHANNEL_OPEN, TotalMsgCount: 100} + store.Must(ss.Channel().Save(c2)) + cm2 := &model.ChannelMember{ChannelId: c2.Id, UserId: m2.UserId, NotifyProps: notifyPropsModel, MsgCount: 90, MentionCount: 5} + store.Must(ss.Channel().SaveMember(cm2)) + + // Check for Channel 1 + if resp := <-ss.Channel().GetChannelUnread(c1.Id, uid); resp.Err != nil { + t.Fatal(resp.Err) + } else { + ch := resp.Data.(*model.ChannelUnread) + if c1.Id != ch.ChannelId { + t.Fatal("wrong channel id") + } + + if teamId1 != ch.TeamId { + t.Fatal("wrong team id for channel 1") + } + + if ch.NotifyProps == nil { + t.Fatal("wrong props for channel 1") + } + + if ch.MentionCount != 0 { + t.Fatal("wrong MentionCount for channel 1") + } + + if ch.MsgCount != 10 { + t.Fatal("wrong MsgCount for channel 1") + } + } + + // Check for Channel 2 + if resp2 := <-ss.Channel().GetChannelUnread(c2.Id, uid); resp2.Err != nil { + t.Fatal(resp2.Err) + } else { + ch2 := resp2.Data.(*model.ChannelUnread) + if c2.Id != ch2.ChannelId { + t.Fatal("wrong channel id") + } + + if teamId2 != ch2.TeamId { + t.Fatal("wrong team id") + } + + if ch2.MentionCount != 5 { + t.Fatal("wrong MentionCount for channel 2") + } + + if ch2.MsgCount != 10 { + t.Fatal("wrong MsgCount for channel 2") + } + } +} + +func testChannelStoreGet(t *testing.T, ss store.Store) { + o1 := model.Channel{} + o1.TeamId = model.NewId() + o1.DisplayName = "Name" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o1)) + + if r1 := <-ss.Channel().Get(o1.Id, false); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.Channel).ToJson() != o1.ToJson() { + t.Fatal("invalid returned channel") + } + } + + if err := (<-ss.Channel().Get("", false)).Err; err == nil { + t.Fatal("Missing id should have failed") + } + + u1 := &model.User{} + u1.Email = model.NewId() + u1.Nickname = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) + + u2 := model.User{} + u2.Email = model.NewId() + u2.Nickname = model.NewId() + store.Must(ss.User().Save(&u2)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id})) + + o2 := model.Channel{} + o2.TeamId = model.NewId() + o2.DisplayName = "Direct Name" + o2.Name = "zz" + model.NewId() + "b" + o2.Type = model.CHANNEL_DIRECT + + m1 := model.ChannelMember{} + m1.ChannelId = o2.Id + m1.UserId = u1.Id + m1.NotifyProps = model.GetDefaultChannelNotifyProps() + + m2 := model.ChannelMember{} + m2.ChannelId = o2.Id + m2.UserId = u2.Id + m2.NotifyProps = model.GetDefaultChannelNotifyProps() + + store.Must(ss.Channel().SaveDirectChannel(&o2, &m1, &m2)) + + if r2 := <-ss.Channel().Get(o2.Id, false); r2.Err != nil { + t.Fatal(r2.Err) + } else { + if r2.Data.(*model.Channel).ToJson() != o2.ToJson() { + t.Fatal("invalid returned channel") + } + } + + if r4 := <-ss.Channel().Get(o2.Id, true); r4.Err != nil { + t.Fatal(r4.Err) + } else { + if r4.Data.(*model.Channel).ToJson() != o2.ToJson() { + t.Fatal("invalid returned channel") + } + } + + if r3 := <-ss.Channel().GetAll(o1.TeamId); r3.Err != nil { + t.Fatal(r3.Err) + } else { + channels := r3.Data.([]*model.Channel) + if len(channels) == 0 { + t.Fatal("too little") + } + } + + if r3 := <-ss.Channel().GetTeamChannels(o1.TeamId); r3.Err != nil { + t.Fatal(r3.Err) + } else { + channels := r3.Data.(*model.ChannelList) + if len(*channels) == 0 { + t.Fatal("too little") + } + } +} + +func testChannelStoreGetForPost(t *testing.T, ss store.Store) { + o1 := store.Must(ss.Channel().Save(&model.Channel{ + TeamId: model.NewId(), + DisplayName: "Name", + Name: "zz" + model.NewId() + "b", + Type: model.CHANNEL_OPEN, + })).(*model.Channel) + + p1 := store.Must(ss.Post().Save(&model.Post{ + UserId: model.NewId(), + ChannelId: o1.Id, + Message: "test", + })).(*model.Post) + + if r1 := <-ss.Channel().GetForPost(p1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else if r1.Data.(*model.Channel).Id != o1.Id { + t.Fatal("incorrect channel returned") + } +} + +func testChannelStoreRestore(t *testing.T, ss store.Store) { + o1 := model.Channel{} + o1.TeamId = model.NewId() + o1.DisplayName = "Channel1" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o1)) + + if r := <-ss.Channel().Delete(o1.Id, model.GetMillis()); r.Err != nil { + t.Fatal(r.Err) + } + + if r := <-ss.Channel().Get(o1.Id, false); r.Data.(*model.Channel).DeleteAt == 0 { + t.Fatal("should have been deleted") + } + + if r := <-ss.Channel().Restore(o1.Id, model.GetMillis()); r.Err != nil { + t.Fatal(r.Err) + } + + if r := <-ss.Channel().Get(o1.Id, false); r.Data.(*model.Channel).DeleteAt != 0 { + t.Fatal("should have been restored") + } + +} + +func testChannelStoreDelete(t *testing.T, ss store.Store) { + o1 := model.Channel{} + o1.TeamId = model.NewId() + o1.DisplayName = "Channel1" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o1)) + + o2 := model.Channel{} + o2.TeamId = o1.TeamId + o2.DisplayName = "Channel2" + o2.Name = "zz" + model.NewId() + "b" + o2.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o2)) + + o3 := model.Channel{} + o3.TeamId = o1.TeamId + o3.DisplayName = "Channel3" + o3.Name = "zz" + model.NewId() + "b" + o3.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o3)) + + o4 := model.Channel{} + o4.TeamId = o1.TeamId + o4.DisplayName = "Channel4" + o4.Name = "zz" + model.NewId() + "b" + o4.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o4)) + + m1 := model.ChannelMember{} + m1.ChannelId = o1.Id + m1.UserId = model.NewId() + m1.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m1)) + + m2 := model.ChannelMember{} + m2.ChannelId = o2.Id + m2.UserId = m1.UserId + m2.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m2)) + + if r := <-ss.Channel().Delete(o1.Id, model.GetMillis()); r.Err != nil { + t.Fatal(r.Err) + } + + if r := <-ss.Channel().Get(o1.Id, false); r.Data.(*model.Channel).DeleteAt == 0 { + t.Fatal("should have been deleted") + } + + if r := <-ss.Channel().Delete(o3.Id, model.GetMillis()); r.Err != nil { + t.Fatal(r.Err) + } + + cresult := <-ss.Channel().GetChannels(o1.TeamId, m1.UserId) + list := cresult.Data.(*model.ChannelList) + + if len(*list) != 1 { + t.Fatal("invalid number of channels") + } + + cresult = <-ss.Channel().GetMoreChannels(o1.TeamId, m1.UserId, 0, 100) + list = cresult.Data.(*model.ChannelList) + + if len(*list) != 1 { + t.Fatal("invalid number of channels") + } + + <-ss.Channel().PermanentDelete(o2.Id) + + cresult = <-ss.Channel().GetChannels(o1.TeamId, m1.UserId) + t.Log(cresult.Err) + if cresult.Err.Id != "store.sql_channel.get_channels.not_found.app_error" { + t.Fatal("no channels should be found") + } + + if r := <-ss.Channel().PermanentDeleteByTeam(o1.TeamId); r.Err != nil { + t.Fatal(r.Err) + } +} + +func testChannelStoreGetByName(t *testing.T, ss store.Store) { + o1 := model.Channel{} + o1.TeamId = model.NewId() + o1.DisplayName = "Name" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o1)) + + r1 := <-ss.Channel().GetByName(o1.TeamId, o1.Name, true) + if r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.Channel).ToJson() != o1.ToJson() { + t.Fatal("invalid returned channel") + } + } + + if err := (<-ss.Channel().GetByName(o1.TeamId, "", true)).Err; err == nil { + t.Fatal("Missing id should have failed") + } + + if r1 := <-ss.Channel().GetByName(o1.TeamId, o1.Name, false); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.Channel).ToJson() != o1.ToJson() { + t.Fatal("invalid returned channel") + } + } + + if err := (<-ss.Channel().GetByName(o1.TeamId, "", false)).Err; err == nil { + t.Fatal("Missing id should have failed") + } + + store.Must(ss.Channel().Delete(r1.Data.(*model.Channel).Id, model.GetMillis())) + + if err := (<-ss.Channel().GetByName(o1.TeamId, "", false)).Err; err == nil { + t.Fatal("Deleted channel should not be returned by GetByName()") + } +} + +func testChannelStoreGetDeletedByName(t *testing.T, ss store.Store) { + o1 := model.Channel{} + o1.TeamId = model.NewId() + o1.DisplayName = "Name" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_OPEN + o1.DeleteAt = model.GetMillis() + store.Must(ss.Channel().Save(&o1)) + + if r1 := <-ss.Channel().GetDeletedByName(o1.TeamId, o1.Name); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.Channel).ToJson() != o1.ToJson() { + t.Fatal("invalid returned channel") + } + } + + if err := (<-ss.Channel().GetDeletedByName(o1.TeamId, "")).Err; err == nil { + t.Fatal("Missing id should have failed") + } +} + +func testChannelStoreGetDeleted(t *testing.T, ss store.Store) { + o1 := model.Channel{} + o1.TeamId = model.NewId() + o1.DisplayName = "Channel1" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_OPEN + o1.DeleteAt = model.GetMillis() + store.Must(ss.Channel().Save(&o1)) + + cresult := <-ss.Channel().GetDeleted(o1.TeamId, 0, 100) + if cresult.Err != nil { + t.Fatal(cresult.Err) + } + list := cresult.Data.(*model.ChannelList) + + if len(*list) != 1 { + t.Fatal("wrong list") + } + + if (*list)[0].Name != o1.Name { + t.Fatal("missing channel") + } + + o2 := model.Channel{} + o2.TeamId = o1.TeamId + o2.DisplayName = "Channel2" + o2.Name = "zz" + model.NewId() + "b" + o2.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o2)) + + cresult = <-ss.Channel().GetDeleted(o1.TeamId, 0, 100) + if cresult.Err != nil { + t.Fatal(cresult.Err) + } + list = cresult.Data.(*model.ChannelList) + + if len(*list) != 1 { + t.Fatal("wrong list") + } + + o3 := model.Channel{} + o3.TeamId = o1.TeamId + o3.DisplayName = "Channel3" + o3.Name = "zz" + model.NewId() + "b" + o3.Type = model.CHANNEL_OPEN + o3.DeleteAt = model.GetMillis() + store.Must(ss.Channel().Save(&o3)) + + cresult = <-ss.Channel().GetDeleted(o1.TeamId, 0, 100) + if cresult.Err != nil { + t.Fatal(cresult.Err) + } + list = cresult.Data.(*model.ChannelList) + + if len(*list) != 2 { + t.Fatal("wrong list length") + } + + cresult = <-ss.Channel().GetDeleted(o1.TeamId, 0, 1) + if cresult.Err != nil { + t.Fatal(cresult.Err) + } + list = cresult.Data.(*model.ChannelList) + + if len(*list) != 1 { + t.Fatal("wrong list length") + } + + cresult = <-ss.Channel().GetDeleted(o1.TeamId, 1, 1) + if cresult.Err != nil { + t.Fatal(cresult.Err) + } + list = cresult.Data.(*model.ChannelList) + + if len(*list) != 1 { + t.Fatal("wrong list length") + } + +} + +func testChannelMemberStore(t *testing.T, ss store.Store) { + c1 := model.Channel{} + c1.TeamId = model.NewId() + c1.DisplayName = "NameName" + c1.Name = "zz" + model.NewId() + "b" + c1.Type = model.CHANNEL_OPEN + c1 = *store.Must(ss.Channel().Save(&c1)).(*model.Channel) + + c1t1 := (<-ss.Channel().Get(c1.Id, false)).Data.(*model.Channel) + t1 := c1t1.ExtraUpdateAt + + u1 := model.User{} + u1.Email = model.NewId() + u1.Nickname = model.NewId() + store.Must(ss.User().Save(&u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) + + u2 := model.User{} + u2.Email = model.NewId() + u2.Nickname = model.NewId() + store.Must(ss.User().Save(&u2)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id})) + + o1 := model.ChannelMember{} + o1.ChannelId = c1.Id + o1.UserId = u1.Id + o1.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&o1)) + + o2 := model.ChannelMember{} + o2.ChannelId = c1.Id + o2.UserId = u2.Id + o2.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&o2)) + + c1t2 := (<-ss.Channel().Get(c1.Id, false)).Data.(*model.Channel) + t2 := c1t2.ExtraUpdateAt + + if t2 <= t1 { + t.Fatal("Member update time incorrect") + } + + count := (<-ss.Channel().GetMemberCount(o1.ChannelId, true)).Data.(int64) + if count != 2 { + t.Fatal("should have saved 2 members") + } + + count = (<-ss.Channel().GetMemberCount(o1.ChannelId, true)).Data.(int64) + if count != 2 { + t.Fatal("should have saved 2 members") + } + + if ss.Channel().GetMemberCountFromCache(o1.ChannelId) != 2 { + t.Fatal("should have saved 2 members") + } + + if ss.Channel().GetMemberCountFromCache("junk") != 0 { + t.Fatal("should have saved 0 members") + } + + count = (<-ss.Channel().GetMemberCount(o1.ChannelId, false)).Data.(int64) + if count != 2 { + t.Fatal("should have saved 2 members") + } + + store.Must(ss.Channel().RemoveMember(o2.ChannelId, o2.UserId)) + + count = (<-ss.Channel().GetMemberCount(o1.ChannelId, false)).Data.(int64) + if count != 1 { + t.Fatal("should have removed 1 member") + } + + c1t3 := (<-ss.Channel().Get(c1.Id, false)).Data.(*model.Channel) + t3 := c1t3.ExtraUpdateAt + + if t3 <= t2 || t3 <= t1 { + t.Fatal("Member update time incorrect on delete") + } + + member := (<-ss.Channel().GetMember(o1.ChannelId, o1.UserId)).Data.(*model.ChannelMember) + if member.ChannelId != o1.ChannelId { + t.Fatal("should have go member") + } + + if err := (<-ss.Channel().SaveMember(&o1)).Err; err == nil { + t.Fatal("Should have been a duplicate") + } + + c1t4 := (<-ss.Channel().Get(c1.Id, false)).Data.(*model.Channel) + t4 := c1t4.ExtraUpdateAt + if t4 != t3 { + t.Fatal("Should not update time upon failure") + } +} + +func testChannelDeleteMemberStore(t *testing.T, ss store.Store) { + c1 := model.Channel{} + c1.TeamId = model.NewId() + c1.DisplayName = "NameName" + c1.Name = "zz" + model.NewId() + "b" + c1.Type = model.CHANNEL_OPEN + c1 = *store.Must(ss.Channel().Save(&c1)).(*model.Channel) + + c1t1 := (<-ss.Channel().Get(c1.Id, false)).Data.(*model.Channel) + t1 := c1t1.ExtraUpdateAt + + u1 := model.User{} + u1.Email = model.NewId() + u1.Nickname = model.NewId() + store.Must(ss.User().Save(&u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) + + u2 := model.User{} + u2.Email = model.NewId() + u2.Nickname = model.NewId() + store.Must(ss.User().Save(&u2)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id})) + + o1 := model.ChannelMember{} + o1.ChannelId = c1.Id + o1.UserId = u1.Id + o1.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&o1)) + + o2 := model.ChannelMember{} + o2.ChannelId = c1.Id + o2.UserId = u2.Id + o2.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&o2)) + + c1t2 := (<-ss.Channel().Get(c1.Id, false)).Data.(*model.Channel) + t2 := c1t2.ExtraUpdateAt + + if t2 <= t1 { + t.Fatal("Member update time incorrect") + } + + count := (<-ss.Channel().GetMemberCount(o1.ChannelId, false)).Data.(int64) + if count != 2 { + t.Fatal("should have saved 2 members") + } + + store.Must(ss.Channel().PermanentDeleteMembersByUser(o2.UserId)) + + count = (<-ss.Channel().GetMemberCount(o1.ChannelId, false)).Data.(int64) + if count != 1 { + t.Fatal("should have removed 1 member") + } + + if r1 := <-ss.Channel().PermanentDeleteMembersByChannel(o1.ChannelId); r1.Err != nil { + t.Fatal(r1.Err) + } + + count = (<-ss.Channel().GetMemberCount(o1.ChannelId, false)).Data.(int64) + if count != 0 { + t.Fatal("should have removed all members") + } +} + +func testChannelStoreGetChannels(t *testing.T, ss store.Store) { + o2 := model.Channel{} + o2.TeamId = model.NewId() + o2.DisplayName = "Channel2" + o2.Name = "zz" + model.NewId() + "b" + o2.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o2)) + + o1 := model.Channel{} + o1.TeamId = model.NewId() + o1.DisplayName = "Channel1" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o1)) + + m1 := model.ChannelMember{} + m1.ChannelId = o1.Id + m1.UserId = model.NewId() + m1.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m1)) + + m2 := model.ChannelMember{} + m2.ChannelId = o1.Id + m2.UserId = model.NewId() + m2.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m2)) + + m3 := model.ChannelMember{} + m3.ChannelId = o2.Id + m3.UserId = model.NewId() + m3.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m3)) + + cresult := <-ss.Channel().GetChannels(o1.TeamId, m1.UserId) + list := cresult.Data.(*model.ChannelList) + + if (*list)[0].Id != o1.Id { + t.Fatal("missing channel") + } + + acresult := <-ss.Channel().GetAllChannelMembersForUser(m1.UserId, false) + ids := acresult.Data.(map[string]string) + if _, ok := ids[o1.Id]; !ok { + t.Fatal("missing channel") + } + + acresult2 := <-ss.Channel().GetAllChannelMembersForUser(m1.UserId, true) + ids2 := acresult2.Data.(map[string]string) + if _, ok := ids2[o1.Id]; !ok { + t.Fatal("missing channel") + } + + acresult3 := <-ss.Channel().GetAllChannelMembersForUser(m1.UserId, true) + ids3 := acresult3.Data.(map[string]string) + if _, ok := ids3[o1.Id]; !ok { + t.Fatal("missing channel") + } + + if !ss.Channel().IsUserInChannelUseCache(m1.UserId, o1.Id) { + t.Fatal("missing channel") + } + + if ss.Channel().IsUserInChannelUseCache(m1.UserId, o2.Id) { + t.Fatal("missing channel") + } + + if ss.Channel().IsUserInChannelUseCache(m1.UserId, "blahblah") { + t.Fatal("missing channel") + } + + if ss.Channel().IsUserInChannelUseCache("blahblah", "blahblah") { + t.Fatal("missing channel") + } + + ss.Channel().InvalidateAllChannelMembersForUser(m1.UserId) +} + +func testChannelStoreGetMoreChannels(t *testing.T, ss store.Store) { + o1 := model.Channel{} + o1.TeamId = model.NewId() + o1.DisplayName = "Channel1" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o1)) + + o2 := model.Channel{} + o2.TeamId = model.NewId() + o2.DisplayName = "Channel2" + o2.Name = "zz" + model.NewId() + "b" + o2.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o2)) + + m1 := model.ChannelMember{} + m1.ChannelId = o1.Id + m1.UserId = model.NewId() + m1.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m1)) + + m2 := model.ChannelMember{} + m2.ChannelId = o1.Id + m2.UserId = model.NewId() + m2.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m2)) + + m3 := model.ChannelMember{} + m3.ChannelId = o2.Id + m3.UserId = model.NewId() + m3.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m3)) + + o3 := model.Channel{} + o3.TeamId = o1.TeamId + o3.DisplayName = "ChannelA" + o3.Name = "zz" + model.NewId() + "b" + o3.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o3)) + + o4 := model.Channel{} + o4.TeamId = o1.TeamId + o4.DisplayName = "ChannelB" + o4.Name = "zz" + model.NewId() + "b" + o4.Type = model.CHANNEL_PRIVATE + store.Must(ss.Channel().Save(&o4)) + + o5 := model.Channel{} + o5.TeamId = o1.TeamId + o5.DisplayName = "ChannelC" + o5.Name = "zz" + model.NewId() + "b" + o5.Type = model.CHANNEL_PRIVATE + store.Must(ss.Channel().Save(&o5)) + + cresult := <-ss.Channel().GetMoreChannels(o1.TeamId, m1.UserId, 0, 100) + if cresult.Err != nil { + t.Fatal(cresult.Err) + } + list := cresult.Data.(*model.ChannelList) + + if len(*list) != 1 { + t.Fatal("wrong list") + } + + if (*list)[0].Name != o3.Name { + t.Fatal("missing channel") + } + + o6 := model.Channel{} + o6.TeamId = o1.TeamId + o6.DisplayName = "ChannelA" + o6.Name = "zz" + model.NewId() + "b" + o6.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o6)) + + cresult = <-ss.Channel().GetMoreChannels(o1.TeamId, m1.UserId, 0, 100) + list = cresult.Data.(*model.ChannelList) + + if len(*list) != 2 { + t.Fatal("wrong list length") + } + + cresult = <-ss.Channel().GetMoreChannels(o1.TeamId, m1.UserId, 0, 1) + list = cresult.Data.(*model.ChannelList) + + if len(*list) != 1 { + t.Fatal("wrong list length") + } + + cresult = <-ss.Channel().GetMoreChannels(o1.TeamId, m1.UserId, 1, 1) + list = cresult.Data.(*model.ChannelList) + + if len(*list) != 1 { + t.Fatal("wrong list length") + } + + if r1 := <-ss.Channel().AnalyticsTypeCount(o1.TeamId, model.CHANNEL_OPEN); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(int64) != 3 { + t.Log(r1.Data) + t.Fatal("wrong value") + } + } + + if r1 := <-ss.Channel().AnalyticsTypeCount(o1.TeamId, model.CHANNEL_PRIVATE); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(int64) != 2 { + t.Log(r1.Data) + t.Fatal("wrong value") + } + } +} + +func testChannelStoreGetPublicChannelsForTeam(t *testing.T, ss store.Store) { + o1 := model.Channel{} + o1.TeamId = model.NewId() + o1.DisplayName = "OpenChannel1Team1" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o1)) + + o2 := model.Channel{} + o2.TeamId = model.NewId() + o2.DisplayName = "OpenChannel1Team2" + o2.Name = "zz" + model.NewId() + "b" + o2.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o2)) + + o3 := model.Channel{} + o3.TeamId = o1.TeamId + o3.DisplayName = "PrivateChannel1Team1" + o3.Name = "zz" + model.NewId() + "b" + o3.Type = model.CHANNEL_PRIVATE + store.Must(ss.Channel().Save(&o3)) + + cresult := <-ss.Channel().GetPublicChannelsForTeam(o1.TeamId, 0, 100) + if cresult.Err != nil { + t.Fatal(cresult.Err) + } + list := cresult.Data.(*model.ChannelList) + + if len(*list) != 1 { + t.Fatal("wrong list") + } + + if (*list)[0].Name != o1.Name { + t.Fatal("missing channel") + } + + o4 := model.Channel{} + o4.TeamId = o1.TeamId + o4.DisplayName = "OpenChannel2Team1" + o4.Name = "zz" + model.NewId() + "b" + o4.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o4)) + + cresult = <-ss.Channel().GetPublicChannelsForTeam(o1.TeamId, 0, 100) + list = cresult.Data.(*model.ChannelList) + + if len(*list) != 2 { + t.Fatal("wrong list length") + } + + cresult = <-ss.Channel().GetPublicChannelsForTeam(o1.TeamId, 0, 1) + list = cresult.Data.(*model.ChannelList) + + if len(*list) != 1 { + t.Fatal("wrong list length") + } + + cresult = <-ss.Channel().GetPublicChannelsForTeam(o1.TeamId, 1, 1) + list = cresult.Data.(*model.ChannelList) + + if len(*list) != 1 { + t.Fatal("wrong list length") + } + + if r1 := <-ss.Channel().AnalyticsTypeCount(o1.TeamId, model.CHANNEL_OPEN); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(int64) != 2 { + t.Log(r1.Data) + t.Fatal("wrong value") + } + } + + if r1 := <-ss.Channel().AnalyticsTypeCount(o1.TeamId, model.CHANNEL_PRIVATE); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(int64) != 1 { + t.Log(r1.Data) + t.Fatal("wrong value") + } + } +} + +func testChannelStoreGetPublicChannelsByIdsForTeam(t *testing.T, ss store.Store) { + teamId1 := model.NewId() + + oc1 := model.Channel{} + oc1.TeamId = teamId1 + oc1.DisplayName = "OpenChannel1Team1" + oc1.Name = "zz" + model.NewId() + "b" + oc1.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&oc1)) + + oc2 := model.Channel{} + oc2.TeamId = model.NewId() + oc2.DisplayName = "OpenChannel2TeamOther" + oc2.Name = "zz" + model.NewId() + "b" + oc2.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&oc2)) + + pc3 := model.Channel{} + pc3.TeamId = teamId1 + pc3.DisplayName = "PrivateChannel3Team1" + pc3.Name = "zz" + model.NewId() + "b" + pc3.Type = model.CHANNEL_PRIVATE + store.Must(ss.Channel().Save(&pc3)) + + cids := []string{oc1.Id} + cresult := <-ss.Channel().GetPublicChannelsByIdsForTeam(teamId1, cids) + list := cresult.Data.(*model.ChannelList) + + if len(*list) != 1 { + t.Fatal("should return 1 channel") + } + + if (*list)[0].Id != oc1.Id { + t.Fatal("missing channel") + } + + cids = append(cids, oc2.Id) + cids = append(cids, model.NewId()) + cids = append(cids, pc3.Id) + cresult = <-ss.Channel().GetPublicChannelsByIdsForTeam(teamId1, cids) + list = cresult.Data.(*model.ChannelList) + + if len(*list) != 1 { + t.Fatal("should return 1 channel") + } + + oc4 := model.Channel{} + oc4.TeamId = teamId1 + oc4.DisplayName = "OpenChannel4Team1" + oc4.Name = "zz" + model.NewId() + "b" + oc4.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&oc4)) + + cids = append(cids, oc4.Id) + cresult = <-ss.Channel().GetPublicChannelsByIdsForTeam(teamId1, cids) + list = cresult.Data.(*model.ChannelList) + + if len(*list) != 2 { + t.Fatal("should return 2 channels") + } + + if (*list)[0].Id != oc1.Id { + t.Fatal("missing channel") + } + + if (*list)[1].Id != oc4.Id { + t.Fatal("missing channel") + } + + cids = cids[:0] + cids = append(cids, model.NewId()) + cresult = <-ss.Channel().GetPublicChannelsByIdsForTeam(teamId1, cids) + list = cresult.Data.(*model.ChannelList) + + if len(*list) != 0 { + t.Fatal("should not return a channel") + } +} + +func testChannelStoreGetChannelCounts(t *testing.T, ss store.Store) { + o2 := model.Channel{} + o2.TeamId = model.NewId() + o2.DisplayName = "Channel2" + o2.Name = "zz" + model.NewId() + "b" + o2.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o2)) + + o1 := model.Channel{} + o1.TeamId = model.NewId() + o1.DisplayName = "Channel1" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o1)) + + m1 := model.ChannelMember{} + m1.ChannelId = o1.Id + m1.UserId = model.NewId() + m1.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m1)) + + m2 := model.ChannelMember{} + m2.ChannelId = o1.Id + m2.UserId = model.NewId() + m2.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m2)) + + m3 := model.ChannelMember{} + m3.ChannelId = o2.Id + m3.UserId = model.NewId() + m3.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m3)) + + cresult := <-ss.Channel().GetChannelCounts(o1.TeamId, m1.UserId) + counts := cresult.Data.(*model.ChannelCounts) + + if len(counts.Counts) != 1 { + t.Fatal("wrong number of counts") + } + + if len(counts.UpdateTimes) != 1 { + t.Fatal("wrong number of update times") + } +} + +func testChannelStoreGetMembersForUser(t *testing.T, ss store.Store) { + t1 := model.Team{} + t1.DisplayName = "Name" + t1.Name = model.NewId() + t1.Email = model.NewId() + "@nowhere.com" + t1.Type = model.TEAM_OPEN + store.Must(ss.Team().Save(&t1)) + + o1 := model.Channel{} + o1.TeamId = t1.Id + o1.DisplayName = "Channel1" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o1)) + + o2 := model.Channel{} + o2.TeamId = o1.TeamId + o2.DisplayName = "Channel2" + o2.Name = "zz" + model.NewId() + "b" + o2.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o2)) + + m1 := model.ChannelMember{} + m1.ChannelId = o1.Id + m1.UserId = model.NewId() + m1.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m1)) + + m2 := model.ChannelMember{} + m2.ChannelId = o2.Id + m2.UserId = m1.UserId + m2.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m2)) + + cresult := <-ss.Channel().GetMembersForUser(o1.TeamId, m1.UserId) + members := cresult.Data.(*model.ChannelMembers) + + // no unread messages + if len(*members) != 2 { + t.Fatal("wrong number of members") + } +} + +func testChannelStoreUpdateLastViewedAt(t *testing.T, ss store.Store) { + o1 := model.Channel{} + o1.TeamId = model.NewId() + o1.DisplayName = "Channel1" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_OPEN + o1.TotalMsgCount = 25 + o1.LastPostAt = 12345 + store.Must(ss.Channel().Save(&o1)) + + m1 := model.ChannelMember{} + m1.ChannelId = o1.Id + m1.UserId = model.NewId() + m1.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m1)) + + o2 := model.Channel{} + o2.TeamId = model.NewId() + o2.DisplayName = "Channel1" + o2.Name = "zz" + model.NewId() + "c" + o2.Type = model.CHANNEL_OPEN + o2.TotalMsgCount = 26 + o2.LastPostAt = 123456 + store.Must(ss.Channel().Save(&o2)) + + m2 := model.ChannelMember{} + m2.ChannelId = o2.Id + m2.UserId = m1.UserId + m2.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m2)) + + if result := <-ss.Channel().UpdateLastViewedAt([]string{m1.ChannelId}, m1.UserId); result.Err != nil { + t.Fatal("failed to update", result.Err) + } else if result.Data.(map[string]int64)[o1.Id] != o1.LastPostAt { + t.Fatal("last viewed at time incorrect") + } + + if result := <-ss.Channel().UpdateLastViewedAt([]string{m1.ChannelId, m2.ChannelId}, m1.UserId); result.Err != nil { + t.Fatal("failed to update", result.Err) + } else if result.Data.(map[string]int64)[o2.Id] != o2.LastPostAt { + t.Fatal("last viewed at time incorrect") + } + + rm1 := store.Must(ss.Channel().GetMember(m1.ChannelId, m1.UserId)).(*model.ChannelMember) + assert.Equal(t, rm1.LastViewedAt, o1.LastPostAt) + assert.Equal(t, rm1.LastUpdateAt, o1.LastPostAt) + assert.Equal(t, rm1.MsgCount, o1.TotalMsgCount) + + rm2 := store.Must(ss.Channel().GetMember(m2.ChannelId, m2.UserId)).(*model.ChannelMember) + assert.Equal(t, rm2.LastViewedAt, o2.LastPostAt) + assert.Equal(t, rm2.LastUpdateAt, o2.LastPostAt) + assert.Equal(t, rm2.MsgCount, o2.TotalMsgCount) + + if result := <-ss.Channel().UpdateLastViewedAt([]string{m1.ChannelId}, "missing id"); result.Err != nil { + t.Fatal("failed to update") + } +} + +func testChannelStoreIncrementMentionCount(t *testing.T, ss store.Store) { + o1 := model.Channel{} + o1.TeamId = model.NewId() + o1.DisplayName = "Channel1" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_OPEN + o1.TotalMsgCount = 25 + store.Must(ss.Channel().Save(&o1)) + + m1 := model.ChannelMember{} + m1.ChannelId = o1.Id + m1.UserId = model.NewId() + m1.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m1)) + + err := (<-ss.Channel().IncrementMentionCount(m1.ChannelId, m1.UserId)).Err + if err != nil { + t.Fatal("failed to update") + } + + err = (<-ss.Channel().IncrementMentionCount(m1.ChannelId, "missing id")).Err + if err != nil { + t.Fatal("failed to update") + } + + err = (<-ss.Channel().IncrementMentionCount("missing id", m1.UserId)).Err + if err != nil { + t.Fatal("failed to update") + } + + err = (<-ss.Channel().IncrementMentionCount("missing id", "missing id")).Err + if err != nil { + t.Fatal("failed to update") + } +} + +func testUpdateChannelMember(t *testing.T, ss store.Store) { + userId := model.NewId() + + c1 := &model.Channel{ + TeamId: model.NewId(), + DisplayName: model.NewId(), + Name: model.NewId(), + Type: model.CHANNEL_OPEN, + } + store.Must(ss.Channel().Save(c1)) + + m1 := &model.ChannelMember{ + ChannelId: c1.Id, + UserId: userId, + NotifyProps: model.GetDefaultChannelNotifyProps(), + } + store.Must(ss.Channel().SaveMember(m1)) + + m1.NotifyProps["test"] = "sometext" + if result := <-ss.Channel().UpdateMember(m1); result.Err != nil { + t.Fatal(result.Err) + } + + m1.UserId = "" + if result := <-ss.Channel().UpdateMember(m1); result.Err == nil { + t.Fatal("bad user id - should fail") + } +} + +func testGetMember(t *testing.T, ss store.Store) { + userId := model.NewId() + + c1 := &model.Channel{ + TeamId: model.NewId(), + DisplayName: model.NewId(), + Name: model.NewId(), + Type: model.CHANNEL_OPEN, + } + store.Must(ss.Channel().Save(c1)) + + c2 := &model.Channel{ + TeamId: c1.TeamId, + DisplayName: model.NewId(), + Name: model.NewId(), + Type: model.CHANNEL_OPEN, + } + store.Must(ss.Channel().Save(c2)) + + m1 := &model.ChannelMember{ + ChannelId: c1.Id, + UserId: userId, + NotifyProps: model.GetDefaultChannelNotifyProps(), + } + store.Must(ss.Channel().SaveMember(m1)) + + m2 := &model.ChannelMember{ + ChannelId: c2.Id, + UserId: userId, + NotifyProps: model.GetDefaultChannelNotifyProps(), + } + store.Must(ss.Channel().SaveMember(m2)) + + if result := <-ss.Channel().GetMember(model.NewId(), userId); result.Err == nil { + t.Fatal("should've failed to get member for non-existant channel") + } + + if result := <-ss.Channel().GetMember(c1.Id, model.NewId()); result.Err == nil { + t.Fatal("should've failed to get member for non-existant user") + } + + if result := <-ss.Channel().GetMember(c1.Id, userId); result.Err != nil { + t.Fatal("shouldn't have errored when getting member", result.Err) + } else if member := result.Data.(*model.ChannelMember); member.ChannelId != c1.Id { + t.Fatal("should've gotten member of channel 1") + } else if member.UserId != userId { + t.Fatal("should've gotten member for user") + } + + if result := <-ss.Channel().GetMember(c2.Id, userId); result.Err != nil { + t.Fatal("shouldn't have errored when getting member", result.Err) + } else if member := result.Data.(*model.ChannelMember); member.ChannelId != c2.Id { + t.Fatal("should've gotten member of channel 2") + } else if member.UserId != userId { + t.Fatal("should've gotten member for user") + } + + if result := <-ss.Channel().GetAllChannelMembersNotifyPropsForChannel(c2.Id, false); result.Err != nil { + t.Fatal(result.Err) + } else { + props := result.Data.(map[string]model.StringMap) + if len(props) == 0 { + t.Fatal("should not be empty") + } + } + + if result := <-ss.Channel().GetAllChannelMembersNotifyPropsForChannel(c2.Id, true); result.Err != nil { + t.Fatal(result.Err) + } else { + props := result.Data.(map[string]model.StringMap) + if len(props) == 0 { + t.Fatal("should not be empty") + } + } + + ss.Channel().InvalidateCacheForChannelMembersNotifyProps(c2.Id) +} + +func testChannelStoreGetMemberForPost(t *testing.T, ss store.Store) { + o1 := store.Must(ss.Channel().Save(&model.Channel{ + TeamId: model.NewId(), + DisplayName: "Name", + Name: "zz" + model.NewId() + "b", + Type: model.CHANNEL_OPEN, + })).(*model.Channel) + + m1 := store.Must(ss.Channel().SaveMember(&model.ChannelMember{ + ChannelId: o1.Id, + UserId: model.NewId(), + NotifyProps: model.GetDefaultChannelNotifyProps(), + })).(*model.ChannelMember) + + p1 := store.Must(ss.Post().Save(&model.Post{ + UserId: model.NewId(), + ChannelId: o1.Id, + Message: "test", + })).(*model.Post) + + if r1 := <-ss.Channel().GetMemberForPost(p1.Id, m1.UserId); r1.Err != nil { + t.Fatal(r1.Err) + } else if r1.Data.(*model.ChannelMember).ToJson() != m1.ToJson() { + t.Fatal("invalid returned channel member") + } + + if r2 := <-ss.Channel().GetMemberForPost(p1.Id, model.NewId()); r2.Err == nil { + t.Fatal("shouldn't have returned a member") + } +} + +func testGetMemberCount(t *testing.T, ss store.Store) { + teamId := model.NewId() + + c1 := model.Channel{ + TeamId: teamId, + DisplayName: "Channel1", + Name: "zz" + model.NewId() + "b", + Type: model.CHANNEL_OPEN, + } + store.Must(ss.Channel().Save(&c1)) + + c2 := model.Channel{ + TeamId: teamId, + DisplayName: "Channel2", + Name: "zz" + model.NewId() + "b", + Type: model.CHANNEL_OPEN, + } + store.Must(ss.Channel().Save(&c2)) + + u1 := &model.User{ + Email: model.NewId(), + DeleteAt: 0, + } + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) + + m1 := model.ChannelMember{ + ChannelId: c1.Id, + UserId: u1.Id, + NotifyProps: model.GetDefaultChannelNotifyProps(), + } + store.Must(ss.Channel().SaveMember(&m1)) + + if result := <-ss.Channel().GetMemberCount(c1.Id, false); result.Err != nil { + t.Fatalf("failed to get member count: %v", result.Err) + } else if result.Data.(int64) != 1 { + t.Fatalf("got incorrect member count %v", result.Data) + } + + u2 := model.User{ + Email: model.NewId(), + DeleteAt: 0, + } + store.Must(ss.User().Save(&u2)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id})) + + m2 := model.ChannelMember{ + ChannelId: c1.Id, + UserId: u2.Id, + NotifyProps: model.GetDefaultChannelNotifyProps(), + } + store.Must(ss.Channel().SaveMember(&m2)) + + if result := <-ss.Channel().GetMemberCount(c1.Id, false); result.Err != nil { + t.Fatalf("failed to get member count: %v", result.Err) + } else if result.Data.(int64) != 2 { + t.Fatalf("got incorrect member count %v", result.Data) + } + + // make sure members of other channels aren't counted + u3 := model.User{ + Email: model.NewId(), + DeleteAt: 0, + } + store.Must(ss.User().Save(&u3)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u3.Id})) + + m3 := model.ChannelMember{ + ChannelId: c2.Id, + UserId: u3.Id, + NotifyProps: model.GetDefaultChannelNotifyProps(), + } + store.Must(ss.Channel().SaveMember(&m3)) + + if result := <-ss.Channel().GetMemberCount(c1.Id, false); result.Err != nil { + t.Fatalf("failed to get member count: %v", result.Err) + } else if result.Data.(int64) != 2 { + t.Fatalf("got incorrect member count %v", result.Data) + } + + // make sure inactive users aren't counted + u4 := &model.User{ + Email: model.NewId(), + DeleteAt: 10000, + } + store.Must(ss.User().Save(u4)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u4.Id})) + + m4 := model.ChannelMember{ + ChannelId: c1.Id, + UserId: u4.Id, + NotifyProps: model.GetDefaultChannelNotifyProps(), + } + store.Must(ss.Channel().SaveMember(&m4)) + + if result := <-ss.Channel().GetMemberCount(c1.Id, false); result.Err != nil { + t.Fatalf("failed to get member count: %v", result.Err) + } else if result.Data.(int64) != 2 { + t.Fatalf("got incorrect member count %v", result.Data) + } +} + +func testUpdateExtrasByUser(t *testing.T, ss store.Store) { + teamId := model.NewId() + + c1 := model.Channel{ + TeamId: teamId, + DisplayName: "Channel1", + Name: "zz" + model.NewId() + "b", + Type: model.CHANNEL_OPEN, + } + store.Must(ss.Channel().Save(&c1)) + + c2 := model.Channel{ + TeamId: teamId, + DisplayName: "Channel2", + Name: "zz" + model.NewId() + "b", + Type: model.CHANNEL_OPEN, + } + store.Must(ss.Channel().Save(&c2)) + + u1 := &model.User{ + Email: model.NewId(), + DeleteAt: 0, + } + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) + + m1 := model.ChannelMember{ + ChannelId: c1.Id, + UserId: u1.Id, + NotifyProps: model.GetDefaultChannelNotifyProps(), + } + store.Must(ss.Channel().SaveMember(&m1)) + + u1.DeleteAt = model.GetMillis() + store.Must(ss.User().Update(u1, true)) + + if result := <-ss.Channel().ExtraUpdateByUser(u1.Id, u1.DeleteAt); result.Err != nil { + t.Fatalf("failed to update extras by user: %v", result.Err) + } + + u1.DeleteAt = 0 + store.Must(ss.User().Update(u1, true)) + + if result := <-ss.Channel().ExtraUpdateByUser(u1.Id, u1.DeleteAt); result.Err != nil { + t.Fatalf("failed to update extras by user: %v", result.Err) + } +} + +func testChannelStoreSearchMore(t *testing.T, ss store.Store) { + o1 := model.Channel{} + o1.TeamId = model.NewId() + o1.DisplayName = "ChannelA" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o1)) + + o2 := model.Channel{} + o2.TeamId = model.NewId() + o2.DisplayName = "Channel2" + o2.Name = "zz" + model.NewId() + "b" + o2.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o2)) + + m1 := model.ChannelMember{} + m1.ChannelId = o1.Id + m1.UserId = model.NewId() + m1.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m1)) + + m2 := model.ChannelMember{} + m2.ChannelId = o1.Id + m2.UserId = model.NewId() + m2.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m2)) + + m3 := model.ChannelMember{} + m3.ChannelId = o2.Id + m3.UserId = model.NewId() + m3.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m3)) + + o3 := model.Channel{} + o3.TeamId = o1.TeamId + o3.DisplayName = "ChannelA" + o3.Name = "zz" + model.NewId() + "b" + o3.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o3)) + + o4 := model.Channel{} + o4.TeamId = o1.TeamId + o4.DisplayName = "ChannelB" + o4.Name = "zz" + model.NewId() + "b" + o4.Type = model.CHANNEL_PRIVATE + store.Must(ss.Channel().Save(&o4)) + + o5 := model.Channel{} + o5.TeamId = o1.TeamId + o5.DisplayName = "ChannelC" + o5.Name = "zz" + model.NewId() + "b" + o5.Type = model.CHANNEL_PRIVATE + store.Must(ss.Channel().Save(&o5)) + + if result := <-ss.Channel().SearchMore(m1.UserId, o1.TeamId, "ChannelA"); result.Err != nil { + t.Fatal(result.Err) + } else { + channels := result.Data.(*model.ChannelList) + if len(*channels) == 0 { + t.Fatal("should not be empty") + } + + if (*channels)[0].Name != o3.Name { + t.Fatal("wrong channel returned") + } + } + + if result := <-ss.Channel().SearchMore(m1.UserId, o1.TeamId, o4.Name); result.Err != nil { + t.Fatal(result.Err) + } else { + channels := result.Data.(*model.ChannelList) + if len(*channels) != 0 { + t.Fatal("should be empty") + } + } + + if result := <-ss.Channel().SearchMore(m1.UserId, o1.TeamId, o3.Name); result.Err != nil { + t.Fatal(result.Err) + } else { + channels := result.Data.(*model.ChannelList) + if len(*channels) == 0 { + t.Fatal("should not be empty") + } + + if (*channels)[0].Name != o3.Name { + t.Fatal("wrong channel returned") + } + } + +} + +func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) { + o1 := model.Channel{} + o1.TeamId = model.NewId() + o1.DisplayName = "ChannelA" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o1)) + + o2 := model.Channel{} + o2.TeamId = model.NewId() + o2.DisplayName = "Channel2" + o2.Name = "zz" + model.NewId() + "b" + o2.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o2)) + + m1 := model.ChannelMember{} + m1.ChannelId = o1.Id + m1.UserId = model.NewId() + m1.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m1)) + + m2 := model.ChannelMember{} + m2.ChannelId = o1.Id + m2.UserId = model.NewId() + m2.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m2)) + + m3 := model.ChannelMember{} + m3.ChannelId = o2.Id + m3.UserId = model.NewId() + m3.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m3)) + + o3 := model.Channel{} + o3.TeamId = o1.TeamId + o3.DisplayName = "ChannelA" + o3.Name = "zz" + model.NewId() + "b" + o3.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o3)) + + o4 := model.Channel{} + o4.TeamId = o1.TeamId + o4.DisplayName = "ChannelB" + o4.Name = "zz" + model.NewId() + "b" + o4.Type = model.CHANNEL_PRIVATE + store.Must(ss.Channel().Save(&o4)) + + o5 := model.Channel{} + o5.TeamId = o1.TeamId + o5.DisplayName = "ChannelC" + o5.Name = "zz" + model.NewId() + "b" + o5.Type = model.CHANNEL_PRIVATE + store.Must(ss.Channel().Save(&o5)) + + if result := <-ss.Channel().SearchInTeam(o1.TeamId, "ChannelA"); result.Err != nil { + t.Fatal(result.Err) + } else { + channels := result.Data.(*model.ChannelList) + if len(*channels) != 2 { + t.Fatal("wrong length") + } + } + + if result := <-ss.Channel().SearchInTeam(o1.TeamId, ""); result.Err != nil { + t.Fatal(result.Err) + } else { + channels := result.Data.(*model.ChannelList) + if len(*channels) == 0 { + t.Fatal("should not be empty") + } + } + + if result := <-ss.Channel().SearchInTeam(o1.TeamId, "blargh"); result.Err != nil { + t.Fatal(result.Err) + } else { + channels := result.Data.(*model.ChannelList) + if len(*channels) != 0 { + t.Fatal("should be empty") + } + } +} + +func testChannelStoreGetMembersByIds(t *testing.T, ss store.Store) { + o1 := model.Channel{} + o1.TeamId = model.NewId() + o1.DisplayName = "ChannelA" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o1)) + + m1 := &model.ChannelMember{ChannelId: o1.Id, UserId: model.NewId(), NotifyProps: model.GetDefaultChannelNotifyProps()} + store.Must(ss.Channel().SaveMember(m1)) + + if r := <-ss.Channel().GetMembersByIds(m1.ChannelId, []string{m1.UserId}); r.Err != nil { + t.Fatal(r.Err) + } else { + rm1 := (*r.Data.(*model.ChannelMembers))[0] + + if rm1.ChannelId != m1.ChannelId { + t.Fatal("bad team id") + } + + if rm1.UserId != m1.UserId { + t.Fatal("bad user id") + } + } + + m2 := &model.ChannelMember{ChannelId: o1.Id, UserId: model.NewId(), NotifyProps: model.GetDefaultChannelNotifyProps()} + store.Must(ss.Channel().SaveMember(m2)) + + if r := <-ss.Channel().GetMembersByIds(m1.ChannelId, []string{m1.UserId, m2.UserId, model.NewId()}); r.Err != nil { + t.Fatal(r.Err) + } else { + rm := (*r.Data.(*model.ChannelMembers)) + + if len(rm) != 2 { + t.Fatal("return wrong number of results") + } + } + + if r := <-ss.Channel().GetMembersByIds(m1.ChannelId, []string{}); r.Err == nil { + t.Fatal("empty user ids - should have failed") + } +} + +func testChannelStoreAnalyticsDeletedTypeCount(t *testing.T, ss store.Store) { + o1 := model.Channel{} + o1.TeamId = model.NewId() + o1.DisplayName = "ChannelA" + o1.Name = "zz" + model.NewId() + "b" + o1.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o1)) + + o2 := model.Channel{} + o2.TeamId = model.NewId() + o2.DisplayName = "Channel2" + o2.Name = "zz" + model.NewId() + "b" + o2.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o2)) + + p3 := model.Channel{} + p3.TeamId = model.NewId() + p3.DisplayName = "Channel3" + p3.Name = "zz" + model.NewId() + "b" + p3.Type = model.CHANNEL_PRIVATE + store.Must(ss.Channel().Save(&p3)) + + u1 := &model.User{} + u1.Email = model.NewId() + u1.Nickname = model.NewId() + store.Must(ss.User().Save(u1)) + + u2 := &model.User{} + u2.Email = model.NewId() + u2.Nickname = model.NewId() + store.Must(ss.User().Save(u2)) + + var d4 *model.Channel + if result := <-ss.Channel().CreateDirectChannel(u1.Id, u2.Id); result.Err != nil { + t.Fatalf(result.Err.Error()) + } else { + d4 = result.Data.(*model.Channel) + } + + var openStartCount int64 + if result := <-ss.Channel().AnalyticsDeletedTypeCount("", "O"); result.Err != nil { + t.Fatal(result.Err.Error()) + } else { + openStartCount = result.Data.(int64) + } + + var privateStartCount int64 + if result := <-ss.Channel().AnalyticsDeletedTypeCount("", "P"); result.Err != nil { + t.Fatal(result.Err.Error()) + } else { + privateStartCount = result.Data.(int64) + } + + var directStartCount int64 + if result := <-ss.Channel().AnalyticsDeletedTypeCount("", "D"); result.Err != nil { + t.Fatal(result.Err.Error()) + } else { + directStartCount = result.Data.(int64) + } + + store.Must(ss.Channel().Delete(o1.Id, model.GetMillis())) + store.Must(ss.Channel().Delete(o2.Id, model.GetMillis())) + store.Must(ss.Channel().Delete(p3.Id, model.GetMillis())) + store.Must(ss.Channel().Delete(d4.Id, model.GetMillis())) + + if result := <-ss.Channel().AnalyticsDeletedTypeCount("", "O"); result.Err != nil { + t.Fatal(result.Err.Error()) + } else { + if result.Data.(int64) != openStartCount+2 { + t.Fatalf("Wrong open channel deleted count.") + } + } + + if result := <-ss.Channel().AnalyticsDeletedTypeCount("", "P"); result.Err != nil { + t.Fatal(result.Err.Error()) + } else { + if result.Data.(int64) != privateStartCount+1 { + t.Fatalf("Wrong private channel deleted count.") + } + } + + if result := <-ss.Channel().AnalyticsDeletedTypeCount("", "D"); result.Err != nil { + t.Fatal(result.Err.Error()) + } else { + if result.Data.(int64) != directStartCount+1 { + t.Fatalf("Wrong direct channel deleted count.") + } + } +} + +func testChannelStoreGetPinnedPosts(t *testing.T, ss store.Store) { + o1 := store.Must(ss.Channel().Save(&model.Channel{ + TeamId: model.NewId(), + DisplayName: "Name", + Name: "zz" + model.NewId() + "b", + Type: model.CHANNEL_OPEN, + })).(*model.Channel) + + p1 := store.Must(ss.Post().Save(&model.Post{ + UserId: model.NewId(), + ChannelId: o1.Id, + Message: "test", + IsPinned: true, + })).(*model.Post) + + if r1 := <-ss.Channel().GetPinnedPosts(o1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else if r1.Data.(*model.PostList).Posts[p1.Id] == nil { + t.Fatal("didn't return relevant pinned posts") + } + + o2 := store.Must(ss.Channel().Save(&model.Channel{ + TeamId: model.NewId(), + DisplayName: "Name", + Name: "zz" + model.NewId() + "b", + Type: model.CHANNEL_OPEN, + })).(*model.Channel) + + store.Must(ss.Post().Save(&model.Post{ + UserId: model.NewId(), + ChannelId: o2.Id, + Message: "test", + })) + + if r2 := <-ss.Channel().GetPinnedPosts(o2.Id); r2.Err != nil { + t.Fatal(r2.Err) + } else if len(r2.Data.(*model.PostList).Posts) != 0 { + t.Fatal("wasn't supposed to return posts") + } +} diff --git a/store/storetest/cluster_discovery_store.go b/store/storetest/cluster_discovery_store.go new file mode 100644 index 000000000..478f2e5f8 --- /dev/null +++ b/store/storetest/cluster_discovery_store.go @@ -0,0 +1,200 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "testing" + + "time" + + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" +) + +func TestClusterDiscoveryStore(t *testing.T, ss store.Store) { + t.Run("", func(t *testing.T) { testClusterDiscoveryStore(t, ss) }) + t.Run("Delete", func(t *testing.T) { testClusterDiscoveryStoreDelete(t, ss) }) + t.Run("LastPing", func(t *testing.T) { testClusterDiscoveryStoreLastPing(t, ss) }) + t.Run("Exists", func(t *testing.T) { testClusterDiscoveryStoreExists(t, ss) }) + t.Run("ClusterDiscoveryGetStore", func(t *testing.T) { testClusterDiscoveryGetStore(t, ss) }) +} + +func testClusterDiscoveryStore(t *testing.T, ss store.Store) { + discovery := &model.ClusterDiscovery{ + ClusterName: "cluster_name", + Hostname: "hostname" + model.NewId(), + Type: "test_test", + } + + if result := <-ss.ClusterDiscovery().Save(discovery); result.Err != nil { + t.Fatal(result.Err) + } + + if result := <-ss.ClusterDiscovery().Cleanup(); result.Err != nil { + t.Fatal(result.Err) + } +} + +func testClusterDiscoveryStoreDelete(t *testing.T, ss store.Store) { + discovery := &model.ClusterDiscovery{ + ClusterName: "cluster_name", + Hostname: "hostname" + model.NewId(), + Type: "test_test", + } + + if result := <-ss.ClusterDiscovery().Save(discovery); result.Err != nil { + t.Fatal(result.Err) + } + + if result := <-ss.ClusterDiscovery().Delete(discovery); result.Err != nil { + t.Fatal(result.Err) + } +} + +func testClusterDiscoveryStoreLastPing(t *testing.T, ss store.Store) { + discovery := &model.ClusterDiscovery{ + ClusterName: "cluster_name_lastPing", + Hostname: "hostname" + model.NewId(), + Type: "test_test_lastPing" + model.NewId(), + } + + if result := <-ss.ClusterDiscovery().Save(discovery); result.Err != nil { + t.Fatal(result.Err) + } + + if result := <-ss.ClusterDiscovery().SetLastPingAt(discovery); result.Err != nil { + t.Fatal(result.Err) + } + + ttime := model.GetMillis() + + time.Sleep(1 * time.Second) + + if result := <-ss.ClusterDiscovery().SetLastPingAt(discovery); result.Err != nil { + t.Fatal(result.Err) + } + + if result := <-ss.ClusterDiscovery().GetAll(discovery.Type, "cluster_name_lastPing"); result.Err != nil { + t.Fatal(result.Err) + } else { + list := result.Data.([]*model.ClusterDiscovery) + + if len(list) != 1 { + t.Fatal("should only be 1 items") + return + } + + if list[0].LastPingAt-ttime < 500 { + t.Fatal("failed to set time") + } + } + + discovery2 := &model.ClusterDiscovery{ + ClusterName: "cluster_name_missing", + Hostname: "hostname" + model.NewId(), + Type: "test_test_missing", + } + + if result := <-ss.ClusterDiscovery().SetLastPingAt(discovery2); result.Err != nil { + t.Fatal(result.Err) + } +} + +func testClusterDiscoveryStoreExists(t *testing.T, ss store.Store) { + discovery := &model.ClusterDiscovery{ + ClusterName: "cluster_name_Exists", + Hostname: "hostname" + model.NewId(), + Type: "test_test_Exists" + model.NewId(), + } + + if result := <-ss.ClusterDiscovery().Save(discovery); result.Err != nil { + t.Fatal(result.Err) + } + + if result := <-ss.ClusterDiscovery().Exists(discovery); result.Err != nil { + t.Fatal(result.Err) + } else { + val := result.Data.(bool) + if !val { + t.Fatal("should be true") + } + } + + discovery.ClusterName = "cluster_name_Exists2" + + if result := <-ss.ClusterDiscovery().Exists(discovery); result.Err != nil { + t.Fatal(result.Err) + } else { + val := result.Data.(bool) + if val { + t.Fatal("should be true") + } + } +} + +func testClusterDiscoveryGetStore(t *testing.T, ss store.Store) { + testType1 := model.NewId() + + discovery1 := &model.ClusterDiscovery{ + ClusterName: "cluster_name", + Hostname: "hostname1", + Type: testType1, + } + store.Must(ss.ClusterDiscovery().Save(discovery1)) + + discovery2 := &model.ClusterDiscovery{ + ClusterName: "cluster_name", + Hostname: "hostname2", + Type: testType1, + } + store.Must(ss.ClusterDiscovery().Save(discovery2)) + + discovery3 := &model.ClusterDiscovery{ + ClusterName: "cluster_name", + Hostname: "hostname3", + Type: testType1, + CreateAt: 1, + LastPingAt: 1, + } + store.Must(ss.ClusterDiscovery().Save(discovery3)) + + testType2 := model.NewId() + + discovery4 := &model.ClusterDiscovery{ + ClusterName: "cluster_name", + Hostname: "hostname1", + Type: testType2, + } + store.Must(ss.ClusterDiscovery().Save(discovery4)) + + if result := <-ss.ClusterDiscovery().GetAll(testType1, "cluster_name"); result.Err != nil { + t.Fatal(result.Err) + } else { + list := result.Data.([]*model.ClusterDiscovery) + + if len(list) != 2 { + t.Fatal("Should only have returned 2") + } + } + + if result := <-ss.ClusterDiscovery().GetAll(testType2, "cluster_name"); result.Err != nil { + t.Fatal(result.Err) + } else { + list := result.Data.([]*model.ClusterDiscovery) + + if len(list) != 1 { + t.Fatal("Should only have returned 1") + } + } + + if result := <-ss.ClusterDiscovery().GetAll(model.NewId(), "cluster_name"); result.Err != nil { + t.Fatal(result.Err) + } else { + list := result.Data.([]*model.ClusterDiscovery) + + if len(list) != 0 { + t.Fatal("shouldn't be any") + } + } +} diff --git a/store/storetest/command_store.go b/store/storetest/command_store.go new file mode 100644 index 000000000..92d981660 --- /dev/null +++ b/store/storetest/command_store.go @@ -0,0 +1,251 @@ +// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "testing" + + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" +) + +func TestCommandStore(t *testing.T, ss store.Store) { + t.Run("Save", func(t *testing.T) { testCommandStoreSave(t, ss) }) + t.Run("Get", func(t *testing.T) { testCommandStoreGet(t, ss) }) + t.Run("GetByTeam", func(t *testing.T) { testCommandStoreGetByTeam(t, ss) }) + t.Run("GetByTrigger", func(t *testing.T) { testCommandStoreGetByTrigger(t, ss) }) + t.Run("Delete", func(t *testing.T) { testCommandStoreDelete(t, ss) }) + t.Run("DeleteByTeam", func(t *testing.T) { testCommandStoreDeleteByTeam(t, ss) }) + t.Run("DeleteByUser", func(t *testing.T) { testCommandStoreDeleteByUser(t, ss) }) + t.Run("Update", func(t *testing.T) { testCommandStoreUpdate(t, ss) }) + t.Run("CommandCount", func(t *testing.T) { testCommandCount(t, ss) }) +} + +func testCommandStoreSave(t *testing.T, ss store.Store) { + o1 := model.Command{} + o1.CreatorId = model.NewId() + o1.Method = model.COMMAND_METHOD_POST + o1.TeamId = model.NewId() + o1.URL = "http://nowhere.com/" + o1.Trigger = "trigger" + + if err := (<-ss.Command().Save(&o1)).Err; err != nil { + t.Fatal("couldn't save item", err) + } + + if err := (<-ss.Command().Save(&o1)).Err; err == nil { + t.Fatal("shouldn't be able to update from save") + } +} + +func testCommandStoreGet(t *testing.T, ss store.Store) { + o1 := &model.Command{} + o1.CreatorId = model.NewId() + o1.Method = model.COMMAND_METHOD_POST + o1.TeamId = model.NewId() + o1.URL = "http://nowhere.com/" + o1.Trigger = "trigger" + + o1 = (<-ss.Command().Save(o1)).Data.(*model.Command) + + if r1 := <-ss.Command().Get(o1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.Command).CreateAt != o1.CreateAt { + t.Fatal("invalid returned command") + } + } + + if err := (<-ss.Command().Get("123")).Err; err == nil { + t.Fatal("Missing id should have failed") + } +} + +func testCommandStoreGetByTeam(t *testing.T, ss store.Store) { + o1 := &model.Command{} + o1.CreatorId = model.NewId() + o1.Method = model.COMMAND_METHOD_POST + o1.TeamId = model.NewId() + o1.URL = "http://nowhere.com/" + o1.Trigger = "trigger" + + o1 = (<-ss.Command().Save(o1)).Data.(*model.Command) + + if r1 := <-ss.Command().GetByTeam(o1.TeamId); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.([]*model.Command)[0].CreateAt != o1.CreateAt { + t.Fatal("invalid returned command") + } + } + + if result := <-ss.Command().GetByTeam("123"); result.Err != nil { + t.Fatal(result.Err) + } else { + if len(result.Data.([]*model.Command)) != 0 { + t.Fatal("no commands should have returned") + } + } +} + +func testCommandStoreGetByTrigger(t *testing.T, ss store.Store) { + o1 := &model.Command{} + o1.CreatorId = model.NewId() + o1.Method = model.COMMAND_METHOD_POST + o1.TeamId = model.NewId() + o1.URL = "http://nowhere.com/" + o1.Trigger = "trigger1" + + o2 := &model.Command{} + o2.CreatorId = model.NewId() + o2.Method = model.COMMAND_METHOD_POST + o2.TeamId = model.NewId() + o2.URL = "http://nowhere.com/" + o2.Trigger = "trigger1" + + o1 = (<-ss.Command().Save(o1)).Data.(*model.Command) + o2 = (<-ss.Command().Save(o2)).Data.(*model.Command) + + if r1 := <-ss.Command().GetByTrigger(o1.TeamId, o1.Trigger); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.Command).Id != o1.Id { + t.Fatal("invalid returned command") + } + } + + store.Must(ss.Command().Delete(o1.Id, model.GetMillis())) + + if result := <-ss.Command().GetByTrigger(o1.TeamId, o1.Trigger); result.Err == nil { + t.Fatal("no commands should have returned") + } +} + +func testCommandStoreDelete(t *testing.T, ss store.Store) { + o1 := &model.Command{} + o1.CreatorId = model.NewId() + o1.Method = model.COMMAND_METHOD_POST + o1.TeamId = model.NewId() + o1.URL = "http://nowhere.com/" + o1.Trigger = "trigger" + + o1 = (<-ss.Command().Save(o1)).Data.(*model.Command) + + if r1 := <-ss.Command().Get(o1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.Command).CreateAt != o1.CreateAt { + t.Fatal("invalid returned command") + } + } + + if r2 := <-ss.Command().Delete(o1.Id, model.GetMillis()); r2.Err != nil { + t.Fatal(r2.Err) + } + + if r3 := (<-ss.Command().Get(o1.Id)); r3.Err == nil { + t.Log(r3.Data) + t.Fatal("Missing id should have failed") + } +} + +func testCommandStoreDeleteByTeam(t *testing.T, ss store.Store) { + o1 := &model.Command{} + o1.CreatorId = model.NewId() + o1.Method = model.COMMAND_METHOD_POST + o1.TeamId = model.NewId() + o1.URL = "http://nowhere.com/" + o1.Trigger = "trigger" + + o1 = (<-ss.Command().Save(o1)).Data.(*model.Command) + + if r1 := <-ss.Command().Get(o1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.Command).CreateAt != o1.CreateAt { + t.Fatal("invalid returned command") + } + } + + if r2 := <-ss.Command().PermanentDeleteByTeam(o1.TeamId); r2.Err != nil { + t.Fatal(r2.Err) + } + + if r3 := (<-ss.Command().Get(o1.Id)); r3.Err == nil { + t.Log(r3.Data) + t.Fatal("Missing id should have failed") + } +} + +func testCommandStoreDeleteByUser(t *testing.T, ss store.Store) { + o1 := &model.Command{} + o1.CreatorId = model.NewId() + o1.Method = model.COMMAND_METHOD_POST + o1.TeamId = model.NewId() + o1.URL = "http://nowhere.com/" + o1.Trigger = "trigger" + + o1 = (<-ss.Command().Save(o1)).Data.(*model.Command) + + if r1 := <-ss.Command().Get(o1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.Command).CreateAt != o1.CreateAt { + t.Fatal("invalid returned command") + } + } + + if r2 := <-ss.Command().PermanentDeleteByUser(o1.CreatorId); r2.Err != nil { + t.Fatal(r2.Err) + } + + if r3 := (<-ss.Command().Get(o1.Id)); r3.Err == nil { + t.Log(r3.Data) + t.Fatal("Missing id should have failed") + } +} + +func testCommandStoreUpdate(t *testing.T, ss store.Store) { + o1 := &model.Command{} + o1.CreatorId = model.NewId() + o1.Method = model.COMMAND_METHOD_POST + o1.TeamId = model.NewId() + o1.URL = "http://nowhere.com/" + o1.Trigger = "trigger" + + o1 = (<-ss.Command().Save(o1)).Data.(*model.Command) + + o1.Token = model.NewId() + + if r2 := <-ss.Command().Update(o1); r2.Err != nil { + t.Fatal(r2.Err) + } +} + +func testCommandCount(t *testing.T, ss store.Store) { + o1 := &model.Command{} + o1.CreatorId = model.NewId() + o1.Method = model.COMMAND_METHOD_POST + o1.TeamId = model.NewId() + o1.URL = "http://nowhere.com/" + o1.Trigger = "trigger" + + o1 = (<-ss.Command().Save(o1)).Data.(*model.Command) + + if r1 := <-ss.Command().AnalyticsCommandCount(""); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(int64) == 0 { + t.Fatal("should be at least 1 command") + } + } + + if r2 := <-ss.Command().AnalyticsCommandCount(o1.TeamId); r2.Err != nil { + t.Fatal(r2.Err) + } else { + if r2.Data.(int64) != 1 { + t.Fatal("should be 1 command") + } + } +} diff --git a/store/storetest/command_webhook_store.go b/store/storetest/command_webhook_store.go new file mode 100644 index 000000000..a1f97b979 --- /dev/null +++ b/store/storetest/command_webhook_store.go @@ -0,0 +1,68 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "testing" + + "net/http" + + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" +) + +func TestCommandWebhookStore(t *testing.T, ss store.Store) { + t.Run("", func(t *testing.T) { testCommandWebhookStore(t, ss) }) +} + +func testCommandWebhookStore(t *testing.T, ss store.Store) { + cws := ss.CommandWebhook() + + h1 := &model.CommandWebhook{} + h1.CommandId = model.NewId() + h1.UserId = model.NewId() + h1.ChannelId = model.NewId() + h1 = (<-cws.Save(h1)).Data.(*model.CommandWebhook) + + if r1 := <-cws.Get(h1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if *r1.Data.(*model.CommandWebhook) != *h1 { + t.Fatal("invalid returned webhook") + } + } + + if err := (<-cws.Get("123")).Err; err.StatusCode != http.StatusNotFound { + t.Fatal("Should have set the status as not found for missing id") + } + + h2 := &model.CommandWebhook{} + h2.CreateAt = model.GetMillis() - 2*model.COMMAND_WEBHOOK_LIFETIME + h2.CommandId = model.NewId() + h2.UserId = model.NewId() + h2.ChannelId = model.NewId() + h2 = (<-cws.Save(h2)).Data.(*model.CommandWebhook) + + if err := (<-cws.Get(h2.Id)).Err; err == nil || err.StatusCode != http.StatusNotFound { + t.Fatal("Should have set the status as not found for expired webhook") + } + + cws.Cleanup() + + if err := (<-cws.Get(h1.Id)).Err; err != nil { + t.Fatal("Should have no error getting unexpired webhook") + } + + if err := (<-cws.Get(h2.Id)).Err; err.StatusCode != http.StatusNotFound { + t.Fatal("Should have set the status as not found for expired webhook") + } + + if err := (<-cws.TryUse(h1.Id, 1)).Err; err != nil { + t.Fatal("Should be able to use webhook once") + } + + if err := (<-cws.TryUse(h1.Id, 1)).Err; err == nil || err.StatusCode != http.StatusBadRequest { + t.Fatal("Should be able to use webhook once") + } +} diff --git a/store/storetest/compliance_store.go b/store/storetest/compliance_store.go new file mode 100644 index 000000000..1069bb88b --- /dev/null +++ b/store/storetest/compliance_store.go @@ -0,0 +1,318 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "testing" + "time" + + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" +) + +func TestComplianceStore(t *testing.T, ss store.Store) { + t.Run("", func(t *testing.T) { testComplianceStore(t, ss) }) + t.Run("ComplianceExport", func(t *testing.T) { testComplianceExport(t, ss) }) + t.Run("ComplianceExportDirectMessages", func(t *testing.T) { testComplianceExportDirectMessages(t, ss) }) +} + +func testComplianceStore(t *testing.T, ss store.Store) { + compliance1 := &model.Compliance{Desc: "Audit for federal subpoena case #22443", UserId: model.NewId(), Status: model.COMPLIANCE_STATUS_FAILED, StartAt: model.GetMillis() - 1, EndAt: model.GetMillis() + 1, Type: model.COMPLIANCE_TYPE_ADHOC} + store.Must(ss.Compliance().Save(compliance1)) + time.Sleep(100 * time.Millisecond) + + compliance2 := &model.Compliance{Desc: "Audit for federal subpoena case #11458", UserId: model.NewId(), Status: model.COMPLIANCE_STATUS_RUNNING, StartAt: model.GetMillis() - 1, EndAt: model.GetMillis() + 1, Type: model.COMPLIANCE_TYPE_ADHOC} + store.Must(ss.Compliance().Save(compliance2)) + time.Sleep(100 * time.Millisecond) + + c := ss.Compliance().GetAll(0, 1000) + result := <-c + compliances := result.Data.(model.Compliances) + + if compliances[0].Status != model.COMPLIANCE_STATUS_RUNNING && compliance2.Id != compliances[0].Id { + t.Fatal() + } + + compliance2.Status = model.COMPLIANCE_STATUS_FAILED + store.Must(ss.Compliance().Update(compliance2)) + + c = ss.Compliance().GetAll(0, 1000) + result = <-c + compliances = result.Data.(model.Compliances) + + if compliances[0].Status != model.COMPLIANCE_STATUS_FAILED && compliance2.Id != compliances[0].Id { + t.Fatal() + } + + c = ss.Compliance().GetAll(0, 1) + result = <-c + compliances = result.Data.(model.Compliances) + + if len(compliances) != 1 { + t.Fatal("should only have returned 1") + } + + c = ss.Compliance().GetAll(1, 1) + result = <-c + compliances = result.Data.(model.Compliances) + + if len(compliances) != 1 { + t.Fatal("should only have returned 1") + } + + rc2 := (<-ss.Compliance().Get(compliance2.Id)).Data.(*model.Compliance) + if rc2.Status != compliance2.Status { + t.Fatal() + } +} + +func testComplianceExport(t *testing.T, ss store.Store) { + time.Sleep(100 * time.Millisecond) + + t1 := &model.Team{} + t1.DisplayName = "DisplayName" + t1.Name = "zz" + model.NewId() + "b" + t1.Email = model.NewId() + "@nowhere.com" + t1.Type = model.TEAM_OPEN + t1 = store.Must(ss.Team().Save(t1)).(*model.Team) + + u1 := &model.User{} + u1.Email = model.NewId() + u1.Username = model.NewId() + u1 = store.Must(ss.User().Save(u1)).(*model.User) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: t1.Id, UserId: u1.Id})) + + u2 := &model.User{} + u2.Email = model.NewId() + u2.Username = model.NewId() + u2 = store.Must(ss.User().Save(u2)).(*model.User) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: t1.Id, UserId: u2.Id})) + + c1 := &model.Channel{} + c1.TeamId = t1.Id + c1.DisplayName = "Channel2" + c1.Name = "zz" + model.NewId() + "b" + c1.Type = model.CHANNEL_OPEN + c1 = store.Must(ss.Channel().Save(c1)).(*model.Channel) + + o1 := &model.Post{} + o1.ChannelId = c1.Id + o1.UserId = u1.Id + o1.CreateAt = model.GetMillis() + o1.Message = "zz" + model.NewId() + "b" + o1 = store.Must(ss.Post().Save(o1)).(*model.Post) + + o1a := &model.Post{} + o1a.ChannelId = c1.Id + o1a.UserId = u1.Id + o1a.CreateAt = o1.CreateAt + 10 + o1a.Message = "zz" + model.NewId() + "b" + o1a = store.Must(ss.Post().Save(o1a)).(*model.Post) + + o2 := &model.Post{} + o2.ChannelId = c1.Id + o2.UserId = u1.Id + o2.CreateAt = o1.CreateAt + 20 + o2.Message = "zz" + model.NewId() + "b" + o2 = store.Must(ss.Post().Save(o2)).(*model.Post) + + o2a := &model.Post{} + o2a.ChannelId = c1.Id + o2a.UserId = u2.Id + o2a.CreateAt = o1.CreateAt + 30 + o2a.Message = "zz" + model.NewId() + "b" + o2a = store.Must(ss.Post().Save(o2a)).(*model.Post) + + time.Sleep(100 * time.Millisecond) + + cr1 := &model.Compliance{Desc: "test" + model.NewId(), StartAt: o1.CreateAt - 1, EndAt: o2a.CreateAt + 1} + if r1 := <-ss.Compliance().ComplianceExport(cr1); r1.Err != nil { + t.Fatal(r1.Err) + } else { + cposts := r1.Data.([]*model.CompliancePost) + + if len(cposts) != 4 { + t.Fatal("return wrong results length") + } + + if cposts[0].PostId != o1.Id { + t.Fatal("Wrong sort") + } + + if cposts[3].PostId != o2a.Id { + t.Fatal("Wrong sort") + } + } + + cr2 := &model.Compliance{Desc: "test" + model.NewId(), StartAt: o1.CreateAt - 1, EndAt: o2a.CreateAt + 1, Emails: u2.Email} + if r1 := <-ss.Compliance().ComplianceExport(cr2); r1.Err != nil { + t.Fatal(r1.Err) + } else { + cposts := r1.Data.([]*model.CompliancePost) + + if len(cposts) != 1 { + t.Fatal("return wrong results length") + } + + if cposts[0].PostId != o2a.Id { + t.Fatal("Wrong sort") + } + } + + cr3 := &model.Compliance{Desc: "test" + model.NewId(), StartAt: o1.CreateAt - 1, EndAt: o2a.CreateAt + 1, Emails: u2.Email + ", " + u1.Email} + if r1 := <-ss.Compliance().ComplianceExport(cr3); r1.Err != nil { + t.Fatal(r1.Err) + } else { + cposts := r1.Data.([]*model.CompliancePost) + + if len(cposts) != 4 { + t.Fatal("return wrong results length") + } + + if cposts[0].PostId != o1.Id { + t.Fatal("Wrong sort") + } + + if cposts[3].PostId != o2a.Id { + t.Fatal("Wrong sort") + } + } + + cr4 := &model.Compliance{Desc: "test" + model.NewId(), StartAt: o1.CreateAt - 1, EndAt: o2a.CreateAt + 1, Keywords: o2a.Message} + if r1 := <-ss.Compliance().ComplianceExport(cr4); r1.Err != nil { + t.Fatal(r1.Err) + } else { + cposts := r1.Data.([]*model.CompliancePost) + + if len(cposts) != 1 { + t.Fatal("return wrong results length") + } + + if cposts[0].PostId != o2a.Id { + t.Fatal("Wrong sort") + } + } + + cr5 := &model.Compliance{Desc: "test" + model.NewId(), StartAt: o1.CreateAt - 1, EndAt: o2a.CreateAt + 1, Keywords: o2a.Message + " " + o1.Message} + if r1 := <-ss.Compliance().ComplianceExport(cr5); r1.Err != nil { + t.Fatal(r1.Err) + } else { + cposts := r1.Data.([]*model.CompliancePost) + + if len(cposts) != 2 { + t.Fatal("return wrong results length") + } + + if cposts[0].PostId != o1.Id { + t.Fatal("Wrong sort") + } + } + + cr6 := &model.Compliance{Desc: "test" + model.NewId(), StartAt: o1.CreateAt - 1, EndAt: o2a.CreateAt + 1, Emails: u2.Email + ", " + u1.Email, Keywords: o2a.Message + " " + o1.Message} + if r1 := <-ss.Compliance().ComplianceExport(cr6); r1.Err != nil { + t.Fatal(r1.Err) + } else { + cposts := r1.Data.([]*model.CompliancePost) + + if len(cposts) != 2 { + t.Fatal("return wrong results length") + } + + if cposts[0].PostId != o1.Id { + t.Fatal("Wrong sort") + } + + if cposts[1].PostId != o2a.Id { + t.Fatal("Wrong sort") + } + } +} + +func testComplianceExportDirectMessages(t *testing.T, ss store.Store) { + time.Sleep(100 * time.Millisecond) + + t1 := &model.Team{} + t1.DisplayName = "DisplayName" + t1.Name = "zz" + model.NewId() + "b" + t1.Email = model.NewId() + "@nowhere.com" + t1.Type = model.TEAM_OPEN + t1 = store.Must(ss.Team().Save(t1)).(*model.Team) + + u1 := &model.User{} + u1.Email = model.NewId() + u1.Username = model.NewId() + u1 = store.Must(ss.User().Save(u1)).(*model.User) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: t1.Id, UserId: u1.Id})) + + u2 := &model.User{} + u2.Email = model.NewId() + u2.Username = model.NewId() + u2 = store.Must(ss.User().Save(u2)).(*model.User) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: t1.Id, UserId: u2.Id})) + + c1 := &model.Channel{} + c1.TeamId = t1.Id + c1.DisplayName = "Channel2" + c1.Name = "zz" + model.NewId() + "b" + c1.Type = model.CHANNEL_OPEN + c1 = store.Must(ss.Channel().Save(c1)).(*model.Channel) + + cDM := store.Must(ss.Channel().CreateDirectChannel(u1.Id, u2.Id)).(*model.Channel) + + o1 := &model.Post{} + o1.ChannelId = c1.Id + o1.UserId = u1.Id + o1.CreateAt = model.GetMillis() + o1.Message = "zz" + model.NewId() + "b" + o1 = store.Must(ss.Post().Save(o1)).(*model.Post) + + o1a := &model.Post{} + o1a.ChannelId = c1.Id + o1a.UserId = u1.Id + o1a.CreateAt = o1.CreateAt + 10 + o1a.Message = "zz" + model.NewId() + "b" + o1a = store.Must(ss.Post().Save(o1a)).(*model.Post) + + o2 := &model.Post{} + o2.ChannelId = c1.Id + o2.UserId = u1.Id + o2.CreateAt = o1.CreateAt + 20 + o2.Message = "zz" + model.NewId() + "b" + o2 = store.Must(ss.Post().Save(o2)).(*model.Post) + + o2a := &model.Post{} + o2a.ChannelId = c1.Id + o2a.UserId = u2.Id + o2a.CreateAt = o1.CreateAt + 30 + o2a.Message = "zz" + model.NewId() + "b" + o2a = store.Must(ss.Post().Save(o2a)).(*model.Post) + + o3 := &model.Post{} + o3.ChannelId = cDM.Id + o3.UserId = u1.Id + o3.CreateAt = o1.CreateAt + 40 + o3.Message = "zz" + model.NewId() + "b" + o3 = store.Must(ss.Post().Save(o3)).(*model.Post) + + time.Sleep(100 * time.Millisecond) + + cr1 := &model.Compliance{Desc: "test" + model.NewId(), StartAt: o1.CreateAt - 1, EndAt: o3.CreateAt + 1, Emails: u1.Email} + if r1 := <-ss.Compliance().ComplianceExport(cr1); r1.Err != nil { + t.Fatal(r1.Err) + } else { + cposts := r1.Data.([]*model.CompliancePost) + + if len(cposts) != 4 { + t.Fatal("return wrong results length") + } + + if cposts[0].PostId != o1.Id { + t.Fatal("Wrong sort") + } + + if cposts[len(cposts)-1].PostId != o3.Id { + t.Fatal("Wrong sort") + } + } +} diff --git a/store/storetest/emoji_store.go b/store/storetest/emoji_store.go new file mode 100644 index 000000000..fc5a31a43 --- /dev/null +++ b/store/storetest/emoji_store.go @@ -0,0 +1,175 @@ +// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "testing" + "time" + + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" +) + +func TestEmojiStore(t *testing.T, ss store.Store) { + t.Run("EmojiSaveDelete", func(t *testing.T) { testEmojiSaveDelete(t, ss) }) + t.Run("EmojiGet", func(t *testing.T) { testEmojiGet(t, ss) }) + t.Run("EmojiGetByName", func(t *testing.T) { testEmojiGetByName(t, ss) }) + t.Run("EmojiGetList", func(t *testing.T) { testEmojiGetList(t, ss) }) +} + +func testEmojiSaveDelete(t *testing.T, ss store.Store) { + emoji1 := &model.Emoji{ + CreatorId: model.NewId(), + Name: model.NewId(), + } + + if result := <-ss.Emoji().Save(emoji1); result.Err != nil { + t.Fatal(result.Err) + } + + if len(emoji1.Id) != 26 { + t.Fatal("should've set id for emoji") + } + + emoji2 := model.Emoji{ + CreatorId: model.NewId(), + Name: emoji1.Name, + } + if result := <-ss.Emoji().Save(&emoji2); result.Err == nil { + t.Fatal("shouldn't be able to save emoji with duplicate name") + } + + if result := <-ss.Emoji().Delete(emoji1.Id, time.Now().Unix()); result.Err != nil { + t.Fatal(result.Err) + } + + if result := <-ss.Emoji().Save(&emoji2); result.Err != nil { + t.Fatal("should be able to save emoji with duplicate name now that original has been deleted", result.Err) + } + + if result := <-ss.Emoji().Delete(emoji2.Id, time.Now().Unix()+1); result.Err != nil { + t.Fatal(result.Err) + } +} + +func testEmojiGet(t *testing.T, ss store.Store) { + emojis := []model.Emoji{ + { + CreatorId: model.NewId(), + Name: model.NewId(), + }, + { + CreatorId: model.NewId(), + Name: model.NewId(), + }, + { + CreatorId: model.NewId(), + Name: model.NewId(), + }, + } + + for i, emoji := range emojis { + emojis[i] = *store.Must(ss.Emoji().Save(&emoji)).(*model.Emoji) + } + defer func() { + for _, emoji := range emojis { + store.Must(ss.Emoji().Delete(emoji.Id, time.Now().Unix())) + } + }() + + for _, emoji := range emojis { + if result := <-ss.Emoji().Get(emoji.Id, false); result.Err != nil { + t.Fatalf("failed to get emoji with id %v: %v", emoji.Id, result.Err) + } + } + + for _, emoji := range emojis { + if result := <-ss.Emoji().Get(emoji.Id, true); result.Err != nil { + t.Fatalf("failed to get emoji with id %v: %v", emoji.Id, result.Err) + } + } + + for _, emoji := range emojis { + if result := <-ss.Emoji().Get(emoji.Id, true); result.Err != nil { + t.Fatalf("failed to get emoji with id %v: %v", emoji.Id, result.Err) + } + } +} + +func testEmojiGetByName(t *testing.T, ss store.Store) { + emojis := []model.Emoji{ + { + CreatorId: model.NewId(), + Name: model.NewId(), + }, + { + CreatorId: model.NewId(), + Name: model.NewId(), + }, + { + CreatorId: model.NewId(), + Name: model.NewId(), + }, + } + + for i, emoji := range emojis { + emojis[i] = *store.Must(ss.Emoji().Save(&emoji)).(*model.Emoji) + } + defer func() { + for _, emoji := range emojis { + store.Must(ss.Emoji().Delete(emoji.Id, time.Now().Unix())) + } + }() + + for _, emoji := range emojis { + if result := <-ss.Emoji().GetByName(emoji.Name); result.Err != nil { + t.Fatalf("failed to get emoji with name %v: %v", emoji.Name, result.Err) + } + } +} + +func testEmojiGetList(t *testing.T, ss store.Store) { + emojis := []model.Emoji{ + { + CreatorId: model.NewId(), + Name: model.NewId(), + }, + { + CreatorId: model.NewId(), + Name: model.NewId(), + }, + { + CreatorId: model.NewId(), + Name: model.NewId(), + }, + } + + for i, emoji := range emojis { + emojis[i] = *store.Must(ss.Emoji().Save(&emoji)).(*model.Emoji) + } + defer func() { + for _, emoji := range emojis { + store.Must(ss.Emoji().Delete(emoji.Id, time.Now().Unix())) + } + }() + + if result := <-ss.Emoji().GetList(0, 100); result.Err != nil { + t.Fatal(result.Err) + } else { + for _, emoji := range emojis { + found := false + + for _, savedEmoji := range result.Data.([]*model.Emoji) { + if emoji.Id == savedEmoji.Id { + found = true + break + } + } + + if !found { + t.Fatalf("failed to get emoji with id %v", emoji.Id) + } + } + } +} diff --git a/store/storetest/file_info_store.go b/store/storetest/file_info_store.go new file mode 100644 index 000000000..9b3388db5 --- /dev/null +++ b/store/storetest/file_info_store.go @@ -0,0 +1,296 @@ +// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "fmt" + "testing" + + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" +) + +func TestFileInfoStore(t *testing.T, ss store.Store) { + t.Run("FileInfoSaveGet", func(t *testing.T) { testFileInfoSaveGet(t, ss) }) + t.Run("FileInfoSaveGetByPath", func(t *testing.T) { testFileInfoSaveGetByPath(t, ss) }) + t.Run("FileInfoGetForPost", func(t *testing.T) { testFileInfoGetForPost(t, ss) }) + t.Run("FileInfoAttachToPost", func(t *testing.T) { testFileInfoAttachToPost(t, ss) }) + t.Run("FileInfoDeleteForPost", func(t *testing.T) { testFileInfoDeleteForPost(t, ss) }) + t.Run("FileInfoPermanentDelete", func(t *testing.T) { testFileInfoPermanentDelete(t, ss) }) + t.Run("FileInfoPermanentDeleteBatch", func(t *testing.T) { testFileInfoPermanentDeleteBatch(t, ss) }) +} + +func testFileInfoSaveGet(t *testing.T, ss store.Store) { + info := &model.FileInfo{ + CreatorId: model.NewId(), + Path: "file.txt", + } + + if result := <-ss.FileInfo().Save(info); result.Err != nil { + t.Fatal(result.Err) + } else if returned := result.Data.(*model.FileInfo); len(returned.Id) == 0 { + t.Fatal("should've assigned an id to FileInfo") + } else { + info = returned + } + defer func() { + <-ss.FileInfo().PermanentDelete(info.Id) + }() + + if result := <-ss.FileInfo().Get(info.Id); result.Err != nil { + t.Fatal(result.Err) + } else if returned := result.Data.(*model.FileInfo); returned.Id != info.Id { + t.Log(info) + t.Log(returned) + t.Fatal("should've returned correct FileInfo") + } + + info2 := store.Must(ss.FileInfo().Save(&model.FileInfo{ + CreatorId: model.NewId(), + Path: "file.txt", + DeleteAt: 123, + })).(*model.FileInfo) + + if result := <-ss.FileInfo().Get(info2.Id); result.Err == nil { + t.Fatal("shouldn't have gotten deleted file") + } + defer func() { + <-ss.FileInfo().PermanentDelete(info2.Id) + }() +} + +func testFileInfoSaveGetByPath(t *testing.T, ss store.Store) { + info := &model.FileInfo{ + CreatorId: model.NewId(), + Path: fmt.Sprintf("%v/file.txt", model.NewId()), + } + + if result := <-ss.FileInfo().Save(info); result.Err != nil { + t.Fatal(result.Err) + } else if returned := result.Data.(*model.FileInfo); len(returned.Id) == 0 { + t.Fatal("should've assigned an id to FileInfo") + } else { + info = returned + } + defer func() { + <-ss.FileInfo().PermanentDelete(info.Id) + }() + + if result := <-ss.FileInfo().GetByPath(info.Path); result.Err != nil { + t.Fatal(result.Err) + } else if returned := result.Data.(*model.FileInfo); returned.Id != info.Id { + t.Log(info) + t.Log(returned) + t.Fatal("should've returned correct FileInfo") + } + + info2 := store.Must(ss.FileInfo().Save(&model.FileInfo{ + CreatorId: model.NewId(), + Path: "file.txt", + DeleteAt: 123, + })).(*model.FileInfo) + + if result := <-ss.FileInfo().GetByPath(info2.Id); result.Err == nil { + t.Fatal("shouldn't have gotten deleted file") + } + defer func() { + <-ss.FileInfo().PermanentDelete(info2.Id) + }() +} + +func testFileInfoGetForPost(t *testing.T, ss store.Store) { + userId := model.NewId() + postId := model.NewId() + + infos := []*model.FileInfo{ + { + PostId: postId, + CreatorId: userId, + Path: "file.txt", + }, + { + PostId: postId, + CreatorId: userId, + Path: "file.txt", + }, + { + PostId: postId, + CreatorId: userId, + Path: "file.txt", + DeleteAt: 123, + }, + { + PostId: model.NewId(), + CreatorId: userId, + Path: "file.txt", + }, + } + + for i, info := range infos { + infos[i] = store.Must(ss.FileInfo().Save(info)).(*model.FileInfo) + defer func(id string) { + <-ss.FileInfo().PermanentDelete(id) + }(infos[i].Id) + } + + if result := <-ss.FileInfo().GetForPost(postId, true, false); result.Err != nil { + t.Fatal(result.Err) + } else if returned := result.Data.([]*model.FileInfo); len(returned) != 2 { + t.Fatal("should've returned exactly 2 file infos") + } + + if result := <-ss.FileInfo().GetForPost(postId, false, false); result.Err != nil { + t.Fatal(result.Err) + } else if returned := result.Data.([]*model.FileInfo); len(returned) != 2 { + t.Fatal("should've returned exactly 2 file infos") + } + + if result := <-ss.FileInfo().GetForPost(postId, true, true); result.Err != nil { + t.Fatal(result.Err) + } else if returned := result.Data.([]*model.FileInfo); len(returned) != 2 { + t.Fatal("should've returned exactly 2 file infos") + } +} + +func testFileInfoAttachToPost(t *testing.T, ss store.Store) { + userId := model.NewId() + postId := model.NewId() + + info1 := store.Must(ss.FileInfo().Save(&model.FileInfo{ + CreatorId: userId, + Path: "file.txt", + })).(*model.FileInfo) + defer func() { + <-ss.FileInfo().PermanentDelete(info1.Id) + }() + + if len(info1.PostId) != 0 { + t.Fatal("file shouldn't have a PostId") + } + + if result := <-ss.FileInfo().AttachToPost(info1.Id, postId); result.Err != nil { + t.Fatal(result.Err) + } else { + info1 = store.Must(ss.FileInfo().Get(info1.Id)).(*model.FileInfo) + } + + if len(info1.PostId) == 0 { + t.Fatal("file should now have a PostId") + } + + info2 := store.Must(ss.FileInfo().Save(&model.FileInfo{ + CreatorId: userId, + Path: "file.txt", + })).(*model.FileInfo) + defer func() { + <-ss.FileInfo().PermanentDelete(info2.Id) + }() + + if result := <-ss.FileInfo().AttachToPost(info2.Id, postId); result.Err != nil { + t.Fatal(result.Err) + } else { + info2 = store.Must(ss.FileInfo().Get(info2.Id)).(*model.FileInfo) + } + + if result := <-ss.FileInfo().GetForPost(postId, true, false); result.Err != nil { + t.Fatal(result.Err) + } else if infos := result.Data.([]*model.FileInfo); len(infos) != 2 { + t.Fatal("should've returned exactly 2 file infos") + } +} + +func testFileInfoDeleteForPost(t *testing.T, ss store.Store) { + userId := model.NewId() + postId := model.NewId() + + infos := []*model.FileInfo{ + { + PostId: postId, + CreatorId: userId, + Path: "file.txt", + }, + { + PostId: postId, + CreatorId: userId, + Path: "file.txt", + }, + { + PostId: postId, + CreatorId: userId, + Path: "file.txt", + DeleteAt: 123, + }, + { + PostId: model.NewId(), + CreatorId: userId, + Path: "file.txt", + }, + } + + for i, info := range infos { + infos[i] = store.Must(ss.FileInfo().Save(info)).(*model.FileInfo) + defer func(id string) { + <-ss.FileInfo().PermanentDelete(id) + }(infos[i].Id) + } + + if result := <-ss.FileInfo().DeleteForPost(postId); result.Err != nil { + t.Fatal(result.Err) + } + + if infos := store.Must(ss.FileInfo().GetForPost(postId, true, false)).([]*model.FileInfo); len(infos) != 0 { + t.Fatal("shouldn't have returned any file infos") + } +} + +func testFileInfoPermanentDelete(t *testing.T, ss store.Store) { + info := store.Must(ss.FileInfo().Save(&model.FileInfo{ + PostId: model.NewId(), + CreatorId: model.NewId(), + Path: "file.txt", + })).(*model.FileInfo) + + if result := <-ss.FileInfo().PermanentDelete(info.Id); result.Err != nil { + t.Fatal(result.Err) + } +} + +func testFileInfoPermanentDeleteBatch(t *testing.T, ss store.Store) { + postId := model.NewId() + + store.Must(ss.FileInfo().Save(&model.FileInfo{ + PostId: postId, + CreatorId: model.NewId(), + Path: "file.txt", + CreateAt: 1000, + })) + + store.Must(ss.FileInfo().Save(&model.FileInfo{ + PostId: postId, + CreatorId: model.NewId(), + Path: "file.txt", + CreateAt: 1200, + })) + + store.Must(ss.FileInfo().Save(&model.FileInfo{ + PostId: postId, + CreatorId: model.NewId(), + Path: "file.txt", + CreateAt: 2000, + })) + + if result := <-ss.FileInfo().GetForPost(postId, true, false); result.Err != nil { + t.Fatal(result.Err) + } else if len(result.Data.([]*model.FileInfo)) != 3 { + t.Fatal("Expected 3 fileInfos") + } + + store.Must(ss.FileInfo().PermanentDeleteBatch(1500, 1000)) + + if result := <-ss.FileInfo().GetForPost(postId, true, false); result.Err != nil { + t.Fatal(result.Err) + } else if len(result.Data.([]*model.FileInfo)) != 1 { + t.Fatal("Expected 3 fileInfos") + } +} diff --git a/store/storetest/job_store.go b/store/storetest/job_store.go new file mode 100644 index 000000000..631df08fd --- /dev/null +++ b/store/storetest/job_store.go @@ -0,0 +1,507 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "testing" + + "time" + + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" + "github.com/stretchr/testify/assert" +) + +func TestJobStore(t *testing.T, ss store.Store) { + t.Run("JobSaveGet", func(t *testing.T) { testJobSaveGet(t, ss) }) + t.Run("JobGetAllByType", func(t *testing.T) { testJobGetAllByType(t, ss) }) + t.Run("JobGetAllByTypePage", func(t *testing.T) { testJobGetAllByTypePage(t, ss) }) + t.Run("JobGetAllPage", func(t *testing.T) { testJobGetAllPage(t, ss) }) + t.Run("JobGetAllByStatus", func(t *testing.T) { testJobGetAllByStatus(t, ss) }) + t.Run("GetNewestJobByStatusAndType", func(t *testing.T) { testJobStoreGetNewestJobByStatusAndType(t, ss) }) + t.Run("GetCountByStatusAndType", func(t *testing.T) { testJobStoreGetCountByStatusAndType(t, ss) }) + t.Run("JobUpdateOptimistically", func(t *testing.T) { testJobUpdateOptimistically(t, ss) }) + t.Run("JobUpdateStatusUpdateStatusOptimistically", func(t *testing.T) { testJobUpdateStatusUpdateStatusOptimistically(t, ss) }) + t.Run("JobDelete", func(t *testing.T) { testJobDelete(t, ss) }) +} + +func testJobSaveGet(t *testing.T, ss store.Store) { + job := &model.Job{ + Id: model.NewId(), + Type: model.NewId(), + Status: model.NewId(), + Data: map[string]string{ + "Processed": "0", + "Total": "12345", + "LastProcessed": "abcd", + }, + } + + if result := <-ss.Job().Save(job); result.Err != nil { + t.Fatal(result.Err) + } + + defer func() { + <-ss.Job().Delete(job.Id) + }() + + if result := <-ss.Job().Get(job.Id); result.Err != nil { + t.Fatal(result.Err) + } else if received := result.Data.(*model.Job); received.Id != job.Id { + t.Fatal("received incorrect job after save") + } else if received.Data["Total"] != "12345" { + t.Fatal("data field was not retrieved successfully:", received.Data) + } +} + +func testJobGetAllByType(t *testing.T, ss store.Store) { + jobType := model.NewId() + + jobs := []*model.Job{ + { + Id: model.NewId(), + Type: jobType, + }, + { + Id: model.NewId(), + Type: jobType, + }, + { + Id: model.NewId(), + Type: model.NewId(), + }, + } + + for _, job := range jobs { + store.Must(ss.Job().Save(job)) + defer ss.Job().Delete(job.Id) + } + + if result := <-ss.Job().GetAllByType(jobType); result.Err != nil { + t.Fatal(result.Err) + } else if received := result.Data.([]*model.Job); len(received) != 2 { + t.Fatal("received wrong number of jobs") + } else if received[0].Id != jobs[0].Id && received[1].Id != jobs[0].Id { + t.Fatal("should've received first jobs") + } else if received[0].Id != jobs[1].Id && received[1].Id != jobs[1].Id { + t.Fatal("should've received second jobs") + } +} + +func testJobGetAllByTypePage(t *testing.T, ss store.Store) { + jobType := model.NewId() + + jobs := []*model.Job{ + { + Id: model.NewId(), + Type: jobType, + CreateAt: 1000, + }, + { + Id: model.NewId(), + Type: jobType, + CreateAt: 999, + }, + { + Id: model.NewId(), + Type: jobType, + CreateAt: 1001, + }, + { + Id: model.NewId(), + Type: model.NewId(), + CreateAt: 1002, + }, + } + + for _, job := range jobs { + store.Must(ss.Job().Save(job)) + defer ss.Job().Delete(job.Id) + } + + if result := <-ss.Job().GetAllByTypePage(jobType, 0, 2); result.Err != nil { + t.Fatal(result.Err) + } else if received := result.Data.([]*model.Job); len(received) != 2 { + t.Fatal("received wrong number of jobs") + } else if received[0].Id != jobs[2].Id { + t.Fatal("should've received newest job first") + } else if received[1].Id != jobs[0].Id { + t.Fatal("should've received second newest job second") + } + + if result := <-ss.Job().GetAllByTypePage(jobType, 2, 2); result.Err != nil { + t.Fatal(result.Err) + } else if received := result.Data.([]*model.Job); len(received) != 1 { + t.Fatal("received wrong number of jobs") + } else if received[0].Id != jobs[1].Id { + t.Fatal("should've received oldest job last") + } +} + +func testJobGetAllPage(t *testing.T, ss store.Store) { + jobType := model.NewId() + createAtTime := model.GetMillis() + + jobs := []*model.Job{ + { + Id: model.NewId(), + Type: jobType, + CreateAt: createAtTime + 1, + }, + { + Id: model.NewId(), + Type: jobType, + CreateAt: createAtTime, + }, + { + Id: model.NewId(), + Type: jobType, + CreateAt: createAtTime + 2, + }, + } + + for _, job := range jobs { + store.Must(ss.Job().Save(job)) + defer ss.Job().Delete(job.Id) + } + + if result := <-ss.Job().GetAllPage(0, 2); result.Err != nil { + t.Fatal(result.Err) + } else if received := result.Data.([]*model.Job); len(received) != 2 { + t.Fatal("received wrong number of jobs") + } else if received[0].Id != jobs[2].Id { + t.Fatal("should've received newest job first") + } else if received[1].Id != jobs[0].Id { + t.Fatal("should've received second newest job second") + } + + if result := <-ss.Job().GetAllPage(2, 2); result.Err != nil { + t.Fatal(result.Err) + } else if received := result.Data.([]*model.Job); len(received) < 1 { + t.Fatal("received wrong number of jobs") + } else if received[0].Id != jobs[1].Id { + t.Fatal("should've received oldest job last") + } +} + +func testJobGetAllByStatus(t *testing.T, ss store.Store) { + jobType := model.NewId() + status := model.NewId() + + jobs := []*model.Job{ + { + Id: model.NewId(), + Type: jobType, + CreateAt: 1000, + Status: status, + Data: map[string]string{ + "test": "data", + }, + }, + { + Id: model.NewId(), + Type: jobType, + CreateAt: 999, + Status: status, + }, + { + Id: model.NewId(), + Type: jobType, + CreateAt: 1001, + Status: status, + }, + { + Id: model.NewId(), + Type: jobType, + CreateAt: 1002, + Status: model.NewId(), + }, + } + + for _, job := range jobs { + store.Must(ss.Job().Save(job)) + defer ss.Job().Delete(job.Id) + } + + if result := <-ss.Job().GetAllByStatus(status); result.Err != nil { + t.Fatal(result.Err) + } else if received := result.Data.([]*model.Job); len(received) != 3 { + t.Fatal("received wrong number of jobs") + } else if received[0].Id != jobs[1].Id || received[1].Id != jobs[0].Id || received[2].Id != jobs[2].Id { + t.Fatal("should've received jobs ordered by CreateAt time") + } else if received[1].Data["test"] != "data" { + t.Fatal("should've received job data field back as saved") + } +} + +func testJobStoreGetNewestJobByStatusAndType(t *testing.T, ss store.Store) { + jobType1 := model.NewId() + jobType2 := model.NewId() + status1 := model.NewId() + status2 := model.NewId() + + jobs := []*model.Job{ + { + Id: model.NewId(), + Type: jobType1, + CreateAt: 1001, + Status: status1, + }, + { + Id: model.NewId(), + Type: jobType1, + CreateAt: 1000, + Status: status1, + }, + { + Id: model.NewId(), + Type: jobType2, + CreateAt: 1003, + Status: status1, + }, + { + Id: model.NewId(), + Type: jobType1, + CreateAt: 1004, + Status: status2, + }, + } + + for _, job := range jobs { + store.Must(ss.Job().Save(job)) + defer ss.Job().Delete(job.Id) + } + + result := <-ss.Job().GetNewestJobByStatusAndType(status1, jobType1) + assert.Nil(t, result.Err) + assert.EqualValues(t, jobs[0].Id, result.Data.(*model.Job).Id) + + result = <-ss.Job().GetNewestJobByStatusAndType(model.NewId(), model.NewId()) + assert.Nil(t, result.Err) + assert.Nil(t, result.Data.(*model.Job)) +} + +func testJobStoreGetCountByStatusAndType(t *testing.T, ss store.Store) { + jobType1 := model.NewId() + jobType2 := model.NewId() + status1 := model.NewId() + status2 := model.NewId() + + jobs := []*model.Job{ + { + Id: model.NewId(), + Type: jobType1, + CreateAt: 1000, + Status: status1, + }, + { + Id: model.NewId(), + Type: jobType1, + CreateAt: 999, + Status: status1, + }, + { + Id: model.NewId(), + Type: jobType2, + CreateAt: 1001, + Status: status1, + }, + { + Id: model.NewId(), + Type: jobType1, + CreateAt: 1002, + Status: status2, + }, + } + + for _, job := range jobs { + store.Must(ss.Job().Save(job)) + defer ss.Job().Delete(job.Id) + } + + result := <-ss.Job().GetCountByStatusAndType(status1, jobType1) + assert.Nil(t, result.Err) + assert.EqualValues(t, 2, result.Data.(int64)) + + result = <-ss.Job().GetCountByStatusAndType(status2, jobType2) + assert.Nil(t, result.Err) + assert.EqualValues(t, 0, result.Data.(int64)) + + result = <-ss.Job().GetCountByStatusAndType(status1, jobType2) + assert.Nil(t, result.Err) + assert.EqualValues(t, 1, result.Data.(int64)) + + result = <-ss.Job().GetCountByStatusAndType(status2, jobType1) + assert.Nil(t, result.Err) + assert.EqualValues(t, 1, result.Data.(int64)) +} + +func testJobUpdateOptimistically(t *testing.T, ss store.Store) { + job := &model.Job{ + Id: model.NewId(), + Type: model.JOB_TYPE_DATA_RETENTION, + CreateAt: model.GetMillis(), + Status: model.JOB_STATUS_PENDING, + } + + if result := <-ss.Job().Save(job); result.Err != nil { + t.Fatal(result.Err) + } + defer ss.Job().Delete(job.Id) + + job.LastActivityAt = model.GetMillis() + job.Status = model.JOB_STATUS_IN_PROGRESS + job.Progress = 50 + job.Data = map[string]string{ + "Foo": "Bar", + } + + if result := <-ss.Job().UpdateOptimistically(job, model.JOB_STATUS_SUCCESS); result.Err != nil { + if result.Data.(bool) { + t.Fatal("should have failed due to incorrect old status") + } + } + + time.Sleep(2 * time.Millisecond) + + if result := <-ss.Job().UpdateOptimistically(job, model.JOB_STATUS_PENDING); result.Err != nil { + t.Fatal(result.Err) + } else { + if !result.Data.(bool) { + t.Fatal("Should have successfully updated") + } + + var updatedJob *model.Job + + if result := <-ss.Job().Get(job.Id); result.Err != nil { + t.Fatal(result.Err) + } else { + updatedJob = result.Data.(*model.Job) + } + + if updatedJob.Type != job.Type || updatedJob.CreateAt != job.CreateAt || updatedJob.Status != job.Status || updatedJob.LastActivityAt <= job.LastActivityAt || updatedJob.Progress != job.Progress || updatedJob.Data["Foo"] != job.Data["Foo"] { + t.Fatal("Some update property was not as expected") + } + } + +} + +func testJobUpdateStatusUpdateStatusOptimistically(t *testing.T, ss store.Store) { + job := &model.Job{ + Id: model.NewId(), + Type: model.JOB_TYPE_DATA_RETENTION, + CreateAt: model.GetMillis(), + Status: model.JOB_STATUS_SUCCESS, + } + + var lastUpdateAt int64 + if result := <-ss.Job().Save(job); result.Err != nil { + t.Fatal(result.Err) + } else { + lastUpdateAt = result.Data.(*model.Job).LastActivityAt + } + + defer ss.Job().Delete(job.Id) + + time.Sleep(2 * time.Millisecond) + + if result := <-ss.Job().UpdateStatus(job.Id, model.JOB_STATUS_PENDING); result.Err != nil { + t.Fatal(result.Err) + } else { + received := result.Data.(*model.Job) + if received.Status != model.JOB_STATUS_PENDING { + t.Fatal("status wasn't updated") + } + if received.LastActivityAt <= lastUpdateAt { + t.Fatal("lastActivityAt wasn't updated") + } + lastUpdateAt = received.LastActivityAt + } + + time.Sleep(2 * time.Millisecond) + + if result := <-ss.Job().UpdateStatusOptimistically(job.Id, model.JOB_STATUS_IN_PROGRESS, model.JOB_STATUS_SUCCESS); result.Err != nil { + t.Fatal(result.Err) + } else { + if result.Data.(bool) { + t.Fatal("should be false due to incorrect original status") + } + } + + if result := <-ss.Job().Get(job.Id); result.Err != nil { + t.Fatal(result.Err) + } else { + received := result.Data.(*model.Job) + if received.Status != model.JOB_STATUS_PENDING { + t.Fatal("should still be pending") + } + if received.LastActivityAt != lastUpdateAt { + t.Fatal("last activity at shouldn't have changed") + } + } + + time.Sleep(2 * time.Millisecond) + + if result := <-ss.Job().UpdateStatusOptimistically(job.Id, model.JOB_STATUS_PENDING, model.JOB_STATUS_IN_PROGRESS); result.Err != nil { + t.Fatal(result.Err) + } else { + if !result.Data.(bool) { + t.Fatal("should have succeeded") + } + } + + var startAtSet int64 + if result := <-ss.Job().Get(job.Id); result.Err != nil { + t.Fatal(result.Err) + } else { + received := result.Data.(*model.Job) + if received.Status != model.JOB_STATUS_IN_PROGRESS { + t.Fatal("should be in progress") + } + if received.StartAt == 0 { + t.Fatal("received should have start at set") + } + if received.LastActivityAt <= lastUpdateAt { + t.Fatal("lastActivityAt wasn't updated") + } + lastUpdateAt = received.LastActivityAt + startAtSet = received.StartAt + } + + time.Sleep(2 * time.Millisecond) + + if result := <-ss.Job().UpdateStatusOptimistically(job.Id, model.JOB_STATUS_IN_PROGRESS, model.JOB_STATUS_SUCCESS); result.Err != nil { + t.Fatal(result.Err) + } else { + if !result.Data.(bool) { + t.Fatal("should have succeeded") + } + } + + if result := <-ss.Job().Get(job.Id); result.Err != nil { + t.Fatal(result.Err) + } else { + received := result.Data.(*model.Job) + if received.Status != model.JOB_STATUS_SUCCESS { + t.Fatal("should be success status") + } + if received.StartAt != startAtSet { + t.Fatal("startAt should not have changed") + } + if received.LastActivityAt <= lastUpdateAt { + t.Fatal("lastActivityAt wasn't updated") + } + lastUpdateAt = received.LastActivityAt + } +} + +func testJobDelete(t *testing.T, ss store.Store) { + job := store.Must(ss.Job().Save(&model.Job{ + Id: model.NewId(), + })).(*model.Job) + + if result := <-ss.Job().Delete(job.Id); result.Err != nil { + t.Fatal(result.Err) + } +} diff --git a/store/storetest/license_store.go b/store/storetest/license_store.go new file mode 100644 index 000000000..452d37e7b --- /dev/null +++ b/store/storetest/license_store.go @@ -0,0 +1,56 @@ +// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "testing" + + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" +) + +func TestLicenseStore(t *testing.T, ss store.Store) { + t.Run("Save", func(t *testing.T) { testLicenseStoreSave(t, ss) }) + t.Run("Get", func(t *testing.T) { testLicenseStoreGet(t, ss) }) +} + +func testLicenseStoreSave(t *testing.T, ss store.Store) { + l1 := model.LicenseRecord{} + l1.Id = model.NewId() + l1.Bytes = "junk" + + if err := (<-ss.License().Save(&l1)).Err; err != nil { + t.Fatal("couldn't save license record", err) + } + + if err := (<-ss.License().Save(&l1)).Err; err != nil { + t.Fatal("shouldn't fail on trying to save existing license record", err) + } + + l1.Id = "" + + if err := (<-ss.License().Save(&l1)).Err; err == nil { + t.Fatal("should fail on invalid license", err) + } +} + +func testLicenseStoreGet(t *testing.T, ss store.Store) { + l1 := model.LicenseRecord{} + l1.Id = model.NewId() + l1.Bytes = "junk" + + store.Must(ss.License().Save(&l1)) + + if r := <-ss.License().Get(l1.Id); r.Err != nil { + t.Fatal("couldn't get license", r.Err) + } else { + if r.Data.(*model.LicenseRecord).Bytes != l1.Bytes { + t.Fatal("license bytes didn't match") + } + } + + if err := (<-ss.License().Get("missing")).Err; err == nil { + t.Fatal("should fail on get license", err) + } +} diff --git a/store/storetest/oauth_store.go b/store/storetest/oauth_store.go new file mode 100644 index 000000000..cd5df18da --- /dev/null +++ b/store/storetest/oauth_store.go @@ -0,0 +1,435 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "testing" + + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" +) + +func TestOAuthStore(t *testing.T, ss store.Store) { + t.Run("SaveApp", func(t *testing.T) { testOAuthStoreSaveApp(t, ss) }) + t.Run("GetApp", func(t *testing.T) { testOAuthStoreGetApp(t, ss) }) + t.Run("UpdateApp", func(t *testing.T) { testOAuthStoreUpdateApp(t, ss) }) + t.Run("SaveAccessData", func(t *testing.T) { testOAuthStoreSaveAccessData(t, ss) }) + t.Run("OAuthUpdateAccessData", func(t *testing.T) { testOAuthUpdateAccessData(t, ss) }) + t.Run("GetAccessData", func(t *testing.T) { testOAuthStoreGetAccessData(t, ss) }) + t.Run("RemoveAccessData", func(t *testing.T) { testOAuthStoreRemoveAccessData(t, ss) }) + t.Run("SaveAuthData", func(t *testing.T) { testOAuthStoreSaveAuthData(t, ss) }) + t.Run("GetAuthData", func(t *testing.T) { testOAuthStoreGetAuthData(t, ss) }) + t.Run("RemoveAuthData", func(t *testing.T) { testOAuthStoreRemoveAuthData(t, ss) }) + t.Run("RemoveAuthDataByUser", func(t *testing.T) { testOAuthStoreRemoveAuthDataByUser(t, ss) }) + t.Run("OAuthGetAuthorizedApps", func(t *testing.T) { testOAuthGetAuthorizedApps(t, ss) }) + t.Run("OAuthGetAccessDataByUserForApp", func(t *testing.T) { testOAuthGetAccessDataByUserForApp(t, ss) }) + t.Run("DeleteApp", func(t *testing.T) { testOAuthStoreDeleteApp(t, ss) }) +} + +func testOAuthStoreSaveApp(t *testing.T, ss store.Store) { + a1 := model.OAuthApp{} + a1.CreatorId = model.NewId() + a1.CallbackUrls = []string{"https://nowhere.com"} + a1.Homepage = "https://nowhere.com" + + // Try to save an app that already has an Id + a1.Id = model.NewId() + if err := (<-ss.OAuth().SaveApp(&a1)).Err; err == nil { + t.Fatal("Should have failed, cannot add an OAuth app cannot be save with an Id, it has to be updated") + } + + // Try to save an Invalid App + a1.Id = "" + if err := (<-ss.OAuth().SaveApp(&a1)).Err; err == nil { + t.Fatal("Should have failed, app should be invalid cause it doesn' have a name set") + } + + // Save the app + a1.Id = "" + a1.Name = "TestApp" + model.NewId() + if err := (<-ss.OAuth().SaveApp(&a1)).Err; err != nil { + t.Fatal(err) + } +} + +func testOAuthStoreGetApp(t *testing.T, ss store.Store) { + a1 := model.OAuthApp{} + a1.CreatorId = model.NewId() + a1.Name = "TestApp" + model.NewId() + a1.CallbackUrls = []string{"https://nowhere.com"} + a1.Homepage = "https://nowhere.com" + store.Must(ss.OAuth().SaveApp(&a1)) + + // Lets try to get and app that does not exists + if err := (<-ss.OAuth().GetApp("fake0123456789abcderfgret1")).Err; err == nil { + t.Fatal("Should have failed. App does not exists") + } + + if err := (<-ss.OAuth().GetApp(a1.Id)).Err; err != nil { + t.Fatal(err) + } + + // Lets try and get the app from a user that hasn't created any apps + if result := (<-ss.OAuth().GetAppByUser("fake0123456789abcderfgret1", 0, 1000)); result.Err == nil { + if len(result.Data.([]*model.OAuthApp)) > 0 { + t.Fatal("Should have failed. Fake user hasn't created any apps") + } + } else { + t.Fatal(result.Err) + } + + if err := (<-ss.OAuth().GetAppByUser(a1.CreatorId, 0, 1000)).Err; err != nil { + t.Fatal(err) + } + + if err := (<-ss.OAuth().GetApps(0, 1000)).Err; err != nil { + t.Fatal(err) + } +} + +func testOAuthStoreUpdateApp(t *testing.T, ss store.Store) { + a1 := model.OAuthApp{} + a1.CreatorId = model.NewId() + a1.Name = "TestApp" + model.NewId() + a1.CallbackUrls = []string{"https://nowhere.com"} + a1.Homepage = "https://nowhere.com" + store.Must(ss.OAuth().SaveApp(&a1)) + + // temporarily save the created app id + id := a1.Id + + a1.CreateAt = 1 + a1.ClientSecret = "pwd" + a1.CreatorId = "12345678901234567890123456" + + // Lets update the app by removing the name + a1.Name = "" + if result := <-ss.OAuth().UpdateApp(&a1); result.Err == nil { + t.Fatal("Should have failed. App name is not set") + } + + // Lets not find the app that we are trying to update + a1.Id = "fake0123456789abcderfgret1" + a1.Name = "NewName" + if result := <-ss.OAuth().UpdateApp(&a1); result.Err == nil { + t.Fatal("Should have failed. Not able to find the app") + } + + a1.Id = id + if result := <-ss.OAuth().UpdateApp(&a1); result.Err != nil { + t.Fatal(result.Err) + } else { + ua1 := (result.Data.([2]*model.OAuthApp)[0]) + if ua1.Name != "NewName" { + t.Fatal("name did not update") + } + if ua1.CreateAt == 1 { + t.Fatal("create at should not have updated") + } + if ua1.CreatorId == "12345678901234567890123456" { + t.Fatal("creator id should not have updated") + } + } +} + +func testOAuthStoreSaveAccessData(t *testing.T, ss store.Store) { + a1 := model.AccessData{} + a1.ClientId = model.NewId() + a1.UserId = model.NewId() + + // Lets try and save an incomplete access data + if err := (<-ss.OAuth().SaveAccessData(&a1)).Err; err == nil { + t.Fatal("Should have failed. Access data needs the token") + } + + a1.Token = model.NewId() + a1.RefreshToken = model.NewId() + a1.RedirectUri = "http://example.com" + + if err := (<-ss.OAuth().SaveAccessData(&a1)).Err; err != nil { + t.Fatal(err) + } +} + +func testOAuthUpdateAccessData(t *testing.T, ss store.Store) { + a1 := model.AccessData{} + a1.ClientId = model.NewId() + a1.UserId = model.NewId() + a1.Token = model.NewId() + a1.RefreshToken = model.NewId() + a1.ExpiresAt = model.GetMillis() + a1.RedirectUri = "http://example.com" + store.Must(ss.OAuth().SaveAccessData(&a1)) + + //Try to update to invalid Refresh Token + refreshToken := a1.RefreshToken + a1.RefreshToken = model.NewId() + "123" + if err := (<-ss.OAuth().UpdateAccessData(&a1)).Err; err == nil { + t.Fatal("Should have failed with invalid token") + } + + //Try to update to invalid RedirectUri + a1.RefreshToken = model.NewId() + a1.RedirectUri = "" + if err := (<-ss.OAuth().UpdateAccessData(&a1)).Err; err == nil { + t.Fatal("Should have failed with invalid Redirect URI") + } + + // Should update fine + a1.RedirectUri = "http://example.com" + if result := <-ss.OAuth().UpdateAccessData(&a1); result.Err != nil { + t.Fatal(result.Err) + } else { + ra1 := result.Data.(*model.AccessData) + if ra1.RefreshToken == refreshToken { + t.Fatal("refresh tokens didn't match") + } + } +} + +func testOAuthStoreGetAccessData(t *testing.T, ss store.Store) { + a1 := model.AccessData{} + a1.ClientId = model.NewId() + a1.UserId = model.NewId() + a1.Token = model.NewId() + a1.RefreshToken = model.NewId() + a1.ExpiresAt = model.GetMillis() + a1.RedirectUri = "http://example.com" + store.Must(ss.OAuth().SaveAccessData(&a1)) + + if err := (<-ss.OAuth().GetAccessData("invalidToken")).Err; err == nil { + t.Fatal("Should have failed. There is no data with an invalid token") + } + + if result := <-ss.OAuth().GetAccessData(a1.Token); result.Err != nil { + t.Fatal(result.Err) + } else { + ra1 := result.Data.(*model.AccessData) + if a1.Token != ra1.Token { + t.Fatal("tokens didn't match") + } + } + + if err := (<-ss.OAuth().GetPreviousAccessData(a1.UserId, a1.ClientId)).Err; err != nil { + t.Fatal(err) + } + + if err := (<-ss.OAuth().GetPreviousAccessData("user", "junk")).Err; err != nil { + t.Fatal(err) + } + + // Try to get the Access data using an invalid refresh token + if err := (<-ss.OAuth().GetAccessDataByRefreshToken(a1.Token)).Err; err == nil { + t.Fatal("Should have failed. There is no data with an invalid token") + } + + // Get the Access Data using the refresh token + if result := <-ss.OAuth().GetAccessDataByRefreshToken(a1.RefreshToken); result.Err != nil { + t.Fatal(result.Err) + } else { + ra1 := result.Data.(*model.AccessData) + if a1.RefreshToken != ra1.RefreshToken { + t.Fatal("tokens didn't match") + } + } +} + +func testOAuthStoreRemoveAccessData(t *testing.T, ss store.Store) { + a1 := model.AccessData{} + a1.ClientId = model.NewId() + a1.UserId = model.NewId() + a1.Token = model.NewId() + a1.RefreshToken = model.NewId() + a1.RedirectUri = "http://example.com" + store.Must(ss.OAuth().SaveAccessData(&a1)) + + if err := (<-ss.OAuth().RemoveAccessData(a1.Token)).Err; err != nil { + t.Fatal(err) + } + + if result := (<-ss.OAuth().GetPreviousAccessData(a1.UserId, a1.ClientId)); result.Err != nil { + } else { + if result.Data != nil { + t.Fatal("did not delete access token") + } + } +} + +func testOAuthStoreSaveAuthData(t *testing.T, ss store.Store) { + a1 := model.AuthData{} + a1.ClientId = model.NewId() + a1.UserId = model.NewId() + a1.Code = model.NewId() + a1.RedirectUri = "http://example.com" + if err := (<-ss.OAuth().SaveAuthData(&a1)).Err; err != nil { + t.Fatal(err) + } +} + +func testOAuthStoreGetAuthData(t *testing.T, ss store.Store) { + a1 := model.AuthData{} + a1.ClientId = model.NewId() + a1.UserId = model.NewId() + a1.Code = model.NewId() + a1.RedirectUri = "http://example.com" + store.Must(ss.OAuth().SaveAuthData(&a1)) + + if err := (<-ss.OAuth().GetAuthData(a1.Code)).Err; err != nil { + t.Fatal(err) + } +} + +func testOAuthStoreRemoveAuthData(t *testing.T, ss store.Store) { + a1 := model.AuthData{} + a1.ClientId = model.NewId() + a1.UserId = model.NewId() + a1.Code = model.NewId() + a1.RedirectUri = "http://example.com" + store.Must(ss.OAuth().SaveAuthData(&a1)) + + if err := (<-ss.OAuth().RemoveAuthData(a1.Code)).Err; err != nil { + t.Fatal(err) + } + + if err := (<-ss.OAuth().GetAuthData(a1.Code)).Err; err == nil { + t.Fatal("should have errored - auth code removed") + } +} + +func testOAuthStoreRemoveAuthDataByUser(t *testing.T, ss store.Store) { + a1 := model.AuthData{} + a1.ClientId = model.NewId() + a1.UserId = model.NewId() + a1.Code = model.NewId() + a1.RedirectUri = "http://example.com" + store.Must(ss.OAuth().SaveAuthData(&a1)) + + if err := (<-ss.OAuth().PermanentDeleteAuthDataByUser(a1.UserId)).Err; err != nil { + t.Fatal(err) + } +} + +func testOAuthGetAuthorizedApps(t *testing.T, ss store.Store) { + a1 := model.OAuthApp{} + a1.CreatorId = model.NewId() + a1.Name = "TestApp" + model.NewId() + a1.CallbackUrls = []string{"https://nowhere.com"} + a1.Homepage = "https://nowhere.com" + store.Must(ss.OAuth().SaveApp(&a1)) + + // Lets try and get an Authorized app for a user who hasn't authorized it + if result := <-ss.OAuth().GetAuthorizedApps("fake0123456789abcderfgret1", 0, 1000); result.Err == nil { + if len(result.Data.([]*model.OAuthApp)) > 0 { + t.Fatal("Should have failed. Fake user hasn't authorized the app") + } + } else { + t.Fatal(result.Err) + } + + // allow the app + p := model.Preference{} + p.UserId = a1.CreatorId + p.Category = model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP + p.Name = a1.Id + p.Value = "true" + store.Must(ss.Preference().Save(&model.Preferences{p})) + + if result := <-ss.OAuth().GetAuthorizedApps(a1.CreatorId, 0, 1000); result.Err != nil { + t.Fatal(result.Err) + } else { + apps := result.Data.([]*model.OAuthApp) + if len(apps) == 0 { + t.Fatal("It should have return apps") + } + } +} + +func testOAuthGetAccessDataByUserForApp(t *testing.T, ss store.Store) { + a1 := model.OAuthApp{} + a1.CreatorId = model.NewId() + a1.Name = "TestApp" + model.NewId() + a1.CallbackUrls = []string{"https://nowhere.com"} + a1.Homepage = "https://nowhere.com" + store.Must(ss.OAuth().SaveApp(&a1)) + + // allow the app + p := model.Preference{} + p.UserId = a1.CreatorId + p.Category = model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP + p.Name = a1.Id + p.Value = "true" + store.Must(ss.Preference().Save(&model.Preferences{p})) + + if result := <-ss.OAuth().GetAuthorizedApps(a1.CreatorId, 0, 1000); result.Err != nil { + t.Fatal(result.Err) + } else { + apps := result.Data.([]*model.OAuthApp) + if len(apps) == 0 { + t.Fatal("It should have return apps") + } + } + + // save the token + ad1 := model.AccessData{} + ad1.ClientId = a1.Id + ad1.UserId = a1.CreatorId + ad1.Token = model.NewId() + ad1.RefreshToken = model.NewId() + ad1.RedirectUri = "http://example.com" + + if err := (<-ss.OAuth().SaveAccessData(&ad1)).Err; err != nil { + t.Fatal(err) + } + + if result := <-ss.OAuth().GetAccessDataByUserForApp(a1.CreatorId, a1.Id); result.Err != nil { + t.Fatal(result.Err) + } else { + accessData := result.Data.([]*model.AccessData) + if len(accessData) == 0 { + t.Fatal("It should have return access data") + } + } +} + +func testOAuthStoreDeleteApp(t *testing.T, ss store.Store) { + a1 := model.OAuthApp{} + a1.CreatorId = model.NewId() + a1.Name = "TestApp" + model.NewId() + a1.CallbackUrls = []string{"https://nowhere.com"} + a1.Homepage = "https://nowhere.com" + store.Must(ss.OAuth().SaveApp(&a1)) + + // delete a non-existent app + if err := (<-ss.OAuth().DeleteApp("fakeclientId")).Err; err != nil { + t.Fatal(err) + } + + s1 := model.Session{} + s1.UserId = model.NewId() + s1.Token = model.NewId() + s1.IsOAuth = true + + store.Must(ss.Session().Save(&s1)) + + ad1 := model.AccessData{} + ad1.ClientId = a1.Id + ad1.UserId = a1.CreatorId + ad1.Token = s1.Token + ad1.RefreshToken = model.NewId() + ad1.RedirectUri = "http://example.com" + + store.Must(ss.OAuth().SaveAccessData(&ad1)) + + if err := (<-ss.OAuth().DeleteApp(a1.Id)).Err; err != nil { + t.Fatal(err) + } + + if err := (<-ss.Session().Get(s1.Token)).Err; err == nil { + t.Fatal("should error - session should be deleted") + } + + if err := (<-ss.OAuth().GetAccessData(s1.Token)).Err; err == nil { + t.Fatal("should error - access data should be deleted") + } +} diff --git a/store/storetest/post_store.go b/store/storetest/post_store.go new file mode 100644 index 000000000..f721bed64 --- /dev/null +++ b/store/storetest/post_store.go @@ -0,0 +1,1684 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "fmt" + "strings" + "testing" + "time" + + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" + "github.com/mattermost/mattermost-server/utils" +) + +func TestPostStore(t *testing.T, ss store.Store) { + t.Run("Save", func(t *testing.T) { testPostStoreSave(t, ss) }) + t.Run("Get", func(t *testing.T) { testPostStoreGet(t, ss) }) + t.Run("GetSingle", func(t *testing.T) { testPostStoreGetSingle(t, ss) }) + t.Run("GetEtagCache", func(t *testing.T) { testGetEtagCache(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) }) + t.Run("GetPostsWtihDetails", func(t *testing.T) { testPostStoreGetPostsWtihDetails(t, ss) }) + t.Run("GetPostsBeforeAfter", func(t *testing.T) { testPostStoreGetPostsBeforeAfter(t, ss) }) + t.Run("GetPostsSince", func(t *testing.T) { testPostStoreGetPostsSince(t, ss) }) + t.Run("Search", func(t *testing.T) { testPostStoreSearch(t, ss) }) + t.Run("UserCountsWithPostsByDay", func(t *testing.T) { testUserCountsWithPostsByDay(t, ss) }) + t.Run("PostCountsByDay", func(t *testing.T) { testPostCountsByDay(t, ss) }) + t.Run("GetFlaggedPostsForTeam", func(t *testing.T) { testPostStoreGetFlaggedPostsForTeam(t, ss) }) + t.Run("GetFlaggedPosts", func(t *testing.T) { testPostStoreGetFlaggedPosts(t, ss) }) + t.Run("GetFlaggedPostsForChannel", func(t *testing.T) { testPostStoreGetFlaggedPostsForChannel(t, ss) }) + t.Run("GetPostsCreatedAt", func(t *testing.T) { testPostStoreGetPostsCreatedAt(t, ss) }) + t.Run("Overwrite", func(t *testing.T) { testPostStoreOverwrite(t, ss) }) + t.Run("GetPostsByIds", func(t *testing.T) { testPostStoreGetPostsByIds(t, ss) }) + t.Run("GetPostsBatchForIndexing", func(t *testing.T) { testPostStoreGetPostsBatchForIndexing(t, ss) }) + t.Run("PermanentDeleteBatch", func(t *testing.T) { testPostStorePermanentDeleteBatch(t, ss) }) +} + +func testPostStoreSave(t *testing.T, ss store.Store) { + o1 := model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "b" + + if err := (<-ss.Post().Save(&o1)).Err; err != nil { + t.Fatal("couldn't save item", err) + } + + if err := (<-ss.Post().Save(&o1)).Err; err == nil { + t.Fatal("shouldn't be able to update from save") + } +} + +func testPostStoreGet(t *testing.T, ss store.Store) { + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "b" + + etag1 := (<-ss.Post().GetEtag(o1.ChannelId, false)).Data.(string) + if strings.Index(etag1, model.CurrentVersion+".") != 0 { + t.Fatal("Invalid Etag") + } + + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + + etag2 := (<-ss.Post().GetEtag(o1.ChannelId, false)).Data.(string) + if strings.Index(etag2, fmt.Sprintf("%v.%v", model.CurrentVersion, o1.UpdateAt)) != 0 { + t.Fatal("Invalid Etag") + } + + if r1 := <-ss.Post().Get(o1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.PostList).Posts[o1.Id].CreateAt != o1.CreateAt { + t.Fatal("invalid returned post") + } + } + + if err := (<-ss.Post().Get("123")).Err; err == nil { + t.Fatal("Missing id should have failed") + } + + if err := (<-ss.Post().Get("")).Err; err == nil { + t.Fatal("should fail for blank post ids") + } +} + +func testPostStoreGetSingle(t *testing.T, ss store.Store) { + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "b" + + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + + if r1 := <-ss.Post().GetSingle(o1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.Post).CreateAt != o1.CreateAt { + t.Fatal("invalid returned post") + } + } + + if err := (<-ss.Post().GetSingle("123")).Err; err == nil { + t.Fatal("Missing id should have failed") + } +} + +func testGetEtagCache(t *testing.T, ss store.Store) { + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "b" + + etag1 := (<-ss.Post().GetEtag(o1.ChannelId, true)).Data.(string) + if strings.Index(etag1, model.CurrentVersion+".") != 0 { + t.Fatal("Invalid Etag") + } + + // This one should come from the cache + etag2 := (<-ss.Post().GetEtag(o1.ChannelId, true)).Data.(string) + if strings.Index(etag2, model.CurrentVersion+".") != 0 { + t.Fatal("Invalid Etag") + } + + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + + // We have not invalidated the cache so this should be the same as above + etag3 := (<-ss.Post().GetEtag(o1.ChannelId, true)).Data.(string) + if strings.Index(etag3, etag2) != 0 { + t.Fatal("Invalid Etag") + } + + ss.Post().InvalidateLastPostTimeCache(o1.ChannelId) + + // Invalidated cache so we should get a good result + etag4 := (<-ss.Post().GetEtag(o1.ChannelId, true)).Data.(string) + if strings.Index(etag4, fmt.Sprintf("%v.%v", model.CurrentVersion, o1.UpdateAt)) != 0 { + t.Fatal("Invalid Etag") + } +} + +func testPostStoreUpdate(t *testing.T, ss store.Store) { + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + + o2 := &model.Post{} + o2.ChannelId = o1.ChannelId + o2.UserId = model.NewId() + o2.Message = "zz" + model.NewId() + "CCCCCCCCC" + o2.ParentId = o1.Id + o2.RootId = o1.Id + o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) + + o3 := &model.Post{} + o3.ChannelId = o1.ChannelId + o3.UserId = model.NewId() + o3.Message = "zz" + model.NewId() + "QQQQQQQQQQ" + o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) + + ro1 := (<-ss.Post().Get(o1.Id)).Data.(*model.PostList).Posts[o1.Id] + ro2 := (<-ss.Post().Get(o1.Id)).Data.(*model.PostList).Posts[o2.Id] + ro3 := (<-ss.Post().Get(o3.Id)).Data.(*model.PostList).Posts[o3.Id] + + if ro1.Message != o1.Message { + t.Fatal("Failed to save/get") + } + + o1a := &model.Post{} + *o1a = *ro1 + o1a.Message = ro1.Message + "BBBBBBBBBB" + if result := <-ss.Post().Update(o1a, ro1); result.Err != nil { + t.Fatal(result.Err) + } + + ro1a := (<-ss.Post().Get(o1.Id)).Data.(*model.PostList).Posts[o1.Id] + + if ro1a.Message != o1a.Message { + t.Fatal("Failed to update/get") + } + + o2a := &model.Post{} + *o2a = *ro2 + o2a.Message = ro2.Message + "DDDDDDD" + if result := <-ss.Post().Update(o2a, ro2); result.Err != nil { + t.Fatal(result.Err) + } + + ro2a := (<-ss.Post().Get(o1.Id)).Data.(*model.PostList).Posts[o2.Id] + + if ro2a.Message != o2a.Message { + t.Fatal("Failed to update/get") + } + + o3a := &model.Post{} + *o3a = *ro3 + o3a.Message = ro3.Message + "WWWWWWW" + if result := <-ss.Post().Update(o3a, ro3); result.Err != nil { + t.Fatal(result.Err) + } + + ro3a := (<-ss.Post().Get(o3.Id)).Data.(*model.PostList).Posts[o3.Id] + + if ro3a.Message != o3a.Message && ro3a.Hashtags != o3a.Hashtags { + t.Fatal("Failed to update/get") + } + + o4 := store.Must(ss.Post().Save(&model.Post{ + ChannelId: model.NewId(), + UserId: model.NewId(), + Message: model.NewId(), + Filenames: []string{"test"}, + })).(*model.Post) + + ro4 := (<-ss.Post().Get(o4.Id)).Data.(*model.PostList).Posts[o4.Id] + + o4a := &model.Post{} + *o4a = *ro4 + o4a.Filenames = []string{} + o4a.FileIds = []string{model.NewId()} + if result := <-ss.Post().Update(o4a, ro4); result.Err != nil { + t.Fatal(result.Err) + } + + if ro4a := store.Must(ss.Post().Get(o4.Id)).(*model.PostList).Posts[o4.Id]; len(ro4a.Filenames) != 0 { + t.Fatal("Failed to clear Filenames") + } else if len(ro4a.FileIds) != 1 { + t.Fatal("Failed to set FileIds") + } +} + +func testPostStoreDelete(t *testing.T, ss store.Store) { + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "b" + + etag1 := (<-ss.Post().GetEtag(o1.ChannelId, false)).Data.(string) + if strings.Index(etag1, model.CurrentVersion+".") != 0 { + t.Fatal("Invalid Etag") + } + + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + + if r1 := <-ss.Post().Get(o1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.PostList).Posts[o1.Id].CreateAt != o1.CreateAt { + t.Fatal("invalid returned post") + } + } + + if r2 := <-ss.Post().Delete(o1.Id, model.GetMillis()); r2.Err != nil { + t.Fatal(r2.Err) + } + + if r3 := (<-ss.Post().Get(o1.Id)); r3.Err == nil { + t.Log(r3.Data) + t.Fatal("Missing id should have failed") + } + + etag2 := (<-ss.Post().GetEtag(o1.ChannelId, false)).Data.(string) + if strings.Index(etag2, model.CurrentVersion+".") != 0 { + t.Fatal("Invalid Etag") + } +} + +func testPostStoreDelete1Level(t *testing.T, ss store.Store) { + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "b" + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + + o2 := &model.Post{} + o2.ChannelId = o1.ChannelId + o2.UserId = model.NewId() + o2.Message = "zz" + model.NewId() + "b" + o2.ParentId = o1.Id + o2.RootId = o1.Id + o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) + + if r2 := <-ss.Post().Delete(o1.Id, model.GetMillis()); r2.Err != nil { + t.Fatal(r2.Err) + } + + if r3 := (<-ss.Post().Get(o1.Id)); r3.Err == nil { + t.Fatal("Deleted id should have failed") + } + + if r4 := (<-ss.Post().Get(o2.Id)); r4.Err == nil { + t.Fatal("Deleted id should have failed") + } +} + +func testPostStoreDelete2Level(t *testing.T, ss store.Store) { + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "b" + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + + o2 := &model.Post{} + o2.ChannelId = o1.ChannelId + o2.UserId = model.NewId() + o2.Message = "zz" + model.NewId() + "b" + o2.ParentId = o1.Id + o2.RootId = o1.Id + o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) + + o3 := &model.Post{} + o3.ChannelId = o1.ChannelId + o3.UserId = model.NewId() + o3.Message = "zz" + model.NewId() + "b" + o3.ParentId = o2.Id + o3.RootId = o1.Id + o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) + + o4 := &model.Post{} + o4.ChannelId = model.NewId() + o4.UserId = model.NewId() + o4.Message = "zz" + model.NewId() + "b" + o4 = (<-ss.Post().Save(o4)).Data.(*model.Post) + + if r2 := <-ss.Post().Delete(o1.Id, model.GetMillis()); r2.Err != nil { + t.Fatal(r2.Err) + } + + if r3 := (<-ss.Post().Get(o1.Id)); r3.Err == nil { + t.Fatal("Deleted id should have failed") + } + + if r4 := (<-ss.Post().Get(o2.Id)); r4.Err == nil { + t.Fatal("Deleted id should have failed") + } + + if r5 := (<-ss.Post().Get(o3.Id)); r5.Err == nil { + t.Fatal("Deleted id should have failed") + } + + if r6 := <-ss.Post().Get(o4.Id); r6.Err != nil { + t.Fatal(r6.Err) + } +} + +func testPostStorePermDelete1Level(t *testing.T, ss store.Store) { + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "b" + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + + o2 := &model.Post{} + o2.ChannelId = o1.ChannelId + o2.UserId = model.NewId() + o2.Message = "zz" + model.NewId() + "b" + o2.ParentId = o1.Id + o2.RootId = o1.Id + o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) + + o3 := &model.Post{} + o3.ChannelId = model.NewId() + o3.UserId = model.NewId() + o3.Message = "zz" + model.NewId() + "b" + o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) + + if r2 := <-ss.Post().PermanentDeleteByUser(o2.UserId); r2.Err != nil { + t.Fatal(r2.Err) + } + + if r3 := (<-ss.Post().Get(o1.Id)); r3.Err != nil { + t.Fatal("Deleted id shouldn't have failed") + } + + if r4 := (<-ss.Post().Get(o2.Id)); r4.Err == nil { + t.Fatal("Deleted id should have failed") + } + + if r2 := <-ss.Post().PermanentDeleteByChannel(o3.ChannelId); r2.Err != nil { + t.Fatal(r2.Err) + } + + if r3 := (<-ss.Post().Get(o3.Id)); r3.Err == nil { + t.Fatal("Deleted id should have failed") + } +} + +func testPostStorePermDelete1Level2(t *testing.T, ss store.Store) { + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "b" + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + + o2 := &model.Post{} + o2.ChannelId = o1.ChannelId + o2.UserId = model.NewId() + o2.Message = "zz" + model.NewId() + "b" + o2.ParentId = o1.Id + o2.RootId = o1.Id + o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) + + o3 := &model.Post{} + o3.ChannelId = model.NewId() + o3.UserId = model.NewId() + o3.Message = "zz" + model.NewId() + "b" + o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) + + if r2 := <-ss.Post().PermanentDeleteByUser(o1.UserId); r2.Err != nil { + t.Fatal(r2.Err) + } + + if r3 := (<-ss.Post().Get(o1.Id)); r3.Err == nil { + t.Fatal("Deleted id should have failed") + } + + if r4 := (<-ss.Post().Get(o2.Id)); r4.Err == nil { + t.Fatal("Deleted id should have failed") + } + + if r5 := (<-ss.Post().Get(o3.Id)); r5.Err != nil { + t.Fatal("Deleted id shouldn't have failed") + } +} + +func testPostStoreGetWithChildren(t *testing.T, ss store.Store) { + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "b" + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + + o2 := &model.Post{} + o2.ChannelId = o1.ChannelId + o2.UserId = model.NewId() + o2.Message = "zz" + model.NewId() + "b" + o2.ParentId = o1.Id + o2.RootId = o1.Id + o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) + + o3 := &model.Post{} + o3.ChannelId = o1.ChannelId + o3.UserId = model.NewId() + o3.Message = "zz" + model.NewId() + "b" + o3.ParentId = o2.Id + o3.RootId = o1.Id + o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) + + if r1 := <-ss.Post().Get(o1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + pl := r1.Data.(*model.PostList) + if len(pl.Posts) != 3 { + t.Fatal("invalid returned post") + } + } + + store.Must(ss.Post().Delete(o3.Id, model.GetMillis())) + + if r2 := <-ss.Post().Get(o1.Id); r2.Err != nil { + t.Fatal(r2.Err) + } else { + pl := r2.Data.(*model.PostList) + if len(pl.Posts) != 2 { + t.Fatal("invalid returned post") + } + } + + store.Must(ss.Post().Delete(o2.Id, model.GetMillis())) + + if r3 := <-ss.Post().Get(o1.Id); r3.Err != nil { + t.Fatal(r3.Err) + } else { + pl := r3.Data.(*model.PostList) + if len(pl.Posts) != 1 { + t.Fatal("invalid returned post") + } + } +} + +func testPostStoreGetPostsWtihDetails(t *testing.T, ss store.Store) { + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "b" + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o2 := &model.Post{} + o2.ChannelId = o1.ChannelId + o2.UserId = model.NewId() + o2.Message = "zz" + model.NewId() + "b" + o2.ParentId = o1.Id + o2.RootId = o1.Id + o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o2a := &model.Post{} + o2a.ChannelId = o1.ChannelId + o2a.UserId = model.NewId() + o2a.Message = "zz" + model.NewId() + "b" + o2a.ParentId = o1.Id + o2a.RootId = o1.Id + o2a = (<-ss.Post().Save(o2a)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o3 := &model.Post{} + o3.ChannelId = o1.ChannelId + o3.UserId = model.NewId() + o3.Message = "zz" + model.NewId() + "b" + o3.ParentId = o1.Id + o3.RootId = o1.Id + o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o4 := &model.Post{} + o4.ChannelId = o1.ChannelId + o4.UserId = model.NewId() + o4.Message = "zz" + model.NewId() + "b" + o4 = (<-ss.Post().Save(o4)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o5 := &model.Post{} + o5.ChannelId = o1.ChannelId + o5.UserId = model.NewId() + o5.Message = "zz" + model.NewId() + "b" + o5.ParentId = o4.Id + o5.RootId = o4.Id + o5 = (<-ss.Post().Save(o5)).Data.(*model.Post) + + r1 := (<-ss.Post().GetPosts(o1.ChannelId, 0, 4, false)).Data.(*model.PostList) + + if r1.Order[0] != o5.Id { + t.Fatal("invalid order") + } + + if r1.Order[1] != o4.Id { + t.Fatal("invalid order") + } + + if r1.Order[2] != o3.Id { + t.Fatal("invalid order") + } + + if r1.Order[3] != o2a.Id { + t.Fatal("invalid order") + } + + if len(r1.Posts) != 6 { //the last 4, + o1 (o2a and o3's parent) + o2 (in same thread as o2a and o3) + t.Fatal("wrong size") + } + + if r1.Posts[o1.Id].Message != o1.Message { + t.Fatal("Missing parent") + } + + r2 := (<-ss.Post().GetPosts(o1.ChannelId, 0, 4, true)).Data.(*model.PostList) + + if r2.Order[0] != o5.Id { + t.Fatal("invalid order") + } + + if r2.Order[1] != o4.Id { + t.Fatal("invalid order") + } + + if r2.Order[2] != o3.Id { + t.Fatal("invalid order") + } + + if r2.Order[3] != o2a.Id { + t.Fatal("invalid order") + } + + if len(r2.Posts) != 6 { //the last 4, + o1 (o2a and o3's parent) + o2 (in same thread as o2a and o3) + t.Fatal("wrong size") + } + + if r2.Posts[o1.Id].Message != o1.Message { + t.Fatal("Missing parent") + } +} + +func testPostStoreGetPostsBeforeAfter(t *testing.T, ss store.Store) { + o0 := &model.Post{} + o0.ChannelId = model.NewId() + o0.UserId = model.NewId() + o0.Message = "zz" + model.NewId() + "b" + o0 = (<-ss.Post().Save(o0)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "b" + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o2 := &model.Post{} + o2.ChannelId = o1.ChannelId + o2.UserId = model.NewId() + o2.Message = "zz" + model.NewId() + "b" + o2.ParentId = o1.Id + o2.RootId = o1.Id + o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o2a := &model.Post{} + o2a.ChannelId = o1.ChannelId + o2a.UserId = model.NewId() + o2a.Message = "zz" + model.NewId() + "b" + o2a.ParentId = o1.Id + o2a.RootId = o1.Id + o2a = (<-ss.Post().Save(o2a)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o3 := &model.Post{} + o3.ChannelId = o1.ChannelId + o3.UserId = model.NewId() + o3.Message = "zz" + model.NewId() + "b" + o3.ParentId = o1.Id + o3.RootId = o1.Id + o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o4 := &model.Post{} + o4.ChannelId = o1.ChannelId + o4.UserId = model.NewId() + o4.Message = "zz" + model.NewId() + "b" + o4 = (<-ss.Post().Save(o4)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o5 := &model.Post{} + o5.ChannelId = o1.ChannelId + o5.UserId = model.NewId() + o5.Message = "zz" + model.NewId() + "b" + o5.ParentId = o4.Id + o5.RootId = o4.Id + o5 = (<-ss.Post().Save(o5)).Data.(*model.Post) + + r1 := (<-ss.Post().GetPostsBefore(o1.ChannelId, o1.Id, 4, 0)).Data.(*model.PostList) + + if len(r1.Posts) != 0 { + t.Fatal("Wrong size") + } + + r2 := (<-ss.Post().GetPostsAfter(o1.ChannelId, o1.Id, 4, 0)).Data.(*model.PostList) + + if r2.Order[0] != o4.Id { + t.Fatal("invalid order") + } + + if r2.Order[1] != o3.Id { + t.Fatal("invalid order") + } + + if r2.Order[2] != o2a.Id { + t.Fatal("invalid order") + } + + if r2.Order[3] != o2.Id { + t.Fatal("invalid order") + } + + if len(r2.Posts) != 5 { + t.Fatal("wrong size") + } + + r3 := (<-ss.Post().GetPostsBefore(o3.ChannelId, o3.Id, 2, 0)).Data.(*model.PostList) + + if r3.Order[0] != o2a.Id { + t.Fatal("invalid order") + } + + if r3.Order[1] != o2.Id { + t.Fatal("invalid order") + } + + if len(r3.Posts) != 3 { + t.Fatal("wrong size") + } + + if r3.Posts[o1.Id].Message != o1.Message { + t.Fatal("Missing parent") + } +} + +func testPostStoreGetPostsSince(t *testing.T, ss store.Store) { + o0 := &model.Post{} + o0.ChannelId = model.NewId() + o0.UserId = model.NewId() + o0.Message = "zz" + model.NewId() + "b" + o0 = (<-ss.Post().Save(o0)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "b" + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o2 := &model.Post{} + o2.ChannelId = o1.ChannelId + o2.UserId = model.NewId() + o2.Message = "zz" + model.NewId() + "b" + o2.ParentId = o1.Id + o2.RootId = o1.Id + o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o2a := &model.Post{} + o2a.ChannelId = o1.ChannelId + o2a.UserId = model.NewId() + o2a.Message = "zz" + model.NewId() + "b" + o2a.ParentId = o1.Id + o2a.RootId = o1.Id + o2a = (<-ss.Post().Save(o2a)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o3 := &model.Post{} + o3.ChannelId = o1.ChannelId + o3.UserId = model.NewId() + o3.Message = "zz" + model.NewId() + "b" + o3.ParentId = o1.Id + o3.RootId = o1.Id + o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o4 := &model.Post{} + o4.ChannelId = o1.ChannelId + o4.UserId = model.NewId() + o4.Message = "zz" + model.NewId() + "b" + o4 = (<-ss.Post().Save(o4)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o5 := &model.Post{} + o5.ChannelId = o1.ChannelId + o5.UserId = model.NewId() + o5.Message = "zz" + model.NewId() + "b" + o5.ParentId = o4.Id + o5.RootId = o4.Id + o5 = (<-ss.Post().Save(o5)).Data.(*model.Post) + + r1 := (<-ss.Post().GetPostsSince(o1.ChannelId, o1.CreateAt, false)).Data.(*model.PostList) + + if r1.Order[0] != o5.Id { + t.Fatal("invalid order") + } + + if r1.Order[1] != o4.Id { + t.Fatal("invalid order") + } + + if r1.Order[2] != o3.Id { + t.Fatal("invalid order") + } + + if r1.Order[3] != o2a.Id { + t.Fatal("invalid order") + } + + if len(r1.Posts) != 6 { + t.Fatal("wrong size") + } + + if r1.Posts[o1.Id].Message != o1.Message { + t.Fatal("Missing parent") + } + + r2 := (<-ss.Post().GetPostsSince(o1.ChannelId, o5.UpdateAt, true)).Data.(*model.PostList) + + if len(r2.Order) != 0 { + t.Fatal("wrong size ", len(r2.Posts)) + } +} + +func testPostStoreSearch(t *testing.T, ss store.Store) { + teamId := model.NewId() + userId := model.NewId() + + c1 := &model.Channel{} + c1.TeamId = teamId + c1.DisplayName = "Channel1" + c1.Name = "zz" + model.NewId() + "b" + c1.Type = model.CHANNEL_OPEN + c1 = (<-ss.Channel().Save(c1)).Data.(*model.Channel) + + m1 := model.ChannelMember{} + m1.ChannelId = c1.Id + m1.UserId = userId + m1.NotifyProps = model.GetDefaultChannelNotifyProps() + store.Must(ss.Channel().SaveMember(&m1)) + + c2 := &model.Channel{} + c2.TeamId = teamId + c2.DisplayName = "Channel1" + c2.Name = "zz" + model.NewId() + "b" + c2.Type = model.CHANNEL_OPEN + c2 = (<-ss.Channel().Save(c2)).Data.(*model.Channel) + + o1 := &model.Post{} + o1.ChannelId = c1.Id + o1.UserId = model.NewId() + o1.Message = "corey mattermost new york" + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + + o1a := &model.Post{} + o1a.ChannelId = c1.Id + o1a.UserId = model.NewId() + o1a.Message = "corey mattermost new york" + o1a.Type = model.POST_JOIN_CHANNEL + o1a = (<-ss.Post().Save(o1a)).Data.(*model.Post) + + o2 := &model.Post{} + o2.ChannelId = c1.Id + o2.UserId = model.NewId() + o2.Message = "New Jersey is where John is from" + o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) + + o3 := &model.Post{} + o3.ChannelId = c2.Id + o3.UserId = model.NewId() + o3.Message = "New Jersey is where John is from corey new york" + o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) + + o4 := &model.Post{} + o4.ChannelId = c1.Id + o4.UserId = model.NewId() + o4.Hashtags = "#hashtag" + o4.Message = "(message)blargh" + o4 = (<-ss.Post().Save(o4)).Data.(*model.Post) + + o5 := &model.Post{} + o5.ChannelId = c1.Id + o5.UserId = model.NewId() + o5.Hashtags = "#secret #howdy" + o5 = (<-ss.Post().Save(o5)).Data.(*model.Post) + + r1 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "corey", IsHashtag: false})).Data.(*model.PostList) + if len(r1.Order) != 1 || r1.Order[0] != o1.Id { + t.Fatal("returned wrong search result") + } + + r3 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "new", IsHashtag: false})).Data.(*model.PostList) + if len(r3.Order) != 2 || (r3.Order[0] != o1.Id && r3.Order[1] != o1.Id) { + t.Fatal("returned wrong search result") + } + + r4 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "john", IsHashtag: false})).Data.(*model.PostList) + if len(r4.Order) != 1 || r4.Order[0] != o2.Id { + t.Fatal("returned wrong search result") + } + + r5 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "matter*", IsHashtag: false})).Data.(*model.PostList) + if len(r5.Order) != 1 || r5.Order[0] != o1.Id { + t.Fatal("returned wrong search result") + } + + r6 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "#hashtag", IsHashtag: true})).Data.(*model.PostList) + if len(r6.Order) != 1 || r6.Order[0] != o4.Id { + t.Fatal("returned wrong search result") + } + + r7 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "#secret", IsHashtag: true})).Data.(*model.PostList) + if len(r7.Order) != 1 || r7.Order[0] != o5.Id { + t.Fatal("returned wrong search result") + } + + r8 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "@thisshouldmatchnothing", IsHashtag: true})).Data.(*model.PostList) + if len(r8.Order) != 0 { + t.Fatal("returned wrong search result") + } + + r9 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "mattermost jersey", IsHashtag: false})).Data.(*model.PostList) + if len(r9.Order) != 0 { + t.Fatal("returned wrong search result") + } + + r9a := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "corey new york", IsHashtag: false})).Data.(*model.PostList) + if len(r9a.Order) != 1 { + t.Fatal("returned wrong search result") + } + + r10 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "matter* jer*", IsHashtag: false})).Data.(*model.PostList) + if len(r10.Order) != 0 { + t.Fatal("returned wrong search result") + } + + r11 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "message blargh", IsHashtag: false})).Data.(*model.PostList) + if len(r11.Order) != 1 { + t.Fatal("returned wrong search result") + } + + r12 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "blargh>", IsHashtag: false})).Data.(*model.PostList) + if len(r12.Order) != 1 { + t.Fatal("returned wrong search result") + } + + r13 := (<-ss.Post().Search(teamId, userId, &model.SearchParams{Terms: "Jersey corey", IsHashtag: false, OrTerms: true})).Data.(*model.PostList) + if len(r13.Order) != 2 { + t.Fatal("returned wrong search result") + } +} + +func testUserCountsWithPostsByDay(t *testing.T, ss store.Store) { + t1 := &model.Team{} + t1.DisplayName = "DisplayName" + t1.Name = "zz" + model.NewId() + "b" + t1.Email = model.NewId() + "@nowhere.com" + t1.Type = model.TEAM_OPEN + t1 = store.Must(ss.Team().Save(t1)).(*model.Team) + + c1 := &model.Channel{} + c1.TeamId = t1.Id + c1.DisplayName = "Channel2" + c1.Name = "zz" + model.NewId() + "b" + c1.Type = model.CHANNEL_OPEN + c1 = store.Must(ss.Channel().Save(c1)).(*model.Channel) + + o1 := &model.Post{} + o1.ChannelId = c1.Id + o1.UserId = model.NewId() + o1.CreateAt = utils.MillisFromTime(utils.Yesterday()) + o1.Message = "zz" + model.NewId() + "b" + o1 = store.Must(ss.Post().Save(o1)).(*model.Post) + + o1a := &model.Post{} + o1a.ChannelId = c1.Id + o1a.UserId = model.NewId() + o1a.CreateAt = o1.CreateAt + o1a.Message = "zz" + model.NewId() + "b" + o1a = store.Must(ss.Post().Save(o1a)).(*model.Post) + + o2 := &model.Post{} + o2.ChannelId = c1.Id + o2.UserId = model.NewId() + o2.CreateAt = o1.CreateAt - (1000 * 60 * 60 * 24) + o2.Message = "zz" + model.NewId() + "b" + o2 = store.Must(ss.Post().Save(o2)).(*model.Post) + + o2a := &model.Post{} + o2a.ChannelId = c1.Id + o2a.UserId = o2.UserId + o2a.CreateAt = o1.CreateAt - (1000 * 60 * 60 * 24) + o2a.Message = "zz" + model.NewId() + "b" + o2a = store.Must(ss.Post().Save(o2a)).(*model.Post) + + if r1 := <-ss.Post().AnalyticsUserCountsWithPostsByDay(t1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + row1 := r1.Data.(model.AnalyticsRows)[0] + if row1.Value != 2 { + t.Fatal("wrong value") + } + + row2 := r1.Data.(model.AnalyticsRows)[1] + if row2.Value != 1 { + t.Fatal("wrong value") + } + } +} + +func testPostCountsByDay(t *testing.T, ss store.Store) { + t1 := &model.Team{} + t1.DisplayName = "DisplayName" + t1.Name = "zz" + model.NewId() + "b" + t1.Email = model.NewId() + "@nowhere.com" + t1.Type = model.TEAM_OPEN + t1 = store.Must(ss.Team().Save(t1)).(*model.Team) + + c1 := &model.Channel{} + c1.TeamId = t1.Id + c1.DisplayName = "Channel2" + c1.Name = "zz" + model.NewId() + "b" + c1.Type = model.CHANNEL_OPEN + c1 = store.Must(ss.Channel().Save(c1)).(*model.Channel) + + o1 := &model.Post{} + o1.ChannelId = c1.Id + o1.UserId = model.NewId() + o1.CreateAt = utils.MillisFromTime(utils.Yesterday()) + o1.Message = "zz" + model.NewId() + "b" + o1 = store.Must(ss.Post().Save(o1)).(*model.Post) + + o1a := &model.Post{} + o1a.ChannelId = c1.Id + o1a.UserId = model.NewId() + o1a.CreateAt = o1.CreateAt + o1a.Message = "zz" + model.NewId() + "b" + o1a = store.Must(ss.Post().Save(o1a)).(*model.Post) + + o2 := &model.Post{} + o2.ChannelId = c1.Id + o2.UserId = model.NewId() + o2.CreateAt = o1.CreateAt - (1000 * 60 * 60 * 24 * 2) + o2.Message = "zz" + model.NewId() + "b" + o2 = store.Must(ss.Post().Save(o2)).(*model.Post) + + o2a := &model.Post{} + o2a.ChannelId = c1.Id + o2a.UserId = o2.UserId + o2a.CreateAt = o1.CreateAt - (1000 * 60 * 60 * 24 * 2) + o2a.Message = "zz" + model.NewId() + "b" + o2a = store.Must(ss.Post().Save(o2a)).(*model.Post) + + time.Sleep(1 * time.Second) + + if r1 := <-ss.Post().AnalyticsPostCountsByDay(t1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + row1 := r1.Data.(model.AnalyticsRows)[0] + if row1.Value != 2 { + t.Fatal(row1) + } + + row2 := r1.Data.(model.AnalyticsRows)[1] + if row2.Value != 2 { + t.Fatal("wrong value") + } + } + + if r1 := <-ss.Post().AnalyticsPostCount(t1.Id, false, false); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(int64) != 4 { + t.Fatal("wrong value") + } + } +} + +func testPostStoreGetFlaggedPostsForTeam(t *testing.T, ss store.Store) { + c1 := &model.Channel{} + c1.TeamId = model.NewId() + c1.DisplayName = "Channel1" + c1.Name = "zz" + model.NewId() + "b" + c1.Type = model.CHANNEL_OPEN + c1 = store.Must(ss.Channel().Save(c1)).(*model.Channel) + + o1 := &model.Post{} + o1.ChannelId = c1.Id + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "b" + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o2 := &model.Post{} + o2.ChannelId = o1.ChannelId + o2.UserId = model.NewId() + o2.Message = "zz" + model.NewId() + "b" + o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o3 := &model.Post{} + o3.ChannelId = o1.ChannelId + o3.UserId = model.NewId() + o3.Message = "zz" + model.NewId() + "b" + o3.DeleteAt = 1 + o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o4 := &model.Post{} + o4.ChannelId = model.NewId() + o4.UserId = model.NewId() + o4.Message = "zz" + model.NewId() + "b" + o4 = (<-ss.Post().Save(o4)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + c2 := &model.Channel{} + c2.DisplayName = "DMChannel1" + c2.Name = "zz" + model.NewId() + "b" + c2.Type = model.CHANNEL_DIRECT + + m1 := &model.ChannelMember{} + m1.ChannelId = c2.Id + m1.UserId = o1.UserId + m1.NotifyProps = model.GetDefaultChannelNotifyProps() + + m2 := &model.ChannelMember{} + m2.ChannelId = c2.Id + m2.UserId = model.NewId() + m2.NotifyProps = model.GetDefaultChannelNotifyProps() + + c2 = store.Must(ss.Channel().SaveDirectChannel(c2, m1, m2)).(*model.Channel) + + o5 := &model.Post{} + o5.ChannelId = c2.Id + o5.UserId = m2.UserId + o5.Message = "zz" + model.NewId() + "b" + o5 = (<-ss.Post().Save(o5)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + r1 := (<-ss.Post().GetFlaggedPosts(o1.ChannelId, 0, 2)).Data.(*model.PostList) + + if len(r1.Order) != 0 { + t.Fatal("should be empty") + } + + preferences := model.Preferences{ + { + UserId: o1.UserId, + Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, + Name: o1.Id, + Value: "true", + }, + } + + store.Must(ss.Preference().Save(&preferences)) + + r2 := (<-ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 2)).Data.(*model.PostList) + + if len(r2.Order) != 1 { + t.Fatal("should have 1 post") + } + + preferences = model.Preferences{ + { + UserId: o1.UserId, + Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, + Name: o2.Id, + Value: "true", + }, + } + + store.Must(ss.Preference().Save(&preferences)) + + r3 := (<-ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 1)).Data.(*model.PostList) + + if len(r3.Order) != 1 { + t.Fatal("should have 1 post") + } + + r3 = (<-ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 1, 1)).Data.(*model.PostList) + + if len(r3.Order) != 1 { + t.Fatal("should have 1 post") + } + + r3 = (<-ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 1000, 10)).Data.(*model.PostList) + + if len(r3.Order) != 0 { + t.Fatal("should be empty") + } + + r4 := (<-ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 2)).Data.(*model.PostList) + + if len(r4.Order) != 2 { + t.Fatal("should have 2 posts") + } + + preferences = model.Preferences{ + { + UserId: o1.UserId, + Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, + Name: o3.Id, + Value: "true", + }, + } + + store.Must(ss.Preference().Save(&preferences)) + + r4 = (<-ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 2)).Data.(*model.PostList) + + if len(r4.Order) != 2 { + t.Fatal("should have 2 posts") + } + + preferences = model.Preferences{ + { + UserId: o1.UserId, + Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, + Name: o4.Id, + Value: "true", + }, + } + store.Must(ss.Preference().Save(&preferences)) + + r4 = (<-ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 2)).Data.(*model.PostList) + + if len(r4.Order) != 2 { + t.Fatal("should have 2 posts") + } + + r4 = (<-ss.Post().GetFlaggedPostsForTeam(o1.UserId, model.NewId(), 0, 2)).Data.(*model.PostList) + + if len(r4.Order) != 0 { + t.Fatal("should have 0 posts") + } + + preferences = model.Preferences{ + { + UserId: o1.UserId, + Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, + Name: o5.Id, + Value: "true", + }, + } + store.Must(ss.Preference().Save(&preferences)) + + r4 = (<-ss.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 10)).Data.(*model.PostList) + + if len(r4.Order) != 3 { + t.Fatal("should have 3 posts") + } +} + +func testPostStoreGetFlaggedPosts(t *testing.T, ss store.Store) { + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "b" + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o2 := &model.Post{} + o2.ChannelId = o1.ChannelId + o2.UserId = model.NewId() + o2.Message = "zz" + model.NewId() + "b" + o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o3 := &model.Post{} + o3.ChannelId = o1.ChannelId + o3.UserId = model.NewId() + o3.Message = "zz" + model.NewId() + "b" + o3.DeleteAt = 1 + o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + r1 := (<-ss.Post().GetFlaggedPosts(o1.UserId, 0, 2)).Data.(*model.PostList) + + if len(r1.Order) != 0 { + t.Fatal("should be empty") + } + + preferences := model.Preferences{ + { + UserId: o1.UserId, + Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, + Name: o1.Id, + Value: "true", + }, + } + + store.Must(ss.Preference().Save(&preferences)) + + r2 := (<-ss.Post().GetFlaggedPosts(o1.UserId, 0, 2)).Data.(*model.PostList) + + if len(r2.Order) != 1 { + t.Fatal("should have 1 post") + } + + preferences = model.Preferences{ + { + UserId: o1.UserId, + Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, + Name: o2.Id, + Value: "true", + }, + } + + store.Must(ss.Preference().Save(&preferences)) + + r3 := (<-ss.Post().GetFlaggedPosts(o1.UserId, 0, 1)).Data.(*model.PostList) + + if len(r3.Order) != 1 { + t.Fatal("should have 1 post") + } + + r3 = (<-ss.Post().GetFlaggedPosts(o1.UserId, 1, 1)).Data.(*model.PostList) + + if len(r3.Order) != 1 { + t.Fatal("should have 1 post") + } + + r3 = (<-ss.Post().GetFlaggedPosts(o1.UserId, 1000, 10)).Data.(*model.PostList) + + if len(r3.Order) != 0 { + t.Fatal("should be empty") + } + + r4 := (<-ss.Post().GetFlaggedPosts(o1.UserId, 0, 2)).Data.(*model.PostList) + + if len(r4.Order) != 2 { + t.Fatal("should have 2 posts") + } + + preferences = model.Preferences{ + { + UserId: o1.UserId, + Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, + Name: o3.Id, + Value: "true", + }, + } + + store.Must(ss.Preference().Save(&preferences)) + + r4 = (<-ss.Post().GetFlaggedPosts(o1.UserId, 0, 2)).Data.(*model.PostList) + + if len(r4.Order) != 2 { + t.Fatal("should have 2 posts") + } +} + +func testPostStoreGetFlaggedPostsForChannel(t *testing.T, ss store.Store) { + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "b" + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o2 := &model.Post{} + o2.ChannelId = o1.ChannelId + o2.UserId = model.NewId() + o2.Message = "zz" + model.NewId() + "b" + o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + // deleted post + o3 := &model.Post{} + o3.ChannelId = model.NewId() + o3.UserId = o1.ChannelId + o3.Message = "zz" + model.NewId() + "b" + o3.DeleteAt = 1 + o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o4 := &model.Post{} + o4.ChannelId = model.NewId() + o4.UserId = model.NewId() + o4.Message = "zz" + model.NewId() + "b" + o4 = (<-ss.Post().Save(o4)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + r := (<-ss.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 0, 10)).Data.(*model.PostList) + + if len(r.Order) != 0 { + t.Fatal("should be empty") + } + + preference := model.Preference{ + UserId: o1.UserId, + Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, + Name: o1.Id, + Value: "true", + } + + store.Must(ss.Preference().Save(&model.Preferences{preference})) + + r = (<-ss.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 0, 10)).Data.(*model.PostList) + + if len(r.Order) != 1 { + t.Fatal("should have 1 post") + } + + preference.Name = o2.Id + store.Must(ss.Preference().Save(&model.Preferences{preference})) + + preference.Name = o3.Id + store.Must(ss.Preference().Save(&model.Preferences{preference})) + + r = (<-ss.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 0, 1)).Data.(*model.PostList) + + if len(r.Order) != 1 { + t.Fatal("should have 1 post") + } + + r = (<-ss.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 1, 1)).Data.(*model.PostList) + + if len(r.Order) != 1 { + t.Fatal("should have 1 post") + } + + r = (<-ss.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 1000, 10)).Data.(*model.PostList) + + if len(r.Order) != 0 { + t.Fatal("should be empty") + } + + r = (<-ss.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 0, 10)).Data.(*model.PostList) + + if len(r.Order) != 2 { + t.Fatal("should have 2 posts") + } + + preference.Name = o4.Id + store.Must(ss.Preference().Save(&model.Preferences{preference})) + + r = (<-ss.Post().GetFlaggedPostsForChannel(o1.UserId, o4.ChannelId, 0, 10)).Data.(*model.PostList) + + if len(r.Order) != 1 { + t.Fatal("should have 1 post") + } +} + +func testPostStoreGetPostsCreatedAt(t *testing.T, ss store.Store) { + createTime := model.GetMillis() + + o0 := &model.Post{} + o0.ChannelId = model.NewId() + o0.UserId = model.NewId() + o0.Message = "zz" + model.NewId() + "b" + o0.CreateAt = createTime + o0 = (<-ss.Post().Save(o0)).Data.(*model.Post) + + o1 := &model.Post{} + o1.ChannelId = o0.Id + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "b" + o0.CreateAt = createTime + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o2 := &model.Post{} + o2.ChannelId = o1.ChannelId + o2.UserId = model.NewId() + o2.Message = "zz" + model.NewId() + "b" + o2.ParentId = o1.Id + o2.RootId = o1.Id + o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + o3 := &model.Post{} + o3.ChannelId = model.NewId() + o3.UserId = model.NewId() + o3.Message = "zz" + model.NewId() + "b" + o3.CreateAt = createTime + o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) + time.Sleep(2 * time.Millisecond) + + r1 := (<-ss.Post().GetPostsCreatedAt(o1.ChannelId, createTime)).Data.([]*model.Post) + + if len(r1) != 2 { + t.Fatalf("Got the wrong number of posts.") + } +} + +func testPostStoreOverwrite(t *testing.T, ss store.Store) { + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + + o2 := &model.Post{} + o2.ChannelId = o1.ChannelId + o2.UserId = model.NewId() + o2.Message = "zz" + model.NewId() + "CCCCCCCCC" + o2.ParentId = o1.Id + o2.RootId = o1.Id + o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) + + o3 := &model.Post{} + o3.ChannelId = o1.ChannelId + o3.UserId = model.NewId() + o3.Message = "zz" + model.NewId() + "QQQQQQQQQQ" + o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) + + ro1 := (<-ss.Post().Get(o1.Id)).Data.(*model.PostList).Posts[o1.Id] + ro2 := (<-ss.Post().Get(o1.Id)).Data.(*model.PostList).Posts[o2.Id] + ro3 := (<-ss.Post().Get(o3.Id)).Data.(*model.PostList).Posts[o3.Id] + + if ro1.Message != o1.Message { + t.Fatal("Failed to save/get") + } + + o1a := &model.Post{} + *o1a = *ro1 + o1a.Message = ro1.Message + "BBBBBBBBBB" + if result := <-ss.Post().Overwrite(o1a); result.Err != nil { + t.Fatal(result.Err) + } + + ro1a := (<-ss.Post().Get(o1.Id)).Data.(*model.PostList).Posts[o1.Id] + + if ro1a.Message != o1a.Message { + t.Fatal("Failed to overwrite/get") + } + + o2a := &model.Post{} + *o2a = *ro2 + o2a.Message = ro2.Message + "DDDDDDD" + if result := <-ss.Post().Overwrite(o2a); result.Err != nil { + t.Fatal(result.Err) + } + + ro2a := (<-ss.Post().Get(o1.Id)).Data.(*model.PostList).Posts[o2.Id] + + if ro2a.Message != o2a.Message { + t.Fatal("Failed to overwrite/get") + } + + o3a := &model.Post{} + *o3a = *ro3 + o3a.Message = ro3.Message + "WWWWWWW" + if result := <-ss.Post().Overwrite(o3a); result.Err != nil { + t.Fatal(result.Err) + } + + ro3a := (<-ss.Post().Get(o3.Id)).Data.(*model.PostList).Posts[o3.Id] + + if ro3a.Message != o3a.Message && ro3a.Hashtags != o3a.Hashtags { + t.Fatal("Failed to overwrite/get") + } + + o4 := store.Must(ss.Post().Save(&model.Post{ + ChannelId: model.NewId(), + UserId: model.NewId(), + Message: model.NewId(), + Filenames: []string{"test"}, + })).(*model.Post) + + ro4 := (<-ss.Post().Get(o4.Id)).Data.(*model.PostList).Posts[o4.Id] + + o4a := &model.Post{} + *o4a = *ro4 + o4a.Filenames = []string{} + o4a.FileIds = []string{model.NewId()} + if result := <-ss.Post().Overwrite(o4a); result.Err != nil { + t.Fatal(result.Err) + } + + if ro4a := store.Must(ss.Post().Get(o4.Id)).(*model.PostList).Posts[o4.Id]; len(ro4a.Filenames) != 0 { + t.Fatal("Failed to clear Filenames") + } else if len(ro4a.FileIds) != 1 { + t.Fatal("Failed to set FileIds") + } +} + +func testPostStoreGetPostsByIds(t *testing.T, ss store.Store) { + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + + o2 := &model.Post{} + o2.ChannelId = o1.ChannelId + o2.UserId = model.NewId() + o2.Message = "zz" + model.NewId() + "CCCCCCCCC" + o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) + + o3 := &model.Post{} + o3.ChannelId = o1.ChannelId + o3.UserId = model.NewId() + o3.Message = "zz" + model.NewId() + "QQQQQQQQQQ" + o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) + + ro1 := (<-ss.Post().Get(o1.Id)).Data.(*model.PostList).Posts[o1.Id] + ro2 := (<-ss.Post().Get(o2.Id)).Data.(*model.PostList).Posts[o2.Id] + ro3 := (<-ss.Post().Get(o3.Id)).Data.(*model.PostList).Posts[o3.Id] + + postIds := []string{ + ro1.Id, + ro2.Id, + ro3.Id, + } + + if ro4 := store.Must(ss.Post().GetPostsByIds(postIds)).([]*model.Post); len(ro4) != 3 { + t.Fatalf("Expected 3 posts in results. Got %v", len(ro4)) + } + + store.Must(ss.Post().Delete(ro1.Id, model.GetMillis())) + + if ro5 := store.Must(ss.Post().GetPostsByIds(postIds)).([]*model.Post); len(ro5) != 2 { + t.Fatalf("Expected 2 posts in results. Got %v", len(ro5)) + } +} + +func testPostStoreGetPostsBatchForIndexing(t *testing.T, ss store.Store) { + c1 := &model.Channel{} + c1.TeamId = model.NewId() + c1.DisplayName = "Channel1" + c1.Name = "zz" + model.NewId() + "b" + c1.Type = model.CHANNEL_OPEN + c1 = (<-ss.Channel().Save(c1)).Data.(*model.Channel) + + c2 := &model.Channel{} + c2.TeamId = model.NewId() + c2.DisplayName = "Channel2" + c2.Name = "zz" + model.NewId() + "b" + c2.Type = model.CHANNEL_OPEN + c2 = (<-ss.Channel().Save(c2)).Data.(*model.Channel) + + o1 := &model.Post{} + o1.ChannelId = c1.Id + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + + o2 := &model.Post{} + o2.ChannelId = c2.Id + o2.UserId = model.NewId() + o2.Message = "zz" + model.NewId() + "CCCCCCCCC" + o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) + + o3 := &model.Post{} + o3.ChannelId = c1.Id + o3.UserId = model.NewId() + o3.ParentId = o1.Id + o3.RootId = o1.Id + o3.Message = "zz" + model.NewId() + "QQQQQQQQQQ" + o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) + + if r := store.Must(ss.Post().GetPostsBatchForIndexing(o1.CreateAt, 100)).([]*model.PostForIndexing); len(r) != 3 { + t.Fatalf("Expected 3 posts in results. Got %v", len(r)) + } else { + for _, p := range r { + if p.Id == o1.Id { + if p.TeamId != c1.TeamId { + t.Fatalf("Unexpected team ID") + } + if p.ParentCreateAt != nil { + t.Fatalf("Unexpected parent create at") + } + } else if p.Id == o2.Id { + if p.TeamId != c2.TeamId { + t.Fatalf("Unexpected team ID") + } + if p.ParentCreateAt != nil { + t.Fatalf("Unexpected parent create at") + } + } else if p.Id == o3.Id { + if p.TeamId != c1.TeamId { + t.Fatalf("Unexpected team ID") + } + if *p.ParentCreateAt != o1.CreateAt { + t.Fatalf("Unexpected parent create at") + } + } else { + t.Fatalf("unexpected post returned") + } + } + } +} + +func testPostStorePermanentDeleteBatch(t *testing.T, ss store.Store) { + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" + o1.CreateAt = 1000 + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + + o2 := &model.Post{} + o2.ChannelId = model.NewId() + o2.UserId = model.NewId() + o2.Message = "zz" + model.NewId() + "AAAAAAAAAAA" + o2.CreateAt = 1000 + o2 = (<-ss.Post().Save(o2)).Data.(*model.Post) + + o3 := &model.Post{} + o3.ChannelId = model.NewId() + o3.UserId = model.NewId() + o3.Message = "zz" + model.NewId() + "AAAAAAAAAAA" + o3.CreateAt = 100000 + o3 = (<-ss.Post().Save(o3)).Data.(*model.Post) + + store.Must(ss.Post().PermanentDeleteBatch(2000, 1000)) + + if p := <-ss.Post().Get(o1.Id); p.Err == nil { + t.Fatalf("Should have not found post 1 after purge") + } + + if p := <-ss.Post().Get(o2.Id); p.Err == nil { + t.Fatalf("Should have not found post 2 after purge") + } + + if p := <-ss.Post().Get(o3.Id); p.Err != nil { + t.Fatalf("Should have found post 3 after purge") + } +} diff --git a/store/storetest/preference_store.go b/store/storetest/preference_store.go new file mode 100644 index 000000000..edd0e9549 --- /dev/null +++ b/store/storetest/preference_store.go @@ -0,0 +1,447 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" +) + +func TestPreferenceStore(t *testing.T, ss store.Store) { + t.Run("PreferenceSave", func(t *testing.T) { testPreferenceSave(t, ss) }) + t.Run("PreferenceGet", func(t *testing.T) { testPreferenceGet(t, ss) }) + t.Run("PreferenceGetCategory", func(t *testing.T) { testPreferenceGetCategory(t, ss) }) + t.Run("PreferenceGetAll", func(t *testing.T) { testPreferenceGetAll(t, ss) }) + t.Run("PreferenceDeleteByUser", func(t *testing.T) { testPreferenceDeleteByUser(t, ss) }) + t.Run("IsFeatureEnabled", func(t *testing.T) { testIsFeatureEnabled(t, ss) }) + t.Run("PreferenceDelete", func(t *testing.T) { testPreferenceDelete(t, ss) }) + t.Run("PreferenceDeleteCategory", func(t *testing.T) { testPreferenceDeleteCategory(t, ss) }) + t.Run("PreferenceDeleteCategoryAndName", func(t *testing.T) { testPreferenceDeleteCategoryAndName(t, ss) }) + t.Run("PreferenceCleanupFlagsBatch", func(t *testing.T) { testPreferenceCleanupFlagsBatch(t, ss) }) +} + +func testPreferenceSave(t *testing.T, ss store.Store) { + id := model.NewId() + + preferences := model.Preferences{ + { + UserId: id, + Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, + Name: model.NewId(), + Value: "value1a", + }, + { + UserId: id, + Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, + Name: model.NewId(), + Value: "value1b", + }, + } + if count := store.Must(ss.Preference().Save(&preferences)); count != 2 { + t.Fatal("got incorrect number of rows saved") + } + + for _, preference := range preferences { + if data := store.Must(ss.Preference().Get(preference.UserId, preference.Category, preference.Name)).(model.Preference); preference != data { + t.Fatal("got incorrect preference after first Save") + } + } + + preferences[0].Value = "value2a" + preferences[1].Value = "value2b" + if count := store.Must(ss.Preference().Save(&preferences)); count != 2 { + t.Fatal("got incorrect number of rows saved") + } + + for _, preference := range preferences { + if data := store.Must(ss.Preference().Get(preference.UserId, preference.Category, preference.Name)).(model.Preference); preference != data { + t.Fatal("got incorrect preference after second Save") + } + } +} + +func testPreferenceGet(t *testing.T, ss store.Store) { + userId := model.NewId() + category := model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW + name := model.NewId() + + preferences := model.Preferences{ + { + UserId: userId, + Category: category, + Name: name, + }, + { + UserId: userId, + Category: category, + Name: model.NewId(), + }, + { + UserId: userId, + Category: model.NewId(), + Name: name, + }, + { + UserId: model.NewId(), + Category: category, + Name: name, + }, + } + + store.Must(ss.Preference().Save(&preferences)) + + if result := <-ss.Preference().Get(userId, category, name); result.Err != nil { + t.Fatal(result.Err) + } else if data := result.Data.(model.Preference); data != preferences[0] { + t.Fatal("got incorrect preference") + } + + // make sure getting a missing preference fails + if result := <-ss.Preference().Get(model.NewId(), model.NewId(), model.NewId()); result.Err == nil { + t.Fatal("no error on getting a missing preference") + } +} + +func testPreferenceGetCategory(t *testing.T, ss store.Store) { + userId := model.NewId() + category := model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW + name := model.NewId() + + preferences := model.Preferences{ + { + UserId: userId, + Category: category, + Name: name, + }, + // same user/category, different name + { + UserId: userId, + Category: category, + Name: model.NewId(), + }, + // same user/name, different category + { + UserId: userId, + Category: model.NewId(), + Name: name, + }, + // same name/category, different user + { + UserId: model.NewId(), + Category: category, + Name: name, + }, + } + + store.Must(ss.Preference().Save(&preferences)) + + if result := <-ss.Preference().GetCategory(userId, category); result.Err != nil { + t.Fatal(result.Err) + } else if data := result.Data.(model.Preferences); len(data) != 2 { + t.Fatal("got the wrong number of preferences") + } else if !((data[0] == preferences[0] && data[1] == preferences[1]) || (data[0] == preferences[1] && data[1] == preferences[0])) { + t.Fatal("got incorrect preferences") + } + + // make sure getting a missing preference category doesn't fail + if result := <-ss.Preference().GetCategory(model.NewId(), model.NewId()); result.Err != nil { + t.Fatal(result.Err) + } else if data := result.Data.(model.Preferences); len(data) != 0 { + t.Fatal("shouldn't have got any preferences") + } +} + +func testPreferenceGetAll(t *testing.T, ss store.Store) { + userId := model.NewId() + category := model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW + name := model.NewId() + + preferences := model.Preferences{ + { + UserId: userId, + Category: category, + Name: name, + }, + // same user/category, different name + { + UserId: userId, + Category: category, + Name: model.NewId(), + }, + // same user/name, different category + { + UserId: userId, + Category: model.NewId(), + Name: name, + }, + // same name/category, different user + { + UserId: model.NewId(), + Category: category, + Name: name, + }, + } + + store.Must(ss.Preference().Save(&preferences)) + + if result := <-ss.Preference().GetAll(userId); result.Err != nil { + t.Fatal(result.Err) + } else if data := result.Data.(model.Preferences); len(data) != 3 { + t.Fatal("got the wrong number of preferences") + } else { + for i := 0; i < 3; i++ { + if data[0] != preferences[i] && data[1] != preferences[i] && data[2] != preferences[i] { + t.Fatal("got incorrect preferences") + } + } + } +} + +func testPreferenceDeleteByUser(t *testing.T, ss store.Store) { + userId := model.NewId() + category := model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW + name := model.NewId() + + preferences := model.Preferences{ + { + UserId: userId, + Category: category, + Name: name, + }, + // same user/category, different name + { + UserId: userId, + Category: category, + Name: model.NewId(), + }, + // same user/name, different category + { + UserId: userId, + Category: model.NewId(), + Name: name, + }, + // same name/category, different user + { + UserId: model.NewId(), + Category: category, + Name: name, + }, + } + + store.Must(ss.Preference().Save(&preferences)) + + if result := <-ss.Preference().PermanentDeleteByUser(userId); result.Err != nil { + t.Fatal(result.Err) + } +} + +func testIsFeatureEnabled(t *testing.T, ss store.Store) { + feature1 := "testFeat1" + feature2 := "testFeat2" + feature3 := "testFeat3" + + userId := model.NewId() + category := model.PREFERENCE_CATEGORY_ADVANCED_SETTINGS + + features := model.Preferences{ + { + UserId: userId, + Category: category, + Name: store.FEATURE_TOGGLE_PREFIX + feature1, + Value: "true", + }, + { + UserId: userId, + Category: category, + Name: model.NewId(), + Value: "false", + }, + { + UserId: userId, + Category: model.NewId(), + Name: store.FEATURE_TOGGLE_PREFIX + feature1, + Value: "false", + }, + { + UserId: model.NewId(), + Category: category, + Name: store.FEATURE_TOGGLE_PREFIX + feature2, + Value: "false", + }, + { + UserId: model.NewId(), + Category: category, + Name: store.FEATURE_TOGGLE_PREFIX + feature3, + Value: "foobar", + }, + } + + store.Must(ss.Preference().Save(&features)) + + if result := <-ss.Preference().IsFeatureEnabled(feature1, userId); result.Err != nil { + t.Fatal(result.Err) + } else if data := result.Data.(bool); data != true { + t.Fatalf("got incorrect setting for feature1, %v=%v", true, data) + } + + if result := <-ss.Preference().IsFeatureEnabled(feature2, userId); result.Err != nil { + t.Fatal(result.Err) + } else if data := result.Data.(bool); data != false { + t.Fatalf("got incorrect setting for feature2, %v=%v", false, data) + } + + // make sure we get false if something different than "true" or "false" has been saved to database + if result := <-ss.Preference().IsFeatureEnabled(feature3, userId); result.Err != nil { + t.Fatal(result.Err) + } else if data := result.Data.(bool); data != false { + t.Fatalf("got incorrect setting for feature3, %v=%v", false, data) + } + + // make sure false is returned if a non-existent feature is queried + if result := <-ss.Preference().IsFeatureEnabled("someOtherFeature", userId); result.Err != nil { + t.Fatal(result.Err) + } else if data := result.Data.(bool); data != false { + t.Fatalf("got incorrect setting for non-existent feature 'someOtherFeature', %v=%v", false, data) + } +} + +func testPreferenceDelete(t *testing.T, ss store.Store) { + preference := model.Preference{ + UserId: model.NewId(), + Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, + Name: model.NewId(), + Value: "value1a", + } + + store.Must(ss.Preference().Save(&model.Preferences{preference})) + + if prefs := store.Must(ss.Preference().GetAll(preference.UserId)).(model.Preferences); len([]model.Preference(prefs)) != 1 { + t.Fatal("should've returned 1 preference") + } + + if result := <-ss.Preference().Delete(preference.UserId, preference.Category, preference.Name); result.Err != nil { + t.Fatal(result.Err) + } + + if prefs := store.Must(ss.Preference().GetAll(preference.UserId)).(model.Preferences); len([]model.Preference(prefs)) != 0 { + t.Fatal("should've returned no preferences") + } +} + +func testPreferenceDeleteCategory(t *testing.T, ss store.Store) { + category := model.NewId() + userId := model.NewId() + + preference1 := model.Preference{ + UserId: userId, + Category: category, + Name: model.NewId(), + Value: "value1a", + } + + preference2 := model.Preference{ + UserId: userId, + Category: category, + Name: model.NewId(), + Value: "value1a", + } + + store.Must(ss.Preference().Save(&model.Preferences{preference1, preference2})) + + if prefs := store.Must(ss.Preference().GetAll(userId)).(model.Preferences); len([]model.Preference(prefs)) != 2 { + t.Fatal("should've returned 2 preferences") + } + + if result := <-ss.Preference().DeleteCategory(userId, category); result.Err != nil { + t.Fatal(result.Err) + } + + if prefs := store.Must(ss.Preference().GetAll(userId)).(model.Preferences); len([]model.Preference(prefs)) != 0 { + t.Fatal("should've returned no preferences") + } +} + +func testPreferenceDeleteCategoryAndName(t *testing.T, ss store.Store) { + category := model.NewId() + name := model.NewId() + userId := model.NewId() + userId2 := model.NewId() + + preference1 := model.Preference{ + UserId: userId, + Category: category, + Name: name, + Value: "value1a", + } + + preference2 := model.Preference{ + UserId: userId2, + Category: category, + Name: name, + Value: "value1a", + } + + store.Must(ss.Preference().Save(&model.Preferences{preference1, preference2})) + + if prefs := store.Must(ss.Preference().GetAll(userId)).(model.Preferences); len([]model.Preference(prefs)) != 1 { + t.Fatal("should've returned 1 preference") + } + + if prefs := store.Must(ss.Preference().GetAll(userId2)).(model.Preferences); len([]model.Preference(prefs)) != 1 { + t.Fatal("should've returned 1 preference") + } + + if result := <-ss.Preference().DeleteCategoryAndName(category, name); result.Err != nil { + t.Fatal(result.Err) + } + + if prefs := store.Must(ss.Preference().GetAll(userId)).(model.Preferences); len([]model.Preference(prefs)) != 0 { + t.Fatal("should've returned no preferences") + } + + if prefs := store.Must(ss.Preference().GetAll(userId2)).(model.Preferences); len([]model.Preference(prefs)) != 0 { + t.Fatal("should've returned no preferences") + } +} + +func testPreferenceCleanupFlagsBatch(t *testing.T, ss store.Store) { + category := model.PREFERENCE_CATEGORY_FLAGGED_POST + userId := model.NewId() + + o1 := &model.Post{} + o1.ChannelId = model.NewId() + o1.UserId = userId + o1.Message = "zz" + model.NewId() + "AAAAAAAAAAA" + o1.CreateAt = 1000 + o1 = (<-ss.Post().Save(o1)).Data.(*model.Post) + + preference1 := model.Preference{ + UserId: userId, + Category: category, + Name: o1.Id, + Value: "true", + } + + preference2 := model.Preference{ + UserId: userId, + Category: category, + Name: model.NewId(), + Value: "true", + } + + store.Must(ss.Preference().Save(&model.Preferences{preference1, preference2})) + + result := <-ss.Preference().CleanupFlagsBatch(10000) + assert.Nil(t, result.Err) + + result = <-ss.Preference().Get(userId, category, preference1.Name) + assert.Nil(t, result.Err) + + result = <-ss.Preference().Get(userId, category, preference2.Name) + assert.NotNil(t, result.Err) +} diff --git a/store/storetest/reaction_store.go b/store/storetest/reaction_store.go new file mode 100644 index 000000000..1b5128426 --- /dev/null +++ b/store/storetest/reaction_store.go @@ -0,0 +1,350 @@ +// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "testing" + + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" +) + +func TestReactionStore(t *testing.T, ss store.Store) { + t.Run("ReactionSave", func(t *testing.T) { testReactionSave(t, ss) }) + t.Run("ReactionDelete", func(t *testing.T) { testReactionDelete(t, ss) }) + t.Run("ReactionGetForPost", func(t *testing.T) { testReactionGetForPost(t, ss) }) + t.Run("ReactionDeleteAllWithEmojiName", func(t *testing.T) { testReactionDeleteAllWithEmojiName(t, ss) }) + t.Run("PermanentDeleteBatch", func(t *testing.T) { testReactionStorePermanentDeleteBatch(t, ss) }) +} + +func testReactionSave(t *testing.T, ss store.Store) { + post := store.Must(ss.Post().Save(&model.Post{ + ChannelId: model.NewId(), + UserId: model.NewId(), + })).(*model.Post) + firstUpdateAt := post.UpdateAt + + reaction1 := &model.Reaction{ + UserId: model.NewId(), + PostId: post.Id, + EmojiName: model.NewId(), + } + if result := <-ss.Reaction().Save(reaction1); result.Err != nil { + t.Fatal(result.Err) + } else if saved := result.Data.(*model.Reaction); saved.UserId != reaction1.UserId || + saved.PostId != reaction1.PostId || saved.EmojiName != reaction1.EmojiName { + t.Fatal("should've saved reaction and returned it") + } + + var secondUpdateAt int64 + if postList := store.Must(ss.Post().Get(reaction1.PostId)).(*model.PostList); !postList.Posts[post.Id].HasReactions { + t.Fatal("should've set HasReactions = true on post") + } else if postList.Posts[post.Id].UpdateAt == firstUpdateAt { + t.Fatal("should've marked post as updated when HasReactions changed") + } else { + secondUpdateAt = postList.Posts[post.Id].UpdateAt + } + + if result := <-ss.Reaction().Save(reaction1); result.Err != nil { + t.Log(result.Err) + t.Fatal("should've allowed saving a duplicate reaction") + } + + // different user + reaction2 := &model.Reaction{ + UserId: model.NewId(), + PostId: reaction1.PostId, + EmojiName: reaction1.EmojiName, + } + if result := <-ss.Reaction().Save(reaction2); result.Err != nil { + t.Fatal(result.Err) + } + + if postList := store.Must(ss.Post().Get(reaction2.PostId)).(*model.PostList); postList.Posts[post.Id].UpdateAt != secondUpdateAt { + t.Fatal("shouldn't mark as updated when HasReactions hasn't changed") + } + + // different post + reaction3 := &model.Reaction{ + UserId: reaction1.UserId, + PostId: model.NewId(), + EmojiName: reaction1.EmojiName, + } + if result := <-ss.Reaction().Save(reaction3); result.Err != nil { + t.Fatal(result.Err) + } + + // different emoji + reaction4 := &model.Reaction{ + UserId: reaction1.UserId, + PostId: reaction1.PostId, + EmojiName: model.NewId(), + } + if result := <-ss.Reaction().Save(reaction4); result.Err != nil { + t.Fatal(result.Err) + } + + // invalid reaction + reaction5 := &model.Reaction{ + UserId: reaction1.UserId, + PostId: reaction1.PostId, + } + if result := <-ss.Reaction().Save(reaction5); result.Err == nil { + t.Fatal("should've failed for invalid reaction") + } +} + +func testReactionDelete(t *testing.T, ss store.Store) { + post := store.Must(ss.Post().Save(&model.Post{ + ChannelId: model.NewId(), + UserId: model.NewId(), + })).(*model.Post) + + reaction := &model.Reaction{ + UserId: model.NewId(), + PostId: post.Id, + EmojiName: model.NewId(), + } + + store.Must(ss.Reaction().Save(reaction)) + firstUpdateAt := store.Must(ss.Post().Get(reaction.PostId)).(*model.PostList).Posts[post.Id].UpdateAt + + if result := <-ss.Reaction().Delete(reaction); result.Err != nil { + t.Fatal(result.Err) + } + + if result := <-ss.Reaction().GetForPost(post.Id, false); result.Err != nil { + t.Fatal(result.Err) + } else if len(result.Data.([]*model.Reaction)) != 0 { + t.Fatal("should've deleted reaction") + } + + if postList := store.Must(ss.Post().Get(post.Id)).(*model.PostList); postList.Posts[post.Id].HasReactions { + t.Fatal("should've set HasReactions = false on post") + } else if postList.Posts[post.Id].UpdateAt == firstUpdateAt { + t.Fatal("shouldn't mark as updated when HasReactions has changed after deleting reactions") + } +} + +func testReactionGetForPost(t *testing.T, ss store.Store) { + postId := model.NewId() + + userId := model.NewId() + + reactions := []*model.Reaction{ + { + UserId: userId, + PostId: postId, + EmojiName: "smile", + }, + { + UserId: model.NewId(), + PostId: postId, + EmojiName: "smile", + }, + { + UserId: userId, + PostId: postId, + EmojiName: "sad", + }, + { + UserId: userId, + PostId: model.NewId(), + EmojiName: "angry", + }, + } + + for _, reaction := range reactions { + store.Must(ss.Reaction().Save(reaction)) + } + + if result := <-ss.Reaction().GetForPost(postId, false); result.Err != nil { + t.Fatal(result.Err) + } else if returned := result.Data.([]*model.Reaction); len(returned) != 3 { + t.Fatal("should've returned 3 reactions") + } else { + for _, reaction := range reactions { + found := false + + for _, returnedReaction := range returned { + if returnedReaction.UserId == reaction.UserId && returnedReaction.PostId == reaction.PostId && + returnedReaction.EmojiName == reaction.EmojiName { + found = true + break + } + } + + if !found && reaction.PostId == postId { + t.Fatalf("should've returned reaction for post %v", reaction) + } else if found && reaction.PostId != postId { + t.Fatal("shouldn't have returned reaction for another post") + } + } + } + + // Should return cached item + if result := <-ss.Reaction().GetForPost(postId, true); result.Err != nil { + t.Fatal(result.Err) + } else if returned := result.Data.([]*model.Reaction); len(returned) != 3 { + t.Fatal("should've returned 3 reactions") + } else { + for _, reaction := range reactions { + found := false + + for _, returnedReaction := range returned { + if returnedReaction.UserId == reaction.UserId && returnedReaction.PostId == reaction.PostId && + returnedReaction.EmojiName == reaction.EmojiName { + found = true + break + } + } + + if !found && reaction.PostId == postId { + t.Fatalf("should've returned reaction for post %v", reaction) + } else if found && reaction.PostId != postId { + t.Fatal("shouldn't have returned reaction for another post") + } + } + } +} + +func testReactionDeleteAllWithEmojiName(t *testing.T, ss store.Store) { + emojiToDelete := model.NewId() + + post := store.Must(ss.Post().Save(&model.Post{ + ChannelId: model.NewId(), + UserId: model.NewId(), + })).(*model.Post) + post2 := store.Must(ss.Post().Save(&model.Post{ + ChannelId: model.NewId(), + UserId: model.NewId(), + })).(*model.Post) + post3 := store.Must(ss.Post().Save(&model.Post{ + ChannelId: model.NewId(), + UserId: model.NewId(), + })).(*model.Post) + + userId := model.NewId() + + reactions := []*model.Reaction{ + { + UserId: userId, + PostId: post.Id, + EmojiName: emojiToDelete, + }, + { + UserId: model.NewId(), + PostId: post.Id, + EmojiName: emojiToDelete, + }, + { + UserId: userId, + PostId: post.Id, + EmojiName: "sad", + }, + { + UserId: userId, + PostId: post2.Id, + EmojiName: "angry", + }, + { + UserId: userId, + PostId: post3.Id, + EmojiName: emojiToDelete, + }, + } + + for _, reaction := range reactions { + store.Must(ss.Reaction().Save(reaction)) + } + + if result := <-ss.Reaction().DeleteAllWithEmojiName(emojiToDelete); result.Err != nil { + t.Fatal(result.Err) + } + + // check that the reactions were deleted + if returned := store.Must(ss.Reaction().GetForPost(post.Id, false)).([]*model.Reaction); len(returned) != 1 { + t.Fatal("should've only removed reactions with emoji name") + } else { + for _, reaction := range returned { + if reaction.EmojiName == "smile" { + t.Fatal("should've removed reaction with emoji name") + } + } + } + + if returned := store.Must(ss.Reaction().GetForPost(post2.Id, false)).([]*model.Reaction); len(returned) != 1 { + t.Fatal("should've only removed reactions with emoji name") + } + + if returned := store.Must(ss.Reaction().GetForPost(post3.Id, false)).([]*model.Reaction); len(returned) != 0 { + t.Fatal("should've only removed reactions with emoji name") + } + + // check that the posts are updated + if postList := store.Must(ss.Post().Get(post.Id)).(*model.PostList); !postList.Posts[post.Id].HasReactions { + t.Fatal("post should still have reactions") + } + + if postList := store.Must(ss.Post().Get(post2.Id)).(*model.PostList); !postList.Posts[post2.Id].HasReactions { + t.Fatal("post should still have reactions") + } + + if postList := store.Must(ss.Post().Get(post3.Id)).(*model.PostList); postList.Posts[post3.Id].HasReactions { + t.Fatal("post shouldn't have reactions any more") + } +} + +func testReactionStorePermanentDeleteBatch(t *testing.T, ss store.Store) { + post := store.Must(ss.Post().Save(&model.Post{ + ChannelId: model.NewId(), + UserId: model.NewId(), + })).(*model.Post) + + reactions := []*model.Reaction{ + { + UserId: model.NewId(), + PostId: post.Id, + EmojiName: "sad", + CreateAt: 1000, + }, + { + UserId: model.NewId(), + PostId: post.Id, + EmojiName: "sad", + CreateAt: 1500, + }, + { + UserId: model.NewId(), + PostId: post.Id, + EmojiName: "sad", + CreateAt: 2000, + }, + { + UserId: model.NewId(), + PostId: post.Id, + EmojiName: "sad", + CreateAt: 2000, + }, + } + + // Need to hang on to a reaction to delete later in order to clear the cache, as "allowFromCache" isn't honoured any more. + var lastReaction *model.Reaction + for _, reaction := range reactions { + lastReaction = store.Must(ss.Reaction().Save(reaction)).(*model.Reaction) + } + + if returned := store.Must(ss.Reaction().GetForPost(post.Id, false)).([]*model.Reaction); len(returned) != 4 { + t.Fatal("expected 4 reactions") + } + + store.Must(ss.Reaction().PermanentDeleteBatch(1800, 1000)) + + // This is to force a clear of the cache. + store.Must(ss.Reaction().Delete(lastReaction)) + + if returned := store.Must(ss.Reaction().GetForPost(post.Id, false)).([]*model.Reaction); len(returned) != 1 { + t.Fatalf("expected 1 reaction. Got: %v", len(returned)) + } +} diff --git a/store/storetest/session_store.go b/store/storetest/session_store.go new file mode 100644 index 000000000..3d35b91ad --- /dev/null +++ b/store/storetest/session_store.go @@ -0,0 +1,250 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "testing" + + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" +) + +func TestSessionStore(t *testing.T, ss store.Store) { + t.Run("Save", func(t *testing.T) { testSessionStoreSave(t, ss) }) + t.Run("SessionGet", func(t *testing.T) { testSessionGet(t, ss) }) + t.Run("SessionGetWithDeviceId", func(t *testing.T) { testSessionGetWithDeviceId(t, ss) }) + t.Run("SessionRemove", func(t *testing.T) { testSessionRemove(t, ss) }) + t.Run("SessionRemoveAll", func(t *testing.T) { testSessionRemoveAll(t, ss) }) + t.Run("SessionRemoveByUser", func(t *testing.T) { testSessionRemoveByUser(t, ss) }) + t.Run("SessionRemoveToken", func(t *testing.T) { testSessionRemoveToken(t, ss) }) + t.Run("SessionUpdateDeviceId", func(t *testing.T) { testSessionUpdateDeviceId(t, ss) }) + t.Run("SessionUpdateDeviceId2", func(t *testing.T) { testSessionUpdateDeviceId2(t, ss) }) + t.Run("UpdateLastActivityAt", func(t *testing.T) { testSessionStoreUpdateLastActivityAt(t, ss) }) + t.Run("SessionCount", func(t *testing.T) { testSessionCount(t, ss) }) +} + +func testSessionStoreSave(t *testing.T, ss store.Store) { + s1 := model.Session{} + s1.UserId = model.NewId() + + if err := (<-ss.Session().Save(&s1)).Err; err != nil { + t.Fatal(err) + } +} + +func testSessionGet(t *testing.T, ss store.Store) { + s1 := model.Session{} + s1.UserId = model.NewId() + store.Must(ss.Session().Save(&s1)) + + s2 := model.Session{} + s2.UserId = s1.UserId + store.Must(ss.Session().Save(&s2)) + + s3 := model.Session{} + s3.UserId = s1.UserId + s3.ExpiresAt = 1 + store.Must(ss.Session().Save(&s3)) + + if rs1 := (<-ss.Session().Get(s1.Id)); rs1.Err != nil { + t.Fatal(rs1.Err) + } else { + if rs1.Data.(*model.Session).Id != s1.Id { + t.Fatal("should match") + } + } + + if rs2 := (<-ss.Session().GetSessions(s1.UserId)); rs2.Err != nil { + t.Fatal(rs2.Err) + } else { + if len(rs2.Data.([]*model.Session)) != 2 { + t.Fatal("should match len") + } + } +} + +func testSessionGetWithDeviceId(t *testing.T, ss store.Store) { + s1 := model.Session{} + s1.UserId = model.NewId() + s1.ExpiresAt = model.GetMillis() + 10000 + store.Must(ss.Session().Save(&s1)) + + s2 := model.Session{} + s2.UserId = s1.UserId + s2.DeviceId = model.NewId() + s2.ExpiresAt = model.GetMillis() + 10000 + store.Must(ss.Session().Save(&s2)) + + s3 := model.Session{} + s3.UserId = s1.UserId + s3.ExpiresAt = 1 + s3.DeviceId = model.NewId() + store.Must(ss.Session().Save(&s3)) + + if rs1 := (<-ss.Session().GetSessionsWithActiveDeviceIds(s1.UserId)); rs1.Err != nil { + t.Fatal(rs1.Err) + } else { + if len(rs1.Data.([]*model.Session)) != 1 { + t.Fatal("should match len") + } + } +} + +func testSessionRemove(t *testing.T, ss store.Store) { + s1 := model.Session{} + s1.UserId = model.NewId() + store.Must(ss.Session().Save(&s1)) + + if rs1 := (<-ss.Session().Get(s1.Id)); rs1.Err != nil { + t.Fatal(rs1.Err) + } else { + if rs1.Data.(*model.Session).Id != s1.Id { + t.Fatal("should match") + } + } + + store.Must(ss.Session().Remove(s1.Id)) + + if rs2 := (<-ss.Session().Get(s1.Id)); rs2.Err == nil { + t.Fatal("should have been removed") + } +} + +func testSessionRemoveAll(t *testing.T, ss store.Store) { + s1 := model.Session{} + s1.UserId = model.NewId() + store.Must(ss.Session().Save(&s1)) + + if rs1 := (<-ss.Session().Get(s1.Id)); rs1.Err != nil { + t.Fatal(rs1.Err) + } else { + if rs1.Data.(*model.Session).Id != s1.Id { + t.Fatal("should match") + } + } + + store.Must(ss.Session().RemoveAllSessions()) + + if rs2 := (<-ss.Session().Get(s1.Id)); rs2.Err == nil { + t.Fatal("should have been removed") + } +} + +func testSessionRemoveByUser(t *testing.T, ss store.Store) { + s1 := model.Session{} + s1.UserId = model.NewId() + store.Must(ss.Session().Save(&s1)) + + if rs1 := (<-ss.Session().Get(s1.Id)); rs1.Err != nil { + t.Fatal(rs1.Err) + } else { + if rs1.Data.(*model.Session).Id != s1.Id { + t.Fatal("should match") + } + } + + store.Must(ss.Session().PermanentDeleteSessionsByUser(s1.UserId)) + + if rs2 := (<-ss.Session().Get(s1.Id)); rs2.Err == nil { + t.Fatal("should have been removed") + } +} + +func testSessionRemoveToken(t *testing.T, ss store.Store) { + s1 := model.Session{} + s1.UserId = model.NewId() + store.Must(ss.Session().Save(&s1)) + + if rs1 := (<-ss.Session().Get(s1.Id)); rs1.Err != nil { + t.Fatal(rs1.Err) + } else { + if rs1.Data.(*model.Session).Id != s1.Id { + t.Fatal("should match") + } + } + + store.Must(ss.Session().Remove(s1.Token)) + + if rs2 := (<-ss.Session().Get(s1.Id)); rs2.Err == nil { + t.Fatal("should have been removed") + } + + if rs3 := (<-ss.Session().GetSessions(s1.UserId)); rs3.Err != nil { + t.Fatal(rs3.Err) + } else { + if len(rs3.Data.([]*model.Session)) != 0 { + t.Fatal("should match len") + } + } +} + +func testSessionUpdateDeviceId(t *testing.T, ss store.Store) { + s1 := model.Session{} + s1.UserId = model.NewId() + store.Must(ss.Session().Save(&s1)) + + if rs1 := (<-ss.Session().UpdateDeviceId(s1.Id, model.PUSH_NOTIFY_APPLE+":1234567890", s1.ExpiresAt)); rs1.Err != nil { + t.Fatal(rs1.Err) + } + + s2 := model.Session{} + s2.UserId = model.NewId() + store.Must(ss.Session().Save(&s2)) + + if rs2 := (<-ss.Session().UpdateDeviceId(s2.Id, model.PUSH_NOTIFY_APPLE+":1234567890", s1.ExpiresAt)); rs2.Err != nil { + t.Fatal(rs2.Err) + } +} + +func testSessionUpdateDeviceId2(t *testing.T, ss store.Store) { + s1 := model.Session{} + s1.UserId = model.NewId() + store.Must(ss.Session().Save(&s1)) + + if rs1 := (<-ss.Session().UpdateDeviceId(s1.Id, model.PUSH_NOTIFY_APPLE_REACT_NATIVE+":1234567890", s1.ExpiresAt)); rs1.Err != nil { + t.Fatal(rs1.Err) + } + + s2 := model.Session{} + s2.UserId = model.NewId() + store.Must(ss.Session().Save(&s2)) + + if rs2 := (<-ss.Session().UpdateDeviceId(s2.Id, model.PUSH_NOTIFY_APPLE_REACT_NATIVE+":1234567890", s1.ExpiresAt)); rs2.Err != nil { + t.Fatal(rs2.Err) + } +} + +func testSessionStoreUpdateLastActivityAt(t *testing.T, ss store.Store) { + s1 := model.Session{} + s1.UserId = model.NewId() + store.Must(ss.Session().Save(&s1)) + + if err := (<-ss.Session().UpdateLastActivityAt(s1.Id, 1234567890)).Err; err != nil { + t.Fatal(err) + } + + if r1 := <-ss.Session().Get(s1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.Session).LastActivityAt != 1234567890 { + t.Fatal("LastActivityAt not updated correctly") + } + } + +} + +func testSessionCount(t *testing.T, ss store.Store) { + s1 := model.Session{} + s1.UserId = model.NewId() + s1.ExpiresAt = model.GetMillis() + 100000 + store.Must(ss.Session().Save(&s1)) + + if r1 := <-ss.Session().AnalyticsSessionCount(); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(int64) == 0 { + t.Fatal("should have at least 1 session") + } + } +} diff --git a/store/storetest/status_store.go b/store/storetest/status_store.go new file mode 100644 index 000000000..f2ea0f898 --- /dev/null +++ b/store/storetest/status_store.go @@ -0,0 +1,106 @@ +// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "testing" + + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" +) + +func TestStatusStore(t *testing.T, ss store.Store) { + t.Run("", func(t *testing.T) { testStatusStore(t, ss) }) + t.Run("ActiveUserCount", func(t *testing.T) { testActiveUserCount(t, ss) }) +} + +func testStatusStore(t *testing.T, ss store.Store) { + status := &model.Status{UserId: model.NewId(), Status: model.STATUS_ONLINE, Manual: false, LastActivityAt: 0, ActiveChannel: ""} + + if err := (<-ss.Status().SaveOrUpdate(status)).Err; err != nil { + t.Fatal(err) + } + + status.LastActivityAt = 10 + + if err := (<-ss.Status().SaveOrUpdate(status)).Err; err != nil { + t.Fatal(err) + } + + if err := (<-ss.Status().Get(status.UserId)).Err; err != nil { + t.Fatal(err) + } + + status2 := &model.Status{UserId: model.NewId(), Status: model.STATUS_AWAY, Manual: false, LastActivityAt: 0, ActiveChannel: ""} + if err := (<-ss.Status().SaveOrUpdate(status2)).Err; err != nil { + t.Fatal(err) + } + + status3 := &model.Status{UserId: model.NewId(), Status: model.STATUS_OFFLINE, Manual: false, LastActivityAt: 0, ActiveChannel: ""} + if err := (<-ss.Status().SaveOrUpdate(status3)).Err; err != nil { + t.Fatal(err) + } + + if result := <-ss.Status().GetOnlineAway(); result.Err != nil { + t.Fatal(result.Err) + } else { + statuses := result.Data.([]*model.Status) + for _, status := range statuses { + if status.Status == model.STATUS_OFFLINE { + t.Fatal("should not have returned offline statuses") + } + } + } + + if result := <-ss.Status().GetOnline(); result.Err != nil { + t.Fatal(result.Err) + } else { + statuses := result.Data.([]*model.Status) + for _, status := range statuses { + if status.Status != model.STATUS_ONLINE { + t.Fatal("should not have returned offline statuses") + } + } + } + + if result := <-ss.Status().GetByIds([]string{status.UserId, "junk"}); result.Err != nil { + t.Fatal(result.Err) + } else { + statuses := result.Data.([]*model.Status) + if len(statuses) != 1 { + t.Fatal("should only have 1 status") + } + } + + if err := (<-ss.Status().ResetAll()).Err; err != nil { + t.Fatal(err) + } + + if result := <-ss.Status().Get(status.UserId); result.Err != nil { + t.Fatal(result.Err) + } else { + status := result.Data.(*model.Status) + if status.Status != model.STATUS_OFFLINE { + t.Fatal("should be offline") + } + } + + if result := <-ss.Status().UpdateLastActivityAt(status.UserId, 10); result.Err != nil { + t.Fatal(result.Err) + } +} + +func testActiveUserCount(t *testing.T, ss store.Store) { + status := &model.Status{UserId: model.NewId(), Status: model.STATUS_ONLINE, Manual: false, LastActivityAt: model.GetMillis(), ActiveChannel: ""} + store.Must(ss.Status().SaveOrUpdate(status)) + + if result := <-ss.Status().GetTotalActiveUsersCount(); result.Err != nil { + t.Fatal(result.Err) + } else { + count := result.Data.(int64) + if count <= 0 { + t.Fatal() + } + } +} diff --git a/store/storetest/system_store.go b/store/storetest/system_store.go new file mode 100644 index 000000000..32c39ee41 --- /dev/null +++ b/store/storetest/system_store.go @@ -0,0 +1,58 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "testing" + + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" +) + +func TestSystemStore(t *testing.T, ss store.Store) { + t.Run("", func(t *testing.T) { testSystemStore(t, ss) }) + t.Run("SaveOrUpdate", func(t *testing.T) { testSystemStoreSaveOrUpdate(t, ss) }) +} + +func testSystemStore(t *testing.T, ss store.Store) { + system := &model.System{Name: model.NewId(), Value: "value"} + store.Must(ss.System().Save(system)) + + result := <-ss.System().Get() + systems := result.Data.(model.StringMap) + + if systems[system.Name] != system.Value { + t.Fatal() + } + + system.Value = "value2" + store.Must(ss.System().Update(system)) + + result2 := <-ss.System().Get() + systems2 := result2.Data.(model.StringMap) + + if systems2[system.Name] != system.Value { + t.Fatal() + } + + result3 := <-ss.System().GetByName(system.Name) + rsystem := result3.Data.(*model.System) + if rsystem.Value != system.Value { + t.Fatal() + } +} + +func testSystemStoreSaveOrUpdate(t *testing.T, ss store.Store) { + system := &model.System{Name: model.NewId(), Value: "value"} + + if err := (<-ss.System().SaveOrUpdate(system)).Err; err != nil { + t.Fatal(err) + } + + system.Value = "value2" + + if r := <-ss.System().SaveOrUpdate(system); r.Err != nil { + t.Fatal(r.Err) + } +} diff --git a/store/storetest/team_store.go b/store/storetest/team_store.go new file mode 100644 index 000000000..e48595780 --- /dev/null +++ b/store/storetest/team_store.go @@ -0,0 +1,1010 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "testing" + "time" + + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" + "github.com/mattermost/mattermost-server/utils" +) + +func TestTeamStore(t *testing.T, ss store.Store) { + t.Run("Save", func(t *testing.T) { testTeamStoreSave(t, ss) }) + t.Run("Update", func(t *testing.T) { testTeamStoreUpdate(t, ss) }) + t.Run("UpdateDisplayName", func(t *testing.T) { testTeamStoreUpdateDisplayName(t, ss) }) + t.Run("Get", func(t *testing.T) { testTeamStoreGet(t, ss) }) + t.Run("GetByName", func(t *testing.T) { testTeamStoreGetByName(t, ss) }) + t.Run("SearchByName", func(t *testing.T) { testTeamStoreSearchByName(t, ss) }) + t.Run("SearchAll", func(t *testing.T) { testTeamStoreSearchAll(t, ss) }) + t.Run("SearchOpen", func(t *testing.T) { testTeamStoreSearchOpen(t, ss) }) + t.Run("GetByIniviteId", func(t *testing.T) { testTeamStoreGetByIniviteId(t, ss) }) + t.Run("ByUserId", func(t *testing.T) { testTeamStoreByUserId(t, ss) }) + t.Run("GetAllTeamListing", func(t *testing.T) { testGetAllTeamListing(t, ss) }) + t.Run("GetAllTeamPageListing", func(t *testing.T) { testGetAllTeamPageListing(t, ss) }) + t.Run("Delete", func(t *testing.T) { testDelete(t, ss) }) + t.Run("TeamCount", func(t *testing.T) { testTeamCount(t, ss) }) + t.Run("TeamMembers", func(t *testing.T) { testTeamMembers(t, ss) }) + t.Run("SaveTeamMemberMaxMembers", func(t *testing.T) { testSaveTeamMemberMaxMembers(t, ss) }) + t.Run("GetTeamMember", func(t *testing.T) { testGetTeamMember(t, ss) }) + t.Run("GetTeamMembersByIds", func(t *testing.T) { testGetTeamMembersByIds(t, ss) }) + t.Run("MemberCount", func(t *testing.T) { testTeamStoreMemberCount(t, ss) }) + t.Run("GetChannelUnreadsForAllTeams", func(t *testing.T) { testGetChannelUnreadsForAllTeams(t, ss) }) + t.Run("GetChannelUnreadsForTeam", func(t *testing.T) { testGetChannelUnreadsForTeam(t, ss) }) +} + +func testTeamStoreSave(t *testing.T, ss store.Store) { + o1 := model.Team{} + o1.DisplayName = "DisplayName" + o1.Name = "z-z-z" + model.NewId() + "b" + o1.Email = model.NewId() + "@nowhere.com" + o1.Type = model.TEAM_OPEN + + if err := (<-ss.Team().Save(&o1)).Err; err != nil { + t.Fatal("couldn't save item", err) + } + + if err := (<-ss.Team().Save(&o1)).Err; err == nil { + t.Fatal("shouldn't be able to update from save") + } + + o1.Id = "" + if err := (<-ss.Team().Save(&o1)).Err; err == nil { + t.Fatal("should be unique domain") + } +} + +func testTeamStoreUpdate(t *testing.T, ss store.Store) { + o1 := model.Team{} + o1.DisplayName = "DisplayName" + o1.Name = "z-z-z" + model.NewId() + "b" + o1.Email = model.NewId() + "@nowhere.com" + o1.Type = model.TEAM_OPEN + if err := (<-ss.Team().Save(&o1)).Err; err != nil { + t.Fatal(err) + } + + time.Sleep(100 * time.Millisecond) + + if err := (<-ss.Team().Update(&o1)).Err; err != nil { + t.Fatal(err) + } + + o1.Id = "missing" + if err := (<-ss.Team().Update(&o1)).Err; err == nil { + t.Fatal("Update should have failed because of missing key") + } + + o1.Id = model.NewId() + if err := (<-ss.Team().Update(&o1)).Err; err == nil { + t.Fatal("Update should have faile because id change") + } +} + +func testTeamStoreUpdateDisplayName(t *testing.T, ss store.Store) { + o1 := &model.Team{} + o1.DisplayName = "Display Name" + o1.Name = "z-z-z" + model.NewId() + "b" + o1.Email = model.NewId() + "@nowhere.com" + o1.Type = model.TEAM_OPEN + o1 = (<-ss.Team().Save(o1)).Data.(*model.Team) + + newDisplayName := "NewDisplayName" + + if err := (<-ss.Team().UpdateDisplayName(newDisplayName, o1.Id)).Err; err != nil { + t.Fatal(err) + } + + ro1 := (<-ss.Team().Get(o1.Id)).Data.(*model.Team) + if ro1.DisplayName != newDisplayName { + t.Fatal("DisplayName not updated") + } +} + +func testTeamStoreGet(t *testing.T, ss store.Store) { + o1 := model.Team{} + o1.DisplayName = "DisplayName" + o1.Name = "z-z-z" + model.NewId() + "b" + o1.Email = model.NewId() + "@nowhere.com" + o1.Type = model.TEAM_OPEN + store.Must(ss.Team().Save(&o1)) + + if r1 := <-ss.Team().Get(o1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.Team).ToJson() != o1.ToJson() { + t.Fatal("invalid returned team") + } + } + + if err := (<-ss.Team().Get("")).Err; err == nil { + t.Fatal("Missing id should have failed") + } +} + +func testTeamStoreGetByName(t *testing.T, ss store.Store) { + o1 := model.Team{} + o1.DisplayName = "DisplayName" + o1.Name = "z-z-z" + model.NewId() + "b" + o1.Email = model.NewId() + "@nowhere.com" + o1.Type = model.TEAM_OPEN + + if err := (<-ss.Team().Save(&o1)).Err; err != nil { + t.Fatal(err) + } + + if r1 := <-ss.Team().GetByName(o1.Name); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.Team).ToJson() != o1.ToJson() { + t.Fatal("invalid returned team") + } + } + + if err := (<-ss.Team().GetByName("")).Err; err == nil { + t.Fatal("Missing id should have failed") + } +} + +func testTeamStoreSearchByName(t *testing.T, ss store.Store) { + o1 := model.Team{} + o1.DisplayName = "DisplayName" + var name = "zzz" + model.NewId() + o1.Name = name + "b" + o1.Email = model.NewId() + "@nowhere.com" + o1.Type = model.TEAM_OPEN + + if err := (<-ss.Team().Save(&o1)).Err; err != nil { + t.Fatal(err) + } + + if r1 := <-ss.Team().SearchByName(name); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.([]*model.Team)[0].ToJson() != o1.ToJson() { + t.Fatal("invalid returned team") + } + } +} + +func testTeamStoreSearchAll(t *testing.T, ss store.Store) { + o1 := model.Team{} + o1.DisplayName = "ADisplayName" + model.NewId() + o1.Name = "zz" + model.NewId() + "a" + o1.Email = model.NewId() + "@nowhere.com" + o1.Type = model.TEAM_OPEN + + if err := (<-ss.Team().Save(&o1)).Err; err != nil { + t.Fatal(err) + } + + p2 := model.Team{} + p2.DisplayName = "BDisplayName" + model.NewId() + p2.Name = "b" + model.NewId() + "b" + p2.Email = model.NewId() + "@nowhere.com" + p2.Type = model.TEAM_INVITE + + if err := (<-ss.Team().Save(&p2)).Err; err != nil { + t.Fatal(err) + } + + r1 := <-ss.Team().SearchAll(o1.Name) + if r1.Err != nil { + t.Fatal(r1.Err) + } + if len(r1.Data.([]*model.Team)) != 1 { + t.Fatal("should have returned 1 team") + } + if r1.Data.([]*model.Team)[0].ToJson() != o1.ToJson() { + t.Fatal("invalid returned team") + } + + r1 = <-ss.Team().SearchAll(p2.DisplayName) + if r1.Err != nil { + t.Fatal(r1.Err) + } + if len(r1.Data.([]*model.Team)) != 1 { + t.Fatal("should have returned 1 team") + } + if r1.Data.([]*model.Team)[0].ToJson() != p2.ToJson() { + t.Fatal("invalid returned team") + } + + r1 = <-ss.Team().SearchAll("junk") + if r1.Err != nil { + t.Fatal(r1.Err) + } + if len(r1.Data.([]*model.Team)) != 0 { + t.Fatal("should have not returned a team") + } +} + +func testTeamStoreSearchOpen(t *testing.T, ss store.Store) { + o1 := model.Team{} + o1.DisplayName = "ADisplayName" + model.NewId() + o1.Name = "zz" + model.NewId() + "a" + o1.Email = model.NewId() + "@nowhere.com" + o1.Type = model.TEAM_OPEN + o1.AllowOpenInvite = true + + if err := (<-ss.Team().Save(&o1)).Err; err != nil { + t.Fatal(err) + } + + o2 := model.Team{} + o2.DisplayName = "ADisplayName" + model.NewId() + o2.Name = "zz" + model.NewId() + "a" + o2.Email = model.NewId() + "@nowhere.com" + o2.Type = model.TEAM_OPEN + o2.AllowOpenInvite = false + + if err := (<-ss.Team().Save(&o2)).Err; err != nil { + t.Fatal(err) + } + + p2 := model.Team{} + p2.DisplayName = "BDisplayName" + model.NewId() + p2.Name = "b" + model.NewId() + "b" + p2.Email = model.NewId() + "@nowhere.com" + p2.Type = model.TEAM_INVITE + p2.AllowOpenInvite = true + + if err := (<-ss.Team().Save(&p2)).Err; err != nil { + t.Fatal(err) + } + + r1 := <-ss.Team().SearchOpen(o1.Name) + if r1.Err != nil { + t.Fatal(r1.Err) + } + if len(r1.Data.([]*model.Team)) != 1 { + t.Fatal("should have returned 1 team") + } + if r1.Data.([]*model.Team)[0].ToJson() != o1.ToJson() { + t.Fatal("invalid returned team") + } + + r1 = <-ss.Team().SearchOpen(o1.DisplayName) + if r1.Err != nil { + t.Fatal(r1.Err) + } + if len(r1.Data.([]*model.Team)) != 1 { + t.Fatal("should have returned 1 team") + } + if r1.Data.([]*model.Team)[0].ToJson() != o1.ToJson() { + t.Fatal("invalid returned team") + } + + r1 = <-ss.Team().SearchOpen(p2.Name) + if r1.Err != nil { + t.Fatal(r1.Err) + } + if len(r1.Data.([]*model.Team)) != 0 { + t.Fatal("should have not returned a team") + } + + r1 = <-ss.Team().SearchOpen(p2.DisplayName) + if r1.Err != nil { + t.Fatal(r1.Err) + } + if len(r1.Data.([]*model.Team)) != 0 { + t.Fatal("should have not returned a team") + } + + r1 = <-ss.Team().SearchOpen("junk") + if r1.Err != nil { + t.Fatal(r1.Err) + } + if len(r1.Data.([]*model.Team)) != 0 { + t.Fatal("should have not returned a team") + } + + r1 = <-ss.Team().SearchOpen(o2.DisplayName) + if r1.Err != nil { + t.Fatal(r1.Err) + } + if len(r1.Data.([]*model.Team)) != 0 { + t.Fatal("should have not returned a team") + } +} + +func testTeamStoreGetByIniviteId(t *testing.T, ss store.Store) { + o1 := model.Team{} + o1.DisplayName = "DisplayName" + o1.Name = "z-z-z" + model.NewId() + "b" + o1.Email = model.NewId() + "@nowhere.com" + o1.Type = model.TEAM_OPEN + o1.InviteId = model.NewId() + + if err := (<-ss.Team().Save(&o1)).Err; err != nil { + t.Fatal(err) + } + + o2 := model.Team{} + o2.DisplayName = "DisplayName" + o2.Name = "zz" + model.NewId() + "b" + o2.Email = model.NewId() + "@nowhere.com" + o2.Type = model.TEAM_OPEN + + if err := (<-ss.Team().Save(&o2)).Err; err != nil { + t.Fatal(err) + } + + if r1 := <-ss.Team().GetByInviteId(o1.InviteId); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.Team).ToJson() != o1.ToJson() { + t.Fatal("invalid returned team") + } + } + + o2.InviteId = "" + <-ss.Team().Update(&o2) + + if r1 := <-ss.Team().GetByInviteId(o2.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.Team).Id != o2.Id { + t.Fatal("invalid returned team") + } + } + + if err := (<-ss.Team().GetByInviteId("")).Err; err == nil { + t.Fatal("Missing id should have failed") + } +} + +func testTeamStoreByUserId(t *testing.T, ss store.Store) { + o1 := &model.Team{} + o1.DisplayName = "DisplayName" + o1.Name = "z-z-z" + model.NewId() + "b" + o1.Email = model.NewId() + "@nowhere.com" + o1.Type = model.TEAM_OPEN + o1.InviteId = model.NewId() + o1 = store.Must(ss.Team().Save(o1)).(*model.Team) + + m1 := &model.TeamMember{TeamId: o1.Id, UserId: model.NewId()} + store.Must(ss.Team().SaveMember(m1)) + + if r1 := <-ss.Team().GetTeamsByUserId(m1.UserId); r1.Err != nil { + t.Fatal(r1.Err) + } else { + teams := r1.Data.([]*model.Team) + if len(teams) == 0 { + t.Fatal("Should return a team") + } + + if teams[0].Id != o1.Id { + t.Fatal("should be a member") + } + + } +} + +func testGetAllTeamListing(t *testing.T, ss store.Store) { + o1 := model.Team{} + o1.DisplayName = "DisplayName" + o1.Name = "z-z-z" + model.NewId() + "b" + o1.Email = model.NewId() + "@nowhere.com" + o1.Type = model.TEAM_OPEN + o1.AllowOpenInvite = true + store.Must(ss.Team().Save(&o1)) + + o2 := model.Team{} + o2.DisplayName = "DisplayName" + o2.Name = "zz" + model.NewId() + "b" + o2.Email = model.NewId() + "@nowhere.com" + o2.Type = model.TEAM_OPEN + store.Must(ss.Team().Save(&o2)) + + o3 := model.Team{} + o3.DisplayName = "DisplayName" + o3.Name = "z-z-z" + model.NewId() + "b" + o3.Email = model.NewId() + "@nowhere.com" + o3.Type = model.TEAM_INVITE + o3.AllowOpenInvite = true + store.Must(ss.Team().Save(&o3)) + + o4 := model.Team{} + o4.DisplayName = "DisplayName" + o4.Name = "zz" + model.NewId() + "b" + o4.Email = model.NewId() + "@nowhere.com" + o4.Type = model.TEAM_INVITE + store.Must(ss.Team().Save(&o4)) + + if r1 := <-ss.Team().GetAllTeamListing(); r1.Err != nil { + t.Fatal(r1.Err) + } else { + teams := r1.Data.([]*model.Team) + + for _, team := range teams { + if !team.AllowOpenInvite { + t.Fatal("should have returned team with AllowOpenInvite as true") + } + } + + if len(teams) == 0 { + t.Fatal("failed team listing") + } + } +} + +func testGetAllTeamPageListing(t *testing.T, ss store.Store) { + o1 := model.Team{} + o1.DisplayName = "DisplayName" + o1.Name = "z-z-z" + model.NewId() + "b" + o1.Email = model.NewId() + "@nowhere.com" + o1.Type = model.TEAM_OPEN + o1.AllowOpenInvite = true + store.Must(ss.Team().Save(&o1)) + + o2 := model.Team{} + o2.DisplayName = "DisplayName" + o2.Name = "zz" + model.NewId() + "b" + o2.Email = model.NewId() + "@nowhere.com" + o2.Type = model.TEAM_OPEN + o2.AllowOpenInvite = false + store.Must(ss.Team().Save(&o2)) + + o3 := model.Team{} + o3.DisplayName = "DisplayName" + o3.Name = "z-z-z" + model.NewId() + "b" + o3.Email = model.NewId() + "@nowhere.com" + o3.Type = model.TEAM_INVITE + o3.AllowOpenInvite = true + store.Must(ss.Team().Save(&o3)) + + o4 := model.Team{} + o4.DisplayName = "DisplayName" + o4.Name = "zz" + model.NewId() + "b" + o4.Email = model.NewId() + "@nowhere.com" + o4.Type = model.TEAM_INVITE + o4.AllowOpenInvite = false + store.Must(ss.Team().Save(&o4)) + + if r1 := <-ss.Team().GetAllTeamPageListing(0, 10); r1.Err != nil { + t.Fatal(r1.Err) + } else { + teams := r1.Data.([]*model.Team) + + for _, team := range teams { + if !team.AllowOpenInvite { + t.Fatal("should have returned team with AllowOpenInvite as true") + } + } + + if len(teams) > 10 { + t.Fatal("should have returned max of 10 teams") + } + } + + o5 := model.Team{} + o5.DisplayName = "DisplayName" + o5.Name = "z-z-z" + model.NewId() + "b" + o5.Email = model.NewId() + "@nowhere.com" + o5.Type = model.TEAM_OPEN + o5.AllowOpenInvite = true + store.Must(ss.Team().Save(&o5)) + + if r1 := <-ss.Team().GetAllTeamPageListing(0, 4); r1.Err != nil { + t.Fatal(r1.Err) + } else { + teams := r1.Data.([]*model.Team) + + for _, team := range teams { + if !team.AllowOpenInvite { + t.Fatal("should have returned team with AllowOpenInvite as true") + } + } + + if len(teams) > 4 { + t.Fatal("should have returned max of 4 teams") + } + } + + if r1 := <-ss.Team().GetAllTeamPageListing(1, 1); r1.Err != nil { + t.Fatal(r1.Err) + } else { + teams := r1.Data.([]*model.Team) + + for _, team := range teams { + if !team.AllowOpenInvite { + t.Fatal("should have returned team with AllowOpenInvite as true") + } + } + + if len(teams) > 1 { + t.Fatal("should have returned max of 1 team") + } + } +} + +func testDelete(t *testing.T, ss store.Store) { + o1 := model.Team{} + o1.DisplayName = "DisplayName" + o1.Name = "z-z-z" + model.NewId() + "b" + o1.Email = model.NewId() + "@nowhere.com" + o1.Type = model.TEAM_OPEN + o1.AllowOpenInvite = true + store.Must(ss.Team().Save(&o1)) + + o2 := model.Team{} + o2.DisplayName = "DisplayName" + o2.Name = "zz" + model.NewId() + "b" + o2.Email = model.NewId() + "@nowhere.com" + o2.Type = model.TEAM_OPEN + store.Must(ss.Team().Save(&o2)) + + if r1 := <-ss.Team().PermanentDelete(o1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } +} + +func testTeamCount(t *testing.T, ss store.Store) { + o1 := model.Team{} + o1.DisplayName = "DisplayName" + o1.Name = "z-z-z" + model.NewId() + "b" + o1.Email = model.NewId() + "@nowhere.com" + o1.Type = model.TEAM_OPEN + o1.AllowOpenInvite = true + store.Must(ss.Team().Save(&o1)) + + if r1 := <-ss.Team().AnalyticsTeamCount(); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(int64) == 0 { + t.Fatal("should be at least 1 team") + } + } +} + +func testTeamMembers(t *testing.T, ss store.Store) { + teamId1 := model.NewId() + teamId2 := model.NewId() + + m1 := &model.TeamMember{TeamId: teamId1, UserId: model.NewId()} + m2 := &model.TeamMember{TeamId: teamId1, UserId: model.NewId()} + m3 := &model.TeamMember{TeamId: teamId2, UserId: model.NewId()} + + if r1 := <-ss.Team().SaveMember(m1); r1.Err != nil { + t.Fatal(r1.Err) + } + + store.Must(ss.Team().SaveMember(m2)) + store.Must(ss.Team().SaveMember(m3)) + + if r1 := <-ss.Team().GetMembers(teamId1, 0, 100); r1.Err != nil { + t.Fatal(r1.Err) + } else { + ms := r1.Data.([]*model.TeamMember) + + if len(ms) != 2 { + t.Fatal() + } + } + + if r1 := <-ss.Team().GetMembers(teamId2, 0, 100); r1.Err != nil { + t.Fatal(r1.Err) + } else { + ms := r1.Data.([]*model.TeamMember) + + if len(ms) != 1 { + t.Fatal() + } + + if ms[0].UserId != m3.UserId { + t.Fatal() + + } + } + + if r1 := <-ss.Team().GetTeamsForUser(m1.UserId); r1.Err != nil { + t.Fatal(r1.Err) + } else { + ms := r1.Data.([]*model.TeamMember) + + if len(ms) != 1 { + t.Fatal() + } + + if ms[0].TeamId != m1.TeamId { + t.Fatal() + + } + } + + if r1 := <-ss.Team().RemoveMember(teamId1, m1.UserId); r1.Err != nil { + t.Fatal(r1.Err) + } + + if r1 := <-ss.Team().GetMembers(teamId1, 0, 100); r1.Err != nil { + t.Fatal(r1.Err) + } else { + ms := r1.Data.([]*model.TeamMember) + + if len(ms) != 1 { + t.Fatal() + } + + if ms[0].UserId != m2.UserId { + t.Fatal() + + } + } + + store.Must(ss.Team().SaveMember(m1)) + + if r1 := <-ss.Team().RemoveAllMembersByTeam(teamId1); r1.Err != nil { + t.Fatal(r1.Err) + } + + if r1 := <-ss.Team().GetMembers(teamId1, 0, 100); r1.Err != nil { + t.Fatal(r1.Err) + } else { + ms := r1.Data.([]*model.TeamMember) + + if len(ms) != 0 { + t.Fatal() + } + } + + uid := model.NewId() + m4 := &model.TeamMember{TeamId: teamId1, UserId: uid} + m5 := &model.TeamMember{TeamId: teamId2, UserId: uid} + store.Must(ss.Team().SaveMember(m4)) + store.Must(ss.Team().SaveMember(m5)) + + if r1 := <-ss.Team().GetTeamsForUser(uid); r1.Err != nil { + t.Fatal(r1.Err) + } else { + ms := r1.Data.([]*model.TeamMember) + + if len(ms) != 2 { + t.Fatal() + } + } + + if r1 := <-ss.Team().RemoveAllMembersByUser(uid); r1.Err != nil { + t.Fatal(r1.Err) + } + + if r1 := <-ss.Team().GetTeamsForUser(m1.UserId); r1.Err != nil { + t.Fatal(r1.Err) + } else { + ms := r1.Data.([]*model.TeamMember) + + if len(ms) != 0 { + t.Fatal() + } + } +} + +func testSaveTeamMemberMaxMembers(t *testing.T, ss store.Store) { + MaxUsersPerTeam := *utils.Cfg.TeamSettings.MaxUsersPerTeam + defer func() { + *utils.Cfg.TeamSettings.MaxUsersPerTeam = MaxUsersPerTeam + }() + *utils.Cfg.TeamSettings.MaxUsersPerTeam = 5 + + team := store.Must(ss.Team().Save(&model.Team{ + DisplayName: "DisplayName", + Name: "z-z-z" + model.NewId() + "b", + Type: model.TEAM_OPEN, + })).(*model.Team) + defer func() { + <-ss.Team().PermanentDelete(team.Id) + }() + + userIds := make([]string, *utils.Cfg.TeamSettings.MaxUsersPerTeam) + + for i := 0; i < *utils.Cfg.TeamSettings.MaxUsersPerTeam; i++ { + userIds[i] = store.Must(ss.User().Save(&model.User{ + Username: model.NewId(), + Email: model.NewId(), + })).(*model.User).Id + + defer func(userId string) { + <-ss.User().PermanentDelete(userId) + }(userIds[i]) + + store.Must(ss.Team().SaveMember(&model.TeamMember{ + TeamId: team.Id, + UserId: userIds[i], + })) + + defer func(userId string) { + <-ss.Team().RemoveMember(team.Id, userId) + }(userIds[i]) + } + + if result := <-ss.Team().GetTotalMemberCount(team.Id); result.Err != nil { + t.Fatal(result.Err) + } else if count := result.Data.(int64); int(count) != *utils.Cfg.TeamSettings.MaxUsersPerTeam { + t.Fatalf("should start with 5 team members, had %v instead", count) + } + + newUserId := store.Must(ss.User().Save(&model.User{ + Username: model.NewId(), + Email: model.NewId(), + })).(*model.User).Id + defer func() { + <-ss.User().PermanentDelete(newUserId) + }() + + if result := <-ss.Team().SaveMember(&model.TeamMember{ + TeamId: team.Id, + UserId: newUserId, + }); result.Err == nil { + t.Fatal("shouldn't be able to save member when at maximum members per team") + } + + if result := <-ss.Team().GetTotalMemberCount(team.Id); result.Err != nil { + t.Fatal(result.Err) + } else if count := result.Data.(int64); int(count) != *utils.Cfg.TeamSettings.MaxUsersPerTeam { + t.Fatalf("should still have 5 team members, had %v instead", count) + } + + // Leaving the team from the UI sets DeleteAt instead of using TeamStore.RemoveMember + store.Must(ss.Team().UpdateMember(&model.TeamMember{ + TeamId: team.Id, + UserId: userIds[0], + DeleteAt: 1234, + })) + + if result := <-ss.Team().GetTotalMemberCount(team.Id); result.Err != nil { + t.Fatal(result.Err) + } else if count := result.Data.(int64); int(count) != *utils.Cfg.TeamSettings.MaxUsersPerTeam-1 { + t.Fatalf("should now only have 4 team members, had %v instead", count) + } + + if result := <-ss.Team().SaveMember(&model.TeamMember{TeamId: team.Id, UserId: newUserId}); result.Err != nil { + t.Fatal("should've been able to save new member after deleting one", result.Err) + } else { + defer func(userId string) { + <-ss.Team().RemoveMember(team.Id, userId) + }(newUserId) + } + + if result := <-ss.Team().GetTotalMemberCount(team.Id); result.Err != nil { + t.Fatal(result.Err) + } else if count := result.Data.(int64); int(count) != *utils.Cfg.TeamSettings.MaxUsersPerTeam { + t.Fatalf("should have 5 team members again, had %v instead", count) + } + + // Deactivating a user should make them stop counting against max members + user2 := store.Must(ss.User().Get(userIds[1])).(*model.User) + user2.DeleteAt = 1234 + store.Must(ss.User().Update(user2, true)) + + newUserId2 := store.Must(ss.User().Save(&model.User{ + Username: model.NewId(), + Email: model.NewId(), + })).(*model.User).Id + if result := <-ss.Team().SaveMember(&model.TeamMember{TeamId: team.Id, UserId: newUserId2}); result.Err != nil { + t.Fatal("should've been able to save new member after deleting one", result.Err) + } else { + defer func(userId string) { + <-ss.Team().RemoveMember(team.Id, userId) + }(newUserId2) + } +} + +func testGetTeamMember(t *testing.T, ss store.Store) { + teamId1 := model.NewId() + + m1 := &model.TeamMember{TeamId: teamId1, UserId: model.NewId()} + store.Must(ss.Team().SaveMember(m1)) + + if r := <-ss.Team().GetMember(m1.TeamId, m1.UserId); r.Err != nil { + t.Fatal(r.Err) + } else { + rm1 := r.Data.(*model.TeamMember) + + if rm1.TeamId != m1.TeamId { + t.Fatal("bad team id") + } + + if rm1.UserId != m1.UserId { + t.Fatal("bad user id") + } + } + + if r := <-ss.Team().GetMember(m1.TeamId, ""); r.Err == nil { + t.Fatal("empty user id - should have failed") + } + + if r := <-ss.Team().GetMember("", m1.UserId); r.Err == nil { + t.Fatal("empty team id - should have failed") + } +} + +func testGetTeamMembersByIds(t *testing.T, ss store.Store) { + teamId1 := model.NewId() + + m1 := &model.TeamMember{TeamId: teamId1, UserId: model.NewId()} + store.Must(ss.Team().SaveMember(m1)) + + if r := <-ss.Team().GetMembersByIds(m1.TeamId, []string{m1.UserId}); r.Err != nil { + t.Fatal(r.Err) + } else { + rm1 := r.Data.([]*model.TeamMember)[0] + + if rm1.TeamId != m1.TeamId { + t.Fatal("bad team id") + } + + if rm1.UserId != m1.UserId { + t.Fatal("bad user id") + } + } + + m2 := &model.TeamMember{TeamId: teamId1, UserId: model.NewId()} + store.Must(ss.Team().SaveMember(m2)) + + if r := <-ss.Team().GetMembersByIds(m1.TeamId, []string{m1.UserId, m2.UserId, model.NewId()}); r.Err != nil { + t.Fatal(r.Err) + } else { + rm := r.Data.([]*model.TeamMember) + + if len(rm) != 2 { + t.Fatal("return wrong number of results") + } + } + + if r := <-ss.Team().GetMembersByIds(m1.TeamId, []string{}); r.Err == nil { + t.Fatal("empty user ids - should have failed") + } +} + +func testTeamStoreMemberCount(t *testing.T, ss store.Store) { + u1 := &model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + + u2 := &model.User{} + u2.Email = model.NewId() + u2.DeleteAt = 1 + store.Must(ss.User().Save(u2)) + + teamId1 := model.NewId() + m1 := &model.TeamMember{TeamId: teamId1, UserId: u1.Id} + store.Must(ss.Team().SaveMember(m1)) + + m2 := &model.TeamMember{TeamId: teamId1, UserId: u2.Id} + store.Must(ss.Team().SaveMember(m2)) + + if result := <-ss.Team().GetTotalMemberCount(teamId1); result.Err != nil { + t.Fatal(result.Err) + } else { + if result.Data.(int64) != 2 { + t.Fatal("wrong count") + } + } + + if result := <-ss.Team().GetActiveMemberCount(teamId1); result.Err != nil { + t.Fatal(result.Err) + } else { + if result.Data.(int64) != 1 { + t.Fatal("wrong count") + } + } + + m3 := &model.TeamMember{TeamId: teamId1, UserId: model.NewId()} + store.Must(ss.Team().SaveMember(m3)) + + if result := <-ss.Team().GetTotalMemberCount(teamId1); result.Err != nil { + t.Fatal(result.Err) + } else { + if result.Data.(int64) != 2 { + t.Fatal("wrong count") + } + } + + if result := <-ss.Team().GetActiveMemberCount(teamId1); result.Err != nil { + t.Fatal(result.Err) + } else { + if result.Data.(int64) != 1 { + t.Fatal("wrong count") + } + } +} + +func testGetChannelUnreadsForAllTeams(t *testing.T, ss store.Store) { + teamId1 := model.NewId() + teamId2 := model.NewId() + + uid := model.NewId() + m1 := &model.TeamMember{TeamId: teamId1, UserId: uid} + m2 := &model.TeamMember{TeamId: teamId2, UserId: uid} + store.Must(ss.Team().SaveMember(m1)) + store.Must(ss.Team().SaveMember(m2)) + + c1 := &model.Channel{TeamId: m1.TeamId, Name: model.NewId(), DisplayName: "Town Square", Type: model.CHANNEL_OPEN, TotalMsgCount: 100} + store.Must(ss.Channel().Save(c1)) + c2 := &model.Channel{TeamId: m2.TeamId, Name: model.NewId(), DisplayName: "Town Square", Type: model.CHANNEL_OPEN, TotalMsgCount: 100} + store.Must(ss.Channel().Save(c2)) + + cm1 := &model.ChannelMember{ChannelId: c1.Id, UserId: m1.UserId, NotifyProps: model.GetDefaultChannelNotifyProps(), MsgCount: 90} + store.Must(ss.Channel().SaveMember(cm1)) + cm2 := &model.ChannelMember{ChannelId: c2.Id, UserId: m2.UserId, NotifyProps: model.GetDefaultChannelNotifyProps(), MsgCount: 90} + store.Must(ss.Channel().SaveMember(cm2)) + + if r1 := <-ss.Team().GetChannelUnreadsForAllTeams("", uid); r1.Err != nil { + t.Fatal(r1.Err) + } else { + ms := r1.Data.([]*model.ChannelUnread) + membersMap := make(map[string]bool) + for i := range ms { + id := ms[i].TeamId + if _, ok := membersMap[id]; !ok { + membersMap[id] = true + } + } + if len(membersMap) != 2 { + t.Fatal("Should be the unreads for all the teams") + } + + if ms[0].MsgCount != 10 { + t.Fatal("subtraction failed") + } + } + + if r2 := <-ss.Team().GetChannelUnreadsForAllTeams(teamId1, uid); r2.Err != nil { + t.Fatal(r2.Err) + } else { + ms := r2.Data.([]*model.ChannelUnread) + membersMap := make(map[string]bool) + for i := range ms { + id := ms[i].TeamId + if _, ok := membersMap[id]; !ok { + membersMap[id] = true + } + } + + if len(membersMap) != 1 { + t.Fatal("Should be the unreads for just one team") + } + + if ms[0].MsgCount != 10 { + t.Fatal("subtraction failed") + } + } + + if r1 := <-ss.Team().RemoveAllMembersByUser(uid); r1.Err != nil { + t.Fatal(r1.Err) + } +} + +func testGetChannelUnreadsForTeam(t *testing.T, ss store.Store) { + teamId1 := model.NewId() + + uid := model.NewId() + m1 := &model.TeamMember{TeamId: teamId1, UserId: uid} + store.Must(ss.Team().SaveMember(m1)) + + c1 := &model.Channel{TeamId: m1.TeamId, Name: model.NewId(), DisplayName: "Town Square", Type: model.CHANNEL_OPEN, TotalMsgCount: 100} + store.Must(ss.Channel().Save(c1)) + c2 := &model.Channel{TeamId: m1.TeamId, Name: model.NewId(), DisplayName: "Town Square", Type: model.CHANNEL_OPEN, TotalMsgCount: 100} + store.Must(ss.Channel().Save(c2)) + + cm1 := &model.ChannelMember{ChannelId: c1.Id, UserId: m1.UserId, NotifyProps: model.GetDefaultChannelNotifyProps(), MsgCount: 90} + store.Must(ss.Channel().SaveMember(cm1)) + cm2 := &model.ChannelMember{ChannelId: c2.Id, UserId: m1.UserId, NotifyProps: model.GetDefaultChannelNotifyProps(), MsgCount: 90} + store.Must(ss.Channel().SaveMember(cm2)) + + if r1 := <-ss.Team().GetChannelUnreadsForTeam(m1.TeamId, m1.UserId); r1.Err != nil { + t.Fatal(r1.Err) + } else { + ms := r1.Data.([]*model.ChannelUnread) + if len(ms) != 2 { + t.Fatal("wrong length") + } + + if ms[0].MsgCount != 10 { + t.Fatal("subtraction failed") + } + } +} diff --git a/store/storetest/user_access_token_store.go b/store/storetest/user_access_token_store.go new file mode 100644 index 000000000..292929419 --- /dev/null +++ b/store/storetest/user_access_token_store.go @@ -0,0 +1,89 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "testing" + + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" +) + +func TestUserAccessTokenStore(t *testing.T, ss store.Store) { + t.Run("UserAccessTokenSaveGetDelete", func(t *testing.T) { testUserAccessTokenSaveGetDelete(t, ss) }) +} + +func testUserAccessTokenSaveGetDelete(t *testing.T, ss store.Store) { + uat := &model.UserAccessToken{ + Token: model.NewId(), + UserId: model.NewId(), + Description: "testtoken", + } + + s1 := model.Session{} + s1.UserId = uat.UserId + s1.Token = uat.Token + + store.Must(ss.Session().Save(&s1)) + + if result := <-ss.UserAccessToken().Save(uat); result.Err != nil { + t.Fatal(result.Err) + } + + if result := <-ss.UserAccessToken().Get(uat.Id); result.Err != nil { + t.Fatal(result.Err) + } else if received := result.Data.(*model.UserAccessToken); received.Token != uat.Token { + t.Fatal("received incorrect token after save") + } + + if result := <-ss.UserAccessToken().GetByToken(uat.Token); result.Err != nil { + t.Fatal(result.Err) + } else if received := result.Data.(*model.UserAccessToken); received.Token != uat.Token { + t.Fatal("received incorrect token after save") + } + + if result := <-ss.UserAccessToken().GetByToken("notarealtoken"); result.Err == nil { + t.Fatal("should have failed on bad token") + } + + if result := <-ss.UserAccessToken().GetByUser(uat.UserId, 0, 100); result.Err != nil { + t.Fatal(result.Err) + } else if received := result.Data.([]*model.UserAccessToken); len(received) != 1 { + t.Fatal("received incorrect number of tokens after save") + } + + if result := <-ss.UserAccessToken().Delete(uat.Id); result.Err != nil { + t.Fatal(result.Err) + } + + if err := (<-ss.Session().Get(s1.Token)).Err; err == nil { + t.Fatal("should error - session should be deleted") + } + + if err := (<-ss.UserAccessToken().GetByToken(s1.Token)).Err; err == nil { + t.Fatal("should error - access token should be deleted") + } + + s2 := model.Session{} + s2.UserId = uat.UserId + s2.Token = uat.Token + + store.Must(ss.Session().Save(&s2)) + + if result := <-ss.UserAccessToken().Save(uat); result.Err != nil { + t.Fatal(result.Err) + } + + if result := <-ss.UserAccessToken().DeleteAllForUser(uat.UserId); result.Err != nil { + t.Fatal(result.Err) + } + + if err := (<-ss.Session().Get(s2.Token)).Err; err == nil { + t.Fatal("should error - session should be deleted") + } + + if err := (<-ss.UserAccessToken().GetByToken(s2.Token)).Err; err == nil { + t.Fatal("should error - access token should be deleted") + } +} diff --git a/store/storetest/user_store.go b/store/storetest/user_store.go new file mode 100644 index 000000000..d00e88f56 --- /dev/null +++ b/store/storetest/user_store.go @@ -0,0 +1,2074 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "strings" + "testing" + "time" + + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" +) + +func TestUserStore(t *testing.T, ss store.Store) { + t.Run("Save", func(t *testing.T) { testUserStoreSave(t, ss) }) + t.Run("Update", func(t *testing.T) { testUserStoreUpdate(t, ss) }) + t.Run("UpdateUpdateAt", func(t *testing.T) { testUserStoreUpdateUpdateAt(t, ss) }) + t.Run("UpdateFailedPasswordAttempts", func(t *testing.T) { testUserStoreUpdateFailedPasswordAttempts(t, ss) }) + t.Run("Get", func(t *testing.T) { testUserStoreGet(t, ss) }) + t.Run("UserCount", func(t *testing.T) { testUserCount(t, ss) }) + t.Run("GetAllUsingAuthService", func(t *testing.T) { testGetAllUsingAuthService(t, ss) }) + t.Run("GetAllProfiles", func(t *testing.T) { testUserStoreGetAllProfiles(t, ss) }) + t.Run("GetProfiles", func(t *testing.T) { testUserStoreGetProfiles(t, ss) }) + t.Run("GetProfilesInChannel", func(t *testing.T) { testUserStoreGetProfilesInChannel(t, ss) }) + t.Run("GetProfilesWithoutTeam", func(t *testing.T) { testUserStoreGetProfilesWithoutTeam(t, ss) }) + t.Run("GetAllProfilesInChannel", func(t *testing.T) { testUserStoreGetAllProfilesInChannel(t, ss) }) + t.Run("GetProfilesNotInChannel", func(t *testing.T) { testUserStoreGetProfilesNotInChannel(t, ss) }) + t.Run("GetProfilesByIds", func(t *testing.T) { testUserStoreGetProfilesByIds(t, ss) }) + t.Run("GetProfilesByUsernames", func(t *testing.T) { testUserStoreGetProfilesByUsernames(t, ss) }) + t.Run("GetSystemAdminProfiles", func(t *testing.T) { testUserStoreGetSystemAdminProfiles(t, ss) }) + t.Run("GetByEmail", func(t *testing.T) { testUserStoreGetByEmail(t, ss) }) + t.Run("GetByAuthData", func(t *testing.T) { testUserStoreGetByAuthData(t, ss) }) + t.Run("GetByUsername", func(t *testing.T) { testUserStoreGetByUsername(t, ss) }) + t.Run("GetForLogin", func(t *testing.T) { testUserStoreGetForLogin(t, ss) }) + t.Run("UpdatePassword", func(t *testing.T) { testUserStoreUpdatePassword(t, ss) }) + t.Run("Delete", func(t *testing.T) { testUserStoreDelete(t, ss) }) + t.Run("UpdateAuthData", func(t *testing.T) { testUserStoreUpdateAuthData(t, ss) }) + t.Run("UserUnreadCount", func(t *testing.T) { testUserUnreadCount(t, ss) }) + t.Run("UpdateMfaSecret", func(t *testing.T) { testUserStoreUpdateMfaSecret(t, ss) }) + t.Run("UpdateMfaActive", func(t *testing.T) { testUserStoreUpdateMfaActive(t, ss) }) + t.Run("GetRecentlyActiveUsersForTeam", func(t *testing.T) { testUserStoreGetRecentlyActiveUsersForTeam(t, ss) }) + t.Run("GetNewUsersForTeam", func(t *testing.T) { testUserStoreGetNewUsersForTeam(t, ss) }) + t.Run("Search", func(t *testing.T) { testUserStoreSearch(t, ss) }) + t.Run("SearchWithoutTeam", func(t *testing.T) { testUserStoreSearchWithoutTeam(t, ss) }) + t.Run("AnalyticsGetInactiveUsersCount", func(t *testing.T) { testUserStoreAnalyticsGetInactiveUsersCount(t, ss) }) + t.Run("AnalyticsGetSystemAdminCount", func(t *testing.T) { testUserStoreAnalyticsGetSystemAdminCount(t, ss) }) + t.Run("GetProfilesNotInTeam", func(t *testing.T) { testUserStoreGetProfilesNotInTeam(t, ss) }) +} + +func testUserStoreSave(t *testing.T, ss store.Store) { + teamId := model.NewId() + + u1 := model.User{} + u1.Email = model.NewId() + u1.Username = model.NewId() + + if err := (<-ss.User().Save(&u1)).Err; err != nil { + t.Fatal("couldn't save user", err) + } + + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) + + if err := (<-ss.User().Save(&u1)).Err; err == nil { + t.Fatal("shouldn't be able to update user from save") + } + + u1.Id = "" + if err := (<-ss.User().Save(&u1)).Err; err == nil { + t.Fatal("should be unique email") + } + + u1.Email = "" + if err := (<-ss.User().Save(&u1)).Err; err == nil { + t.Fatal("should be unique username") + } + + u1.Email = strings.Repeat("0123456789", 20) + u1.Username = "" + if err := (<-ss.User().Save(&u1)).Err; err == nil { + t.Fatal("should be unique username") + } + + for i := 0; i < 49; i++ { + u1.Id = "" + u1.Email = model.NewId() + u1.Username = model.NewId() + if err := (<-ss.User().Save(&u1)).Err; err != nil { + t.Fatal("couldn't save item", err) + } + + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) + } + + u1.Id = "" + u1.Email = model.NewId() + u1.Username = model.NewId() + if err := (<-ss.User().Save(&u1)).Err; err != nil { + t.Fatal("couldn't save item", err) + } + + if err := (<-ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})).Err; err == nil { + t.Fatal("should be the limit") + } + +} + +func testUserStoreUpdate(t *testing.T, ss store.Store) { + u1 := &model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) + + u2 := &model.User{} + u2.Email = model.NewId() + u2.AuthService = "ldap" + store.Must(ss.User().Save(u2)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id})) + + time.Sleep(100 * time.Millisecond) + + if err := (<-ss.User().Update(u1, false)).Err; err != nil { + t.Fatal(err) + } + + u1.Id = "missing" + if err := (<-ss.User().Update(u1, false)).Err; err == nil { + t.Fatal("Update should have failed because of missing key") + } + + u1.Id = model.NewId() + if err := (<-ss.User().Update(u1, false)).Err; err == nil { + t.Fatal("Update should have faile because id change") + } + + u2.Email = model.NewId() + if err := (<-ss.User().Update(u2, false)).Err; err == nil { + t.Fatal("Update should have failed because you can't modify AD/LDAP fields") + } + + u3 := &model.User{} + u3.Email = model.NewId() + oldEmail := u3.Email + u3.AuthService = "gitlab" + store.Must(ss.User().Save(u3)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u3.Id})) + + u3.Email = model.NewId() + if result := <-ss.User().Update(u3, false); result.Err != nil { + t.Fatal("Update should not have failed") + } else { + newUser := result.Data.([2]*model.User)[0] + if newUser.Email != oldEmail { + t.Fatal("Email should not have been updated as the update is not trusted") + } + } + + if result := <-ss.User().Update(u3, true); result.Err != nil { + t.Fatal("Update should not have failed") + } else { + newUser := result.Data.([2]*model.User)[0] + if newUser.Email != u3.Email { + t.Fatal("Email should have been updated as the update is trusted") + } + } + + if result := <-ss.User().UpdateLastPictureUpdate(u1.Id); result.Err != nil { + t.Fatal("Update should not have failed") + } +} + +func testUserStoreUpdateUpdateAt(t *testing.T, ss store.Store) { + u1 := &model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) + + time.Sleep(10 * time.Millisecond) + + if err := (<-ss.User().UpdateUpdateAt(u1.Id)).Err; err != nil { + t.Fatal(err) + } + + if r1 := <-ss.User().Get(u1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.User).UpdateAt <= u1.UpdateAt { + t.Fatal("UpdateAt not updated correctly") + } + } + +} + +func testUserStoreUpdateFailedPasswordAttempts(t *testing.T, ss store.Store) { + u1 := &model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) + + if err := (<-ss.User().UpdateFailedPasswordAttempts(u1.Id, 3)).Err; err != nil { + t.Fatal(err) + } + + if r1 := <-ss.User().Get(u1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.User).FailedAttempts != 3 { + t.Fatal("FailedAttempts not updated correctly") + } + } + +} + +func testUserStoreGet(t *testing.T, ss store.Store) { + u1 := &model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) + + if r1 := <-ss.User().Get(u1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.User).ToJson() != u1.ToJson() { + t.Fatal("invalid returned user") + } + } + + if err := (<-ss.User().Get("")).Err; err == nil { + t.Fatal("Missing id should have failed") + } +} + +func testUserCount(t *testing.T, ss store.Store) { + u1 := &model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) + + if result := <-ss.User().GetTotalUsersCount(); result.Err != nil { + t.Fatal(result.Err) + } else { + count := result.Data.(int64) + if count <= 0 { + t.Fatal() + } + } +} + +func testGetAllUsingAuthService(t *testing.T, ss store.Store) { + u1 := &model.User{} + u1.Email = model.NewId() + u1.AuthService = "someservice" + store.Must(ss.User().Save(u1)) + + u2 := &model.User{} + u2.Email = model.NewId() + u2.AuthService = "someservice" + store.Must(ss.User().Save(u2)) + + if r1 := <-ss.User().GetAllUsingAuthService(u1.AuthService); r1.Err != nil { + t.Fatal(r1.Err) + } else { + users := r1.Data.([]*model.User) + if len(users) < 2 { + t.Fatal("invalid returned users") + } + } +} + +func testUserStoreGetAllProfiles(t *testing.T, ss store.Store) { + u1 := &model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + + u2 := &model.User{} + u2.Email = model.NewId() + store.Must(ss.User().Save(u2)) + + if r1 := <-ss.User().GetAllProfiles(0, 100); r1.Err != nil { + t.Fatal(r1.Err) + } else { + users := r1.Data.([]*model.User) + if len(users) < 2 { + t.Fatal("invalid returned users") + } + } + + if r2 := <-ss.User().GetAllProfiles(0, 1); r2.Err != nil { + t.Fatal(r2.Err) + } else { + users := r2.Data.([]*model.User) + if len(users) != 1 { + t.Fatal("invalid returned users, limit did not work") + } + } + + if r2 := <-ss.User().GetAll(); r2.Err != nil { + t.Fatal(r2.Err) + } else { + users := r2.Data.([]*model.User) + if len(users) < 2 { + t.Fatal("invalid returned users") + } + } + + etag := "" + if r2 := <-ss.User().GetEtagForAllProfiles(); r2.Err != nil { + t.Fatal(r2.Err) + } else { + etag = r2.Data.(string) + } + + u3 := &model.User{} + u3.Email = model.NewId() + store.Must(ss.User().Save(u3)) + + if r2 := <-ss.User().GetEtagForAllProfiles(); r2.Err != nil { + t.Fatal(r2.Err) + } else { + if etag == r2.Data.(string) { + t.Fatal("etags should not match") + } + } +} + +func testUserStoreGetProfiles(t *testing.T, ss store.Store) { + teamId := model.NewId() + + u1 := &model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) + + u2 := &model.User{} + u2.Email = model.NewId() + store.Must(ss.User().Save(u2)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id})) + + if r1 := <-ss.User().GetProfiles(teamId, 0, 100); r1.Err != nil { + t.Fatal(r1.Err) + } else { + users := r1.Data.([]*model.User) + if len(users) != 2 { + t.Fatal("invalid returned users") + } + + found := false + for _, u := range users { + if u.Id == u1.Id { + found = true + } + } + + if !found { + t.Fatal("missing user") + } + } + + if r2 := <-ss.User().GetProfiles("123", 0, 100); r2.Err != nil { + t.Fatal(r2.Err) + } else { + if len(r2.Data.([]*model.User)) != 0 { + t.Fatal("should have returned empty map") + } + } + + etag := "" + if r2 := <-ss.User().GetEtagForProfiles(teamId); r2.Err != nil { + t.Fatal(r2.Err) + } else { + etag = r2.Data.(string) + } + + u3 := &model.User{} + u3.Email = model.NewId() + store.Must(ss.User().Save(u3)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u3.Id})) + + if r2 := <-ss.User().GetEtagForProfiles(teamId); r2.Err != nil { + t.Fatal(r2.Err) + } else { + if etag == r2.Data.(string) { + t.Fatal("etags should not match") + } + } +} + +func testUserStoreGetProfilesInChannel(t *testing.T, ss store.Store) { + teamId := model.NewId() + + u1 := &model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) + + u2 := &model.User{} + u2.Email = model.NewId() + store.Must(ss.User().Save(u2)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id})) + + c1 := model.Channel{} + c1.TeamId = teamId + c1.DisplayName = "Profiles in channel" + c1.Name = "profiles-" + model.NewId() + c1.Type = model.CHANNEL_OPEN + + c2 := model.Channel{} + c2.TeamId = teamId + c2.DisplayName = "Profiles in private" + c2.Name = "profiles-" + model.NewId() + c2.Type = model.CHANNEL_PRIVATE + + store.Must(ss.Channel().Save(&c1)) + store.Must(ss.Channel().Save(&c2)) + + m1 := model.ChannelMember{} + m1.ChannelId = c1.Id + m1.UserId = u1.Id + m1.NotifyProps = model.GetDefaultChannelNotifyProps() + + m2 := model.ChannelMember{} + m2.ChannelId = c1.Id + m2.UserId = u2.Id + m2.NotifyProps = model.GetDefaultChannelNotifyProps() + + m3 := model.ChannelMember{} + m3.ChannelId = c2.Id + m3.UserId = u1.Id + m3.NotifyProps = model.GetDefaultChannelNotifyProps() + + store.Must(ss.Channel().SaveMember(&m1)) + store.Must(ss.Channel().SaveMember(&m2)) + store.Must(ss.Channel().SaveMember(&m3)) + + if r1 := <-ss.User().GetProfilesInChannel(c1.Id, 0, 100); r1.Err != nil { + t.Fatal(r1.Err) + } else { + users := r1.Data.([]*model.User) + if len(users) != 2 { + t.Fatal("invalid returned users") + } + + found := false + for _, u := range users { + if u.Id == u1.Id { + found = true + } + } + + if !found { + t.Fatal("missing user") + } + } + + if r2 := <-ss.User().GetProfilesInChannel(c2.Id, 0, 1); r2.Err != nil { + t.Fatal(r2.Err) + } else { + if len(r2.Data.([]*model.User)) != 1 { + t.Fatal("should have returned only 1 user") + } + } +} + +func testUserStoreGetProfilesWithoutTeam(t *testing.T, ss store.Store) { + teamId := model.NewId() + + // These usernames need to appear in the first 100 users for this to work + + u1 := &model.User{} + u1.Username = "a000000000" + model.NewId() + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) + defer ss.User().PermanentDelete(u1.Id) + + u2 := &model.User{} + u2.Username = "a000000001" + model.NewId() + u2.Email = model.NewId() + store.Must(ss.User().Save(u2)) + defer ss.User().PermanentDelete(u2.Id) + + if r1 := <-ss.User().GetProfilesWithoutTeam(0, 100); r1.Err != nil { + t.Fatal(r1.Err) + } else { + users := r1.Data.([]*model.User) + + found1 := false + found2 := false + for _, u := range users { + if u.Id == u1.Id { + found1 = true + } else if u.Id == u2.Id { + found2 = true + } + } + + if found1 { + t.Fatal("shouldn't have returned user on team") + } else if !found2 { + t.Fatal("should've returned user without any teams") + } + } +} + +func testUserStoreGetAllProfilesInChannel(t *testing.T, ss store.Store) { + teamId := model.NewId() + + u1 := &model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) + + u2 := &model.User{} + u2.Email = model.NewId() + store.Must(ss.User().Save(u2)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id})) + + c1 := model.Channel{} + c1.TeamId = teamId + c1.DisplayName = "Profiles in channel" + c1.Name = "profiles-" + model.NewId() + c1.Type = model.CHANNEL_OPEN + + c2 := model.Channel{} + c2.TeamId = teamId + c2.DisplayName = "Profiles in private" + c2.Name = "profiles-" + model.NewId() + c2.Type = model.CHANNEL_PRIVATE + + store.Must(ss.Channel().Save(&c1)) + store.Must(ss.Channel().Save(&c2)) + + m1 := model.ChannelMember{} + m1.ChannelId = c1.Id + m1.UserId = u1.Id + m1.NotifyProps = model.GetDefaultChannelNotifyProps() + + m2 := model.ChannelMember{} + m2.ChannelId = c1.Id + m2.UserId = u2.Id + m2.NotifyProps = model.GetDefaultChannelNotifyProps() + + m3 := model.ChannelMember{} + m3.ChannelId = c2.Id + m3.UserId = u1.Id + m3.NotifyProps = model.GetDefaultChannelNotifyProps() + + store.Must(ss.Channel().SaveMember(&m1)) + store.Must(ss.Channel().SaveMember(&m2)) + store.Must(ss.Channel().SaveMember(&m3)) + + if r1 := <-ss.User().GetAllProfilesInChannel(c1.Id, false); r1.Err != nil { + t.Fatal(r1.Err) + } else { + users := r1.Data.(map[string]*model.User) + if len(users) != 2 { + t.Fatal("invalid returned users") + } + + if users[u1.Id].Id != u1.Id { + t.Fatal("invalid returned user") + } + } + + if r2 := <-ss.User().GetAllProfilesInChannel(c2.Id, false); r2.Err != nil { + t.Fatal(r2.Err) + } else { + if len(r2.Data.(map[string]*model.User)) != 1 { + t.Fatal("should have returned empty map") + } + } + + if r2 := <-ss.User().GetAllProfilesInChannel(c2.Id, true); r2.Err != nil { + t.Fatal(r2.Err) + } else { + if len(r2.Data.(map[string]*model.User)) != 1 { + t.Fatal("should have returned empty map") + } + } + + if r2 := <-ss.User().GetAllProfilesInChannel(c2.Id, true); r2.Err != nil { + t.Fatal(r2.Err) + } else { + if len(r2.Data.(map[string]*model.User)) != 1 { + t.Fatal("should have returned empty map") + } + } + + ss.User().InvalidateProfilesInChannelCacheByUser(u1.Id) + ss.User().InvalidateProfilesInChannelCache(c2.Id) +} + +func testUserStoreGetProfilesNotInChannel(t *testing.T, ss store.Store) { + teamId := model.NewId() + + u1 := &model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) + + u2 := &model.User{} + u2.Email = model.NewId() + store.Must(ss.User().Save(u2)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id})) + + c1 := model.Channel{} + c1.TeamId = teamId + c1.DisplayName = "Profiles in channel" + c1.Name = "profiles-" + model.NewId() + c1.Type = model.CHANNEL_OPEN + + c2 := model.Channel{} + c2.TeamId = teamId + c2.DisplayName = "Profiles in private" + c2.Name = "profiles-" + model.NewId() + c2.Type = model.CHANNEL_PRIVATE + + store.Must(ss.Channel().Save(&c1)) + store.Must(ss.Channel().Save(&c2)) + + if r1 := <-ss.User().GetProfilesNotInChannel(teamId, c1.Id, 0, 100); r1.Err != nil { + t.Fatal(r1.Err) + } else { + users := r1.Data.([]*model.User) + if len(users) != 2 { + t.Fatal("invalid returned users") + } + + found := false + for _, u := range users { + if u.Id == u1.Id { + found = true + } + } + + if !found { + t.Fatal("missing user") + } + } + + if r2 := <-ss.User().GetProfilesNotInChannel(teamId, c2.Id, 0, 100); r2.Err != nil { + t.Fatal(r2.Err) + } else { + if len(r2.Data.([]*model.User)) != 2 { + t.Fatal("invalid returned users") + } + } + + m1 := model.ChannelMember{} + m1.ChannelId = c1.Id + m1.UserId = u1.Id + m1.NotifyProps = model.GetDefaultChannelNotifyProps() + + m2 := model.ChannelMember{} + m2.ChannelId = c1.Id + m2.UserId = u2.Id + m2.NotifyProps = model.GetDefaultChannelNotifyProps() + + m3 := model.ChannelMember{} + m3.ChannelId = c2.Id + m3.UserId = u1.Id + m3.NotifyProps = model.GetDefaultChannelNotifyProps() + + store.Must(ss.Channel().SaveMember(&m1)) + store.Must(ss.Channel().SaveMember(&m2)) + store.Must(ss.Channel().SaveMember(&m3)) + + if r1 := <-ss.User().GetProfilesNotInChannel(teamId, c1.Id, 0, 100); r1.Err != nil { + t.Fatal(r1.Err) + } else { + users := r1.Data.([]*model.User) + if len(users) != 0 { + t.Fatal("invalid returned users") + } + } + + if r2 := <-ss.User().GetProfilesNotInChannel(teamId, c2.Id, 0, 100); r2.Err != nil { + t.Fatal(r2.Err) + } else { + if len(r2.Data.([]*model.User)) != 1 { + t.Fatal("should have had 1 user not in channel") + } + } +} + +func testUserStoreGetProfilesByIds(t *testing.T, ss store.Store) { + teamId := model.NewId() + + u1 := &model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) + + u2 := &model.User{} + u2.Email = model.NewId() + store.Must(ss.User().Save(u2)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id})) + + if r1 := <-ss.User().GetProfileByIds([]string{u1.Id}, false); r1.Err != nil { + t.Fatal(r1.Err) + } else { + users := r1.Data.([]*model.User) + if len(users) != 1 { + t.Fatal("invalid returned users") + } + + found := false + for _, u := range users { + if u.Id == u1.Id { + found = true + } + } + + if !found { + t.Fatal("missing user") + } + } + + if r1 := <-ss.User().GetProfileByIds([]string{u1.Id}, true); r1.Err != nil { + t.Fatal(r1.Err) + } else { + users := r1.Data.([]*model.User) + if len(users) != 1 { + t.Fatal("invalid returned users") + } + + found := false + for _, u := range users { + if u.Id == u1.Id { + found = true + } + } + + if !found { + t.Fatal("missing user") + } + } + + if r1 := <-ss.User().GetProfileByIds([]string{u1.Id, u2.Id}, true); r1.Err != nil { + t.Fatal(r1.Err) + } else { + users := r1.Data.([]*model.User) + if len(users) != 2 { + t.Fatal("invalid returned users") + } + + found := false + for _, u := range users { + if u.Id == u1.Id { + found = true + } + } + + if !found { + t.Fatal("missing user") + } + } + + if r1 := <-ss.User().GetProfileByIds([]string{u1.Id, u2.Id}, true); r1.Err != nil { + t.Fatal(r1.Err) + } else { + users := r1.Data.([]*model.User) + if len(users) != 2 { + t.Fatal("invalid returned users") + } + + found := false + for _, u := range users { + if u.Id == u1.Id { + found = true + } + } + + if !found { + t.Fatal("missing user") + } + } + + if r1 := <-ss.User().GetProfileByIds([]string{u1.Id, u2.Id}, false); r1.Err != nil { + t.Fatal(r1.Err) + } else { + users := r1.Data.([]*model.User) + if len(users) != 2 { + t.Fatal("invalid returned users") + } + + found := false + for _, u := range users { + if u.Id == u1.Id { + found = true + } + } + + if !found { + t.Fatal("missing user") + } + } + + if r1 := <-ss.User().GetProfileByIds([]string{u1.Id}, false); r1.Err != nil { + t.Fatal(r1.Err) + } else { + users := r1.Data.([]*model.User) + if len(users) != 1 { + t.Fatal("invalid returned users") + } + + found := false + for _, u := range users { + if u.Id == u1.Id { + found = true + } + } + + if !found { + t.Fatal("missing user") + } + } + + if r2 := <-ss.User().GetProfiles("123", 0, 100); r2.Err != nil { + t.Fatal(r2.Err) + } else { + if len(r2.Data.([]*model.User)) != 0 { + t.Fatal("should have returned empty array") + } + } +} + +func testUserStoreGetProfilesByUsernames(t *testing.T, ss store.Store) { + teamId := model.NewId() + + u1 := &model.User{} + u1.Email = model.NewId() + u1.Username = "username1" + model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) + + u2 := &model.User{} + u2.Email = model.NewId() + u2.Username = "username2" + model.NewId() + store.Must(ss.User().Save(u2)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id})) + + if r1 := <-ss.User().GetProfilesByUsernames([]string{u1.Username, u2.Username}, teamId); r1.Err != nil { + t.Fatal(r1.Err) + } else { + users := r1.Data.([]*model.User) + if len(users) != 2 { + t.Fatal("invalid returned users") + } + + if users[0].Id != u1.Id && users[1].Id != u1.Id { + t.Fatal("invalid returned user 1") + } + + if users[0].Id != u2.Id && users[1].Id != u2.Id { + t.Fatal("invalid returned user 2") + } + } + + if r1 := <-ss.User().GetProfilesByUsernames([]string{u1.Username}, teamId); r1.Err != nil { + t.Fatal(r1.Err) + } else { + users := r1.Data.([]*model.User) + if len(users) != 1 { + t.Fatal("invalid returned users") + } + + if users[0].Id != u1.Id { + t.Fatal("invalid returned user") + } + } + + team2Id := model.NewId() + + u3 := &model.User{} + u3.Email = model.NewId() + u3.Username = "username3" + model.NewId() + store.Must(ss.User().Save(u3)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: team2Id, UserId: u3.Id})) + + if r1 := <-ss.User().GetProfilesByUsernames([]string{u1.Username, u3.Username}, ""); r1.Err != nil { + t.Fatal(r1.Err) + } else { + users := r1.Data.([]*model.User) + if len(users) != 2 { + t.Fatal("invalid returned users") + } + + if users[0].Id != u1.Id && users[1].Id != u1.Id { + t.Fatal("invalid returned user 1") + } + + if users[0].Id != u3.Id && users[1].Id != u3.Id { + t.Fatal("invalid returned user 3") + } + } + + if r1 := <-ss.User().GetProfilesByUsernames([]string{u1.Username, u3.Username}, teamId); r1.Err != nil { + t.Fatal(r1.Err) + } else { + users := r1.Data.([]*model.User) + if len(users) != 1 { + t.Fatal("invalid returned users") + } + + if users[0].Id != u1.Id { + t.Fatal("invalid returned user") + } + } +} + +func testUserStoreGetSystemAdminProfiles(t *testing.T, ss store.Store) { + teamId := model.NewId() + + u1 := &model.User{} + u1.Email = model.NewId() + u1.Roles = model.ROLE_SYSTEM_USER.Id + " " + model.ROLE_SYSTEM_ADMIN.Id + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) + + u2 := &model.User{} + u2.Email = model.NewId() + store.Must(ss.User().Save(u2)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id})) + + if r1 := <-ss.User().GetSystemAdminProfiles(); r1.Err != nil { + t.Fatal(r1.Err) + } else { + users := r1.Data.(map[string]*model.User) + if len(users) <= 0 { + t.Fatal("invalid returned system admin users") + } + } +} + +func testUserStoreGetByEmail(t *testing.T, ss store.Store) { + teamid := model.NewId() + + u1 := &model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamid, UserId: u1.Id})) + + if err := (<-ss.User().GetByEmail(u1.Email)).Err; err != nil { + t.Fatal(err) + } + + if err := (<-ss.User().GetByEmail("")).Err; err == nil { + t.Fatal("Should have failed because of missing email") + } +} + +func testUserStoreGetByAuthData(t *testing.T, ss store.Store) { + teamId := model.NewId() + + auth := "123" + model.NewId() + + u1 := &model.User{} + u1.Email = model.NewId() + u1.AuthData = &auth + u1.AuthService = "service" + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) + + if err := (<-ss.User().GetByAuth(u1.AuthData, u1.AuthService)).Err; err != nil { + t.Fatal(err) + } + + rauth := "" + if err := (<-ss.User().GetByAuth(&rauth, "")).Err; err == nil { + t.Fatal("Should have failed because of missing auth data") + } +} + +func testUserStoreGetByUsername(t *testing.T, ss store.Store) { + teamId := model.NewId() + + u1 := &model.User{} + u1.Email = model.NewId() + u1.Username = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) + + if err := (<-ss.User().GetByUsername(u1.Username)).Err; err != nil { + t.Fatal(err) + } + + if err := (<-ss.User().GetByUsername("")).Err; err == nil { + t.Fatal("Should have failed because of missing username") + } +} + +func testUserStoreGetForLogin(t *testing.T, ss store.Store) { + auth := model.NewId() + + u1 := &model.User{ + Email: model.NewId(), + Username: model.NewId(), + AuthService: model.USER_AUTH_SERVICE_GITLAB, + AuthData: &auth, + } + store.Must(ss.User().Save(u1)) + + auth2 := model.NewId() + + u2 := &model.User{ + Email: model.NewId(), + Username: model.NewId(), + AuthService: model.USER_AUTH_SERVICE_LDAP, + AuthData: &auth2, + } + store.Must(ss.User().Save(u2)) + + if result := <-ss.User().GetForLogin(u1.Username, true, true, true); result.Err != nil { + t.Fatal("Should have gotten user by username", result.Err) + } else if result.Data.(*model.User).Id != u1.Id { + t.Fatal("Should have gotten user1 by username") + } + + if result := <-ss.User().GetForLogin(u1.Email, true, true, true); result.Err != nil { + t.Fatal("Should have gotten user by email", result.Err) + } else if result.Data.(*model.User).Id != u1.Id { + t.Fatal("Should have gotten user1 by email") + } + + if result := <-ss.User().GetForLogin(*u2.AuthData, true, true, true); result.Err != nil { + t.Fatal("Should have gotten user by AD/LDAP AuthData", result.Err) + } else if result.Data.(*model.User).Id != u2.Id { + t.Fatal("Should have gotten user2 by AD/LDAP AuthData") + } + + // prevent getting user by AuthData when they're not an LDAP user + if result := <-ss.User().GetForLogin(*u1.AuthData, true, true, true); result.Err == nil { + t.Fatal("Should not have gotten user by non-AD/LDAP AuthData") + } + + // prevent getting user when different login methods are disabled + if result := <-ss.User().GetForLogin(u1.Username, false, true, true); result.Err == nil { + t.Fatal("Should have failed to get user1 by username") + } + + if result := <-ss.User().GetForLogin(u1.Email, true, false, true); result.Err == nil { + t.Fatal("Should have failed to get user1 by email") + } + + if result := <-ss.User().GetForLogin(*u2.AuthData, true, true, false); result.Err == nil { + t.Fatal("Should have failed to get user3 by AD/LDAP AuthData") + } + + auth3 := model.NewId() + + // test a special case where two users will have conflicting login information so we throw a special error + u3 := &model.User{ + Email: model.NewId(), + Username: model.NewId(), + AuthService: model.USER_AUTH_SERVICE_LDAP, + AuthData: &auth3, + } + store.Must(ss.User().Save(u3)) + + u4 := &model.User{ + Email: model.NewId(), + Username: model.NewId(), + AuthService: model.USER_AUTH_SERVICE_LDAP, + AuthData: &u3.Username, + } + store.Must(ss.User().Save(u4)) + + if err := (<-ss.User().GetForLogin(u3.Username, true, true, true)).Err; err == nil { + t.Fatal("Should have failed to get users with conflicting login information") + } +} + +func testUserStoreUpdatePassword(t *testing.T, ss store.Store) { + teamId := model.NewId() + + u1 := &model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) + + hashedPassword := model.HashPassword("newpwd") + + if err := (<-ss.User().UpdatePassword(u1.Id, hashedPassword)).Err; err != nil { + t.Fatal(err) + } + + if r1 := <-ss.User().GetByEmail(u1.Email); r1.Err != nil { + t.Fatal(r1.Err) + } else { + user := r1.Data.(*model.User) + if user.Password != hashedPassword { + t.Fatal("Password was not updated correctly") + } + } +} + +func testUserStoreDelete(t *testing.T, ss store.Store) { + u1 := &model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) + + if err := (<-ss.User().PermanentDelete(u1.Id)).Err; err != nil { + t.Fatal(err) + } +} + +func testUserStoreUpdateAuthData(t *testing.T, ss store.Store) { + teamId := model.NewId() + + u1 := &model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) + + service := "someservice" + authData := model.NewId() + + if err := (<-ss.User().UpdateAuthData(u1.Id, service, &authData, "", true)).Err; err != nil { + t.Fatal(err) + } + + if r1 := <-ss.User().GetByEmail(u1.Email); r1.Err != nil { + t.Fatal(r1.Err) + } else { + user := r1.Data.(*model.User) + if user.AuthService != service { + t.Fatal("AuthService was not updated correctly") + } + if *user.AuthData != authData { + t.Fatal("AuthData was not updated correctly") + } + if user.Password != "" { + t.Fatal("Password was not cleared properly") + } + } +} + +func testUserUnreadCount(t *testing.T, ss store.Store) { + teamId := model.NewId() + + c1 := model.Channel{} + c1.TeamId = teamId + c1.DisplayName = "Unread Messages" + c1.Name = "unread-messages-" + model.NewId() + c1.Type = model.CHANNEL_OPEN + + c2 := model.Channel{} + c2.TeamId = teamId + c2.DisplayName = "Unread Direct" + c2.Name = "unread-direct-" + model.NewId() + c2.Type = model.CHANNEL_DIRECT + + u1 := &model.User{} + u1.Username = "user1" + model.NewId() + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) + + u2 := &model.User{} + u2.Email = model.NewId() + u2.Username = "user2" + model.NewId() + store.Must(ss.User().Save(u2)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id})) + + if err := (<-ss.Channel().Save(&c1)).Err; err != nil { + t.Fatal("couldn't save item", err) + } + + m1 := model.ChannelMember{} + m1.ChannelId = c1.Id + m1.UserId = u1.Id + m1.NotifyProps = model.GetDefaultChannelNotifyProps() + + m2 := model.ChannelMember{} + m2.ChannelId = c1.Id + m2.UserId = u2.Id + m2.NotifyProps = model.GetDefaultChannelNotifyProps() + + store.Must(ss.Channel().SaveMember(&m1)) + store.Must(ss.Channel().SaveMember(&m2)) + + m1.ChannelId = c2.Id + m2.ChannelId = c2.Id + + if err := (<-ss.Channel().SaveDirectChannel(&c2, &m1, &m2)).Err; err != nil { + t.Fatal("couldn't save direct channel", err) + } + + p1 := model.Post{} + p1.ChannelId = c1.Id + p1.UserId = u1.Id + p1.Message = "this is a message for @" + u2.Username + + // Post one message with mention to open channel + store.Must(ss.Post().Save(&p1)) + store.Must(ss.Channel().IncrementMentionCount(c1.Id, u2.Id)) + + // Post 2 messages without mention to direct channel + p2 := model.Post{} + p2.ChannelId = c2.Id + p2.UserId = u1.Id + p2.Message = "first message" + store.Must(ss.Post().Save(&p2)) + store.Must(ss.Channel().IncrementMentionCount(c2.Id, u2.Id)) + + p3 := model.Post{} + p3.ChannelId = c2.Id + p3.UserId = u1.Id + p3.Message = "second message" + store.Must(ss.Post().Save(&p3)) + store.Must(ss.Channel().IncrementMentionCount(c2.Id, u2.Id)) + + badge := (<-ss.User().GetUnreadCount(u2.Id)).Data.(int64) + if badge != 3 { + t.Fatal("should have 3 unread messages") + } + + badge = (<-ss.User().GetUnreadCountForChannel(u2.Id, c1.Id)).Data.(int64) + if badge != 1 { + t.Fatal("should have 1 unread messages for that channel") + } + + badge = (<-ss.User().GetUnreadCountForChannel(u2.Id, c2.Id)).Data.(int64) + if badge != 2 { + t.Fatal("should have 2 unread messages for that channel") + } +} + +func testUserStoreUpdateMfaSecret(t *testing.T, ss store.Store) { + u1 := model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(&u1)) + + time.Sleep(100 * time.Millisecond) + + if err := (<-ss.User().UpdateMfaSecret(u1.Id, "12345")).Err; err != nil { + t.Fatal(err) + } + + // should pass, no update will occur though + if err := (<-ss.User().UpdateMfaSecret("junk", "12345")).Err; err != nil { + t.Fatal(err) + } +} + +func testUserStoreUpdateMfaActive(t *testing.T, ss store.Store) { + u1 := model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(&u1)) + + time.Sleep(100 * time.Millisecond) + + if err := (<-ss.User().UpdateMfaActive(u1.Id, true)).Err; err != nil { + t.Fatal(err) + } + + if err := (<-ss.User().UpdateMfaActive(u1.Id, false)).Err; err != nil { + t.Fatal(err) + } + + // should pass, no update will occur though + if err := (<-ss.User().UpdateMfaActive("junk", true)).Err; err != nil { + t.Fatal(err) + } +} + +func testUserStoreGetRecentlyActiveUsersForTeam(t *testing.T, ss store.Store) { + u1 := &model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Status().SaveOrUpdate(&model.Status{UserId: u1.Id, Status: model.STATUS_ONLINE, Manual: false, LastActivityAt: model.GetMillis(), ActiveChannel: ""})) + tid := model.NewId() + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: tid, UserId: u1.Id})) + + if r1 := <-ss.User().GetRecentlyActiveUsersForTeam(tid, 0, 100); r1.Err != nil { + t.Fatal(r1.Err) + } +} + +func testUserStoreGetNewUsersForTeam(t *testing.T, ss store.Store) { + u1 := &model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Status().SaveOrUpdate(&model.Status{UserId: u1.Id, Status: model.STATUS_ONLINE, Manual: false, LastActivityAt: model.GetMillis(), ActiveChannel: ""})) + tid := model.NewId() + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: tid, UserId: u1.Id})) + + if r1 := <-ss.User().GetNewUsersForTeam(tid, 0, 100); r1.Err != nil { + t.Fatal(r1.Err) + } +} + +func testUserStoreSearch(t *testing.T, ss store.Store) { + u1 := &model.User{} + u1.Username = "jimbo" + model.NewId() + u1.FirstName = "Tim" + u1.LastName = "Bill" + u1.Nickname = "Rob" + u1.Email = "harold" + model.NewId() + "@simulator.amazonses.com" + store.Must(ss.User().Save(u1)) + + u2 := &model.User{} + u2.Username = "jim-bobby" + model.NewId() + u2.Email = model.NewId() + store.Must(ss.User().Save(u2)) + + u3 := &model.User{} + u3.Username = "jimbo" + model.NewId() + u3.Email = model.NewId() + u3.DeleteAt = 1 + store.Must(ss.User().Save(u3)) + + u5 := &model.User{} + u5.Username = "yu" + model.NewId() + u5.FirstName = "En" + u5.LastName = "Yu" + u5.Nickname = "enyu" + u5.Email = model.NewId() + "@simulator.amazonses.com" + store.Must(ss.User().Save(u5)) + + u6 := &model.User{} + u6.Username = "underscore" + model.NewId() + u6.FirstName = "Du_" + u6.LastName = "_DE" + u6.Nickname = "lodash" + u6.Email = model.NewId() + "@simulator.amazonses.com" + store.Must(ss.User().Save(u6)) + + tid := model.NewId() + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: tid, UserId: u1.Id})) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: tid, UserId: u2.Id})) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: tid, UserId: u3.Id})) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: tid, UserId: u5.Id})) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: tid, UserId: u6.Id})) + + searchOptions := map[string]bool{} + searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true + + if r1 := <-ss.User().Search(tid, "jimb", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found1 := false + found2 := false + for _, profile := range profiles { + if profile.Id == u1.Id { + found1 = true + } + + if profile.Id == u3.Id { + found2 = true + } + } + + if !found1 { + t.Fatal("should have found user") + } + + if found2 { + t.Fatal("should not have found inactive user") + } + } + + if r1 := <-ss.User().Search(tid, "en", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found1 := false + for _, profile := range profiles { + if profile.Id == u5.Id { + found1 = true + } + } + + if !found1 { + t.Fatal("should have found user") + } + } + + searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = false + + if r1 := <-ss.User().Search(tid, u1.Email, searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found1 := false + for _, profile := range profiles { + if profile.Id == u1.Id { + found1 = true + } + } + + if !found1 { + t.Fatal("should have found user") + } + } + + searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true + + // * should be treated as a space + if r1 := <-ss.User().Search(tid, "jimb*", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found1 := false + found2 := false + for _, profile := range profiles { + if profile.Id == u1.Id { + found1 = true + } + + if profile.Id == u3.Id { + found2 = true + } + } + + if !found1 { + t.Fatal("should have found user") + } + + if found2 { + t.Fatal("should not have found inactive user") + } + } + + if r1 := <-ss.User().Search(tid, "harol", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found1 := false + for _, profile := range profiles { + if profile.Id == u1.Id { + found1 = true + } + } + + if found1 { + t.Fatal("should not have found user") + } + } + + // % should be escaped and searched for. + if r1 := <-ss.User().Search(tid, "h%", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + if len(profiles) != 0 { + t.Fatal("shouldn't have found anything") + } + } + + // "_" should be properly escaped and searched for. + if r1 := <-ss.User().Search(tid, "h_", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + if len(profiles) != 0 { + t.Fatal("shouldn't have found anything") + } + } + if r1 := <-ss.User().Search(tid, "Du_", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found6 := false + for _, profile := range profiles { + if profile.Id == u6.Id { + found6 = true + } + } + + if !found6 { + t.Fatal("should have found user") + } + } + if r1 := <-ss.User().Search(tid, "_dE", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found6 := false + for _, profile := range profiles { + if profile.Id == u6.Id { + found6 = true + } + } + + if !found6 { + t.Fatal("should have found user") + } + } + + searchOptions[store.USER_SEARCH_OPTION_ALLOW_INACTIVE] = true + + if r1 := <-ss.User().Search(tid, "jimb", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found1 := false + found2 := false + for _, profile := range profiles { + if profile.Id == u1.Id { + found1 = true + } + + if profile.Id == u3.Id { + found2 = true + } + } + + if !found1 { + t.Fatal("should have found user") + } + + if !found2 { + t.Fatal("should have found inactive user") + } + } + + searchOptions[store.USER_SEARCH_OPTION_ALLOW_INACTIVE] = false + + if r1 := <-ss.User().Search(tid, "jimb", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found := false + for _, profile := range profiles { + if profile.Id == u1.Id { + found = true + break + } + } + + if !found { + t.Fatal("should have found user") + } + } + + if r1 := <-ss.User().Search("", "jimb", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found := false + for _, profile := range profiles { + if profile.Id == u1.Id { + found = true + break + } + } + + if !found { + t.Fatal("should have found user") + } + } + + if r1 := <-ss.User().Search("", "jim-bobb", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found := false + for _, profile := range profiles { + t.Log(profile.Username) + if profile.Id == u2.Id { + found = true + break + } + } + + if !found { + t.Fatal("should have found user") + } + } + + if r1 := <-ss.User().Search(tid, "", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } + + c1 := model.Channel{} + c1.TeamId = tid + c1.DisplayName = "NameName" + c1.Name = "zz" + model.NewId() + "b" + c1.Type = model.CHANNEL_OPEN + c1 = *store.Must(ss.Channel().Save(&c1)).(*model.Channel) + + if r1 := <-ss.User().SearchNotInChannel(tid, c1.Id, "jimb", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found := false + for _, profile := range profiles { + if profile.Id == u1.Id { + found = true + break + } + } + + if !found { + t.Fatal("should have found user") + } + } + + if r1 := <-ss.User().SearchNotInChannel("", c1.Id, "jimb", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found := false + for _, profile := range profiles { + if profile.Id == u1.Id { + found = true + break + } + } + + if !found { + t.Fatal("should have found user") + } + } + + if r1 := <-ss.User().SearchNotInChannel("junk", c1.Id, "jimb", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found := false + for _, profile := range profiles { + if profile.Id == u1.Id { + found = true + break + } + } + + if found { + t.Fatal("should not have found user") + } + } + + if r1 := <-ss.User().SearchInChannel(c1.Id, "jimb", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found := false + for _, profile := range profiles { + if profile.Id == u1.Id { + found = true + break + } + } + + if found { + t.Fatal("should not have found user") + } + } + + store.Must(ss.Channel().SaveMember(&model.ChannelMember{ChannelId: c1.Id, UserId: u1.Id, NotifyProps: model.GetDefaultChannelNotifyProps()})) + + if r1 := <-ss.User().SearchInChannel(c1.Id, "jimb", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found := false + for _, profile := range profiles { + if profile.Id == u1.Id { + found = true + break + } + } + + if !found { + t.Fatal("should have found user") + } + } + + searchOptions = map[string]bool{} + + if r1 := <-ss.User().Search(tid, "harol", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found1 := false + for _, profile := range profiles { + if profile.Id == u1.Id { + found1 = true + } + } + + if !found1 { + t.Fatal("should have found user") + } + } + + if r1 := <-ss.User().Search(tid, "Tim", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found := false + for _, profile := range profiles { + if profile.Id == u1.Id { + found = true + break + } + } + + if !found { + t.Fatal("should have found user") + } + } + + if r1 := <-ss.User().Search(tid, "Bill", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found := false + for _, profile := range profiles { + if profile.Id == u1.Id { + found = true + break + } + } + + if !found { + t.Fatal("should have found user") + } + } + + if r1 := <-ss.User().Search(tid, "Rob", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found := false + for _, profile := range profiles { + if profile.Id == u1.Id { + found = true + break + } + } + + if !found { + t.Fatal("should have found user") + } + } + + // Search Users not in Team. + u4 := &model.User{} + u4.Username = "simon" + model.NewId() + u4.Email = model.NewId() + u4.DeleteAt = 0 + store.Must(ss.User().Save(u4)) + + if r1 := <-ss.User().SearchNotInTeam(tid, "simo", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found := false + for _, profile := range profiles { + if profile.Id == u4.Id { + found = true + break + } + } + + if !found { + t.Fatal("should have found user") + } + } + + if r1 := <-ss.User().SearchNotInTeam(tid, "jimb", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found := false + for _, profile := range profiles { + if profile.Id == u1.Id { + found = true + break + } + } + + if found { + t.Fatal("should not have found user") + } + } + + // Check SearchNotInTeam finds previously deleted team members. + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: tid, UserId: u4.Id})) + + if r1 := <-ss.User().SearchNotInTeam(tid, "simo", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found := false + for _, profile := range profiles { + if profile.Id == u4.Id { + found = true + break + } + } + + if found { + t.Fatal("should not have found user") + } + } + + store.Must(ss.Team().UpdateMember(&model.TeamMember{TeamId: tid, UserId: u4.Id, DeleteAt: model.GetMillis() - 1000})) + if r1 := <-ss.User().SearchNotInTeam(tid, "simo", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + found := false + for _, profile := range profiles { + if profile.Id == u4.Id { + found = true + break + } + } + + if !found { + t.Fatal("should have found user") + } + } +} + +func testUserStoreSearchWithoutTeam(t *testing.T, ss store.Store) { + u1 := &model.User{} + u1.Username = "jimbo" + model.NewId() + u1.FirstName = "Tim" + u1.LastName = "Bill" + u1.Nickname = "Rob" + u1.Email = "harold" + model.NewId() + "@simulator.amazonses.com" + store.Must(ss.User().Save(u1)) + + u2 := &model.User{} + u2.Username = "jim-bobby" + model.NewId() + u2.Email = model.NewId() + store.Must(ss.User().Save(u2)) + + u3 := &model.User{} + u3.Username = "jimbo" + model.NewId() + u3.Email = model.NewId() + u3.DeleteAt = 1 + store.Must(ss.User().Save(u3)) + + tid := model.NewId() + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: tid, UserId: u3.Id})) + + searchOptions := map[string]bool{} + searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true + + if r1 := <-ss.User().SearchWithoutTeam("", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } + + if r1 := <-ss.User().SearchWithoutTeam("jim", searchOptions); r1.Err != nil { + t.Fatal(r1.Err) + } else { + profiles := r1.Data.([]*model.User) + + found1 := false + found2 := false + found3 := false + + for _, profile := range profiles { + if profile.Id == u1.Id { + found1 = true + } else if profile.Id == u2.Id { + found2 = true + } else if profile.Id == u3.Id { + found3 = true + } + } + + if !found1 { + t.Fatal("should have found user1") + } else if !found2 { + t.Fatal("should have found user2") + } else if found3 { + t.Fatal("should not have found user3") + } + } +} + +func testUserStoreAnalyticsGetInactiveUsersCount(t *testing.T, ss store.Store) { + u1 := &model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + + var count int64 + + if result := <-ss.User().AnalyticsGetInactiveUsersCount(); result.Err != nil { + t.Fatal(result.Err) + } else { + count = result.Data.(int64) + } + + u2 := &model.User{} + u2.Email = model.NewId() + u2.DeleteAt = model.GetMillis() + store.Must(ss.User().Save(u2)) + + if result := <-ss.User().AnalyticsGetInactiveUsersCount(); result.Err != nil { + t.Fatal(result.Err) + } else { + newCount := result.Data.(int64) + if count != newCount-1 { + t.Fatal("Expected 1 more inactive users but found otherwise.", count, newCount) + } + } +} + +func testUserStoreAnalyticsGetSystemAdminCount(t *testing.T, ss store.Store) { + var countBefore int64 + if result := <-ss.User().AnalyticsGetSystemAdminCount(); result.Err != nil { + t.Fatal(result.Err) + } else { + countBefore = result.Data.(int64) + } + + u1 := model.User{} + u1.Email = model.NewId() + u1.Username = model.NewId() + u1.Roles = "system_user system_admin" + + u2 := model.User{} + u2.Email = model.NewId() + u2.Username = model.NewId() + + if err := (<-ss.User().Save(&u1)).Err; err != nil { + t.Fatal("couldn't save user", err) + } + + if err := (<-ss.User().Save(&u2)).Err; err != nil { + t.Fatal("couldn't save user", err) + } + + if result := <-ss.User().AnalyticsGetSystemAdminCount(); result.Err != nil { + t.Fatal(result.Err) + } else { + // We expect to find 1 more system admin than there was at the start of this test function. + if count := result.Data.(int64); count != countBefore+1 { + t.Fatal("Did not get the expected number of system admins. Expected, got: ", countBefore+1, count) + } + } +} + +func testUserStoreGetProfilesNotInTeam(t *testing.T, ss store.Store) { + teamId := model.NewId() + + u1 := &model.User{} + u1.Email = model.NewId() + store.Must(ss.User().Save(u1)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) + store.Must(ss.User().UpdateUpdateAt(u1.Id)) + + u2 := &model.User{} + u2.Email = model.NewId() + store.Must(ss.User().Save(u2)) + store.Must(ss.User().UpdateUpdateAt(u2.Id)) + + var initialUsersNotInTeam int + var etag1, etag2, etag3 string + + if er1 := <-ss.User().GetEtagForProfilesNotInTeam(teamId); er1.Err != nil { + t.Fatal(er1.Err) + } else { + etag1 = er1.Data.(string) + } + + if r1 := <-ss.User().GetProfilesNotInTeam(teamId, 0, 100000); r1.Err != nil { + t.Fatal(r1.Err) + } else { + users := r1.Data.([]*model.User) + initialUsersNotInTeam = len(users) + if initialUsersNotInTeam < 1 { + t.Fatalf("Should be at least 1 user not in the team") + } + + found := false + for _, u := range users { + if u.Id == u2.Id { + found = true + } + if u.Id == u1.Id { + t.Fatalf("Should not have found user1") + } + } + + if !found { + t.Fatal("missing user2") + } + } + + time.Sleep(time.Millisecond * 10) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id})) + store.Must(ss.User().UpdateUpdateAt(u2.Id)) + + if er2 := <-ss.User().GetEtagForProfilesNotInTeam(teamId); er2.Err != nil { + t.Fatal(er2.Err) + } else { + etag2 = er2.Data.(string) + if etag1 == etag2 { + t.Fatalf("etag should have changed") + } + } + + if r2 := <-ss.User().GetProfilesNotInTeam(teamId, 0, 100000); r2.Err != nil { + t.Fatal(r2.Err) + } else { + users := r2.Data.([]*model.User) + + if len(users) != initialUsersNotInTeam-1 { + t.Fatalf("Should be one less user not in team") + } + + for _, u := range users { + if u.Id == u2.Id { + t.Fatalf("Should not have found user2") + } + if u.Id == u1.Id { + t.Fatalf("Should not have found user1") + } + } + } + + time.Sleep(time.Millisecond * 10) + store.Must(ss.Team().RemoveMember(teamId, u1.Id)) + store.Must(ss.Team().RemoveMember(teamId, u2.Id)) + store.Must(ss.User().UpdateUpdateAt(u1.Id)) + store.Must(ss.User().UpdateUpdateAt(u2.Id)) + + if er3 := <-ss.User().GetEtagForProfilesNotInTeam(teamId); er3.Err != nil { + t.Fatal(er3.Err) + } else { + etag3 = er3.Data.(string) + t.Log(etag3) + if etag1 == etag3 || etag3 == etag2 { + t.Fatalf("etag should have changed") + } + } + + if r3 := <-ss.User().GetProfilesNotInTeam(teamId, 0, 100000); r3.Err != nil { + t.Fatal(r3.Err) + } else { + users := r3.Data.([]*model.User) + found1, found2 := false, false + for _, u := range users { + if u.Id == u2.Id { + found2 = true + } + if u.Id == u1.Id { + found1 = true + } + } + + if !found1 || !found2 { + t.Fatal("missing user1 or user2") + } + } + + time.Sleep(time.Millisecond * 10) + u3 := &model.User{} + u3.Email = model.NewId() + store.Must(ss.User().Save(u3)) + store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u3.Id})) + store.Must(ss.User().UpdateUpdateAt(u3.Id)) + + if er4 := <-ss.User().GetEtagForProfilesNotInTeam(teamId); er4.Err != nil { + t.Fatal(er4.Err) + } else { + etag4 := er4.Data.(string) + t.Log(etag4) + if etag4 != etag3 { + t.Fatalf("etag should be the same") + } + } +} diff --git a/store/storetest/webhook_store.go b/store/storetest/webhook_store.go new file mode 100644 index 000000000..7f87ec29d --- /dev/null +++ b/store/storetest/webhook_store.go @@ -0,0 +1,507 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "testing" + "time" + + "net/http" + + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" +) + +func TestWebhookStore(t *testing.T, ss store.Store) { + t.Run("SaveIncoming", func(t *testing.T) { testWebhookStoreSaveIncoming(t, ss) }) + t.Run("UpdateIncoming", func(t *testing.T) { testWebhookStoreUpdateIncoming(t, ss) }) + t.Run("GetIncoming", func(t *testing.T) { testWebhookStoreGetIncoming(t, ss) }) + t.Run("GetIncomingList", func(t *testing.T) { testWebhookStoreGetIncomingList(t, ss) }) + t.Run("GetIncomingByTeam", func(t *testing.T) { testWebhookStoreGetIncomingByTeam(t, ss) }) + t.Run("DeleteIncoming", func(t *testing.T) { testWebhookStoreDeleteIncoming(t, ss) }) + t.Run("DeleteIncomingByChannel", func(t *testing.T) { testWebhookStoreDeleteIncomingByChannel(t, ss) }) + t.Run("DeleteIncomingByUser", func(t *testing.T) { testWebhookStoreDeleteIncomingByUser(t, ss) }) + t.Run("SaveOutgoing", func(t *testing.T) { testWebhookStoreSaveOutgoing(t, ss) }) + t.Run("GetOutgoing", func(t *testing.T) { testWebhookStoreGetOutgoing(t, ss) }) + t.Run("GetOutgoingList", func(t *testing.T) { testWebhookStoreGetOutgoingList(t, ss) }) + t.Run("GetOutgoingByChannel", func(t *testing.T) { testWebhookStoreGetOutgoingByChannel(t, ss) }) + t.Run("GetOutgoingByTeam", func(t *testing.T) { testWebhookStoreGetOutgoingByTeam(t, ss) }) + t.Run("DeleteOutgoing", func(t *testing.T) { testWebhookStoreDeleteOutgoing(t, ss) }) + t.Run("DeleteOutgoingByChannel", func(t *testing.T) { testWebhookStoreDeleteOutgoingByChannel(t, ss) }) + t.Run("DeleteOutgoingByUser", func(t *testing.T) { testWebhookStoreDeleteOutgoingByUser(t, ss) }) + t.Run("UpdateOutgoing", func(t *testing.T) { testWebhookStoreUpdateOutgoing(t, ss) }) + t.Run("CountIncoming", func(t *testing.T) { testWebhookStoreCountIncoming(t, ss) }) + t.Run("CountOutgoing", func(t *testing.T) { testWebhookStoreCountOutgoing(t, ss) }) +} + +func testWebhookStoreSaveIncoming(t *testing.T, ss store.Store) { + o1 := buildIncomingWebhook() + + if err := (<-ss.Webhook().SaveIncoming(o1)).Err; err != nil { + t.Fatal("couldn't save item", err) + } + + if err := (<-ss.Webhook().SaveIncoming(o1)).Err; err == nil { + t.Fatal("shouldn't be able to update from save") + } +} + +func testWebhookStoreUpdateIncoming(t *testing.T, ss store.Store) { + o1 := buildIncomingWebhook() + o1 = (<-ss.Webhook().SaveIncoming(o1)).Data.(*model.IncomingWebhook) + previousUpdatedAt := o1.UpdateAt + + o1.DisplayName = "TestHook" + time.Sleep(10 * time.Millisecond) + + if result := (<-ss.Webhook().UpdateIncoming(o1)); result.Err != nil { + t.Fatal("updation of incoming hook failed", result.Err) + } else { + if result.Data.(*model.IncomingWebhook).UpdateAt == previousUpdatedAt { + t.Fatal("should have updated the UpdatedAt of the hook") + } + + if result.Data.(*model.IncomingWebhook).DisplayName != "TestHook" { + t.Fatal("display name is not updated") + } + } +} + +func testWebhookStoreGetIncoming(t *testing.T, ss store.Store) { + o1 := buildIncomingWebhook() + o1 = (<-ss.Webhook().SaveIncoming(o1)).Data.(*model.IncomingWebhook) + + if r1 := <-ss.Webhook().GetIncoming(o1.Id, false); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.IncomingWebhook).CreateAt != o1.CreateAt { + t.Fatal("invalid returned webhook") + } + } + + if r1 := <-ss.Webhook().GetIncoming(o1.Id, true); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.IncomingWebhook).CreateAt != o1.CreateAt { + t.Fatal("invalid returned webhook") + } + } + + if err := (<-ss.Webhook().GetIncoming("123", false)).Err; err == nil { + t.Fatal("Missing id should have failed") + } + + if err := (<-ss.Webhook().GetIncoming("123", true)).Err; err == nil { + t.Fatal("Missing id should have failed") + } + + if err := (<-ss.Webhook().GetIncoming("123", true)).Err; err.StatusCode != http.StatusNotFound { + t.Fatal("Should have set the status as not found for missing id") + } +} + +func testWebhookStoreGetIncomingList(t *testing.T, ss store.Store) { + o1 := &model.IncomingWebhook{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.TeamId = model.NewId() + + o1 = (<-ss.Webhook().SaveIncoming(o1)).Data.(*model.IncomingWebhook) + + if r1 := <-ss.Webhook().GetIncomingList(0, 1000); r1.Err != nil { + t.Fatal(r1.Err) + } else { + found := false + hooks := r1.Data.([]*model.IncomingWebhook) + for _, hook := range hooks { + if hook.Id == o1.Id { + found = true + } + } + if !found { + t.Fatal("missing webhook") + } + } + + if result := <-ss.Webhook().GetIncomingList(0, 1); result.Err != nil { + t.Fatal(result.Err) + } else { + if len(result.Data.([]*model.IncomingWebhook)) != 1 { + t.Fatal("only 1 should be returned") + } + } +} + +func testWebhookStoreGetIncomingByTeam(t *testing.T, ss store.Store) { + o1 := buildIncomingWebhook() + + o1 = (<-ss.Webhook().SaveIncoming(o1)).Data.(*model.IncomingWebhook) + + if r1 := <-ss.Webhook().GetIncomingByTeam(o1.TeamId, 0, 100); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.([]*model.IncomingWebhook)[0].CreateAt != o1.CreateAt { + t.Fatal("invalid returned webhook") + } + } + + if result := <-ss.Webhook().GetIncomingByTeam("123", 0, 100); result.Err != nil { + t.Fatal(result.Err) + } else { + if len(result.Data.([]*model.IncomingWebhook)) != 0 { + t.Fatal("no webhooks should have returned") + } + } +} + +func testWebhookStoreDeleteIncoming(t *testing.T, ss store.Store) { + o1 := buildIncomingWebhook() + + o1 = (<-ss.Webhook().SaveIncoming(o1)).Data.(*model.IncomingWebhook) + + if r1 := <-ss.Webhook().GetIncoming(o1.Id, true); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.IncomingWebhook).CreateAt != o1.CreateAt { + t.Fatal("invalid returned webhook") + } + } + + if r2 := <-ss.Webhook().DeleteIncoming(o1.Id, model.GetMillis()); r2.Err != nil { + t.Fatal(r2.Err) + } + + if r3 := (<-ss.Webhook().GetIncoming(o1.Id, true)); r3.Err == nil { + t.Log(r3.Data) + t.Fatal("Missing id should have failed") + } +} + +func testWebhookStoreDeleteIncomingByChannel(t *testing.T, ss store.Store) { + o1 := buildIncomingWebhook() + + o1 = (<-ss.Webhook().SaveIncoming(o1)).Data.(*model.IncomingWebhook) + + if r1 := <-ss.Webhook().GetIncoming(o1.Id, true); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.IncomingWebhook).CreateAt != o1.CreateAt { + t.Fatal("invalid returned webhook") + } + } + + if r2 := <-ss.Webhook().PermanentDeleteIncomingByChannel(o1.ChannelId); r2.Err != nil { + t.Fatal(r2.Err) + } + + if r3 := (<-ss.Webhook().GetIncoming(o1.Id, true)); r3.Err == nil { + t.Log(r3.Data) + t.Fatal("Missing id should have failed") + } +} + +func testWebhookStoreDeleteIncomingByUser(t *testing.T, ss store.Store) { + o1 := buildIncomingWebhook() + + o1 = (<-ss.Webhook().SaveIncoming(o1)).Data.(*model.IncomingWebhook) + + if r1 := <-ss.Webhook().GetIncoming(o1.Id, true); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.IncomingWebhook).CreateAt != o1.CreateAt { + t.Fatal("invalid returned webhook") + } + } + + if r2 := <-ss.Webhook().PermanentDeleteIncomingByUser(o1.UserId); r2.Err != nil { + t.Fatal(r2.Err) + } + + if r3 := (<-ss.Webhook().GetIncoming(o1.Id, true)); r3.Err == nil { + t.Log(r3.Data) + t.Fatal("Missing id should have failed") + } +} + +func buildIncomingWebhook() *model.IncomingWebhook { + o1 := &model.IncomingWebhook{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.TeamId = model.NewId() + + return o1 +} + +func testWebhookStoreSaveOutgoing(t *testing.T, ss store.Store) { + o1 := model.OutgoingWebhook{} + o1.ChannelId = model.NewId() + o1.CreatorId = model.NewId() + o1.TeamId = model.NewId() + o1.CallbackURLs = []string{"http://nowhere.com/"} + + if err := (<-ss.Webhook().SaveOutgoing(&o1)).Err; err != nil { + t.Fatal("couldn't save item", err) + } + + if err := (<-ss.Webhook().SaveOutgoing(&o1)).Err; err == nil { + t.Fatal("shouldn't be able to update from save") + } +} + +func testWebhookStoreGetOutgoing(t *testing.T, ss store.Store) { + o1 := &model.OutgoingWebhook{} + o1.ChannelId = model.NewId() + o1.CreatorId = model.NewId() + o1.TeamId = model.NewId() + o1.CallbackURLs = []string{"http://nowhere.com/"} + + o1 = (<-ss.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook) + + if r1 := <-ss.Webhook().GetOutgoing(o1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.OutgoingWebhook).CreateAt != o1.CreateAt { + t.Fatal("invalid returned webhook") + } + } + + if err := (<-ss.Webhook().GetOutgoing("123")).Err; err == nil { + t.Fatal("Missing id should have failed") + } +} + +func testWebhookStoreGetOutgoingList(t *testing.T, ss store.Store) { + o1 := &model.OutgoingWebhook{} + o1.ChannelId = model.NewId() + o1.CreatorId = model.NewId() + o1.TeamId = model.NewId() + o1.CallbackURLs = []string{"http://nowhere.com/"} + + o1 = (<-ss.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook) + + o2 := &model.OutgoingWebhook{} + o2.ChannelId = model.NewId() + o2.CreatorId = model.NewId() + o2.TeamId = model.NewId() + o2.CallbackURLs = []string{"http://nowhere.com/"} + + o2 = (<-ss.Webhook().SaveOutgoing(o2)).Data.(*model.OutgoingWebhook) + + if r1 := <-ss.Webhook().GetOutgoingList(0, 1000); r1.Err != nil { + t.Fatal(r1.Err) + } else { + hooks := r1.Data.([]*model.OutgoingWebhook) + found1 := false + found2 := false + + for _, hook := range hooks { + if hook.CreateAt != o1.CreateAt { + found1 = true + } + + if hook.CreateAt != o2.CreateAt { + found2 = true + } + } + + if !found1 { + t.Fatal("missing hook1") + } + if !found2 { + t.Fatal("missing hook2") + } + } + + if result := <-ss.Webhook().GetOutgoingList(0, 2); result.Err != nil { + t.Fatal(result.Err) + } else { + if len(result.Data.([]*model.OutgoingWebhook)) != 2 { + t.Fatal("wrong number of hooks returned") + } + } +} + +func testWebhookStoreGetOutgoingByChannel(t *testing.T, ss store.Store) { + o1 := &model.OutgoingWebhook{} + o1.ChannelId = model.NewId() + o1.CreatorId = model.NewId() + o1.TeamId = model.NewId() + o1.CallbackURLs = []string{"http://nowhere.com/"} + + o1 = (<-ss.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook) + + if r1 := <-ss.Webhook().GetOutgoingByChannel(o1.ChannelId, 0, 100); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.([]*model.OutgoingWebhook)[0].CreateAt != o1.CreateAt { + t.Fatal("invalid returned webhook") + } + } + + if result := <-ss.Webhook().GetOutgoingByChannel("123", -1, -1); result.Err != nil { + t.Fatal(result.Err) + } else { + if len(result.Data.([]*model.OutgoingWebhook)) != 0 { + t.Fatal("no webhooks should have returned") + } + } +} + +func testWebhookStoreGetOutgoingByTeam(t *testing.T, ss store.Store) { + o1 := &model.OutgoingWebhook{} + o1.ChannelId = model.NewId() + o1.CreatorId = model.NewId() + o1.TeamId = model.NewId() + o1.CallbackURLs = []string{"http://nowhere.com/"} + + o1 = (<-ss.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook) + + if r1 := <-ss.Webhook().GetOutgoingByTeam(o1.TeamId, 0, 100); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.([]*model.OutgoingWebhook)[0].CreateAt != o1.CreateAt { + t.Fatal("invalid returned webhook") + } + } + + if result := <-ss.Webhook().GetOutgoingByTeam("123", -1, -1); result.Err != nil { + t.Fatal(result.Err) + } else { + if len(result.Data.([]*model.OutgoingWebhook)) != 0 { + t.Fatal("no webhooks should have returned") + } + } +} + +func testWebhookStoreDeleteOutgoing(t *testing.T, ss store.Store) { + o1 := &model.OutgoingWebhook{} + o1.ChannelId = model.NewId() + o1.CreatorId = model.NewId() + o1.TeamId = model.NewId() + o1.CallbackURLs = []string{"http://nowhere.com/"} + + o1 = (<-ss.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook) + + if r1 := <-ss.Webhook().GetOutgoing(o1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.OutgoingWebhook).CreateAt != o1.CreateAt { + t.Fatal("invalid returned webhook") + } + } + + if r2 := <-ss.Webhook().DeleteOutgoing(o1.Id, model.GetMillis()); r2.Err != nil { + t.Fatal(r2.Err) + } + + if r3 := (<-ss.Webhook().GetOutgoing(o1.Id)); r3.Err == nil { + t.Log(r3.Data) + t.Fatal("Missing id should have failed") + } +} + +func testWebhookStoreDeleteOutgoingByChannel(t *testing.T, ss store.Store) { + o1 := &model.OutgoingWebhook{} + o1.ChannelId = model.NewId() + o1.CreatorId = model.NewId() + o1.TeamId = model.NewId() + o1.CallbackURLs = []string{"http://nowhere.com/"} + + o1 = (<-ss.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook) + + if r1 := <-ss.Webhook().GetOutgoing(o1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.OutgoingWebhook).CreateAt != o1.CreateAt { + t.Fatal("invalid returned webhook") + } + } + + if r2 := <-ss.Webhook().PermanentDeleteOutgoingByChannel(o1.ChannelId); r2.Err != nil { + t.Fatal(r2.Err) + } + + if r3 := (<-ss.Webhook().GetOutgoing(o1.Id)); r3.Err == nil { + t.Log(r3.Data) + t.Fatal("Missing id should have failed") + } +} + +func testWebhookStoreDeleteOutgoingByUser(t *testing.T, ss store.Store) { + o1 := &model.OutgoingWebhook{} + o1.ChannelId = model.NewId() + o1.CreatorId = model.NewId() + o1.TeamId = model.NewId() + o1.CallbackURLs = []string{"http://nowhere.com/"} + + o1 = (<-ss.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook) + + if r1 := <-ss.Webhook().GetOutgoing(o1.Id); r1.Err != nil { + t.Fatal(r1.Err) + } else { + if r1.Data.(*model.OutgoingWebhook).CreateAt != o1.CreateAt { + t.Fatal("invalid returned webhook") + } + } + + if r2 := <-ss.Webhook().PermanentDeleteOutgoingByUser(o1.CreatorId); r2.Err != nil { + t.Fatal(r2.Err) + } + + if r3 := (<-ss.Webhook().GetOutgoing(o1.Id)); r3.Err == nil { + t.Log(r3.Data) + t.Fatal("Missing id should have failed") + } +} + +func testWebhookStoreUpdateOutgoing(t *testing.T, ss store.Store) { + o1 := &model.OutgoingWebhook{} + o1.ChannelId = model.NewId() + o1.CreatorId = model.NewId() + o1.TeamId = model.NewId() + o1.CallbackURLs = []string{"http://nowhere.com/"} + + o1 = (<-ss.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook) + + o1.Token = model.NewId() + + if r2 := <-ss.Webhook().UpdateOutgoing(o1); r2.Err != nil { + t.Fatal(r2.Err) + } +} + +func testWebhookStoreCountIncoming(t *testing.T, ss store.Store) { + o1 := &model.IncomingWebhook{} + o1.ChannelId = model.NewId() + o1.UserId = model.NewId() + o1.TeamId = model.NewId() + + o1 = (<-ss.Webhook().SaveIncoming(o1)).Data.(*model.IncomingWebhook) + + if r := <-ss.Webhook().AnalyticsIncomingCount(""); r.Err != nil { + t.Fatal(r.Err) + } else { + if r.Data.(int64) == 0 { + t.Fatal("should have at least 1 incoming hook") + } + } +} + +func testWebhookStoreCountOutgoing(t *testing.T, ss store.Store) { + o1 := &model.OutgoingWebhook{} + o1.ChannelId = model.NewId() + o1.CreatorId = model.NewId() + o1.TeamId = model.NewId() + o1.CallbackURLs = []string{"http://nowhere.com/"} + + o1 = (<-ss.Webhook().SaveOutgoing(o1)).Data.(*model.OutgoingWebhook) + + if r := <-ss.Webhook().AnalyticsOutgoingCount(""); r.Err != nil { + t.Fatal(r.Err) + } else { + if r.Data.(int64) == 0 { + t.Fatal("should have at least 1 outgoing hook") + } + } +} -- cgit v1.2.3-1-g7c22