vgc UTs part 4

Change-Id: I0e78854fefb8f0ad270a84bc88982f859a0d5995
diff --git a/internal/pkg/application/dhcprelay_test.go b/internal/pkg/application/dhcprelay_test.go
new file mode 100644
index 0000000..2354d41
--- /dev/null
+++ b/internal/pkg/application/dhcprelay_test.go
@@ -0,0 +1,637 @@
+/*
+* 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"
+	"encoding/json"
+	"net"
+	"reflect"
+	"sync"
+	"testing"
+	"voltha-go-controller/internal/pkg/of"
+	"voltha-go-controller/internal/test/mocks"
+
+	"github.com/golang/mock/gomock"
+	"github.com/google/gopacket"
+	"github.com/google/gopacket/layers"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestVoltApplication_GetIgnoredPorts(t *testing.T) {
+	voltDevice := &VoltDevice{
+		Name:         "11c3175b-50f3-4220-9555-93df733ded1d",
+		SerialNum:    "SDX6320031",
+		SouthBoundID: "68580342-6b3e-57cb-9ea4-06125594e330",
+		NniPort:      "16777472",
+		Ports:        sync.Map{},
+		PonPortList:  sync.Map{},
+	}
+	voltPort := &VoltPort{
+		Name:                     "16777472",
+		Device:                   "SDX6320031",
+		ID:                       16777472,
+		State:                    PortStateDown,
+		ChannelPerSubAlarmRaised: false,
+		Type:                     VoltPortTypeNni,
+	}
+	voltPortVnets := make([]*VoltPortVnet, 0)
+	voltPortVnet := &VoltPortVnet{
+		Device:      "SDX6320031",
+		Port:        "16777472",
+		MacLearning: MacLearningNone,
+	}
+	voltPortVnets = append(voltPortVnets, voltPortVnet)
+	IgnoredPorts := make(map[string][]string)
+	IgnoredPorts["SDX6320031"] = append(IgnoredPorts["SDX6320031"], "16777472")
+	tests := []struct {
+		name    string
+		want    map[string][]string
+		wantErr bool
+	}{
+		{
+			name:    "Positive_Case_GetIgnoredPorts",
+			want:    IgnoredPorts,
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			va := &VoltApplication{
+				DevicesDisc: sync.Map{},
+			}
+			va.DevicesDisc.Store("SDX6320031", voltDevice)
+			voltDevice.Ports.Store("16777472", voltPort)
+			voltApp := GetApplication()
+			voltApp.VnetsByPort.Store("16777472", voltPortVnets)
+			got, err := va.GetIgnoredPorts()
+			if (err != nil) != tt.wantErr {
+				t.Errorf("VoltApplication.GetIgnoredPorts() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("VoltApplication.GetIgnoredPorts() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestDhcpNetworks_AddDhcpSession(t *testing.T) {
+	pkt := mocks.NewMockPacket(gomock.NewController(t))
+	type args struct {
+		pkt     gopacket.Packet
+		session IDhcpRelaySession
+	}
+	tests := []struct {
+		name    string
+		args    args
+		wantErr bool
+	}{
+		{
+			name: "DhcpNetworks_AddDhcpSession",
+			args: args{
+				pkt:     pkt,
+				session: &VoltPortVnet{},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			network := make(map[uint32]*DhcpRelayVnet)
+			dn := &DhcpNetworks{
+				Networks: network,
+			}
+			pkt.EXPECT().Layer(layers.LayerTypeEthernet).Return(eth).Times(1)
+			if err := dn.AddDhcpSession(tt.args.pkt, tt.args.session); (err != nil) != tt.wantErr {
+				t.Errorf("DhcpNetworks.AddDhcpSession() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func TestDhcpNetworks_DelDhcpSession(t *testing.T) {
+	pkt := mocks.NewMockPacket(gomock.NewController(t))
+	type args struct {
+		pkt     gopacket.Packet
+		session IDhcpRelaySession
+	}
+	tests := []struct {
+		name string
+		args args
+	}{
+		{
+			name: "DhcpNetworks_DelDhcpSession",
+			args: args{
+				pkt:     pkt,
+				session: &VoltPortVnet{},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			network := make(map[uint32]*DhcpRelayVnet)
+			dn := &DhcpNetworks{
+				Networks: network,
+			}
+			pkt.EXPECT().Layer(layers.LayerTypeEthernet).Return(eth).Times(1)
+			dn.DelDhcpSession(tt.args.pkt, tt.args.session)
+		})
+	}
+}
+
+func TestDhcpNetworks_AddDhcp6Session(t *testing.T) {
+	type args struct {
+		key     [MaxLenDhcpv6DUID]byte
+		session IDhcpRelaySession
+	}
+	tests := []struct {
+		name    string
+		args    args
+		wantErr bool
+	}{
+		{
+			name: "DhcpNetworks_AddDhcp6Session",
+			args: args{
+				session: &VoltPortVnet{},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			network := make(map[uint32]*DhcpRelayVnet)
+			dn := &DhcpNetworks{
+				Networks: network,
+			}
+			if err := dn.AddDhcp6Session(tt.args.key, tt.args.session); (err != nil) != tt.wantErr {
+				t.Errorf("DhcpNetworks.AddDhcp6Session() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func TestDhcpNetworks_DelDhcp6Session(t *testing.T) {
+	type args struct {
+		key     [MaxLenDhcpv6DUID]byte
+		session IDhcpRelaySession
+	}
+	tests := []struct {
+		name string
+		args args
+	}{
+		{
+			name: "DhcpNetworks_DelDhcp6Session",
+			args: args{
+				session: &VoltPortVnet{},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			network := make(map[uint32]*DhcpRelayVnet)
+			network[uint32(4097)] = &DhcpRelayVnet{
+				InnerVlan: uint16(4097),
+			}
+			dn := &DhcpNetworks{
+				Networks: network,
+			}
+			dn.DelDhcp6Session(tt.args.key, tt.args.session)
+		})
+	}
+}
+
+func TestDhcpNetworks_GetDhcpSession(t *testing.T) {
+	type fields struct {
+		Networks map[uint32]*DhcpRelayVnet
+	}
+	type args struct {
+		outerVlan uint16
+		innerVlan uint16
+		addr      net.HardwareAddr
+	}
+	macAdd, _ := net.ParseMAC("ff:ff:ff:ff:ff:ff")
+	tests := []struct {
+		name   string
+		fields fields
+		args   args
+		want   IDhcpRelaySession
+	}{
+		{
+			name: "DhcpNetworks_GetDhcpSession",
+			args: args{
+				outerVlan: uint16(0),
+				innerVlan: uint16(4097),
+				addr:      macAdd,
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			network := make(map[uint32]*DhcpRelayVnet)
+			network[uint32(4097)] = &DhcpRelayVnet{
+				InnerVlan: uint16(4097),
+			}
+			dn := &DhcpNetworks{
+				Networks: network,
+			}
+			got, err := dn.GetDhcpSession(tt.args.outerVlan, tt.args.innerVlan, tt.args.addr)
+			assert.NotNil(t, err)
+			assert.Nil(t, got)
+		})
+	}
+}
+
+func TestDhcpNetworks_GetDhcp6Session(t *testing.T) {
+	type fields struct {
+		Networks map[uint32]*DhcpRelayVnet
+	}
+	type args struct {
+		outerVlan uint16
+		innerVlan uint16
+		key       [MaxLenDhcpv6DUID]byte
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		want    IDhcpRelaySession
+		wantErr bool
+	}{
+		{
+			name: "DhcpNetworks_GetDhcp6Session",
+			args: args{
+				outerVlan: uint16(0),
+				innerVlan: uint16(4097),
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			network := make(map[uint32]*DhcpRelayVnet)
+			network[uint32(4097)] = &DhcpRelayVnet{
+				InnerVlan: uint16(4097),
+			}
+			dn := &DhcpNetworks{
+				Networks: network,
+			}
+			got, err := dn.GetDhcp6Session(tt.args.outerVlan, tt.args.innerVlan, tt.args.key)
+			assert.NotNil(t, err)
+			assert.Nil(t, got)
+		})
+	}
+}
+
+func TestGetVnetForV4Nni(t *testing.T) {
+	type args struct {
+		dhcp  *layers.DHCPv4
+		cvlan of.VlanType
+		svlan of.VlanType
+		pbit  uint8
+	}
+	macAdd, _ := net.ParseMAC("ff:ff:ff:ff:ff:ff")
+	tests := []struct {
+		name    string
+		args    args
+		want    []*VoltPortVnet
+		wantErr bool
+	}{
+		{
+			name: "GetVnetForV4Nni",
+			args: args{
+				cvlan: of.VlanAny,
+				svlan: of.VlanAny,
+				dhcp: &layers.DHCPv4{
+					BaseLayer:    dot1Q.BaseLayer,
+					ClientHWAddr: macAdd,
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, err := GetVnetForV4Nni(tt.args.dhcp, tt.args.cvlan, tt.args.svlan, tt.args.pbit)
+			assert.NotNil(t, err)
+			assert.Nil(t, got)
+		})
+	}
+}
+
+func TestGetVnetForV6Nni(t *testing.T) {
+	type args struct {
+		dhcp      *layers.DHCPv6
+		cvlan     of.VlanType
+		svlan     of.VlanType
+		pbit      uint8
+		clientMAC net.HardwareAddr
+	}
+	macAdd, _ := net.ParseMAC("ff:ff:ff:ff:ff:ff")
+	tests := []struct {
+		name    string
+		args    args
+		want    []*VoltPortVnet
+		want1   net.HardwareAddr
+		wantErr bool
+	}{
+		{
+			name: "GetVnetForV6Nni",
+			args: args{
+				dhcp: &layers.DHCPv6{
+					BaseLayer: dot1Q.BaseLayer,
+					Options: layers.DHCPv6Options{
+						{
+							Code: layers.DHCPv6OptClientID,
+							Data: []byte{2, 3, 4, 2, 3, 4, 2, 3, 4},
+						},
+					},
+				},
+				cvlan:     of.VlanAny,
+				svlan:     of.VlanAny,
+				clientMAC: macAdd,
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, got1, err := GetVnetForV6Nni(tt.args.dhcp, tt.args.cvlan, tt.args.svlan, tt.args.pbit, tt.args.clientMAC)
+			assert.NotNil(t, err)
+			assert.Nil(t, got)
+			assert.NotNil(t, got1)
+		})
+	}
+}
+
+func TestAddDhcpv4Option82(t *testing.T) {
+	type args struct {
+		svc    *VoltService
+		rID    []byte
+		dhcpv4 *layers.DHCPv4
+	}
+	tests := []struct {
+		name string
+		args args
+	}{
+		{
+			name: "AddDhcpv4Option82",
+			args: args{
+				svc: &VoltService{
+					VoltServiceCfg: VoltServiceCfg{
+						CircuitID:    "test_circuit_id",
+						DataRateAttr: DSLAttrEnabled,
+					},
+				},
+				rID: []byte{1},
+				dhcpv4: &layers.DHCPv4{
+					Options: layers.DHCPOptions{
+						{
+							Type: layers.DHCPOptARPTimeout,
+						},
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			AddDhcpv4Option82(tt.args.svc, tt.args.rID, tt.args.dhcpv4)
+		})
+	}
+}
+
+func TestVoltApplication_ProcessDsDhcpv4Packet(t *testing.T) {
+	pkt := mocks.NewMockPacket(gomock.NewController(t))
+	type args struct {
+		cntx   context.Context
+		device string
+		port   string
+		pkt    gopacket.Packet
+	}
+	tests := []struct {
+		name string
+		args args
+	}{
+		{
+			name: "VoltApplication_ProcessDsDhcpv4Packet",
+			args: args{
+				cntx:   context.Background(),
+				device: test_device,
+				port:   "test_port",
+				pkt:    pkt,
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			va := &VoltApplication{}
+			iPv4 := &layers.IPv4{
+				Version: uint8(1),
+			}
+			uDP := &layers.UDP{
+				Length: uint16(1),
+			}
+			dHCPv4 := &layers.DHCPv4{
+				HardwareLen: uint8(1),
+			}
+			dot1Q_test := &layers.Dot1Q{
+				Priority: uint8(1),
+			}
+			pkt.EXPECT().Layer(layers.LayerTypeEthernet).Return(eth).Times(1)
+			pkt.EXPECT().Layer(layers.LayerTypeIPv4).Return(iPv4).Times(1)
+			pkt.EXPECT().Layer(layers.LayerTypeUDP).Return(uDP).Times(1)
+			pkt.EXPECT().Layer(layers.LayerTypeDHCPv4).Return(dHCPv4).Times(1)
+			pkt.EXPECT().Layer(layers.LayerTypeDot1Q).Return(dot1Q_test).Times(1)
+			pkt.EXPECT().Layers().Return(LayerTypeDot2Q).Times(1)
+			va.ProcessDsDhcpv4Packet(tt.args.cntx, tt.args.device, tt.args.port, tt.args.pkt)
+		})
+	}
+}
+
+func TestDelOption82(t *testing.T) {
+	type args struct {
+		dhcpv4 *layers.DHCPv4
+	}
+	tests := []struct {
+		name string
+		args args
+	}{
+		{
+			name: "DelOption82",
+			args: args{
+				dhcpv4: &layers.DHCPv4{
+					Options: layers.DHCPOptions{
+						{
+							Type: opt82,
+						},
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			DelOption82(tt.args.dhcpv4)
+		})
+	}
+}
+
+func TestDhcpMsgType(t *testing.T) {
+	type args struct {
+		dhcp *layers.DHCPv4
+	}
+	tests := []struct {
+		name string
+		args args
+		want layers.DHCPMsgType
+	}{
+		{
+			name: "DhcpMsgType",
+			args: args{
+				dhcp: &layers.DHCPv4{
+					Options: layers.DHCPOptions{
+						{
+							Type: layers.DHCPOptMessageType,
+							Data: []byte{1},
+						},
+					},
+				},
+			},
+			want: layers.DHCPMsgTypeDiscover,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := DhcpMsgType(tt.args.dhcp); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("DhcpMsgType() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestGetIpv4Addr(t *testing.T) {
+	type args struct {
+		dhcp *layers.DHCPv4
+	}
+	tests := []struct {
+		name  string
+		args  args
+		want  net.IP
+		want1 int64
+	}{
+		{
+			name: "GetIpv4Addr",
+			args: args{
+				dhcp: &layers.DHCPv4{
+					Options: layers.DHCPOptions{
+						{
+							Type: layers.DHCPOptLeaseTime,
+							Data: []byte{1, 2, 3, 4, 5},
+						},
+					},
+				},
+			},
+			want1: int64(16909060),
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, got1 := GetIpv4Addr(tt.args.dhcp)
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("GetIpv4Addr() got = %v, want %v", got, tt.want)
+			}
+			if got1 != tt.want1 {
+				t.Errorf("GetIpv4Addr() got1 = %v, want %v", got1, tt.want1)
+			}
+		})
+	}
+}
+
+func TestGetIpv6Addr(t *testing.T) {
+	type args struct {
+		dhcp6 *layers.DHCPv6
+	}
+	b, err := json.Marshal(layers.DHCPv6OptIAAddr)
+	if err != nil {
+		panic(err)
+	}
+	tests := []struct {
+		name  string
+		args  args
+		want  net.IP
+		want1 uint32
+	}{
+		{
+			name: "GetIpv6Addr_error",
+			args: args{
+				dhcp6: &layers.DHCPv6{
+					MsgType: layers.DHCPv6MsgTypeReply,
+					Options: layers.DHCPv6Options{
+						{
+							Code: layers.DHCPv6OptIANA,
+							Data: b,
+						},
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, got1 := GetIpv6Addr(tt.args.dhcp6)
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("GetIpv6Addr() got = %v, want %v", got, tt.want)
+			}
+			if got1 != tt.want1 {
+				t.Errorf("GetIpv6Addr() got1 = %v, want %v", got1, tt.want1)
+			}
+		})
+	}
+}
+
+func TestVoltApplication_GetMacLearnerInfo(t *testing.T) {
+	type args struct {
+		cntx       context.Context
+		deviceID   string
+		portNumber string
+		vlanID     string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    MacLearnerInfo
+		wantErr bool
+	}{
+		{
+			name: "VoltApplication_GetMacLearnerInfo",
+			args: args{
+				cntx:       context.Background(),
+				deviceID:   test_device,
+				portNumber: "test_port_number",
+				vlanID:     "test_vlanID",
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			va := &VoltApplication{}
+			got, err := va.GetMacLearnerInfo(tt.args.cntx, tt.args.deviceID, tt.args.portNumber, tt.args.vlanID)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("VoltApplication.GetMacLearnerInfo() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("VoltApplication.GetMacLearnerInfo() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}