tests: replace time.Sleep with testing/synctest

Goal

Tests that waited for goroutines with time.Sleep ("give the other requests time to pile up", "give the proxy time to notice the hang-up", "ensure the TTL has elapsed") or polled in a loop were timing gambles: slow on a fast machine and flaky on a loaded one. Run them in testing/synctest bubbles instead. synctest.Wait() returns exactly when everything else is blocked, and timeouts, TTLs and sleeps pass on a fake clock, instantly and exactly. That also turns assertions such as "took less than 5s" into exact ones ("took RevalidateWait").

Design

  • A goroutine blocked on a real socket keeps a bubble's clock from moving, so the HTTP harnesses (proxy, lxdproxy, gomodproxy, snapproxy, idletimeout, fill, reqlog) move to httptest's in-memory network: httptest.NewTestServer plus Server.Client(), whose transport sends every request to that server whatever host it names. That replaces the fake-DNS dialer in internal/proxy's harness.
  • NewTestServer is new in Go 1.27, so go.mod goes from 1.26.5 to 1.27.1 (CI's image is already golang:1.27).
  • lxdindex's checkpoint test compared file mtimes 10ms apart. It now backdates the file with os.Chtimes, which synctest cannot help with (real filesystem time).

Found along the way

httprange.Serve relied on TCPConn.ReadFrom to get the bytes of a still-filling entity to the client. Over any other connection, and for any chunked response (a 206 to a Range resume, say), up to 4 KiB of what had already arrived sat in the server's write buffer. With FlushHeaders set it now flushes after each chunk.

Edited by Zygmunt Krynicki