소스 검색

test: stop swapping http.DefaultTransport in the Happ network test (#6742)

* test: stop swapping http.DefaultTransport in the Happ network test

The Happ local-generation test replaced the http.DefaultTransport global to
refuse sockets. resolvePublicIPsInBackground fires a fire-and-forget resolver
(ServerService.GetStatus -> resolvePublicIPs -> getPublicIP), and that
goroutine can outlive the test that scheduled it, so a later test writes the
global while the resolver is reading it: a data race that `make race`
(-shuffle=on) only reports when the status test happens to run first.

Route the lookup transport through an atomic swap point and count in-flight
lookups, so the test stubs its own path and waits for earlier resolvers to
settle before installing it. That also stops another test's dials from
landing in this test's zero-network tally.

Reproduced on the parent commit with -shuffle=6 (read in getPublicIP,
previous write in TestHappGenerateLocallyWithoutNetwork); the same seed is
clean with this change, across repeats and for the whole package under -race.

* test: prove the Happ network guard intercepts panel egress

The PR review pointed out that HappService.Generate never reaches a stub
installed only on the public-IP lookup, so the "zero network attempts"
assertion could not fail. Move the override onto the panel's shared egress
seam — getPublicIP and SettingService.NewProxiedHTTPClient — and gate the
test on a canary request that must be refused and must move the tally, so a
future outbound call from local generation is reported instead of passing
unnoticed.

* test(service): stop the cold-status test leaking a public-IP resolver

The race CI hit (run 37345781756) came from TestCurrentStatusSamplesBeforeFirstTick:
its CurrentStatus call starts resolvePublicIPsInBackground, a goroutine that
makes real internet requests and outlives the test. On a runner without
IPv6 every lookup waits out its 3s timeout, so the goroutine is still
building clients from http.DefaultTransport when the Happ test swaps it.

Pre-settling the IP cache keeps that test from starting the resolver at
all, so no unit test reaches the internet or leaks the goroutine. This
replaces the earlier panelEgressTransport / panelEgressLookups seam, which
added test-only hooks to production code without removing the leak.

Reproduced in golang:1.27-bookworm with egress routed to a blackhole
(HTTPS_PROXY=http://10.255.255.1:9, -race -count=3 on the two tests): the
same server.go:406 race as CI before, clean over -count=5 after.

---------

Co-authored-by: MHSanaei <[email protected]>
冰 17 시간 전
부모
커밋
f0016f6cf9
1개의 변경된 파일과 3개의 추가작업 그리고 1개의 파일을 삭제
  1. 3 1
      internal/web/service/server_cold_status_test.go

+ 3 - 1
internal/web/service/server_cold_status_test.go

@@ -14,7 +14,9 @@ func TestCurrentStatusSamplesBeforeFirstTick(t *testing.T) {
 	t.Setenv("XUI_DB_FOLDER", dbDir)
 	dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
 
-	svc := &ServerService{}
+	// A settled IP cache keeps GetStatus from starting a public-IP resolver that
+	// outlives this test and races http.DefaultTransport in later ones.
+	svc := &ServerService{cachedIPv4: "192.0.2.1", noIPv6: true}
 	if svc.LastStatus() != nil {
 		t.Fatal("a fresh ServerService should hold no snapshot yet")
 	}