package util

import (
	"testing"

	. "github.com/onsi/gomega"
)

func TestGetTypeIOPSThroughputFromClassName(t *testing.T) {
	g := NewGomegaWithT(t)

	type Case struct {
		name               string
		expectedType       string
		expectedIOPS       uint32
		expectedThroughput uint32
	}

	validStorageClassNames := []Case{
		{
			name:               "tikv-gp2",
			expectedType:       "gp2",
			expectedIOPS:       0,
			expectedThroughput: 0,
		},
		{
			name:               "tikv-pd-ssd",
			expectedType:       "pd-ssd",
			expectedIOPS:       0,
			expectedThroughput: 0,
		},
		{
			name:               "tiflash-gp3-0-2",
			expectedType:       "gp3",
			expectedIOPS:       0,
			expectedThroughput: 2,
		},
		{
			name:               "tidb-io2-20-whatever",
			expectedType:       "io2",
			expectedIOPS:       20,
			expectedThroughput: 0,
		},
		{
			name:               "mysql-io1-0-100",
			expectedType:       "io1",
			expectedIOPS:       0,
			expectedThroughput: 0,
		},
		{
			name:               "tikv-premiumv2-1000-800",
			expectedType:       "premiumv2",
			expectedIOPS:       1000,
			expectedThroughput: 800,
		},
		{
			name:               "tikv-ultrassd-1000-800",
			expectedType:       "ultrassd",
			expectedIOPS:       1000,
			expectedThroughput: 800,
		},
		{
			name:               "tikv-gp3-8000-594-906324658258-key-1c33ece5-b50e-4728-bbae-0b4bf0b24401",
			expectedType:       "gp3",
			expectedIOPS:       8000,
			expectedThroughput: 594,
		},
	}

	for _, c := range validStorageClassNames {
		volumeType, iops, throughput := GetTypeIOPSThroughputFromClassName(c.name)
		g.Expect(volumeType).To(Equal(c.expectedType))
		g.Expect(iops).To(Equal(c.expectedIOPS))
		g.Expect(throughput).To(Equal(c.expectedThroughput))
	}

	invalidStorageClassNames := []string{
		"tikv",
		"tikv-pd-ssd-3-4",
		"tikv-pd-ssd-3",
		"tikv-gp2-100-100",
		"tikv-gp3",
		"tikv-gp3-xx-100",
		"tikv-io2-xx-100",
		"tikv-gp4-100-100",
		"tikv-gp3-100-x",
		"tikv-gp6-8000-594-906324658258-key-1c33ece5-b50e-4728-bbae-0b4bf0b24401",
	}

	for _, name := range invalidStorageClassNames {
		volumeType, iops, throughput := GetTypeIOPSThroughputFromClassName(name)
		g.Expect(volumeType).To(Equal(""))
		g.Expect(iops).To(Equal(uint32(0)))
		g.Expect(throughput).To(Equal(uint32(0)))
	}
}

func TestGCPHyperdiskPerformanceChanged(t *testing.T) {
	tests := []struct {
		name    string
		current string
		desired string
		want    bool
	}{
		{name: "IOPS changed", current: "tikv-hyperdisk-balanced-3000-140", desired: "tikv-hyperdisk-balanced-6000-140", want: true},
		{name: "throughput changed", current: "tikv-hyperdisk-balanced-3000-140", desired: "tikv-hyperdisk-balanced-3000-200", want: true},
		{name: "unchanged", current: "tikv-hyperdisk-balanced-3000-140", desired: "tikv-hyperdisk-balanced-3000-140"},
		{name: "new Hyperdisk", desired: "tikv-hyperdisk-balanced-3000-140"},
		{name: "volume type changed", current: "tikv-pd-ssd", desired: "tikv-hyperdisk-balanced-3000-140"},
		{name: "invalid desired class", current: "tikv-hyperdisk-balanced-3000-140", desired: "invalid"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := GCPHyperdiskPerformanceChanged(tt.current, tt.desired); got != tt.want {
				t.Fatalf("GCPHyperdiskPerformanceChanged(%q, %q) = %v, want %v", tt.current, tt.desired, got, tt.want)
			}
		})
	}
}
