|
@@ -0,0 +1,639 @@
|
|
|
+package nginx
|
|
|
+
|
|
|
+import (
|
|
|
+ "path/filepath"
|
|
|
+ "regexp"
|
|
|
+ "testing"
|
|
|
+)
|
|
|
+
|
|
|
+// Mock nginx -T output for testing purposes
|
|
|
+const mockNginxTOutput = `
|
|
|
+# configuration file /etc/nginx/nginx.conf:
|
|
|
+user nginx;
|
|
|
+worker_processes auto;
|
|
|
+
|
|
|
+error_log /var/log/nginx/error.log notice;
|
|
|
+error_log /var/log/nginx/error.local.log notice;
|
|
|
+pid /var/run/nginx.pid;
|
|
|
+
|
|
|
+events {
|
|
|
+ worker_connections 1024;
|
|
|
+}
|
|
|
+
|
|
|
+http {
|
|
|
+ include /etc/nginx/mime.types;
|
|
|
+ default_type application/octet-stream;
|
|
|
+
|
|
|
+ log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
|
|
+ '$status $body_bytes_sent "$http_referer" '
|
|
|
+ '"$http_user_agent" "$http_x_forwarded_for"';
|
|
|
+
|
|
|
+ access_log /var/log/nginx/access.log main;
|
|
|
+ access_log /var/log/nginx/access.local.log main;
|
|
|
+
|
|
|
+ sendfile on;
|
|
|
+ keepalive_timeout 65;
|
|
|
+ gzip on;
|
|
|
+
|
|
|
+ server {
|
|
|
+ listen 80;
|
|
|
+ server_name localhost;
|
|
|
+
|
|
|
+ access_log /var/log/nginx/server.access.log;
|
|
|
+ error_log /var/log/nginx/server.error.log warn;
|
|
|
+
|
|
|
+ location / {
|
|
|
+ root /usr/share/nginx/html;
|
|
|
+ index index.html index.htm;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+stream {
|
|
|
+ error_log /var/log/nginx/stream.error.log info;
|
|
|
+
|
|
|
+ server {
|
|
|
+ listen 3306;
|
|
|
+ proxy_pass backend;
|
|
|
+ }
|
|
|
+}
|
|
|
+`
|
|
|
+
|
|
|
+// Mock nginx -T output with relative paths
|
|
|
+const mockNginxTOutputRelative = `
|
|
|
+# configuration file /etc/nginx/nginx.conf:
|
|
|
+user nginx;
|
|
|
+worker_processes auto;
|
|
|
+
|
|
|
+error_log logs/error.log notice;
|
|
|
+pid /var/run/nginx.pid;
|
|
|
+
|
|
|
+http {
|
|
|
+ access_log logs/access.log main;
|
|
|
+
|
|
|
+ server {
|
|
|
+ listen 80;
|
|
|
+ server_name localhost;
|
|
|
+
|
|
|
+ access_log logs/server.access.log;
|
|
|
+ error_log logs/server.error.log warn;
|
|
|
+ }
|
|
|
+}
|
|
|
+`
|
|
|
+
|
|
|
+// Mock nginx -T output with access_log off
|
|
|
+const mockNginxTOutputOff = `
|
|
|
+# configuration file /etc/nginx/nginx.conf:
|
|
|
+user nginx;
|
|
|
+worker_processes auto;
|
|
|
+
|
|
|
+error_log /var/log/nginx/error.log notice;
|
|
|
+
|
|
|
+http {
|
|
|
+ access_log off;
|
|
|
+
|
|
|
+ server {
|
|
|
+ listen 80;
|
|
|
+ server_name localhost;
|
|
|
+
|
|
|
+ access_log /var/log/nginx/server.access.log;
|
|
|
+ error_log /var/log/nginx/server.error.log warn;
|
|
|
+ }
|
|
|
+}
|
|
|
+`
|
|
|
+
|
|
|
+// Mock nginx -T output with commented log directives
|
|
|
+const mockNginxTOutputCommented = `
|
|
|
+# configuration file /etc/nginx/nginx.conf:
|
|
|
+user nginx;
|
|
|
+worker_processes auto;
|
|
|
+
|
|
|
+# error_log /var/log/nginx/commented.error.log notice;
|
|
|
+error_log /var/log/nginx/error.log notice;
|
|
|
+
|
|
|
+http {
|
|
|
+ # access_log /var/log/nginx/commented.access.log main;
|
|
|
+ access_log /var/log/nginx/access.log main;
|
|
|
+
|
|
|
+ server {
|
|
|
+ listen 80;
|
|
|
+ server_name localhost;
|
|
|
+
|
|
|
+ # access_log /var/log/nginx/commented.server.access.log;
|
|
|
+ access_log /var/log/nginx/server.access.log;
|
|
|
+ # error_log /var/log/nginx/commented.server.error.log warn;
|
|
|
+ error_log /var/log/nginx/server.error.log warn;
|
|
|
+ }
|
|
|
+}
|
|
|
+`
|
|
|
+
|
|
|
+func TestAccessLogRegexParsing(t *testing.T) {
|
|
|
+ testCases := []struct {
|
|
|
+ name string
|
|
|
+ nginxTOutput string
|
|
|
+ expectedPath string
|
|
|
+ shouldHaveLog bool
|
|
|
+ }{
|
|
|
+ {
|
|
|
+ name: "standard access log",
|
|
|
+ nginxTOutput: "access_log /var/log/nginx/access.log main;",
|
|
|
+ expectedPath: "/var/log/nginx/access.log",
|
|
|
+ shouldHaveLog: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "access log turned off",
|
|
|
+ nginxTOutput: "access_log off;",
|
|
|
+ expectedPath: "",
|
|
|
+ shouldHaveLog: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "no access log directive",
|
|
|
+ nginxTOutput: "server_name localhost;",
|
|
|
+ expectedPath: "",
|
|
|
+ shouldHaveLog: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "indented access log",
|
|
|
+ nginxTOutput: " access_log /var/log/nginx/server.log;",
|
|
|
+ expectedPath: "/var/log/nginx/server.log",
|
|
|
+ shouldHaveLog: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "multiple access logs - should get first",
|
|
|
+ nginxTOutput: "access_log /var/log/nginx/access1.log main;\naccess_log /var/log/nginx/access2.log combined;",
|
|
|
+ expectedPath: "/var/log/nginx/access1.log",
|
|
|
+ shouldHaveLog: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "commented access log should be ignored",
|
|
|
+ nginxTOutput: "# access_log /var/log/nginx/commented.access.log main;\naccess_log /var/log/nginx/access.log main;",
|
|
|
+ expectedPath: "/var/log/nginx/access.log",
|
|
|
+ shouldHaveLog: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "only commented access log",
|
|
|
+ nginxTOutput: "# access_log /var/log/nginx/commented.access.log main;",
|
|
|
+ expectedPath: "",
|
|
|
+ shouldHaveLog: false,
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ accessLogRegex := regexp.MustCompile(AccessLogRegexPattern)
|
|
|
+
|
|
|
+ for _, tc := range testCases {
|
|
|
+ t.Run(tc.name, func(t *testing.T) {
|
|
|
+ matches := accessLogRegex.FindAllStringSubmatch(tc.nginxTOutput, -1)
|
|
|
+
|
|
|
+ if !tc.shouldHaveLog {
|
|
|
+ if len(matches) > 0 {
|
|
|
+ // Check if it's the "off" directive
|
|
|
+ if len(matches[0]) >= 2 {
|
|
|
+ logPath := matches[0][1]
|
|
|
+ if logPath != "off" {
|
|
|
+ t.Errorf("Expected no valid access log, but found: %s", logPath)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if len(matches) == 0 {
|
|
|
+ t.Errorf("Expected to find access log directive, but found none")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if len(matches[0]) < 2 {
|
|
|
+ t.Errorf("Expected regex match to have at least 2 groups, got %d", len(matches[0]))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ logPath := matches[0][1]
|
|
|
+
|
|
|
+ if logPath != tc.expectedPath {
|
|
|
+ t.Errorf("Expected access log path %s, got %s", tc.expectedPath, logPath)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestErrorLogRegexParsing(t *testing.T) {
|
|
|
+ testCases := []struct {
|
|
|
+ name string
|
|
|
+ nginxTOutput string
|
|
|
+ expectedPath string
|
|
|
+ shouldHaveLog bool
|
|
|
+ }{
|
|
|
+ {
|
|
|
+ name: "standard error log",
|
|
|
+ nginxTOutput: "error_log /var/log/nginx/error.log notice;",
|
|
|
+ expectedPath: "/var/log/nginx/error.log",
|
|
|
+ shouldHaveLog: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "error log without level",
|
|
|
+ nginxTOutput: "error_log /var/log/nginx/error.log;",
|
|
|
+ expectedPath: "/var/log/nginx/error.log",
|
|
|
+ shouldHaveLog: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "no error log directive",
|
|
|
+ nginxTOutput: "server_name localhost;",
|
|
|
+ expectedPath: "",
|
|
|
+ shouldHaveLog: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "indented error log",
|
|
|
+ nginxTOutput: " error_log /var/log/nginx/server.error.log warn;",
|
|
|
+ expectedPath: "/var/log/nginx/server.error.log",
|
|
|
+ shouldHaveLog: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "multiple error logs - should get first",
|
|
|
+ nginxTOutput: "error_log /var/log/nginx/error1.log notice;\nerror_log /var/log/nginx/error2.log warn;",
|
|
|
+ expectedPath: "/var/log/nginx/error1.log",
|
|
|
+ shouldHaveLog: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "commented error log should be ignored",
|
|
|
+ nginxTOutput: "# error_log /var/log/nginx/commented.error.log notice;\nerror_log /var/log/nginx/error.log notice;",
|
|
|
+ expectedPath: "/var/log/nginx/error.log",
|
|
|
+ shouldHaveLog: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "only commented error log",
|
|
|
+ nginxTOutput: "# error_log /var/log/nginx/commented.error.log notice;",
|
|
|
+ expectedPath: "",
|
|
|
+ shouldHaveLog: false,
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ errorLogRegex := regexp.MustCompile(ErrorLogRegexPattern)
|
|
|
+
|
|
|
+ for _, tc := range testCases {
|
|
|
+ t.Run(tc.name, func(t *testing.T) {
|
|
|
+ matches := errorLogRegex.FindAllStringSubmatch(tc.nginxTOutput, -1)
|
|
|
+
|
|
|
+ if !tc.shouldHaveLog {
|
|
|
+ if len(matches) > 0 {
|
|
|
+ t.Errorf("Expected no error log directive, but found: %v", matches)
|
|
|
+ }
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if len(matches) == 0 {
|
|
|
+ t.Errorf("Expected to find error log directive, but found none")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if len(matches[0]) < 2 {
|
|
|
+ t.Errorf("Expected regex match to have at least 2 groups, got %d", len(matches[0]))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ logPath := matches[0][1]
|
|
|
+
|
|
|
+ if logPath != tc.expectedPath {
|
|
|
+ t.Errorf("Expected error log path %s, got %s", tc.expectedPath, logPath)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestLogPathParsing(t *testing.T) {
|
|
|
+ testCases := []struct {
|
|
|
+ name string
|
|
|
+ nginxTOutput string
|
|
|
+ expectedAccessPath string
|
|
|
+ expectedErrorPath string
|
|
|
+ shouldHaveAccess bool
|
|
|
+ shouldHaveError bool
|
|
|
+ }{
|
|
|
+ {
|
|
|
+ name: "complete configuration",
|
|
|
+ nginxTOutput: mockNginxTOutput,
|
|
|
+ expectedAccessPath: "/var/log/nginx/access.log",
|
|
|
+ expectedErrorPath: "/var/log/nginx/error.log",
|
|
|
+ shouldHaveAccess: true,
|
|
|
+ shouldHaveError: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "configuration with commented directives",
|
|
|
+ nginxTOutput: mockNginxTOutputCommented,
|
|
|
+ expectedAccessPath: "/var/log/nginx/access.log",
|
|
|
+ expectedErrorPath: "/var/log/nginx/error.log",
|
|
|
+ shouldHaveAccess: true,
|
|
|
+ shouldHaveError: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "access log turned off",
|
|
|
+ nginxTOutput: mockNginxTOutputOff,
|
|
|
+ expectedAccessPath: "/var/log/nginx/server.access.log", // Should get the server-level access log
|
|
|
+ expectedErrorPath: "/var/log/nginx/error.log",
|
|
|
+ shouldHaveAccess: true,
|
|
|
+ shouldHaveError: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "empty configuration",
|
|
|
+ nginxTOutput: "",
|
|
|
+ expectedAccessPath: "",
|
|
|
+ expectedErrorPath: "",
|
|
|
+ shouldHaveAccess: false,
|
|
|
+ shouldHaveError: false,
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, tc := range testCases {
|
|
|
+ t.Run(tc.name, func(t *testing.T) {
|
|
|
+ // Test access log parsing
|
|
|
+ accessLogRegex := regexp.MustCompile(AccessLogRegexPattern)
|
|
|
+ accessMatches := accessLogRegex.FindAllStringSubmatch(tc.nginxTOutput, -1)
|
|
|
+
|
|
|
+ var foundAccessPath string
|
|
|
+ for _, match := range accessMatches {
|
|
|
+ if len(match) >= 2 {
|
|
|
+ logPath := match[1]
|
|
|
+ if logPath != "off" {
|
|
|
+ foundAccessPath = logPath
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if tc.shouldHaveAccess {
|
|
|
+ if foundAccessPath == "" {
|
|
|
+ t.Errorf("Expected access log path %s, but found none", tc.expectedAccessPath)
|
|
|
+ } else if foundAccessPath != tc.expectedAccessPath {
|
|
|
+ t.Errorf("Expected access log path %s, got %s", tc.expectedAccessPath, foundAccessPath)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if foundAccessPath != "" {
|
|
|
+ t.Errorf("Expected no access log path, but found %s", foundAccessPath)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Test error log parsing
|
|
|
+ errorLogRegex := regexp.MustCompile(ErrorLogRegexPattern)
|
|
|
+ errorMatches := errorLogRegex.FindAllStringSubmatch(tc.nginxTOutput, -1)
|
|
|
+
|
|
|
+ var foundErrorPath string
|
|
|
+ if len(errorMatches) > 0 && len(errorMatches[0]) >= 2 {
|
|
|
+ foundErrorPath = errorMatches[0][1]
|
|
|
+ }
|
|
|
+
|
|
|
+ if tc.shouldHaveError {
|
|
|
+ if foundErrorPath == "" {
|
|
|
+ t.Errorf("Expected error log path %s, but found none", tc.expectedErrorPath)
|
|
|
+ } else if foundErrorPath != tc.expectedErrorPath {
|
|
|
+ t.Errorf("Expected error log path %s, got %s", tc.expectedErrorPath, foundErrorPath)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if foundErrorPath != "" {
|
|
|
+ t.Errorf("Expected no error log path, but found %s", foundErrorPath)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestRelativePathHandling(t *testing.T) {
|
|
|
+ // Mock GetPrefix function for testing
|
|
|
+ originalGetPrefix := GetPrefix
|
|
|
+ defer func() {
|
|
|
+ // Restore original function (if needed for other tests)
|
|
|
+ _ = originalGetPrefix
|
|
|
+ }()
|
|
|
+
|
|
|
+ testPrefix := "/usr/local/nginx"
|
|
|
+
|
|
|
+ testCases := []struct {
|
|
|
+ name string
|
|
|
+ inputPath string
|
|
|
+ expectedPath string
|
|
|
+ isRelative bool
|
|
|
+ }{
|
|
|
+ {
|
|
|
+ name: "absolute path",
|
|
|
+ inputPath: "/var/log/nginx/access.log",
|
|
|
+ expectedPath: "/var/log/nginx/access.log",
|
|
|
+ isRelative: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "relative path",
|
|
|
+ inputPath: "logs/access.log",
|
|
|
+ expectedPath: filepath.Join(testPrefix, "logs/access.log"),
|
|
|
+ isRelative: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "relative path with ./",
|
|
|
+ inputPath: "./logs/access.log",
|
|
|
+ expectedPath: filepath.Join(testPrefix, "./logs/access.log"),
|
|
|
+ isRelative: true,
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, tc := range testCases {
|
|
|
+ t.Run(tc.name, func(t *testing.T) {
|
|
|
+ var result string
|
|
|
+
|
|
|
+ if tc.isRelative {
|
|
|
+ result = filepath.Join(testPrefix, tc.inputPath)
|
|
|
+ } else {
|
|
|
+ result = tc.inputPath
|
|
|
+ }
|
|
|
+
|
|
|
+ if result != tc.expectedPath {
|
|
|
+ t.Errorf("Expected path %s, got %s", tc.expectedPath, result)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestComplexNginxConfiguration(t *testing.T) {
|
|
|
+ complexConfig := `
|
|
|
+# Main configuration
|
|
|
+user nginx;
|
|
|
+worker_processes auto;
|
|
|
+error_log /var/log/nginx/error.log warn;
|
|
|
+pid /var/run/nginx.pid;
|
|
|
+
|
|
|
+events {
|
|
|
+ worker_connections 1024;
|
|
|
+}
|
|
|
+
|
|
|
+http {
|
|
|
+ include /etc/nginx/mime.types;
|
|
|
+ default_type application/octet-stream;
|
|
|
+
|
|
|
+ log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
|
|
+ '$status $body_bytes_sent "$http_referer" '
|
|
|
+ '"$http_user_agent" "$http_x_forwarded_for"';
|
|
|
+
|
|
|
+ access_log /var/log/nginx/access.log main;
|
|
|
+
|
|
|
+ sendfile on;
|
|
|
+ tcp_nopush on;
|
|
|
+ tcp_nodelay on;
|
|
|
+ keepalive_timeout 65;
|
|
|
+ types_hash_max_size 2048;
|
|
|
+
|
|
|
+ # Virtual Host Configs
|
|
|
+ include /etc/nginx/conf.d/*.conf;
|
|
|
+ include /etc/nginx/sites-enabled/*;
|
|
|
+
|
|
|
+ server {
|
|
|
+ listen 80 default_server;
|
|
|
+ listen [::]:80 default_server;
|
|
|
+ server_name _;
|
|
|
+ root /var/www/html;
|
|
|
+ index index.html index.htm index.nginx-debian.html;
|
|
|
+
|
|
|
+ access_log /var/log/nginx/default.access.log;
|
|
|
+ error_log /var/log/nginx/default.error.log;
|
|
|
+
|
|
|
+ location / {
|
|
|
+ try_files $uri $uri/ =404;
|
|
|
+ }
|
|
|
+
|
|
|
+ location ~ /\.ht {
|
|
|
+ deny all;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ server {
|
|
|
+ listen 443 ssl http2;
|
|
|
+ server_name example.com;
|
|
|
+ root /var/www/example.com;
|
|
|
+
|
|
|
+ access_log /var/log/nginx/example.access.log combined;
|
|
|
+ error_log /var/log/nginx/example.error.log info;
|
|
|
+
|
|
|
+ ssl_certificate /etc/ssl/certs/example.com.pem;
|
|
|
+ ssl_certificate_key /etc/ssl/private/example.com.key;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+stream {
|
|
|
+ error_log /var/log/nginx/stream.error.log info;
|
|
|
+
|
|
|
+ upstream backend {
|
|
|
+ server 192.168.1.100:3306;
|
|
|
+ server 192.168.1.101:3306;
|
|
|
+ }
|
|
|
+
|
|
|
+ server {
|
|
|
+ listen 3306;
|
|
|
+ proxy_pass backend;
|
|
|
+ proxy_timeout 1s;
|
|
|
+ proxy_responses 1;
|
|
|
+ }
|
|
|
+}
|
|
|
+`
|
|
|
+
|
|
|
+ // Test that we can extract the main access log and error log from complex config
|
|
|
+ accessLogRegex := regexp.MustCompile(AccessLogRegexPattern)
|
|
|
+ errorLogRegex := regexp.MustCompile(ErrorLogRegexPattern)
|
|
|
+
|
|
|
+ // Find all access logs
|
|
|
+ accessMatches := accessLogRegex.FindAllStringSubmatch(complexConfig, -1)
|
|
|
+ if len(accessMatches) == 0 {
|
|
|
+ t.Error("Expected to find access log directives in complex config")
|
|
|
+ } else {
|
|
|
+ firstAccessLog := accessMatches[0][1]
|
|
|
+ expectedFirstAccess := "/var/log/nginx/access.log"
|
|
|
+ if firstAccessLog != expectedFirstAccess {
|
|
|
+ t.Errorf("Expected first access log to be %s, got %s", expectedFirstAccess, firstAccessLog)
|
|
|
+ }
|
|
|
+ t.Logf("Found %d access log directives, first: %s", len(accessMatches), firstAccessLog)
|
|
|
+ }
|
|
|
+
|
|
|
+ // Find all error logs
|
|
|
+ errorMatches := errorLogRegex.FindAllStringSubmatch(complexConfig, -1)
|
|
|
+ if len(errorMatches) == 0 {
|
|
|
+ t.Error("Expected to find error log directives in complex config")
|
|
|
+ } else {
|
|
|
+ firstErrorLog := errorMatches[0][1]
|
|
|
+ expectedFirstError := "/var/log/nginx/error.log"
|
|
|
+ if firstErrorLog != expectedFirstError {
|
|
|
+ t.Errorf("Expected first error log to be %s, got %s", expectedFirstError, firstErrorLog)
|
|
|
+ }
|
|
|
+ t.Logf("Found %d error log directives, first: %s", len(errorMatches), firstErrorLog)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestCommentedDirectivesIgnored(t *testing.T) {
|
|
|
+ testConfig := `
|
|
|
+# Main configuration
|
|
|
+user nginx;
|
|
|
+worker_processes auto;
|
|
|
+
|
|
|
+# These should be ignored
|
|
|
+# error_log /var/log/nginx/commented.error.log notice;
|
|
|
+# access_log /var/log/nginx/commented.access.log main;
|
|
|
+
|
|
|
+# Real directives
|
|
|
+error_log /var/log/nginx/error.log warn;
|
|
|
+
|
|
|
+http {
|
|
|
+ # This should be ignored too
|
|
|
+ # access_log /var/log/nginx/commented.http.access.log combined;
|
|
|
+
|
|
|
+ # Real directive
|
|
|
+ access_log /var/log/nginx/access.log main;
|
|
|
+
|
|
|
+ server {
|
|
|
+ listen 80;
|
|
|
+ server_name example.com;
|
|
|
+
|
|
|
+ # Commented server-level logs should be ignored
|
|
|
+ # access_log /var/log/nginx/commented.server.access.log;
|
|
|
+ # error_log /var/log/nginx/commented.server.error.log warn;
|
|
|
+
|
|
|
+ # Real server-level logs
|
|
|
+ access_log /var/log/nginx/server.access.log;
|
|
|
+ error_log /var/log/nginx/server.error.log info;
|
|
|
+ }
|
|
|
+}
|
|
|
+`
|
|
|
+
|
|
|
+ // Test access log parsing ignores comments
|
|
|
+ accessLogRegex := regexp.MustCompile(AccessLogRegexPattern)
|
|
|
+ accessMatches := accessLogRegex.FindAllStringSubmatch(testConfig, -1)
|
|
|
+
|
|
|
+ expectedAccessLogs := []string{
|
|
|
+ "/var/log/nginx/access.log",
|
|
|
+ "/var/log/nginx/server.access.log",
|
|
|
+ }
|
|
|
+
|
|
|
+ if len(accessMatches) != len(expectedAccessLogs) {
|
|
|
+ t.Errorf("Expected %d access log matches, got %d", len(expectedAccessLogs), len(accessMatches))
|
|
|
+ }
|
|
|
+
|
|
|
+ for i, match := range accessMatches {
|
|
|
+ if i < len(expectedAccessLogs) {
|
|
|
+ if match[1] != expectedAccessLogs[i] {
|
|
|
+ t.Errorf("Expected access log %d to be %s, got %s", i, expectedAccessLogs[i], match[1])
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Test error log parsing ignores comments
|
|
|
+ errorLogRegex := regexp.MustCompile(ErrorLogRegexPattern)
|
|
|
+ errorMatches := errorLogRegex.FindAllStringSubmatch(testConfig, -1)
|
|
|
+
|
|
|
+ expectedErrorLogs := []string{
|
|
|
+ "/var/log/nginx/error.log",
|
|
|
+ "/var/log/nginx/server.error.log",
|
|
|
+ }
|
|
|
+
|
|
|
+ if len(errorMatches) != len(expectedErrorLogs) {
|
|
|
+ t.Errorf("Expected %d error log matches, got %d", len(expectedErrorLogs), len(errorMatches))
|
|
|
+ }
|
|
|
+
|
|
|
+ for i, match := range errorMatches {
|
|
|
+ if i < len(expectedErrorLogs) {
|
|
|
+ if match[1] != expectedErrorLogs[i] {
|
|
|
+ t.Errorf("Expected error log %d to be %s, got %s", i, expectedErrorLogs[i], match[1])
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|