Skip to content

Unit-tests for UCNF Close and Request functions and CircleCI go test job #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
36 changes: 36 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ defaults-machine: &defaults-machine
GOPATH: ~/go
ORG: ciscoappnetworking

# Golang testing environment.
defaults-go-tester: &defaults-go-tester
working_directory: /go/src/github.com/cisco-app-networking/nsm-nse
docker:
- image: cimg/go:1.15
environment:
GOPATH: /home/circleci/go
ORG: ciscoappnetworking


commands:
publish-steps:
parameters:
Expand Down Expand Up @@ -158,6 +168,21 @@ e2e-kind-kiknos-test: &e2e-kind-kiknos-test
- store_artifacts:
path: /tmp/cluster_state

run-all-go-tests: &run-all-go-tests
steps:
- checkout:
path: ~/go/src/github.com/cisco-app-networking/nsm-nse
- run:
name: Run all go unit tests
working_directory: ~/go/src/github.com/cisco-app-networking/nsm-nse/
# runs all the go tests recursively (excluding test/e2e and cmd/vl3-nse directories)
command: |
go test $(go list ./... | grep -v /test/e2e | grep -v cmd/vl3-nse)
#- run:
# name: Run all go unit tests with coverage tests
# working_directory: ~/go/src/github.com/cisco-app-networking/nsm-nse/
# command: |
# go test $(go list ./... | grep -v /test/e2e | grep -v cmd/vl3-nse) -coverprofile .testCoverage.txt

jobs:
build-NSEs:
Expand Down Expand Up @@ -206,6 +231,10 @@ jobs:
- publish-steps:
tag: ${CIRCLE_TAG}

go-test-integration:
<<: *defaults-go-tester
<<: *run-all-go-tests


orbs:
helm: circleci/[email protected]
Expand All @@ -230,6 +259,7 @@ workflows:
only:
- master
- /release.*/
- go-test-integration
test-and-push-tagged:
jobs:
- build-NSEs:
Expand Down Expand Up @@ -264,4 +294,10 @@ workflows:
ignore: /.*/
tags:
only: /^v[0-9]+\.[0-9]+\.[0-9]+-vl3/
- go-test-integration:
filters:
branches:
ignore: /.*/
tags:
only: /^v[0-9]+\.[0-9]+\.[0-9]+-vl3/

