Skip to content

Commit

Permalink
feat: test cases of new config management
Browse files Browse the repository at this point in the history
  • Loading branch information
vinitparekh17 committed Nov 15, 2024
1 parent 38d3e5a commit cd1bfc6
Show file tree
Hide file tree
Showing 3 changed files with 370 additions and 171 deletions.
72 changes: 36 additions & 36 deletions config/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,25 +35,25 @@ func (p *ConfigParser) ParseFromFile(filename string) error {
return processConfigData(scanner, p)
}

// processConfigData reads the configuration data line by line and stores it in the ConfigParser
func processConfigData(scanner *bufio.Scanner, p *ConfigParser) error {
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" || strings.HasPrefix(line, "#") {
continue
}
// ParseFromStdin reads the configuration data from stdin
func (p *ConfigParser) ParseFromStdin() error {
scanner := bufio.NewScanner(os.Stdin)
return processConfigData(scanner, p)
}

parts := strings.SplitN(line, "=", 2)
if len(parts) != 2 {
continue
}
// ParseDefaults populates a struct with default values based on struct tag `default`
func (p *ConfigParser) ParseDefaults(cfg interface{}) error {
val := reflect.ValueOf(cfg)
if val.Kind() != reflect.Ptr || val.IsNil() {
return fmt.Errorf("config must be a non-nil pointer to a struct")
}

key := strings.TrimSpace(parts[0])
value := strings.Trim(strings.TrimSpace(parts[1]), "\"")
p.store[key] = value
val = val.Elem()
if val.Kind() != reflect.Struct {
return fmt.Errorf("config must be a pointer to a struct")
}

return scanner.Err()
return p.unmarshalStruct(val, "")
}

// Loadconfig populates a struct with configuration values based on struct tags
Expand All @@ -79,6 +79,27 @@ func (p *ConfigParser) Loadconfig(cfg interface{}) error {
return nil
}

// processConfigData reads the configuration data line by line and stores it in the ConfigParser
func processConfigData(scanner *bufio.Scanner, p *ConfigParser) error {
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" || strings.HasPrefix(line, "#") {
continue
}

parts := strings.SplitN(line, "=", 2)
if len(parts) != 2 {
return fmt.Errorf("invalid config line: %s", line)
}

key := strings.TrimSpace(parts[0])
value := strings.Trim(strings.TrimSpace(parts[1]), "\"")
p.store[key] = value
}

return scanner.Err()
}

