package runner
import (
"context"
"net/http"
"net/http/httptest"
"sync/atomic"
"testing"
"time"
)
// A finished task's report survives a forge restarting under a deploy:
// refused or 404 while the repository is not yet served, it is sent
// again until it lands. A cancelled run's 409 is not retried.
func TestATasksEndIsReportedThroughARestart(t *testing.T) {
for _, c := range []struct {
name string
answers []int
want int32
}{
{"through a restart", []int{http.StatusNotFound, http.StatusBadGateway, http.StatusOK}, 3},
{"a cancelled run", []int{http.StatusConflict, http.StatusOK}, 1},
{"gives up in the end", []int{404, 404, 404, 404, 404, 404}, 4},
} {
var calls atomic.Int32
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
n := int(calls.Add(1)) - 1
code := http.StatusOK
if n < len(c.answers) {
code = c.answers[n]
}
w.WriteHeader(code)
}))
r, err := New(Config{Bridge: srv.URL, Token: "WT", Tasks: []string{"t"}, MaxTasks: 1, WorkDir: t.TempDir(),
Checkout: appCheckout{}, ResolveRetry: []time.Duration{time.Millisecond, time.Millisecond, time.Millisecond},
Logf: func(string, ...any) {}})
if err != nil {
t.Fatal(err)
}
r.finish(context.Background(), "task-1", map[string]any{"action": "complete"})
srv.Close()
if got := calls.Load(); got != c.want {
t.Errorf("FAIL: %s: %d reports sent, want %d", c.name, got, c.want)
}
}
}