github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/store/storetest/link_metadata_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  	"time"
    10  
    11  	"github.com/dyatlov/go-opengraph/opengraph"
    12  	"github.com/mattermost/mattermost-server/v5/model"
    13  	"github.com/mattermost/mattermost-server/v5/store"
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  // These tests are ran on the same store instance, so this provides easier unique, valid timestamps
    19  var linkMetadataTimestamp int64 = 1546300800000
    20  
    21  func getNextLinkMetadataTimestamp() int64 {
    22  	linkMetadataTimestamp += int64(time.Hour) / (1000 * 1000)
    23  	return linkMetadataTimestamp
    24  }
    25  
    26  func TestLinkMetadataStore(t *testing.T, ss store.Store) {
    27  	t.Run("Save", func(t *testing.T) { testLinkMetadataStoreSave(t, ss) })
    28  	t.Run("Get", func(t *testing.T) { testLinkMetadataStoreGet(t, ss) })
    29  	t.Run("Types", func(t *testing.T) { testLinkMetadataStoreTypes(t, ss) })
    30  }
    31  
    32  func testLinkMetadataStoreSave(t *testing.T, ss store.Store) {
    33  	t.Run("should save item", func(t *testing.T) {
    34  		metadata := &model.LinkMetadata{
    35  			URL:       "http://example.com",
    36  			Timestamp: getNextLinkMetadataTimestamp(),
    37  			Type:      model.LINK_METADATA_TYPE_IMAGE,
    38  			Data:      &model.PostImage{},
    39  		}
    40  
    41  		linkMetadata, err := ss.LinkMetadata().Save(metadata)
    42  
    43  		require.Nil(t, err)
    44  		assert.Equal(t, *metadata, *linkMetadata)
    45  	})
    46  
    47  	t.Run("should fail to save invalid item", func(t *testing.T) {
    48  		metadata := &model.LinkMetadata{
    49  			URL:       "",
    50  			Timestamp: 0,
    51  			Type:      "garbage",
    52  			Data:      nil,
    53  		}
    54  
    55  		_, err := ss.LinkMetadata().Save(metadata)
    56  
    57  		assert.NotNil(t, err)
    58  	})
    59  
    60  	t.Run("should save with duplicate URL and different timestamp", func(t *testing.T) {
    61  		metadata := &model.LinkMetadata{
    62  			URL:       "http://example.com",
    63  			Timestamp: getNextLinkMetadataTimestamp(),
    64  			Type:      model.LINK_METADATA_TYPE_IMAGE,
    65  			Data:      &model.PostImage{},
    66  		}
    67  
    68  		_, err := ss.LinkMetadata().Save(metadata)
    69  		require.Nil(t, err)
    70  
    71  		metadata.Timestamp = getNextLinkMetadataTimestamp()
    72  
    73  		linkMetadata, err := ss.LinkMetadata().Save(metadata)
    74  
    75  		require.Nil(t, err)
    76  		assert.Equal(t, *metadata, *linkMetadata)
    77  	})
    78  
    79  	t.Run("should save with duplicate timestamp and different URL", func(t *testing.T) {
    80  		metadata := &model.LinkMetadata{
    81  			URL:       "http://example.com",
    82  			Timestamp: getNextLinkMetadataTimestamp(),
    83  			Type:      model.LINK_METADATA_TYPE_IMAGE,
    84  			Data:      &model.PostImage{},
    85  		}
    86  
    87  		_, err := ss.LinkMetadata().Save(metadata)
    88  		require.Nil(t, err)
    89  
    90  		metadata.URL = "http://example.com/another/page"
    91  
    92  		linkMetadata, err := ss.LinkMetadata().Save(metadata)
    93  
    94  		require.Nil(t, err)
    95  		assert.Equal(t, *metadata, *linkMetadata)
    96  	})
    97  
    98  	t.Run("should not save with duplicate URL and timestamp, but should not return an error", func(t *testing.T) {
    99  		metadata := &model.LinkMetadata{
   100  			URL:       "http://example.com",
   101  			Timestamp: getNextLinkMetadataTimestamp(),
   102  			Type:      model.LINK_METADATA_TYPE_IMAGE,
   103  			Data:      &model.PostImage{},
   104  		}
   105  
   106  		linkMetadata, err := ss.LinkMetadata().Save(metadata)
   107  		require.Nil(t, err)
   108  		assert.Equal(t, &model.PostImage{}, linkMetadata.Data)
   109  
   110  		metadata.Data = &model.PostImage{Height: 10, Width: 20}
   111  
   112  		linkMetadata, err = ss.LinkMetadata().Save(metadata)
   113  		require.Nil(t, err)
   114  		assert.Equal(t, linkMetadata.Data, &model.PostImage{Height: 10, Width: 20})
   115  
   116  		// Should return the original result, not the duplicate one
   117  		linkMetadata, err = ss.LinkMetadata().Get(metadata.URL, metadata.Timestamp)
   118  		require.Nil(t, err)
   119  		assert.Equal(t, &model.PostImage{}, linkMetadata.Data)
   120  	})
   121  }
   122  
   123  func testLinkMetadataStoreGet(t *testing.T, ss store.Store) {
   124  	t.Run("should get value", func(t *testing.T) {
   125  		metadata := &model.LinkMetadata{
   126  			URL:       "http://example.com",
   127  			Timestamp: getNextLinkMetadataTimestamp(),
   128  			Type:      model.LINK_METADATA_TYPE_IMAGE,
   129  			Data:      &model.PostImage{},
   130  		}
   131  
   132  		_, err := ss.LinkMetadata().Save(metadata)
   133  		require.Nil(t, err)
   134  
   135  		linkMetadata, err := ss.LinkMetadata().Get(metadata.URL, metadata.Timestamp)
   136  
   137  		require.Nil(t, err)
   138  		require.IsType(t, metadata, linkMetadata)
   139  		assert.Equal(t, *metadata, *linkMetadata)
   140  	})
   141  
   142  	t.Run("should return not found with incorrect URL", func(t *testing.T) {
   143  		metadata := &model.LinkMetadata{
   144  			URL:       "http://example.com",
   145  			Timestamp: getNextLinkMetadataTimestamp(),
   146  			Type:      model.LINK_METADATA_TYPE_IMAGE,
   147  			Data:      &model.PostImage{},
   148  		}
   149  
   150  		_, err := ss.LinkMetadata().Save(metadata)
   151  		require.Nil(t, err)
   152  
   153  		_, err = ss.LinkMetadata().Get("http://example.com/another_page", metadata.Timestamp)
   154  
   155  		require.NotNil(t, err)
   156  		var nfErr *store.ErrNotFound
   157  		assert.True(t, errors.As(err, &nfErr))
   158  	})
   159  
   160  	t.Run("should return not found with incorrect timestamp", func(t *testing.T) {
   161  		metadata := &model.LinkMetadata{
   162  			URL:       "http://example.com",
   163  			Timestamp: getNextLinkMetadataTimestamp(),
   164  			Type:      model.LINK_METADATA_TYPE_IMAGE,
   165  			Data:      &model.PostImage{},
   166  		}
   167  
   168  		_, err := ss.LinkMetadata().Save(metadata)
   169  		require.Nil(t, err)
   170  
   171  		_, err = ss.LinkMetadata().Get(metadata.URL, getNextLinkMetadataTimestamp())
   172  
   173  		require.NotNil(t, err)
   174  		var nfErr *store.ErrNotFound
   175  		assert.True(t, errors.As(err, &nfErr))
   176  	})
   177  }
   178  
   179  func testLinkMetadataStoreTypes(t *testing.T, ss store.Store) {
   180  	t.Run("should save and get image metadata", func(t *testing.T) {
   181  		metadata := &model.LinkMetadata{
   182  			URL:       "http://example.com",
   183  			Timestamp: getNextLinkMetadataTimestamp(),
   184  			Type:      model.LINK_METADATA_TYPE_IMAGE,
   185  			Data: &model.PostImage{
   186  				Width:  123,
   187  				Height: 456,
   188  			},
   189  		}
   190  
   191  		received, err := ss.LinkMetadata().Save(metadata)
   192  		require.Nil(t, err)
   193  
   194  		require.IsType(t, &model.PostImage{}, received.Data)
   195  		assert.Equal(t, *(metadata.Data.(*model.PostImage)), *(received.Data.(*model.PostImage)))
   196  
   197  		received, err = ss.LinkMetadata().Get(metadata.URL, metadata.Timestamp)
   198  		require.Nil(t, err)
   199  
   200  		require.IsType(t, &model.PostImage{}, received.Data)
   201  		assert.Equal(t, *(metadata.Data.(*model.PostImage)), *(received.Data.(*model.PostImage)))
   202  	})
   203  
   204  	t.Run("should save and get opengraph data", func(t *testing.T) {
   205  		og := &opengraph.OpenGraph{
   206  			URL: "http://example.com",
   207  			Images: []*opengraph.Image{
   208  				{
   209  					URL: "http://example.com/image.png",
   210  				},
   211  			},
   212  		}
   213  
   214  		metadata := &model.LinkMetadata{
   215  			URL:       "http://example.com",
   216  			Timestamp: getNextLinkMetadataTimestamp(),
   217  			Type:      model.LINK_METADATA_TYPE_OPENGRAPH,
   218  			Data:      og,
   219  		}
   220  
   221  		received, err := ss.LinkMetadata().Save(metadata)
   222  		require.Nil(t, err)
   223  
   224  		require.IsType(t, &opengraph.OpenGraph{}, received.Data)
   225  		assert.Equal(t, *(metadata.Data.(*opengraph.OpenGraph)), *(received.Data.(*opengraph.OpenGraph)))
   226  
   227  		received, err = ss.LinkMetadata().Get(metadata.URL, metadata.Timestamp)
   228  		require.Nil(t, err)
   229  
   230  		require.IsType(t, &opengraph.OpenGraph{}, received.Data)
   231  		assert.Equal(t, *(metadata.Data.(*opengraph.OpenGraph)), *(received.Data.(*opengraph.OpenGraph)))
   232  	})
   233  
   234  	t.Run("should save and get nil", func(t *testing.T) {
   235  		metadata := &model.LinkMetadata{
   236  			URL:       "http://example.com",
   237  			Timestamp: getNextLinkMetadataTimestamp(),
   238  			Type:      model.LINK_METADATA_TYPE_NONE,
   239  			Data:      nil,
   240  		}
   241  
   242  		received, err := ss.LinkMetadata().Save(metadata)
   243  		require.Nil(t, err)
   244  		assert.Nil(t, received.Data)
   245  
   246  		received, err = ss.LinkMetadata().Get(metadata.URL, metadata.Timestamp)
   247  		require.Nil(t, err)
   248  
   249  		require.Nil(t, received.Data)
   250  	})
   251  }