MM-13664 Cache external link metadata when populating post metadata (#10128)
* MM-13664 Added LinkMetadata types * MM-13664 Use LinkMetadata when populating post metadata * Fix unused import * Fix index name on SQLite * Finish adding unit tests * Address feedback * Increase max length of URL column to 2048 characters
Этот коммит содержится в:
коммит произвёл
Carlos Tadeu Panato Junior
родитель
5c76e90a83
Коммит
26684716aa
@@ -187,6 +187,10 @@ func (s *LayeredStore) Group() GroupStore {
|
||||
return s.GroupStore
|
||||
}
|
||||
|
||||
func (s *LayeredStore) LinkMetadata() LinkMetadataStore {
|
||||
return s.DatabaseLayer.LinkMetadata()
|
||||
}
|
||||
|
||||
func (s *LayeredStore) MarkSystemRanUnitTests() {
|
||||
s.DatabaseLayer.MarkSystemRanUnitTests()
|
||||
}
|
||||
|
||||
88
store/sqlstore/link_metadata_store.go
Обычный файл
88
store/sqlstore/link_metadata_store.go
Обычный файл
@@ -0,0 +1,88 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package sqlstore
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"net/http"
|
||||
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
"github.com/mattermost/mattermost-server/store"
|
||||
)
|
||||
|
||||
type SqlLinkMetadataStore struct {
|
||||
SqlStore
|
||||
}
|
||||
|
||||
func NewSqlLinkMetadataStore(sqlStore SqlStore) store.LinkMetadataStore {
|
||||
s := &SqlLinkMetadataStore{sqlStore}
|
||||
|
||||
for _, db := range sqlStore.GetAllConns() {
|
||||
table := db.AddTableWithName(model.LinkMetadata{}, "LinkMetadata").SetKeys(false, "Hash")
|
||||
table.ColMap("URL").SetMaxSize(2048)
|
||||
table.ColMap("Type").SetMaxSize(16)
|
||||
table.ColMap("Data").SetMaxSize(4096)
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (s SqlLinkMetadataStore) CreateIndexesIfNotExists() {
|
||||
if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
|
||||
s.CreateCompositeIndexIfNotExists("idx_link_metadata_url_timestamp", "LinkMetadata", []string{"URL(512)", "Timestamp"})
|
||||
} else {
|
||||
s.CreateCompositeIndexIfNotExists("idx_link_metadata_url_timestamp", "LinkMetadata", []string{"URL", "Timestamp"})
|
||||
}
|
||||
}
|
||||
|
||||
func (s SqlLinkMetadataStore) Save(metadata *model.LinkMetadata) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
if result.Err = metadata.IsValid(); result.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
metadata.PreSave()
|
||||
|
||||
err := s.GetMaster().Insert(metadata)
|
||||
if err != nil {
|
||||
result.Err = model.NewAppError("SqlLinkMetadataStore.Save", "store.sql_link_metadata.save.app_error", nil, "url="+metadata.URL+", "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
result.Data = metadata
|
||||
})
|
||||
}
|
||||
|
||||
func (s SqlLinkMetadataStore) Get(url string, timestamp int64) store.StoreChannel {
|
||||
return store.Do(func(result *store.StoreResult) {
|
||||
var metadata *model.LinkMetadata
|
||||
|
||||
err := s.GetReplica().SelectOne(&metadata,
|
||||
`SELECT
|
||||
*
|
||||
FROM
|
||||
LinkMetadata
|
||||
WHERE
|
||||
URL = :URL
|
||||
AND Timestamp = :Timestamp`, map[string]interface{}{"URL": url, "Timestamp": timestamp})
|
||||
if err != nil {
|
||||
result.Err = model.NewAppError("SqlLinkMetadataStore.Get", "store.sql_link_metadata.get.app_error", nil, "url="+url+", "+err.Error(), http.StatusInternalServerError)
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
result.Err.StatusCode = http.StatusNotFound
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
err = metadata.DeserializeDataToConcreteType()
|
||||
if err != nil {
|
||||
result.Err = model.NewAppError("SqlLinkMetadataStore.Get", "store.sql_link_metadata.get.app_error", nil, "url="+url+", "+err.Error(), http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
result.Data = metadata
|
||||
})
|
||||
}
|
||||
14
store/sqlstore/link_metadata_store_test.go
Обычный файл
14
store/sqlstore/link_metadata_store_test.go
Обычный файл
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package sqlstore
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/mattermost/mattermost-server/store/storetest"
|
||||
)
|
||||
|
||||
func TestLinkMetadataStore(t *testing.T) {
|
||||
StoreTest(t, storetest.TestLinkMetadataStore)
|
||||
}
|
||||
@@ -96,4 +96,5 @@ type SqlStore interface {
|
||||
Scheme() store.SchemeStore
|
||||
TermsOfService() store.TermsOfServiceStore
|
||||
UserTermsOfService() store.UserTermsOfServiceStore
|
||||
LinkMetadata() store.LinkMetadataStore
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/dyatlov/go-opengraph/opengraph"
|
||||
"github.com/go-sql-driver/mysql"
|
||||
"github.com/lib/pq"
|
||||
"github.com/mattermost/gorp"
|
||||
@@ -95,6 +96,7 @@ type SqlSupplierOldStores struct {
|
||||
TermsOfService store.TermsOfServiceStore
|
||||
group store.GroupStore
|
||||
UserTermsOfService store.UserTermsOfServiceStore
|
||||
linkMetadata store.LinkMetadataStore
|
||||
}
|
||||
|
||||
type SqlSupplier struct {
|
||||
@@ -145,6 +147,7 @@ func NewSqlSupplier(settings model.SqlSettings, metrics einterfaces.MetricsInter
|
||||
supplier.oldStores.plugin = NewSqlPluginStore(supplier)
|
||||
supplier.oldStores.TermsOfService = NewSqlTermsOfServiceStore(supplier, metrics)
|
||||
supplier.oldStores.UserTermsOfService = NewSqlUserTermsOfServiceStore(supplier)
|
||||
supplier.oldStores.linkMetadata = NewSqlLinkMetadataStore(supplier)
|
||||
|
||||
initSqlSupplierReactions(supplier)
|
||||
initSqlSupplierRoles(supplier)
|
||||
@@ -183,6 +186,7 @@ func NewSqlSupplier(settings model.SqlSettings, metrics einterfaces.MetricsInter
|
||||
supplier.oldStores.plugin.(*SqlPluginStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.TermsOfService.(SqlTermsOfServiceStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.UserTermsOfService.(SqlUserTermsOfServiceStore).CreateIndexesIfNotExists()
|
||||
supplier.oldStores.linkMetadata.(*SqlLinkMetadataStore).CreateIndexesIfNotExists()
|
||||
|
||||
supplier.CreateIndexesIfNotExistsGroups()
|
||||
|
||||
@@ -1032,6 +1036,10 @@ func (ss *SqlSupplier) Group() store.GroupStore {
|
||||
return ss.oldStores.group
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) LinkMetadata() store.LinkMetadataStore {
|
||||
return ss.oldStores.linkMetadata
|
||||
}
|
||||
|
||||
func (ss *SqlSupplier) DropAllTables() {
|
||||
ss.master.TruncateTables()
|
||||
}
|
||||
@@ -1051,6 +1059,10 @@ func (me mattermConverter) ToDb(val interface{}) (interface{}, error) {
|
||||
return model.StringInterfaceToJson(t), nil
|
||||
case map[string]interface{}:
|
||||
return model.StringInterfaceToJson(model.StringInterface(t)), nil
|
||||
case JSONSerializable:
|
||||
return t.ToJson(), nil
|
||||
case *opengraph.OpenGraph:
|
||||
return json.Marshal(t)
|
||||
}
|
||||
|
||||
return val, nil
|
||||
@@ -1113,6 +1125,10 @@ func (me mattermConverter) FromDb(target interface{}) (gorp.CustomScanner, bool)
|
||||
return gorp.CustomScanner{}, false
|
||||
}
|
||||
|
||||
type JSONSerializable interface {
|
||||
ToJson() string
|
||||
}
|
||||
|
||||
func convertMySQLFullTextColumnsToPostgres(columnNames string) string {
|
||||
columns := strings.Split(columnNames, ", ")
|
||||
concatenatedColumnNames := ""
|
||||
|
||||
@@ -68,6 +68,7 @@ type Store interface {
|
||||
TermsOfService() TermsOfServiceStore
|
||||
Group() GroupStore
|
||||
UserTermsOfService() UserTermsOfServiceStore
|
||||
LinkMetadata() LinkMetadataStore
|
||||
MarkSystemRanUnitTests()
|
||||
Close()
|
||||
LockToMaster()
|
||||
@@ -563,3 +564,8 @@ type GroupStore interface {
|
||||
PendingAutoAddTeamMembers(minGroupMembersCreateAt int64) StoreChannel
|
||||
PendingAutoAddChannelMembers(minGroupMembersCreateAt int64) StoreChannel
|
||||
}
|
||||
|
||||
type LinkMetadataStore interface {
|
||||
Save(linkMetadata *model.LinkMetadata) StoreChannel
|
||||
Get(url string, timestamp int64) StoreChannel
|
||||
}
|
||||
|
||||
251
store/storetest/link_metadata_store.go
Обычный файл
251
store/storetest/link_metadata_store.go
Обычный файл
@@ -0,0 +1,251 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package storetest
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/dyatlov/go-opengraph/opengraph"
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
"github.com/mattermost/mattermost-server/store"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// These tests are ran on the same store instance, so this provides easier unique, valid timestamps
|
||||
var linkMetadataTimestamp int64 = 1546300800000
|
||||
|
||||
func getNextLinkMetadataTimestamp() int64 {
|
||||
linkMetadataTimestamp += int64(time.Hour) / 1000
|
||||
return linkMetadataTimestamp
|
||||
}
|
||||
|
||||
func TestLinkMetadataStore(t *testing.T, ss store.Store) {
|
||||
t.Run("Save", func(t *testing.T) { testLinkMetadataStoreSave(t, ss) })
|
||||
t.Run("Get", func(t *testing.T) { testLinkMetadataStoreGet(t, ss) })
|
||||
t.Run("Types", func(t *testing.T) { testLinkMetadataStoreTypes(t, ss) })
|
||||
}
|
||||
|
||||
func testLinkMetadataStoreSave(t *testing.T, ss store.Store) {
|
||||
t.Run("should save item", func(t *testing.T) {
|
||||
metadata := &model.LinkMetadata{
|
||||
URL: "http://example.com",
|
||||
Timestamp: getNextLinkMetadataTimestamp(),
|
||||
Type: model.LINK_METADATA_TYPE_IMAGE,
|
||||
Data: &model.PostImage{},
|
||||
}
|
||||
|
||||
result := <-ss.LinkMetadata().Save(metadata)
|
||||
|
||||
require.Nil(t, result.Err)
|
||||
require.IsType(t, metadata, result.Data)
|
||||
assert.Equal(t, *metadata, *result.Data.(*model.LinkMetadata))
|
||||
})
|
||||
|
||||
t.Run("should fail to save invalid item", func(t *testing.T) {
|
||||
metadata := &model.LinkMetadata{
|
||||
URL: "",
|
||||
Timestamp: 0,
|
||||
Type: "garbage",
|
||||
Data: nil,
|
||||
}
|
||||
|
||||
result := <-ss.LinkMetadata().Save(metadata)
|
||||
|
||||
assert.NotNil(t, result.Err)
|
||||
})
|
||||
|
||||
t.Run("should save with duplicate URL and different timestamp", func(t *testing.T) {
|
||||
metadata := &model.LinkMetadata{
|
||||
URL: "http://example.com",
|
||||
Timestamp: getNextLinkMetadataTimestamp(),
|
||||
Type: model.LINK_METADATA_TYPE_IMAGE,
|
||||
Data: &model.PostImage{},
|
||||
}
|
||||
|
||||
result := <-ss.LinkMetadata().Save(metadata)
|
||||
require.Nil(t, result.Err)
|
||||
|
||||
metadata.Timestamp = getNextLinkMetadataTimestamp()
|
||||
|
||||
result = <-ss.LinkMetadata().Save(metadata)
|
||||
|
||||
require.Nil(t, result.Err)
|
||||
require.IsType(t, metadata, result.Data)
|
||||
assert.Equal(t, *metadata, *result.Data.(*model.LinkMetadata))
|
||||
})
|
||||
|
||||
t.Run("should save with duplicate timestamp and different URL", func(t *testing.T) {
|
||||
metadata := &model.LinkMetadata{
|
||||
URL: "http://example.com",
|
||||
Timestamp: getNextLinkMetadataTimestamp(),
|
||||
Type: model.LINK_METADATA_TYPE_IMAGE,
|
||||
Data: &model.PostImage{},
|
||||
}
|
||||
|
||||
result := <-ss.LinkMetadata().Save(metadata)
|
||||
require.Nil(t, result.Err)
|
||||
|
||||
metadata.URL = "http://example.com/another/page"
|
||||
|
||||
result = <-ss.LinkMetadata().Save(metadata)
|
||||
|
||||
require.Nil(t, result.Err)
|
||||
require.IsType(t, metadata, result.Data)
|
||||
assert.Equal(t, *metadata, *result.Data.(*model.LinkMetadata))
|
||||
})
|
||||
|
||||
t.Run("should fail to save with duplicate URL and timestamp", func(t *testing.T) {
|
||||
metadata := &model.LinkMetadata{
|
||||
URL: "http://example.com",
|
||||
Timestamp: getNextLinkMetadataTimestamp(),
|
||||
Type: model.LINK_METADATA_TYPE_IMAGE,
|
||||
Data: &model.PostImage{},
|
||||
}
|
||||
|
||||
result := <-ss.LinkMetadata().Save(metadata)
|
||||
require.Nil(t, result.Err)
|
||||
|
||||
result = <-ss.LinkMetadata().Save(metadata)
|
||||
|
||||
assert.NotNil(t, result.Err)
|
||||
})
|
||||
}
|
||||
|
||||
func testLinkMetadataStoreGet(t *testing.T, ss store.Store) {
|
||||
t.Run("should get value", func(t *testing.T) {
|
||||
metadata := &model.LinkMetadata{
|
||||
URL: "http://example.com",
|
||||
Timestamp: getNextLinkMetadataTimestamp(),
|
||||
Type: model.LINK_METADATA_TYPE_IMAGE,
|
||||
Data: &model.PostImage{},
|
||||
}
|
||||
|
||||
result := <-ss.LinkMetadata().Save(metadata)
|
||||
require.Nil(t, result.Err)
|
||||
|
||||
result = <-ss.LinkMetadata().Get(metadata.URL, metadata.Timestamp)
|
||||
|
||||
require.Nil(t, result.Err)
|
||||
require.IsType(t, metadata, result.Data)
|
||||
assert.Equal(t, *metadata, *result.Data.(*model.LinkMetadata))
|
||||
})
|
||||
|
||||
t.Run("should return not found with incorrect URL", func(t *testing.T) {
|
||||
metadata := &model.LinkMetadata{
|
||||
URL: "http://example.com",
|
||||
Timestamp: getNextLinkMetadataTimestamp(),
|
||||
Type: model.LINK_METADATA_TYPE_IMAGE,
|
||||
Data: &model.PostImage{},
|
||||
}
|
||||
|
||||
result := <-ss.LinkMetadata().Save(metadata)
|
||||
require.Nil(t, result.Err)
|
||||
|
||||
result = <-ss.LinkMetadata().Get("http://example.com/another_page", metadata.Timestamp)
|
||||
|
||||
require.NotNil(t, result.Err)
|
||||
assert.Equal(t, http.StatusNotFound, result.Err.StatusCode)
|
||||
})
|
||||
|
||||
t.Run("should return not found with incorrect timestamp", func(t *testing.T) {
|
||||
metadata := &model.LinkMetadata{
|
||||
URL: "http://example.com",
|
||||
Timestamp: getNextLinkMetadataTimestamp(),
|
||||
Type: model.LINK_METADATA_TYPE_IMAGE,
|
||||
Data: &model.PostImage{},
|
||||
}
|
||||
|
||||
result := <-ss.LinkMetadata().Save(metadata)
|
||||
require.Nil(t, result.Err)
|
||||
|
||||
result = <-ss.LinkMetadata().Get(metadata.URL, getNextLinkMetadataTimestamp())
|
||||
|
||||
require.NotNil(t, result.Err)
|
||||
assert.Equal(t, http.StatusNotFound, result.Err.StatusCode)
|
||||
})
|
||||
}
|
||||
|
||||
func testLinkMetadataStoreTypes(t *testing.T, ss store.Store) {
|
||||
t.Run("should save and get image metadata", func(t *testing.T) {
|
||||
metadata := &model.LinkMetadata{
|
||||
URL: "http://example.com",
|
||||
Timestamp: getNextLinkMetadataTimestamp(),
|
||||
Type: model.LINK_METADATA_TYPE_IMAGE,
|
||||
Data: &model.PostImage{
|
||||
Width: 123,
|
||||
Height: 456,
|
||||
},
|
||||
}
|
||||
|
||||
result := <-ss.LinkMetadata().Save(metadata)
|
||||
require.Nil(t, result.Err)
|
||||
|
||||
received := result.Data.(*model.LinkMetadata)
|
||||
require.IsType(t, &model.PostImage{}, received.Data)
|
||||
assert.Equal(t, *(metadata.Data.(*model.PostImage)), *(received.Data.(*model.PostImage)))
|
||||
|
||||
result = <-ss.LinkMetadata().Get(metadata.URL, metadata.Timestamp)
|
||||
require.Nil(t, result.Err)
|
||||
|
||||
received = result.Data.(*model.LinkMetadata)
|
||||
require.IsType(t, &model.PostImage{}, received.Data)
|
||||
assert.Equal(t, *(metadata.Data.(*model.PostImage)), *(received.Data.(*model.PostImage)))
|
||||
})
|
||||
|
||||
t.Run("should save and get opengraph data", func(t *testing.T) {
|
||||
og := &opengraph.OpenGraph{
|
||||
URL: "http://example.com",
|
||||
Images: []*opengraph.Image{
|
||||
{
|
||||
URL: "http://example.com/image.png",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
metadata := &model.LinkMetadata{
|
||||
URL: "http://example.com",
|
||||
Timestamp: getNextLinkMetadataTimestamp(),
|
||||
Type: model.LINK_METADATA_TYPE_OPENGRAPH,
|
||||
Data: og,
|
||||
}
|
||||
|
||||
result := <-ss.LinkMetadata().Save(metadata)
|
||||
require.Nil(t, result.Err)
|
||||
|
||||
received := result.Data.(*model.LinkMetadata)
|
||||
require.IsType(t, &opengraph.OpenGraph{}, received.Data)
|
||||
assert.Equal(t, *(metadata.Data.(*opengraph.OpenGraph)), *(received.Data.(*opengraph.OpenGraph)))
|
||||
|
||||
result = <-ss.LinkMetadata().Get(metadata.URL, metadata.Timestamp)
|
||||
require.Nil(t, result.Err)
|
||||
|
||||
received = result.Data.(*model.LinkMetadata)
|
||||
require.IsType(t, &opengraph.OpenGraph{}, received.Data)
|
||||
assert.Equal(t, *(metadata.Data.(*opengraph.OpenGraph)), *(received.Data.(*opengraph.OpenGraph)))
|
||||
})
|
||||
|
||||
t.Run("should save and get nil", func(t *testing.T) {
|
||||
metadata := &model.LinkMetadata{
|
||||
URL: "http://example.com",
|
||||
Timestamp: getNextLinkMetadataTimestamp(),
|
||||
Type: model.LINK_METADATA_TYPE_NONE,
|
||||
Data: nil,
|
||||
}
|
||||
|
||||
result := <-ss.LinkMetadata().Save(metadata)
|
||||
require.Nil(t, result.Err)
|
||||
|
||||
received := result.Data.(*model.LinkMetadata)
|
||||
assert.Nil(t, received.Data)
|
||||
|
||||
result = <-ss.LinkMetadata().Get(metadata.URL, metadata.Timestamp)
|
||||
require.Nil(t, result.Err)
|
||||
|
||||
received = result.Data.(*model.LinkMetadata)
|
||||
require.Nil(t, received.Data)
|
||||
})
|
||||
}
|
||||
@@ -584,6 +584,22 @@ func (_m *LayeredStoreDatabaseLayer) License() store.LicenseStore {
|
||||
return r0
|
||||
}
|
||||
|
||||
// LinkMetadata provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) LinkMetadata() store.LinkMetadataStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.LinkMetadataStore
|
||||
if rf, ok := ret.Get(0).(func() store.LinkMetadataStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.LinkMetadataStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// LockToMaster provides a mock function with given fields:
|
||||
func (_m *LayeredStoreDatabaseLayer) LockToMaster() {
|
||||
_m.Called()
|
||||
|
||||
46
store/storetest/mocks/LinkMetadataStore.go
Обычный файл
46
store/storetest/mocks/LinkMetadataStore.go
Обычный файл
@@ -0,0 +1,46 @@
|
||||
// Code generated by mockery v1.0.0. DO NOT EDIT.
|
||||
|
||||
// Regenerate this file using `make store-mocks`.
|
||||
|
||||
package mocks
|
||||
|
||||
import mock "github.com/stretchr/testify/mock"
|
||||
import model "github.com/mattermost/mattermost-server/model"
|
||||
import store "github.com/mattermost/mattermost-server/store"
|
||||
|
||||
// LinkMetadataStore is an autogenerated mock type for the LinkMetadataStore type
|
||||
type LinkMetadataStore struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// Get provides a mock function with given fields: url, timestamp
|
||||
func (_m *LinkMetadataStore) Get(url string, timestamp int64) store.StoreChannel {
|
||||
ret := _m.Called(url, timestamp)
|
||||
|
||||
var r0 store.StoreChannel
|
||||
if rf, ok := ret.Get(0).(func(string, int64) store.StoreChannel); ok {
|
||||
r0 = rf(url, timestamp)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.StoreChannel)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Save provides a mock function with given fields: linkMetadata
|
||||
func (_m *LinkMetadataStore) Save(linkMetadata *model.LinkMetadata) store.StoreChannel {
|
||||
ret := _m.Called(linkMetadata)
|
||||
|
||||
var r0 store.StoreChannel
|
||||
if rf, ok := ret.Get(0).(func(*model.LinkMetadata) store.StoreChannel); ok {
|
||||
r0 = rf(linkMetadata)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.StoreChannel)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
97
store/storetest/mocks/ObjectCache.go
Обычный файл
97
store/storetest/mocks/ObjectCache.go
Обычный файл
@@ -0,0 +1,97 @@
|
||||
// Code generated by mockery v1.0.0. DO NOT EDIT.
|
||||
|
||||
// Regenerate this file using `make store-mocks`.
|
||||
|
||||
package mocks
|
||||
|
||||
import mock "github.com/stretchr/testify/mock"
|
||||
|
||||
// ObjectCache is an autogenerated mock type for the ObjectCache type
|
||||
type ObjectCache struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// AddWithDefaultExpires provides a mock function with given fields: key, value
|
||||
func (_m *ObjectCache) AddWithDefaultExpires(key interface{}, value interface{}) {
|
||||
_m.Called(key, value)
|
||||
}
|
||||
|
||||
// AddWithExpiresInSecs provides a mock function with given fields: key, value, expireAtSecs
|
||||
func (_m *ObjectCache) AddWithExpiresInSecs(key interface{}, value interface{}, expireAtSecs int64) {
|
||||
_m.Called(key, value, expireAtSecs)
|
||||
}
|
||||
|
||||
// Get provides a mock function with given fields: key
|
||||
func (_m *ObjectCache) Get(key interface{}) (interface{}, bool) {
|
||||
ret := _m.Called(key)
|
||||
|
||||
var r0 interface{}
|
||||
if rf, ok := ret.Get(0).(func(interface{}) interface{}); ok {
|
||||
r0 = rf(key)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(interface{})
|
||||
}
|
||||
}
|
||||
|
||||
var r1 bool
|
||||
if rf, ok := ret.Get(1).(func(interface{}) bool); ok {
|
||||
r1 = rf(key)
|
||||
} else {
|
||||
r1 = ret.Get(1).(bool)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetInvalidateClusterEvent provides a mock function with given fields:
|
||||
func (_m *ObjectCache) GetInvalidateClusterEvent() string {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 string
|
||||
if rf, ok := ret.Get(0).(func() string); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Len provides a mock function with given fields:
|
||||
func (_m *ObjectCache) Len() int {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 int
|
||||
if rf, ok := ret.Get(0).(func() int); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(int)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Name provides a mock function with given fields:
|
||||
func (_m *ObjectCache) Name() string {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 string
|
||||
if rf, ok := ret.Get(0).(func() string); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Purge provides a mock function with given fields:
|
||||
func (_m *ObjectCache) Purge() {
|
||||
_m.Called()
|
||||
}
|
||||
|
||||
// Remove provides a mock function with given fields: key
|
||||
func (_m *ObjectCache) Remove(key interface{}) {
|
||||
_m.Called(key)
|
||||
}
|
||||
@@ -439,6 +439,22 @@ func (_m *SqlStore) License() store.LicenseStore {
|
||||
return r0
|
||||
}
|
||||
|
||||
// LinkMetadata provides a mock function with given fields:
|
||||
func (_m *SqlStore) LinkMetadata() store.LinkMetadataStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.LinkMetadataStore
|
||||
if rf, ok := ret.Get(0).(func() store.LinkMetadataStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.LinkMetadataStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// LockToMaster provides a mock function with given fields:
|
||||
func (_m *SqlStore) LockToMaster() {
|
||||
_m.Called()
|
||||
|
||||
@@ -214,6 +214,22 @@ func (_m *Store) License() store.LicenseStore {
|
||||
return r0
|
||||
}
|
||||
|
||||
// LinkMetadata provides a mock function with given fields:
|
||||
func (_m *Store) LinkMetadata() store.LinkMetadataStore {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 store.LinkMetadataStore
|
||||
if rf, ok := ret.Get(0).(func() store.LinkMetadataStore); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(store.LinkMetadataStore)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// LockToMaster provides a mock function with given fields:
|
||||
func (_m *Store) LockToMaster() {
|
||||
_m.Called()
|
||||
|
||||
@@ -48,6 +48,7 @@ type Store struct {
|
||||
TermsOfServiceStore mocks.TermsOfServiceStore
|
||||
GroupStore mocks.GroupStore
|
||||
UserTermsOfServiceStore mocks.UserTermsOfServiceStore
|
||||
LinkMetadataStore mocks.LinkMetadataStore
|
||||
}
|
||||
|
||||
func (s *Store) Team() store.TeamStore { return &s.TeamStore }
|
||||
@@ -80,15 +81,16 @@ func (s *Store) UserTermsOfService() store.UserTermsOfServiceStore { return &s.U
|
||||
func (s *Store) ChannelMemberHistory() store.ChannelMemberHistoryStore {
|
||||
return &s.ChannelMemberHistoryStore
|
||||
}
|
||||
func (s *Store) Group() store.GroupStore { return &s.GroupStore }
|
||||
func (s *Store) MarkSystemRanUnitTests() { /* do nothing */ }
|
||||
func (s *Store) Close() { /* do nothing */ }
|
||||
func (s *Store) LockToMaster() { /* do nothing */ }
|
||||
func (s *Store) UnlockFromMaster() { /* do nothing */ }
|
||||
func (s *Store) DropAllTables() { /* do nothing */ }
|
||||
func (s *Store) TotalMasterDbConnections() int { return 1 }
|
||||
func (s *Store) TotalReadDbConnections() int { return 1 }
|
||||
func (s *Store) TotalSearchDbConnections() int { return 1 }
|
||||
func (s *Store) Group() store.GroupStore { return &s.GroupStore }
|
||||
func (s *Store) LinkMetadata() store.LinkMetadataStore { return &s.LinkMetadataStore }
|
||||
func (s *Store) MarkSystemRanUnitTests() { /* do nothing */ }
|
||||
func (s *Store) Close() { /* do nothing */ }
|
||||
func (s *Store) LockToMaster() { /* do nothing */ }
|
||||
func (s *Store) UnlockFromMaster() { /* do nothing */ }
|
||||
func (s *Store) DropAllTables() { /* do nothing */ }
|
||||
func (s *Store) TotalMasterDbConnections() int { return 1 }
|
||||
func (s *Store) TotalReadDbConnections() int { return 1 }
|
||||
func (s *Store) TotalSearchDbConnections() int { return 1 }
|
||||
|
||||
func (s *Store) AssertExpectations(t mock.TestingT) bool {
|
||||
return mock.AssertExpectationsForObjects(t,
|
||||
|
||||
Ссылка в новой задаче
Block a user