From e7c89f1935d117a2778339cc4774393331002254 Mon Sep 17 00:00:00 2001
From: jingxiaolu <lujingxiao@huawei.com>
Date: Mon, 12 Jun 2023 23:12:37 +0800
Subject: [PATCH 3/7] rubik: test coverage for PSI Manager

Adding test cases for PSI Manager

Signed-off-by: jingxiaolu <lujingxiao@huawei.com>
---
 Makefile                     |   3 +
 pkg/config/config_test.go    |  29 ++++++++
 pkg/services/psi/psi.go      |  14 ++--
 pkg/services/psi/psi_test.go | 126 +++++++++++++++++++++++++++++++++++
 pkg/services/service_test.go |   4 ++
 5 files changed, 169 insertions(+), 7 deletions(-)
 create mode 100644 pkg/services/psi/psi_test.go

diff --git a/Makefile b/Makefile
index 7a92d12..bd66147 100644
--- a/Makefile
+++ b/Makefile
@@ -54,6 +54,7 @@ help:
 	@echo "make test-unit                # run unit test"
 	@echo "make cover                    # generate coverage report"
 	@echo "make install                  # install files to /var/lib/rubik"
+	@echo "make clean"                   # clean built files and test logs
 
 prepare:
 	mkdir -p $(TMP_DIR) $(BUILD_DIR)
