sandbox_test.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. package nginx
  2. import (
  3. "os"
  4. "strings"
  5. "testing"
  6. )
  7. func TestCreateSandbox(t *testing.T) {
  8. namespaceInfo := &NamespaceInfo{
  9. ID: 1,
  10. Name: "test-namespace",
  11. }
  12. sitePaths := []string{"site1.conf", "site2.conf"}
  13. streamPaths := []string{"stream1.conf"}
  14. sandbox, err := createSandbox(namespaceInfo, sitePaths, streamPaths)
  15. if err != nil {
  16. t.Fatalf("Failed to create sandbox: %v", err)
  17. }
  18. defer sandbox.Cleanup()
  19. // Verify sandbox directory exists
  20. if _, err := os.Stat(sandbox.Dir); os.IsNotExist(err) {
  21. t.Errorf("Sandbox directory does not exist: %s", sandbox.Dir)
  22. }
  23. // Verify config file exists
  24. if _, err := os.Stat(sandbox.ConfigPath); os.IsNotExist(err) {
  25. t.Errorf("Sandbox config file does not exist: %s", sandbox.ConfigPath)
  26. }
  27. // Verify namespace info
  28. if sandbox.Namespace.ID != 1 {
  29. t.Errorf("Expected namespace ID 1, got %d", sandbox.Namespace.ID)
  30. }
  31. }
  32. func TestSandboxCleanup(t *testing.T) {
  33. sandbox, err := createSandbox(nil, []string{}, []string{})
  34. if err != nil {
  35. t.Fatalf("Failed to create sandbox: %v", err)
  36. }
  37. sandboxDir := sandbox.Dir
  38. // Cleanup
  39. sandbox.Cleanup()
  40. // Verify directory is removed
  41. if _, err := os.Stat(sandboxDir); !os.IsNotExist(err) {
  42. t.Errorf("Sandbox directory still exists after cleanup: %s", sandboxDir)
  43. }
  44. }
  45. func TestGenerateSandboxConfig(t *testing.T) {
  46. // Skip this test as it requires mocking GetConfEntryPath
  47. // The logic is tested in TestReplaceIncludeDirectives instead
  48. t.Skip("Skipping - requires dependency injection refactoring")
  49. }
  50. func TestReplaceIncludeDirectives(t *testing.T) {
  51. tests := []struct {
  52. name string
  53. mainConf string
  54. includePatterns []string
  55. expectContains []string
  56. expectNotContain []string
  57. }{
  58. {
  59. name: "Replace HTTP includes",
  60. mainConf: `http {
  61. include /etc/nginx/sites-enabled/*;
  62. }`,
  63. includePatterns: []string{
  64. " include /etc/nginx/sites-enabled/site1.conf;",
  65. " include /etc/nginx/sites-enabled/site2.conf;",
  66. },
  67. expectContains: []string{
  68. "include /etc/nginx/sites-enabled/site1.conf",
  69. "include /etc/nginx/sites-enabled/site2.conf",
  70. "Sandbox-specific includes",
  71. },
  72. expectNotContain: []string{
  73. "include /etc/nginx/sites-enabled/*",
  74. },
  75. },
  76. {
  77. name: "Replace Stream includes",
  78. mainConf: `stream {
  79. include /etc/nginx/streams-enabled/*;
  80. }`,
  81. includePatterns: []string{
  82. " include /etc/nginx/streams-enabled/stream1.conf;",
  83. },
  84. expectContains: []string{
  85. "include /etc/nginx/streams-enabled/stream1.conf",
  86. "Sandbox-specific includes",
  87. },
  88. expectNotContain: []string{
  89. "include /etc/nginx/streams-enabled/*",
  90. },
  91. },
  92. {
  93. name: "Rewrite other includes to sandbox",
  94. mainConf: `http {
  95. include /etc/nginx/mime.types;
  96. include /etc/nginx/conf.d/*.conf;
  97. include /etc/nginx/sites-enabled/*;
  98. }`,
  99. includePatterns: []string{
  100. " include /etc/nginx/sites-enabled/site1.conf;",
  101. },
  102. expectContains: []string{
  103. "include /tmp/test-sandbox/mime.types", // Rewritten to sandbox
  104. "include /tmp/test-sandbox/conf.d/*.conf", // Rewritten to sandbox
  105. "include /etc/nginx/sites-enabled/site1.conf",
  106. },
  107. expectNotContain: []string{
  108. "include /etc/nginx/sites-enabled/*",
  109. "include /etc/nginx/mime.types", // Should be rewritten
  110. "include /etc/nginx/conf.d/*.conf", // Should be rewritten
  111. },
  112. },
  113. }
  114. for _, tt := range tests {
  115. t.Run(tt.name, func(t *testing.T) {
  116. sandboxDir := "/tmp/test-sandbox"
  117. result := replaceIncludeDirectives(tt.mainConf, tt.includePatterns, sandboxDir)
  118. for _, expected := range tt.expectContains {
  119. if !strings.Contains(result, expected) {
  120. t.Errorf("Expected result to contain %q, but it doesn't.\nResult:\n%s", expected, result)
  121. }
  122. }
  123. for _, notExpected := range tt.expectNotContain {
  124. if strings.Contains(result, notExpected) {
  125. t.Errorf("Expected result NOT to contain %q, but it does.\nResult:\n%s", notExpected, result)
  126. }
  127. }
  128. })
  129. }
  130. }
  131. func TestReplaceIncludeDirectivesEdgeCases(t *testing.T) {
  132. t.Run("Empty include patterns", func(t *testing.T) {
  133. mainConf := `http {
  134. include /etc/nginx/sites-enabled/*;
  135. }`
  136. result := replaceIncludeDirectives(mainConf, []string{}, "/tmp/test-sandbox")
  137. // Should still add comment but no includes
  138. if !strings.Contains(result, "Sandbox-specific includes") {
  139. t.Error("Expected sandbox comment even with empty patterns")
  140. }
  141. })
  142. t.Run("No http or stream blocks", func(t *testing.T) {
  143. mainConf := `events {
  144. worker_connections 1024;
  145. }`
  146. includePatterns := []string{" include /etc/nginx/sites-enabled/site1.conf;"}
  147. result := replaceIncludeDirectives(mainConf, includePatterns, "/tmp/test-sandbox")
  148. // Should preserve original config
  149. if !strings.Contains(result, "worker_connections 1024") {
  150. t.Error("Original config not preserved when no http/stream blocks")
  151. }
  152. })
  153. t.Run("Nested braces", func(t *testing.T) {
  154. mainConf := `http {
  155. server {
  156. location / {
  157. return 200;
  158. }
  159. }
  160. include /etc/nginx/sites-enabled/*;
  161. }`
  162. includePatterns := []string{" include /etc/nginx/sites-enabled/site1.conf;"}
  163. result := replaceIncludeDirectives(mainConf, includePatterns, "/tmp/test-sandbox")
  164. // Should preserve nested structure
  165. if !strings.Contains(result, "location /") {
  166. t.Error("Nested location directive not preserved")
  167. }
  168. // Should replace include
  169. if strings.Contains(result, "include /etc/nginx/sites-enabled/*") {
  170. t.Error("Generic include should be replaced even with nested braces")
  171. }
  172. })
  173. }
  174. func TestSandboxTestConfigWithPaths(t *testing.T) {
  175. // Skip this integration test - requires nginx installation and proper setup
  176. t.Skip("Skipping integration test - requires nginx binary and proper configuration")
  177. }
  178. func BenchmarkCreateSandbox(b *testing.B) {
  179. namespaceInfo := &NamespaceInfo{
  180. ID: 1,
  181. Name: "bench-namespace",
  182. }
  183. sitePaths := []string{"site1.conf", "site2.conf", "site3.conf"}
  184. streamPaths := []string{"stream1.conf"}
  185. b.ResetTimer()
  186. for i := 0; i < b.N; i++ {
  187. sandbox, err := createSandbox(namespaceInfo, sitePaths, streamPaths)
  188. if err != nil {
  189. b.Fatalf("Failed to create sandbox: %v", err)
  190. }
  191. sandbox.Cleanup()
  192. }
  193. }
  194. func BenchmarkReplaceIncludeDirectives(b *testing.B) {
  195. mainConf := `
  196. events {
  197. worker_connections 1024;
  198. }
  199. http {
  200. include /etc/nginx/mime.types;
  201. include /etc/nginx/conf.d/*.conf;
  202. include /etc/nginx/sites-enabled/*;
  203. server {
  204. listen 80;
  205. server_name default;
  206. }
  207. }
  208. stream {
  209. include /etc/nginx/streams-enabled/*;
  210. }
  211. `
  212. includePatterns := []string{
  213. " include /etc/nginx/sites-enabled/site1.conf;",
  214. " include /etc/nginx/sites-enabled/site2.conf;",
  215. " include /etc/nginx/sites-enabled/site3.conf;",
  216. " include /etc/nginx/streams-enabled/stream1.conf;",
  217. }
  218. b.ResetTimer()
  219. for i := 0; i < b.N; i++ {
  220. _ = replaceIncludeDirectives(mainConf, includePatterns, "/tmp/test-sandbox")
  221. }
  222. }