From d083f0e0247fbded92a0ae2a0e71da4176baed95 Mon Sep 17 00:00:00 2001
From: xiadanni <xiadanni1@huawei.com>
Date: Tue, 18 Aug 2020 17:08:23 +0800
Subject: [PATCH 37/50] runtime: add IPVS test

Signed-off-by: xiadanni <xiadanni1@huawei.com>
---
 cli/ipvsadm_test.go                | 775 +++++++++++++++++++++++++++++++++++++
 virtcontainers/api_test.go         |  36 ++
 virtcontainers/kata_agent_test.go  |   4 +
 virtcontainers/pkg/vcmock/types.go |   2 +-
 4 files changed, 816 insertions(+), 1 deletion(-)
 create mode 100644 cli/ipvsadm_test.go

diff --git a/cli/ipvsadm_test.go b/cli/ipvsadm_test.go
new file mode 100644
index 00000000..92958aee
--- /dev/null
+++ b/cli/ipvsadm_test.go
@@ -0,0 +1,775 @@
+// Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+// SPDX-License-Identifier: Apache-2.0
+// Description: IPVS common functions test
+// Author: xiadanni
+// Create: 2020-08-01
+
+package main
+
+import (
+	"context"
+	"flag"
+	"fmt"
+	"os"
+	"strings"
+	"testing"
+
+	"github.com/kata-containers/agent/protocols/grpc"
+	vc "github.com/kata-containers/runtime/virtcontainers"
+	vcAnnotations "github.com/kata-containers/runtime/virtcontainers/pkg/annotations"
+	"github.com/kata-containers/runtime/virtcontainers/pkg/vcmock"
+	"github.com/kata-containers/runtime/virtcontainers/types"
+	"github.com/stretchr/testify/assert"
+	"github.com/urfave/cli"
+)
+
+func TestKataIPVSCliAction(t *testing.T) {
+	assert := assert.New(t)
+
+	actionFunc, ok := kataIPVSCLICommand.Action.(func(ctx *cli.Context) error)
+	assert.True(ok)
+
+	flagSet := flag.NewFlagSet("kata-IPVS", flag.ContinueOnError)
+	ctx := createCLIContext(flagSet)
+
+	err := actionFunc(ctx)
+	assert.NoError(err)
+}
+
+func TestIPVSadmCliAction(t *testing.T) {
+	assert := assert.New(t)
+
+	actionFunc, ok := IPVSadmCommand.Action.(func(ctx *cli.Context) error)
+	assert.True(ok)
+
+	flagSet := flag.NewFlagSet("IPVSadm", flag.ContinueOnError)
+	ctx := createCLIContext(flagSet)
+
+	err := actionFunc(ctx)
+	assert.Error(err, "Missing container ID")
+}
+
+func TestIPVSadmCLISuccessful(t *testing.T) {
+	assert := assert.New(t)
+
+	sandbox := &vcmock.Sandbox{
+		MockID: testContainerID,
+	}
+
+	sandbox.MockContainers = []*vcmock.Container{
+		{
+			MockID:      sandbox.ID(),
+			MockSandbox: sandbox,
+		},
+	}
+
+	testingImpl.StatusContainerFunc = func(ctx context.Context, sandboxID, containerID string) (vc.ContainerStatus, error) {
+		return vc.ContainerStatus{
+			ID: sandbox.ID(),
+			Annotations: map[string]string{
+				vcAnnotations.ContainerTypeKey: string(vc.PodContainer),
+			},
+			State: types.ContainerState{
+				State: types.StateRunning,
+			},
+		}, nil
+	}
+
+	testingImpl.UpdateIPVSRuleFunc = func(ctx context.Context, sandboxID string, IPVS *grpc.UpdateIPVSRequest) (*grpc.IPVSResponse, error) {
+		return &grpc.IPVSResponse{}, nil
+	}
+
+	defer func() {
+		testingImpl.StatusContainerFunc = nil
+		testingImpl.UpdateIPVSRuleFunc = nil
+	}()
+
+	path, err := createTempContainerIDMapping(sandbox.ID(), sandbox.ID())
+	assert.NoError(err)
+	defer os.RemoveAll(path)
+
+	actionFunc, ok := IPVSadmCommand.Action.(func(ctx *cli.Context) error)
+	assert.True(ok)
+
+	flagSet := flag.NewFlagSet("IPVSadm", flag.ContinueOnError)
+	flagSet.Parse([]string{testContainerID})
+	flagSet.String("parameters", "-a -t 192.168.0.7:80 -r 192.168.0.4:80", "")
+	ctx := createCLIContext(flagSet)
+	err = actionFunc(ctx)
+	assert.NoError(err)
+
+	// result not nil
+	testingImpl.UpdateIPVSRuleFunc = func(ctx context.Context, sandboxID string, IPVS *grpc.UpdateIPVSRequest) (*grpc.IPVSResponse, error) {
+		return &grpc.IPVSResponse{IPVSRes: "IPVS rule updating success"}, nil
+	}
+
+	err = actionFunc(ctx)
+	assert.NoError(err)
+}
+
+func TestIPVSadmCLIError(t *testing.T) {
+	assert := assert.New(t)
+
+	sandbox := &vcmock.Sandbox{
+		MockID: testContainerID,
+	}
+
+	sandbox.MockContainers = []*vcmock.Container{
+		{
+			MockID:      sandbox.ID(),
+			MockSandbox: sandbox,
+		},
+	}
+
+	testingImpl.StatusContainerFunc = func(ctx context.Context, sandboxID, containerID string) (vc.ContainerStatus, error) {
+		return vc.ContainerStatus{
+			ID: sandbox.ID(),
+			Annotations: map[string]string{
+				vcAnnotations.ContainerTypeKey: string(vc.PodContainer),
+			},
+			State: types.ContainerState{
+				State: types.StateRunning,
+			},
+		}, nil
+	}
+
+	testingImpl.UpdateIPVSRuleFunc = func(ctx context.Context, sandboxID string, IPVS *grpc.UpdateIPVSRequest) (*grpc.IPVSResponse, error) {
+		return &grpc.IPVSResponse{}, nil
+	}
+
+	defer func() {
+		testingImpl.StatusContainerFunc = nil
+		testingImpl.UpdateIPVSRuleFunc = nil
+	}()
+
+	path, err := createTempContainerIDMapping(sandbox.ID(), sandbox.ID())
+	assert.NoError(err)
+	defer os.RemoveAll(path)
+
+	actionFunc, ok := IPVSadmCommand.Action.(func(ctx *cli.Context) error)
+	assert.True(ok)
+
+	// no stdin rule file
+	flagSet := flag.NewFlagSet("IPVSadm", flag.ContinueOnError)
+	flagSet.Parse([]string{testContainerID})
+	flagSet.String("restore", "-", "")
+	ctx := createCLIContext(flagSet)
+	err = actionFunc(ctx)
+	assert.Error(err)
+
+	// restore parameter error
+	flagSet = flag.NewFlagSet("IPVSadm", flag.ContinueOnError)
+	flagSet.Parse([]string{testContainerID})
+	flagSet.String("restore", "abc", "")
+	ctx = createCLIContext(flagSet)
+	err = actionFunc(ctx)
+	assert.Error(err)
+
+	// checkrule returns error
+	flagSet = flag.NewFlagSet("IPVSadm", flag.ContinueOnError)
+	flagSet.Parse([]string{testContainerID})
+	flagSet.String("parameters", "-A -t 192.168.0.7:80 -s rr -p -3000", "")
+	ctx = createCLIContext(flagSet)
+	err = actionFunc(ctx)
+	assert.Error(err)
+
+	// updatefunction returns error
+	testingImpl.UpdateIPVSRuleFunc = func(ctx context.Context, sandboxID string, IPVS *grpc.UpdateIPVSRequest) (*grpc.IPVSResponse, error) {
+		return &grpc.IPVSResponse{}, fmt.Errorf("IPVSadm test error")
+	}
+
+	flagSet = flag.NewFlagSet("IPVSadm", flag.ContinueOnError)
+	flagSet.Parse([]string{testContainerID})
+	flagSet.String("parameters", "-A -t 192.168.0.7:80 -s rr -p 3000", "")
+	ctx = createCLIContext(flagSet)
+	err = actionFunc(ctx)
+	assert.Error(err)
+}
+
+func TestCleanupCliAction(t *testing.T) {
+	assert := assert.New(t)
+
+	actionFunc, ok := CleanupCommand.Action.(func(ctx *cli.Context) error)
+	assert.True(ok)
+
+	flagSet := flag.NewFlagSet("cleanup", flag.ContinueOnError)
+	ctx := createCLIContext(flagSet)
+
+	err := actionFunc(ctx)
+	assert.Error(err, "Missing container ID")
+}
+
+func TestCleanupCLISuccessful(t *testing.T) {
+	assert := assert.New(t)
+
+	sandbox := &vcmock.Sandbox{
+		MockID: testContainerID,
+	}
+
+	sandbox.MockContainers = []*vcmock.Container{
+		{
+			MockID:      sandbox.ID(),
+			MockSandbox: sandbox,
+		},
+	}
+
+	testingImpl.StatusContainerFunc = func(ctx context.Context, sandboxID, containerID string) (vc.ContainerStatus, error) {
+		return vc.ContainerStatus{
+			ID: sandbox.ID(),
+			Annotations: map[string]string{
+				vcAnnotations.ContainerTypeKey: string(vc.PodContainer),
+			},
+			State: types.ContainerState{
+				State: types.StateRunning,
+			},
+		}, nil
+	}
+
+	testingImpl.UpdateIPVSRuleFunc = func(ctx context.Context, sandboxID string, IPVS *grpc.UpdateIPVSRequest) (*grpc.IPVSResponse, error) {
+		return &grpc.IPVSResponse{}, nil
+	}
+
+	defer func() {
+		testingImpl.StatusContainerFunc = nil
+		testingImpl.UpdateIPVSRuleFunc = nil
+	}()
+
+	path, err := createTempContainerIDMapping(sandbox.ID(), sandbox.ID())
+	assert.NoError(err)
+	defer os.RemoveAll(path)
+
+	actionFunc, ok := CleanupCommand.Action.(func(ctx *cli.Context) error)
+	assert.True(ok)
+
+	flagSet := flag.NewFlagSet("cleanup", flag.ContinueOnError)
+	flagSet.Parse([]string{testContainerID})
+	flagSet.String("parameters", "-d 192.168.0.4 -p tcp", "")
+	ctx := createCLIContext(flagSet)
+	err = actionFunc(ctx)
+	assert.NoError(err)
+}
+
+func TestCleanupCLIError(t *testing.T) {
+	assert := assert.New(t)
+
+	sandbox := &vcmock.Sandbox{
+		MockID: testContainerID,
+	}
+
+	sandbox.MockContainers = []*vcmock.Container{
+		{
+			MockID:      sandbox.ID(),
+			MockSandbox: sandbox,
+		},
+	}
+
+	testingImpl.StatusContainerFunc = func(ctx context.Context, sandboxID, containerID string) (vc.ContainerStatus, error) {
+		return vc.ContainerStatus{
+			ID: sandbox.ID(),
+			Annotations: map[string]string{
+				vcAnnotations.ContainerTypeKey: string(vc.PodContainer),
+			},
+			State: types.ContainerState{
+				State: types.StateRunning,
+			},
+		}, nil
+	}
+
+	testingImpl.UpdateIPVSRuleFunc = func(ctx context.Context, sandboxID string, IPVS *grpc.UpdateIPVSRequest) (*grpc.IPVSResponse, error) {
+		return &grpc.IPVSResponse{}, nil
+	}
+
+	defer func() {
+		testingImpl.StatusContainerFunc = nil
+		testingImpl.UpdateIPVSRuleFunc = nil
+	}()
+
+	path, err := createTempContainerIDMapping(sandbox.ID(), sandbox.ID())
+	assert.NoError(err)
+	defer os.RemoveAll(path)
+
+	actionFunc, ok := CleanupCommand.Action.(func(ctx *cli.Context) error)
+	assert.True(ok)
+
+	// checkrule returns error
+	flagSet := flag.NewFlagSet("cleanup", flag.ContinueOnError)
+	flagSet.Parse([]string{testContainerID})
+	flagSet.String("parameters", "-d 192.168.0.4", "")
+	ctx := createCLIContext(flagSet)
+	err = actionFunc(ctx)
+	assert.Error(err)
+
+	// updatefunction returns error
+	testingImpl.UpdateIPVSRuleFunc = func(ctx context.Context, sandboxID string, IPVS *grpc.UpdateIPVSRequest) (*grpc.IPVSResponse, error) {
+		return &grpc.IPVSResponse{}, fmt.Errorf("IPVSadm cleanup test error")
+	}
+
+	flagSet = flag.NewFlagSet("cleanup", flag.ContinueOnError)
+	flagSet.Parse([]string{testContainerID})
+	flagSet.String("parameters", "-d 192.168.0.4 -p tcp", "")
+	ctx = createCLIContext(flagSet)
+	err = actionFunc(ctx)
+	assert.Error(err)
+}
+
+func TestAddServiceSuccessfully(t *testing.T) {
+	assert := assert.New(t)
+	addServiceCommandTCP := "IPVSadm --add-service --tcp-service 192.168.0.7:80 --scheduler rr --persistent 3000"
+	_, err := checkIPVSRule(addServiceCommandTCP)
+	assert.NoError(err)
+	addServiceCommandUDP := "IPVSadm --add-service --udp-service 192.168.0.7:80 --scheduler rr --persistent 3000"
+	_, err = checkIPVSRule(addServiceCommandUDP)
+	assert.NoError(err)
+	addServiceCmd := "IPVSadm -A -t 192.168.0.7:80 -s rr -p 3000"
+	_, err = checkIPVSRule(addServiceCmd)
+	assert.NoError(err)
+}
+
+func TestAddServiceNoService(t *testing.T) {
+	assert := assert.New(t)
+	addServiceCommand := "IPVSadm --add-service --scheduler rr --persistent 3000"
+	_, err := checkIPVSRule(addServiceCommand)
+	assert.Error(err)
+	addServiceCmd := "IPVSadm -A -s rr -p 3000"
+	_, err = checkIPVSRule(addServiceCmd)
+	assert.Error(err)
+}
+
+func TestAddServiceNoScheduler(t *testing.T) {
+	assert := assert.New(t)
+	addServiceCommand := "IPVSadm --add-service --tcp-service 192.168.0.7:80 --persistent 3000"
+	_, err := checkIPVSRule(addServiceCommand)
+	assert.Error(err)
+	addServiceCmd := "IPVSadm -A -t 192.168.0.7:80 -p 3000"
+	_, err = checkIPVSRule(addServiceCmd)
+	assert.Error(err)
+}
+
+func TestAddServiceNoPersistent(t *testing.T) {
+	assert := assert.New(t)
+	addServiceCommand := "IPVSadm --add-service --tcp-service 192.168.0.7:80 --scheduler rr"
+	_, err := checkIPVSRule(addServiceCommand)
+	assert.Error(err)
+	addServiceCmd := "IPVSadm -A -t 192.168.0.7:80 -s rr"
+	_, err = checkIPVSRule(addServiceCmd)
+	assert.Error(err)
+}
+
+func TestAddServiceIpError(t *testing.T) {
+	assert := assert.New(t)
+	addServiceCommand := "IPVSadm --add-service --tcp-service 192.168.2.2.7:80 --scheduler rr --persistent 3000"
+	_, err := checkIPVSRule(addServiceCommand)
+	assert.Error(err)
+	addServiceCmd := "IPVSadm -A -t 192.168.2.2.7:80 -s rr -p 3000"
+	_, err = checkIPVSRule(addServiceCmd)
+	assert.Error(err)
+}
+
+func TestAddServicePortError(t *testing.T) {
+	assert := assert.New(t)
+	addServiceCommand := "IPVSadm --add-service --tcp-service 192.168.0.7:9999999 --scheduler rr --persistent 3000"
+	_, err := checkIPVSRule(addServiceCommand)
+	assert.Error(err)
+	addServiceCmd := "IPVSadm -A -t 192.168.0.7:9999999 -s rr -p 3000"
+	_, err = checkIPVSRule(addServiceCmd)
+	assert.Error(err)
+}
+
+func TestAddServiceSchedulerError(t *testing.T) {
+	assert := assert.New(t)
+	addServiceCommand := "IPVSadm --add-service --tcp-service 192.168.0.7:80 --scheduler rrr --persistent 3000"
+	_, err := checkIPVSRule(addServiceCommand)
+	assert.Error(err)
+	addServiceCmd := "IPVSadm -A -t 192.168.0.7:80 -s rrr -p 3000"
+	_, err = checkIPVSRule(addServiceCmd)
+	assert.Error(err)
+}
+
+func TestAddServicePersistentError(t *testing.T) {
+	assert := assert.New(t)
+	addServiceCommand := "IPVSadm --add-service --tcp-service 192.168.0.7:80 --scheduler rr --persistent 99999999999"
+	_, err := checkIPVSRule(addServiceCommand)
+	assert.Error(err)
+	addServiceCmd := "IPVSadm -A -t 192.168.0.7:80 -s rr -p 99999999999"
+	_, err = checkIPVSRule(addServiceCmd)
+	assert.Error(err)
+}
+
+func TestEditServiceSuccessfully(t *testing.T) {
+	assert := assert.New(t)
+	editServiceCommandTCP := "IPVSadm --edit-service --tcp-service 192.168.0.7:80 --scheduler rr --persistent 3000"
+	_, err := checkIPVSRule(editServiceCommandTCP)
+	assert.NoError(err)
+	editServiceCommandUcp := "IPVSadm --edit-service --udp-service 192.168.0.7:80 --scheduler rr --persistent 3000"
+	_, err = checkIPVSRule(editServiceCommandUcp)
+	assert.NoError(err)
+	editServiceCmd := "IPVSadm -A -t 192.168.0.7:80 -s rr -p 3000"
+	_, err = checkIPVSRule(editServiceCmd)
+	assert.NoError(err)
+}
+
+func TestEditServiceNoService(t *testing.T) {
+	assert := assert.New(t)
+	editServiceCommand := "IPVSadm --edit-service --scheduler rr --persistent 3000"
+	_, err := checkIPVSRule(editServiceCommand)
+	assert.Error(err)
+	editServiceCmd := "IPVSadm -E -s rr -p 3000"
+	_, err = checkIPVSRule(editServiceCmd)
+	assert.Error(err)
+}
+
+func TestEditServiceNoScheduler(t *testing.T) {
+	assert := assert.New(t)
+	editServiceCommand := "IPVSadm --edit-service --tcp-service 192.168.0.7:80 --persistent 3000"
+	_, err := checkIPVSRule(editServiceCommand)
+	assert.Error(err)
+	editServiceCmd := "IPVSadm -E -t 192.168.0.7:80 -p 3000"
+	_, err = checkIPVSRule(editServiceCmd)
+	assert.Error(err)
+}
+
+func TestEditServiceNoPersistent(t *testing.T) {
+	assert := assert.New(t)
+	editServiceCommand := "IPVSadm --edit-service --tcp-service 192.168.0.7:80 --scheduler rr"
+	_, err := checkIPVSRule(editServiceCommand)
+	assert.Error(err)
+	editServiceCmd := "IPVSadm -E -t 192.168.0.7:80 -s rr"
+	_, err = checkIPVSRule(editServiceCmd)
+	assert.Error(err)
+}
+
+func TestEditServiceIpError(t *testing.T) {
+	assert := assert.New(t)
+	editServiceCommand := "IPVSadm --edit-service --tcp-service 192.168.2.2.7:80 --scheduler rr --persistent 3000"
+	_, err := checkIPVSRule(editServiceCommand)
+	assert.Error(err)
+	editServiceCmd := "IPVSadm -E -t 192.168.2.2.7:80 -s rr -p 3000"
+	_, err = checkIPVSRule(editServiceCmd)
+	assert.Error(err)
+}
+
+func TestEditServicePortError(t *testing.T) {
+	assert := assert.New(t)
+	editServiceCommand := "IPVSadm --edit-service --tcp-service 192.168.0.7:9999999 --scheduler rr --persistent 3000"
+	_, err := checkIPVSRule(editServiceCommand)
+	assert.Error(err)
+	editServiceCmd := "IPVSadm -E -t 192.168.0.7:9999999 -s rr -p 3000"
+	_, err = checkIPVSRule(editServiceCmd)
+	assert.Error(err)
+}
+
+func TestEditServiceSchedulerError(t *testing.T) {
+	assert := assert.New(t)
+	editServiceCommand := "IPVSadm --edit-service --tcp-service 192.168.0.7:80 --scheduler rrr --persistent 3000"
+	_, err := checkIPVSRule(editServiceCommand)
+	assert.Error(err)
+	editServiceCmd := "IPVSadm -E -t 192.168.0.7:80 -s rrr -p 3000"
+	_, err = checkIPVSRule(editServiceCmd)
+	assert.Error(err)
+}
+
+func TestEditServicePersistentError(t *testing.T) {
+	assert := assert.New(t)
+	editServiceCommand := "IPVSadm --edit-service --tcp-service 192.168.0.7:80 --scheduler rr --persistent 99999999999"
+	_, err := checkIPVSRule(editServiceCommand)
+	assert.Error(err)
+	editServiceCmd := "IPVSadm -E -t 192.168.0.7:80 -s rr -p 99999999999"
+	_, err = checkIPVSRule(editServiceCmd)
+	assert.Error(err)
+}
+
+func TestDeleteServiceSuccessfully(t *testing.T) {
+	assert := assert.New(t)
+	deleteServiceCommandTCP := "IPVSadm --delete-service --tcp-service 192.168.0.7:80"
+	_, err := checkIPVSRule(deleteServiceCommandTCP)
+	assert.NoError(err)
+	deleteServiceCommandUDP := "IPVSadm --delete-service --udp-service 192.168.0.7:80"
+	_, err = checkIPVSRule(deleteServiceCommandUDP)
+	assert.NoError(err)
+	deleteServiceCmd := "IPVSadm -D -t 192.168.0.7:80"
+	_, err = checkIPVSRule(deleteServiceCmd)
+	assert.NoError(err)
+}
+
+func TestDeleteServiceNoService(t *testing.T) {
+	assert := assert.New(t)
+	deleteServiceCommand := "IPVSadm --delete-service"
+	_, err := checkIPVSRule(deleteServiceCommand)
+	assert.Error(err)
+	deleteServiceCmd := "IPVSadm -D"
+	_, err = checkIPVSRule(deleteServiceCmd)
+	assert.Error(err)
+}
+
+func TestDeleteServiceIpError(t *testing.T) {
+	assert := assert.New(t)
+	deleteServiceCommand := "IPVSadm --delete-service --tcp-service 192.168.2.2.7:80"
+	_, err := checkIPVSRule(deleteServiceCommand)
+	assert.Error(err)
+	deleteServiceCmd := "IPVSadm -D -t 192.168.2.2.7:80"
+	_, err = checkIPVSRule(deleteServiceCmd)
+	assert.Error(err)
+}
+
+func TestDeleteServicePortError(t *testing.T) {
+	assert := assert.New(t)
+	deleteServiceCommand := "IPVSadm --delete-service --tcp-service 192.168.0.7:9999999"
+	_, err := checkIPVSRule(deleteServiceCommand)
+	assert.Error(err)
+	deleteServiceCmd := "IPVSadm -D -t 192.168.0.7:9999999"
+	_, err = checkIPVSRule(deleteServiceCmd)
+	assert.Error(err)
+}
+
+func TestAddServerSuccessfully(t *testing.T) {
+	assert := assert.New(t)
+	addServerCommandTCP := "IPVSadm --add-server --tcp-service 192.168.0.7:80 --real-server 192.168.0.4:80 --weight 100"
+	_, err := checkIPVSRule(addServerCommandTCP)
+	assert.NoError(err)
+	addServerCommandUDP := "IPVSadm --add-server --udp-service 192.168.0.7:80 --real-server 192.168.0.4:80 --weight 100"
+	_, err = checkIPVSRule(addServerCommandUDP)
+	assert.NoError(err)
+	addServerCmd := "IPVSadm -a -t 192.168.0.7:80 -r 192.168.0.4:80 -w 100"
+	_, err = checkIPVSRule(addServerCmd)
+	assert.NoError(err)
+}
+
+func TestAddServerNoService(t *testing.T) {
+	assert := assert.New(t)
+	addServerCommand := "IPVSadm --add-server --real-server 192.168.0.4:80"
+	_, err := checkIPVSRule(addServerCommand)
+	assert.Error(err)
+	addServerCmd := "IPVSadm -a -r 192.168.0.4:80"
+	_, err = checkIPVSRule(addServerCmd)
+	assert.Error(err)
+}
+
+func TestAddServerNoServer(t *testing.T) {
+	assert := assert.New(t)
+	addServerCommand := "IPVSadm --add-server --tcp-service 192.168.0.7:80"
+	_, err := checkIPVSRule(addServerCommand)
+	assert.Error(err)
+	addServerCmd := "IPVSadm -a -t 192.168.0.7:80"
+	_, err = checkIPVSRule(addServerCmd)
+	assert.Error(err)
+}
+
+func TestAddServerIpError(t *testing.T) {
+	assert := assert.New(t)
+	addServerCommand := "IPVSadm --add-server --tcp-service 192.168.2.0.7:80 --real-server 192.168.0.4:80"
+	_, err := checkIPVSRule(addServerCommand)
+	assert.Error(err)
+	addServerCmd := "IPVSadm -a -t 192.168.2.0.7:80 -r 192.168.0.4:80"
+	_, err = checkIPVSRule(addServerCmd)
+	assert.Error(err)
+}
+
+func TestAddServerPortError(t *testing.T) {
+	assert := assert.New(t)
+	addServerCommand := "IPVSadm --add-server --tcp-service 192.168.0.7:99999 --real-server 192.168.0.4:80"
+	_, err := checkIPVSRule(addServerCommand)
+	assert.Error(err)
+	addServerCmd := "IPVSadm -a -t 192.168.0.7:99999 -r 192.168.0.4:80"
+	_, err = checkIPVSRule(addServerCmd)
+	assert.Error(err)
+}
+
+func TestEditServerSuccessfully(t *testing.T) {
+	assert := assert.New(t)
+	editServerCommandTCP := "IPVSadm --edit-server --tcp-service 192.168.0.7:80 --real-server 192.168.0.4:80 --weight 100"
+	_, err := checkIPVSRule(editServerCommandTCP)
+	assert.NoError(err)
+	editServerCommandUDP := "IPVSadm --edit-server --udp-service 192.168.0.7:80 --real-server 192.168.0.4:80 --weight 100"
+	_, err = checkIPVSRule(editServerCommandUDP)
+	assert.NoError(err)
+	editServerCmd := "IPVSadm -e -t 192.168.0.7:80 -r 192.168.0.4:80 -w 100"
+	_, err = checkIPVSRule(editServerCmd)
+	assert.NoError(err)
+}
+
+func TestEditServerNoService(t *testing.T) {
+	assert := assert.New(t)
+	editServerCommand := "IPVSadm --edit-server --real-server 192.168.0.4:80"
+	_, err := checkIPVSRule(editServerCommand)
+	assert.Error(err)
+	editServerCmd := "IPVSadm -e -r 192.168.0.4:80"
+	_, err = checkIPVSRule(editServerCmd)
+	assert.Error(err)
+}
+
+func TestEditServerNoServer(t *testing.T) {
+	assert := assert.New(t)
+	editServerCommand := "IPVSadm --edit-server --tcp-service 192.168.0.7:80"
+	_, err := checkIPVSRule(editServerCommand)
+	assert.Error(err)
+	editServerCmd := "IPVSadm -e -t 192.168.0.7:80"
+	_, err = checkIPVSRule(editServerCmd)
+	assert.Error(err)
+}
+
+func TestEditServerIpError(t *testing.T) {
+	assert := assert.New(t)
+	editServerCommand := "IPVSadm --edit-server --tcp-service 192.168.2.0.7:80 --real-server 192.168.0.4:80"
+	_, err := checkIPVSRule(editServerCommand)
+	assert.Error(err)
+	editServerCmd := "IPVSadm -e -t 192.168.2.0.7:80 -r 192.168.0.4:80"
+	_, err = checkIPVSRule(editServerCmd)
+	assert.Error(err)
+}
+
+func TestEditServerPortError(t *testing.T) {
+	assert := assert.New(t)
+	editServerCommand := "IPVSadm --edit-server --tcp-service 192.168.0.7:99999 --real-server 192.168.0.4:80"
+	_, err := checkIPVSRule(editServerCommand)
+	assert.Error(err)
+	editServerCmd := "IPVSadm -e -t 192.168.0.7:99999 -r 192.168.0.4:80"
+	_, err = checkIPVSRule(editServerCmd)
+	assert.Error(err)
+}
+
+func TestDeleteServerSuccessfully(t *testing.T) {
+	assert := assert.New(t)
+	deleteServerCommandTCP := "IPVSadm --delete-server --tcp-service 192.168.0.7:80 --real-server 192.168.0.4:80"
+	_, err := checkIPVSRule(deleteServerCommandTCP)
+	assert.NoError(err)
+	deleteServerCommandUDP := "IPVSadm --delete-server --udp-service 192.168.0.7:80 --real-server 192.168.0.4:80"
+	_, err = checkIPVSRule(deleteServerCommandUDP)
+	assert.NoError(err)
+	deleteServerCmd := "IPVSadm -d -t 192.168.0.7:80 -r 192.168.0.4:80"
+	_, err = checkIPVSRule(deleteServerCmd)
+	assert.NoError(err)
+}
+
+func TestDeleteServerNoService(t *testing.T) {
+	assert := assert.New(t)
+	deleteServerCommand := "IPVSadm --delete-server --real-server 192.168.0.4:80"
+	_, err := checkIPVSRule(deleteServerCommand)
+	assert.Error(err)
+	deleteServerCmd := "IPVSadm -d -r 192.168.0.4:80"
+	_, err = checkIPVSRule(deleteServerCmd)
+	assert.Error(err)
+}
+
+func TestDeleteServerNoServer(t *testing.T) {
+	assert := assert.New(t)
+	deleteServerCommand := "IPVSadm --delete-server --tcp-service 192.168.0.7:80"
+	_, err := checkIPVSRule(deleteServerCommand)
+	assert.Error(err)
+	deleteServerCmd := "IPVSadm -d -t 192.168.0.7:80"
+	_, err = checkIPVSRule(deleteServerCmd)
+	assert.Error(err)
+}
+
+func TestDeleteServerIpError(t *testing.T) {
+	assert := assert.New(t)
+	deleteServerCommand := "IPVSadm --delete-server --tcp-service 192.168.2.0.7:80 --real-server 192.168.0.4:80"
+	_, err := checkIPVSRule(deleteServerCommand)
+	assert.Error(err)
+	deleteServerCmd := "IPVSadm -d -t 192.168.2.0.7:80 -r 192.168.0.4:80"
+	_, err = checkIPVSRule(deleteServerCmd)
+	assert.Error(err)
+}
+
+func TestDeleteServerPortError(t *testing.T) {
+	assert := assert.New(t)
+	deleteServerCommand := "IPVSadm --delete-server --tcp-service 192.168.0.7:99999 --real-server 192.168.0.4:80"
+	_, err := checkIPVSRule(deleteServerCommand)
+	assert.Error(err)
+	deleteServerCmd := "IPVSadm -d -t 192.168.0.7:99999 -r 192.168.0.4:80"
+	_, err = checkIPVSRule(deleteServerCmd)
+	assert.Error(err)
+}
+
+func TestListSuccessfully(t *testing.T) {
+	assert := assert.New(t)
+	listCommand := "IPVSadm --list"
+	_, err := checkIPVSRule(listCommand)
+	assert.NoError(err)
+	listCmd := "IPVSadm -L"
+	_, err = checkIPVSRule(listCmd)
+	assert.NoError(err)
+}
+
+func TestSetSuccessfully(t *testing.T) {
+	assert := assert.New(t)
+	setCommand := "IPVSadm --set"
+	_, err := checkIPVSRule(setCommand)
+	assert.NoError(err)
+}
+
+func TestCleanupSuccessfully(t *testing.T) {
+	assert := assert.New(t)
+	cleanupCommand := "conntrack -D --orig-dst 192.168.0.4 --protonum tcp"
+	_, err := checkIPVSRule(cleanupCommand)
+	assert.NoError(err)
+	cleanupCmd := "conntrack -D -d 192.168.0.4 -p tcp"
+	_, err = checkIPVSRule(cleanupCmd)
+	assert.NoError(err)
+}
+
+func TestCleanupNoDestination(t *testing.T) {
+	assert := assert.New(t)
+	cleanupCommand := "conntrack -D --protonum tcp"
+	_, err := checkIPVSRule(cleanupCommand)
+	assert.Error(err)
+	cleanupCmd := "conntrack -D -p tcp"
+	_, err = checkIPVSRule(cleanupCmd)
+	assert.Error(err)
+}
+
+func TestCleanupNoProtocol(t *testing.T) {
+	assert := assert.New(t)
+	cleanupCommand := "conntrack -D --orig-dst 192.168.0.4"
+	_, err := checkIPVSRule(cleanupCommand)
+	assert.Error(err)
+	cleanupCmd := "conntrack -D -d 192.168.0.4"
+	_, err = checkIPVSRule(cleanupCmd)
+	assert.Error(err)
+}
+
+func TestCleanupIpError(t *testing.T) {
+	assert := assert.New(t)
+	cleanupCommand := "conntrack -D --orig-dst 192.168.0.2.4 --protonum tcp"
+	_, err := checkIPVSRule(cleanupCommand)
+	assert.Error(err)
+	cleanupCmd := "conntrack -D -d 192.168.0.2.4 -p tcp"
+	_, err = checkIPVSRule(cleanupCmd)
+	assert.Error(err)
+}
+
+func TestCleanupProtocolError(t *testing.T) {
+	assert := assert.New(t)
+	cleanupCommand := "conntrack -D --orig-dst 192.168.0.4 --protonum ttcp"
+	_, err := checkIPVSRule(cleanupCommand)
+	assert.Error(err)
+	cleanupCmd := "conntrack -D -d 192.168.0.4 -p ttcp"
+	_, err = checkIPVSRule(cleanupCmd)
+	assert.Error(err)
+}
+
+func TestRestoreFileNil(t *testing.T) {
+	assert := assert.New(t)
+	stdin := strings.NewReader("")
+	fileContext, cnt, err := getRestoreFile(stdin)
+	assert.Equal(cnt, 0)
+	assert.Equal(fileContext, "")
+	assert.Error(err)
+}
+
+func TestRestoreFileError(t *testing.T) {
+	assert := assert.New(t)
+	stdin := strings.NewReader("aaa")
+	fileContext, cnt, err := getRestoreFile(stdin)
+	assert.Equal(cnt, 0)
+	assert.Equal(fileContext, "")
+	assert.Error(err)
+}
+
+func TestRestoreFile(t *testing.T) {
+	assert := assert.New(t)
+	stdin := strings.NewReader("-A -t 10.10.11.12:100 -s rr -p 3000\n-a -t 10.10.11.12:100 -r 172.16.0.1:80 -m")
+	fileContext, cnt, err := getRestoreFile(stdin)
+	assert.Equal(cnt, 2)
+	assert.Equal(fileContext, "-A -t 10.10.11.12:100 -s rr -p 3000\n-a -t 10.10.11.12:100 -r 172.16.0.1:80 -m")
+	assert.NoError(err)
+}
diff --git a/virtcontainers/api_test.go b/virtcontainers/api_test.go
index c01d47b8..2a5488f9 100644
--- a/virtcontainers/api_test.go
+++ b/virtcontainers/api_test.go
@@ -15,6 +15,7 @@ import (
 	"syscall"
 	"testing"
 
+	"github.com/kata-containers/agent/protocols/grpc"
 	ktu "github.com/kata-containers/runtime/pkg/katatestutils"
 	"github.com/kata-containers/runtime/virtcontainers/persist"
 	"github.com/kata-containers/runtime/virtcontainers/pkg/annotations"
@@ -1745,3 +1746,38 @@ func TestCleanupContainer(t *testing.T) {
 		t.Fatal(err)
 	}
 }
