package main import ( "os" "path/filepath" "strings" "testing" ) func TestGenerateEnv(t *testing.T) { tmpDir := t.TempDir() // Create test directories testLogDir := filepath.Join(tmpDir, "test-log") testLog2Dir := filepath.Join(tmpDir, "test-log-2") err := os.MkdirAll(testLogDir, 0755) if err != nil { t.Fatal(err) } err = os.MkdirAll(testLog2Dir, 0755) if err != nil { t.Fatal(err) } // Create test roots files rootsFile := filepath.Join(tmpDir, "roots.pem") extraRootsFile := filepath.Join(tmpDir, "extra-roots.pem") rootsContent := `-----BEGIN CERTIFICATE----- MIIBkTCB+wIJAKZJ... -----END CERTIFICATE-----` extraRootsContent := `-----BEGIN CERTIFICATE----- MIIBkTCB+wIJAKZK... -----END CERTIFICATE-----` err = os.WriteFile(rootsFile, []byte(rootsContent), 0644) if err != nil { t.Fatal(err) } err = os.WriteFile(extraRootsFile, []byte(extraRootsContent), 0644) if err != nil { t.Fatal(err) } // Create test config configContent := `listen: - ":8080" roots: "` + rootsFile + `" logs: - shortname: "test-log" submissionprefix: "https://example.com/submit" monitoringprefix: "https://example.com/monitor" extraroots: "` + extraRootsFile + `" secret: "test-data/test-log.key" localdirectory: "` + testLogDir + `" listen: ":8081" notafterstart: "2024-01-01T00:00:00Z" notafterlimit: "2025-01-01T00:00:00Z" - shortname: "test-log-2" submissionprefix: "https://log2.example.com/submit" monitoringprefix: "https://log2.example.com/monitor" secret: "test-data/test-log-2.key" localdirectory: "` + testLog2Dir + `"` configFile := filepath.Join(tmpDir, "test-config.yaml") err = os.WriteFile(configFile, []byte(configContent), 0644) if err != nil { t.Fatal(err) } // Run generateEnv generateEnv(configFile, false, true, false) // Verify .env file was created for first log envFile := filepath.Join(testLogDir, ".env") envContent, err := os.ReadFile(envFile) if err != nil { t.Fatalf("Failed to read .env file: %v", err) } envStr := string(envContent) // Check TESSERACT_ARGS contains expected values if !strings.Contains(envStr, "TESSERACT_ARGS=") { t.Error("Expected TESSERACT_ARGS in .env file") } if !strings.Contains(envStr, "--private_key=test-data/test-log.key") { t.Error("Expected private_key argument in TESSERACT_ARGS") } if !strings.Contains(envStr, "--origin=example.com") { t.Error("Expected origin argument in TESSERACT_ARGS") } if !strings.Contains(envStr, "--storage_dir="+testLogDir) { t.Error("Expected storage_dir argument in TESSERACT_ARGS") } if !strings.Contains(envStr, "--http_endpoint=:8081") { t.Error("Expected http_endpoint argument in TESSERACT_ARGS") } if !strings.Contains(envStr, "--not_after_start=2024-01-01T00:00:00Z") { t.Error("Expected not_after_start argument in TESSERACT_ARGS") } if !strings.Contains(envStr, "--not_after_limit=2025-01-01T00:00:00Z") { t.Error("Expected not_after_limit argument in TESSERACT_ARGS") } if !strings.Contains(envStr, "OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318") { t.Error("Expected OTEL_EXPORTER_OTLP_ENDPOINT in .env file") } // Verify combined roots.pem was created combinedRootsFile := filepath.Join(testLogDir, "roots.pem") combinedContent, err := os.ReadFile(combinedRootsFile) if err != nil { t.Fatalf("Failed to read combined roots.pem: %v", err) } combinedStr := string(combinedContent) if !strings.Contains(combinedStr, "MIIBkTCB+wIJAKZJ") { t.Error("Expected content from main roots file") } if !strings.Contains(combinedStr, "MIIBkTCB+wIJAKZK") { t.Error("Expected content from extra roots file") } // Verify second log's .env file was created env2File := filepath.Join(testLog2Dir, ".env") env2Content, err := os.ReadFile(env2File) if err != nil { t.Fatalf("Failed to read second .env file: %v", err) } env2Str := string(env2Content) if !strings.Contains(env2Str, "--origin=log2.example.com") { t.Error("Expected correct origin for second log") } if strings.Contains(env2Str, "--http_endpoint=") { t.Error("Second log should not have http_endpoint (not specified)") } } func TestCreateCombinedRootsPemWithStatus(t *testing.T) { tmpDir := t.TempDir() // Test case 1: Both files exist rootsFile := filepath.Join(tmpDir, "roots.pem") extraFile := filepath.Join(tmpDir, "extra.pem") outputFile := filepath.Join(tmpDir, "combined.pem") rootsContent := "ROOT CERT CONTENT\n" extraContent := "EXTRA CERT CONTENT\n" err := os.WriteFile(rootsFile, []byte(rootsContent), 0644) if err != nil { t.Fatal(err) } err = os.WriteFile(extraFile, []byte(extraContent), 0644) if err != nil { t.Fatal(err) } err = createCombinedRootsPemWithStatus(rootsFile, extraFile, outputFile, false, true, false) if err != nil { t.Errorf("createCombinedRootsPemWithStatus() error = %v", err) } combinedContent, err := os.ReadFile(outputFile) if err != nil { t.Fatal(err) } expected := rootsContent + extraContent if string(combinedContent) != expected { t.Errorf("Combined content = %s, want %s", string(combinedContent), expected) } // Test case 2: Only roots file exists outputFile2 := filepath.Join(tmpDir, "combined2.pem") err = createCombinedRootsPemWithStatus(rootsFile, "", outputFile2, false, true, false) if err != nil { t.Errorf("createCombinedRootsPemWithStatus() with empty extra file error = %v", err) } combinedContent2, err := os.ReadFile(outputFile2) if err != nil { t.Fatal(err) } if string(combinedContent2) != rootsContent { t.Errorf("Combined content = %s, want %s", string(combinedContent2), rootsContent) } // Test case 3: Extra file doesn't exist (should error) outputFile3 := filepath.Join(tmpDir, "combined3.pem") err = createCombinedRootsPemWithStatus(rootsFile, "nonexistent.pem", outputFile3, false, true, false) if err == nil { t.Error("Expected error when extra file doesn't exist") } } func TestGenerateEnvMissingDirectory(t *testing.T) { tmpDir := t.TempDir() // Create config with non-existent directory configContent := `logs: - shortname: "test-log" submissionprefix: "https://example.com/submit" secret: "test.key" localdirectory: "/nonexistent/directory"` configFile := filepath.Join(tmpDir, "test-config.yaml") err := os.WriteFile(configFile, []byte(configContent), 0644) if err != nil { t.Fatal(err) } // Should call log.Fatalf which exits the program // We can't easily test this without subprocess, so we'll skip it t.Skip("Cannot easily test log.Fatalf without subprocess") }