From 8778376aa64d4e5082f1b23e2d6c2200c70dab08 Mon Sep 17 00:00:00 2001 From: Mathias Date: Thu, 1 Oct 2026 23:21:17 +0200 Subject: [PATCH] test(transcribe): a shutdown in the middle of either engine stops the job Mutation-testing showed each of the two cancellation checks was redundant with the other in my first test. Now a cancel during the first engine must not start the second or the cloud, and a cancel during the second must not be recorded as a single-engine success ('kb-whisper failed'). Co-Authored-By: Claude Sonnet 5.5 --- internal/adapters/transcribe/ensemble_test.go | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/internal/adapters/transcribe/ensemble_test.go b/internal/adapters/transcribe/ensemble_test.go index e0735e8..f9feca4 100644 --- a/internal/adapters/transcribe/ensemble_test.go +++ b/internal/adapters/transcribe/ensemble_test.go @@ -164,3 +164,43 @@ func TestEnsemble_AModelThatIsDownGivesTheBaseTextUnreconciledNotAFailedJob(t *t assert.Equal(t, domain.ReconcileSkipped, got.Reconciliation.Status) assert.Equal(t, 3, adj.calls) } + +// cancelling is a backend that cancels the job's context while it runs, the way a +// shutdown arrives in the middle of a long transcription. +type cancelling struct { + name string + cancel context.CancelFunc + calls *[]string +} + +func (c *cancelling) Name() string { return c.name } +func (c *cancelling) Transcribe(_ context.Context, _ string) (domain.Transcription, error) { + *c.calls = append(*c.calls, c.name) + c.cancel() + return domain.Transcription{}, context.Canceled +} + +func TestEnsemble_AShutdownDuringTheFirstEngineStopsBeforeTheSecondOrTheCloud(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + calls := &[]string{} + base := &cancelling{name: "iguana/pianissimo", cancel: cancel, calls: calls} + alt := &orderedBackend{name: "iguana/kb-whisper", text: "alt", calls: calls} + fb := &orderedBackend{name: "berget/kb-whisper", text: "fb", calls: calls} + + _, err := transcribe.NewEnsemble(base, alt, fb, &verdictAdj{}, ensembleOpts).Transcribe(ctx, "/a.wav") + + assert.ErrorIs(t, err, context.Canceled) + assert.Equal(t, []string{"iguana/pianissimo"}, *calls, "no second engine and no cloud once the job is cancelled") +} + +func TestEnsemble_AShutdownDuringTheSecondEngineIsAnErrorNotASingleEngineSuccess(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + calls := &[]string{} + base := &orderedBackend{name: "iguana/pianissimo", text: "base", calls: calls} + alt := &cancelling{name: "iguana/kb-whisper", cancel: cancel, calls: calls} + + got, err := transcribe.NewEnsemble(base, alt, nil, &verdictAdj{}, ensembleOpts).Transcribe(ctx, "/a.wav") + + assert.ErrorIs(t, err, context.Canceled, "a cancelled job must not be recorded as 'kb-whisper failed'") + assert.Empty(t, got.Text) +}