package main import ( "os" "path/filepath" "strings" "testing" ) func TestGenerateNginx(t *testing.T) { tmpDir := t.TempDir() // Create test directories log1Dir := filepath.Join(tmpDir, "log1") log2Dir := filepath.Join(tmpDir, "log2") err := os.MkdirAll(log1Dir, 0755) if err != nil { t.Fatal(err) } err = os.MkdirAll(log2Dir, 0755) if err != nil { t.Fatal(err) } // Create test config configContent := `listen: - ":8080" logs: - shortname: "log1" monitoringprefix: "https://log1.example.com/monitor" localdirectory: "` + log1Dir + `" - shortname: "log2" monitoringprefix: "https://log2.example.com:9090/monitor" localdirectory: "` + log2Dir + `"` configFile := filepath.Join(tmpDir, "test-config.yaml") err = os.WriteFile(configFile, []byte(configContent), 0644) if err != nil { t.Fatal(err) } // Run generateNginx generateNginx(configFile, false, true, false) // Verify nginx config for first log nginxFile1 := filepath.Join(log1Dir, "log1.example.com.conf") nginxContent1, err := os.ReadFile(nginxFile1) if err != nil { t.Fatalf("Failed to read nginx config: %v", err) } nginx1Str := string(nginxContent1) // Check server block basics if !strings.Contains(nginx1Str, "server {") { t.Error("Expected server block") } if !strings.Contains(nginx1Str, "listen 8080;") { t.Error("Expected listen directive with port 8080") } if !strings.Contains(nginx1Str, "listen [::]:8080;") { t.Error("Expected IPv6 listen directive") } if !strings.Contains(nginx1Str, "server_name log1.example.com;") { t.Error("Expected correct server name") } if !strings.Contains(nginx1Str, "root "+log1Dir+";") { t.Error("Expected correct document root") } // Check location blocks if !strings.Contains(nginx1Str, "location = / {") { t.Error("Expected root location block") } if !strings.Contains(nginx1Str, "location = /checkpoint {") { t.Error("Expected checkpoint location block") } if !strings.Contains(nginx1Str, "location = /log.v3.json {") { t.Error("Expected log.v3.json location block") } if !strings.Contains(nginx1Str, "location ~ ^/issuer/(.+)$ {") { t.Error("Expected issuer location block") } if !strings.Contains(nginx1Str, "location ~ ^/tile/(.+)$ {") { t.Error("Expected tile location block") } // Check CORS headers if !strings.Contains(nginx1Str, `add_header Access-Control-Allow-Origin "*" always;`) { t.Error("Expected CORS headers") } // Check cache control headers if !strings.Contains(nginx1Str, `add_header Cache-Control "no-store" always;`) { t.Error("Expected no-store cache control for checkpoint") } if !strings.Contains(nginx1Str, `add_header Cache-Control "public, max-age=3600, immutable" always;`) { t.Error("Expected long cache control for log.v3.json") } if !strings.Contains(nginx1Str, `add_header Cache-Control "public, max-age=604800, immutable" always;`) { t.Error("Expected very long cache control for static files") } // Check content types if !strings.Contains(nginx1Str, `add_header Content-Type "text/html; charset=utf-8" always;`) { t.Error("Expected HTML content type") } if !strings.Contains(nginx1Str, `add_header Content-Type "text/plain; charset=utf-8" always;`) { t.Error("Expected plain text content type for checkpoint") } if !strings.Contains(nginx1Str, `add_header Content-Type "application/json" always;`) { t.Error("Expected JSON content type") } if !strings.Contains(nginx1Str, `add_header Content-Type "application/pkix-cert" always;`) { t.Error("Expected certificate content type") } if !strings.Contains(nginx1Str, `add_header Content-Type "application/octet-stream" always;`) { t.Error("Expected octet-stream content type") } // Check gzip handling if !strings.Contains(nginx1Str, `add_header Content-Encoding "gzip" always;`) { t.Error("Expected gzip content encoding for .gz files") } // Verify nginx config for second log (with port) nginxFile2 := filepath.Join(log2Dir, "log2.example.com:9090.conf") nginxContent2, err := os.ReadFile(nginxFile2) if err != nil { t.Fatalf("Failed to read second nginx config: %v", err) } nginx2Str := string(nginxContent2) if !strings.Contains(nginx2Str, "server_name log2.example.com:9090;") { t.Error("Expected correct server name with port") } if !strings.Contains(nginx2Str, "root "+log2Dir+";") { t.Error("Expected correct document root for second log") } } func TestGenerateNginxCustomPort(t *testing.T) { tmpDir := t.TempDir() logDir := filepath.Join(tmpDir, "test-log") err := os.MkdirAll(logDir, 0755) if err != nil { t.Fatal(err) } // Create config with custom port configContent := `listen: - ":9999" logs: - shortname: "test-log" monitoringprefix: "https://test.example.com/monitor" localdirectory: "` + logDir + `"` configFile := filepath.Join(tmpDir, "test-config.yaml") err = os.WriteFile(configFile, []byte(configContent), 0644) if err != nil { t.Fatal(err) } generateNginx(configFile, false, true, false) nginxFile := filepath.Join(logDir, "test.example.com.conf") nginxContent, err := os.ReadFile(nginxFile) if err != nil { t.Fatalf("Failed to read nginx config: %v", err) } nginxStr := string(nginxContent) if !strings.Contains(nginxStr, "listen 9999;") { t.Error("Expected listen directive with custom port 9999") } if !strings.Contains(nginxStr, "listen [::]:9999;") { t.Error("Expected IPv6 listen directive with custom port") } } func TestGenerateNginxMultiplePorts(t *testing.T) { tmpDir := t.TempDir() logDir := filepath.Join(tmpDir, "test-log") err := os.MkdirAll(logDir, 0755) if err != nil { t.Fatal(err) } // Create config with multiple listen addresses (should use first one) configContent := `listen: - ":8080" - ":8081" logs: - shortname: "test-log" monitoringprefix: "https://test.example.com/monitor" localdirectory: "` + logDir + `"` configFile := filepath.Join(tmpDir, "test-config.yaml") err = os.WriteFile(configFile, []byte(configContent), 0644) if err != nil { t.Fatal(err) } generateNginx(configFile, false, true, false) nginxFile := filepath.Join(logDir, "test.example.com.conf") nginxContent, err := os.ReadFile(nginxFile) if err != nil { t.Fatalf("Failed to read nginx config: %v", err) } nginxStr := string(nginxContent) if !strings.Contains(nginxStr, "listen 8080;") { t.Error("Expected first port to be used") } if strings.Contains(nginxStr, "listen 8081;") { t.Error("Should not contain second port") } } func TestGenerateNginxInvalidURL(t *testing.T) { tmpDir := t.TempDir() logDir := filepath.Join(tmpDir, "test-log") err := os.MkdirAll(logDir, 0755) if err != nil { t.Fatal(err) } // Create config with invalid monitoring URL configContent := `logs: - shortname: "test-log" monitoringprefix: "not-a-valid-url" localdirectory: "` + logDir + `"` configFile := filepath.Join(tmpDir, "test-config.yaml") err = os.WriteFile(configFile, []byte(configContent), 0644) if err != nil { t.Fatal(err) } // Should not create nginx config file due to invalid URL generateNginx(configFile, false, true, false) // Check that a .conf file was still created (even with invalid hostname extraction) // The function continues execution and creates a file with empty hostname files, err := filepath.Glob(filepath.Join(logDir, "*.conf")) if err != nil { t.Fatal(err) } // The function still creates a file, but with an empty hostname, resulting in ".conf" if len(files) == 0 { t.Error("Expected at least one config file to be created despite invalid URL") } } func TestNginxTemplateData(t *testing.T) { data := NginxTemplateData{ MonitoringHost: "example.com", LocalDirectory: "/path/to/files", ListenPort: "8080", } if data.MonitoringHost != "example.com" { t.Errorf("Expected MonitoringHost 'example.com', got %s", data.MonitoringHost) } if data.LocalDirectory != "/path/to/files" { t.Errorf("Expected LocalDirectory '/path/to/files', got %s", data.LocalDirectory) } if data.ListenPort != "8080" { t.Errorf("Expected ListenPort '8080', got %s", data.ListenPort) } } func TestGenerateNginxNoListenConfig(t *testing.T) { tmpDir := t.TempDir() logDir := filepath.Join(tmpDir, "test-log") err := os.MkdirAll(logDir, 0755) if err != nil { t.Fatal(err) } // Create config without listen directive (should use default 8080) configContent := `logs: - shortname: "test-log" monitoringprefix: "https://test.example.com/monitor" localdirectory: "` + logDir + `"` configFile := filepath.Join(tmpDir, "test-config.yaml") err = os.WriteFile(configFile, []byte(configContent), 0644) if err != nil { t.Fatal(err) } generateNginx(configFile, false, true, false) nginxFile := filepath.Join(logDir, "test.example.com.conf") nginxContent, err := os.ReadFile(nginxFile) if err != nil { t.Fatalf("Failed to read nginx config: %v", err) } nginxStr := string(nginxContent) if !strings.Contains(nginxStr, "listen 8080;") { t.Error("Expected default port 8080 when no listen config provided") } }