Compare commits
1
Commits
next
...
2dfd67b490
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2dfd67b490 |
No files matched your search
@@ -153,14 +153,10 @@ func TestUnsetRouteWatchChangesNothing(t *testing.T) {
|
|||||||
func TestUnreachableRouteWatchLetsTheRequestThroughAndSaysWhy(t *testing.T) {
|
func TestUnreachableRouteWatchLetsTheRequestThroughAndSaysWhy(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// A stand-in that is closed at once, so that the port refuses connections.
|
// Another test can take a closed server's port at once, so routewatch's
|
||||||
dead := httptest.NewServer(http.NotFoundHandler())
|
// address here is a multicast address, to which TCP cannot connect.
|
||||||
url := dead.URL
|
|
||||||
|
|
||||||
dead.Close()
|
|
||||||
|
|
||||||
s, _, _ := startWithClock(t, "", map[string]string{
|
s, _, _ := startWithClock(t, "", map[string]string{
|
||||||
lookupSource: off, routeWatchURL: url,
|
lookupSource: off, routeWatchURL: "http://224.0.0.1",
|
||||||
})
|
})
|
||||||
|
|
||||||
wantTagsMissing(t, s.get(fromDE, http.StatusOK, requestlog.ActionForward),
|
wantTagsMissing(t, s.get(fromDE, http.StatusOK, requestlog.ActionForward),
|
||||||
|
|||||||
@@ -239,12 +239,17 @@ func TestAnswerRoutewatchCannotBeTakenFromFails(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRefusedConnectionFailsTheQueryAndTheLogOmitsTheClient(t *testing.T) {
|
func TestUnreachableRoutewatchFailsTheQueryAndTheLogOmitsTheClient(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
f := newFixture(t, answering(routedAnswer))
|
f := newFixture(t, answering(routedAnswer))
|
||||||
|
|
||||||
f.server.Close()
|
// Another test can take a closed server's port at once, so routewatch's
|
||||||
|
// address here is a multicast address, to which TCP cannot connect.
|
||||||
|
f.client = routewatch.New(routewatch.Params{
|
||||||
|
URL: "http://224.0.0.1/", Now: f.clk.Now,
|
||||||
|
ProcessLog: slog.New(slog.NewTextHandler(f.log, nil)),
|
||||||
|
})
|
||||||
|
|
||||||
f.route()
|
f.route()
|
||||||
f.waitFor(routewatch.RequestFailed)
|
f.waitFor(routewatch.RequestFailed)
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"io"
|
"io"
|
||||||
"maps"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
@@ -14,6 +13,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -195,7 +195,13 @@ func TestTheSiteAnswersWhileDiscriminatorIsStoppedAndStartedAgain(t *testing.T)
|
|||||||
|
|
||||||
env := discriminatorSettings(t)
|
env := discriminatorSettings(t)
|
||||||
addr, _, stop := startDiscriminator(t, env)
|
addr, _, stop := startDiscriminator(t, env)
|
||||||
site, out := startRProxy(t, "http://"+addr, startApp(t))
|
|
||||||
|
// rproxy asks discriminator through an address the test holds throughout,
|
||||||
|
// so no other test can take it while discriminator is stopped.
|
||||||
|
backend, forwardTo := startForwarder(t)
|
||||||
|
forwardTo(addr)
|
||||||
|
|
||||||
|
site, out := startRProxy(t, "http://"+backend, startApp(t))
|
||||||
|
|
||||||
// A visitor who keeps asking throughout, and is never refused.
|
// A visitor who keeps asking throughout, and is never refused.
|
||||||
visitorDone := make(chan struct{})
|
visitorDone := make(chan struct{})
|
||||||
@@ -221,6 +227,10 @@ func TestTheSiteAnswersWhileDiscriminatorIsStoppedAndStartedAgain(t *testing.T)
|
|||||||
|
|
||||||
wantStatus(t, site+bannedProbe, placed, http.StatusForbidden)
|
wantStatus(t, site+bannedProbe, placed, http.StatusForbidden)
|
||||||
wantStatus(t, site+"/", placed, http.StatusForbidden)
|
wantStatus(t, site+"/", placed, http.StatusForbidden)
|
||||||
|
|
||||||
|
// rproxy's connections are closed at once from here, before discriminator
|
||||||
|
// stops and frees its port.
|
||||||
|
forwardTo("")
|
||||||
stop()
|
stop()
|
||||||
|
|
||||||
// With discriminator down, the site answers, and rproxy says the default did it.
|
// With discriminator down, the site answers, and rproxy says the default did it.
|
||||||
@@ -232,12 +242,14 @@ func TestTheSiteAnswersWhileDiscriminatorIsStoppedAndStartedAgain(t *testing.T)
|
|||||||
t.Errorf("rproxy's line is %v", line)
|
t.Errorf("rproxy's line is %v", line)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Back at its address, with its state files, it applies the ban again.
|
// Started again with its state files, it applies the ban again.
|
||||||
restarted := maps.Clone(env)
|
addr, _, stop = startDiscriminator(t, env)
|
||||||
restarted[listenAddr] = addr
|
forwardTo(addr)
|
||||||
_, _, stop = startDiscriminator(t, restarted)
|
|
||||||
|
|
||||||
defer stop()
|
defer func() {
|
||||||
|
forwardTo("")
|
||||||
|
stop()
|
||||||
|
}()
|
||||||
|
|
||||||
wantStatus(t, site+"/", placed, http.StatusForbidden)
|
wantStatus(t, site+"/", placed, http.StatusForbidden)
|
||||||
|
|
||||||
@@ -249,6 +261,83 @@ func TestTheSiteAnswersWhileDiscriminatorIsStoppedAndStartedAgain(t *testing.T)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// startForwarder listens at a free port until the test ends, and returns its
|
||||||
|
// address and what sets the address it forwards to. It forwards each
|
||||||
|
// connection it takes to that address, and closes the connection at once while
|
||||||
|
// the address is "".
|
||||||
|
func startForwarder(t *testing.T) (string, func(addr string)) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
ctx := t.Context()
|
||||||
|
|
||||||
|
listener, err := (&net.ListenConfig{}).Listen(ctx, "tcp", localhost+":0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("listen: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
_ = listener.Close()
|
||||||
|
})
|
||||||
|
|
||||||
|
var (
|
||||||
|
mu sync.Mutex
|
||||||
|
to string
|
||||||
|
)
|
||||||
|
|
||||||
|
// dial connects to the address set, and returns nil while it is "". It
|
||||||
|
// holds the lock throughout, so once another address is set, nothing
|
||||||
|
// connects to the one before.
|
||||||
|
dial := func() net.Conn {
|
||||||
|
mu.Lock()
|
||||||
|
defer mu.Unlock()
|
||||||
|
|
||||||
|
if to == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := (&net.Dialer{}).DialContext(ctx, "tcp", to)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return conn
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
conn, err := listener.Accept()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream := dial()
|
||||||
|
if upstream == nil {
|
||||||
|
_ = conn.Close()
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
go pipe(upstream, conn)
|
||||||
|
go pipe(conn, upstream)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return listener.Addr().String(), func(addr string) {
|
||||||
|
mu.Lock()
|
||||||
|
defer mu.Unlock()
|
||||||
|
|
||||||
|
to = addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pipe copies src to dst until src ends, then closes both, which ends the copy
|
||||||
|
// the other way too.
|
||||||
|
func pipe(dst, src net.Conn) {
|
||||||
|
_, _ = io.Copy(dst, src)
|
||||||
|
_ = dst.Close()
|
||||||
|
_ = src.Close()
|
||||||
|
}
|
||||||
|
|
||||||
// answersNormally reports whether a request to url from the client at from, as
|
// answersNormally reports whether a request to url from the client at from, as
|
||||||
// X-Forwarded-For names it, gets the app's answer.
|
// X-Forwarded-For names it, gets the app's answer.
|
||||||
func answersNormally(ctx context.Context, url, from string) bool {
|
func answersNormally(ctx context.Context, url, from string) bool {
|
||||||
|
|||||||
@@ -975,9 +975,20 @@ func TestStalledRemoteLogEndpointHoldsUpNoRequest(t *testing.T) {
|
|||||||
t.Errorf("no line dropped in the metrics:\n%s", metrics)
|
t.Errorf("no line dropped in the metrics:\n%s", metrics)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Closed, the endpoint refuses the connection made to send the
|
// From here the endpoint closes each connection it takes, so the
|
||||||
// lines still waiting at the stop, which then does not wait.
|
// one made to send the lines still waiting at the stop fails at
|
||||||
_ = endpoint.Close()
|
// once. Closing the endpoint instead would free its port for
|
||||||
|
// another test to take.
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
conn, err := endpoint.Accept()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = conn.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
})
|
})
|
||||||
|
|
||||||
out.line(t, "type", "request")
|
out.line(t, "type", "request")
|
||||||
|
|||||||
Reference in new issue
Block a user