+
+func TestUpdateIPVSRule(t *testing.T) {
+	defer cleanUp()
+	assert := assert.New(t)
+
+	contID := "abc"
+	ctx := context.Background()
+	var ipvs = &grpc.UpdateIPVSRequest{
+		IPVSReq: "ipvsadm -A -t 192.168.0.7:80 -s rr -p -3000",
+	}
+
+	config := newTestSandboxConfigNoop()
+	p, _, err := createAndStartSandbox(ctx, config)
+	if p == nil || err != nil {
+		t.Fatal(err)
+	}
+
+	s, ok := p.(*Sandbox)
+	assert.True(ok)
+
+	contConfig := newTestContainerConfigNoop(contID)
+	c, err := p.CreateContainer(contConfig)
+	if c == nil || err != nil {
+		t.Fatal(err)
+	}
+
+	_, err = UpdateIPVSRule(ctx, s.id, ipvs)
+	assert.NoError(err)
+
+	_, err = UpdateIPVSRule(ctx, "aaa", ipvs)
+	assert.Error(err)
+
+	_, err = UpdateIPVSRule(ctx, "", ipvs)
+	assert.Error(err)
+}
diff --git a/virtcontainers/kata_agent_test.go b/virtcontainers/kata_agent_test.go
index 18a5a0a6..4f9409a0 100644
--- a/virtcontainers/kata_agent_test.go
+++ b/virtcontainers/kata_agent_test.go
@@ -246,6 +246,10 @@ func (p *gRPCProxy) MemHotplugByProbe(ctx context.Context, req *pb.MemHotplugByP
 	return &gpb.Empty{}, nil
 }
 
