server_public_ip_async_test.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. package service
  2. import (
  3. "net/http"
  4. "net/http/httptest"
  5. "path/filepath"
  6. "testing"
  7. "time"
  8. "github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
  9. )
  10. // A box with no IPv6 route spends 3s per lookup service, and a status sample
  11. // that waits for that is a panel reporting nothing for the first ~15s.
  12. func TestStatusSampleDoesNotWaitOnPublicIPLookup(t *testing.T) {
  13. dbDir := t.TempDir()
  14. t.Setenv("XUI_DB_FOLDER", dbDir)
  15. dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
  16. release := make(chan struct{})
  17. srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  18. select {
  19. case <-release:
  20. case <-r.Context().Done():
  21. return
  22. }
  23. _, _ = w.Write([]byte("203.0.113.7"))
  24. }))
  25. t.Cleanup(srv.Close)
  26. savedV4, savedV6 := publicIPv4Services, publicIPv6Services
  27. publicIPv4Services = []string{srv.URL}
  28. publicIPv6Services = []string{srv.URL}
  29. t.Cleanup(func() { publicIPv4Services, publicIPv6Services = savedV4, savedV6 })
  30. svc := &ServerService{}
  31. status := svc.CurrentStatus()
  32. if status == nil {
  33. t.Fatal("CurrentStatus returned nil while the IP lookup was in flight")
  34. }
  35. if status.PublicIP.IPv4 != "" {
  36. t.Fatalf("the sample waited for the lookup: PublicIP.IPv4 = %q, want it still unresolved", status.PublicIP.IPv4)
  37. }
  38. close(release)
  39. deadline := time.Now().Add(10 * time.Second)
  40. for {
  41. if ipv4, _ := svc.publicIPs(); ipv4 == "203.0.113.7" {
  42. return
  43. }
  44. if time.Now().After(deadline) {
  45. t.Fatal("the background lookup never cached the public IP")
  46. }
  47. time.Sleep(20 * time.Millisecond)
  48. }
  49. }