consul/internal/controller/cache/kind_test.go

203 lines
6.3 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package cache
import (
"errors"
"testing"
"github.com/hashicorp/consul/internal/controller/cache/index"
"github.com/hashicorp/consul/internal/resource"
"github.com/hashicorp/consul/internal/resource/resourcetest"
"github.com/hashicorp/consul/proto-public/pbresource"
pbdemo "github.com/hashicorp/consul/proto/private/pbdemo/v1"
"github.com/hashicorp/consul/proto/private/prototest"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
)
var injectedError = errors.New("test-error")
type argsErrorIndexer struct{}
func (i argsErrorIndexer) FromArgs(args ...any) ([]byte, error) {
return nil, injectedError
}
func (i argsErrorIndexer) FromResource(r *pbresource.Resource) (bool, []byte, error) {
return true, index.IndexFromRefOrID(r.GetId()), nil
}
type resourceErrorIndexer struct{}
func (i resourceErrorIndexer) FromArgs(args ...any) ([]byte, error) {
return index.ReferenceOrIDFromArgs(args...)
}
func (i resourceErrorIndexer) FromResource(r *pbresource.Resource) (bool, []byte, error) {
return false, nil, injectedError
}
func TestKindIndices(t *testing.T) {
suite.Run(t, &kindSuite{})
}
type kindSuite struct {
suite.Suite
k *kindIndices
album1 *pbresource.Resource
album2 *pbresource.Resource
album3 *pbresource.Resource
album4 *pbresource.Resource
}
func (suite *kindSuite) SetupTest() {
suite.k = newKindIndices()
require.NoError(suite.T(), suite.k.addIndex(namePrefixIndexer()))
require.NoError(suite.T(), suite.k.addIndex(releaseYearIndexer()))
require.NoError(suite.T(), suite.k.addIndex(tracksIndexer()))
suite.album1 = resourcetest.Resource(pbdemo.AlbumType, "one").
WithTenancy(resource.DefaultNamespacedTenancy()).
WithData(suite.T(), &pbdemo.Album{
Name: "one",
YearOfRelease: 2023,
Tracks: []string{"foo", "bar", "baz"},
}).
Build()
suite.album2 = resourcetest.Resource(pbdemo.AlbumType, "two").
WithTenancy(resource.DefaultNamespacedTenancy()).
WithData(suite.T(), &pbdemo.Album{
Name: "two",
YearOfRelease: 2023,
Tracks: []string{"fangorn", "zoo"},
}).
Build()
suite.album3 = resourcetest.Resource(pbdemo.AlbumType, "third").
WithTenancy(resource.DefaultNamespacedTenancy()).
WithData(suite.T(), &pbdemo.Album{
Name: "foo",
YearOfRelease: 2022,
Tracks: []string{"blah", "something", "else"},
}).
Build()
suite.album4 = resourcetest.Resource(pbdemo.AlbumType, "four").
WithTenancy(resource.DefaultNamespacedTenancy()).
WithData(suite.T(), &pbdemo.Album{
Name: "food",
YearOfRelease: 2020,
Tracks: []string{"nothing", "food"},
}).
Build()
require.NoError(suite.T(), suite.k.insert(suite.album1))
require.NoError(suite.T(), suite.k.insert(suite.album2))
require.NoError(suite.T(), suite.k.insert(suite.album3))
require.NoError(suite.T(), suite.k.insert(suite.album4))
}
func (suite *kindSuite) TestGet() {
res, err := suite.k.get("id", suite.album1.Id)
require.NoError(suite.T(), err)
prototest.AssertDeepEqual(suite.T(), suite.album1, res)
res, err = suite.k.get("year", int32(2022))
require.NoError(suite.T(), err)
prototest.AssertDeepEqual(suite.T(), suite.album3, res)
res, err = suite.k.get("tracks", "fangorn")
require.NoError(suite.T(), err)
prototest.AssertDeepEqual(suite.T(), suite.album2, res)
}
func (suite *kindSuite) TestGet_IndexNotFound() {
res, err := suite.k.get("blah", suite.album1.Id)
require.Error(suite.T(), err)
require.ErrorIs(suite.T(), err, IndexNotFoundError{name: "blah"})
require.Nil(suite.T(), res)
}
func (suite *kindSuite) TestList() {
resources, err := expandIterator(suite.k.listIterator("year", int32(2023)))
require.NoError(suite.T(), err)
prototest.AssertElementsMatch(suite.T(), []*pbresource.Resource{suite.album1, suite.album2}, resources)
resources, err = expandIterator(suite.k.listIterator("tracks", "f", true))
require.NoError(suite.T(), err)
prototest.AssertElementsMatch(suite.T(), []*pbresource.Resource{suite.album1, suite.album2, suite.album4}, resources)
}
func (suite *kindSuite) TestList_IndexNotFound() {
res, err := expandIterator(suite.k.listIterator("blah", suite.album1.Id))
require.Error(suite.T(), err)
require.ErrorIs(suite.T(), err, IndexNotFoundError{name: "blah"})
require.Nil(suite.T(), res)
}
func (suite *kindSuite) TestParents() {
resources, err := expandIterator(suite.k.parentsIterator("name_prefix", "food"))
require.NoError(suite.T(), err)
prototest.AssertElementsMatch(suite.T(), []*pbresource.Resource{suite.album3, suite.album4}, resources)
}
func (suite *kindSuite) TestParents_IndexNotFound() {
res, err := expandIterator(suite.k.parentsIterator("blah", suite.album1.Id))
require.Error(suite.T(), err)
require.ErrorIs(suite.T(), err, IndexNotFoundError{name: "blah"})
require.Nil(suite.T(), res)
}
func (suite *kindSuite) TestDelete() {
err := suite.k.delete(suite.album1)
require.NoError(suite.T(), err)
res, err := suite.k.get("id", suite.album1.Id)
require.NoError(suite.T(), err)
require.Nil(suite.T(), res)
resources, err := expandIterator(suite.k.listIterator("year", int32(2023)))
require.NoError(suite.T(), err)
prototest.AssertElementsMatch(suite.T(), []*pbresource.Resource{suite.album2}, resources)
resources, err = expandIterator(suite.k.parentsIterator("name_prefix", "onesie"))
require.NoError(suite.T(), err)
require.Nil(suite.T(), resources)
}
func (suite *kindSuite) TestInsertIndexError() {
err := suite.k.insert(
resourcetest.Resource(pbdemo.ConceptType, "foo").
WithTenancy(resource.DefaultNamespacedTenancy()).
WithData(suite.T(), &pbdemo.Concept{}).
Build())
require.Error(suite.T(), err)
require.ErrorAs(suite.T(), err, &IndexError{})
}
func (suite *kindSuite) TestGetIndexError() {
val, err := suite.k.get("year", "blah")
require.Error(suite.T(), err)
require.ErrorAs(suite.T(), err, &IndexError{})
require.Nil(suite.T(), val)
}
func (suite *kindSuite) TestListIteratorIndexError() {
vals, err := suite.k.listIterator("year", "blah")
require.Error(suite.T(), err)
require.ErrorAs(suite.T(), err, &IndexError{})
require.Nil(suite.T(), vals)
}
func (suite *kindSuite) TestParentsIteratorIndexError() {
vals, err := suite.k.parentsIterator("year", "blah")
require.Error(suite.T(), err)
require.ErrorAs(suite.T(), err, &IndexError{})
require.Nil(suite.T(), vals)
}