consul/internal/controller/cache/decoded_test.go

361 lines
14 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package cache_test
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"github.com/hashicorp/consul/internal/controller/cache"
"github.com/hashicorp/consul/internal/controller/cache/cachemock"
"github.com/hashicorp/consul/internal/resource"
"github.com/hashicorp/consul/internal/resource/demo"
"github.com/hashicorp/consul/proto-public/pbresource"
pbdemo "github.com/hashicorp/consul/proto/private/pbdemo/v2"
"github.com/hashicorp/consul/proto/private/prototest"
)
type decodedSuite struct {
suite.Suite
rc *cachemock.ReadOnlyCache
iter *cachemock.ResourceIterator
artistGood *resource.DecodedResource[*pbdemo.Artist]
artistGood2 *resource.DecodedResource[*pbdemo.Artist]
artistBad *pbresource.Resource
}
func (suite *decodedSuite) SetupTest() {
suite.rc = cachemock.NewReadOnlyCache(suite.T())
suite.iter = cachemock.NewResourceIterator(suite.T())
artist, err := demo.GenerateV2Artist()
require.NoError(suite.T(), err)
suite.artistGood, err = resource.Decode[*pbdemo.Artist](artist)
require.NoError(suite.T(), err)
artist2, err := demo.GenerateV2Artist()
require.NoError(suite.T(), err)
suite.artistGood2, err = resource.Decode[*pbdemo.Artist](artist2)
require.NoError(suite.T(), err)
suite.artistBad, err = demo.GenerateV2Album(artist.Id)
require.NoError(suite.T(), err)
}
func (suite *decodedSuite) TestGetDecoded_Ok() {
suite.rc.EXPECT().Get(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(suite.artistGood.Resource, nil)
dec, err := cache.GetDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id)
require.NoError(suite.T(), err)
prototest.AssertDeepEqual(suite.T(), suite.artistGood.Resource, dec.Resource)
prototest.AssertDeepEqual(suite.T(), suite.artistGood.Data, dec.Data)
}
func (suite *decodedSuite) TestGetDecoded_DecodeError() {
suite.rc.EXPECT().Get(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(suite.artistBad, nil)
dec, err := cache.GetDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id)
require.Error(suite.T(), err)
require.Nil(suite.T(), dec)
}
func (suite *decodedSuite) TestGetDecoded_CacheError() {
suite.rc.EXPECT().Get(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(nil, injectedError)
dec, err := cache.GetDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id)
require.ErrorIs(suite.T(), err, injectedError)
require.Nil(suite.T(), dec)
}
func (suite *decodedSuite) TestGetDecoded_Nil() {
suite.rc.EXPECT().Get(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(nil, nil)
dec, err := cache.GetDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id)
require.NoError(suite.T(), err)
require.Nil(suite.T(), dec)
}
func (suite *decodedSuite) TestListDecoded_Ok() {
suite.rc.EXPECT().List(pbdemo.ArtistType, "id", suite.artistGood.Id).
Return([]*pbresource.Resource{suite.artistGood.Resource, suite.artistGood2.Resource}, nil)
dec, err := cache.ListDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id)
require.NoError(suite.T(), err)
require.Len(suite.T(), dec, 2)
prototest.AssertDeepEqual(suite.T(), suite.artistGood.Resource, dec[0].Resource)
prototest.AssertDeepEqual(suite.T(), suite.artistGood.Data, dec[0].Data)
prototest.AssertDeepEqual(suite.T(), suite.artistGood2.Resource, dec[1].Resource)
prototest.AssertDeepEqual(suite.T(), suite.artistGood2.Data, dec[1].Data)
}
func (suite *decodedSuite) TestListDecoded_DecodeError() {
suite.rc.EXPECT().List(pbdemo.ArtistType, "id", suite.artistGood.Id).
Return([]*pbresource.Resource{suite.artistGood.Resource, suite.artistBad}, nil)
dec, err := cache.ListDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id)
require.Error(suite.T(), err)
require.Nil(suite.T(), dec)
}
func (suite *decodedSuite) TestListDecoded_CacheError() {
suite.rc.EXPECT().List(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(nil, injectedError)
dec, err := cache.ListDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id)
require.ErrorIs(suite.T(), err, injectedError)
require.Nil(suite.T(), dec)
}
func (suite *decodedSuite) TestListDecoded_Nil() {
suite.rc.EXPECT().List(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(nil, nil)
dec, err := cache.ListDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id)
require.NoError(suite.T(), err)
require.Nil(suite.T(), dec)
}
func (suite *decodedSuite) TestListIteratorDecoded_Ok() {
suite.iter.EXPECT().Next().Return(suite.artistGood.Resource).Once()
suite.iter.EXPECT().Next().Return(suite.artistGood2.Resource).Once()
suite.iter.EXPECT().Next().Return(nil).Times(0)
suite.rc.EXPECT().ListIterator(pbdemo.ArtistType, "id", suite.artistGood.Id).
Return(suite.iter, nil)
iter, err := cache.ListIteratorDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id)
require.NoError(suite.T(), err)
require.NotNil(suite.T(), iter)
dec, err := iter.Next()
require.NoError(suite.T(), err)
prototest.AssertDeepEqual(suite.T(), suite.artistGood.Resource, dec.Resource)
prototest.AssertDeepEqual(suite.T(), suite.artistGood.Data, dec.Data)
dec, err = iter.Next()
require.NoError(suite.T(), err)
prototest.AssertDeepEqual(suite.T(), suite.artistGood2.Resource, dec.Resource)
prototest.AssertDeepEqual(suite.T(), suite.artistGood2.Data, dec.Data)
dec, err = iter.Next()
require.NoError(suite.T(), err)
require.Nil(suite.T(), dec)
}
func (suite *decodedSuite) TestListIteratorDecoded_DecodeError() {
suite.iter.EXPECT().Next().Return(suite.artistGood.Resource).Once()
suite.iter.EXPECT().Next().Return(suite.artistBad).Once()
suite.iter.EXPECT().Next().Return(nil).Times(0)
suite.rc.EXPECT().ListIterator(pbdemo.ArtistType, "id", suite.artistGood.Id).
Return(suite.iter, nil)
iter, err := cache.ListIteratorDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id)
require.NoError(suite.T(), err)
require.NotNil(suite.T(), iter)
dec, err := iter.Next()
require.NoError(suite.T(), err)
prototest.AssertDeepEqual(suite.T(), suite.artistGood.Resource, dec.Resource)
prototest.AssertDeepEqual(suite.T(), suite.artistGood.Data, dec.Data)
dec, err = iter.Next()
require.Error(suite.T(), err)
require.Nil(suite.T(), dec)
dec, err = iter.Next()
require.NoError(suite.T(), err)
require.Nil(suite.T(), dec)
}
func (suite *decodedSuite) TestListIteratorDecoded_CacheError() {
suite.rc.EXPECT().ListIterator(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(nil, injectedError)
iter, err := cache.ListIteratorDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id)
require.ErrorIs(suite.T(), err, injectedError)
require.Nil(suite.T(), iter)
}
func (suite *decodedSuite) TestListIteratorDecoded_Nil() {
suite.rc.EXPECT().ListIterator(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(nil, nil)
dec, err := cache.ListIteratorDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id)
require.NoError(suite.T(), err)
require.Nil(suite.T(), dec)
}
func (suite *decodedSuite) TestParentsDecoded_Ok() {
suite.rc.EXPECT().Parents(pbdemo.ArtistType, "id", suite.artistGood.Id).
Return([]*pbresource.Resource{suite.artistGood.Resource, suite.artistGood2.Resource}, nil)
dec, err := cache.ParentsDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id)
require.NoError(suite.T(), err)
require.Len(suite.T(), dec, 2)
prototest.AssertDeepEqual(suite.T(), suite.artistGood.Resource, dec[0].Resource)
prototest.AssertDeepEqual(suite.T(), suite.artistGood.Data, dec[0].Data)
prototest.AssertDeepEqual(suite.T(), suite.artistGood2.Resource, dec[1].Resource)
prototest.AssertDeepEqual(suite.T(), suite.artistGood2.Data, dec[1].Data)
}
func (suite *decodedSuite) TestParentsDecoded_DecodeError() {
suite.rc.EXPECT().Parents(pbdemo.ArtistType, "id", suite.artistGood.Id).
Return([]*pbresource.Resource{suite.artistGood.Resource, suite.artistBad}, nil)
dec, err := cache.ParentsDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id)
require.Error(suite.T(), err)
require.Nil(suite.T(), dec)
}
func (suite *decodedSuite) TestParentsDecoded_CacheError() {
suite.rc.EXPECT().Parents(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(nil, injectedError)
dec, err := cache.ParentsDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id)
require.ErrorIs(suite.T(), err, injectedError)
require.Nil(suite.T(), dec)
}
func (suite *decodedSuite) TestParentsDecoded_Nil() {
suite.rc.EXPECT().Parents(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(nil, nil)
dec, err := cache.ParentsDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id)
require.NoError(suite.T(), err)
require.Nil(suite.T(), dec)
}
func (suite *decodedSuite) TestParentsIteratorDecoded_Ok() {
suite.iter.EXPECT().Next().Return(suite.artistGood.Resource).Once()
suite.iter.EXPECT().Next().Return(suite.artistGood2.Resource).Once()
suite.iter.EXPECT().Next().Return(nil).Times(0)
suite.rc.EXPECT().ParentsIterator(pbdemo.ArtistType, "id", suite.artistGood.Id).
Return(suite.iter, nil)
iter, err := cache.ParentsIteratorDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id)
require.NoError(suite.T(), err)
require.NotNil(suite.T(), iter)
dec, err := iter.Next()
require.NoError(suite.T(), err)
prototest.AssertDeepEqual(suite.T(), suite.artistGood.Resource, dec.Resource)
prototest.AssertDeepEqual(suite.T(), suite.artistGood.Data, dec.Data)
dec, err = iter.Next()
require.NoError(suite.T(), err)
prototest.AssertDeepEqual(suite.T(), suite.artistGood2.Resource, dec.Resource)
prototest.AssertDeepEqual(suite.T(), suite.artistGood2.Data, dec.Data)
dec, err = iter.Next()
require.NoError(suite.T(), err)
require.Nil(suite.T(), dec)
}
func (suite *decodedSuite) TestParentsIteratorDecoded_DecodeError() {
suite.iter.EXPECT().Next().Return(suite.artistGood.Resource).Once()
suite.iter.EXPECT().Next().Return(suite.artistBad).Once()
suite.iter.EXPECT().Next().Return(nil).Times(0)
suite.rc.EXPECT().ParentsIterator(pbdemo.ArtistType, "id", suite.artistGood.Id).
Return(suite.iter, nil)
iter, err := cache.ParentsIteratorDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id)
require.NoError(suite.T(), err)
require.NotNil(suite.T(), iter)
dec, err := iter.Next()
require.NoError(suite.T(), err)
prototest.AssertDeepEqual(suite.T(), suite.artistGood.Resource, dec.Resource)
prototest.AssertDeepEqual(suite.T(), suite.artistGood.Data, dec.Data)
dec, err = iter.Next()
require.Error(suite.T(), err)
require.Nil(suite.T(), dec)
dec, err = iter.Next()
require.NoError(suite.T(), err)
require.Nil(suite.T(), dec)
}
func (suite *decodedSuite) TestParentsIteratorDecoded_CacheError() {
suite.rc.EXPECT().ParentsIterator(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(nil, injectedError)
iter, err := cache.ParentsIteratorDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id)
require.ErrorIs(suite.T(), err, injectedError)
require.Nil(suite.T(), iter)
}
func (suite *decodedSuite) TestParentsIteratorDecoded_Nil() {
suite.rc.EXPECT().ParentsIterator(pbdemo.ArtistType, "id", suite.artistGood.Id).Return(nil, nil)
dec, err := cache.ParentsIteratorDecoded[*pbdemo.Artist](suite.rc, pbdemo.ArtistType, "id", suite.artistGood.Id)
require.NoError(suite.T(), err)
require.Nil(suite.T(), dec)
}
func (suite *decodedSuite) TestQueryDecoded_Ok() {
suite.iter.EXPECT().Next().Return(suite.artistGood.Resource).Once()
suite.iter.EXPECT().Next().Return(suite.artistGood2.Resource).Once()
suite.iter.EXPECT().Next().Return(nil).Times(0)
suite.rc.EXPECT().Query("query", "blah").
Return(suite.iter, nil)
iter, err := cache.QueryDecoded[*pbdemo.Artist](suite.rc, "query", "blah")
require.NoError(suite.T(), err)
require.NotNil(suite.T(), iter)
dec, err := iter.Next()
require.NoError(suite.T(), err)
prototest.AssertDeepEqual(suite.T(), suite.artistGood.Resource, dec.Resource)
prototest.AssertDeepEqual(suite.T(), suite.artistGood.Data, dec.Data)
dec, err = iter.Next()
require.NoError(suite.T(), err)
prototest.AssertDeepEqual(suite.T(), suite.artistGood2.Resource, dec.Resource)
prototest.AssertDeepEqual(suite.T(), suite.artistGood2.Data, dec.Data)
dec, err = iter.Next()
require.NoError(suite.T(), err)
require.Nil(suite.T(), dec)
}
func (suite *decodedSuite) TestQueryDecoded_DecodeError() {
suite.iter.EXPECT().Next().Return(suite.artistGood.Resource).Once()
suite.iter.EXPECT().Next().Return(suite.artistBad).Once()
suite.iter.EXPECT().Next().Return(nil).Times(0)
suite.rc.EXPECT().Query("query", "blah").
Return(suite.iter, nil)
iter, err := cache.QueryDecoded[*pbdemo.Artist](suite.rc, "query", "blah")
require.NoError(suite.T(), err)
require.NotNil(suite.T(), iter)
dec, err := iter.Next()
require.NoError(suite.T(), err)
prototest.AssertDeepEqual(suite.T(), suite.artistGood.Resource, dec.Resource)
prototest.AssertDeepEqual(suite.T(), suite.artistGood.Data, dec.Data)
dec, err = iter.Next()
require.Error(suite.T(), err)
require.Nil(suite.T(), dec)
dec, err = iter.Next()
require.NoError(suite.T(), err)
require.Nil(suite.T(), dec)
}
func (suite *decodedSuite) TestQueryDecoded_CacheError() {
suite.rc.EXPECT().Query("query", "blah").Return(nil, injectedError)
dec, err := cache.QueryDecoded[*pbdemo.Artist](suite.rc, "query", "blah")
require.ErrorIs(suite.T(), err, injectedError)
require.Nil(suite.T(), dec)
}
func (suite *decodedSuite) TestQueryDecoded_Nil() {
suite.rc.EXPECT().Query("query", "blah").Return(nil, nil)
dec, err := cache.QueryDecoded[*pbdemo.Artist](suite.rc, "query", "blah")
require.NoError(suite.T(), err)
require.Nil(suite.T(), dec)
}
func TestDecodedCache(t *testing.T) {
suite.Run(t, new(decodedSuite))
}