package cluster

import (
	"context"
	"testing"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"

	. "github.com/onsi/gomega"
	"github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1"
	apps "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/meta"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/utils/pointer"
)

func TestBuildSuspendCondition(t *testing.T) {
	cases := map[string]struct {
		dbstatus       *cloudv1.DBStatus
		disableTiFlash bool
		expect         cloudv1.ClusterCondition
	}{
		"DBnil": {
			dbstatus: nil,
			expect: cloudv1.ClusterCondition{
				Type:    cloudv1.ClusterSuspended,
				Status:  cloudv1.ConditionFalse,
				Reason:  "ClusterNotSuspended",
				Message: "Cluster.Status.DB is nil",
			},
		},
		"ComponentStatusnil": {
			dbstatus: &cloudv1.DBStatus{
				PD:      nil,
				TiDB:    nil,
				TiKV:    nil,
				TiFlash: nil,
			},
			expect: cloudv1.ClusterCondition{
				Type:    cloudv1.ClusterSuspended,
				Status:  cloudv1.ConditionFalse,
				Reason:  "ClusterNotSuspended",
				Message: "Cluster.Status.DB.PD is nil;Cluster.Status.DB.TiDB is nil;Cluster.Status.DB.TiKV is nil;Cluster.Status.DB.TiFlash is nil",
			},
		},
		"AllFalse": {
			dbstatus: &cloudv1.DBStatus{
				PD: nil,
				TiDB: &cloudv1.TiDBStatus{
					Conditions: []metav1.Condition{},
				},
				TiKV: &cloudv1.TiKVStatus{
					Conditions: []metav1.Condition{
						{
							Type: "test",
						},
					},
				},
				TiFlash: &cloudv1.TiFlashStatus{
					Conditions: []metav1.Condition{
						{
							Type:   cloudv1.ComponentSuspended,
							Status: metav1.ConditionFalse,
						},
					},
				},
			},
			expect: cloudv1.ClusterCondition{
				Type:    cloudv1.ClusterSuspended,
				Status:  cloudv1.ConditionFalse,
				Reason:  "ClusterNotSuspended",
				Message: "Cluster.Status.DB.PD is nil;TiDB has not been suspended;TiKV has not been suspended;TiFlash has not been suspended",
			},
		},
		"AllFalseNoTiFlash": {
			dbstatus: &cloudv1.DBStatus{
				PD: nil,
				TiDB: &cloudv1.TiDBStatus{
					Conditions: []metav1.Condition{},
				},
				TiKV: &cloudv1.TiKVStatus{
					Conditions: []metav1.Condition{
						{
							Type: "test",
						},
					},
				},
				TiFlash: &cloudv1.TiFlashStatus{
					Conditions: []metav1.Condition{
						{
							Type:   cloudv1.ComponentSuspended,
							Status: metav1.ConditionFalse,
						},
					},
				},
			},
			disableTiFlash: true,
			expect: cloudv1.ClusterCondition{
				Type:    cloudv1.ClusterSuspended,
				Status:  cloudv1.ConditionFalse,
				Reason:  "ClusterNotSuspended",
				Message: "Cluster.Status.DB.PD is nil;TiDB has not been suspended;TiKV has not been suspended",
			},
		},
		"AllTrue": {
			dbstatus: &cloudv1.DBStatus{
				PD: &cloudv1.PDStatus{
					Conditions: []metav1.Condition{
						{
							Type:   cloudv1.ComponentSuspended,
							Status: metav1.ConditionTrue,
						},
					},
				},
				TiDB: &cloudv1.TiDBStatus{
					Conditions: []metav1.Condition{
						{
							Type:   cloudv1.ComponentSuspended,
							Status: metav1.ConditionTrue,
						},
					},
				},
				TiKV: &cloudv1.TiKVStatus{
					Conditions: []metav1.Condition{
						{
							Type:   cloudv1.ComponentSuspended,
							Status: metav1.ConditionTrue,
						},
					},
				},
				TiFlash: &cloudv1.TiFlashStatus{
					Conditions: []metav1.Condition{
						{
							Type:   cloudv1.ComponentSuspended,
							Status: metav1.ConditionTrue,
						},
					},
				},
			},
			expect: cloudv1.ClusterCondition{
				Type:    cloudv1.ClusterSuspended,
				Status:  cloudv1.ConditionTrue,
				Reason:  "ClusterSuspended",
				Message: "The cluster has been suspended",
			},
		},
		"AllTrueNoTiFlash": {
			disableTiFlash: true,
			dbstatus: &cloudv1.DBStatus{
				PD: &cloudv1.PDStatus{
					Conditions: []metav1.Condition{
						{
							Type:   cloudv1.ComponentSuspended,
							Status: metav1.ConditionTrue,
						},
					},
				},
				TiDB: &cloudv1.TiDBStatus{
					Conditions: []metav1.Condition{
						{
							Type:   cloudv1.ComponentSuspended,
							Status: metav1.ConditionTrue,
						},
					},
				},
				TiKV: &cloudv1.TiKVStatus{
					Conditions: []metav1.Condition{
						{
							Type:   cloudv1.ComponentSuspended,
							Status: metav1.ConditionTrue,
						},
					},
				},
				TiFlash: &cloudv1.TiFlashStatus{
					Conditions: []metav1.Condition{
						{
							Type:   cloudv1.ComponentSuspended,
							Status: metav1.ConditionTrue,
						},
					},
				},
			},
			expect: cloudv1.ClusterCondition{
				Type:    cloudv1.ClusterSuspended,
				Status:  cloudv1.ConditionTrue,
				Reason:  "ClusterSuspended",
				Message: "The cluster has been suspended",
			},
		},
	}
	for name, tc := range cases {
		t.Run(name, func(t *testing.T) {
			g := NewGomegaWithT(t)
			cluster := &cloudv1.Cluster{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "123",
					Namespace: "test",
					Labels:    map[string]string{"tags.tidbcloud.com/a": "aa", "tags.tidbcloud.com/b": "bb"},
				},
				Spec: cloudv1.ClusterSpec{
					SqlEndpoints: cloudv1.SqlEndpoints{
						Private: &cloudv1.Service{
							Enabled: pointer.Bool(true),
						},
					},
					Cluster: cloudv1.ClusterTopology{
						TiFlash: cloudv1.TiFlash{
							Replicas: 1,
						},
					},
				},
				Status: cloudv1.ClusterStatus{
					DB: &cloudv1.DBStatus{
						PD:      &cloudv1.PDStatus{},
						TiDB:    &cloudv1.TiDBStatus{},
						TiKV:    &cloudv1.TiKVStatus{},
						TiFlash: &cloudv1.TiFlashStatus{},
					},
				},
			}
			if tc.disableTiFlash {
				cluster.Spec.Cluster.TiFlash.Replicas = 0
			}
			pdMixedDeployConfig := &cloudv1.MixedDeployPDWithTiKV{}
			pdMixedDeployConfig.SetAlwaysEnabled()
			resolver := &TiDBClusterStatusResolver{
				Target:              cluster,
				PDMixedDeployConfig: pdMixedDeployConfig,
			}
			result := resolver.buildSuspendCondition(tc.dbstatus)
			g.Expect(result).To(Equal(tc.expect))

		})
	}
}
func TestComputeTiDBComponentConditions(t *testing.T) {
	cases := map[string]struct {
		componentStatusNil bool
		conditions         []metav1.Condition
		status             v1alpha1.TiDBStatus
		nodes              []corev1.Node
		expect             []metav1.Condition
	}{
		"componentStatus_nil_status_suspended_nodes_0": {
			componentStatusNil: true,
			status: v1alpha1.TiDBStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionTrue,
					Reason:  "ResourcesSuspended",
					Message: "All Pods and nodes are suspended",
				},
			},
		},
		"componentStatus_nil_status_suspended_nodes_1": {
			componentStatusNil: true,
			status: v1alpha1.TiDBStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "1 Nodes not suspended",
				},
			},
		},
		"componentStatus_nil_status_nosuspended_nodes_0": {
			componentStatusNil: true,
			status: v1alpha1.TiDBStatus{
				Phase:       v1alpha1.NormalPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: nil,
			expect:     []metav1.Condition{},
		},
		"componentStatus_nil_status_nosuspended_nodes_1": {
			componentStatusNil: true,
			status: v1alpha1.TiDBStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: &apps.StatefulSetStatus{},
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "Pods not suspended;1 Nodes not suspended",
				},
			},
		},
		"Condition_nil_status_suspended_nodes_0": {
			status: v1alpha1.TiDBStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionTrue,
					Reason:  "ResourcesSuspended",
					Message: "All Pods and nodes are suspended",
				},
			},
		},
		"Condition_nil_status_suspended_nodes_1": {
			status: v1alpha1.TiDBStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "1 Nodes not suspended",
				},
			},
		},
		"Condition_nil_status_nosuspended_nodes_0": {
			status: v1alpha1.TiDBStatus{
				Phase:       v1alpha1.NormalPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: nil,
			expect:     []metav1.Condition{},
		},
		"Condition_nil_status_nosuspended_nodes_1": {
			status: v1alpha1.TiDBStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: &apps.StatefulSetStatus{},
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "Pods not suspended;1 Nodes not suspended",
				},
			},
		},
		"Condition_empty_status_suspended_nodes_0": {
			status: v1alpha1.TiDBStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: []metav1.Condition{},
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionTrue,
					Reason:  "ResourcesSuspended",
					Message: "All Pods and nodes are suspended",
				},
			},
		},
		"Condition_empty_status_suspended_nodes_1": {
			status: v1alpha1.TiDBStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: []metav1.Condition{},
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "1 Nodes not suspended",
				},
			},
		},
		"Condition_empty_status_nosuspended_nodes_0": {
			status: v1alpha1.TiDBStatus{
				Phase:       v1alpha1.NormalPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: []metav1.Condition{},
			expect:     []metav1.Condition{},
		},
		"Condition_empty_status_nosuspended_nodes_1": {
			status: v1alpha1.TiDBStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: &apps.StatefulSetStatus{},
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: []metav1.Condition{},
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "Pods not suspended;1 Nodes not suspended",
				},
			},
		},
		"Condition_nonempty_status_suspended_nodes_0": {
			status: v1alpha1.TiDBStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{},
			conditions: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
			expect: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionTrue,
					Reason:  "ResourcesSuspended",
					Message: "All Pods and nodes are suspended",
				},
			},
		},
		"Condition_nonempty_status_suspended_nodes_1": {
			status: v1alpha1.TiDBStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
			expect: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "1 Nodes not suspended",
				},
			},
		},
		"Condition_nonempty_status_nosuspended_nodes_0": {
			status: v1alpha1.TiDBStatus{
				Phase:       v1alpha1.NormalPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{},
			conditions: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
			expect: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
		},
		"Condition_nonempty_status_nosuspended_nodes_1": {
			status: v1alpha1.TiDBStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: &apps.StatefulSetStatus{},
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
			expect: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "Pods not suspended;1 Nodes not suspended",
				},
			},
		},
	}
	for name, tc := range cases {
		t.Run(name, func(t *testing.T) {
			g := NewGomegaWithT(t)
			tct := &v1alpha1.TidbCluster{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "tls-nightly",
					Namespace: "ns",
				},
				Spec: v1alpha1.TidbClusterSpec{
					PD: &v1alpha1.PDSpec{
						ComponentSpec: v1alpha1.ComponentSpec{
							Image: "pingcap/pd:nightly",
						},
						Replicas: 3,
					},
					TiKV: &v1alpha1.TiKVSpec{},
					TiDB: &v1alpha1.TiDBSpec{},
				},
				Status: v1alpha1.TidbClusterStatus{},
			}
			cluster := &cloudv1.Cluster{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "123",
					Namespace: "test",
					Labels:    map[string]string{"tags.tidbcloud.com/a": "aa", "tags.tidbcloud.com/b": "bb"},
				},
				Spec: cloudv1.ClusterSpec{
					SqlEndpoints: cloudv1.SqlEndpoints{
						Private: &cloudv1.Service{
							Enabled: pointer.Bool(true),
						},
					},
					Cluster: cloudv1.ClusterTopology{
						TiFlash: cloudv1.TiFlash{
							Replicas: 1,
						},
					},
				},
				Status: cloudv1.ClusterStatus{
					DB: &cloudv1.DBStatus{
						PD:      &cloudv1.PDStatus{},
						TiDB:    &cloudv1.TiDBStatus{},
						TiKV:    &cloudv1.TiKVStatus{},
						TiFlash: &cloudv1.TiFlashStatus{},
					},
				},
			}
			tct.Spec.TiDB.SuspendAction = &v1alpha1.SuspendAction{
				SuspendStatefulSet: true,
			}

			tct.Status.TiDB = tc.status
			cluster.Status.DB.TiDB.Conditions = tc.conditions
			pdMixedDeployConfig := &cloudv1.MixedDeployPDWithTiKV{}
			pdMixedDeployConfig.SetAlwaysEnabled()
			resolver := &TiDBClusterStatusResolver{
				Target:              cluster,
				TiDBCluster:         tct,
				PDMixedDeployConfig: pdMixedDeployConfig,
			}
			result := resolver.computeComponentConditions(context.TODO(), cloudv1.ComponentTiDB, tc.nodes)
			g.Expect(len(result)).To(Equal(len(tc.expect)))
			for _, r := range result {
				e := meta.FindStatusCondition(tc.expect, r.Type)
				g.Expect(r.Type).To(Equal(e.Type))
				g.Expect(r.Status).To(Equal(e.Status))
				g.Expect(r.Reason).To(Equal(e.Reason))
				g.Expect(r.Message).To(Equal(e.Message))

			}

		})
	}
}
func TestComputeTiKVComponentConditions(t *testing.T) {
	cases := map[string]struct {
		componentStatusNil bool
		conditions         []metav1.Condition
		status             v1alpha1.TiKVStatus
		nodes              []corev1.Node
		expect             []metav1.Condition
	}{
		"componentStatus_nil_status_suspended_nodes_0": {
			componentStatusNil: true,
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionTrue,
					Reason:  "ResourcesSuspended",
					Message: "All Pods and nodes are suspended",
				},
			},
		},
		"componentStatus_nil_status_suspended_nodes_1": {
			componentStatusNil: true,
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "1 Nodes not suspended",
				},
			},
		},
		"componentStatus_nil_status_nosuspended_nodes_0": {
			componentStatusNil: true,
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.NormalPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: nil,
			expect:     []metav1.Condition{},
		},
		"componentStatus_nil_status_nosuspended_nodes_1": {
			componentStatusNil: true,
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: &apps.StatefulSetStatus{},
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "Pods not suspended;1 Nodes not suspended",
				},
			},
		},
		"Condition_nil_status_suspended_nodes_0": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionTrue,
					Reason:  "ResourcesSuspended",
					Message: "All Pods and nodes are suspended",
				},
			},
		},
		"Condition_nil_status_suspended_nodes_1": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "1 Nodes not suspended",
				},
			},
		},
		"Condition_nil_status_nosuspended_nodes_0": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.NormalPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: nil,
			expect:     []metav1.Condition{},
		},
		"Condition_nil_status_nosuspended_nodes_1": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: &apps.StatefulSetStatus{},
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "Pods not suspended;1 Nodes not suspended",
				},
			},
		},
		"Condition_empty_status_suspended_nodes_0": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: []metav1.Condition{},
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionTrue,
					Reason:  "ResourcesSuspended",
					Message: "All Pods and nodes are suspended",
				},
			},
		},
		"Condition_empty_status_suspended_nodes_1": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: []metav1.Condition{},
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "1 Nodes not suspended",
				},
			},
		},
		"Condition_empty_status_nosuspended_nodes_0": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.NormalPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: []metav1.Condition{},
			expect:     []metav1.Condition{},
		},
		"Condition_empty_status_nosuspended_nodes_1": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: &apps.StatefulSetStatus{},
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: []metav1.Condition{},
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "Pods not suspended;1 Nodes not suspended",
				},
			},
		},
		"Condition_nonempty_status_suspended_nodes_0": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{},
			conditions: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
			expect: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionTrue,
					Reason:  "ResourcesSuspended",
					Message: "All Pods and nodes are suspended",
				},
			},
		},
		"Condition_nonempty_status_suspended_nodes_1": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
			expect: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "1 Nodes not suspended",
				},
			},
		},
		"Condition_nonempty_status_nosuspended_nodes_0": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.NormalPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{},
			conditions: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
			expect: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
		},
		"Condition_nonempty_status_nosuspended_nodes_1": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: &apps.StatefulSetStatus{},
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
			expect: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "Pods not suspended;1 Nodes not suspended",
				},
			},
		},
	}
	for name, tc := range cases {
		t.Run(name, func(t *testing.T) {
			g := NewGomegaWithT(t)
			tct := &v1alpha1.TidbCluster{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "tls-nightly",
					Namespace: "ns",
				},
				Spec: v1alpha1.TidbClusterSpec{
					PD: &v1alpha1.PDSpec{
						ComponentSpec: v1alpha1.ComponentSpec{
							Image: "pingcap/pd:nightly",
						},
						Replicas: 3,
					},
					TiKV: &v1alpha1.TiKVSpec{},
					TiDB: &v1alpha1.TiDBSpec{},
				},
				Status: v1alpha1.TidbClusterStatus{},
			}
			cluster := &cloudv1.Cluster{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "123",
					Namespace: "test",
					Labels:    map[string]string{"tags.tidbcloud.com/a": "aa", "tags.tidbcloud.com/b": "bb"},
				},
				Spec: cloudv1.ClusterSpec{
					SqlEndpoints: cloudv1.SqlEndpoints{
						Private: &cloudv1.Service{
							Enabled: pointer.Bool(true),
						},
					},
					Cluster: cloudv1.ClusterTopology{
						TiFlash: cloudv1.TiFlash{
							Replicas: 1,
						},
					},
				},
				Status: cloudv1.ClusterStatus{
					DB: &cloudv1.DBStatus{
						PD:      &cloudv1.PDStatus{},
						TiDB:    &cloudv1.TiDBStatus{},
						TiKV:    &cloudv1.TiKVStatus{},
						TiFlash: &cloudv1.TiFlashStatus{},
					},
				},
			}
			tct.Spec.TiKV.SuspendAction = &v1alpha1.SuspendAction{
				SuspendStatefulSet: true,
			}

			tct.Status.TiKV = tc.status
			cluster.Status.DB.TiKV.Conditions = tc.conditions
			pdMixedDeployConfig := &cloudv1.MixedDeployPDWithTiKV{}
			pdMixedDeployConfig.SetAlwaysEnabled()
			resolver := &TiDBClusterStatusResolver{
				Target:              cluster,
				TiDBCluster:         tct,
				PDMixedDeployConfig: pdMixedDeployConfig,
			}
			result := resolver.computeComponentConditions(context.TODO(), cloudv1.ComponentTiKV, tc.nodes)
			g.Expect(len(result)).To(Equal(len(tc.expect)))
			for _, r := range result {
				e := meta.FindStatusCondition(tc.expect, r.Type)
				g.Expect(r.Type).To(Equal(e.Type))
				g.Expect(r.Status).To(Equal(e.Status))
				g.Expect(r.Reason).To(Equal(e.Reason))
				g.Expect(r.Message).To(Equal(e.Message))

			}

		})
	}
}
func TestComputePDComponentConditions(t *testing.T) {
	cases := map[string]struct {
		componentStatusNil bool
		conditions         []metav1.Condition
		status             v1alpha1.PDStatus
		nodes              []corev1.Node
		expect             []metav1.Condition
	}{
		"componentStatus_nil_status_suspended_nodes_0": {
			componentStatusNil: true,
			status: v1alpha1.PDStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionTrue,
					Reason:  "ResourcesSuspended",
					Message: "All Pods and nodes are suspended",
				},
			},
		},
		"componentStatus_nil_status_suspended_nodes_1": {
			componentStatusNil: true,
			status: v1alpha1.PDStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "1 Nodes not suspended",
				},
			},
		},
		"componentStatus_nil_status_nosuspended_nodes_0": {
			componentStatusNil: true,
			status: v1alpha1.PDStatus{
				Phase:       v1alpha1.NormalPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: nil,
			expect:     []metav1.Condition{},
		},
		"componentStatus_nil_status_nosuspended_nodes_1": {
			componentStatusNil: true,
			status: v1alpha1.PDStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: &apps.StatefulSetStatus{},
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "Pods not suspended;1 Nodes not suspended",
				},
			},
		},
		"Condition_nil_status_suspended_nodes_0": {
			status: v1alpha1.PDStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionTrue,
					Reason:  "ResourcesSuspended",
					Message: "All Pods and nodes are suspended",
				},
			},
		},
		"Condition_nil_status_suspended_nodes_1": {
			status: v1alpha1.PDStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "1 Nodes not suspended",
				},
			},
		},
		"Condition_nil_status_nosuspended_nodes_0": {
			status: v1alpha1.PDStatus{
				Phase:       v1alpha1.NormalPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: nil,
			expect:     []metav1.Condition{},
		},
		"Condition_nil_status_nosuspended_nodes_1": {
			status: v1alpha1.PDStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: &apps.StatefulSetStatus{},
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "Pods not suspended;1 Nodes not suspended",
				},
			},
		},
		"Condition_empty_status_suspended_nodes_0": {
			status: v1alpha1.PDStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: []metav1.Condition{},
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionTrue,
					Reason:  "ResourcesSuspended",
					Message: "All Pods and nodes are suspended",
				},
			},
		},
		"Condition_empty_status_suspended_nodes_1": {
			status: v1alpha1.PDStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: []metav1.Condition{},
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "1 Nodes not suspended",
				},
			},
		},
		"Condition_empty_status_nosuspended_nodes_0": {
			status: v1alpha1.PDStatus{
				Phase:       v1alpha1.NormalPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: []metav1.Condition{},
			expect:     []metav1.Condition{},
		},
		"Condition_empty_status_nosuspended_nodes_1": {
			status: v1alpha1.PDStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: &apps.StatefulSetStatus{},
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: []metav1.Condition{},
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "Pods not suspended;1 Nodes not suspended",
				},
			},
		},
		"Condition_nonempty_status_suspended_nodes_0": {
			status: v1alpha1.PDStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{},
			conditions: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
			expect: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionTrue,
					Reason:  "ResourcesSuspended",
					Message: "All Pods and nodes are suspended",
				},
			},
		},
		"Condition_nonempty_status_suspended_nodes_1": {
			status: v1alpha1.PDStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
			expect: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "1 Nodes not suspended",
				},
			},
		},
		"Condition_nonempty_status_nosuspended_nodes_0": {
			status: v1alpha1.PDStatus{
				Phase:       v1alpha1.NormalPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{},
			conditions: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
			expect: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
		},
		"Condition_nonempty_status_nosuspended_nodes_1": {
			status: v1alpha1.PDStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: &apps.StatefulSetStatus{},
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
			expect: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "Pods not suspended;1 Nodes not suspended",
				},
			},
		},
	}
	for name, tc := range cases {
		t.Run(name, func(t *testing.T) {
			g := NewGomegaWithT(t)
			tct := &v1alpha1.TidbCluster{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "tls-nightly",
					Namespace: "ns",
				},
				Spec: v1alpha1.TidbClusterSpec{
					PD: &v1alpha1.PDSpec{
						ComponentSpec: v1alpha1.ComponentSpec{
							Image: "pingcap/pd:nightly",
						},
						Replicas: 3,
					},
					TiKV: &v1alpha1.TiKVSpec{},
					TiDB: &v1alpha1.TiDBSpec{},
				},
				Status: v1alpha1.TidbClusterStatus{},
			}
			cluster := &cloudv1.Cluster{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "123",
					Namespace: "test",
					Labels:    map[string]string{"tags.tidbcloud.com/a": "aa", "tags.tidbcloud.com/b": "bb"},
				},
				Spec: cloudv1.ClusterSpec{
					SqlEndpoints: cloudv1.SqlEndpoints{
						Private: &cloudv1.Service{
							Enabled: pointer.Bool(true),
						},
					},
					Cluster: cloudv1.ClusterTopology{
						TiFlash: cloudv1.TiFlash{
							Replicas: 1,
						},
					},
				},
				Status: cloudv1.ClusterStatus{
					DB: &cloudv1.DBStatus{
						PD:      &cloudv1.PDStatus{},
						TiDB:    &cloudv1.TiDBStatus{},
						TiKV:    &cloudv1.TiKVStatus{},
						TiFlash: &cloudv1.TiFlashStatus{},
					},
				},
			}
			tct.Spec.PD.SuspendAction = &v1alpha1.SuspendAction{
				SuspendStatefulSet: true,
			}

			tct.Status.PD = tc.status
			cluster.Status.DB.PD.Conditions = tc.conditions
			pdMixedDeployConfig := &cloudv1.MixedDeployPDWithTiKV{}
			pdMixedDeployConfig.SetAlwaysEnabled()
			resolver := &TiDBClusterStatusResolver{
				Target:              cluster,
				TiDBCluster:         tct,
				PDMixedDeployConfig: pdMixedDeployConfig,
			}
			result := resolver.computeComponentConditions(context.TODO(), cloudv1.ComponentPD, tc.nodes)
			g.Expect(len(result)).To(Equal(len(tc.expect)))
			for _, r := range result {
				e := meta.FindStatusCondition(tc.expect, r.Type)
				g.Expect(r.Type).To(Equal(e.Type))
				g.Expect(r.Status).To(Equal(e.Status))
				g.Expect(r.Reason).To(Equal(e.Reason))
				g.Expect(r.Message).To(Equal(e.Message))

			}

		})
	}
}
func TestComputeTiFlashComponentConditions(t *testing.T) {
	cases := map[string]struct {
		componentStatusNil bool
		conditions         []metav1.Condition
		status             v1alpha1.TiFlashStatus
		nodes              []corev1.Node
		expect             []metav1.Condition
	}{
		"componentStatus_nil_status_suspended_nodes_0": {
			componentStatusNil: true,
			status: v1alpha1.TiFlashStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionTrue,
					Reason:  "ResourcesSuspended",
					Message: "All Pods and nodes are suspended",
				},
			},
		},
		"componentStatus_nil_status_suspended_nodes_1": {
			componentStatusNil: true,
			status: v1alpha1.TiFlashStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "1 Nodes not suspended",
				},
			},
		},
		"componentStatus_nil_status_nosuspended_nodes_0": {
			componentStatusNil: true,
			status: v1alpha1.TiFlashStatus{
				Phase:       v1alpha1.NormalPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: nil,
			expect:     []metav1.Condition{},
		},
		"componentStatus_nil_status_nosuspended_nodes_1": {
			componentStatusNil: true,
			status: v1alpha1.TiFlashStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: &apps.StatefulSetStatus{},
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "Pods not suspended;1 Nodes not suspended",
				},
			},
		},
		"Condition_nil_status_suspended_nodes_0": {
			status: v1alpha1.TiFlashStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionTrue,
					Reason:  "ResourcesSuspended",
					Message: "All Pods and nodes are suspended",
				},
			},
		},
		"Condition_nil_status_suspended_nodes_1": {
			status: v1alpha1.TiFlashStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "1 Nodes not suspended",
				},
			},
		},
		"Condition_nil_status_nosuspended_nodes_0": {
			status: v1alpha1.TiFlashStatus{
				Phase:       v1alpha1.NormalPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: nil,
			expect:     []metav1.Condition{},
		},
		"Condition_nil_status_nosuspended_nodes_1": {
			status: v1alpha1.TiFlashStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: &apps.StatefulSetStatus{},
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: nil,
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "Pods not suspended;1 Nodes not suspended",
				},
			},
		},
		"Condition_empty_status_suspended_nodes_0": {
			status: v1alpha1.TiFlashStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: []metav1.Condition{},
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionTrue,
					Reason:  "ResourcesSuspended",
					Message: "All Pods and nodes are suspended",
				},
			},
		},
		"Condition_empty_status_suspended_nodes_1": {
			status: v1alpha1.TiFlashStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: []metav1.Condition{},
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "1 Nodes not suspended",
				},
			},
		},
		"Condition_empty_status_nosuspended_nodes_0": {
			status: v1alpha1.TiFlashStatus{
				Phase:       v1alpha1.NormalPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: []metav1.Condition{},
			expect:     []metav1.Condition{},
		},
		"Condition_empty_status_nosuspended_nodes_1": {
			status: v1alpha1.TiFlashStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: &apps.StatefulSetStatus{},
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: []metav1.Condition{},
			expect: []metav1.Condition{
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "Pods not suspended;1 Nodes not suspended",
				},
			},
		},
		"Condition_nonempty_status_suspended_nodes_0": {
			status: v1alpha1.TiFlashStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{},
			conditions: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
			expect: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionTrue,
					Reason:  "ResourcesSuspended",
					Message: "All Pods and nodes are suspended",
				},
			},
		},
		"Condition_nonempty_status_suspended_nodes_1": {
			status: v1alpha1.TiFlashStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
			expect: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "1 Nodes not suspended",
				},
			},
		},
		"Condition_nonempty_status_nosuspended_nodes_0": {
			status: v1alpha1.TiFlashStatus{
				Phase:       v1alpha1.NormalPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{},
			conditions: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
			expect: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
		},
		"Condition_nonempty_status_nosuspended_nodes_1": {
			status: v1alpha1.TiFlashStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: &apps.StatefulSetStatus{},
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
			expect: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
				{
					Type:    cloudv1.ComponentSuspended,
					Status:  metav1.ConditionFalse,
					Reason:  "ResourcesNotSuspended",
					Message: "Pods not suspended;1 Nodes not suspended",
				},
			},
		},
	}
	for name, tc := range cases {
		t.Run(name, func(t *testing.T) {
			g := NewGomegaWithT(t)
			tct := &v1alpha1.TidbCluster{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "tls-nightly",
					Namespace: "ns",
				},
				Spec: v1alpha1.TidbClusterSpec{
					PD: &v1alpha1.PDSpec{
						ComponentSpec: v1alpha1.ComponentSpec{
							Image: "pingcap/pd:nightly",
						},
						Replicas: 3,
					},
					TiKV:    &v1alpha1.TiKVSpec{},
					TiDB:    &v1alpha1.TiDBSpec{},
					TiFlash: &v1alpha1.TiFlashSpec{},
				},
				Status: v1alpha1.TidbClusterStatus{},
			}
			cluster := &cloudv1.Cluster{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "123",
					Namespace: "test",
					Labels:    map[string]string{"tags.tidbcloud.com/a": "aa", "tags.tidbcloud.com/b": "bb"},
				},
				Spec: cloudv1.ClusterSpec{
					SqlEndpoints: cloudv1.SqlEndpoints{
						Private: &cloudv1.Service{
							Enabled: pointer.Bool(true),
						},
					},
					Cluster: cloudv1.ClusterTopology{
						TiFlash: cloudv1.TiFlash{
							Replicas: 1,
						},
					},
				},
				Status: cloudv1.ClusterStatus{
					DB: &cloudv1.DBStatus{
						PD:      &cloudv1.PDStatus{},
						TiDB:    &cloudv1.TiDBStatus{},
						TiKV:    &cloudv1.TiKVStatus{},
						TiFlash: &cloudv1.TiFlashStatus{},
					},
				},
			}
			tct.Spec.TiFlash.SuspendAction = &v1alpha1.SuspendAction{
				SuspendStatefulSet: true,
			}

			tct.Status.TiFlash = tc.status
			cluster.Status.DB.TiFlash.Conditions = tc.conditions
			pdMixedDeployConfig := &cloudv1.MixedDeployPDWithTiKV{}
			pdMixedDeployConfig.SetAlwaysEnabled()
			resolver := &TiDBClusterStatusResolver{
				Target:              cluster,
				TiDBCluster:         tct,
				PDMixedDeployConfig: pdMixedDeployConfig,
			}
			result := resolver.computeComponentConditions(context.TODO(), cloudv1.ComponentTiFlash, tc.nodes)
			g.Expect(len(result)).To(Equal(len(tc.expect)))
			for _, r := range result {
				e := meta.FindStatusCondition(tc.expect, r.Type)
				g.Expect(r.Type).To(Equal(e.Type))
				g.Expect(r.Status).To(Equal(e.Status))
				g.Expect(r.Reason).To(Equal(e.Reason))
				g.Expect(r.Message).To(Equal(e.Message))

			}

		})
	}
}
func TestComputeBackupComponentConditions(t *testing.T) {
	cases := map[string]struct {
		conditions []metav1.Condition
		status     v1alpha1.TiKVStatus
		nodes      []corev1.Node
		expect     []metav1.Condition
	}{
		"Condition_nil_status_suspended_nodes_0": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: nil,
			expect:     []metav1.Condition{},
		},
		"Condition_nil_status_suspended_nodes_1": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: nil,
			expect:     []metav1.Condition{},
		},
		"Condition_nil_status_nosuspended_nodes_0": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.NormalPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: nil,
			expect:     []metav1.Condition{},
		},
		"Condition_nil_status_nosuspended_nodes_1": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: &apps.StatefulSetStatus{},
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: nil,
			expect:     []metav1.Condition{},
		},
		"Condition_empty_status_suspended_nodes_0": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: []metav1.Condition{},
			expect:     []metav1.Condition{},
		},
		"Condition_empty_status_suspended_nodes_1": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: []metav1.Condition{},
			expect:     []metav1.Condition{},
		},
		"Condition_empty_status_nosuspended_nodes_0": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.NormalPhase,
				StatefulSet: nil,
			},
			nodes:      []corev1.Node{},
			conditions: []metav1.Condition{},
			expect:     []metav1.Condition{},
		},
		"Condition_empty_status_nosuspended_nodes_1": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: &apps.StatefulSetStatus{},
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: []metav1.Condition{},
			expect:     []metav1.Condition{},
		},
		"Condition_nonempty_status_suspended_nodes_0": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{},
			conditions: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
			expect: []metav1.Condition{},
		},
		"Condition_nonempty_status_suspended_nodes_1": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
			expect: []metav1.Condition{},
		},
		"Condition_nonempty_status_nosuspended_nodes_0": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.NormalPhase,
				StatefulSet: nil,
			},
			nodes: []corev1.Node{},
			conditions: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
			expect: []metav1.Condition{},
		},
		"Condition_nonempty_status_nosuspended_nodes_1": {
			status: v1alpha1.TiKVStatus{
				Phase:       v1alpha1.SuspendPhase,
				StatefulSet: &apps.StatefulSetStatus{},
			},
			nodes: []corev1.Node{
				{
					ObjectMeta: metav1.ObjectMeta{
						Name:      "tls-nightly",
						Namespace: "ns",
					},
				},
			},
			conditions: []metav1.Condition{
				{
					Type:    "test",
					Status:  metav1.ConditionFalse,
					Reason:  "test",
					Message: "test",
				},
			},
			expect: []metav1.Condition{},
		},
	}
	for name, tc := range cases {
		t.Run(name, func(t *testing.T) {
			g := NewGomegaWithT(t)
			tct := &v1alpha1.TidbCluster{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "tls-nightly",
					Namespace: "ns",
				},
				Spec: v1alpha1.TidbClusterSpec{
					PD: &v1alpha1.PDSpec{
						ComponentSpec: v1alpha1.ComponentSpec{
							Image: "pingcap/pd:nightly",
						},
						Replicas: 3,
					},
					TiKV: &v1alpha1.TiKVSpec{},
					TiDB: &v1alpha1.TiDBSpec{},
				},
				Status: v1alpha1.TidbClusterStatus{},
			}
			cluster := &cloudv1.Cluster{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "123",
					Namespace: "test",
					Labels:    map[string]string{"tags.tidbcloud.com/a": "aa", "tags.tidbcloud.com/b": "bb"},
				},
				Spec: cloudv1.ClusterSpec{
					SqlEndpoints: cloudv1.SqlEndpoints{
						Private: &cloudv1.Service{
							Enabled: pointer.Bool(true),
						},
					},
					Cluster: cloudv1.ClusterTopology{
						TiFlash: cloudv1.TiFlash{
							Replicas: 1,
						},
					},
				},
				Status: cloudv1.ClusterStatus{
					DB: &cloudv1.DBStatus{
						PD:      &cloudv1.PDStatus{},
						TiDB:    &cloudv1.TiDBStatus{},
						TiKV:    &cloudv1.TiKVStatus{},
						TiFlash: &cloudv1.TiFlashStatus{},
					},
				},
			}
			tct.Spec.TiKV.SuspendAction = &v1alpha1.SuspendAction{
				SuspendStatefulSet: true,
			}

			tct.Status.TiKV = tc.status
			cluster.Status.DB.TiKV.Conditions = tc.conditions
			pdMixedDeployConfig := &cloudv1.MixedDeployPDWithTiKV{}
			pdMixedDeployConfig.SetAlwaysEnabled()
			resolver := &TiDBClusterStatusResolver{
				Target:              cluster,
				TiDBCluster:         tct,
				PDMixedDeployConfig: pdMixedDeployConfig,
			}
			result := resolver.computeComponentConditions(context.TODO(), cloudv1.ComponentBackup, tc.nodes)
			g.Expect(len(result)).To(Equal(len(tc.expect)))
			for _, r := range result {
				e := meta.FindStatusCondition(tc.expect, r.Type)
				g.Expect(r.Type).To(Equal(e.Type))
				g.Expect(r.Status).To(Equal(e.Status))
				g.Expect(r.Reason).To(Equal(e.Reason))
				g.Expect(r.Message).To(Equal(e.Message))

			}

		})
	}
}
