check / check (push) Failing after 3s
The Dockerfile's last stage is now the image of "Deployment" in SPEC.md: Ubuntu 26.04 with ca-certificates, nix-bin and runit from a dated snapshot whose InRelease files are checked by hash, nixpkgs from its release file checked by SHA-256, runsvinit built at a fixed commit, and smallwebwaf as a runit service. smallwebwaf answers /_smallwebwaf/healthz, and `smallwebwaf healthcheck`, which takes no further argument, is the image's HEALTHCHECK. script/example-app builds an app on the image and checks it end to end. The Nix profile comes last on the PATH: first, busybox from nixpkgs replaced runit's own runsvdir and sv. SPEC.md is corrected to match what was built. Model: opus-5-5
98 lines
2.3 KiB
Go
98 lines
2.3 KiB
Go
package smallwebwaf_test
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"net"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"sneak.berlin/go/smallwebwaf/internal/smallwebwaf"
|
|
)
|
|
|
|
func TestHealthCheck(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
app := httptest.NewServer(http.NotFoundHandler())
|
|
defer app.Close()
|
|
|
|
ctx, stop := context.WithCancel(t.Context())
|
|
defer stop()
|
|
|
|
out := &output{}
|
|
exited := make(chan int, 1)
|
|
|
|
go func() {
|
|
exited <- run(ctx, map[string]string{
|
|
listenAddr: localhost + ":0",
|
|
upstreamURL: app.URL,
|
|
}, out)
|
|
}()
|
|
|
|
addr, _ := out.line(t, "msg", "starting")["address"].(string)
|
|
_, port, _ := net.SplitHostPort(addr)
|
|
// The container's settings: an address to listen on with an empty
|
|
// host part, which the health check asks at 127.0.0.1.
|
|
env := map[string]string{listenAddr: ":" + port, upstreamURL: app.URL}
|
|
|
|
wantHealthCheck(t, env, 0, "")
|
|
|
|
app.Close()
|
|
wantHealthCheck(t, env, 1, "unhealthy: connect to the app: ")
|
|
|
|
stop()
|
|
|
|
select {
|
|
case <-exited:
|
|
case <-time.After(waitLimit):
|
|
t.Fatal("still running after being told to stop")
|
|
}
|
|
|
|
wantHealthCheck(t, env, 1, "unhealthy: ask smallwebwaf: ")
|
|
wantHealthCheck(t, map[string]string{listenAddr: "8080"}, 1,
|
|
"unhealthy: invalid setting: SWWAF_LISTEN_ADDR: ")
|
|
}
|
|
|
|
func TestHealthCheckRefusesAnArgument(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var stderr bytes.Buffer
|
|
|
|
noSettings := func(string) (string, bool) {
|
|
return "", false
|
|
}
|
|
|
|
got := smallwebwaf.HealthCheck(t.Context(), []string{"now"}, noSettings, &stderr)
|
|
|
|
want := "smallwebwaf healthcheck: unexpected argument \"now\"\n"
|
|
if got != 1 || stderr.String() != want {
|
|
t.Errorf("health check returned %d and wrote %q, want 1 and %q",
|
|
got, stderr.String(), want)
|
|
}
|
|
}
|
|
|
|
// wantHealthCheck runs the health check with the settings in env, and
|
|
// checks its exit status and the start of what it writes to stderr,
|
|
// which is nothing when message is empty.
|
|
func wantHealthCheck(t *testing.T, env map[string]string, status int, message string) {
|
|
t.Helper()
|
|
|
|
var stderr bytes.Buffer
|
|
|
|
got := smallwebwaf.HealthCheck(t.Context(), nil, func(name string) (string, bool) {
|
|
value, ok := env[name]
|
|
|
|
return value, ok
|
|
}, &stderr)
|
|
|
|
wrote := stderr.String()
|
|
if got != status || !strings.HasPrefix(wrote, message) ||
|
|
(message == "" && wrote != "") {
|
|
t.Errorf("health check returned %d and wrote %q, want %d and %q",
|
|
got, wrote, status, message)
|
|
}
|
|
}
|