upstream_expansion_test.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. package site
  2. import (
  3. "os"
  4. "testing"
  5. "time"
  6. "github.com/0xJacky/Nginx-UI/internal/config"
  7. "github.com/0xJacky/Nginx-UI/internal/upstream"
  8. )
  9. func TestBuildConfig_UpstreamExpansion(t *testing.T) {
  10. // Setup upstream service with test data
  11. service := upstream.GetUpstreamService()
  12. service.ClearTargets() // Clear any existing data
  13. // Add test upstream definitions
  14. webBackendServers := []upstream.ProxyTarget{
  15. {Host: "192.168.1.100", Port: "8080", Type: "upstream"},
  16. {Host: "192.168.1.101", Port: "8080", Type: "upstream"},
  17. {Host: "::1", Port: "8080", Type: "upstream"},
  18. }
  19. service.UpdateUpstreamDefinition("web_backend", webBackendServers, "test.conf")
  20. apiBackendServers := []upstream.ProxyTarget{
  21. {Host: "api1.example.com", Port: "3000", Type: "upstream"},
  22. {Host: "api2.example.com", Port: "3000", Type: "upstream"},
  23. }
  24. service.UpdateUpstreamDefinition("api_backend", apiBackendServers, "test.conf")
  25. // Create a mock indexed site with proxy targets that reference upstreams
  26. IndexedSites["test_site"] = &SiteIndex{
  27. Path: "test_site",
  28. Content: "test content",
  29. Urls: []string{"example.com"},
  30. ProxyTargets: []ProxyTarget{
  31. {Host: "web_backend", Port: "80", Type: "proxy_pass"}, // This should be expanded
  32. {Host: "api_backend", Port: "80", Type: "proxy_pass"}, // This should be expanded
  33. {Host: "direct.example.com", Port: "8080", Type: "proxy_pass"}, // This should remain as-is
  34. },
  35. }
  36. // Create mock file info
  37. fileInfo := &mockFileInfo{
  38. name: "test_site",
  39. size: 1024,
  40. modTime: time.Now(),
  41. isDir: false,
  42. }
  43. // Call buildConfig
  44. result := buildConfig("test_site", fileInfo, config.StatusEnabled, 0, nil)
  45. // Verify the results
  46. expectedTargetCount := 6 // 3 from web_backend + 2 from api_backend + 1 direct
  47. if len(result.ProxyTargets) != expectedTargetCount {
  48. t.Errorf("Expected %d proxy targets, got %d", expectedTargetCount, len(result.ProxyTargets))
  49. for i, target := range result.ProxyTargets {
  50. t.Logf("Target %d: Host=%s, Port=%s, Type=%s", i, target.Host, target.Port, target.Type)
  51. }
  52. }
  53. // Check for specific targets
  54. expectedHosts := map[string]bool{
  55. "192.168.1.100": false,
  56. "192.168.1.101": false,
  57. "::1": false,
  58. "api1.example.com": false,
  59. "api2.example.com": false,
  60. "direct.example.com": false,
  61. }
  62. for _, target := range result.ProxyTargets {
  63. if _, exists := expectedHosts[target.Host]; exists {
  64. expectedHosts[target.Host] = true
  65. }
  66. }
  67. // Verify all expected hosts were found
  68. for host, found := range expectedHosts {
  69. if !found {
  70. t.Errorf("Expected to find host %s in proxy targets", host)
  71. }
  72. }
  73. // Verify that upstream names are not present in the final targets
  74. for _, target := range result.ProxyTargets {
  75. if target.Host == "web_backend" || target.Host == "api_backend" {
  76. t.Errorf("Upstream name %s should have been expanded, not included directly", target.Host)
  77. }
  78. }
  79. // Clean up
  80. delete(IndexedSites, "test_site")
  81. }
  82. func TestBuildConfig_NoUpstreamExpansion(t *testing.T) {
  83. // Test case where proxy targets don't reference any upstreams
  84. IndexedSites["test_site_no_upstream"] = &SiteIndex{
  85. Path: "test_site_no_upstream",
  86. Content: "test content",
  87. Urls: []string{"example.com"},
  88. ProxyTargets: []ProxyTarget{
  89. {Host: "direct1.example.com", Port: "8080", Type: "proxy_pass"},
  90. {Host: "direct2.example.com", Port: "9000", Type: "proxy_pass"},
  91. {Host: "::1", Port: "3000", Type: "proxy_pass"},
  92. },
  93. }
  94. fileInfo := &mockFileInfo{
  95. name: "test_site_no_upstream",
  96. size: 1024,
  97. modTime: time.Now(),
  98. isDir: false,
  99. }
  100. result := buildConfig("test_site_no_upstream", fileInfo, config.StatusEnabled, 0, nil)
  101. // Should have exactly 3 targets, unchanged
  102. if len(result.ProxyTargets) != 3 {
  103. t.Errorf("Expected 3 proxy targets, got %d", len(result.ProxyTargets))
  104. }
  105. expectedTargets := []config.ProxyTarget{
  106. {Host: "direct1.example.com", Port: "8080", Type: "proxy_pass"},
  107. {Host: "direct2.example.com", Port: "9000", Type: "proxy_pass"},
  108. {Host: "::1", Port: "3000", Type: "proxy_pass"},
  109. }
  110. for i, expected := range expectedTargets {
  111. if i >= len(result.ProxyTargets) {
  112. t.Errorf("Missing target %d", i)
  113. continue
  114. }
  115. actual := result.ProxyTargets[i]
  116. if actual.Host != expected.Host || actual.Port != expected.Port || actual.Type != expected.Type {
  117. t.Errorf("Target %d mismatch: expected %+v, got %+v", i, expected, actual)
  118. }
  119. }
  120. // Clean up
  121. delete(IndexedSites, "test_site_no_upstream")
  122. }
  123. // mockFileInfo implements os.FileInfo for testing
  124. type mockFileInfo struct {
  125. name string
  126. size int64
  127. modTime time.Time
  128. isDir bool
  129. }
  130. func (m *mockFileInfo) Name() string { return m.name }
  131. func (m *mockFileInfo) Size() int64 { return m.size }
  132. func (m *mockFileInfo) Mode() os.FileMode { return 0644 }
  133. func (m *mockFileInfo) ModTime() time.Time { return m.modTime }
  134. func (m *mockFileInfo) IsDir() bool { return m.isDir }
  135. func (m *mockFileInfo) Sys() interface{} { return nil }