github.com/haalcala/mattermost-server-change-repo@v0.0.0-20210713015153-16753fbeee5f/store/storetest/bot_store.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package storetest
     5  
     6  import (
     7  	"errors"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/require"
    11  
    12  	"github.com/mattermost/mattermost-server/v5/model"
    13  	"github.com/mattermost/mattermost-server/v5/store"
    14  )
    15  
    16  func makeBotWithUser(t *testing.T, ss store.Store, bot *model.Bot) (*model.Bot, *model.User) {
    17  	user, err := ss.User().Save(model.UserFromBot(bot))
    18  	require.NoError(t, err)
    19  
    20  	bot.UserId = user.Id
    21  	bot, nErr := ss.Bot().Save(bot)
    22  	require.NoError(t, nErr)
    23  
    24  	return bot, user
    25  }
    26  
    27  func TestBotStore(t *testing.T, ss store.Store, s SqlStore) {
    28  	t.Run("Get", func(t *testing.T) { testBotStoreGet(t, ss, s) })
    29  	t.Run("GetAll", func(t *testing.T) { testBotStoreGetAll(t, ss, s) })
    30  	t.Run("Save", func(t *testing.T) { testBotStoreSave(t, ss) })
    31  	t.Run("Update", func(t *testing.T) { testBotStoreUpdate(t, ss) })
    32  	t.Run("PermanentDelete", func(t *testing.T) { testBotStorePermanentDelete(t, ss) })
    33  }
    34  
    35  func testBotStoreGet(t *testing.T, ss store.Store, s SqlStore) {
    36  	deletedBot, _ := makeBotWithUser(t, ss, &model.Bot{
    37  		Username:       "deleted_bot",
    38  		Description:    "A deleted bot",
    39  		OwnerId:        model.NewId(),
    40  		LastIconUpdate: model.GetMillis(),
    41  	})
    42  	deletedBot.DeleteAt = 1
    43  	deletedBot, err := ss.Bot().Update(deletedBot)
    44  	require.NoError(t, err)
    45  	defer func() { require.NoError(t, ss.Bot().PermanentDelete(deletedBot.UserId)) }()
    46  	defer func() { require.NoError(t, ss.User().PermanentDelete(deletedBot.UserId)) }()
    47  
    48  	permanentlyDeletedBot, _ := makeBotWithUser(t, ss, &model.Bot{
    49  		Username:       "permanently_deleted_bot",
    50  		Description:    "A permanently deleted bot",
    51  		OwnerId:        model.NewId(),
    52  		LastIconUpdate: model.GetMillis(),
    53  		DeleteAt:       0,
    54  	})
    55  	require.NoError(t, ss.Bot().PermanentDelete(permanentlyDeletedBot.UserId))
    56  	defer func() { require.NoError(t, ss.User().PermanentDelete(permanentlyDeletedBot.UserId)) }()
    57  
    58  	b1, _ := makeBotWithUser(t, ss, &model.Bot{
    59  		Username:       "b1",
    60  		Description:    "The first bot",
    61  		OwnerId:        model.NewId(),
    62  		LastIconUpdate: model.GetMillis(),
    63  	})
    64  	defer func() { require.NoError(t, ss.Bot().PermanentDelete(b1.UserId)) }()
    65  	defer func() { require.NoError(t, ss.User().PermanentDelete(b1.UserId)) }()
    66  
    67  	b2, _ := makeBotWithUser(t, ss, &model.Bot{
    68  		Username:       "b2",
    69  		Description:    "The second bot",
    70  		OwnerId:        model.NewId(),
    71  		LastIconUpdate: 0,
    72  	})
    73  	defer func() { require.NoError(t, ss.Bot().PermanentDelete(b2.UserId)) }()
    74  	defer func() { require.NoError(t, ss.User().PermanentDelete(b2.UserId)) }()
    75  
    76  	// Artificially set b2.LastIconUpdate to NULL to verify handling of same.
    77  	_, sqlErr := s.GetMaster().Exec("UPDATE Bots SET LastIconUpdate = NULL WHERE UserId = '" + b2.UserId + "'")
    78  	require.NoError(t, sqlErr)
    79  
    80  	t.Run("get non-existent bot", func(t *testing.T) {
    81  		_, err := ss.Bot().Get("unknown", false)
    82  		require.Error(t, err)
    83  		var nfErr *store.ErrNotFound
    84  		require.True(t, errors.As(err, &nfErr))
    85  	})
    86  
    87  	t.Run("get deleted bot", func(t *testing.T) {
    88  		_, err := ss.Bot().Get(deletedBot.UserId, false)
    89  		require.Error(t, err)
    90  		var nfErr *store.ErrNotFound
    91  		require.True(t, errors.As(err, &nfErr))
    92  	})
    93  
    94  	t.Run("get deleted bot, include deleted", func(t *testing.T) {
    95  		bot, err := ss.Bot().Get(deletedBot.UserId, true)
    96  		require.NoError(t, err)
    97  		require.Equal(t, deletedBot, bot)
    98  	})
    99  
   100  	t.Run("get permanently deleted bot", func(t *testing.T) {
   101  		_, err := ss.Bot().Get(permanentlyDeletedBot.UserId, false)
   102  		require.Error(t, err)
   103  		var nfErr *store.ErrNotFound
   104  		require.True(t, errors.As(err, &nfErr))
   105  	})
   106  
   107  	t.Run("get bot 1", func(t *testing.T) {
   108  		bot, err := ss.Bot().Get(b1.UserId, false)
   109  		require.NoError(t, err)
   110  		require.Equal(t, b1, bot)
   111  	})
   112  
   113  	t.Run("get bot 2", func(t *testing.T) {
   114  		bot, err := ss.Bot().Get(b2.UserId, false)
   115  		require.NoError(t, err)
   116  		require.Equal(t, b2, bot)
   117  	})
   118  }
   119  
   120  func testBotStoreGetAll(t *testing.T, ss store.Store, s SqlStore) {
   121  	OwnerId1 := model.NewId()
   122  	OwnerId2 := model.NewId()
   123  
   124  	deletedBot, _ := makeBotWithUser(t, ss, &model.Bot{
   125  		Username:       "deleted_bot",
   126  		Description:    "A deleted bot",
   127  		OwnerId:        OwnerId1,
   128  		LastIconUpdate: model.GetMillis(),
   129  	})
   130  	deletedBot.DeleteAt = 1
   131  	deletedBot, err := ss.Bot().Update(deletedBot)
   132  	require.NoError(t, err)
   133  	defer func() { require.NoError(t, ss.Bot().PermanentDelete(deletedBot.UserId)) }()
   134  	defer func() { require.NoError(t, ss.User().PermanentDelete(deletedBot.UserId)) }()
   135  
   136  	permanentlyDeletedBot, _ := makeBotWithUser(t, ss, &model.Bot{
   137  		Username:       "permanently_deleted_bot",
   138  		Description:    "A permanently deleted bot",
   139  		OwnerId:        OwnerId1,
   140  		LastIconUpdate: model.GetMillis(),
   141  		DeleteAt:       0,
   142  	})
   143  	require.NoError(t, ss.Bot().PermanentDelete(permanentlyDeletedBot.UserId))
   144  	defer func() { require.NoError(t, ss.User().PermanentDelete(permanentlyDeletedBot.UserId)) }()
   145  
   146  	b1, _ := makeBotWithUser(t, ss, &model.Bot{
   147  		Username:       "b1",
   148  		Description:    "The first bot",
   149  		OwnerId:        OwnerId1,
   150  		LastIconUpdate: model.GetMillis(),
   151  	})
   152  	defer func() { require.NoError(t, ss.Bot().PermanentDelete(b1.UserId)) }()
   153  	defer func() { require.NoError(t, ss.User().PermanentDelete(b1.UserId)) }()
   154  
   155  	b2, _ := makeBotWithUser(t, ss, &model.Bot{
   156  		Username:       "b2",
   157  		Description:    "The second bot",
   158  		OwnerId:        OwnerId1,
   159  		LastIconUpdate: 0,
   160  	})
   161  	defer func() { require.NoError(t, ss.Bot().PermanentDelete(b2.UserId)) }()
   162  	defer func() { require.NoError(t, ss.User().PermanentDelete(b2.UserId)) }()
   163  
   164  	// Artificially set b2.LastIconUpdate to NULL to verify handling of same.
   165  	_, sqlErr := s.GetMaster().Exec("UPDATE Bots SET LastIconUpdate = NULL WHERE UserId = '" + b2.UserId + "'")
   166  	require.NoError(t, sqlErr)
   167  
   168  	t.Run("get original bots", func(t *testing.T) {
   169  		bot, err := ss.Bot().GetAll(&model.BotGetOptions{Page: 0, PerPage: 10})
   170  		require.NoError(t, err)
   171  		require.Equal(t, []*model.Bot{
   172  			b1,
   173  			b2,
   174  		}, bot)
   175  	})
   176  
   177  	b3, _ := makeBotWithUser(t, ss, &model.Bot{
   178  		Username:    "b3",
   179  		Description: "The third bot",
   180  		OwnerId:     OwnerId1,
   181  	})
   182  	defer func() { require.NoError(t, ss.Bot().PermanentDelete(b3.UserId)) }()
   183  	defer func() { require.NoError(t, ss.User().PermanentDelete(b3.UserId)) }()
   184  
   185  	b4, _ := makeBotWithUser(t, ss, &model.Bot{
   186  		Username:    "b4",
   187  		Description: "The fourth bot",
   188  		OwnerId:     OwnerId2,
   189  	})
   190  	defer func() { require.NoError(t, ss.Bot().PermanentDelete(b4.UserId)) }()
   191  	defer func() { require.NoError(t, ss.User().PermanentDelete(b4.UserId)) }()
   192  
   193  	deletedUser := model.User{
   194  		Email:    MakeEmail(),
   195  		Username: model.NewId(),
   196  	}
   197  	_, err1 := ss.User().Save(&deletedUser)
   198  	require.NoError(t, err1, "couldn't save user")
   199  
   200  	deletedUser.DeleteAt = model.GetMillis()
   201  	_, err2 := ss.User().Update(&deletedUser, true)
   202  	require.NoError(t, err2, "couldn't delete user")
   203  
   204  	defer func() { require.NoError(t, ss.User().PermanentDelete(deletedUser.Id)) }()
   205  	ob5, _ := makeBotWithUser(t, ss, &model.Bot{
   206  		Username:    "ob5",
   207  		Description: "Orphaned bot 5",
   208  		OwnerId:     deletedUser.Id,
   209  	})
   210  	defer func() { require.NoError(t, ss.Bot().PermanentDelete(b4.UserId)) }()
   211  	defer func() { require.NoError(t, ss.User().PermanentDelete(b4.UserId)) }()
   212  
   213  	t.Run("get newly created bot stoo", func(t *testing.T) {
   214  		bots, err := ss.Bot().GetAll(&model.BotGetOptions{Page: 0, PerPage: 10})
   215  		require.NoError(t, err)
   216  		require.Equal(t, []*model.Bot{
   217  			b1,
   218  			b2,
   219  			b3,
   220  			b4,
   221  			ob5,
   222  		}, bots)
   223  	})
   224  
   225  	t.Run("get orphaned", func(t *testing.T) {
   226  		bots, err := ss.Bot().GetAll(&model.BotGetOptions{Page: 0, PerPage: 10, OnlyOrphaned: true})
   227  		require.NoError(t, err)
   228  		require.Equal(t, []*model.Bot{
   229  			ob5,
   230  		}, bots)
   231  	})
   232  
   233  	t.Run("get page=0, per_page=2", func(t *testing.T) {
   234  		bots, err := ss.Bot().GetAll(&model.BotGetOptions{Page: 0, PerPage: 2})
   235  		require.NoError(t, err)
   236  		require.Equal(t, []*model.Bot{
   237  			b1,
   238  			b2,
   239  		}, bots)
   240  	})
   241  
   242  	t.Run("get page=1, limit=2", func(t *testing.T) {
   243  		bots, err := ss.Bot().GetAll(&model.BotGetOptions{Page: 1, PerPage: 2})
   244  		require.NoError(t, err)
   245  		require.Equal(t, []*model.Bot{
   246  			b3,
   247  			b4,
   248  		}, bots)
   249  	})
   250  
   251  	t.Run("get page=5, perpage=1000", func(t *testing.T) {
   252  		bots, err := ss.Bot().GetAll(&model.BotGetOptions{Page: 5, PerPage: 1000})
   253  		require.NoError(t, err)
   254  		require.Equal(t, []*model.Bot{}, bots)
   255  	})
   256  
   257  	t.Run("get offset=0, limit=2, include deleted", func(t *testing.T) {
   258  		bots, err := ss.Bot().GetAll(&model.BotGetOptions{Page: 0, PerPage: 2, IncludeDeleted: true})
   259  		require.NoError(t, err)
   260  		require.Equal(t, []*model.Bot{
   261  			deletedBot,
   262  			b1,
   263  		}, bots)
   264  	})
   265  
   266  	t.Run("get offset=2, limit=2, include deleted", func(t *testing.T) {
   267  		bots, err := ss.Bot().GetAll(&model.BotGetOptions{Page: 1, PerPage: 2, IncludeDeleted: true})
   268  		require.NoError(t, err)
   269  		require.Equal(t, []*model.Bot{
   270  			b2,
   271  			b3,
   272  		}, bots)
   273  	})
   274  
   275  	t.Run("get offset=0, limit=10, creator id 1", func(t *testing.T) {
   276  		bots, err := ss.Bot().GetAll(&model.BotGetOptions{Page: 0, PerPage: 10, OwnerId: OwnerId1})
   277  		require.NoError(t, err)
   278  		require.Equal(t, []*model.Bot{
   279  			b1,
   280  			b2,
   281  			b3,
   282  		}, bots)
   283  	})
   284  
   285  	t.Run("get offset=0, limit=10, creator id 2", func(t *testing.T) {
   286  		bots, err := ss.Bot().GetAll(&model.BotGetOptions{Page: 0, PerPage: 10, OwnerId: OwnerId2})
   287  		require.NoError(t, err)
   288  		require.Equal(t, []*model.Bot{
   289  			b4,
   290  		}, bots)
   291  	})
   292  
   293  	t.Run("get offset=0, limit=10, include deleted, creator id 1", func(t *testing.T) {
   294  		bots, err := ss.Bot().GetAll(&model.BotGetOptions{Page: 0, PerPage: 10, IncludeDeleted: true, OwnerId: OwnerId1})
   295  		require.NoError(t, err)
   296  		require.Equal(t, []*model.Bot{
   297  			deletedBot,
   298  			b1,
   299  			b2,
   300  			b3,
   301  		}, bots)
   302  	})
   303  
   304  	t.Run("get offset=0, limit=10, include deleted, creator id 2", func(t *testing.T) {
   305  		bots, err := ss.Bot().GetAll(&model.BotGetOptions{Page: 0, PerPage: 10, IncludeDeleted: true, OwnerId: OwnerId2})
   306  		require.NoError(t, err)
   307  		require.Equal(t, []*model.Bot{
   308  			b4,
   309  		}, bots)
   310  	})
   311  }
   312  
   313  func testBotStoreSave(t *testing.T, ss store.Store) {
   314  	t.Run("invalid bot", func(t *testing.T) {
   315  		bot := &model.Bot{
   316  			UserId:      model.NewId(),
   317  			Username:    "invalid bot",
   318  			Description: "description",
   319  		}
   320  
   321  		_, err := ss.Bot().Save(bot)
   322  		require.Error(t, err)
   323  		var appErr *model.AppError
   324  		require.True(t, errors.As(err, &appErr))
   325  		// require.Equal(t, "model.bot.is_valid.username.app_error", err.Id)
   326  	})
   327  
   328  	t.Run("normal bot", func(t *testing.T) {
   329  		bot := &model.Bot{
   330  			Username:    "normal_bot",
   331  			Description: "description",
   332  			OwnerId:     model.NewId(),
   333  		}
   334  
   335  		user, err := ss.User().Save(model.UserFromBot(bot))
   336  		require.NoError(t, err)
   337  		defer func() { require.NoError(t, ss.User().PermanentDelete(user.Id)) }()
   338  		bot.UserId = user.Id
   339  
   340  		returnedNewBot, nErr := ss.Bot().Save(bot)
   341  		require.NoError(t, nErr)
   342  		defer func() { require.NoError(t, ss.Bot().PermanentDelete(bot.UserId)) }()
   343  
   344  		// Verify the returned bot matches the saved bot, modulo expected changes
   345  		require.NotEqual(t, 0, returnedNewBot.CreateAt)
   346  		require.NotEqual(t, 0, returnedNewBot.UpdateAt)
   347  		require.Equal(t, returnedNewBot.CreateAt, returnedNewBot.UpdateAt)
   348  		bot.UserId = returnedNewBot.UserId
   349  		bot.CreateAt = returnedNewBot.CreateAt
   350  		bot.UpdateAt = returnedNewBot.UpdateAt
   351  		bot.DeleteAt = 0
   352  		require.Equal(t, bot, returnedNewBot)
   353  
   354  		// Verify the actual bot in the database matches the saved bot.
   355  		actualNewBot, nErr := ss.Bot().Get(bot.UserId, false)
   356  		require.NoError(t, nErr)
   357  		require.Equal(t, bot, actualNewBot)
   358  	})
   359  }
   360  
   361  func testBotStoreUpdate(t *testing.T, ss store.Store) {
   362  	t.Run("invalid bot should fail to update", func(t *testing.T) {
   363  		existingBot, _ := makeBotWithUser(t, ss, &model.Bot{
   364  			Username: "existing_bot",
   365  			OwnerId:  model.NewId(),
   366  		})
   367  		defer func() { require.NoError(t, ss.Bot().PermanentDelete(existingBot.UserId)) }()
   368  		defer func() { require.NoError(t, ss.User().PermanentDelete(existingBot.UserId)) }()
   369  
   370  		bot := existingBot.Clone()
   371  		bot.Username = "invalid username"
   372  		_, err := ss.Bot().Update(bot)
   373  		require.Error(t, err)
   374  		var appErr *model.AppError
   375  		require.True(t, errors.As(err, &appErr))
   376  		require.Equal(t, "model.bot.is_valid.username.app_error", appErr.Id)
   377  	})
   378  
   379  	t.Run("existing bot should update", func(t *testing.T) {
   380  		existingBot, _ := makeBotWithUser(t, ss, &model.Bot{
   381  			Username: "existing_bot",
   382  			OwnerId:  model.NewId(),
   383  		})
   384  		defer func() { require.NoError(t, ss.Bot().PermanentDelete(existingBot.UserId)) }()
   385  		defer func() { require.NoError(t, ss.User().PermanentDelete(existingBot.UserId)) }()
   386  
   387  		bot := existingBot.Clone()
   388  		bot.OwnerId = model.NewId()
   389  		bot.Description = "updated description"
   390  		bot.CreateAt = 999999       // Ignored
   391  		bot.UpdateAt = 999999       // Ignored
   392  		bot.LastIconUpdate = 100000 // Allowed
   393  		bot.DeleteAt = 100000       // Allowed
   394  
   395  		returnedBot, err := ss.Bot().Update(bot)
   396  		require.NoError(t, err)
   397  
   398  		// Verify the returned bot matches the updated bot, modulo expected timestamp changes
   399  		require.Equal(t, existingBot.CreateAt, returnedBot.CreateAt)
   400  		require.NotEqual(t, bot.UpdateAt, returnedBot.UpdateAt, "update should have advanced UpdateAt")
   401  		require.True(t, returnedBot.UpdateAt > bot.UpdateAt, "update should have advanced UpdateAt")
   402  		require.NotEqual(t, 99999, returnedBot.UpdateAt, "should have ignored user-provided UpdateAt")
   403  		require.Equal(t, bot.LastIconUpdate, returnedBot.LastIconUpdate, "should have marked icon as updated")
   404  		require.Equal(t, bot.DeleteAt, returnedBot.DeleteAt, "should have marked bot as deleted")
   405  		bot.CreateAt = returnedBot.CreateAt
   406  		bot.UpdateAt = returnedBot.UpdateAt
   407  
   408  		// Verify the actual (now deleted) bot in the database
   409  		actualBot, err := ss.Bot().Get(bot.UserId, true)
   410  		require.NoError(t, err)
   411  		require.Equal(t, bot, actualBot)
   412  	})
   413  
   414  	t.Run("deleted bot should update, restoring", func(t *testing.T) {
   415  		existingBot, _ := makeBotWithUser(t, ss, &model.Bot{
   416  			Username: "existing_bot",
   417  			OwnerId:  model.NewId(),
   418  		})
   419  		defer func() { require.NoError(t, ss.Bot().PermanentDelete(existingBot.UserId)) }()
   420  		defer func() { require.NoError(t, ss.User().PermanentDelete(existingBot.UserId)) }()
   421  
   422  		existingBot.DeleteAt = 100000
   423  		existingBot, err := ss.Bot().Update(existingBot)
   424  		require.NoError(t, err)
   425  
   426  		bot := existingBot.Clone()
   427  		bot.DeleteAt = 0
   428  
   429  		returnedBot, err := ss.Bot().Update(bot)
   430  		require.NoError(t, err)
   431  
   432  		// Verify the returned bot matches the updated bot, modulo expected timestamp changes
   433  		require.EqualValues(t, 0, returnedBot.DeleteAt)
   434  		bot.UpdateAt = returnedBot.UpdateAt
   435  
   436  		// Verify the actual bot in the database
   437  		actualBot, err := ss.Bot().Get(bot.UserId, false)
   438  		require.NoError(t, err)
   439  		require.Equal(t, bot, actualBot)
   440  	})
   441  }
   442  
   443  func testBotStorePermanentDelete(t *testing.T, ss store.Store) {
   444  	b1, _ := makeBotWithUser(t, ss, &model.Bot{
   445  		Username: "b1",
   446  		OwnerId:  model.NewId(),
   447  	})
   448  	defer func() { require.NoError(t, ss.Bot().PermanentDelete(b1.UserId)) }()
   449  	defer func() { require.NoError(t, ss.User().PermanentDelete(b1.UserId)) }()
   450  
   451  	b2, _ := makeBotWithUser(t, ss, &model.Bot{
   452  		Username: "b2",
   453  		OwnerId:  model.NewId(),
   454  	})
   455  	defer func() { require.NoError(t, ss.Bot().PermanentDelete(b2.UserId)) }()
   456  	defer func() { require.NoError(t, ss.User().PermanentDelete(b2.UserId)) }()
   457  
   458  	t.Run("permanently delete a non-existent bot", func(t *testing.T) {
   459  		err := ss.Bot().PermanentDelete("unknown")
   460  		require.NoError(t, err)
   461  	})
   462  
   463  	t.Run("permanently delete bot", func(t *testing.T) {
   464  		err := ss.Bot().PermanentDelete(b1.UserId)
   465  		require.NoError(t, err)
   466  
   467  		_, err = ss.Bot().Get(b1.UserId, false)
   468  		require.Error(t, err)
   469  		var nfErr *store.ErrNotFound
   470  		require.True(t, errors.As(err, &nfErr))
   471  	})
   472  }