diff options
| author | Lena <lena@omega> | 2026-08-01 00:00:00 +0000 |
|---|---|---|
| committer | Lena <lena@omega> | 2026-08-01 00:00:00 +0000 |
| commit | 3284b1c4906b90ca2e3864937c66d0fa30772ebf (patch) | |
| tree | ad799407ac7b0a2589a344751f4c5b3cf575d5c5 /logs_test.go | |
| download | git-forge-cloudflare-master.tar.gz | |
Runs git-forge on Cloudflare Containers with R2 for durable storage. A
Worker routes every request to one container through a Durable Object.
Inside it, syncd mirrors the data directory to the bucket and restores
it at boot, holding a write until it is durable.
git-forge is neither modified nor vendored: the image builds it from
its own repository at the commit named in forge.rev.
Diffstat (limited to 'logs_test.go')
| -rw-r--r-- | logs_test.go | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/logs_test.go b/logs_test.go new file mode 100644 index 0000000..abef7eb --- /dev/null +++ b/logs_test.go @@ -0,0 +1,66 @@ +package main + +import ( + "io" + "net/http" + "net/http/httptest" + "strings" + "sync" + "testing" +) + +// A gap in the log reads as nothing having happened, so a line that never +// reaches the worker has to be counted and reported by one that does. The two +// ways it fails are a send that errors and a send that is answered with an +// error, and only the first of them looks like a failure to the client. +func TestShipperReportsWhatDidNotLand(t *testing.T) { + var mu sync.Mutex + mode := "refuse" + var landed []string + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + mu.Lock() + defer mu.Unlock() + switch mode { + case "refuse": + http.Error(w, "no", http.StatusInternalServerError) + case "drop": + // A send that errors rather than answering. + if conn, _, err := w.(http.Hijacker).Hijack(); err == nil { + conn.Close() + } + default: + body, _ := io.ReadAll(r.Body) + landed = append(landed, string(body)) + w.WriteHeader(http.StatusNoContent) + } + })) + defer srv.Close() + + s := newShipper(srv.URL) + // close sends what is queued and waits, so each of these is one send. + for _, step := range []struct{ mode, line string }{ + {"refuse", "answered with a 500"}, + {"drop", "the connection went away"}, + {"take", "this one lands"}, + } { + mu.Lock() + mode = step.mode + mu.Unlock() + if _, err := s.Write([]byte(step.line + "\n")); err != nil { + t.Fatal(err) + } + s.close() + } + + mu.Lock() + defer mu.Unlock() + if len(landed) != 1 { + t.Fatalf("the worker was handed %d bodies, want the one it accepted: %q", len(landed), landed) + } + if !strings.Contains(landed[0], "this one lands") { + t.Errorf("the line that should have landed is missing from %q", landed[0]) + } + if !strings.Contains(landed[0], "2 log lines did not reach the worker") { + t.Errorf("the two lines that did not land are not reported in %q", landed[0]) + } +} |