508 lines
11 KiB
Go
508 lines
11 KiB
Go
package monitoring
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"gopkg.in/yaml.v2"
|
|
|
|
"kubesphere.io/kubesphere/pkg/simple/client/monitoring"
|
|
)
|
|
|
|
func TestGetMaxPointValue(t *testing.T) {
|
|
tests := []struct {
|
|
actualPoints []monitoring.Point
|
|
expectedValue string
|
|
}{
|
|
{
|
|
actualPoints: []monitoring.Point{
|
|
{1.0, 2.0},
|
|
{3.0, 4.0},
|
|
},
|
|
expectedValue: "4.0000000000",
|
|
},
|
|
{
|
|
actualPoints: []monitoring.Point{
|
|
{2, 1},
|
|
{4, 3.1},
|
|
},
|
|
expectedValue: "3.1000000000",
|
|
},
|
|
{
|
|
actualPoints: []monitoring.Point{
|
|
{5, 100},
|
|
{6, 100000.001},
|
|
},
|
|
expectedValue: "100000.0010000000",
|
|
},
|
|
}
|
|
|
|
for i, tt := range tests {
|
|
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
|
max := getMaxPointValue(tt.actualPoints)
|
|
if max != tt.expectedValue {
|
|
t.Fatal("max point value caculation is wrong.")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetMinPointValue(t *testing.T) {
|
|
tests := []struct {
|
|
actualPoints []monitoring.Point
|
|
expectedValue string
|
|
}{
|
|
{
|
|
actualPoints: []monitoring.Point{
|
|
{1.0, 2.0},
|
|
{3.0, 4.0},
|
|
},
|
|
expectedValue: "2.0000000000",
|
|
},
|
|
{
|
|
actualPoints: []monitoring.Point{
|
|
{2, 1},
|
|
{4, 3.1},
|
|
},
|
|
expectedValue: "1.0000000000",
|
|
},
|
|
{
|
|
actualPoints: []monitoring.Point{
|
|
{5, 100},
|
|
{6, 100000.001},
|
|
},
|
|
expectedValue: "100.0000000000",
|
|
},
|
|
}
|
|
|
|
for i, tt := range tests {
|
|
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
|
max := getMinPointValue(tt.actualPoints)
|
|
if max != tt.expectedValue {
|
|
t.Fatal("min point value caculation is wrong.")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetSumPointValue(t *testing.T) {
|
|
tests := []struct {
|
|
actualPoints []monitoring.Point
|
|
expectedValue string
|
|
}{
|
|
{
|
|
actualPoints: []monitoring.Point{
|
|
{1.0, 2.0},
|
|
{3.0, 4.0},
|
|
},
|
|
expectedValue: "6.0000000000",
|
|
},
|
|
{
|
|
actualPoints: []monitoring.Point{
|
|
{2, 1},
|
|
{4, 3.1},
|
|
},
|
|
expectedValue: "4.1000000000",
|
|
},
|
|
{
|
|
actualPoints: []monitoring.Point{
|
|
{5, 100},
|
|
{6, 100000.001},
|
|
},
|
|
expectedValue: "100100.0010000000",
|
|
},
|
|
}
|
|
|
|
for i, tt := range tests {
|
|
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
|
max := getSumPointValue(tt.actualPoints)
|
|
if max != tt.expectedValue {
|
|
t.Fatal("sum point value caculation is wrong.")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetAvgPointValue(t *testing.T) {
|
|
tests := []struct {
|
|
actualPoints []monitoring.Point
|
|
expectedValue string
|
|
}{
|
|
{
|
|
actualPoints: []monitoring.Point{
|
|
{1.0, 2.0},
|
|
{3.0, 4.0},
|
|
},
|
|
expectedValue: "3.0000000000",
|
|
},
|
|
{
|
|
actualPoints: []monitoring.Point{
|
|
{2, 1},
|
|
{4, 3.1},
|
|
},
|
|
expectedValue: "2.0500000000",
|
|
},
|
|
{
|
|
actualPoints: []monitoring.Point{
|
|
{5, 100},
|
|
{6, 100000.001},
|
|
},
|
|
expectedValue: "50050.0005000000",
|
|
},
|
|
}
|
|
|
|
for i, tt := range tests {
|
|
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
|
max := getAvgPointValue(tt.actualPoints)
|
|
if max != tt.expectedValue {
|
|
t.Fatal("avg point value caculattion is wrong.")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func saveTestConfig(t *testing.T, conf *MeterConfig) {
|
|
content, err := yaml.Marshal(conf)
|
|
if err != nil {
|
|
t.Fatalf("error marshal config. %v", err)
|
|
}
|
|
|
|
err = ioutil.WriteFile(meteringConfigName, content, 0640)
|
|
if err != nil {
|
|
t.Fatalf("error write configuration file, %v", err)
|
|
}
|
|
}
|
|
|
|
func testInvalidConfig(t *testing.T) {
|
|
os.Mkdir(meteringConfigName, os.ModeDir)
|
|
defer os.RemoveAll(meteringConfigName)
|
|
_, err := LoadYaml()
|
|
if err == nil {
|
|
t.Error("LoadYaml should fail")
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func cleanTestConfig(t *testing.T) {
|
|
|
|
if _, err := os.Stat(meteringConfigName); os.IsNotExist(err) {
|
|
t.Log("file not exists, skipping")
|
|
return
|
|
}
|
|
|
|
err := os.Remove(meteringConfigName)
|
|
if err != nil {
|
|
t.Fatalf("remove %s file failed", meteringConfigName)
|
|
}
|
|
|
|
}
|
|
|
|
func TestGetCurrencyUnit(t *testing.T) {
|
|
if getCurrencyUnit() != "" {
|
|
t.Fatal("currency unit should be empty")
|
|
}
|
|
|
|
saveTestConfig(t, &MeterConfig{
|
|
Billing: Billing{
|
|
PriceInfo: PriceInfo{
|
|
IngressNetworkTrafficPerMegabytesPerHour: 1,
|
|
EgressNetworkTrafficPerMegabytesPerHour: 2,
|
|
CpuPerCorePerHour: 3,
|
|
MemPerGigabytesPerHour: 4,
|
|
PvcPerGigabytesPerHour: 5,
|
|
CurrencyUnit: "CNY",
|
|
},
|
|
},
|
|
})
|
|
defer cleanTestConfig(t)
|
|
|
|
if getCurrencyUnit() != "CNY" {
|
|
t.Fatal("failed to get currency unit from config")
|
|
}
|
|
}
|
|
|
|
func TestGenerateFloatFormat(t *testing.T) {
|
|
format := generateFloatFormat(10)
|
|
if format != "%.10f" {
|
|
t.Fatalf("get currency float format failed, %s", format)
|
|
}
|
|
}
|
|
|
|
func TestGetResourceUnit(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
meterName string
|
|
expectedValue string
|
|
}{
|
|
{
|
|
meterName: "no-exist",
|
|
expectedValue: "",
|
|
},
|
|
{
|
|
meterName: "meter_cluster_cpu_usage",
|
|
expectedValue: "cores",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
if getResourceUnit(tt.meterName) != tt.expectedValue {
|
|
t.Fatal("get resource unit failed")
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func TestSquashPoints(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
input []monitoring.Point
|
|
factor int
|
|
expected []monitoring.Point
|
|
}{
|
|
{
|
|
input: []monitoring.Point{
|
|
{1, 1},
|
|
{2, 2},
|
|
{3, 3},
|
|
{4, 4},
|
|
{5, 5},
|
|
{6, 6},
|
|
{7, 7},
|
|
{8, 8},
|
|
},
|
|
factor: 1,
|
|
expected: []monitoring.Point{
|
|
{1, 1},
|
|
{2, 2},
|
|
{3, 3},
|
|
{4, 4},
|
|
{5, 5},
|
|
{6, 6},
|
|
{7, 7},
|
|
{8, 8},
|
|
},
|
|
},
|
|
{
|
|
input: []monitoring.Point{
|
|
{1, 1},
|
|
{2, 2},
|
|
{3, 3},
|
|
{4, 4},
|
|
{5, 5},
|
|
{6, 6},
|
|
{7, 7},
|
|
{8, 8},
|
|
},
|
|
factor: 2,
|
|
expected: []monitoring.Point{
|
|
{2, 3},
|
|
{4, 7},
|
|
{6, 11},
|
|
{8, 15},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
got := squashPoints(tt.input, tt.factor)
|
|
if diff := cmp.Diff(got, tt.expected); diff != "" {
|
|
t.Errorf("%T differ (-got, +want): %s", tt.expected, diff)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLoadYaml(t *testing.T) {
|
|
|
|
testInvalidConfig(t)
|
|
|
|
// LoadYaml file not exist
|
|
_, err := LoadYaml()
|
|
if err == nil {
|
|
t.Error("LoadYaml should return error.")
|
|
return
|
|
}
|
|
|
|
saveTestConfig(t, &MeterConfig{
|
|
Billing: Billing{
|
|
PriceInfo: PriceInfo{
|
|
IngressNetworkTrafficPerMegabytesPerHour: 1,
|
|
EgressNetworkTrafficPerMegabytesPerHour: 2,
|
|
CpuPerCorePerHour: 3,
|
|
MemPerGigabytesPerHour: 4,
|
|
PvcPerGigabytesPerHour: 5,
|
|
CurrencyUnit: "CNY",
|
|
},
|
|
},
|
|
})
|
|
|
|
_, err = LoadYaml()
|
|
if err != nil {
|
|
t.Error("LoadYaml failed")
|
|
return
|
|
}
|
|
cleanTestConfig(t)
|
|
}
|
|
|
|
func TestGetFeeWithMeterName(t *testing.T) {
|
|
saveTestConfig(t, &MeterConfig{
|
|
Billing: Billing{
|
|
PriceInfo: PriceInfo{
|
|
IngressNetworkTrafficPerMegabytesPerHour: 1,
|
|
EgressNetworkTrafficPerMegabytesPerHour: 2,
|
|
CpuPerCorePerHour: 3,
|
|
MemPerGigabytesPerHour: 4,
|
|
PvcPerGigabytesPerHour: 5,
|
|
CurrencyUnit: "CNY",
|
|
},
|
|
},
|
|
})
|
|
defer cleanTestConfig(t)
|
|
|
|
if getFeeWithMeterName("meter_cluster_cpu_usage", "1") != "3.000" {
|
|
t.Error("failed to get fee with meter_cluster_cpu_usage")
|
|
return
|
|
}
|
|
if getFeeWithMeterName("meter_cluster_memory_usage", "0") != "0.000" {
|
|
t.Error("failed to get fee with meter_cluster_memory_usage")
|
|
return
|
|
}
|
|
if getFeeWithMeterName("meter_cluster_net_bytes_transmitted", "0") != "0.000" {
|
|
t.Error("failed to get fee with meter_cluster_net_bytes_transmitted")
|
|
return
|
|
}
|
|
if getFeeWithMeterName("meter_cluster_net_bytes_received", "0") != "0.000" {
|
|
t.Error("failed to get fee with meter_cluster_net_bytes_received")
|
|
return
|
|
}
|
|
if getFeeWithMeterName("meter_cluster_pvc_bytes_total", "0") != "0.000" {
|
|
t.Error("failed to get fee with meter_cluster_pvc_bytes_total")
|
|
return
|
|
}
|
|
}
|
|
|
|
func TestGetPriceInfo(t *testing.T) {
|
|
meterConfig := MeterConfig{
|
|
Billing: Billing{
|
|
PriceInfo: PriceInfo{
|
|
CpuPerCorePerHour: 1,
|
|
MemPerGigabytesPerHour: 1,
|
|
IngressNetworkTrafficPerMegabytesPerHour: 1,
|
|
EgressNetworkTrafficPerMegabytesPerHour: 1,
|
|
PvcPerGigabytesPerHour: 1,
|
|
CurrencyUnit: "USD",
|
|
},
|
|
},
|
|
}
|
|
|
|
if meterConfig.GetPriceInfo().CurrencyUnit != meterConfig.Billing.PriceInfo.CurrencyUnit ||
|
|
meterConfig.GetPriceInfo().CpuPerCorePerHour != meterConfig.Billing.PriceInfo.CpuPerCorePerHour ||
|
|
meterConfig.GetPriceInfo().MemPerGigabytesPerHour != meterConfig.Billing.PriceInfo.MemPerGigabytesPerHour ||
|
|
meterConfig.GetPriceInfo().IngressNetworkTrafficPerMegabytesPerHour != meterConfig.Billing.PriceInfo.IngressNetworkTrafficPerMegabytesPerHour ||
|
|
meterConfig.GetPriceInfo().EgressNetworkTrafficPerMegabytesPerHour != meterConfig.Billing.PriceInfo.EgressNetworkTrafficPerMegabytesPerHour ||
|
|
meterConfig.GetPriceInfo().PvcPerGigabytesPerHour != meterConfig.Billing.PriceInfo.PvcPerGigabytesPerHour {
|
|
t.Error("failed to get price info")
|
|
}
|
|
}
|
|
|
|
func TestUpdateMetricStatData(t *testing.T) {
|
|
|
|
saveTestConfig(t, &MeterConfig{
|
|
Billing: Billing{
|
|
PriceInfo: PriceInfo{
|
|
IngressNetworkTrafficPerMegabytesPerHour: 1,
|
|
EgressNetworkTrafficPerMegabytesPerHour: 2,
|
|
CpuPerCorePerHour: 3,
|
|
MemPerGigabytesPerHour: 4,
|
|
PvcPerGigabytesPerHour: 5,
|
|
CurrencyUnit: "CNY",
|
|
},
|
|
},
|
|
})
|
|
defer cleanTestConfig(t)
|
|
|
|
tests := []struct {
|
|
metric monitoring.Metric
|
|
scalingMap map[string]float64
|
|
expected monitoring.MetricData
|
|
}{
|
|
{
|
|
metric: monitoring.Metric{
|
|
MetricName: "test",
|
|
MetricData: monitoring.MetricData{
|
|
MetricType: monitoring.MetricTypeMatrix,
|
|
MetricValues: []monitoring.MetricValue{
|
|
{
|
|
Metadata: map[string]string{},
|
|
Series: []monitoring.Point{
|
|
{1, 1},
|
|
{2, 2},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
scalingMap: map[string]float64{
|
|
"test": 1,
|
|
},
|
|
expected: monitoring.MetricData{
|
|
MetricType: monitoring.MetricTypeMatrix,
|
|
MetricValues: []monitoring.MetricValue{
|
|
{
|
|
Metadata: map[string]string{},
|
|
Series: []monitoring.Point{
|
|
{1, 1},
|
|
{2, 2},
|
|
},
|
|
MinValue: "1.0000000000",
|
|
MaxValue: "2.0000000000",
|
|
AvgValue: "1.5000000000",
|
|
SumValue: "3.0000000000",
|
|
CurrencyUnit: "CNY",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
metric: monitoring.Metric{
|
|
MetricName: "test",
|
|
MetricData: monitoring.MetricData{
|
|
MetricType: monitoring.MetricTypeVector,
|
|
MetricValues: []monitoring.MetricValue{
|
|
{
|
|
Metadata: map[string]string{},
|
|
Sample: &monitoring.Point{1, 2},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
scalingMap: nil,
|
|
expected: monitoring.MetricData{
|
|
MetricType: monitoring.MetricTypeVector,
|
|
MetricValues: []monitoring.MetricValue{
|
|
{
|
|
Metadata: map[string]string{},
|
|
Sample: &monitoring.Point{1, 2},
|
|
MinValue: "2.0000000000",
|
|
MaxValue: "2.0000000000",
|
|
AvgValue: "2.0000000000",
|
|
SumValue: "2.0000000000",
|
|
CurrencyUnit: "CNY",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
got := updateMetricStatData(test.metric, test.scalingMap)
|
|
if diff := cmp.Diff(got, test.expected); diff != "" {
|
|
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
|
|
return
|
|
}
|
|
}
|
|
|
|
}
|