Skip to content

Commit

Permalink
Enhance the IPBlocksInfo unit tests (#790)
Browse files Browse the repository at this point in the history
Signed-off-by: Yanjun Zhou <[email protected]>
  • Loading branch information
yanjunz97 authored Oct 3, 2024
1 parent 2183145 commit b910006
Show file tree
Hide file tree
Showing 2 changed files with 234 additions and 12 deletions.
107 changes: 107 additions & 0 deletions pkg/nsx/services/ipblocksinfo/ipblocksinfo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import (
"fmt"
"reflect"
"testing"
"time"

"github.com/agiledragon/gomonkey"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/client-go/tools/cache"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/vmware-tanzu/nsx-operator/pkg/apis/vpc/v1alpha1"
Expand Down Expand Up @@ -167,3 +170,107 @@ func TestIPBlocksInfoService_SyncIPBlocksInfo(t *testing.T) {
err := service.SyncIPBlocksInfo(context.TODO())
assert.Equal(t, nil, err)
}

func TestIPBlocksInfoService_StartPeriodicSync(t *testing.T) {
ipBlocksInfoService := &IPBlocksInfoService{
Service: common.Service{},
SyncTask: NewIPBlocksInfoSyncTask(time.Millisecond*100, time.Millisecond*50),
}
done := make(chan bool)
go func() {
syncIPBlocksInfoPatch := gomonkey.ApplyMethod(reflect.TypeOf(ipBlocksInfoService), "SyncIPBlocksInfo", func(_ *IPBlocksInfoService, cxt context.Context) error {
return fmt.Errorf("mock error")
})
defer syncIPBlocksInfoPatch.Reset()
ipBlocksInfoService.StartPeriodicSync()
done <- true
}()

time.Sleep(time.Millisecond * 20)
ipBlocksInfoService.SyncTask.resetChan <- struct{}{}

select {
case <-done:
t.Error("StartPeriodicSync stop unexpectedly")
case <-time.After(time.Millisecond * 500):
// Stop StartPeriodicSync after some time
}
}

func TestIPBlocksInfoService_getIPBlockCIDRsFromStore(t *testing.T) {
ipBlockStore := &IPBlockStore{ResourceStore: common.ResourceStore{
Indexer: cache.NewIndexer(keyFunc, cache.Indexers{}),
BindingType: model.IpAddressBlockBindingType(),
}}
ipblock1 := model.IpAddressBlock{
Path: &ipBlocksPath1,
}
ipBlockStore.Apply(&ipblock1)
service := &IPBlocksInfoService{}

// Fetch non-existed IPBlocks
pathSet := sets.New[string]()
pathSet.Insert(ipBlocksPath2)
_, err := service.getIPBlockCIDRsFromStore(pathSet, ipBlockStore)
assert.ErrorContains(t, err, "failed to get IPBlock")

// No CIDR in IPBlocks
pathSet = sets.New[string]()
pathSet.Insert(ipBlocksPath1)
_, err = service.getIPBlockCIDRsFromStore(pathSet, ipBlockStore)
assert.ErrorContains(t, err, "failed to get CIDR from ipblock")
}

func TestIPBlocksInfoService_createOrUpdateIPBlocksInfo(t *testing.T) {
service, mockController, mockK8sClient := createService(t)
defer mockController.Finish()

ipBlocksInfo := v1alpha1.IPBlocksInfo{}
mockErr := fmt.Errorf("mock error")

// Fail to get IPBlocksInfo CR
mockK8sClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(mockErr)

err := service.createOrUpdateIPBlocksInfo(context.TODO(), &ipBlocksInfo, false)
assert.ErrorIs(t, err, mockErr)

// Fail to create IPBlocksInfo CR
mockK8sClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(apierrors.NewNotFound(v1alpha1.Resource("IPBlocksInfo"), "ipBlocksInfoName"))
mockK8sClient.EXPECT().Create(gomock.Any(), gomock.Any()).Return(mockErr)
err = service.createOrUpdateIPBlocksInfo(context.TODO(), &ipBlocksInfo, false)
assert.ErrorIs(t, err, mockErr)

// // Fail to udpate IPBlocksInfo CR
mockK8sClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).Do(func(_ context.Context, _ client.ObjectKey, obj client.Object, option ...client.GetOption) error {
ipBlocksInfoCR := obj.(*v1alpha1.IPBlocksInfo)
ipBlocksInfoCR.ExternalIPCIDRs = []string{ipBlocksMap[ipBlocksPath4]}
return nil
})
mockK8sClient.EXPECT().Update(gomock.Any(), gomock.Any()).Return(mockErr)
err = service.createOrUpdateIPBlocksInfo(context.TODO(), &ipBlocksInfo, false)
assert.ErrorIs(t, err, mockErr)
}

func TestIsDefaultNetworkConfigCR(t *testing.T) {
testCRD1 := v1alpha1.VPCNetworkConfiguration{}
testCRD1.Name = "test-1"
testCRD2 := v1alpha1.VPCNetworkConfiguration{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
common.AnnotationDefaultNetworkConfig: "invalid",
},
},
}
testCRD2.Name = "test-2"
testCRD3 := v1alpha1.VPCNetworkConfiguration{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
common.AnnotationDefaultNetworkConfig: "true",
},
},
}
testCRD3.Name = "test-3"
assert.Equal(t, isDefaultNetworkConfigCR(testCRD1), false)
assert.Equal(t, isDefaultNetworkConfigCR(testCRD2), false)
assert.Equal(t, isDefaultNetworkConfigCR(testCRD3), true)
}
139 changes: 127 additions & 12 deletions pkg/nsx/services/ipblocksinfo/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,23 @@ import (

"github.com/stretchr/testify/assert"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model"
"k8s.io/client-go/tools/cache"

"github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/common"
)

