Skip to content

Commit

Permalink
gp init cluster:Added functional tests for expansion support
Browse files Browse the repository at this point in the history
This commit adds functional tests for expansion support changes pushed in the PR

Below changes are included:

init_cluster_config_validation_test.go - This contains tests related to the input expansion config validations, new functions GetDefaultExpansionConfig is added to create default config with expansion support along with config validaiton related tests

init_cluster_db_validation_test.go - This contains tests related to the database configuration checks after the cluster is successfully initialized with expansion support, it also included validation for spread and group mirroring

init_cluster_test.go: This includes expansion validation by passing config file with different file formats

init_cluster_suite_test.go: In this file check has been added to fetch the hostname
  • Loading branch information
srividyaky committed May 15, 2024
1 parent 1da9ac3 commit 88d8d68
Show file tree
Hide file tree
Showing 4 changed files with 994 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,295 @@ func TestInputFileValidation(t *testing.T) {
// t.Errorf("got %q, want %q", result.OutputMsg, expectedOut)
// }
// })

t.Run("validate expansion with no coordinator details", func(t *testing.T) {
configFile := testutils.GetTempFile(t, "config.json")
config := GetDefaultExpansionConfig(t, true)

configMap := config.AllSettings()
delete(configMap, "coordinator")

encodedConfig, err := json.MarshalIndent(configMap, "", " ")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
err = os.WriteFile(configFile, encodedConfig, 0777)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

result, err := testutils.RunInitCluster(configFile)
if e, ok := err.(*exec.ExitError); !ok || e.ExitCode() != 1 {
t.Fatalf("got %v, want exit status 1", err)
}

expectedOut := "[ERROR]:-no coordinator segment provided in input config file"
if !strings.Contains(result.OutputMsg, expectedOut) {
t.Errorf("got %q, want %q", result.OutputMsg, expectedOut)
}
})

t.Run("verify expansion when primary data directory is not provided", func(t *testing.T) {
configFile := testutils.GetTempFile(t, "config.json")
config := GetDefaultExpansionConfig(t, true)

config.Set("primary-data-directories", []string{})
if err := config.WriteConfigAs(configFile); err != nil {
t.Fatalf("failed to write config to file: %v", err)
}

result, err := testutils.RunInitCluster(configFile)
if e, ok := err.(*exec.ExitError); !ok || e.ExitCode() != 1 {
t.Fatalf("got %v, want exit status 1", err)
}

expectedOut := "[ERROR]:-primary-data-directories not specified. Please specify primary-data-directories to continue"
if !strings.Contains(result.OutputMsg, expectedOut) {
t.Errorf("got %q, want %q", result.OutputMsg, expectedOut)
}
})

t.Run("verify expansion with invalid primary base port is provided", func(t *testing.T) {
configFile := testutils.GetTempFile(t, "config.json")
config := GetDefaultExpansionConfig(t, true)

config.Set("primary-base-port", 0)
if err := config.WriteConfigAs(configFile); err != nil {
t.Fatalf("failed to write config to file: %v", err)
}

result, err := testutils.RunInitCluster(configFile)
if e, ok := err.(*exec.ExitError); !ok || e.ExitCode() != 1 {
t.Fatalf("got %v, want exit status 1", err)
}

expectedOut := "[ERROR]:-invalid primary-base-port value provided: 0"
if !strings.Contains(result.OutputMsg, expectedOut) {
t.Errorf("got %q, want %q", result.OutputMsg, expectedOut)
}
})

t.Run("verify expansion when empty hostlist is provided", func(t *testing.T) {
configFile := testutils.GetTempFile(t, "config.json")
config := GetDefaultExpansionConfig(t, true)

config.Set("hostlist", []string{})
if err := config.WriteConfigAs(configFile); err != nil {
t.Fatalf("failed to write config to file: %v", err)
}

result, err := testutils.RunInitCluster(configFile)
if e, ok := err.(*exec.ExitError); !ok || e.ExitCode() != 1 {
t.Fatalf("got %v, want exit status 1", err)
}

expectedOut := "[ERROR]:-hostlist not specified. Please specify hostlist to continue"
if !strings.Contains(result.OutputMsg, expectedOut) {
t.Errorf("got %q, want %q", result.OutputMsg, expectedOut)
}
})

t.Run("verify expansion when empty string is provided for mirror data directory", func(t *testing.T) {
configFile := testutils.GetTempFile(t, "config.json")
config := GetDefaultExpansionConfig(t)

mirrorDataDirectories := config.GetStringSlice("mirror-data-directories")
if len(mirrorDataDirectories) > 0 {
mirrorDataDirectories[0] = ""
}
if err := config.WriteConfigAs(configFile); err != nil {
t.Fatalf("failed to write config to file: %v", err)
}

result, err := testutils.RunInitCluster(configFile)
if e, ok := err.(*exec.ExitError); !ok || e.ExitCode() != 1 {
t.Fatalf("got %v, want exit status 1", err)
}

expectedOut := "[ERROR]:-empty mirror-data-directories entry provided, please provide valid directory"
if !strings.Contains(result.OutputMsg, expectedOut) {
t.Errorf("got %q, want %q", result.OutputMsg, expectedOut)
}
})

t.Run("verify expansion when invalid mirror base port is provided", func(t *testing.T) {
configFile := testutils.GetTempFile(t, "config.json")
config := GetDefaultExpansionConfig(t)

config.Set("mirror-base-port", 0)
if err := config.WriteConfigAs(configFile); err != nil {
t.Fatalf("failed to write config to file: %v", err)
}

result, err := testutils.RunInitCluster(configFile)
if e, ok := err.(*exec.ExitError); !ok || e.ExitCode() != 1 {
t.Fatalf("got %v, want exit status 1", err)
}

expectedOut := "[ERROR]:-invalid mirror-base-port value provided: 0"
if !strings.Contains(result.OutputMsg, expectedOut) {
t.Errorf("got %q, want %q", result.OutputMsg, expectedOut)
}
})

t.Run("verify expansion with duplicate ports for primary and mirror", func(t *testing.T) {
configFile := testutils.GetTempFile(t, "config.json")
config := GetDefaultExpansionConfig(t)

config.Set("primary-base-port", 7002)
config.Set("mirror-base-port", 7002)
if err := config.WriteConfigAs(configFile); err != nil {
t.Fatalf("failed to write config to file: %v", err)
}

result, err := testutils.RunInitCluster(configFile)
if e, ok := err.(*exec.ExitError); !ok || e.ExitCode() != 1 {
t.Fatalf("got %v, want exit status 1", err)
}

expectedOut := "[ERROR]:-primary-base-port and mirror-base-port value cannot be same. Please provide different values"
if !strings.Contains(result.OutputMsg, expectedOut) {
t.Errorf("got %q, want %q", result.OutputMsg, expectedOut)
}
})

t.Run("verify spread mirroing by providing hosts count less than or equal to primary segment count", func(t *testing.T) {
configFile := testutils.GetTempFile(t, "config.json")
config := GetDefaultExpansionConfig(t)

config.Set("mirroring-type", "spread")
config.Set("primary-data-directories", append(config.GetStringSlice("primary-data-directories"), "/tmp/additionalprimary"))
config.Set("mirror-data-directories", append(config.GetStringSlice("mirror-data-directories"), "/tmp/additionalmirror"))
if err := config.WriteConfigAs(configFile); err != nil {
t.Fatalf("failed to write config to file: %v", err)
}

result, err := testutils.RunInitCluster(configFile)
if e, ok := err.(*exec.ExitError); !ok || e.ExitCode() != 1 {
t.Fatalf("got %v, want exit status 1", err)
}

expectedOut := "[ERROR]:-To enable spread mirroring, number of hosts should be more than number of primary segments per host"
if !strings.Contains(result.OutputMsg, expectedOut) {
t.Errorf("got %q, want %q", result.OutputMsg, expectedOut)
}
})

t.Run("verify expansion with mismatched Number of primary and mirror directories", func(t *testing.T) {
configFile := testutils.GetTempFile(t, "config.json")
config := GetDefaultExpansionConfig(t)

primaryDirs := config.GetStringSlice("primary-data-directories")
primaryDirs = append(primaryDirs, "/tmp/demo/additionalprimary")
config.Set("primary-data-directories", primaryDirs)
if err := config.WriteConfigAs(configFile); err != nil {
t.Fatalf("failed to write updated config to file: %v", err)
}

result, err := testutils.RunInitCluster(configFile)
if e, ok := err.(*exec.ExitError); !ok || e.ExitCode() != 1 {
t.Fatalf("got %v, want exit status 1", err)
}

expectedOut := "[ERROR]:-number of primary-data-directories should be equal to number of mirror-data-directories"
if !strings.Contains(result.OutputMsg, expectedOut) {
t.Errorf("got %q, want %q", result.OutputMsg, expectedOut)
}
})

t.Run("verify expansion with invalid mirror type", func(t *testing.T) {
configFile := testutils.GetTempFile(t, "config.json")
config := GetDefaultExpansionConfig(t)

config.Set("mirroring-type", "test_mirror")
if err := config.WriteConfigAs(configFile); err != nil {
t.Fatalf("failed to write config to file: %v", err)
}

result, err := testutils.RunInitCluster(configFile)
if e, ok := err.(*exec.ExitError); !ok || e.ExitCode() != 1 {
t.Fatalf("got %v, want exit status 1", err)
}

expectedOut := "[ERROR]:-invalid mirroring-Type: test_mirror. Valid options are 'group' and 'spread'"
if !strings.Contains(result.OutputMsg, expectedOut) {
t.Errorf("got %q, want %q", result.OutputMsg, expectedOut)
}
})

t.Run("verify expansion without mirror support", func(t *testing.T) {
configFile := testutils.GetTempFile(t, "config.json")
config := GetDefaultExpansionConfig(t, true)
if err := config.WriteConfigAs(configFile); err != nil {
t.Fatalf("failed to write config to file: %v", err)
}

result, err := testutils.RunInitCluster(configFile)
if err != nil {
t.Fatalf("Error while intializing cluster: %#v", err)
}

expectedWarning := "[WARNING]:-No mirror-data-directories provided. Will create mirror-less cluster"
if !strings.Contains(result.OutputMsg, expectedWarning) {
t.Fatalf("got %q, want %q", result.OutputMsg, expectedWarning)
}

expectedOut := "[INFO]:-Cluster initialized successfully"
if !strings.Contains(result.OutputMsg, expectedOut) {
t.Fatalf("got %q, want %q", result.OutputMsg, expectedOut)
}

_, err = testutils.DeleteCluster()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

})
t.Run("verify expansion with mirror support", func(t *testing.T) {
configFile := testutils.GetTempFile(t, "config.json")
config := GetDefaultExpansionConfig(t)
if err := config.WriteConfigAs(configFile); err != nil {
t.Fatalf("failed to write config to file: %v", err)
}

result, err := testutils.RunInitCluster(configFile)
if err != nil {
t.Fatalf("Error while intializing cluster: %#v", err)
}

expectedOut := "[INFO]:-Cluster initialized successfully"
if !strings.Contains(result.OutputMsg, expectedOut) {
t.Fatalf("got %q, want %q", result.OutputMsg, expectedOut)
}

_, err = testutils.DeleteCluster()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

})

t.Run("when segment-array is also specified along with the expansion parameter", func(t *testing.T) {
configFile := testutils.GetTempFile(t, "config.json")
config := GetDefaultExpansionConfig(t)

segmentArray := []interface{}{map[string]interface{}{}}
config.Set("segment-array", segmentArray)
if err := config.WriteConfigAs(configFile); err != nil {
t.Fatalf("failed to write config to file: %v", err)
}

result, err := testutils.RunInitCluster(configFile)
if e, ok := err.(*exec.ExitError); !ok || e.ExitCode() != 1 {
t.Fatalf("got %v, want exit status 1", err)
}

expectedOut := "[ERROR]:-cannot specify segments-array and primary-base-directories together"
if !strings.Contains(result.OutputMsg, expectedOut) {
t.Errorf("got %q, want %q", result.OutputMsg, expectedOut)
}

})
}