1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ require (
github.com/sirupsen/logrus v1.6.0
github.com/stretchr/testify v1.4.0
go.ligato.io/vpp-agent/v3 v3.2.0
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
google.golang.org/grpc v1.29.1
gopkg.in/yaml.v2 v2.3.0
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/gomega v1.1.0/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA=
Expand Down
283 changes: 283 additions & 0 deletions pkg/universal-cnf/config/composite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
package config

import (
"fmt"
"os"
"testing"

"github.com/cisco-app-networking/nsm-nse/pkg/nseconfig"
"github.com/networkservicemesh/networkservicemesh/controlplane/api/connection"
"github.com/networkservicemesh/networkservicemesh/controlplane/api/connectioncontext"
"github.com/networkservicemesh/networkservicemesh/controlplane/api/networkservice"
"github.com/sirupsen/logrus"
"go.ligato.io/vpp-agent/v3/proto/ligato/vpp"
"golang.org/x/net/context"

. "github.com/onsi/gomega"

vpp_interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces"
)

const (
// fields of type nseconfig.Endpoint
ucnfeName string = ""
nseName string = ""
nseControlName string = ""
nseControlAddress string = ""
nseControlAccessToken string = ""
nseControlConnectivityDomain string = ""
vl3Ifname string = ""
ipamDefaultPrefixPool string = ""
ipamServerAddress string = ""
ipamPrefixLength int = 0

// fields of type connection.Connection
connId string = ""
connNetworkService string = "uncf"
machanismCls string = ""
mechanismType string = "MEMIF"
paraDescription string = ""
paraName string = "test"
paraNetnsInode string = ""
paraSocketfile = paraName + "/memif.sock"
srcIP string = "192.168.22.2/30"
dstIP string = "192.168.22.1/30"
srcRequired bool = true
dstRequired bool = true
dstRoutePrefix string = "192.168.0.0/16"
labelsNamespace string = "default"
ucnfPodName string = "helloworld-ucnf-"
labelsPodName = ucnfPodName + "test"
controlPlaneName string = "-control-plane"
clusterName string = "kind-2"
pathSegmentName = clusterName + controlPlaneName
)

var (
// fields of type nseconfig.Endpoint
ucnfeLabels = map[string]string{}
ipamRoute = []string{""}
vl3NameServers = []string{""}
vl3DNSZones = []string{""}
)

// mock implementor
type MockUcnfBackend struct {
newDPConfig func() *vpp.ConfigData
newUniversalCNFBackEnd func() error
processClient func(dpconfig interface{}, ifName string, conn *connection.Connection) error
processDPConfig func(dpconfig interface{}, update bool) error
processEndpoints func(dpconfig interface{}, serviceName, ifName string, conn *connection.Connection) error
}

/*
mock functions returning the defined overriding functions otherwise will return nil by default
*/
func (m *MockUcnfBackend) NewDPConfig() *vpp.ConfigData {
if m.newDPConfig == nil {
return &vpp.ConfigData{}
}
return m.newDPConfig()
}

func (m *MockUcnfBackend) NewUniversalCNFBackend() error {
if m.newUniversalCNFBackEnd == nil {
return nil
}
return m.newUniversalCNFBackEnd()
}

func (m *MockUcnfBackend) ProcessClient(dpconfig interface{}, ifName string, conn *connection.Connection) error {
if m.processClient == nil {
return nil
}
return m.processClient(dpconfig, ifName, conn)
}

func (m *MockUcnfBackend) ProcessEndpoint(dpconfig interface{}, serviceName, ifName string, conn *connection.Connection) error {
if m.processEndpoints == nil {
return nil
}
return m.processEndpoints(dpconfig, serviceName, ifName, conn)
}

func (m *MockUcnfBackend) ProcessDPConfig(dpconfig interface{}, update bool) error {
if m.processDPConfig == nil {
return nil
}
return m.processDPConfig(dpconfig, update)
}

func createNseConfigEndpoint() (e *nseconfig.Endpoint) {
e = &nseconfig.Endpoint{
Name: ucnfeName,
Labels: ucnfeLabels,
NseName: nseName,
NseControl: &nseconfig.NseControl{
Name: nseControlName,
Address: nseControlAddress,
AccessToken: nseControlAccessToken,
ConnectivityDomain: nseControlConnectivityDomain,
},
VL3: nseconfig.VL3{
IPAM: nseconfig.IPAM{
DefaultPrefixPool: ipamDefaultPrefixPool,
PrefixLength: ipamPrefixLength,
Routes: ipamRoute,
ServerAddress: ipamServerAddress,
},
Ifname: vl3Ifname,
NameServers: vl3NameServers,
DNSZones: vl3DNSZones,
},
}
return
}

func createNsmConnection() (conn *connection.Connection) {
conn = &connection.Connection{
Id: connId,
NetworkService: connNetworkService,
Mechanism: &connection.Mechanism{
Cls: machanismCls,
Type: mechanismType,
Parameters: map[string]string{
"description": paraDescription,
"name": paraName,
"netnsInode": paraNetnsInode,
"socketfile": paraSocketfile,
},
},
Context: &connectioncontext.ConnectionContext{
IpContext: &connectioncontext.IPContext{
SrcIpAddr: srcIP,
DstIpAddr: dstIP,
SrcIpRequired: srcRequired,
DstIpRequired: dstRequired,
DstRoutes: []*connectioncontext.Route{
{Prefix: dstRoutePrefix},
},
},
},
Labels: map[string]string{
"namespace": labelsNamespace,
"podName": labelsPodName,
},
Path: &connection.Path{
PathSegments: []*connection.PathSegment{
{Name: pathSegmentName},
},
},
}
return
}

/*
assigning an empty interface to dpConfig to prevent crashing, it cannot be a null pointer
*/
func createVppDpConfig() (dpConfig *vpp.ConfigData) {
dpConfig = &vpp.ConfigData{
Interfaces: []*vpp_interfaces.Interface{},
}
return
}

func initUcnfEndpoint() (ucnfe UniversalCNFEndpoint) {
ucnfe = UniversalCNFEndpoint{
endpoint: createNseConfigEndpoint(),
backend: &MockUcnfBackend{},
dpConfig: createVppDpConfig(),
}
return
}

func TestMain(m *testing.M) {
runTests := m.Run()
os.Exit(runTests)
}

/*
description is the log describing what the test do
positiveTest is a flag to determine whether positive or negative tests
*/
type ucnfBackendTest struct {
mockBackend *MockUcnfBackend
description string
positiveTest bool
}

/*
run either positive or negative tests depending on the flag
*/
func runTest(g *GomegaWithT, err error, flag bool){
if !flag{
g.Expect(err).Should(HaveOccurred(), fmt.Sprintf("ERROR : %v", err))
} else {
g.Expect(err).ShouldNot(HaveOccurred(), fmt.Sprintf("ERROR : %v", err))
}
}

/*
this test ensures that the Request function can get return values fromProcessEndpoint function and ProcessDPConfig function
*/
func TestRequest(t *testing.T) {
g := NewWithT(t)
ctx := context.TODO()
r := &networkservice.NetworkServiceRequest{}
ucnfe := initUcnfEndpoint()

tables := []ucnfBackendTest{
{mockBackend: &MockUcnfBackend{processDPConfig: func(dpconfig interface{}, update bool) error {
return nil
},
}, description: "method ProcessDPConfig() should return nil", positiveTest: true},
{mockBackend: &MockUcnfBackend{processEndpoints: func(dpconfig interface{}, serviceName, ifName string, conn *connection.Connection) error {
return nil
},
}, description: "method ProcessEndpoints() should return nil", positiveTest: true},
{mockBackend: &MockUcnfBackend{processDPConfig: func(dpconfig interface{}, update bool) error {
return fmt.Errorf("failed to run ProcessDPConfig() method")
},
}, description: "method ProcessDPConfig() should return err", positiveTest: false},
{mockBackend: &MockUcnfBackend{processEndpoints: func(dpconfig interface{}, serviceName, ifName string, conn *connection.Connection) error {
return fmt.Errorf("failed to run ProcessEndpoint() method")
},
}, description: "method ProcessEndpoints() should return err", positiveTest: false},
}

for _, table := range tables {
ucnfe.backend = table.mockBackend
logrus.Printf(table.description)
_, err := ucnfe.Request(ctx, r)
runTest(g, err, table.positiveTest)
}
}

/*
this test ensures that the Close function can get return values of ProcessDPConfig function
*/
func TestClose(t *testing.T) {
g := NewWithT(t)
ctx := context.TODO()
ucnfe := initUcnfEndpoint()
conn := createNsmConnection()

tables := []ucnfBackendTest{
{mockBackend: &MockUcnfBackend{processDPConfig: func(dpconfig interface{}, update bool) error {
return nil
},
}, description: "method ProcessDPConfig() should return nil", positiveTest: true},
{mockBackend: &MockUcnfBackend{processDPConfig: func(dpconfig interface{}, update bool) error {
return fmt.Errorf("failed to run ProcessDPConfig() method")
},
}, description: "method ProcessDPConfig() should return err", positiveTest: false},
}

for _, table := range tables {
ucnfe.backend = table.mockBackend
logrus.Printf(table.description)
_, err := ucnfe.Close(ctx, conn)
runTest(g, err, table.positiveTest)
}
}