// unmarshalStruct handles the recursive struct parsing.
func (p *ConfigParser) unmarshalStruct(val reflect.Value, prefix string) error {
typ := val.Type()
Expand Down Expand Up @@ -203,24 +224,3 @@ func setField(field reflect.Value, value string) error {

return nil
}

// perse from stdin reads the configuration data from stdin
func (p *ConfigParser) ParseFromStdin() error {
scanner := bufio.NewScanner(os.Stdin)
return processConfigData(scanner, p)
}

// ParseDefaults populates a struct with default values, will be used in case the config file is missing
func (p *ConfigParser) ParseDefaults(cfg interface{}) error {
val := reflect.ValueOf(cfg)
if val.Kind() != reflect.Ptr || val.IsNil() {
return fmt.Errorf("config must be a non-nil pointer to a struct")
}

val = val.Elem()
if val.Kind() != reflect.Struct {
return fmt.Errorf("config must be a pointer to a struct")
}

return p.unmarshalStruct(val, "")
}
232 changes: 97 additions & 135 deletions integration_tests/config/config_test.go
Original file line number Diff line number Diff line change
@@ -1,136 +1,98 @@
package commands

import "testing"

// import (
// "os"
// "path/filepath"
// "testing"

// "github.com/dicedb/dice/config"
// )

// // scenario 1: Create a config file if the directory is provided (-o flag)
// func TestSetupConfig_CreateAndLoadDefault(t *testing.T) {
// config.ResetConfig()
// tempDir := t.TempDir()

// // Simulate the flag: -o=<dir_path>
// config.CustomConfigFilePath = tempDir
// config.SetupConfig()

// if config.DiceConfig.AsyncServer.Addr != config.DefaultHost {
// t.Fatalf("Expected server addr to be '%s', got '%s'", config.DefaultHost, config.DiceConfig.AsyncServer.Addr)
// }
// if config.DiceConfig.AsyncServer.Port != config.DefaultPort {
// t.Fatalf("Expected server port to be %d, got %d", config.DefaultPort, config.DiceConfig.AsyncServer.Port)
// }
// }

// // scenario 2: Load default config if no config file or directory is provided
// func TestSetupConfig_DefaultConfig(t *testing.T) {
// // Simulate no flags being set (default config scenario)
// config.ResetConfig()
// config.CustomConfigFilePath = ""
// config.FileLocation = filepath.Join(config.DefaultConfigFilePath, config.DefaultConfigName)

// // Verify that the configuration was loaded from the default values
// if config.DiceConfig.AsyncServer.Addr != config.DefaultHost {
// t.Fatalf("Expected server addr to be '%s', got '%s'", config.DefaultHost, config.DiceConfig.AsyncServer.Addr) // 127.0.0.1
// }
// if config.DiceConfig.AsyncServer.Port != config.DefaultPort {
// t.Fatalf("Expected server port to be %d, got %d", 8739, config.DiceConfig.AsyncServer.Port)
// }
// }

// // scenario 3: Config file is present but not well-structured (Malformed)
// func TestSetupConfig_InvalidConfigFile(t *testing.T) {
// config.DiceConfig = nil
// tempDir := t.TempDir()
// configFilePath := filepath.Join(tempDir, "dice.toml")

// content := `
// [asyncserver]
// addr = 127.0.0.1 // Missing quotes around string value
// port = abc // Invalid integer
// `
// if err := os.WriteFile(configFilePath, []byte(content), 0666); err != nil {
// t.Fatalf("Failed to create invalid test config file: %v", err)
// }

// // Simulate the flag: -c=<configfile_path>
// config.CustomConfigFilePath = ""
// config.FileLocation = configFilePath

// config.SetupConfig()

// if config.DiceConfig.AsyncServer.Addr != config.DefaultHost {
// t.Fatalf("Expected server addr to be '%s' after unmarshal error, got '%s'", config.DefaultHost, config.DiceConfig.AsyncServer.Addr)
// }
// if config.DiceConfig.AsyncServer.Port != config.DefaultPort {
// t.Fatalf("Expected server port to be %d after unmarshal error, got %d", config.DefaultPort, config.DiceConfig.AsyncServer.Port)
// }
// }

// // scenario 4: Config file is present with partial content
// func TestSetupConfig_PartialConfigFile(t *testing.T) {
// tempDir := t.TempDir()
// configFilePath := filepath.Join(tempDir, "dice.toml")

// content := `
// [asyncserver]
// addr = "127.0.0.1"
// `
// if err := os.WriteFile(configFilePath, []byte(content), 0666); err != nil {
// t.Fatalf("Failed to create partial test config file: %v", err)
// }

// // Simulate the flag: -c=<configfile_path>
// config.CustomConfigFilePath = ""
// config.FileLocation = configFilePath

// config.SetupConfig()

// t.Log(config.DiceConfig.AsyncServer.Port)

// if config.DiceConfig.AsyncServer.Addr != "127.0.0.1" {
// t.Fatalf("Expected server addr to be '127.0.0.1', got '%s'", config.DiceConfig.AsyncServer.Addr)
// }
// if config.DiceConfig.AsyncServer.Port != config.DefaultPort {
// t.Fatalf("Expected server port to be %d (default), got %d", config.DefaultPort, config.DiceConfig.AsyncServer.Port)
// }
// }

// // scenario 5: Load config from the provided file path
// func TestSetupConfig_LoadFromFile(t *testing.T) {
// config.ResetConfig()
// tempDir := t.TempDir()
// configFilePath := filepath.Join(tempDir, "dice.toml")

// content := `
// [asyncserver]
// addr = "127.0.0.1"
// port = 8739
// `
// if err := os.WriteFile(configFilePath, []byte(content), 0666); err != nil {
// t.Fatalf("Failed to write test config file: %v", err)
// }

// // Simulate the flag: -c=<configfile_path>
// config.CustomConfigFilePath = ""
// config.FileLocation = configFilePath

// config.SetupConfig()

// if config.DiceConfig.AsyncServer.Addr != "127.0.0.1" {
// t.Fatalf("Expected server addr to be '127.0.0.1', got '%s'", config.DiceConfig.AsyncServer.Addr)
// }
// if config.DiceConfig.AsyncServer.Port != 8739 {
// t.Fatalf("Expected server port to be 8374, got %d", config.DiceConfig.AsyncServer.Port)
// }

// }

func Test_demo(t *testing.T) {
t.Log("todo implement new tests")
package config_test

import (
"os"
"path/filepath"
"testing"

"github.com/dicedb/dice/config"
)

const configFileName = "dicedb.conf"

// TestCreateConfigFile_FileExists tests the scenario when config file already exists
func TestCreateConfigFile_FileExists(t *testing.T) {
tempDir := t.TempDir()
configPath := filepath.Join(tempDir, configFileName)

if err := os.WriteFile(configPath, []byte("test config"), 0644); err != nil {
t.Fatalf("Failed to create test config file: %v", err)
}

config.CreateConfigFile(configPath)

content, err := os.ReadFile(configPath)
if err != nil {
t.Fatalf("Failed to read config file: %v", err)
}

if string(content) != "test config" {
t.Error("Config file content was modified when it should have been preserved")
}
}

// TestCreateConfigFile_NewFile tests creating a new config file
func TestCreateConfigFile_NewFile(t *testing.T) {
tempDir := t.TempDir()
configPath := filepath.Join(tempDir, configFileName)
config.CreateConfigFile(configPath)

if _, err := os.Stat(configPath); os.IsNotExist(err) {
t.Error("Config file was not created")
}

content, err := os.ReadFile(configPath)
if err != nil {
t.Fatalf("Failed to read created config file: %v", err)
}

if len(content) == 0 {
t.Error("Created config file is empty")
}
}

// TestCreateConfigFile_InvalidPath tests creation with an invalid file path
func TestCreateConfigFile_InvalidPath(t *testing.T) {
configPath := "/nonexistent/directory/dicedb.conf"
config.CreateConfigFile(configPath)

if _, err := os.Stat(configPath); !os.IsNotExist(err) {
t.Error("Config file should not have been created at invalid path")
}
}

func TestCreateConfigFile_NoPermission(t *testing.T) {
if os.Getuid() == 0 {
t.Skip("Skipping test when running as root")
}

tempDir := t.TempDir()
err := os.Chmod(tempDir, 0555) // read + execute only
if err != nil {
t.Fatalf("Failed to change directory permissions: %v", err)
}
defer os.Chmod(tempDir, 0755) // restore permissions

configPath := filepath.Join(tempDir, configFileName)
config.CreateConfigFile(configPath)

if _, err := os.Stat(configPath); !os.IsNotExist(err) {
t.Error("Config file should not have been created without permissions")
}
}

// TestCreateConfigFile_ExistingDirectory tests creation in existing directory
func TestCreateConfigFile_ExistingDirectory(t *testing.T) {
tempDir := t.TempDir()
configDir := filepath.Join(tempDir, "config")
if err := os.MkdirAll(configDir, 0755); err != nil {
t.Fatalf("Failed to create config directory: %v", err)
}

configPath := filepath.Join(configDir, configFileName)
config.CreateConfigFile(configPath)

if _, err := os.Stat(configPath); os.IsNotExist(err) {
t.Error("Config file was not created in existing directory")
}
}
Loading

0 comments on commit cd1bfc6

Please sign in to comment.