github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/store/localcachelayer/user_layer_test.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package localcachelayer
     5  
     6  import (
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/require"
    11  
    12  	"github.com/mattermost/mattermost-server/v5/model"
    13  	"github.com/mattermost/mattermost-server/v5/store"
    14  	"github.com/mattermost/mattermost-server/v5/store/storetest"
    15  	"github.com/mattermost/mattermost-server/v5/store/storetest/mocks"
    16  )
    17  
    18  func TestUserStore(t *testing.T) {
    19  	StoreTestWithSqlSupplier(t, storetest.TestUserStore)
    20  }
    21  
    22  func TestUserStoreCache(t *testing.T) {
    23  	fakeUserIds := []string{"123"}
    24  	fakeUser := []*model.User{{
    25  		Id:          "123",
    26  		AuthData:    model.NewString("authData"),
    27  		AuthService: "authService",
    28  	}}
    29  
    30  	t.Run("first call not cached, second cached and returning same data", func(t *testing.T) {
    31  		mockStore := getMockStore()
    32  		mockCacheProvider := getMockCacheProvider()
    33  		cachedStore := NewLocalCacheLayer(mockStore, nil, nil, mockCacheProvider)
    34  
    35  		gotUser, err := cachedStore.User().GetProfileByIds(fakeUserIds, &store.UserGetByIdsOpts{}, true)
    36  		require.Nil(t, err)
    37  		assert.Equal(t, fakeUser, gotUser)
    38  		mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "GetProfileByIds", 1)
    39  
    40  		_, _ = cachedStore.User().GetProfileByIds(fakeUserIds, &store.UserGetByIdsOpts{}, true)
    41  		mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "GetProfileByIds", 1)
    42  	})
    43  
    44  	t.Run("first call not cached, second force not cached", func(t *testing.T) {
    45  		mockStore := getMockStore()
    46  		mockCacheProvider := getMockCacheProvider()
    47  		cachedStore := NewLocalCacheLayer(mockStore, nil, nil, mockCacheProvider)
    48  
    49  		gotUser, err := cachedStore.User().GetProfileByIds(fakeUserIds, &store.UserGetByIdsOpts{}, true)
    50  		require.Nil(t, err)
    51  		assert.Equal(t, fakeUser, gotUser)
    52  		mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "GetProfileByIds", 1)
    53  
    54  		_, _ = cachedStore.User().GetProfileByIds(fakeUserIds, &store.UserGetByIdsOpts{}, false)
    55  		mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "GetProfileByIds", 2)
    56  	})
    57  
    58  	t.Run("first call not cached, invalidate, and then not cached again", func(t *testing.T) {
    59  		mockStore := getMockStore()
    60  		mockCacheProvider := getMockCacheProvider()
    61  		cachedStore := NewLocalCacheLayer(mockStore, nil, nil, mockCacheProvider)
    62  
    63  		gotUser, err := cachedStore.User().GetProfileByIds(fakeUserIds, &store.UserGetByIdsOpts{}, true)
    64  		require.Nil(t, err)
    65  		assert.Equal(t, fakeUser, gotUser)
    66  
    67  		cachedStore.User().InvalidateProfileCacheForUser("123")
    68  
    69  		_, _ = cachedStore.User().GetProfileByIds(fakeUserIds, &store.UserGetByIdsOpts{}, true)
    70  		mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "GetProfileByIds", 2)
    71  	})
    72  
    73  	t.Run("should always return a copy of the stored data", func(t *testing.T) {
    74  		mockStore := getMockStore()
    75  		mockCacheProvider := getMockCacheProvider()
    76  		cachedStore := NewLocalCacheLayer(mockStore, nil, nil, mockCacheProvider)
    77  
    78  		storedUsers, err := mockStore.User().GetProfileByIds(fakeUserIds, &store.UserGetByIdsOpts{}, false)
    79  		require.Nil(t, err)
    80  
    81  		originalProps := make([]model.StringMap, len(storedUsers))
    82  
    83  		for i := 0; i < len(storedUsers); i++ {
    84  			originalProps[i] = storedUsers[i].NotifyProps
    85  			storedUsers[i].NotifyProps = map[string]string{}
    86  			storedUsers[i].NotifyProps["key"] = "somevalue"
    87  		}
    88  
    89  		cachedUsers, err := cachedStore.User().GetProfileByIds(fakeUserIds, &store.UserGetByIdsOpts{}, true)
    90  		require.Nil(t, err)
    91  
    92  		for i := 0; i < len(storedUsers); i++ {
    93  			assert.Equal(t, storedUsers[i].Id, cachedUsers[i].Id)
    94  			if storedUsers[i] == cachedUsers[i] {
    95  				assert.Fail(t, "should be different pointers")
    96  			}
    97  			cachedUsers[i].NotifyProps["key"] = "othervalue"
    98  			assert.NotEqual(t, storedUsers[i], cachedUsers[i])
    99  		}
   100  
   101  		cachedUsers, err = cachedStore.User().GetProfileByIds(fakeUserIds, &store.UserGetByIdsOpts{}, true)
   102  		require.Nil(t, err)
   103  		for i := 0; i < len(storedUsers); i++ {
   104  			assert.Equal(t, storedUsers[i], cachedUsers[i])
   105  			if storedUsers[i] == cachedUsers[i] {
   106  				assert.Fail(t, "should be different pointers")
   107  			}
   108  			cachedUsers[i].NotifyProps["key"] = "othervalue"
   109  			assert.NotEqual(t, storedUsers[i], cachedUsers[i])
   110  		}
   111  
   112  		for i := 0; i < len(storedUsers); i++ {
   113  			storedUsers[i].NotifyProps = originalProps[i]
   114  		}
   115  	})
   116  }
   117  
   118  func TestUserStoreProfilesInChannelCache(t *testing.T) {
   119  	fakeChannelId := "123"
   120  	fakeUserId := "456"
   121  	fakeMap := map[string]*model.User{
   122  		fakeUserId: {Id: "456"},
   123  	}
   124  
   125  	t.Run("first call not cached, second cached and returning same data", func(t *testing.T) {
   126  		mockStore := getMockStore()
   127  		mockCacheProvider := getMockCacheProvider()
   128  		cachedStore := NewLocalCacheLayer(mockStore, nil, nil, mockCacheProvider)
   129  
   130  		gotMap, err := cachedStore.User().GetAllProfilesInChannel(fakeChannelId, true)
   131  		require.Nil(t, err)
   132  		assert.Equal(t, fakeMap, gotMap)
   133  		mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "GetAllProfilesInChannel", 1)
   134  
   135  		_, _ = cachedStore.User().GetAllProfilesInChannel(fakeChannelId, true)
   136  		mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "GetAllProfilesInChannel", 1)
   137  	})
   138  
   139  	t.Run("first call not cached, second force not cached", func(t *testing.T) {
   140  		mockStore := getMockStore()
   141  		mockCacheProvider := getMockCacheProvider()
   142  		cachedStore := NewLocalCacheLayer(mockStore, nil, nil, mockCacheProvider)
   143  
   144  		gotMap, err := cachedStore.User().GetAllProfilesInChannel(fakeChannelId, true)
   145  		require.Nil(t, err)
   146  		assert.Equal(t, fakeMap, gotMap)
   147  		mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "GetAllProfilesInChannel", 1)
   148  
   149  		_, _ = cachedStore.User().GetAllProfilesInChannel(fakeChannelId, false)
   150  		mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "GetAllProfilesInChannel", 2)
   151  	})
   152  
   153  	t.Run("first call not cached, invalidate by channel, and then not cached again", func(t *testing.T) {
   154  		mockStore := getMockStore()
   155  		mockCacheProvider := getMockCacheProvider()
   156  		cachedStore := NewLocalCacheLayer(mockStore, nil, nil, mockCacheProvider)
   157  
   158  		gotMap, err := cachedStore.User().GetAllProfilesInChannel(fakeChannelId, true)
   159  		require.Nil(t, err)
   160  		assert.Equal(t, fakeMap, gotMap)
   161  		mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "GetAllProfilesInChannel", 1)
   162  
   163  		cachedStore.User().InvalidateProfilesInChannelCache("123")
   164  
   165  		_, _ = cachedStore.User().GetAllProfilesInChannel(fakeChannelId, true)
   166  		mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "GetAllProfilesInChannel", 2)
   167  	})
   168  
   169  	t.Run("first call not cached, invalidate by user, and then not cached again", func(t *testing.T) {
   170  		mockStore := getMockStore()
   171  		mockCacheProvider := getMockCacheProvider()
   172  		cachedStore := NewLocalCacheLayer(mockStore, nil, nil, mockCacheProvider)
   173  
   174  		gotMap, err := cachedStore.User().GetAllProfilesInChannel(fakeChannelId, true)
   175  		require.Nil(t, err)
   176  		assert.Equal(t, fakeMap, gotMap)
   177  		mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "GetAllProfilesInChannel", 1)
   178  
   179  		cachedStore.User().InvalidateProfilesInChannelCacheByUser("456")
   180  
   181  		_, _ = cachedStore.User().GetAllProfilesInChannel(fakeChannelId, true)
   182  		mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "GetAllProfilesInChannel", 2)
   183  	})
   184  }
   185  
   186  func TestUserStoreGetCache(t *testing.T) {
   187  	fakeUserId := "123"
   188  	fakeUser := &model.User{
   189  		Id:          "123",
   190  		AuthData:    model.NewString("authData"),
   191  		AuthService: "authService",
   192  	}
   193  	t.Run("first call not cached, second cached and returning same data", func(t *testing.T) {
   194  		mockStore := getMockStore()
   195  		mockCacheProvider := getMockCacheProvider()
   196  		cachedStore := NewLocalCacheLayer(mockStore, nil, nil, mockCacheProvider)
   197  
   198  		gotUser, err := cachedStore.User().Get(fakeUserId)
   199  		require.Nil(t, err)
   200  		assert.Equal(t, fakeUser, gotUser)
   201  		mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "Get", 1)
   202  
   203  		_, _ = cachedStore.User().Get(fakeUserId)
   204  		mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "Get", 1)
   205  	})
   206  
   207  	t.Run("first call not cached, invalidate, and then not cached again", func(t *testing.T) {
   208  		mockStore := getMockStore()
   209  		mockCacheProvider := getMockCacheProvider()
   210  		cachedStore := NewLocalCacheLayer(mockStore, nil, nil, mockCacheProvider)
   211  
   212  		gotUser, err := cachedStore.User().Get(fakeUserId)
   213  		require.Nil(t, err)
   214  		assert.Equal(t, fakeUser, gotUser)
   215  		mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "Get", 1)
   216  
   217  		cachedStore.User().InvalidateProfileCacheForUser("123")
   218  
   219  		_, _ = cachedStore.User().Get(fakeUserId)
   220  		mockStore.User().(*mocks.UserStore).AssertNumberOfCalls(t, "Get", 2)
   221  	})
   222  
   223  	t.Run("should always return a copy of the stored data", func(t *testing.T) {
   224  		mockStore := getMockStore()
   225  		mockCacheProvider := getMockCacheProvider()
   226  		cachedStore := NewLocalCacheLayer(mockStore, nil, nil, mockCacheProvider)
   227  
   228  		storedUser, err := mockStore.User().Get(fakeUserId)
   229  		require.Nil(t, err)
   230  		originalProps := storedUser.NotifyProps
   231  
   232  		storedUser.NotifyProps = map[string]string{}
   233  		storedUser.NotifyProps["key"] = "somevalue"
   234  
   235  		cachedUser, err := cachedStore.User().Get(fakeUserId)
   236  		require.Nil(t, err)
   237  		assert.Equal(t, storedUser, cachedUser)
   238  		if storedUser == cachedUser {
   239  			assert.Fail(t, "should be different pointers")
   240  		}
   241  		cachedUser.NotifyProps["key"] = "othervalue"
   242  		assert.NotEqual(t, storedUser, cachedUser)
   243  
   244  		cachedUser, err = cachedStore.User().Get(fakeUserId)
   245  		require.Nil(t, err)
   246  		assert.Equal(t, storedUser, cachedUser)
   247  		if storedUser == cachedUser {
   248  			assert.Fail(t, "should be different pointers")
   249  		}
   250  		cachedUser.NotifyProps["key"] = "othervalue"
   251  		assert.NotEqual(t, storedUser, cachedUser)
   252  
   253  		storedUser.NotifyProps = originalProps
   254  	})
   255  }