Consul is a distributed, highly available, and data center aware solution to connect and configure applications across dynamic, distributed infrastructure.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

166 lines
5.2 KiB

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package dependency
import (
"context"
"testing"
"github.com/hashicorp/consul/internal/controller"
"github.com/hashicorp/consul/internal/controller/controllermock"
"github.com/hashicorp/consul/internal/controller/dependency/dependencymock"
"github.com/hashicorp/consul/internal/resource/resourcetest"
"github.com/hashicorp/consul/proto-public/pbresource"
"github.com/hashicorp/consul/proto/private/prototest"
"github.com/hashicorp/go-hclog"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
func TestMapperWithTransform(t *testing.T) {
res := resourcetest.Resource(fakeMapType, "something").Build()
rt := controller.Runtime{
// populating some field to differentiate from zero value
Logger: hclog.Default(),
}
transformed1 := resourcetest.Resource(fakeResourceType, "foo").Build()
transformed2 := resourcetest.Resource(fakeResourceType, "bar").Build()
t.Run("transform-err", func(t *testing.T) {
mockTransform := dependencymock.NewDependencyTransform(t)
mockTransform.EXPECT().
Execute(mock.Anything, rt, res).
Return(nil, injectedErr).
Once()
mockMapper := controllermock.NewDependencyMapper(t)
mt := MapperWithTransform(mockMapper.Execute, mockTransform.Execute)
reqs, err := mt(context.Background(), rt, res)
require.Nil(t, reqs)
require.ErrorIs(t, err, injectedErr)
})
t.Run("mapper-err", func(t *testing.T) {
mockTransform := dependencymock.NewDependencyTransform(t)
mockTransform.EXPECT().
Execute(mock.Anything, rt, res).
Return([]*pbresource.Resource{transformed1, transformed2}, nil).
Once()
mockMapper := controllermock.NewDependencyMapper(t)
mockMapper.EXPECT().
Execute(mock.Anything, rt, transformed1).
Return(nil, injectedErr).
Once()
mt := MapperWithTransform(mockMapper.Execute, mockTransform.Execute)
reqs, err := mt(context.Background(), rt, res)
require.Nil(t, reqs)
require.ErrorIs(t, err, injectedErr)
})
t.Run("ok", func(t *testing.T) {
mockTransform := dependencymock.NewDependencyTransform(t)
mockTransform.EXPECT().
Execute(mock.Anything, rt, res).
Return([]*pbresource.Resource{transformed1, transformed2}, nil).
Once()
mockMapper := controllermock.NewDependencyMapper(t)
mockMapper.EXPECT().
Execute(mock.Anything, rt, transformed1).
Return([]controller.Request{
{ID: resourceID("testing", "v1", "alt-fake", "foo")},
{ID: resourceID("testing", "v1", "alt-fake", "bar")},
}, nil).
Once()
mockMapper.EXPECT().
Execute(mock.Anything, rt, transformed2).
Return([]controller.Request{
{ID: resourceID("testing", "v1", "alt-fake", "foo2")},
{ID: resourceID("testing", "v1", "alt-fake", "bar2")},
}, nil).
Once()
mt := MapperWithTransform(mockMapper.Execute, mockTransform.Execute)
reqs, err := mt(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", "alt-fake", "foo2")},
{ID: resourceID("testing", "v1", "alt-fake", "bar2")},
}
prototest.AssertElementsMatch(t, expected, reqs)
})
}
func TestTransformChain(t *testing.T) {
res := resourcetest.Resource(fakeMapType, "something").Build()
rt := controller.Runtime{
// populating some field to differentiate from zero value
Logger: hclog.Default(),
}
transformed1 := resourcetest.Resource(fakeResourceType, "foo").Build()
transformed2 := resourcetest.Resource(fakeResourceType, "bar").Build()
out1 := resourcetest.Resource(altFakeResourceType, "foo").Build()
out2 := resourcetest.Resource(altFakeResourceType, "bar").Build()
out3 := resourcetest.Resource(altFakeResourceType, "baz").Build()
t.Run("err", func(t *testing.T) {
mockTransform := dependencymock.NewDependencyTransform(t)
mockTransform.EXPECT().
Execute(mock.Anything, rt, res).
Return([]*pbresource.Resource{transformed1}, nil).
Once()
mockTransform.EXPECT().
Execute(mock.Anything, rt, transformed1).
Return(nil, injectedErr).
Once()
resources, err := TransformChain(mockTransform.Execute, mockTransform.Execute)(
context.Background(),
rt,
res,
)
require.Nil(t, resources)
require.ErrorIs(t, err, injectedErr)
})
t.Run("ok", func(t *testing.T) {
mockTransform := dependencymock.NewDependencyTransform(t)
// Transform Chain
//
// 1. Transform original res to the two outputs
// 2. Transform the first output from 1
// 3. Transform the second output from 1
mockTransform.EXPECT().
Execute(mock.Anything, rt, res).
Return([]*pbresource.Resource{transformed1, transformed2}, nil).
Once()
mockTransform.EXPECT().
Execute(mock.Anything, rt, transformed1).
Return([]*pbresource.Resource{out1, out2}, nil).
Once()
mockTransform.EXPECT().
Execute(mock.Anything, rt, transformed2).
Return([]*pbresource.Resource{out3}, nil).
Once()
resources, err := TransformChain(mockTransform.Execute, mockTransform.Execute)(
context.Background(),
rt,
res,
)
require.NoError(t, err)
expected := []*pbresource.Resource{out1, out2, out3}
prototest.AssertElementsMatch(t, expected, resources)
})
}