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.
consul/proto-public/pbcatalog/v1alpha1/failover_policy_extras_test.go

172 lines
3.9 KiB

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package catalogv1alpha1
import (
"testing"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
pbresource "github.com/hashicorp/consul/proto-public/pbresource"
)
func TestFailoverPolicy_IsEmpty(t *testing.T) {
t.Run("nil", func(t *testing.T) {
var fc *FailoverConfig
require.True(t, fc.IsEmpty())
})
t.Run("empty", func(t *testing.T) {
fc := &FailoverConfig{}
require.True(t, fc.IsEmpty())
})
t.Run("dest", func(t *testing.T) {
fc := &FailoverConfig{
Destinations: []*FailoverDestination{
newFailoverDestination("foo"),
},
}
require.False(t, fc.IsEmpty())
})
t.Run("regions", func(t *testing.T) {
fc := &FailoverConfig{
Regions: []string{"us-east"},
}
require.False(t, fc.IsEmpty())
})
t.Run("regions", func(t *testing.T) {
fc := &FailoverConfig{
SamenessGroup: "blah",
}
require.False(t, fc.IsEmpty())
})
}
func TestFailoverPolicy_GetUnderlyingDestinations_AndRefs(t *testing.T) {
type testcase struct {
failover *FailoverPolicy
expectDests []*FailoverDestination
expectRefs []*pbresource.Reference
}
run := func(t *testing.T, tc testcase) {
assertSliceEquals(t, tc.expectDests, tc.failover.GetUnderlyingDestinations())
assertSliceEquals(t, tc.expectRefs, tc.failover.GetUnderlyingDestinationRefs())
}
cases := map[string]testcase{
"nil": {},
"kitchen sink dests": {
failover: &FailoverPolicy{
Config: &FailoverConfig{
Destinations: []*FailoverDestination{
newFailoverDestination("foo"),
newFailoverDestination("bar"),
},
},
PortConfigs: map[string]*FailoverConfig{
"admin": {
Destinations: []*FailoverDestination{
newFailoverDestination("admin"),
},
},
"web": {
Destinations: []*FailoverDestination{
newFailoverDestination("foo"), // duplicated
newFailoverDestination("www"),
},
},
},
},
expectDests: []*FailoverDestination{
newFailoverDestination("foo"),
newFailoverDestination("bar"),
newFailoverDestination("admin"),
newFailoverDestination("foo"), // duplicated
newFailoverDestination("www"),
},
expectRefs: []*pbresource.Reference{
newFailoverRef("foo"),
newFailoverRef("bar"),
newFailoverRef("admin"),
newFailoverRef("foo"), // duplicated
newFailoverRef("www"),
},
},
}
for name, tc := range cases {
t.Run(name, func(t *testing.T) {
run(t, tc)
})
}
}
func assertSliceEquals[V proto.Message](t *testing.T, expect, got []V) {
t.Helper()
require.Len(t, got, len(expect))
// O(N*M) scan
var expectedMissing []string
for _, expectVal := range expect {
found := false
for j, gotVal := range got {
if proto.Equal(expectVal, gotVal) {
found = true
got = append(got[:j], got[j+1:]...) // remove found item
break
}
}
if !found {
expectedMissing = append(expectedMissing, protoToString(t, expectVal))
}
}
if len(expectedMissing) > 0 || len(got) > 0 {
var gotMissing []string
for _, gotVal := range got {
gotMissing = append(gotMissing, protoToString(t, gotVal))
}
t.Fatalf("assertion failed: unmatched values\n\texpected: %s\n\tactual: %s",
expectedMissing,
gotMissing,
)
}
}
func protoToString[V proto.Message](t *testing.T, pb V) string {
m := protojson.MarshalOptions{
Indent: " ",
}
gotJSON, err := m.Marshal(pb)
require.NoError(t, err)
return string(gotJSON)
}
func newFailoverRef(name string) *pbresource.Reference {
return &pbresource.Reference{
Type: &pbresource.Type{
Group: "fake",
GroupVersion: "v1alpha1",
Kind: "fake",
},
Tenancy: &pbresource.Tenancy{
Partition: "default",
Namespace: "default",
PeerName: "local",
},
Name: name,
}
}
func newFailoverDestination(name string) *FailoverDestination {
return &FailoverDestination{
Ref: newFailoverRef(name),
}
}