From 0d9451b4bf3212e4522ad567eefcbf719b55ec18 Mon Sep 17 00:00:00 2001 From: Song Gao <2695690803@qq.com> Date: Thu, 2 Apr 2020 17:30:21 +0800 Subject: [PATCH 1/8] add ut --- .../autoscaler/calculate/calculate_test.go | 48 ++++ .../autoscaler/calculate/cpu_test.go | 64 +++++ pkg/autoscaler/autoscaler/util_test.go | 224 +++++++++++++++++- 3 files changed, 329 insertions(+), 7 deletions(-) create mode 100644 pkg/autoscaler/autoscaler/calculate/calculate_test.go create mode 100644 pkg/autoscaler/autoscaler/calculate/cpu_test.go diff --git a/pkg/autoscaler/autoscaler/calculate/calculate_test.go b/pkg/autoscaler/autoscaler/calculate/calculate_test.go new file mode 100644 index 0000000000..cad5455cbf --- /dev/null +++ b/pkg/autoscaler/autoscaler/calculate/calculate_test.go @@ -0,0 +1,48 @@ +// Copyright 2020 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package calculate + +import ( + . "github.com/onsi/gomega" + "testing" +) + +func TestCalculate(t *testing.T) { + g := NewGomegaWithT(t) + currentValue, targetValue := 20.0, 30.0 + currentReplicas := int32(4) + r, err := calculate(currentValue, targetValue, currentReplicas) + g.Expect(err).Should(BeNil()) + g.Expect(r).Should(Equal(int32(3))) + + currentValue, targetValue = 30.0, 30.0 + currentReplicas = int32(4) + r, err = calculate(currentValue, targetValue, currentReplicas) + g.Expect(err).Should(BeNil()) + g.Expect(r).Should(Equal(int32(4))) + + currentValue, targetValue = 35.0, 30.0 + currentReplicas = int32(4) + r, err = calculate(currentValue, targetValue, currentReplicas) + g.Expect(err).Should(BeNil()) + g.Expect(r).Should(Equal(int32(5))) + + currentValue, targetValue = 0.0, 0.0 + currentReplicas = int32(4) + r, err = calculate(currentValue, targetValue, currentReplicas) + g.Expect(err).ShouldNot(BeNil()) + g.Expect(err.Error()).Should(Equal("targetValue in calculate func can't be zero")) + g.Expect(r).Should(Equal(int32(-1))) + +} diff --git a/pkg/autoscaler/autoscaler/calculate/cpu_test.go b/pkg/autoscaler/autoscaler/calculate/cpu_test.go new file mode 100644 index 0000000000..ed80806d37 --- /dev/null +++ b/pkg/autoscaler/autoscaler/calculate/cpu_test.go @@ -0,0 +1,64 @@ +// Copyright 2020 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package calculate + +import ( + "fmt" + "testing" + + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" +) + +func TestExtractCpuRequestsRatio(t *testing.T) { + g := NewGomegaWithT(t) + c := newContainer() + r, err := extractCpuRequestsRatio(c) + g.Expect(err).Should(BeNil()) + g.Expect(almostEqual(r, 1.0)).Should(Equal(true)) + + c.Resources.Requests = map[corev1.ResourceName]resource.Quantity{ + corev1.ResourceCPU: resource.MustParse("1000m"), + } + r, err = extractCpuRequestsRatio(c) + g.Expect(err).Should(BeNil()) + g.Expect(almostEqual(r, 1.0)).Should(Equal(true)) + + c.Resources.Requests = map[corev1.ResourceName]resource.Quantity{ + corev1.ResourceCPU: resource.MustParse("1500m"), + } + r, err = extractCpuRequestsRatio(c) + g.Expect(err).Should(BeNil()) + g.Expect(almostEqual(r, 1.5)).Should(Equal(true)) + + c.Resources.Requests = map[corev1.ResourceName]resource.Quantity{} + r, err = extractCpuRequestsRatio(c) + g.Expect(err).ShouldNot(BeNil()) + g.Expect(err.Error()).Should(Equal(fmt.Sprintf("container[%s] cpu requests is empty", c.Name))) + g.Expect(almostEqual(r, 0)).Should(Equal(true)) + +} + +func newContainer() *corev1.Container { + return &corev1.Container{ + Name: "container", + Image: "fake:fake", + Resources: corev1.ResourceRequirements{ + Requests: map[corev1.ResourceName]resource.Quantity{ + corev1.ResourceCPU: resource.MustParse("1"), + }, + }, + } +} diff --git a/pkg/autoscaler/autoscaler/util_test.go b/pkg/autoscaler/autoscaler/util_test.go index f77b8773de..3e768c3f2d 100644 --- a/pkg/autoscaler/autoscaler/util_test.go +++ b/pkg/autoscaler/autoscaler/util_test.go @@ -14,27 +14,237 @@ package autoscaler import ( + "fmt" + "testing" + "time" + + . "github.com/onsi/gomega" "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/label" + appsv1 "k8s.io/api/apps/v1" + autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2" "k8s.io/utils/pointer" ) +func TestCheckStsAutoScalingInterval(t *testing.T) { + g := NewGomegaWithT(t) + tac := newTidbClusterAutoScaler() + intervalSec := int32(100) + r, err := checkStsAutoScalingInterval(tac, intervalSec, v1alpha1.TiKVMemberType) + g.Expect(r).Should(Equal(true)) + g.Expect(err).Should(BeNil()) + + r, err = checkStsAutoScalingInterval(tac, intervalSec, v1alpha1.TiDBMemberType) + g.Expect(r).Should(Equal(true)) + g.Expect(err).Should(BeNil()) + + tac.Annotations = map[string]string{} + tac.Annotations[label.AnnTiDBLastAutoScalingTimestamp] = fmt.Sprintf("%d", time.Now().Truncate(60*time.Second).Unix()) + tac.Annotations[label.AnnTiKVLastAutoScalingTimestamp] = fmt.Sprintf("%d", time.Now().Truncate(60*time.Second).Unix()) + r, err = checkStsAutoScalingInterval(tac, intervalSec, v1alpha1.TiDBMemberType) + g.Expect(r).Should(Equal(false)) + g.Expect(err).Should(BeNil()) + r, err = checkStsAutoScalingInterval(tac, intervalSec, v1alpha1.TiKVMemberType) + g.Expect(r).Should(Equal(false)) + g.Expect(err).Should(BeNil()) + + tac.Annotations = map[string]string{} + tac.Annotations[label.AnnTiDBLastAutoScalingTimestamp] = fmt.Sprintf("%d", time.Now().Truncate(120*time.Second).Unix()) + tac.Annotations[label.AnnTiKVLastAutoScalingTimestamp] = fmt.Sprintf("%d", time.Now().Truncate(120*time.Second).Unix()) + r, err = checkStsAutoScalingInterval(tac, intervalSec, v1alpha1.TiDBMemberType) + g.Expect(r).Should(Equal(false)) + g.Expect(err).Should(BeNil()) + r, err = checkStsAutoScalingInterval(tac, intervalSec, v1alpha1.TiKVMemberType) + g.Expect(r).Should(Equal(false)) + g.Expect(err).Should(BeNil()) +} + +func TestCheckStsAutoScalingPrerequisites(t *testing.T) { + g := NewGomegaWithT(t) + sts := newSts() + + r := checkStsAutoScalingPrerequisites(sts) + g.Expect(r).Should(Equal(false)) + + sts.Status.UpdateRevision = "1" + sts.Status.CurrentRevision = "1" + sts.Spec.Replicas = pointer.Int32Ptr(1) + sts.Status.Replicas = 1 + r = checkStsAutoScalingPrerequisites(sts) + g.Expect(r).Should(Equal(true)) + + sts.Status.UpdateRevision = "1" + sts.Status.CurrentRevision = "2" + sts.Spec.Replicas = pointer.Int32Ptr(1) + sts.Status.Replicas = 1 + r = checkStsAutoScalingPrerequisites(sts) + g.Expect(r).Should(Equal(false)) + + sts.Status.UpdateRevision = "1" + sts.Status.CurrentRevision = "1" + sts.Spec.Replicas = pointer.Int32Ptr(1) + sts.Status.Replicas = 2 + r = checkStsAutoScalingPrerequisites(sts) + g.Expect(r).Should(Equal(false)) +} + +func TestLimitTargetReplicas(t *testing.T) { + g := NewGomegaWithT(t) + tac := newTidbClusterAutoScaler() + tac.Spec.TiDB.MinReplicas = pointer.Int32Ptr(2) + tac.Spec.TiDB.MaxReplicas = 4 + + tac.Spec.TiKV.MinReplicas = pointer.Int32Ptr(2) + tac.Spec.TiKV.MaxReplicas = 4 + + targetReplicas := int32(1) + r := limitTargetReplicas(targetReplicas, tac, v1alpha1.TiDBMemberType) + g.Expect(r).Should(Equal(int32(2))) + r = limitTargetReplicas(targetReplicas, tac, v1alpha1.TiKVMemberType) + g.Expect(r).Should(Equal(int32(2))) + + targetReplicas = int32(2) + r = limitTargetReplicas(targetReplicas, tac, v1alpha1.TiDBMemberType) + g.Expect(r).Should(Equal(int32(2))) + r = limitTargetReplicas(targetReplicas, tac, v1alpha1.TiKVMemberType) + g.Expect(r).Should(Equal(int32(2))) + + targetReplicas = int32(3) + r = limitTargetReplicas(targetReplicas, tac, v1alpha1.TiDBMemberType) + g.Expect(r).Should(Equal(int32(3))) + r = limitTargetReplicas(targetReplicas, tac, v1alpha1.TiKVMemberType) + g.Expect(r).Should(Equal(int32(3))) + + targetReplicas = int32(4) + r = limitTargetReplicas(targetReplicas, tac, v1alpha1.TiDBMemberType) + g.Expect(r).Should(Equal(int32(4))) + r = limitTargetReplicas(targetReplicas, tac, v1alpha1.TiKVMemberType) + g.Expect(r).Should(Equal(int32(4))) + + targetReplicas = int32(5) + r = limitTargetReplicas(targetReplicas, tac, v1alpha1.TiDBMemberType) + g.Expect(r).Should(Equal(int32(4))) + r = limitTargetReplicas(targetReplicas, tac, v1alpha1.TiKVMemberType) + g.Expect(r).Should(Equal(int32(4))) +} + +func TestDefaultTac(t *testing.T) { + g := NewGomegaWithT(t) + tac := newTidbClusterAutoScaler() + tac.Spec.TiDB = nil + tac.Spec.TiKV.MinReplicas = nil + tac.Spec.TiKV.Metrics = []autoscalingv2beta2.MetricSpec{} + tac.Spec.TiKV.MetricsTimeDuration = nil + tac.Spec.TiKV.ScaleOutIntervalSeconds = nil + tac.Spec.TiKV.ScaleInIntervalSeconds = nil + defaultTAC(tac) + g.Expect(*tac.Spec.TiKV.MinReplicas).Should(Equal(int32(1))) + g.Expect(len(tac.Spec.TiKV.Metrics)).Should(Equal(1)) + g.Expect(*tac.Spec.TiKV.MetricsTimeDuration).Should(Equal("3m")) + g.Expect(*tac.Spec.TiKV.ScaleOutIntervalSeconds).Should(Equal(int32(300))) + g.Expect(*tac.Spec.TiKV.ScaleInIntervalSeconds).Should(Equal(int32(500))) + + tac = newTidbClusterAutoScaler() + tac.Spec.TiKV = nil + tac.Spec.TiDB.MinReplicas = nil + tac.Spec.TiDB.Metrics = []autoscalingv2beta2.MetricSpec{} + tac.Spec.TiDB.MetricsTimeDuration = nil + tac.Spec.TiDB.ScaleOutIntervalSeconds = nil + tac.Spec.TiDB.ScaleInIntervalSeconds = nil + defaultTAC(tac) + g.Expect(*tac.Spec.TiDB.MinReplicas).Should(Equal(int32(1))) + g.Expect(len(tac.Spec.TiDB.Metrics)).Should(Equal(1)) + g.Expect(*tac.Spec.TiDB.MetricsTimeDuration).Should(Equal("3m")) + g.Expect(*tac.Spec.TiDB.ScaleOutIntervalSeconds).Should(Equal(int32(300))) + g.Expect(*tac.Spec.TiDB.ScaleInIntervalSeconds).Should(Equal(int32(500))) + +} + +func TestCheckAndUpdateTacAnn(t *testing.T) { + g := NewGomegaWithT(t) + tac := newTidbClusterAutoScaler() + + tac.Annotations = nil + checkAndUpdateTacAnn(tac) + g.Expect(tac.Annotations).ShouldNot(BeNil()) + g.Expect(len(tac.Annotations)).Should(Equal(2)) + v, ok := tac.Annotations[label.AnnAutoScalingTargetNamespace] + g.Expect(ok).Should(Equal(ok)) + g.Expect(v).Should(Equal("default")) + v, ok = tac.Annotations[label.AnnAutoScalingTargetName] + g.Expect(ok).Should(Equal(ok)) + g.Expect(v).Should(Equal("tc")) + + tac.Spec.Cluster = v1alpha1.TidbClusterRef{ + Name: "foo", + Namespace: "bar", + } + checkAndUpdateTacAnn(tac) + g.Expect(tac.Annotations).ShouldNot(BeNil()) + g.Expect(len(tac.Annotations)).Should(Equal(2)) + v, ok = tac.Annotations[label.AnnAutoScalingTargetNamespace] + g.Expect(ok).Should(Equal(ok)) + g.Expect(v).Should(Equal("bar")) + v, ok = tac.Annotations[label.AnnAutoScalingTargetName] + g.Expect(ok).Should(Equal(ok)) + g.Expect(v).Should(Equal("foo")) +} + +func TestGenMetricsEndpoint(t *testing.T) { + g := NewGomegaWithT(t) + tac := newTidbClusterAutoScaler() + tac.Spec.Monitor = nil + r, err := genMetricsEndpoint(tac) + g.Expect(err).ShouldNot(BeNil()) + g.Expect(err.Error()).Should(Equal(fmt.Sprintf("tac[%s/%s] metrics url or monitor should be defined explicitly", tac.Namespace, tac.Name))) + g.Expect(r).Should(Equal("")) + + tac.Spec.Monitor = &v1alpha1.TidbMonitorRef{ + Name: "monitor", + Namespace: "default", + } + r, err = genMetricsEndpoint(tac) + g.Expect(err).Should(BeNil()) + g.Expect(r).Should(Equal(fmt.Sprintf("http://%s-prometheus.%s.svc:9090", tac.Spec.Monitor.Name, tac.Spec.Monitor.Namespace))) + + u := "metrics-url" + tac.Spec.MetricsUrl = &u + r, err = genMetricsEndpoint(tac) + g.Expect(err).Should(BeNil()) + g.Expect(r).Should(Equal(u)) +} + func newTidbClusterAutoScaler() *v1alpha1.TidbClusterAutoScaler { tac := &v1alpha1.TidbClusterAutoScaler{} + tac.Name = "tac" + tac.Namespace = "default" tac.Annotations = map[string]string{} + tac.Spec.Cluster = v1alpha1.TidbClusterRef{ + Name: "tc", + Namespace: "default", + } + tac.Spec.Monitor = &v1alpha1.TidbMonitorRef{ + Namespace: "monitor", + Name: "default", + } tac.Spec.TiKV = &v1alpha1.TikvAutoScalerSpec{} tac.Spec.TiDB = &v1alpha1.TidbAutoScalerSpec{} tac.Spec.TiKV.ScaleOutThreshold = pointer.Int32Ptr(2) tac.Spec.TiKV.ScaleInThreshold = pointer.Int32Ptr(2) tac.Spec.TiDB.ScaleOutThreshold = pointer.Int32Ptr(2) tac.Spec.TiDB.ScaleInThreshold = pointer.Int32Ptr(2) - defaultTAC(tac) return tac } -func newTidbCluster() *v1alpha1.TidbCluster { - tc := &v1alpha1.TidbCluster{} - tc.Annotations = map[string]string{} - tc.Name = "tc" - tc.Namespace = "ns" - return tc +func newSts() *appsv1.StatefulSet { + return &appsv1.StatefulSet{ + Spec: appsv1.StatefulSetSpec{ + Replicas: pointer.Int32Ptr(1), + }, + Status: appsv1.StatefulSetStatus{ + CurrentRevision: "1", + UpdateRevision: "2", + Replicas: 2, + }, + } } From d31547876278541f0572f9c5663d2ef78d74b1ab Mon Sep 17 00:00:00 2001 From: Song Gao <2695690803@qq.com> Date: Thu, 2 Apr 2020 17:44:45 +0800 Subject: [PATCH 2/8] fix --- pkg/autoscaler/autoscaler/util_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/autoscaler/autoscaler/util_test.go b/pkg/autoscaler/autoscaler/util_test.go index 3e768c3f2d..0d9deb01bb 100644 --- a/pkg/autoscaler/autoscaler/util_test.go +++ b/pkg/autoscaler/autoscaler/util_test.go @@ -52,10 +52,10 @@ func TestCheckStsAutoScalingInterval(t *testing.T) { tac.Annotations[label.AnnTiDBLastAutoScalingTimestamp] = fmt.Sprintf("%d", time.Now().Truncate(120*time.Second).Unix()) tac.Annotations[label.AnnTiKVLastAutoScalingTimestamp] = fmt.Sprintf("%d", time.Now().Truncate(120*time.Second).Unix()) r, err = checkStsAutoScalingInterval(tac, intervalSec, v1alpha1.TiDBMemberType) - g.Expect(r).Should(Equal(false)) + g.Expect(r).Should(Equal(true)) g.Expect(err).Should(BeNil()) r, err = checkStsAutoScalingInterval(tac, intervalSec, v1alpha1.TiKVMemberType) - g.Expect(r).Should(Equal(false)) + g.Expect(r).Should(Equal(true)) g.Expect(err).Should(BeNil()) } From 8e58cd01ac4568a9d2f42fca4f8d90e221225b62 Mon Sep 17 00:00:00 2001 From: Song Gao <2695690803@qq.com> Date: Thu, 2 Apr 2020 19:06:36 +0800 Subject: [PATCH 3/8] fix test --- pkg/autoscaler/autoscaler/util_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/autoscaler/autoscaler/util_test.go b/pkg/autoscaler/autoscaler/util_test.go index 0d9deb01bb..af838c3ba3 100644 --- a/pkg/autoscaler/autoscaler/util_test.go +++ b/pkg/autoscaler/autoscaler/util_test.go @@ -49,8 +49,8 @@ func TestCheckStsAutoScalingInterval(t *testing.T) { g.Expect(err).Should(BeNil()) tac.Annotations = map[string]string{} - tac.Annotations[label.AnnTiDBLastAutoScalingTimestamp] = fmt.Sprintf("%d", time.Now().Truncate(120*time.Second).Unix()) - tac.Annotations[label.AnnTiKVLastAutoScalingTimestamp] = fmt.Sprintf("%d", time.Now().Truncate(120*time.Second).Unix()) + tac.Annotations[label.AnnTiDBLastAutoScalingTimestamp] = fmt.Sprintf("%d", time.Now().Truncate(200*time.Second).Unix()) + tac.Annotations[label.AnnTiKVLastAutoScalingTimestamp] = fmt.Sprintf("%d", time.Now().Truncate(200*time.Second).Unix()) r, err = checkStsAutoScalingInterval(tac, intervalSec, v1alpha1.TiDBMemberType) g.Expect(r).Should(Equal(true)) g.Expect(err).Should(BeNil()) From bdc47d85a4da293fc699776376ae64670e5e776c Mon Sep 17 00:00:00 2001 From: Song Gao <2695690803@qq.com> Date: Thu, 2 Apr 2020 23:06:59 +0800 Subject: [PATCH 4/8] fix test --- .../autoscaler/calculate/calculate_test.go | 76 +++- pkg/autoscaler/autoscaler/util_test.go | 405 +++++++++++++----- 2 files changed, 346 insertions(+), 135 deletions(-) diff --git a/pkg/autoscaler/autoscaler/calculate/calculate_test.go b/pkg/autoscaler/autoscaler/calculate/calculate_test.go index cad5455cbf..f0b6472019 100644 --- a/pkg/autoscaler/autoscaler/calculate/calculate_test.go +++ b/pkg/autoscaler/autoscaler/calculate/calculate_test.go @@ -20,29 +20,59 @@ import ( func TestCalculate(t *testing.T) { g := NewGomegaWithT(t) - currentValue, targetValue := 20.0, 30.0 - currentReplicas := int32(4) - r, err := calculate(currentValue, targetValue, currentReplicas) - g.Expect(err).Should(BeNil()) - g.Expect(r).Should(Equal(int32(3))) + type testcase struct { + name string + currentReplicas int32 + currentValue float64 + targetValue float64 + expectedReplicas int32 + errMsg string + } - currentValue, targetValue = 30.0, 30.0 - currentReplicas = int32(4) - r, err = calculate(currentValue, targetValue, currentReplicas) - g.Expect(err).Should(BeNil()) - g.Expect(r).Should(Equal(int32(4))) - - currentValue, targetValue = 35.0, 30.0 - currentReplicas = int32(4) - r, err = calculate(currentValue, targetValue, currentReplicas) - g.Expect(err).Should(BeNil()) - g.Expect(r).Should(Equal(int32(5))) - - currentValue, targetValue = 0.0, 0.0 - currentReplicas = int32(4) - r, err = calculate(currentValue, targetValue, currentReplicas) - g.Expect(err).ShouldNot(BeNil()) - g.Expect(err.Error()).Should(Equal("targetValue in calculate func can't be zero")) - g.Expect(r).Should(Equal(int32(-1))) + testFn := func(tt *testcase) { + t.Log(tt.name) + r, err := calculate(tt.currentValue, tt.targetValue, tt.currentReplicas) + if len(tt.errMsg) < 1 { + g.Expect(err).Should(BeNil()) + } else { + g.Expect(err).ShouldNot(BeNil()) + g.Expect(err.Error()).Should(Equal(tt.errMsg)) + } + g.Expect(r).Should(Equal(tt.expectedReplicas)) + } + testcases := []testcase{ + { + name: "under target value", + currentReplicas: 4, + currentValue: 20.0, + targetValue: 30.0, + expectedReplicas: 3, + }, + { + name: "equal target value", + currentReplicas: 4, + currentValue: 30.0, + targetValue: 30.0, + expectedReplicas: 4, + }, + { + name: "greater than target value", + currentReplicas: 4, + currentValue: 35.0, + targetValue: 30.0, + expectedReplicas: 5, + }, + { + name: "target value is zero", + currentReplicas: 4, + currentValue: 35.0, + targetValue: 0, + expectedReplicas: -1, + errMsg: "targetValue in calculate func can't be zero", + }, + } + for _, tt := range testcases { + testFn(&tt) + } } diff --git a/pkg/autoscaler/autoscaler/util_test.go b/pkg/autoscaler/autoscaler/util_test.go index af838c3ba3..ec894cd39f 100644 --- a/pkg/autoscaler/autoscaler/util_test.go +++ b/pkg/autoscaler/autoscaler/util_test.go @@ -28,104 +28,256 @@ import ( func TestCheckStsAutoScalingInterval(t *testing.T) { g := NewGomegaWithT(t) - tac := newTidbClusterAutoScaler() - intervalSec := int32(100) - r, err := checkStsAutoScalingInterval(tac, intervalSec, v1alpha1.TiKVMemberType) - g.Expect(r).Should(Equal(true)) - g.Expect(err).Should(BeNil()) + type testcase struct { + name string + memberType v1alpha1.MemberType + HaveScaled bool + LastScaleIntervalSec int + expectedPermitScaling bool + } - r, err = checkStsAutoScalingInterval(tac, intervalSec, v1alpha1.TiDBMemberType) - g.Expect(r).Should(Equal(true)) - g.Expect(err).Should(BeNil()) + testFn := func(tt *testcase) { + t.Log(tt.name) + tac := newTidbClusterAutoScaler() + intervalSec := int32(100) + if tt.memberType == v1alpha1.TiKVMemberType { + if !tt.HaveScaled { + tac.Annotations = map[string]string{} + } else { + d := time.Duration(tt.LastScaleIntervalSec) * time.Second + tac.Annotations[label.AnnTiKVLastAutoScalingTimestamp] = fmt.Sprintf("%d", time.Now().Truncate(d).Unix()) + } + } else if tt.memberType == v1alpha1.TiDBMemberType { + if !tt.HaveScaled { + tac.Annotations = map[string]string{} + } else { + d := time.Duration(tt.LastScaleIntervalSec) * time.Second + tac.Annotations[label.AnnTiDBLastAutoScalingTimestamp] = fmt.Sprintf("%d", time.Now().Truncate(d).Unix()) + } + } + r, err := checkStsAutoScalingInterval(tac, intervalSec, tt.memberType) + g.Expect(err).Should(BeNil()) + g.Expect(r).Should(Equal(tt.expectedPermitScaling)) + } - tac.Annotations = map[string]string{} - tac.Annotations[label.AnnTiDBLastAutoScalingTimestamp] = fmt.Sprintf("%d", time.Now().Truncate(60*time.Second).Unix()) - tac.Annotations[label.AnnTiKVLastAutoScalingTimestamp] = fmt.Sprintf("%d", time.Now().Truncate(60*time.Second).Unix()) - r, err = checkStsAutoScalingInterval(tac, intervalSec, v1alpha1.TiDBMemberType) - g.Expect(r).Should(Equal(false)) - g.Expect(err).Should(BeNil()) - r, err = checkStsAutoScalingInterval(tac, intervalSec, v1alpha1.TiKVMemberType) - g.Expect(r).Should(Equal(false)) - g.Expect(err).Should(BeNil()) + testcases := []testcase{ + { + name: "tikv, first scaling", + memberType: v1alpha1.TiKVMemberType, + HaveScaled: false, + LastScaleIntervalSec: 0, + expectedPermitScaling: true, + }, + { + name: "tikv, scaling 60 secs ago", + memberType: v1alpha1.TiKVMemberType, + HaveScaled: true, + LastScaleIntervalSec: 60, + expectedPermitScaling: false, + }, + { + name: "tikv, scaling 1000 secs ago", + memberType: v1alpha1.TiKVMemberType, + HaveScaled: true, + LastScaleIntervalSec: 1000, + expectedPermitScaling: true, + }, + { + name: "tidb, first scaling", + memberType: v1alpha1.TiDBMemberType, + HaveScaled: false, + LastScaleIntervalSec: 0, + expectedPermitScaling: true, + }, + { + name: "tidb, scaling 60 secs ago", + memberType: v1alpha1.TiDBMemberType, + HaveScaled: true, + LastScaleIntervalSec: 60, + expectedPermitScaling: false, + }, + { + name: "tidb, scaling 1000 secs ago", + memberType: v1alpha1.TiDBMemberType, + HaveScaled: true, + LastScaleIntervalSec: 1000, + expectedPermitScaling: true, + }, + } - tac.Annotations = map[string]string{} - tac.Annotations[label.AnnTiDBLastAutoScalingTimestamp] = fmt.Sprintf("%d", time.Now().Truncate(200*time.Second).Unix()) - tac.Annotations[label.AnnTiKVLastAutoScalingTimestamp] = fmt.Sprintf("%d", time.Now().Truncate(200*time.Second).Unix()) - r, err = checkStsAutoScalingInterval(tac, intervalSec, v1alpha1.TiDBMemberType) - g.Expect(r).Should(Equal(true)) - g.Expect(err).Should(BeNil()) - r, err = checkStsAutoScalingInterval(tac, intervalSec, v1alpha1.TiKVMemberType) - g.Expect(r).Should(Equal(true)) - g.Expect(err).Should(BeNil()) + for _, tt := range testcases { + testFn(&tt) + } } func TestCheckStsAutoScalingPrerequisites(t *testing.T) { g := NewGomegaWithT(t) - sts := newSts() - - r := checkStsAutoScalingPrerequisites(sts) - g.Expect(r).Should(Equal(false)) - - sts.Status.UpdateRevision = "1" - sts.Status.CurrentRevision = "1" - sts.Spec.Replicas = pointer.Int32Ptr(1) - sts.Status.Replicas = 1 - r = checkStsAutoScalingPrerequisites(sts) - g.Expect(r).Should(Equal(true)) - - sts.Status.UpdateRevision = "1" - sts.Status.CurrentRevision = "2" - sts.Spec.Replicas = pointer.Int32Ptr(1) - sts.Status.Replicas = 1 - r = checkStsAutoScalingPrerequisites(sts) - g.Expect(r).Should(Equal(false)) - - sts.Status.UpdateRevision = "1" - sts.Status.CurrentRevision = "1" - sts.Spec.Replicas = pointer.Int32Ptr(1) - sts.Status.Replicas = 2 - r = checkStsAutoScalingPrerequisites(sts) - g.Expect(r).Should(Equal(false)) + type testcase struct { + name string + stsUpdating bool + stsScaling bool + expectedCheckResult bool + } + testFn := func(tt *testcase) { + t.Log(tt.name) + sts := newSts() + if tt.stsUpdating { + sts.Status.UpdateRevision = "1" + sts.Status.CurrentRevision = "2" + } else { + sts.Status.UpdateRevision = "1" + sts.Status.CurrentRevision = "1" + } + + if tt.stsScaling { + sts.Spec.Replicas = pointer.Int32Ptr(1) + sts.Status.Replicas = 2 + } else { + sts.Spec.Replicas = pointer.Int32Ptr(1) + sts.Status.Replicas = 1 + } + r := checkStsAutoScalingPrerequisites(sts) + g.Expect(r).Should(Equal(tt.expectedCheckResult)) + } + + testcases := []testcase{ + { + name: "upgrading", + stsUpdating: true, + stsScaling: false, + expectedCheckResult: false, + }, + { + name: "scaling", + stsUpdating: false, + stsScaling: true, + expectedCheckResult: false, + }, + { + name: "no upgrading, no scaling", + stsUpdating: false, + stsScaling: false, + expectedCheckResult: true, + }, + } + for _, tt := range testcases { + testFn(&tt) + } + } func TestLimitTargetReplicas(t *testing.T) { g := NewGomegaWithT(t) - tac := newTidbClusterAutoScaler() - tac.Spec.TiDB.MinReplicas = pointer.Int32Ptr(2) - tac.Spec.TiDB.MaxReplicas = 4 - - tac.Spec.TiKV.MinReplicas = pointer.Int32Ptr(2) - tac.Spec.TiKV.MaxReplicas = 4 - - targetReplicas := int32(1) - r := limitTargetReplicas(targetReplicas, tac, v1alpha1.TiDBMemberType) - g.Expect(r).Should(Equal(int32(2))) - r = limitTargetReplicas(targetReplicas, tac, v1alpha1.TiKVMemberType) - g.Expect(r).Should(Equal(int32(2))) - - targetReplicas = int32(2) - r = limitTargetReplicas(targetReplicas, tac, v1alpha1.TiDBMemberType) - g.Expect(r).Should(Equal(int32(2))) - r = limitTargetReplicas(targetReplicas, tac, v1alpha1.TiKVMemberType) - g.Expect(r).Should(Equal(int32(2))) - - targetReplicas = int32(3) - r = limitTargetReplicas(targetReplicas, tac, v1alpha1.TiDBMemberType) - g.Expect(r).Should(Equal(int32(3))) - r = limitTargetReplicas(targetReplicas, tac, v1alpha1.TiKVMemberType) - g.Expect(r).Should(Equal(int32(3))) - - targetReplicas = int32(4) - r = limitTargetReplicas(targetReplicas, tac, v1alpha1.TiDBMemberType) - g.Expect(r).Should(Equal(int32(4))) - r = limitTargetReplicas(targetReplicas, tac, v1alpha1.TiKVMemberType) - g.Expect(r).Should(Equal(int32(4))) - - targetReplicas = int32(5) - r = limitTargetReplicas(targetReplicas, tac, v1alpha1.TiDBMemberType) - g.Expect(r).Should(Equal(int32(4))) - r = limitTargetReplicas(targetReplicas, tac, v1alpha1.TiKVMemberType) - g.Expect(r).Should(Equal(int32(4))) + type testcase struct { + name string + targetReplicas int32 + minReplicas int32 + maxReplicas int32 + memberType v1alpha1.MemberType + expectedReplicas int32 + } + + testFn := func(tt *testcase) { + t.Log(tt.name) + tac := newTidbClusterAutoScaler() + if tt.memberType == v1alpha1.TiKVMemberType { + tac.Spec.TiKV.MinReplicas = pointer.Int32Ptr(tt.minReplicas) + tac.Spec.TiKV.MaxReplicas = tt.maxReplicas + } else if tt.memberType == v1alpha1.TiDBMemberType { + tac.Spec.TiDB.MinReplicas = pointer.Int32Ptr(tt.minReplicas) + tac.Spec.TiDB.MaxReplicas = tt.maxReplicas + } + r := limitTargetReplicas(tt.targetReplicas, tac, tt.memberType) + g.Expect(tt.expectedReplicas).Should(Equal(r)) + } + + testcases := []testcase{ + { + name: "tikv,smaller than min", + targetReplicas: 1, + minReplicas: 2, + maxReplicas: 4, + memberType: v1alpha1.TiKVMemberType, + expectedReplicas: 2, + }, + { + name: "tikv,equal min", + targetReplicas: 2, + minReplicas: 2, + maxReplicas: 4, + memberType: v1alpha1.TiKVMemberType, + expectedReplicas: 2, + }, + { + name: "tikv,bigger than min, smaller than max", + targetReplicas: 3, + minReplicas: 2, + maxReplicas: 4, + memberType: v1alpha1.TiKVMemberType, + expectedReplicas: 3, + }, + { + name: "tikv,equal max", + targetReplicas: 4, + minReplicas: 2, + maxReplicas: 4, + memberType: v1alpha1.TiKVMemberType, + expectedReplicas: 4, + }, + { + name: "tikv,greater than max", + targetReplicas: 5, + minReplicas: 2, + maxReplicas: 4, + memberType: v1alpha1.TiKVMemberType, + expectedReplicas: 4, + }, + //tidb + { + name: "tidb,smaller than min", + targetReplicas: 1, + minReplicas: 2, + maxReplicas: 4, + memberType: v1alpha1.TiDBMemberType, + expectedReplicas: 2, + }, + { + name: "tidb,equal min", + targetReplicas: 2, + minReplicas: 2, + maxReplicas: 4, + memberType: v1alpha1.TiDBMemberType, + expectedReplicas: 2, + }, + { + name: "tidb,bigger than min, smaller than max", + targetReplicas: 3, + minReplicas: 2, + maxReplicas: 4, + memberType: v1alpha1.TiDBMemberType, + expectedReplicas: 3, + }, + { + name: "tidb,equal max", + targetReplicas: 4, + minReplicas: 2, + maxReplicas: 4, + memberType: v1alpha1.TiDBMemberType, + expectedReplicas: 4, + }, + { + name: "tidb,greater than max", + targetReplicas: 5, + minReplicas: 2, + maxReplicas: 4, + memberType: v1alpha1.TiDBMemberType, + expectedReplicas: 4, + }, + } + for _, tt := range testcases { + testFn(&tt) + } + } func TestDefaultTac(t *testing.T) { @@ -162,32 +314,61 @@ func TestDefaultTac(t *testing.T) { func TestCheckAndUpdateTacAnn(t *testing.T) { g := NewGomegaWithT(t) - tac := newTidbClusterAutoScaler() - - tac.Annotations = nil - checkAndUpdateTacAnn(tac) - g.Expect(tac.Annotations).ShouldNot(BeNil()) - g.Expect(len(tac.Annotations)).Should(Equal(2)) - v, ok := tac.Annotations[label.AnnAutoScalingTargetNamespace] - g.Expect(ok).Should(Equal(ok)) - g.Expect(v).Should(Equal("default")) - v, ok = tac.Annotations[label.AnnAutoScalingTargetName] - g.Expect(ok).Should(Equal(ok)) - g.Expect(v).Should(Equal("tc")) + type testcase struct { + name string + haveScaling bool + targetNamespace string + targetName string + markedNamespace string + markedName string + } - tac.Spec.Cluster = v1alpha1.TidbClusterRef{ - Name: "foo", - Namespace: "bar", - } - checkAndUpdateTacAnn(tac) - g.Expect(tac.Annotations).ShouldNot(BeNil()) - g.Expect(len(tac.Annotations)).Should(Equal(2)) - v, ok = tac.Annotations[label.AnnAutoScalingTargetNamespace] - g.Expect(ok).Should(Equal(ok)) - g.Expect(v).Should(Equal("bar")) - v, ok = tac.Annotations[label.AnnAutoScalingTargetName] - g.Expect(ok).Should(Equal(ok)) - g.Expect(v).Should(Equal("foo")) + testFn := func(tt *testcase) { + tac := newTidbClusterAutoScaler() + tac.Annotations = nil + tac.Spec.Cluster.Name = tt.targetName + tac.Spec.Cluster.Namespace = tt.targetNamespace + if tt.haveScaling { + tac.Annotations[label.AnnAutoScalingTargetNamespace] = tt.targetNamespace + tac.Annotations[label.AnnAutoScalingTargetName] = tt.targetName + } + checkAndUpdateTacAnn(tac) + v, ok := tac.Annotations[label.AnnAutoScalingTargetNamespace] + g.Expect(ok).Should(Equal(ok)) + g.Expect(v).Should(Equal(tt.targetNamespace)) + v, ok = tac.Annotations[label.AnnAutoScalingTargetName] + g.Expect(ok).Should(Equal(ok)) + g.Expect(v).Should(Equal(tt.targetName)) + } + testcases := []testcase{ + { + name: "first syncing", + haveScaling: false, + markedName: "", + markedNamespace: "", + targetName: "foo", + targetNamespace: "bar", + }, + { + name: "second syncing", + haveScaling: true, + markedName: "foo", + markedNamespace: "bar", + targetName: "foo", + targetNamespace: "bar", + }, + { + name: "change target", + haveScaling: true, + markedName: "foo", + markedNamespace: "bar", + targetName: "foo2", + targetNamespace: "bar2", + }, + } + for _, tt := range testcases { + testFn(&tt) + } } func TestGenMetricsEndpoint(t *testing.T) { From 028353f4d543c9197ca2d0452a795e391b2747d3 Mon Sep 17 00:00:00 2001 From: Song Gao <2695690803@qq.com> Date: Fri, 3 Apr 2020 11:03:46 +0800 Subject: [PATCH 5/8] remove flasky test --- pkg/autoscaler/autoscaler/util_test.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/pkg/autoscaler/autoscaler/util_test.go b/pkg/autoscaler/autoscaler/util_test.go index ec894cd39f..c8bc9c483a 100644 --- a/pkg/autoscaler/autoscaler/util_test.go +++ b/pkg/autoscaler/autoscaler/util_test.go @@ -75,13 +75,6 @@ func TestCheckStsAutoScalingInterval(t *testing.T) { LastScaleIntervalSec: 60, expectedPermitScaling: false, }, - { - name: "tikv, scaling 1000 secs ago", - memberType: v1alpha1.TiKVMemberType, - HaveScaled: true, - LastScaleIntervalSec: 1000, - expectedPermitScaling: true, - }, { name: "tidb, first scaling", memberType: v1alpha1.TiDBMemberType, @@ -96,13 +89,6 @@ func TestCheckStsAutoScalingInterval(t *testing.T) { LastScaleIntervalSec: 60, expectedPermitScaling: false, }, - { - name: "tidb, scaling 1000 secs ago", - memberType: v1alpha1.TiDBMemberType, - HaveScaled: true, - LastScaleIntervalSec: 1000, - expectedPermitScaling: true, - }, } for _, tt := range testcases { From 52f62af92982f6a1b571c031379a4d39893406eb Mon Sep 17 00:00:00 2001 From: Song Gao <2695690803@qq.com> Date: Fri, 3 Apr 2020 11:10:21 +0800 Subject: [PATCH 6/8] fix unittest --- pkg/autoscaler/autoscaler/util_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/autoscaler/autoscaler/util_test.go b/pkg/autoscaler/autoscaler/util_test.go index c8bc9c483a..6947d7a730 100644 --- a/pkg/autoscaler/autoscaler/util_test.go +++ b/pkg/autoscaler/autoscaler/util_test.go @@ -315,6 +315,7 @@ func TestCheckAndUpdateTacAnn(t *testing.T) { tac.Spec.Cluster.Name = tt.targetName tac.Spec.Cluster.Namespace = tt.targetNamespace if tt.haveScaling { + tac.Annotations = map[string]string{} tac.Annotations[label.AnnAutoScalingTargetNamespace] = tt.targetNamespace tac.Annotations[label.AnnAutoScalingTargetName] = tt.targetName } From ab38831d384af9bec668913d784051101741ca9b Mon Sep 17 00:00:00 2001 From: Song Gao <2695690803@qq.com> Date: Fri, 3 Apr 2020 13:37:36 +0800 Subject: [PATCH 7/8] fix cpu test --- .../autoscaler/calculate/cpu_test.go | 84 ++++++++++++++----- 1 file changed, 62 insertions(+), 22 deletions(-) diff --git a/pkg/autoscaler/autoscaler/calculate/cpu_test.go b/pkg/autoscaler/autoscaler/calculate/cpu_test.go index ed80806d37..6f5e869f08 100644 --- a/pkg/autoscaler/autoscaler/calculate/cpu_test.go +++ b/pkg/autoscaler/autoscaler/calculate/cpu_test.go @@ -24,31 +24,71 @@ import ( func TestExtractCpuRequestsRatio(t *testing.T) { g := NewGomegaWithT(t) - c := newContainer() - r, err := extractCpuRequestsRatio(c) - g.Expect(err).Should(BeNil()) - g.Expect(almostEqual(r, 1.0)).Should(Equal(true)) - - c.Resources.Requests = map[corev1.ResourceName]resource.Quantity{ - corev1.ResourceCPU: resource.MustParse("1000m"), + type testcase struct { + name string + defineRequest bool + cpuValue string + expectedRadio float64 + occurError bool + errMsg string } - r, err = extractCpuRequestsRatio(c) - g.Expect(err).Should(BeNil()) - g.Expect(almostEqual(r, 1.0)).Should(Equal(true)) - c.Resources.Requests = map[corev1.ResourceName]resource.Quantity{ - corev1.ResourceCPU: resource.MustParse("1500m"), + testFn := func(tt *testcase) { + t.Log(tt.name) + c := newContainer() + if tt.defineRequest { + c.Resources.Requests = map[corev1.ResourceName]resource.Quantity{ + corev1.ResourceCPU: resource.MustParse(tt.cpuValue), + } + } else { + c.Resources.Requests = map[corev1.ResourceName]resource.Quantity{} + } + r, err := extractCpuRequestsRatio(c) + if !tt.occurError { + g.Expect(err).Should(BeNil()) + } else { + g.Expect(err).ShouldNot(BeNil()) + g.Expect(err.Error()).Should(Equal(tt.errMsg)) + } + g.Expect(almostEqual(r, tt.expectedRadio)).Should(Equal(true)) + } + testcases := []testcase{ + { + name: "cpu 1", + defineRequest: true, + cpuValue: "1", + occurError: false, + expectedRadio: 1.0, + errMsg: "", + }, + { + name: "cpu 1000m", + defineRequest: true, + cpuValue: "1000m", + occurError: false, + expectedRadio: 1.0, + errMsg: "", + }, + { + name: "cpu 1500m", + defineRequest: true, + cpuValue: "1500m", + occurError: false, + expectedRadio: 1.5, + errMsg: "", + }, + { + name: "no cpu request", + defineRequest: false, + cpuValue: "", + occurError: true, + expectedRadio: 0, + errMsg: fmt.Sprintf("container[%s] cpu requests is empty", "container"), + }, + } + for _, tt := range testcases { + testFn(&tt) } - r, err = extractCpuRequestsRatio(c) - g.Expect(err).Should(BeNil()) - g.Expect(almostEqual(r, 1.5)).Should(Equal(true)) - - c.Resources.Requests = map[corev1.ResourceName]resource.Quantity{} - r, err = extractCpuRequestsRatio(c) - g.Expect(err).ShouldNot(BeNil()) - g.Expect(err.Error()).Should(Equal(fmt.Sprintf("container[%s] cpu requests is empty", c.Name))) - g.Expect(almostEqual(r, 0)).Should(Equal(true)) - } func newContainer() *corev1.Container { From 3aff829b1e6499f5aaeae01f0dbd9fa2366aaac2 Mon Sep 17 00:00:00 2001 From: Song Gao <2695690803@qq.com> Date: Fri, 3 Apr 2020 18:08:04 +0800 Subject: [PATCH 8/8] revise test --- .../autoscaler/calculate/calculate_test.go | 32 ++- .../autoscaler/calculate/cpu_test.go | 47 ++--- pkg/autoscaler/autoscaler/util_test.go | 190 ++++++++---------- 3 files changed, 124 insertions(+), 145 deletions(-) diff --git a/pkg/autoscaler/autoscaler/calculate/calculate_test.go b/pkg/autoscaler/autoscaler/calculate/calculate_test.go index f0b6472019..899672fee3 100644 --- a/pkg/autoscaler/autoscaler/calculate/calculate_test.go +++ b/pkg/autoscaler/autoscaler/calculate/calculate_test.go @@ -20,28 +20,14 @@ import ( func TestCalculate(t *testing.T) { g := NewGomegaWithT(t) - type testcase struct { + tests := []struct { name string currentReplicas int32 currentValue float64 targetValue float64 expectedReplicas int32 errMsg string - } - - testFn := func(tt *testcase) { - t.Log(tt.name) - r, err := calculate(tt.currentValue, tt.targetValue, tt.currentReplicas) - if len(tt.errMsg) < 1 { - g.Expect(err).Should(BeNil()) - } else { - g.Expect(err).ShouldNot(BeNil()) - g.Expect(err.Error()).Should(Equal(tt.errMsg)) - } - g.Expect(r).Should(Equal(tt.expectedReplicas)) - } - - testcases := []testcase{ + }{ { name: "under target value", currentReplicas: 4, @@ -72,7 +58,17 @@ func TestCalculate(t *testing.T) { errMsg: "targetValue in calculate func can't be zero", }, } - for _, tt := range testcases { - testFn(&tt) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + r, err := calculate(tt.currentValue, tt.targetValue, tt.currentReplicas) + if len(tt.errMsg) < 1 { + g.Expect(err).Should(BeNil()) + } else { + g.Expect(err).ShouldNot(BeNil()) + g.Expect(err.Error()).Should(Equal(tt.errMsg)) + } + g.Expect(r).Should(Equal(tt.expectedReplicas)) + }) } } diff --git a/pkg/autoscaler/autoscaler/calculate/cpu_test.go b/pkg/autoscaler/autoscaler/calculate/cpu_test.go index 6f5e869f08..712b1bc281 100644 --- a/pkg/autoscaler/autoscaler/calculate/cpu_test.go +++ b/pkg/autoscaler/autoscaler/calculate/cpu_test.go @@ -24,35 +24,14 @@ import ( func TestExtractCpuRequestsRatio(t *testing.T) { g := NewGomegaWithT(t) - type testcase struct { + tests := []struct { name string defineRequest bool cpuValue string expectedRadio float64 occurError bool errMsg string - } - - testFn := func(tt *testcase) { - t.Log(tt.name) - c := newContainer() - if tt.defineRequest { - c.Resources.Requests = map[corev1.ResourceName]resource.Quantity{ - corev1.ResourceCPU: resource.MustParse(tt.cpuValue), - } - } else { - c.Resources.Requests = map[corev1.ResourceName]resource.Quantity{} - } - r, err := extractCpuRequestsRatio(c) - if !tt.occurError { - g.Expect(err).Should(BeNil()) - } else { - g.Expect(err).ShouldNot(BeNil()) - g.Expect(err.Error()).Should(Equal(tt.errMsg)) - } - g.Expect(almostEqual(r, tt.expectedRadio)).Should(Equal(true)) - } - testcases := []testcase{ + }{ { name: "cpu 1", defineRequest: true, @@ -86,8 +65,26 @@ func TestExtractCpuRequestsRatio(t *testing.T) { errMsg: fmt.Sprintf("container[%s] cpu requests is empty", "container"), }, } - for _, tt := range testcases { - testFn(&tt) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := newContainer() + if tt.defineRequest { + c.Resources.Requests = map[corev1.ResourceName]resource.Quantity{ + corev1.ResourceCPU: resource.MustParse(tt.cpuValue), + } + } else { + c.Resources.Requests = map[corev1.ResourceName]resource.Quantity{} + } + r, err := extractCpuRequestsRatio(c) + if !tt.occurError { + g.Expect(err).Should(BeNil()) + } else { + g.Expect(err).ShouldNot(BeNil()) + g.Expect(err.Error()).Should(Equal(tt.errMsg)) + } + g.Expect(almostEqual(r, tt.expectedRadio)).Should(Equal(true)) + }) } } diff --git a/pkg/autoscaler/autoscaler/util_test.go b/pkg/autoscaler/autoscaler/util_test.go index 6947d7a730..6668dcf070 100644 --- a/pkg/autoscaler/autoscaler/util_test.go +++ b/pkg/autoscaler/autoscaler/util_test.go @@ -28,39 +28,13 @@ import ( func TestCheckStsAutoScalingInterval(t *testing.T) { g := NewGomegaWithT(t) - type testcase struct { + tests := []struct { name string memberType v1alpha1.MemberType HaveScaled bool LastScaleIntervalSec int expectedPermitScaling bool - } - - testFn := func(tt *testcase) { - t.Log(tt.name) - tac := newTidbClusterAutoScaler() - intervalSec := int32(100) - if tt.memberType == v1alpha1.TiKVMemberType { - if !tt.HaveScaled { - tac.Annotations = map[string]string{} - } else { - d := time.Duration(tt.LastScaleIntervalSec) * time.Second - tac.Annotations[label.AnnTiKVLastAutoScalingTimestamp] = fmt.Sprintf("%d", time.Now().Truncate(d).Unix()) - } - } else if tt.memberType == v1alpha1.TiDBMemberType { - if !tt.HaveScaled { - tac.Annotations = map[string]string{} - } else { - d := time.Duration(tt.LastScaleIntervalSec) * time.Second - tac.Annotations[label.AnnTiDBLastAutoScalingTimestamp] = fmt.Sprintf("%d", time.Now().Truncate(d).Unix()) - } - } - r, err := checkStsAutoScalingInterval(tac, intervalSec, tt.memberType) - g.Expect(err).Should(BeNil()) - g.Expect(r).Should(Equal(tt.expectedPermitScaling)) - } - - testcases := []testcase{ + }{ { name: "tikv, first scaling", memberType: v1alpha1.TiKVMemberType, @@ -91,42 +65,42 @@ func TestCheckStsAutoScalingInterval(t *testing.T) { }, } - for _, tt := range testcases { - testFn(&tt) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + + tac := newTidbClusterAutoScaler() + intervalSec := int32(100) + if tt.memberType == v1alpha1.TiKVMemberType { + if !tt.HaveScaled { + tac.Annotations = map[string]string{} + } else { + d := time.Duration(tt.LastScaleIntervalSec) * time.Second + tac.Annotations[label.AnnTiKVLastAutoScalingTimestamp] = fmt.Sprintf("%d", time.Now().Truncate(d).Unix()) + } + } else if tt.memberType == v1alpha1.TiDBMemberType { + if !tt.HaveScaled { + tac.Annotations = map[string]string{} + } else { + d := time.Duration(tt.LastScaleIntervalSec) * time.Second + tac.Annotations[label.AnnTiDBLastAutoScalingTimestamp] = fmt.Sprintf("%d", time.Now().Truncate(d).Unix()) + } + } + r, err := checkStsAutoScalingInterval(tac, intervalSec, tt.memberType) + g.Expect(err).Should(BeNil()) + g.Expect(r).Should(Equal(tt.expectedPermitScaling)) + }) + } } func TestCheckStsAutoScalingPrerequisites(t *testing.T) { g := NewGomegaWithT(t) - type testcase struct { + tests := []struct { name string stsUpdating bool stsScaling bool expectedCheckResult bool - } - testFn := func(tt *testcase) { - t.Log(tt.name) - sts := newSts() - if tt.stsUpdating { - sts.Status.UpdateRevision = "1" - sts.Status.CurrentRevision = "2" - } else { - sts.Status.UpdateRevision = "1" - sts.Status.CurrentRevision = "1" - } - - if tt.stsScaling { - sts.Spec.Replicas = pointer.Int32Ptr(1) - sts.Status.Replicas = 2 - } else { - sts.Spec.Replicas = pointer.Int32Ptr(1) - sts.Status.Replicas = 1 - } - r := checkStsAutoScalingPrerequisites(sts) - g.Expect(r).Should(Equal(tt.expectedCheckResult)) - } - - testcases := []testcase{ + }{ { name: "upgrading", stsUpdating: true, @@ -146,38 +120,41 @@ func TestCheckStsAutoScalingPrerequisites(t *testing.T) { expectedCheckResult: true, }, } - for _, tt := range testcases { - testFn(&tt) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + sts := newSts() + if tt.stsUpdating { + sts.Status.UpdateRevision = "1" + sts.Status.CurrentRevision = "2" + } else { + sts.Status.UpdateRevision = "1" + sts.Status.CurrentRevision = "1" + } + if tt.stsScaling { + sts.Spec.Replicas = pointer.Int32Ptr(1) + sts.Status.Replicas = 2 + } else { + sts.Spec.Replicas = pointer.Int32Ptr(1) + sts.Status.Replicas = 1 + } + r := checkStsAutoScalingPrerequisites(sts) + g.Expect(r).Should(Equal(tt.expectedCheckResult)) + }) } } func TestLimitTargetReplicas(t *testing.T) { g := NewGomegaWithT(t) - type testcase struct { + tests := []struct { name string targetReplicas int32 minReplicas int32 maxReplicas int32 memberType v1alpha1.MemberType expectedReplicas int32 - } - - testFn := func(tt *testcase) { - t.Log(tt.name) - tac := newTidbClusterAutoScaler() - if tt.memberType == v1alpha1.TiKVMemberType { - tac.Spec.TiKV.MinReplicas = pointer.Int32Ptr(tt.minReplicas) - tac.Spec.TiKV.MaxReplicas = tt.maxReplicas - } else if tt.memberType == v1alpha1.TiDBMemberType { - tac.Spec.TiDB.MinReplicas = pointer.Int32Ptr(tt.minReplicas) - tac.Spec.TiDB.MaxReplicas = tt.maxReplicas - } - r := limitTargetReplicas(tt.targetReplicas, tac, tt.memberType) - g.Expect(tt.expectedReplicas).Should(Equal(r)) - } - - testcases := []testcase{ + }{ { name: "tikv,smaller than min", targetReplicas: 1, @@ -260,10 +237,21 @@ func TestLimitTargetReplicas(t *testing.T) { expectedReplicas: 4, }, } - for _, tt := range testcases { - testFn(&tt) - } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tac := newTidbClusterAutoScaler() + if tt.memberType == v1alpha1.TiKVMemberType { + tac.Spec.TiKV.MinReplicas = pointer.Int32Ptr(tt.minReplicas) + tac.Spec.TiKV.MaxReplicas = tt.maxReplicas + } else if tt.memberType == v1alpha1.TiDBMemberType { + tac.Spec.TiDB.MinReplicas = pointer.Int32Ptr(tt.minReplicas) + tac.Spec.TiDB.MaxReplicas = tt.maxReplicas + } + r := limitTargetReplicas(tt.targetReplicas, tac, tt.memberType) + g.Expect(tt.expectedReplicas).Should(Equal(r)) + }) + } } func TestDefaultTac(t *testing.T) { @@ -300,34 +288,14 @@ func TestDefaultTac(t *testing.T) { func TestCheckAndUpdateTacAnn(t *testing.T) { g := NewGomegaWithT(t) - type testcase struct { + tests := []struct { name string haveScaling bool targetNamespace string targetName string markedNamespace string markedName string - } - - testFn := func(tt *testcase) { - tac := newTidbClusterAutoScaler() - tac.Annotations = nil - tac.Spec.Cluster.Name = tt.targetName - tac.Spec.Cluster.Namespace = tt.targetNamespace - if tt.haveScaling { - tac.Annotations = map[string]string{} - tac.Annotations[label.AnnAutoScalingTargetNamespace] = tt.targetNamespace - tac.Annotations[label.AnnAutoScalingTargetName] = tt.targetName - } - checkAndUpdateTacAnn(tac) - v, ok := tac.Annotations[label.AnnAutoScalingTargetNamespace] - g.Expect(ok).Should(Equal(ok)) - g.Expect(v).Should(Equal(tt.targetNamespace)) - v, ok = tac.Annotations[label.AnnAutoScalingTargetName] - g.Expect(ok).Should(Equal(ok)) - g.Expect(v).Should(Equal(tt.targetName)) - } - testcases := []testcase{ + }{ { name: "first syncing", haveScaling: false, @@ -353,8 +321,26 @@ func TestCheckAndUpdateTacAnn(t *testing.T) { targetNamespace: "bar2", }, } - for _, tt := range testcases { - testFn(&tt) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tac := newTidbClusterAutoScaler() + tac.Annotations = nil + tac.Spec.Cluster.Name = tt.targetName + tac.Spec.Cluster.Namespace = tt.targetNamespace + if tt.haveScaling { + tac.Annotations = map[string]string{} + tac.Annotations[label.AnnAutoScalingTargetNamespace] = tt.targetNamespace + tac.Annotations[label.AnnAutoScalingTargetName] = tt.targetName + } + checkAndUpdateTacAnn(tac) + v, ok := tac.Annotations[label.AnnAutoScalingTargetNamespace] + g.Expect(ok).Should(Equal(ok)) + g.Expect(v).Should(Equal(tt.targetNamespace)) + v, ok = tac.Annotations[label.AnnAutoScalingTargetName] + g.Expect(ok).Should(Equal(ok)) + g.Expect(v).Should(Equal(tt.targetName)) + }) } }