Documentation
¶
Overview ¶
Package netfixture gives a test an HTTP address that stops answering without giving its port away.
A test that needed "a server that is gone" used to start an httptest server and close it, keeping the URL. Closing the server gives the port back to the kernel at once, and the next listener given that port can answer the request the test exists to see fail: one of the package's parallel tests starting a server of its own, or a test binary of another package running beside it in the same coverage run. cmd/bench_resources had a test fail that way in CI, and issue 1132 moved sixteen more sites off the same pattern.
DeadEndpoint is an address that accepts every connection and closes it before reading a byte, for the whole test. StoppableServer is a server that answers through its handler until the test calls StoppableServer.Stop, and from then on hangs up on every request without answering, keeping its port: it is for the test that needs the instance to answer first and then go away, which closing an httptest server used to stand for.
What a client meets at either address is not "connection refused". The connection is made and then ends, with an EOF or a reset, before any response arrives. A test that held a closed server's address to refuse the connection has to say what it actually checks instead: that no answer came.
cmd/audit_test_closed_servers keeps the old pattern from coming back: it reports an httptest server closed while its address, or a value built from it, is still used later in the same function.
The package sits beside github.com/jmrplens/gitlab-mcp-server/v3/internal/testutil rather than inside it because internal/gitlab's own tests use it, and testutil imports internal/gitlab: importing testutil from those tests is an import cycle the compiler refuses. It imports nothing of this module, so any test in it may use it.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DeadEndpoint ¶
DeadEndpoint returns the base URL, "http://127.0.0.1:port", of an address nothing answers on for the rest of the test.
A listener holds the port and closes every connection it accepts before reading a byte, so every request sent there fails before any response, which code under test handles as it would an instance that is gone. Nothing else can be given the port while the test runs, which is the whole difference from a closed httptest server. The listener is closed by the cleanup DeadEndpoint registers, and cleanups run last registered first, so the port is held through every cleanup registered after the call and given back before any registered earlier: a cleanup registered before the call must not send a request to the address.
The request does not fail with "connection refused": the connection is made, then ends with an EOF or a reset. A caller that needs only the host and port trims the scheme.
Types ¶
type StoppableServer ¶
type StoppableServer struct {
// URL is the server's base URL, "http://127.0.0.1:port", the same before
// and after Stop.
URL string
// contains filtered or unexported fields
}
StoppableServer is an HTTP server on a loopback port that answers through its handler until StoppableServer.Stop is called, and from then on hangs up on every request without answering. It keeps its port, stopped or not, until the cleanup NewStoppableServer registers closes it, which runs after every cleanup registered later and before any registered earlier.
It is for the test whose instance has to answer first and then go away: a client bound to the address, a cache keyed on it. Closing an httptest server gave that test its "gone" by freeing the port, which anything else could then be given.
func NewStoppableServer ¶
func NewStoppableServer(tb testing.TB, handler http.Handler) *StoppableServer
NewStoppableServer starts a server answering through handler, closed by a cleanup it registers on tb.
func (*StoppableServer) Stop ¶
func (s *StoppableServer) Stop()
Stop makes the server hang up on every request from now on, including one sent on a connection a client kept open from before, and closes the connections already open, so a response in progress ends where it is. The port stays held. Calling it again changes nothing.