473 lines
11 KiB
Go
473 lines
11 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestEncryptDecryptCDK(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
original string
|
|
}{
|
|
{
|
|
name: "Empty CDK",
|
|
original: "",
|
|
},
|
|
{
|
|
name: "Simple CDK",
|
|
original: "test123",
|
|
},
|
|
{
|
|
name: "Complex CDK",
|
|
original: "ABC123-DEF456-GHI789",
|
|
},
|
|
{
|
|
name: "CDK with special characters",
|
|
original: "test@#$%^&*()_+-={}[]|\\:;\"'<>?,./",
|
|
},
|
|
{
|
|
name: "Long CDK",
|
|
original: "this-is-a-very-long-cdk-key-that-should-still-work-properly-with-encryption-and-decryption",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Test encryption
|
|
encrypted := encryptCDK(tt.original)
|
|
|
|
// Empty string should remain empty
|
|
if tt.original == "" {
|
|
if encrypted != "" {
|
|
t.Errorf("Expected empty string for empty input, got %s", encrypted)
|
|
}
|
|
return
|
|
}
|
|
|
|
// Encrypted should be different from original (unless original is empty)
|
|
if encrypted == tt.original {
|
|
t.Errorf("Encrypted CDK should be different from original")
|
|
}
|
|
|
|
// Test decryption
|
|
decrypted, err := decryptCDK(encrypted)
|
|
if err != nil {
|
|
t.Errorf("Decryption failed: %v", err)
|
|
}
|
|
|
|
// Decrypted should match original
|
|
if decrypted != tt.original {
|
|
t.Errorf("Expected %s, got %s", tt.original, decrypted)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConfigSetGetCDK(t *testing.T) {
|
|
config := &Config{}
|
|
|
|
testCDK := "test-cdk-123"
|
|
|
|
// Set CDK (should encrypt)
|
|
config.SetCDK(testCDK)
|
|
|
|
// CDK field should be encrypted (different from original)
|
|
if config.CDK == testCDK {
|
|
t.Errorf("CDK should be encrypted in config")
|
|
}
|
|
|
|
// Get CDK (should decrypt)
|
|
retrievedCDK, err := config.GetCDK()
|
|
if err != nil {
|
|
t.Errorf("Failed to get CDK: %v", err)
|
|
}
|
|
|
|
if retrievedCDK != testCDK {
|
|
t.Errorf("Expected %s, got %s", testCDK, retrievedCDK)
|
|
}
|
|
}
|
|
|
|
func TestDecryptInvalidCDK(t *testing.T) {
|
|
// Test with invalid base64
|
|
_, err := decryptCDK("invalid-base64!")
|
|
if err == nil {
|
|
t.Errorf("Expected error for invalid base64")
|
|
}
|
|
}
|
|
|
|
func TestConfigManagerLoadSave(t *testing.T) {
|
|
// Create temporary directory for test
|
|
tempDir := t.TempDir()
|
|
|
|
// Create config manager with temp path
|
|
cm := &DefaultConfigManager{
|
|
configPath: filepath.Join(tempDir, "test-config.yaml"),
|
|
}
|
|
|
|
// Test loading non-existent config (should create default)
|
|
config, err := cm.Load()
|
|
if err != nil {
|
|
t.Errorf("Failed to load config: %v", err)
|
|
}
|
|
|
|
if config == nil {
|
|
t.Errorf("Config should not be nil")
|
|
}
|
|
|
|
// Verify default values
|
|
if config.CurrentVersion != "v1.0.0" {
|
|
t.Errorf("Expected default version v1.0.0, got %s", config.CurrentVersion)
|
|
}
|
|
|
|
if config.UserAgent != "LightweightUpdater/1.0" {
|
|
t.Errorf("Expected default user agent, got %s", config.UserAgent)
|
|
}
|
|
|
|
// Set some values including CDK
|
|
config.ResourceID = "TEST123"
|
|
config.SetCDK("secret-cdk-key")
|
|
|
|
// Save config
|
|
err = cm.Save(config)
|
|
if err != nil {
|
|
t.Errorf("Failed to save config: %v", err)
|
|
}
|
|
|
|
// Load config again
|
|
loadedConfig, err := cm.Load()
|
|
if err != nil {
|
|
t.Errorf("Failed to load saved config: %v", err)
|
|
}
|
|
|
|
// Verify values
|
|
if loadedConfig.ResourceID != "TEST123" {
|
|
t.Errorf("Expected ResourceID TEST123, got %s", loadedConfig.ResourceID)
|
|
}
|
|
|
|
// Verify CDK is properly encrypted/decrypted
|
|
retrievedCDK, err := loadedConfig.GetCDK()
|
|
if err != nil {
|
|
t.Errorf("Failed to get CDK from loaded config: %v", err)
|
|
}
|
|
|
|
if retrievedCDK != "secret-cdk-key" {
|
|
t.Errorf("Expected CDK secret-cdk-key, got %s", retrievedCDK)
|
|
}
|
|
|
|
// Verify CDK is encrypted in the config struct
|
|
if loadedConfig.CDK == "secret-cdk-key" {
|
|
t.Errorf("CDK should be encrypted in config file")
|
|
}
|
|
}
|
|
|
|
func TestConfigValidation(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
config *Config
|
|
expectError bool
|
|
}{
|
|
{
|
|
name: "Nil config",
|
|
config: nil,
|
|
expectError: true,
|
|
},
|
|
{
|
|
name: "Empty ResourceID",
|
|
config: &Config{
|
|
ResourceID: "",
|
|
CurrentVersion: "v1.0.0",
|
|
UserAgent: "Test/1.0",
|
|
LogLevel: "info",
|
|
CheckInterval: 3600,
|
|
},
|
|
expectError: true,
|
|
},
|
|
{
|
|
name: "Empty CurrentVersion",
|
|
config: &Config{
|
|
ResourceID: "TEST",
|
|
CurrentVersion: "",
|
|
UserAgent: "Test/1.0",
|
|
LogLevel: "info",
|
|
CheckInterval: 3600,
|
|
},
|
|
expectError: true,
|
|
},
|
|
{
|
|
name: "Invalid LogLevel",
|
|
config: &Config{
|
|
ResourceID: "TEST",
|
|
CurrentVersion: "v1.0.0",
|
|
UserAgent: "Test/1.0",
|
|
LogLevel: "invalid",
|
|
CheckInterval: 3600,
|
|
},
|
|
expectError: true,
|
|
},
|
|
{
|
|
name: "Invalid CheckInterval",
|
|
config: &Config{
|
|
ResourceID: "TEST",
|
|
CurrentVersion: "v1.0.0",
|
|
UserAgent: "Test/1.0",
|
|
LogLevel: "info",
|
|
CheckInterval: 30, // Less than 60
|
|
},
|
|
expectError: true,
|
|
},
|
|
{
|
|
name: "Valid config",
|
|
config: &Config{
|
|
ResourceID: "TEST",
|
|
CurrentVersion: "v1.0.0",
|
|
UserAgent: "Test/1.0",
|
|
LogLevel: "info",
|
|
CheckInterval: 3600,
|
|
},
|
|
expectError: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := validateConfig(tt.config)
|
|
if tt.expectError && err == nil {
|
|
t.Errorf("Expected error but got none")
|
|
}
|
|
if !tt.expectError && err != nil {
|
|
t.Errorf("Expected no error but got: %v", err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetConfigDir(t *testing.T) {
|
|
// Save original APPDATA
|
|
originalAppData := os.Getenv("APPDATA")
|
|
defer os.Setenv("APPDATA", originalAppData)
|
|
|
|
// Test with APPDATA set
|
|
os.Setenv("APPDATA", "C:\\Users\\Test\\AppData\\Roaming")
|
|
dir := getConfigDir()
|
|
expected := "C:\\Users\\Test\\AppData\\Roaming\\LightweightUpdater"
|
|
if dir != expected {
|
|
t.Errorf("Expected %s, got %s", expected, dir)
|
|
}
|
|
|
|
// Test without APPDATA
|
|
os.Unsetenv("APPDATA")
|
|
dir = getConfigDir()
|
|
if dir != "." {
|
|
t.Errorf("Expected current directory, got %s", dir)
|
|
}
|
|
}
|
|
|
|
func TestValidateAndApplyDefaults(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input *Config
|
|
expected *Config
|
|
hasError bool
|
|
}{
|
|
{
|
|
name: "Apply defaults to empty config",
|
|
input: &Config{
|
|
ResourceID: "TEST",
|
|
},
|
|
expected: &Config{
|
|
ResourceID: "TEST",
|
|
CurrentVersion: "v1.0.0",
|
|
UserAgent: "LightweightUpdater/1.0",
|
|
LogLevel: "info",
|
|
CheckInterval: 3600,
|
|
},
|
|
hasError: false,
|
|
},
|
|
{
|
|
name: "Partial config with some defaults needed",
|
|
input: &Config{
|
|
ResourceID: "TEST",
|
|
CurrentVersion: "v2.0.0",
|
|
LogLevel: "debug",
|
|
},
|
|
expected: &Config{
|
|
ResourceID: "TEST",
|
|
CurrentVersion: "v2.0.0",
|
|
UserAgent: "LightweightUpdater/1.0",
|
|
LogLevel: "debug",
|
|
CheckInterval: 3600,
|
|
},
|
|
hasError: false,
|
|
},
|
|
{
|
|
name: "Config with invalid values after defaults",
|
|
input: &Config{
|
|
ResourceID: "", // Invalid - empty
|
|
CheckInterval: 30, // Invalid - too small
|
|
},
|
|
expected: nil,
|
|
hasError: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := validateAndApplyDefaults(tt.input)
|
|
|
|
if tt.hasError {
|
|
if err == nil {
|
|
t.Errorf("Expected error but got none")
|
|
}
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
t.Errorf("Unexpected error: %v", err)
|
|
return
|
|
}
|
|
|
|
// Check that defaults were applied correctly
|
|
if tt.input.CurrentVersion != tt.expected.CurrentVersion {
|
|
t.Errorf("CurrentVersion: expected %s, got %s", tt.expected.CurrentVersion, tt.input.CurrentVersion)
|
|
}
|
|
if tt.input.UserAgent != tt.expected.UserAgent {
|
|
t.Errorf("UserAgent: expected %s, got %s", tt.expected.UserAgent, tt.input.UserAgent)
|
|
}
|
|
if tt.input.LogLevel != tt.expected.LogLevel {
|
|
t.Errorf("LogLevel: expected %s, got %s", tt.expected.LogLevel, tt.input.LogLevel)
|
|
}
|
|
if tt.input.CheckInterval != tt.expected.CheckInterval {
|
|
t.Errorf("CheckInterval: expected %d, got %d", tt.expected.CheckInterval, tt.input.CheckInterval)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetDefaultConfig(t *testing.T) {
|
|
config := getDefaultConfig()
|
|
|
|
if config == nil {
|
|
t.Fatal("getDefaultConfig() returned nil")
|
|
}
|
|
|
|
// Verify default values
|
|
if config.ResourceID != "PLACEHOLDER" {
|
|
t.Errorf("Expected ResourceID 'PLACEHOLDER', got %s", config.ResourceID)
|
|
}
|
|
if config.CurrentVersion != "v1.0.0" {
|
|
t.Errorf("Expected CurrentVersion 'v1.0.0', got %s", config.CurrentVersion)
|
|
}
|
|
if config.UserAgent != "LightweightUpdater/1.0" {
|
|
t.Errorf("Expected UserAgent 'LightweightUpdater/1.0', got %s", config.UserAgent)
|
|
}
|
|
if config.LogLevel != "info" {
|
|
t.Errorf("Expected LogLevel 'info', got %s", config.LogLevel)
|
|
}
|
|
if config.CheckInterval != 3600 {
|
|
t.Errorf("Expected CheckInterval 3600, got %d", config.CheckInterval)
|
|
}
|
|
if !config.AutoCheck {
|
|
t.Errorf("Expected AutoCheck true, got %v", config.AutoCheck)
|
|
}
|
|
}
|
|
|
|
func TestConfigManagerWithCustomPath(t *testing.T) {
|
|
tempDir := t.TempDir()
|
|
customPath := filepath.Join(tempDir, "custom-config.yaml")
|
|
|
|
cm := &DefaultConfigManager{
|
|
configPath: customPath,
|
|
}
|
|
|
|
// Test GetConfigPath
|
|
if cm.GetConfigPath() != customPath {
|
|
t.Errorf("Expected config path %s, got %s", customPath, cm.GetConfigPath())
|
|
}
|
|
|
|
// Test Save and Load with custom path
|
|
testConfig := &Config{
|
|
ResourceID: "CUSTOM",
|
|
CurrentVersion: "v1.5.0",
|
|
UserAgent: "CustomUpdater/1.0",
|
|
LogLevel: "debug",
|
|
CheckInterval: 7200,
|
|
AutoCheck: false,
|
|
}
|
|
|
|
// Save config
|
|
err := cm.Save(testConfig)
|
|
if err != nil {
|
|
t.Fatalf("Failed to save config: %v", err)
|
|
}
|
|
|
|
// Load config
|
|
loadedConfig, err := cm.Load()
|
|
if err != nil {
|
|
t.Fatalf("Failed to load config: %v", err)
|
|
}
|
|
|
|
// Verify loaded config matches saved config
|
|
if loadedConfig.ResourceID != testConfig.ResourceID {
|
|
t.Errorf("ResourceID mismatch: expected %s, got %s", testConfig.ResourceID, loadedConfig.ResourceID)
|
|
}
|
|
if loadedConfig.CurrentVersion != testConfig.CurrentVersion {
|
|
t.Errorf("CurrentVersion mismatch: expected %s, got %s", testConfig.CurrentVersion, loadedConfig.CurrentVersion)
|
|
}
|
|
if loadedConfig.AutoCheck != testConfig.AutoCheck {
|
|
t.Errorf("AutoCheck mismatch: expected %v, got %v", testConfig.AutoCheck, loadedConfig.AutoCheck)
|
|
}
|
|
}
|
|
|
|
func TestConfigManagerErrorHandling(t *testing.T) {
|
|
// Test with invalid directory path
|
|
invalidPath := string([]byte{0}) + "/invalid/config.yaml"
|
|
cm := &DefaultConfigManager{
|
|
configPath: invalidPath,
|
|
}
|
|
|
|
// Load should fail with invalid path
|
|
_, err := cm.Load()
|
|
if err == nil {
|
|
t.Error("Expected error when loading from invalid path")
|
|
}
|
|
|
|
// Save should fail with invalid path
|
|
testConfig := getDefaultConfig()
|
|
testConfig.ResourceID = "TEST"
|
|
err = cm.Save(testConfig)
|
|
if err == nil {
|
|
t.Error("Expected error when saving to invalid path")
|
|
}
|
|
}
|
|
|
|
func TestEncryptDecryptEdgeCases(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
}{
|
|
{"Unicode characters", "测试CDK密钥🔑"},
|
|
{"Very long string", strings.Repeat("A", 1000)},
|
|
{"Binary-like data", string([]byte{0, 1, 2, 3, 255, 254, 253})},
|
|
{"Only spaces", " "},
|
|
{"Newlines and tabs", "line1\nline2\tindented"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
encrypted := encryptCDK(tt.input)
|
|
decrypted, err := decryptCDK(encrypted)
|
|
|
|
if err != nil {
|
|
t.Errorf("Decryption failed: %v", err)
|
|
}
|
|
|
|
if decrypted != tt.input {
|
|
t.Errorf("Encryption/decryption mismatch: expected %q, got %q", tt.input, decrypted)
|
|
}
|
|
})
|
|
}
|
|
}
|