package config //nolint:testpackage // exercises unexported extractAgeSecretKey import ( "os" "path/filepath" "testing" ) const ( testSneakAgePublicKey = "age1278m9q7dp3chsh2dcy82qk27v047zywyvt" + "xwnj4cvt0z65jw6a7q5dqhfj" testIntegrationAgePublicKey = "age1ezrjmfpwsc95svdg0y54mums3zevgzu" + "0x0ecq2f7tp8a05gl0sjq9q9wjg" testIntegrationAgePrivateKey = "AGE-SECRET-KEY-19CR5YSFW59HM4TLD6GX" + "VEDMZFTVVF7PPHKUT68TXSFPK7APHXA2QS2NJA5" ) func TestMain(m *testing.M) { // Set up test environment testConfigPath := filepath.Join("..", "..", "test", "config.yaml") absPath, err := filepath.Abs(testConfigPath) if err == nil { _ = os.Setenv("VAULTIK_CONFIG", absPath) } code := m.Run() os.Exit(code) } // TestConfigLoad ensures the config package can be imported and basic // functionality works. func TestConfigLoad(t *testing.T) { t.Parallel() // Use the test config file configPath := os.Getenv("VAULTIK_CONFIG") if configPath == "" { t.Fatal("VAULTIK_CONFIG environment variable not set") } // Test loading the config cfg, err := Load(configPath) if err != nil { t.Fatalf("Failed to load config: %v", err) } // Basic validation if len(cfg.AgeRecipients) != 2 { t.Errorf("Expected 2 age recipients, got %d", len(cfg.AgeRecipients)) } if cfg.AgeRecipients[0] != testSneakAgePublicKey { t.Errorf("Expected first age recipient to be %s, got '%s'", testSneakAgePublicKey, cfg.AgeRecipients[0]) } if len(cfg.Snapshots) != 1 { t.Errorf("Expected 1 snapshot, got %d", len(cfg.Snapshots)) } testSnap, ok := cfg.Snapshots["test"] if !ok { t.Fatal("Expected 'test' snapshot to exist") } if len(testSnap.Paths) != 2 { t.Errorf("Expected 2 paths in test snapshot, got %d", len(testSnap.Paths)) } if testSnap.Paths[0] != "/tmp/vaultik-test-source" { t.Errorf("Expected first path to be '/tmp/vaultik-test-source', got '%s'", testSnap.Paths[0]) } if cfg.S3.Bucket != "vaultik-test-bucket" { t.Errorf("Expected S3 bucket to be 'vaultik-test-bucket', got '%s'", cfg.S3.Bucket) } if cfg.Hostname != "test-host" { t.Errorf("Expected hostname to be 'test-host', got '%s'", cfg.Hostname) } } // TestConfigFromEnv tests loading config path from environment variable func TestConfigFromEnv(t *testing.T) { t.Parallel() configPath := os.Getenv("VAULTIK_CONFIG") if configPath == "" { t.Skip("VAULTIK_CONFIG not set") } // Verify the file exists //nolint:gosec // G703: test config path comes from the test environment _, err := os.Stat(configPath) if os.IsNotExist(err) { t.Errorf("Config file does not exist at path from VAULTIK_CONFIG: %s", configPath) } } // TestExtractAgeSecretKey tests extraction of AGE-SECRET-KEY from various inputs func TestExtractAgeSecretKey(t *testing.T) { t.Parallel() tests := []struct { name string input string expected string }{ { name: "plain key", input: testIntegrationAgePrivateKey, expected: testIntegrationAgePrivateKey, }, { name: "key with trailing newline", input: testIntegrationAgePrivateKey + "\n", expected: testIntegrationAgePrivateKey, }, { name: "full age-keygen output", input: "# created: 2025-01-14T12:00:00Z\n" + "# public key: " + testIntegrationAgePublicKey + "\n" + testIntegrationAgePrivateKey + "\n", expected: testIntegrationAgePrivateKey, }, { name: "age-keygen output with extra blank lines", input: "# created: 2025-01-14T12:00:00Z\n" + "# public key: " + testIntegrationAgePublicKey + "\n\n" + testIntegrationAgePrivateKey + "\n\n", expected: testIntegrationAgePrivateKey, }, { name: "key with leading whitespace", input: " " + testIntegrationAgePrivateKey + " ", expected: testIntegrationAgePrivateKey, }, { name: "empty input", input: "", expected: "", }, { name: "only comments", input: "# this is a comment\n# another comment", expected: "# this is a comment\n# another comment", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { t.Parallel() result := extractAgeSecretKey(tt.input) if result != tt.expected { t.Errorf("extractAgeSecretKey(%q) = %q, want %q", tt.input, result, tt.expected) } }) } }