var (
fakeVpcPath = "vpc-path"
fakeVpcProfilePath = "vpc-connectivity-profile-path"
fakeIpBlockPath = "ip-block-path"
fakeDeleted = true
)

func Test_KeyFunc(t *testing.T) {
vpcPath := "vpc-path"
vpc := model.Vpc{Path: &vpcPath}
vpcProfilePath := "vpc-connectivity-profile-path"
vpcProfile := model.VpcConnectivityProfile{Path: &vpcProfilePath}
ipBlockPath := "ip-block-path"
ipBlock := model.IpAddressBlock{Path: &ipBlockPath}
vpc := model.Vpc{Path: &fakeVpcPath}
vpcProfile := model.VpcConnectivityProfile{Path: &fakeVpcProfilePath}
ipBlock := model.IpAddressBlock{Path: &fakeIpBlockPath}
notSupported := struct{}{}

type args struct {
obj interface{}
Expand All @@ -23,32 +31,139 @@ func Test_KeyFunc(t *testing.T) {
name string
expectedKey string
item args
expectedErr bool
}{
{
name: "Vpc",
item: args{obj: &vpc},
expectedKey: vpcPath,
expectedKey: fakeVpcPath,
},
{
name: "VpcConnectivityProfile",
item: args{obj: &vpcProfile},
expectedKey: vpcProfilePath,
expectedKey: fakeVpcProfilePath,
},
{
name: "IpBlock",
item: args{obj: &ipBlock},
expectedKey: ipBlockPath,
expectedKey: fakeIpBlockPath,
},
{
name: "NotSupported",
item: args{obj: &notSupported},
expectedErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := keyFunc(tt.item.obj)
assert.Nil(t, err)
if got != tt.expectedKey {
t.Errorf("keyFunc() = %v, want %v", got, tt.expectedKey)
if !tt.expectedErr {
assert.Nil(t, err)
if got != tt.expectedKey {
t.Errorf("keyFunc() = %v, want %v", got, tt.expectedKey)
}
} else {
assert.NotNil(t, err)
}

})
}

}

func TestVPCConnectivityProfileStore_Apply(t *testing.T) {
vpcConnectivityProfileStore := &VPCConnectivityProfileStore{ResourceStore: common.ResourceStore{
Indexer: cache.NewIndexer(keyFunc, cache.Indexers{}),
BindingType: model.VpcConnectivityProfileBindingType(),
}}

profile1 := model.VpcConnectivityProfile{
Path: &fakeVpcProfilePath,
}
profile2 := model.VpcConnectivityProfile{
Path: &fakeVpcProfilePath,
MarkedForDelete: &fakeDeleted,
}

type args struct {
i interface{}
}
tests := []struct {
name string
args args
}{
{"Add", args{i: &profile1}},
{"Delete", args{i: &profile2}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := vpcConnectivityProfileStore.Apply(tt.args.i)
assert.Nil(t, err)
})
}
}

func TestVPCStore_Apply(t *testing.T) {
vpcStore := &VPCStore{ResourceStore: common.ResourceStore{
Indexer: cache.NewIndexer(keyFunc, cache.Indexers{}),
BindingType: model.VpcBindingType(),
}}

vpc1 := model.Vpc{
Path: &fakeVpcPath,
}
vpc2 := model.Vpc{
Path: &fakeVpcPath,
MarkedForDelete: &fakeDeleted,
}

type args struct {
i interface{}
}
tests := []struct {
name string
args args
}{
{"Add", args{i: &vpc1}},
{"Delete", args{i: &vpc2}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := vpcStore.Apply(tt.args.i)
assert.Nil(t, err)
})
}
}

func TestIPBlockStore_Apply(t *testing.T) {
ipBlockStore := &IPBlockStore{ResourceStore: common.ResourceStore{
Indexer: cache.NewIndexer(keyFunc, cache.Indexers{}),
BindingType: model.IpAddressBlockBindingType(),
}}

ipblock1 := model.IpAddressBlock{
Path: &fakeIpBlockPath,
}
ipblock2 := model.IpAddressBlock{
Path: &fakeIpBlockPath,
MarkedForDelete: &fakeDeleted,
}

type args struct {
i interface{}
}
tests := []struct {
name string
args args
}{
{"Add", args{i: &ipblock1}},
{"Delete", args{i: &ipblock2}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := ipBlockStore.Apply(tt.args.i)
assert.Nil(t, err)
})
}
}

0 comments on commit b910006

Please sign in to comment.