+func (p *gRPCProxy) UpdateIPVSRule(ctx context.Context, req *pb.UpdateIPVSRequest) (*pb.IPVSResponse, error) {
+	return &pb.IPVSResponse{}, nil
+}
+
 func gRPCRegister(s *grpc.Server, srv interface{}) {
 	switch g := srv.(type) {
 	case *gRPCProxy:
diff --git a/virtcontainers/pkg/vcmock/types.go b/virtcontainers/pkg/vcmock/types.go
index 43247ef9..610b4602 100644
--- a/virtcontainers/pkg/vcmock/types.go
+++ b/virtcontainers/pkg/vcmock/types.go
@@ -76,5 +76,5 @@ type VCMock struct {
 	UpdateRoutesFunc     func(ctx context.Context, sandboxID string, routes []*vcTypes.Route) ([]*vcTypes.Route, error)
 	ListRoutesFunc       func(ctx context.Context, sandboxID string) ([]*vcTypes.Route, error)
 	CleanupContainerFunc func(ctx context.Context, sandboxID, containerID string, force bool) error
-	UpdateIPVSRuleFunc   func(ctx context.Context, sandboxID string, ipvs *grpc.UpdateIpvsRequest) (*grpc.IpvsResponse, error)
+	UpdateIPVSRuleFunc   func(ctx context.Context, sandboxID string, ipvs *grpc.UpdateIPVSRequest) (*grpc.IPVSResponse, error)
 }
-- 
2.14.3 (Apple Git-98)

