vgc unit tests part 3

Change-Id: Id87302102ea05fc99083842e3fc9ebab4304e2ca
diff --git a/internal/pkg/application/vnets_test.go b/internal/pkg/application/vnets_test.go
new file mode 100644
index 0000000..8942dbb
--- /dev/null
+++ b/internal/pkg/application/vnets_test.go
@@ -0,0 +1,647 @@
+/*
+* Copyright 2022-present Open Networking Foundation
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+ */
+
+package application
+
+import (
+	"context"
+	"reflect"
+	"testing"
+	cntlr "voltha-go-controller/internal/pkg/controller"
+	"voltha-go-controller/internal/pkg/of"
+	"voltha-go-controller/internal/pkg/util"
+	"voltha-go-controller/internal/test/mocks"
+
+	"github.com/golang/mock/gomock"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestVoltPortVnet_JSONMarshal(t *testing.T) {
+	tests := []struct {
+		name    string
+		want    []byte
+		wantErr bool
+	}{
+		{
+			name: "VoltPortVnet_JSONMarshal",
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			vpv := &VoltPortVnet{}
+			_, err := vpv.JSONMarshal()
+			if (err != nil) != tt.wantErr {
+				t.Errorf("VoltPortVnet.JSONMarshal() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+		})
+	}
+}
+
+func TestVoltPortVnet_IsServiceActivated(t *testing.T) {
+	type args struct {
+		cntx context.Context
+	}
+	tests := []struct {
+		name string
+		args args
+		want bool
+	}{
+		{
+			name: "VoltPortVnet_IsServiceActivated",
+			args: args{
+				cntx: context.Background(),
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			vpv := &VoltPortVnet{}
+			voltServ := &VoltService{
+				VoltServiceOper: VoltServiceOper{
+					Device:      test_device,
+					ForceDelete: true,
+				},
+			}
+			vpv.services.Store(test_device, voltServ)
+			if got := vpv.IsServiceActivated(tt.args.cntx); got != tt.want {
+				t.Errorf("VoltPortVnet.IsServiceActivated() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestVoltVnet_JSONMarshal(t *testing.T) {
+	tests := []struct {
+		name    string
+		want    []byte
+		wantErr bool
+	}{
+		{
+			name: "VoltVnet_JSONMarshal",
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			vv := &VoltVnet{}
+			_, err := vv.JSONMarshal()
+			if (err != nil) != tt.wantErr {
+				t.Errorf("VoltVnet.JSONMarshal() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+		})
+	}
+}
+
+func TestVoltVnet_TriggerAssociatedFlowDelete(t *testing.T) {
+	type args struct {
+		cntx   context.Context
+		device string
+	}
+	tests := []struct {
+		name string
+		args args
+		want bool
+	}{
+		{
+			name: "VoltVnet_TriggerAssociatedFlowDelete",
+			args: args{
+				cntx:   context.Background(),
+				device: test_device,
+			},
+			want: true,
+		},
+		{
+			name: "cookieList_empty",
+			args: args{
+				cntx:   context.Background(),
+				device: test_device,
+			},
+			want: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			vv := &VoltVnet{}
+			switch tt.name {
+			case "VoltVnet_TriggerAssociatedFlowDelete":
+				cookie := map[string]bool{}
+				cookie["1234"] = true
+				pendingDeleteFlow := map[string]map[string]bool{}
+				pendingDeleteFlow[test_device] = cookie
+				vv.PendingDeleteFlow = pendingDeleteFlow
+				dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+				db = dbintf
+				dbintf.EXPECT().PutVnet(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).Times(1)
+				if got := vv.TriggerAssociatedFlowDelete(tt.args.cntx, tt.args.device); got != tt.want {
+					t.Errorf("VoltVnet.TriggerAssociatedFlowDelete() = %v, want %v", got, tt.want)
+				}
+			case "cookieList_empty":
+				if got := vv.TriggerAssociatedFlowDelete(tt.args.cntx, tt.args.device); got != tt.want {
+					t.Errorf("VoltVnet.TriggerAssociatedFlowDelete() = %v, want %v", got, tt.want)
+				}
+			}
+		})
+	}
+}
+
+func TestVoltApplication_GetMatchingMcastService(t *testing.T) {
+	type args struct {
+		port   string
+		device string
+		cvlan  of.VlanType
+	}
+	tests := []struct {
+		name string
+		args args
+		want *VoltService
+	}{
+		{
+			name: "VoltApplication_GetMatchingMcastService",
+			args: args{
+				port:   "test_port",
+				device: test_device,
+				cvlan:  of.VlanAny,
+			},
+		},
+		{
+			name: "dIntf_error",
+			args: args{
+				port:   "test_port",
+				device: test_device,
+				cvlan:  of.VlanAny,
+			},
+		},
+		{
+			name: "port == d.NniPort",
+			args: args{
+				port:   "test_port",
+				device: test_device,
+				cvlan:  of.VlanAny,
+			},
+		},
+		{
+			name: "vnets_error",
+			args: args{
+				port:   "",
+				device: test_device,
+				cvlan:  of.VlanAny,
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			va := &VoltApplication{}
+			switch tt.name {
+			case "VoltApplication_GetMatchingMcastService":
+				va.DevicesDisc.Store(test_device, voltDevice)
+				va.VnetsByPort.Store("test_port", voltPortVnet1)
+				if got := va.GetMatchingMcastService(tt.args.port, tt.args.device, tt.args.cvlan); !reflect.DeepEqual(got, tt.want) {
+					t.Errorf("VoltApplication.GetMatchingMcastService() = %v, want %v", got, tt.want)
+				}
+			case "dIntf_error":
+				if got := va.GetMatchingMcastService(tt.args.port, tt.args.device, tt.args.cvlan); !reflect.DeepEqual(got, tt.want) {
+					t.Errorf("VoltApplication.GetMatchingMcastService() = %v, want %v", got, tt.want)
+				}
+			case "port == d.NniPort":
+				va.DevicesDisc.Store(test_device, voltDevice)
+				voltDevice.NniPort = "test_port"
+				if got := va.GetMatchingMcastService(tt.args.port, tt.args.device, tt.args.cvlan); !reflect.DeepEqual(got, tt.want) {
+					t.Errorf("VoltApplication.GetMatchingMcastService() = %v, want %v", got, tt.want)
+				}
+			case "vnets_error":
+				va.DevicesDisc.Store(test_device, voltDevice)
+				va.VnetsByPort.Store("test_port1", voltPortVnet1)
+				if got := va.GetMatchingMcastService(tt.args.port, tt.args.device, tt.args.cvlan); !reflect.DeepEqual(got, tt.want) {
+					t.Errorf("VoltApplication.GetMatchingMcastService() = %v, want %v", got, tt.want)
+				}
+			}
+		})
+	}
+}
+
+func TestVoltPortVnet_IgmpFlowInstallFailure(t *testing.T) {
+	type args struct {
+		cookie    string
+		errorCode uint32
+		errReason string
+	}
+	tests := []struct {
+		name string
+		args args
+	}{
+		{
+			name: "VoltPortVnet_IgmpFlowInstallFailure",
+			args: args{
+				cookie:    "test_cookie",
+				errorCode: uint32(1),
+				errReason: "errReason",
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			vpv := &VoltPortVnet{}
+			switch tt.name {
+			case "VoltPortVnet_IgmpFlowInstallFailure":
+				voltService.IgmpEnabled = true
+				vpv.services.Store("test_cookie", voltService)
+				vpv.IgmpFlowInstallFailure(tt.args.cookie, tt.args.errorCode, tt.args.errReason)
+			}
+		})
+	}
+}
+
+func TestVoltVnet_FlowRemoveFailure(t *testing.T) {
+	type args struct {
+		cntx      context.Context
+		cookie    string
+		device    string
+		errorCode uint32
+		errReason string
+	}
+	tests := []struct {
+		name string
+		args args
+	}{
+		{
+			name: "VoltVnet_FlowRemoveFailure",
+			args: args{
+				cntx:   context.Background(),
+				cookie: "1234",
+				device: test_device,
+			},
+		},
+		{
+			name: "mismatch_cookie",
+			args: args{
+				cntx:   context.Background(),
+				cookie: "1234",
+				device: test_device,
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			vv := &VoltVnet{}
+			switch tt.name {
+			case "VoltVnet_FlowRemoveFailure":
+				cookie := map[string]bool{}
+				cookie["1234"] = true
+				pendingDeleteFlow := map[string]map[string]bool{}
+				pendingDeleteFlow[test_device] = cookie
+				vv.PendingDeleteFlow = pendingDeleteFlow
+				vv.DeleteInProgress = true
+				vv.Name = "test_name"
+				dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+				db = dbintf
+				dbintf.EXPECT().DelVnet(tt.args.cntx, "test_name").Return(nil).Times(1)
+				vv.FlowRemoveFailure(tt.args.cntx, tt.args.cookie, tt.args.device, tt.args.errorCode, tt.args.errReason)
+			case "mismatch_cookie":
+				cookie := map[string]bool{}
+				cookie["12345"] = true
+				pendingDeleteFlow := map[string]map[string]bool{}
+				pendingDeleteFlow[test_device] = cookie
+				vv.PendingDeleteFlow = pendingDeleteFlow
+				vv.DeleteInProgress = true
+				vv.Name = "test_name"
+				dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+				db = dbintf
+				dbintf.EXPECT().DelVnet(tt.args.cntx, "test_name").Return(nil).Times(1)
+				vv.FlowRemoveFailure(tt.args.cntx, tt.args.cookie, tt.args.device, tt.args.errorCode, tt.args.errReason)
+			}
+		})
+	}
+}
+
+func TestVoltVnet_FlowRemoveSuccess(t *testing.T) {
+	type args struct {
+		cntx   context.Context
+		cookie string
+		device string
+	}
+	tests := []struct {
+		name string
+		args args
+	}{
+		{
+			name: "VoltVnet_FlowRemoveSuccess",
+			args: args{
+				cntx:   context.Background(),
+				cookie: "1234",
+				device: test_device,
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			vv := &VoltVnet{}
+			cookie := map[string]bool{}
+			cookie["1234"] = true
+			pendingDeleteFlow := map[string]map[string]bool{}
+			pendingDeleteFlow[test_device] = cookie
+			vv.PendingDeleteFlow = pendingDeleteFlow
+			ga := GetApplication()
+			voltDevice.ConfiguredVlanForDeviceFlows = util.NewConcurrentMap()
+			ga.DevicesDisc.Store(test_device, voltDevice)
+			dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+			db = dbintf
+			dbintf.EXPECT().PutVnet(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).Times(1)
+			vv.FlowRemoveSuccess(tt.args.cntx, tt.args.cookie, tt.args.device)
+		})
+	}
+}
+
+func TestVoltPortVnet_FlowRemoveFailure(t *testing.T) {
+	type args struct {
+		cntx      context.Context
+		cookie    string
+		device    string
+		errorCode uint32
+		errReason string
+	}
+	tests := []struct {
+		name string
+		args args
+	}{
+		{
+			name: "VoltPortVnet_FlowRemoveFailure",
+			args: args{
+				cntx:   context.Background(),
+				cookie: "1234",
+				device: test_device,
+			},
+		},
+		{
+			name: "DeleteInProgress_false",
+			args: args{
+				cntx:   context.Background(),
+				cookie: "1234",
+				device: test_device,
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			vpv := &VoltPortVnet{}
+			switch tt.name {
+			case "VoltPortVnet_FlowRemoveFailure":
+				vpv.services.Store("1234", voltService)
+				vpv.DeleteInProgress = true
+				dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+				db = dbintf
+				dbintf.EXPECT().DelVpv(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).Times(1)
+				vpv.FlowRemoveFailure(tt.args.cntx, tt.args.cookie, tt.args.device, tt.args.errorCode, tt.args.errReason)
+			case "DeleteInProgress_false":
+				dbintf := mocks.NewMockDBIntf(gomock.NewController(t))
+				db = dbintf
+				dbintf.EXPECT().PutVpv(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).Times(1)
+				vpv.FlowRemoveFailure(tt.args.cntx, tt.args.cookie, tt.args.device, tt.args.errorCode, tt.args.errReason)
+			}
+		})
+	}
+}
+
+func TestVoltPortVnet_PushFlows(t *testing.T) {
+	type args struct {
+		cntx   context.Context
+		device *VoltDevice
+		flow   *of.VoltFlow
+	}
+	vsf := make(map[uint64]*of.VoltSubFlow)
+	vsf[uint64(1)] = &of.VoltSubFlow{
+		Cookie: uint64(1234),
+	}
+	tests := []struct {
+		name    string
+		args    args
+		wantErr bool
+	}{
+		{
+			name: "VoltPortVnet_PushFlows",
+			args: args{
+				cntx:   context.Background(),
+				device: voltDevice,
+				flow: &of.VoltFlow{
+					PortName: "test_port",
+					SubFlows: vsf,
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			vpv := &VoltPortVnet{}
+			_ = cntlr.NewController(context.Background(), mocks.NewMockApp(gomock.NewController(t)))
+			err := vpv.PushFlows(tt.args.cntx, tt.args.device, tt.args.flow)
+			assert.NotNil(t, err)
+		})
+	}
+}
+
+func TestVoltPortVnet_isVlanMatching(t *testing.T) {
+	type args struct {
+		cvlan of.VlanType
+		svlan of.VlanType
+	}
+	tests := []struct {
+		name string
+		args args
+		want bool
+	}{
+		{
+			name: "VoltPortVnet_isVlanMatching",
+			args: args{
+				cvlan: of.VlanAny,
+				svlan: of.VlanAny,
+			},
+			want: true,
+		},
+		{
+			name: "vpv.VlanControl_nil",
+			args: args{
+				cvlan: of.VlanAny,
+				svlan: of.VlanAny,
+			},
+			want: true,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			vpv := &VoltPortVnet{}
+			switch tt.name {
+			case "VoltPortVnet_isVlanMatching":
+				vpv.VlanControl = ONUCVlanOLTSVlan
+				vpv.SVlan = of.VlanAny
+				vpv.CVlan = of.VlanAny
+				if got := vpv.isVlanMatching(tt.args.cvlan, tt.args.svlan); got != tt.want {
+					t.Errorf("VoltPortVnet.isVlanMatching() = %v, want %v", got, tt.want)
+				}
+			}
+		})
+	}
+}
+
+func TestProcessIcmpv6McGroup(t *testing.T) {
+	type args struct {
+		device string
+		delete bool
+	}
+	tests := []struct {
+		name    string
+		args    args
+		wantErr bool
+	}{
+		{
+			name: "TestProcessIcmpv6McGroup",
+			args: args{
+				device: test_device,
+				delete: false,
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			err := ProcessIcmpv6McGroup(tt.args.device, tt.args.delete)
+			assert.NotNil(t, err)
+		})
+	}
+}
+
+func TestVoltVnet_setPbitRemarking(t *testing.T) {
+	tests := []struct {
+		name string
+		want uint32
+	}{
+		{
+			name: "VoltVnet_setPbitRemarking",
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			vv := &VoltVnet{}
+			a := make(map[of.PbitType]of.PbitType)
+			a[of.PbitMatchAll] = of.PbitMatchAll
+			vv.CtrlPktPbitRemark = a
+			if got := vv.setPbitRemarking(); got != tt.want {
+				t.Errorf("VoltVnet.setPbitRemarking() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestBuildDSArpFlow(t *testing.T) {
+	type args struct {
+		inport uint32
+		vnet   *VoltVnet
+	}
+	tests := []struct {
+		name string
+		args args
+		want *of.VoltFlow
+	}{
+		{
+			name: "BuildDSArpFlow",
+			args: args{
+				inport: uint32(1),
+				vnet: &VoltVnet{
+					Version: "test_version",
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			switch tt.name {
+			case "BuildDSArpFlow":
+				got := BuildDSArpFlow(tt.args.inport, tt.args.vnet)
+				assert.NotNil(t, got)
+			}
+		})
+	}
+}
+
+func TestBuildICMPv6Flow(t *testing.T) {
+	type args struct {
+		inport uint32
+		vnet   *VoltVnet
+	}
+	tests := []struct {
+		name string
+		args args
+		want *of.VoltFlow
+	}{
+		{
+			name: "BuildICMPv6Flow",
+			args: args{
+				inport: uint32(1),
+				vnet: &VoltVnet{
+					Version: "test_version",
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got := BuildICMPv6Flow(tt.args.inport, tt.args.vnet)
+			assert.NotNil(t, got)
+		})
+	}
+}
+
+func TestVoltApplication_DeleteDevFlowForVlanFromDevice(t *testing.T) {
+	type args struct {
+		cntx            context.Context
+		vnet            *VoltVnet
+		deviceSerialNum string
+	}
+	tests := []struct {
+		name string
+		args args
+	}{
+		{
+			name: "device.SerialNum != deviceSerialNum",
+			args: args{
+				cntx: context.Background(),
+				vnet: &VoltVnet{
+					Version: "test_version",
+				},
+			},
+		},
+		{
+			name: "VoltApplication_DeleteDevFlowForVlanFromDevice",
+			args: args{
+				cntx: context.Background(),
+				vnet: &VoltVnet{
+					Version: "test_version",
+				},
+				deviceSerialNum: "test_serial_number",
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			va := &VoltApplication{}
+			switch tt.name {
+			case "device.SerialNum != deviceSerialNum":
+				va.DevicesDisc.Store(test_device, voltDevice)
+				va.DeleteDevFlowForVlanFromDevice(tt.args.cntx, tt.args.vnet, tt.args.deviceSerialNum)
+			case "VoltApplication_DeleteDevFlowForVlanFromDevice":
+				va.DevicesDisc.Store(test_device, voltDevice)
+				va.DeleteDevFlowForVlanFromDevice(tt.args.cntx, tt.args.vnet, tt.args.deviceSerialNum)
+			}
+		})
+	}
+}