@@ -101,3 +102,5 @@ install:
 	cp -f $(BUILD_DIR)/* $(INSTALL_DIR)
 	cp -f $(BUILD_DIR)/rubik.service /lib/systemd/system/
 
+clean:
+	rm -rf build/* cover.* unit_test_log
diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go
index dbbd2e4..03ff4ca 100644
--- a/pkg/config/config_test.go
+++ b/pkg/config/config_test.go
@@ -53,6 +53,35 @@ var rubikConfig string = `
 		"mid": 30,
 		"high": 50
 	  }
+	},
+	"ioCost": [
+	  {
+		"nodeName": "k8s-single",
+		"config": [
+		  {
+			"dev": "sdb",
+			"enable": true,
+			"model": "linear",
+			"param": {
+			  "rbps": 10000000,
+			  "rseqiops": 10000000,
+			  "rrandiops": 10000000,
+			  "wbps": 10000000,
+			  "wseqiops": 10000000,
+			  "wrandiops": 10000000
+			}
+		  }
+		]
+	  }
+	],
+	"psi": {
+		"interval": 10,
+		"resource": [
+		  "cpu",
+		  "memory",
+		  "io"
+		],
+		"avg10Threshold": 5.0
 	}
 }
 `
diff --git a/pkg/services/psi/psi.go b/pkg/services/psi/psi.go
index 1c70255..a55922e 100644
--- a/pkg/services/psi/psi.go
+++ b/pkg/services/psi/psi.go
@@ -37,19 +37,19 @@ const (
 	minThreshold float64 = 5.0
 )
 
-// Factory is the QuotaTurbo factory class
+// Factory is the PSI Manager factory class
 type Factory struct {
 	ObjName string
 }
 
 // Name returns the factory class name
-func (i Factory) Name() string {
-	return "Factory"
+func (f Factory) Name() string {
+	return "PSIFactory"
 }
 
-// NewObj returns a QuotaTurbo object
-func (i Factory) NewObj() (interface{}, error) {
-	return NewManager(i.ObjName), nil
+// NewObj returns a Manager object
+func (f Factory) NewObj() (interface{}, error) {
+	return NewManager(f.ObjName), nil
 }
 
 // Config is PSI service configuration
@@ -130,7 +130,7 @@ func (m *Manager) SetConfig(f helper.ConfigHandler) error {
 }
 
 // IsRunner returns true that tells other Manager is a persistent service
-func (qt *Manager) IsRunner() bool {
+func (m *Manager) IsRunner() bool {
 	return true
 }
 
diff --git a/pkg/services/psi/psi_test.go b/pkg/services/psi/psi_test.go
new file mode 100644
index 0000000..2036aa1
--- /dev/null
+++ b/pkg/services/psi/psi_test.go
@@ -0,0 +1,126 @@
+// Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
+// rubik licensed under the Mulan PSL v2.
+// You can use this software according to the terms and conditions of the Mulan PSL v2.
+// You may obtain a copy of Mulan PSL v2 at:
+//     http://license.coscl.org.cn/MulanPSL2
+// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+// PURPOSE.
+// See the Mulan PSL v2 for more details.
+// Author: Jingxiao Lu
+// Date: 2023-06-12
+// Description: This file is used for testing psi.go
+
+package psi
+
+import (
+	"context"
+	"fmt"
+	"testing"
+	"time"
+
+	"isula.org/rubik/pkg/api"
+	"isula.org/rubik/pkg/core/typedef"
+)
+
+// TestNewManagerObj tests NewObj() for Factory
+func TestNewManagerObj(t *testing.T) {
+	var fact = Factory{
+		ObjName: "psi",
+	}
+	nm, err := fact.NewObj()
+	if err != nil {
+		t.Fatalf("New PSI Manager failed: %v", err)
+		return
+	}
+	fmt.Printf("New PSI Manager %s is %#v", fact.Name(), nm)
+}
+
+// TestConfigValidate tests Config Validate
+func TestConfigValidate(t *testing.T) {
+	var tests = []struct {
+		name    string
+		conf    *Config
+		wantErr bool
+	}{
+		{
+			name:    "TC1 - Default Config",
+			conf:    NewConfig(),
+			wantErr: true,
+		},
+		{
+			name: "TC2 - Wrong Interval value",
+			conf: &Config{
+				Interval: minInterval - 1,
+			},
+			wantErr: true,
+		},
+		{
+			name: "TC3 - Wrong Threshold value",
+			conf: &Config{
+				Interval:       minInterval,
+				Avg10Threshold: minThreshold - 1,
+			},
+			wantErr: true,
+		},
+		{
+			name: "TC4 - No resource type specified",
+			conf: &Config{
+				Interval:       minInterval,
+				Avg10Threshold: minThreshold,
+			},
+			wantErr: true,
+		},
+		{
+			name: "TC5 - Wrong resource type cpuacct - cpuacct is for psi subsystem, not for resource type",
+			conf: &Config{
+				Interval:       minInterval,
+				Avg10Threshold: minThreshold,
+				Resource:       []string{"cpu", "memory", "io", "cpuacct"},
+			},
+			wantErr: true,
+		},
+		{
+			name: "TC6 - Success case - trully end",
+			conf: &Config{
+				Interval:       minInterval,
+				Avg10Threshold: minThreshold,
+				Resource:       []string{"cpu", "memory", "io"},
+			},
+			wantErr: false,
+		},
+	}
+	for _, tc := range tests {
+		t.Run(tc.name, func(t *testing.T) {
+			if err := tc.conf.Validate(); (err != nil) != tc.wantErr {
+				t.Errorf("Config.Validate() error = %v, wantErr %v", err, tc.wantErr)
+			}
+		})
+	}
+}
+
+type FakeManager struct{}
+
+func (m *FakeManager) ListContainersWithOptions(options ...api.ListOption) map[string]*typedef.ContainerInfo {
+	return make(map[string]*typedef.ContainerInfo)
+}
+func (m *FakeManager) ListPodsWithOptions(options ...api.ListOption) map[string]*typedef.PodInfo {
+	return make(map[string]*typedef.PodInfo, 1)
+}
+
+// TestManagerRun creates a fake manager and runs it
+func TestManagerRun(t *testing.T) {
+	nm := NewManager("psi")
+	nm.conf.Interval = 1
+	nm.PreStart(&FakeManager{})
+	nm.SetConfig(func(configName string, d interface{}) error { return nil })
+	if !nm.IsRunner() {
+		t.Fatalf("FakeManager is not a runner!")
+		return
+	}
+
+	ctx, cancel := context.WithCancel(context.Background())
+	go nm.Run(ctx)
+	time.Sleep(time.Second)
+	cancel()
+}
diff --git a/pkg/services/service_test.go b/pkg/services/service_test.go
index a6e0298..537d0b3 100644
--- a/pkg/services/service_test.go
+++ b/pkg/services/service_test.go
@@ -36,6 +36,10 @@ var defaultFeature = []FeatureSpec{
 		Name:    feature.QuotaTurboFeature,
 		Default: true,
 	},
+	{
+		Name:    feature.PSIFeature,
+		Default: true,
+	},
 }
 
 func TestErrorInitServiceComponents(t *testing.T) {
-- 
2.32.1 (Apple Git-133)