func GetDefaultConfig(t *testing.T, mirrorless ...bool) *viper.Viper {
Expand All @@ -696,7 +985,7 @@ func GetDefaultConfig(t *testing.T, mirrorless ...bool) *viper.Viper {
if err != nil {
t.Fatalf("unexpected error: %#v", err)
}

hostList := testutils.GetHostListFromFile(*hostfile)
coordinatorHost := hostList[0]
instance.Set("coordinator", cli.Segment{
Port: testutils.DEFAULT_COORDINATOR_PORT,
Expand Down Expand Up @@ -798,3 +1087,55 @@ func SetConfigKey(t *testing.T, filename string, key string, value interface{},
t.Fatalf("unexpected error: %v", err)
}
}
func GetDefaultExpansionConfig(t *testing.T, mirrorless ...bool) *viper.Viper {
t.Helper()
instance := viper.New()
instance.SetConfigFile("sample_init_config.json")
instance.SetDefault("common-config", make(map[string]string))
instance.SetDefault("coordinator-config", make(map[string]string))
instance.SetDefault("segment-config", make(map[string]string))

err := instance.ReadInConfig()
if err != nil {
t.Fatalf("unexpected error: %#v", err)
}

hostList := testutils.GetHostListFromFile(*hostfile)

instance.Set("coordinator", cli.Segment{
Port: testutils.DEFAULT_COORDINATOR_PORT,
Hostname: hostList[0],
Address: hostList[0],
DataDirectory: coordinatorDatadir,
})
//creates mirrorless config when mirrorless param is passed
if len(mirrorless) == 1 && mirrorless[0] {
primaryDataDirectories := make([]string, 0)
for i := 1; i <= 2; i++ {
primaryDataDirectories = append(primaryDataDirectories, fmt.Sprintf("/tmp/primary%d", i))
}
instance.Set("primary-base-port", testutils.DEFAULT_COORDINATOR_PORT+2)
instance.Set("primary-data-directories", primaryDataDirectories)

} else { //by default creates both primary and mirror
primaryDataDirectories := make([]string, 0)
mirrorDataDirectories := make([]string, 0)

for i := 1; i <= 2; i++ {
primaryDataDirectories = append(primaryDataDirectories, fmt.Sprintf("/tmp/primary%d", i))
mirrorDataDirectories = append(mirrorDataDirectories, fmt.Sprintf("/tmp/mirror%d", i))
}

instance.Set("primary-base-port", testutils.DEFAULT_COORDINATOR_PORT+2)
instance.Set("primary-data-directories", primaryDataDirectories)
instance.Set("mirror-base-port", testutils.DEFAULT_COORDINATOR_PORT+1002)
instance.Set("mirroring-type", "group")
instance.Set("mirror-data-directories", mirrorDataDirectories)
}
if len(hostList) == 1 {
instance.Set("hostlist", hostList)
} else {
instance.Set("hostlist", hostList[1:])
}
return instance
}
Loading

0 comments on commit 88d8d68

Please sign in to comment.