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 }