1
0

server_settings_test.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. package tuic
  2. import (
  3. "fmt"
  4. "slices"
  5. "strings"
  6. "testing"
  7. "time"
  8. "github.com/mhsanaei/3x-ui/v3/internal/logger"
  9. )
  10. func TestNormalizeCongestionControl(t *testing.T) {
  11. tests := []struct {
  12. name string
  13. input string
  14. want string
  15. wantValid bool
  16. }{
  17. {name: "default", want: "bbr", wantValid: true},
  18. {name: "bbr", input: "bbr", want: "bbr", wantValid: true},
  19. {name: "cubic", input: "cubic", want: "cubic", wantValid: true},
  20. {name: "new reno", input: "new_reno", want: "new_reno", wantValid: true},
  21. {name: "reno alias", input: "reno", want: "new_reno", wantValid: true},
  22. {name: "unknown falls back to reno", input: "quic", want: "new_reno"},
  23. }
  24. for _, test := range tests {
  25. t.Run(test.name, func(t *testing.T) {
  26. got, valid := normalizeCongestionControl(test.input)
  27. if got != test.want || valid != test.wantValid {
  28. t.Fatalf("normalizeCongestionControl(%q) = (%q, %t), want (%q, %t)", test.input, got, valid, test.want, test.wantValid)
  29. }
  30. })
  31. }
  32. }
  33. func TestLogfUsesCommonLoggerAndHonorsThreshold(t *testing.T) {
  34. tests := []struct {
  35. level string
  36. want []string
  37. }{
  38. {level: "debug", want: []string{"debug", "info", "warn", "error"}},
  39. {level: "info", want: []string{"info", "warn", "error"}},
  40. {level: "warn", want: []string{"warn", "error"}},
  41. {level: "error", want: []string{"error"}},
  42. }
  43. for _, test := range tests {
  44. t.Run(test.level, func(t *testing.T) {
  45. marker := fmt.Sprintf("tuic-log-%s-%d", test.level, time.Now().UnixNano())
  46. server := &Server{id: 99001}
  47. server.updateRuntimeSettings("log-test", "bbr", test.level)
  48. for _, level := range []struct {
  49. name string
  50. value uint32
  51. }{{"debug", tuicLogDebug}, {"info", tuicLogInfo}, {"warn", tuicLogWarn}, {"error", tuicLogError}} {
  52. server.logf(level.value, "%s-%s", marker, level.name)
  53. }
  54. logs := strings.Join(logger.GetLogs(10000, "DEBUG"), "\n")
  55. for _, name := range []string{"debug", "info", "warn", "error"} {
  56. want := slices.Contains(test.want, name)
  57. got := strings.Contains(logs, marker+"-"+name)
  58. if got != want {
  59. t.Errorf("log level %s present = %t, want %t", name, got, want)
  60. }
  61. }
  62. if !strings.Contains(logs, "inbound 99001 (log-test)") {
  63. t.Fatal("TUIC event was not written through the shared 3x-ui logger")
  64. }
  65. })
  66. }
  67. }
  68. func TestLogLevelsAreIsolatedPerInboundAndUpdateLive(t *testing.T) {
  69. marker := fmt.Sprintf("tuic-log-isolation-%d", time.Now().UnixNano())
  70. debugInbound := &Server{id: 99011}
  71. errorInbound := &Server{id: 99012}
  72. debugInbound.updateRuntimeSettings("debug-inbound", "bbr", "debug")
  73. errorInbound.updateRuntimeSettings("error-inbound", "bbr", "error")
  74. debugInbound.logf(tuicLogInfo, "%s-debug", marker)
  75. errorInbound.logf(tuicLogInfo, "%s-hidden", marker)
  76. debugInbound.UpdateRuntimeSettings("debug-inbound", "bbr", "warn")
  77. debugInbound.logf(tuicLogInfo, "%s-hidden-after-update", marker)
  78. debugInbound.logf(tuicLogWarn, "%s-warn-after-update", marker)
  79. logs := strings.Join(logger.GetLogs(10000, "DEBUG"), "\n")
  80. if !strings.Contains(logs, marker+"-debug") || !strings.Contains(logs, marker+"-warn-after-update") {
  81. t.Fatal("expected permitted events from debug inbound")
  82. }
  83. if strings.Contains(logs, marker+"-hidden") || strings.Contains(logs, marker+"-hidden-after-update") {
  84. t.Fatal("a TUIC inbound emitted an event below its own log threshold")
  85. }
  86. }
  87. func TestEnsureStartupFailureHonorsInboundLogThreshold(t *testing.T) {
  88. tests := []struct {
  89. level string
  90. want bool
  91. }{
  92. {level: "error", want: false},
  93. {level: "warn", want: true},
  94. }
  95. for _, test := range tests {
  96. t.Run(test.level, func(t *testing.T) {
  97. marker := fmt.Sprintf("tuic-start-failure-%s-%d", test.level, time.Now().UnixNano())
  98. manager := &Manager{servers: map[int]*managed{}, lastStartErr: map[int]string{}, pendingTraffic: map[string]ClientTrafficDelta{}}
  99. err := manager.Ensure(Instance{
  100. Id: 99031,
  101. Tag: marker,
  102. Listen: "127.0.0.1",
  103. Port: 0,
  104. LogLevel: test.level,
  105. CongestionControl: "bbr",
  106. Clients: []TuicClientSettings{{UUID: "a0000000-0000-0000-0000-000000000031", Password: "p", Email: "startup@x"}},
  107. })
  108. if err == nil {
  109. t.Fatal("Ensure unexpectedly started without a certificate")
  110. }
  111. logs := strings.Join(logger.GetLogs(10000, "DEBUG"), "\n")
  112. got := strings.Contains(logs, marker+"): failed to start server")
  113. if got != test.want {
  114. t.Fatalf("startup warning logged = %t, want %t", got, test.want)
  115. }
  116. })
  117. }
  118. }