Add unit-test to increase test coverage

This commit is contained in:
Tomofumi Hayashi
2022-06-08 13:49:17 +09:00
parent a77d3cbedb
commit 580b72a5b2
8 changed files with 206 additions and 31 deletions

View File

@@ -198,7 +198,7 @@ func main() {
defer func() { defer func() {
stopChannel <- struct{}{} stopChannel <- struct{}{}
}() }()
if err := configManager.MonitorPluginConfiguration(stopChannel, configWatcherDoneChannel); err != nil { if err := configManager.MonitorPluginConfiguration(configWatcherDoneChannel, stopChannel); err != nil {
_ = logging.Errorf("error watching file: %v", err) _ = logging.Errorf("error watching file: %v", err)
} }
}(make(chan struct{}), configWatcherDoneChannel) }(make(chan struct{}), configWatcherDoneChannel)

View File

@@ -15,9 +15,13 @@
package logging package logging
import ( import (
"fmt"
"io/ioutil"
"os"
"testing"
testutils "gopkg.in/k8snetworkplumbingwg/multus-cni.v3/pkg/testing" testutils "gopkg.in/k8snetworkplumbingwg/multus-cni.v3/pkg/testing"
"gopkg.in/natefinch/lumberjack.v2" "gopkg.in/natefinch/lumberjack.v2"
"testing"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@@ -56,12 +60,16 @@ var _ = Describe("logging operations", func() {
It("Check loglevel setter", func() { It("Check loglevel setter", func() {
SetLogLevel("debug") SetLogLevel("debug")
Expect(loggingLevel).To(Equal(DebugLevel)) Expect(loggingLevel).To(Equal(DebugLevel))
Expect(loggingLevel.String()).To(Equal("debug"))
SetLogLevel("Error") SetLogLevel("Error")
Expect(loggingLevel).To(Equal(ErrorLevel)) Expect(loggingLevel).To(Equal(ErrorLevel))
Expect(loggingLevel.String()).To(Equal("error"))
SetLogLevel("VERbose") SetLogLevel("VERbose")
Expect(loggingLevel).To(Equal(VerboseLevel)) Expect(loggingLevel).To(Equal(VerboseLevel))
Expect(loggingLevel.String()).To(Equal("verbose"))
SetLogLevel("PANIC") SetLogLevel("PANIC")
Expect(loggingLevel).To(Equal(PanicLevel)) Expect(loggingLevel).To(Equal(PanicLevel))
Expect(loggingLevel.String()).To(Equal("panic"))
}) })
It("Check loglevel setter with invalid level", func() { It("Check loglevel setter with invalid level", func() {
@@ -76,6 +84,37 @@ var _ = Describe("logging operations", func() {
Expect(loggingStderr).NotTo(Equal(currentVal)) Expect(loggingStderr).NotTo(Equal(currentVal))
}) })
It("Check log function is worked", func() {
Debugf("foobar")
Verbosef("foobar")
Expect(Errorf("foobar")).NotTo(BeNil())
Panicf("foobar")
})
It("Check log function is worked with stderr", func() {
SetLogStderr(true)
Debugf("foobar")
Verbosef("foobar")
Expect(Errorf("foobar")).NotTo(BeNil())
Panicf("foobar")
})
It("Check log function is worked with stderr", func() {
tmpDir, err := ioutil.TempDir("", "multus_tmp")
SetLogFile(fmt.Sprintf("%s/log.txt", tmpDir))
Debugf("foobar")
Verbosef("foobar")
Expect(Errorf("foobar")).NotTo(BeNil())
Panicf("foobar")
logger.Filename = ""
loggingW = nil
err = os.RemoveAll(tmpDir)
Expect(err).NotTo(HaveOccurred())
// Revert the log variable to init
loggingW = nil
logger = &lumberjack.Logger{}
})
// Tests public getter // Tests public getter
It("Check getter for logging level with current level", func() { It("Check getter for logging level with current level", func() {
currentLevel := loggingLevel currentLevel := loggingLevel

View File

@@ -47,7 +47,7 @@ type Manager struct {
// configuration to `multusAutoconfigDir`. This constructor will auto-discover // configuration to `multusAutoconfigDir`. This constructor will auto-discover
// the primary CNI for which it will delegate. // the primary CNI for which it will delegate.
func NewManager(config MultusConf, multusAutoconfigDir string, forceCNIVersion bool) (*Manager, error) { func NewManager(config MultusConf, multusAutoconfigDir string, forceCNIVersion bool) (*Manager, error) {
defaultCNIPluginName, err := primaryCNIPluginName(multusAutoconfigDir) defaultCNIPluginName, err := getPrimaryCNIPluginName(multusAutoconfigDir)
if err != nil { if err != nil {
_ = logging.Errorf("failed to find the primary CNI plugin: %v", err) _ = logging.Errorf("failed to find the primary CNI plugin: %v", err)
return nil, err return nil, err
@@ -218,7 +218,7 @@ func (m Manager) PersistMultusConfig(config string) error {
return ioutil.WriteFile(m.multusConfigFilePath, []byte(config), UserRWPermission) return ioutil.WriteFile(m.multusConfigFilePath, []byte(config), UserRWPermission)
} }
func primaryCNIPluginName(multusAutoconfigDir string) (string, error) { func getPrimaryCNIPluginName(multusAutoconfigDir string) (string, error) {
masterCniConfigFileName, err := findMasterPlugin(multusAutoconfigDir, 120) masterCniConfigFileName, err := findMasterPlugin(multusAutoconfigDir, 120)
if err != nil { if err != nil {
return "", fmt.Errorf("failed to find the cluster master CNI plugin: %w", err) return "", fmt.Errorf("failed to find the cluster master CNI plugin: %w", err)

View File

@@ -16,9 +16,11 @@
package config package config
import ( import (
"encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"time"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@@ -69,6 +71,62 @@ var _ = Describe("Configuration Manager", func() {
Expect(config).To(Equal(expectedResult)) Expect(config).To(Equal(expectedResult))
}) })
It("Check overrideCNIVersion is worked", func() {
err := overrideCNIVersion(defaultCniConfig, "1.1.1")
Expect(err).NotTo(HaveOccurred())
raw, err := ioutil.ReadFile(defaultCniConfig)
Expect(err).NotTo(HaveOccurred())
var jsonConfig map[string]interface{}
err = json.Unmarshal(raw, &jsonConfig)
Expect(err).NotTo(HaveOccurred())
Expect(jsonConfig["cniVersion"].(string)).To(Equal("1.1.1"))
})
It("Check primaryCNIPlugin can be identified", func() {
fileName, err := getPrimaryCNIPluginName(multusConfigDir)
Expect(err).NotTo(HaveOccurred())
Expect(fileName).To(Equal(primaryCNIPluginName))
})
It("Check MonitorPluginConfiguration", func() {
config, err := configManager.GenerateConfig()
Expect(err).NotTo(HaveOccurred())
err = configManager.PersistMultusConfig(config)
Expect(err).NotTo(HaveOccurred())
configWatcherDoneChannel := make(chan struct{})
go func(stopChannel chan struct{}, doneChannel chan struct{}) {
defer func() {
stopChannel <- struct{}{}
}()
err := configManager.MonitorPluginConfiguration(configWatcherDoneChannel, stopChannel)
Expect(err).NotTo(HaveOccurred())
}(make(chan struct{}), configWatcherDoneChannel)
updatedCNIConfig := `
{
"cniVersion": "0.4.0",
"name": "mycni-name",
"type": "mycni2",
"ipam": {},
"dns": {}
}
`
// update the CNI config to update the master config
Expect(ioutil.WriteFile(defaultCniConfig, []byte(updatedCNIConfig), UserRWPermission)).To(Succeed())
// wait for a while to get fsnotify event
time.Sleep(100 * time.Millisecond)
file, err := ioutil.ReadFile(configManager.multusConfigFilePath)
Expect(err).NotTo(HaveOccurred())
Expect(string(file)).To(Equal(config))
// stop groutine
configWatcherDoneChannel <- struct{}{}
})
When("the user requests the name of the multus configuration to be overridden", func() { When("the user requests the name of the multus configuration to be overridden", func() {
BeforeEach(func() { BeforeEach(func() {
Expect(configManager.OverrideNetworkName()).To(Succeed()) Expect(configManager.OverrideNetworkName()).To(Succeed())

View File

@@ -0,0 +1,58 @@
// Copyright (c) 2021 Multus Authors
//
// 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 server
import (
"context"
"os"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("exec_chroot", func() {
It("Call ChrootExec.ExecPlugin with dummy", func() {
chrootExec := &ChrootExec{
Stderr: os.Stderr,
chrootDir: "/usr",
}
_, err := chrootExec.ExecPlugin(context.Background(), "/bin/true", nil, nil)
Expect(err).ToNot(HaveOccurred())
})
It("Call invalid ChrootExec.ExecPlugin with dummy", func() {
chrootExec := &ChrootExec{
Stderr: os.Stderr,
chrootDir: "/tmp",
}
_, err := chrootExec.ExecPlugin(context.Background(), "/bin/true", nil, nil)
Expect(err).To(HaveOccurred())
})
It("Call ChrootExec.FindInPath with dummy", func() {
chrootExec := &ChrootExec{
Stderr: os.Stderr,
chrootDir: "/usr/bin",
}
_, err := chrootExec.FindInPath("true", []string{"/"})
Expect(err).NotTo(HaveOccurred())
})
})

View File

@@ -0,0 +1,28 @@
// Copyright (c) 2021 Multus Authors
//
// 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 server
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
)
func TestServer(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "server")
}

View File

@@ -72,10 +72,12 @@ func postRequest(args *skel.CmdArgs) (*Response, string, error) {
} }
response := &Response{} response := &Response{}
if len(body) != 0 {
if err = json.Unmarshal(body, response); err != nil { if err = json.Unmarshal(body, response); err != nil {
err = fmt.Errorf("failed to unmarshal response '%s': %v", string(body), err) err = fmt.Errorf("failed to unmarshal response '%s': %v", string(body), err)
return nil, multusShimConfig.CNIVersion, err return nil, multusShimConfig.CNIVersion, err
} }
}
return response, multusShimConfig.CNIVersion, nil return response, multusShimConfig.CNIVersion, nil
} }

View File

@@ -20,7 +20,6 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"testing"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@@ -43,11 +42,6 @@ import (
const suiteName = "Thick CNI architecture" const suiteName = "Thick CNI architecture"
func TestMultusThickCNIArchitecture(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, suiteName)
}
type fakeExec struct{} type fakeExec struct{}
// ExecPlugin executes the plugin // ExecPlugin executes the plugin
@@ -132,16 +126,15 @@ var _ = Describe(suiteName, func() {
context.TODO(), podName, metav1.DeleteOptions{})) context.TODO(), podName, metav1.DeleteOptions{}))
}) })
It("ADD works successfully", func() { It("ADD/CHECK/DEL works successfully", func() {
Expect(os.Setenv("CNI_COMMAND", "ADD")).NotTo(HaveOccurred())
Expect(CmdAdd(cniCmdArgs(containerID, netns.Path(), ifaceName, referenceConfig(thickPluginRunDir)))).To(Succeed()) Expect(CmdAdd(cniCmdArgs(containerID, netns.Path(), ifaceName, referenceConfig(thickPluginRunDir)))).To(Succeed())
})
It("DEL works successfully", func() { Expect(os.Setenv("CNI_COMMAND", "CHECK")).NotTo(HaveOccurred())
Expect(CmdDel(cniCmdArgs(containerID, netns.Path(), ifaceName, referenceConfig(thickPluginRunDir)))).To(Succeed())
})
It("CHECK works successfully", func() {
Expect(CmdCheck(cniCmdArgs(containerID, netns.Path(), ifaceName, referenceConfig(thickPluginRunDir)))).To(Succeed()) Expect(CmdCheck(cniCmdArgs(containerID, netns.Path(), ifaceName, referenceConfig(thickPluginRunDir)))).To(Succeed())
Expect(os.Setenv("CNI_COMMAND", "DEL")).NotTo(HaveOccurred())
Expect(CmdDel(cniCmdArgs(containerID, netns.Path(), ifaceName, referenceConfig(thickPluginRunDir)))).To(Succeed())
}) })
}) })
@@ -186,16 +179,16 @@ var _ = Describe(suiteName, func() {
context.TODO(), podName, metav1.DeleteOptions{})) context.TODO(), podName, metav1.DeleteOptions{}))
}) })
It("ADD works successfully", func() { It("ADD/CHECK/DEL works successfully", func() {
Expect(os.Setenv("CNI_COMMAND", "ADD")).NotTo(HaveOccurred())
Expect(CmdAdd(cniCmdArgs(containerID, netns.Path(), ifaceName, referenceConfig(thickPluginRunDir)))).To(Succeed()) Expect(CmdAdd(cniCmdArgs(containerID, netns.Path(), ifaceName, referenceConfig(thickPluginRunDir)))).To(Succeed())
})
It("DEL works successfully", func() { Expect(os.Setenv("CNI_COMMAND", "CHECK")).NotTo(HaveOccurred())
Expect(CmdDel(cniCmdArgs(containerID, netns.Path(), ifaceName, referenceConfig(thickPluginRunDir)))).To(Succeed())
})
It("CHECK works successfully", func() {
Expect(CmdCheck(cniCmdArgs(containerID, netns.Path(), ifaceName, referenceConfig(thickPluginRunDir)))).To(Succeed()) Expect(CmdCheck(cniCmdArgs(containerID, netns.Path(), ifaceName, referenceConfig(thickPluginRunDir)))).To(Succeed())
Expect(os.Setenv("CNI_COMMAND", "DEL")).NotTo(HaveOccurred())
Expect(CmdDel(cniCmdArgs(containerID, netns.Path(), ifaceName, referenceConfig(thickPluginRunDir)))).To(Succeed())
}) })
}) })
}) })
@@ -219,9 +212,6 @@ func cniCmdArgs(containerID string, netnsPath string, ifName string, stdinData s
func prepareCNIEnv(netnsPath string, namespaceName string, podName string, podUID string) error { func prepareCNIEnv(netnsPath string, namespaceName string, podName string, podUID string) error {
cniArgs := fmt.Sprintf("K8S_POD_NAMESPACE=%s;K8S_POD_NAME=%s;K8S_POD_INFRA_CONTAINER_ID=;K8S_POD_UID=%s", namespaceName, podName, podUID) cniArgs := fmt.Sprintf("K8S_POD_NAMESPACE=%s;K8S_POD_NAME=%s;K8S_POD_INFRA_CONTAINER_ID=;K8S_POD_UID=%s", namespaceName, podName, podUID)
if err := os.Setenv("CNI_COMMAND", "ADD"); err != nil {
return err
}
if err := os.Setenv("CNI_CONTAINERID", "123456789"); err != nil { if err := os.Setenv("CNI_CONTAINERID", "123456789"); err != nil {
return err return err
} }
@@ -290,7 +280,7 @@ func referenceConfig(thickPluginSocketDir string) string {
"defaultnetworkwaitseconds": 3, "defaultnetworkwaitseconds": 3,
"delegates": [{ "delegates": [{
"name": "weave1", "name": "weave1",
"cniVersion": "0.3.1", "cniVersion": "0.4.0",
"type": "weave-net" "type": "weave-net"
}]}` }]}`
return fmt.Sprintf(referenceConfigTemplate, thickPluginSocketDir) return fmt.Sprintf(referenceConfigTemplate, thickPluginSocketDir)