consul/internal/controller/dependency/higher_order_test.go

145 lines
3.9 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package dependency
import (
"context"
"errors"
"testing"
"github.com/hashicorp/consul/internal/controller"
"github.com/hashicorp/consul/internal/controller/controllermock"
"github.com/hashicorp/go-hclog"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"github.com/hashicorp/consul/internal/resource/resourcetest"
"github.com/hashicorp/consul/proto-public/pbresource"
"github.com/hashicorp/consul/proto/private/prototest"
)
var (
fakeMapType = &pbresource.Type{
Group: "testing",
GroupVersion: "v1",
Kind: "pre-map",
}
fakeResourceType = &pbresource.Type{
Group: "testing",
GroupVersion: "v1",
Kind: "fake",
}
altFakeResourceType = &pbresource.Type{
Group: "testing",
GroupVersion: "v1",
Kind: "alt-fake",
}
injectedErr = errors.New("injected")
)
func TestWrapAndReplaceType(t *testing.T) {
res := resourcetest.Resource(fakeMapType, "something").Build()
// populating the runtime with something so we can tell that
// the runtime is passed through
rt := controller.Runtime{
Logger: hclog.Default(),
}
t.Run("ok", func(t *testing.T) {
mm := controllermock.NewDependencyMapper(t)
mm.EXPECT().
Execute(mock.Anything, rt, res).
Return([]controller.Request{
{ID: resourceID("testing", "v1", "fake", "foo")},
{ID: resourceID("testing", "v1", "fake", "bar")},
}, nil).
Once()
mapper := WrapAndReplaceType(altFakeResourceType, mm.Execute)
reqs, err := mapper(context.Background(), rt, res)
require.NoError(t, err)
require.Len(t, reqs, 2)
expected := []controller.Request{
{ID: resourceID("testing", "v1", "alt-fake", "foo")},
{ID: resourceID("testing", "v1", "alt-fake", "bar")},
}
prototest.AssertElementsMatch(t, expected, reqs)
})
t.Run("err", func(t *testing.T) {
mm := controllermock.NewDependencyMapper(t)
mm.EXPECT().
Execute(mock.Anything, rt, res).
Return(nil, injectedErr).
Once()
mapper := WrapAndReplaceType(altFakeResourceType, mm.Execute)
reqs, err := mapper(context.Background(), rt, res)
require.Nil(t, reqs)
require.ErrorIs(t, err, injectedErr)
})
}
func TestMultiMapper(t *testing.T) {
res := resourcetest.Resource(fakeMapType, "something").Build()
// populating the runtime with something so we can tell that
// the runtime is passed through
rt := controller.Runtime{
Logger: hclog.Default(),
}
t.Run("ok", func(t *testing.T) {
mockMapper := controllermock.NewDependencyMapper(t)
mockMapper.EXPECT().
Execute(mock.Anything, rt, res).
Return([]controller.Request{
{ID: resourceID("testing", "v1", "fake", "foo")},
{ID: resourceID("testing", "v1", "fake", "bar")},
}, nil).
Times(2)
mm := MultiMapper(
mockMapper.Execute,
WrapAndReplaceType(altFakeResourceType, mockMapper.Execute),
)
reqs, err := mm(context.Background(), rt, res)
require.NoError(t, err)
require.Len(t, reqs, 4)
expected := []controller.Request{
{ID: resourceID("testing", "v1", "alt-fake", "foo")},
{ID: resourceID("testing", "v1", "alt-fake", "bar")},
{ID: resourceID("testing", "v1", "fake", "foo")},
{ID: resourceID("testing", "v1", "fake", "bar")},
}
prototest.AssertElementsMatch(t, expected, reqs)
})
t.Run("err", func(t *testing.T) {
mockMapper := controllermock.NewDependencyMapper(t)
mockMapper.EXPECT().
Execute(mock.Anything, rt, res).
Return([]controller.Request{
{ID: resourceID("testing", "v1", "fake", "foo")},
{ID: resourceID("testing", "v1", "fake", "bar")},
}, nil).
Once()
mockMapper.EXPECT().
Execute(mock.Anything, rt, res).
Return(nil, injectedErr).
Once()
mm := MultiMapper(
mockMapper.Execute,
WrapAndReplaceType(altFakeResourceType, mockMapper.Execute),
)
reqs, err := mm(context.Background(), rt, res)
require.Nil(t, reqs)
require.ErrorIs(t, err, injectedErr)
})
}