Skip to content

Commit 7495cf9

Browse files
Merge branch 'master' into fix/quota-unsuspend-rescan
2 parents 2a68951 + 80f353e commit 7495cf9

1 file changed

Lines changed: 65 additions & 0 deletions

File tree

internal/jobs/deploy_failure_autopsy_test.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,71 @@ func TestCaptureDeploymentAutopsy_LastLinesJSONRoundtrip(t *testing.T) {
380380
}
381381
}
382382

383+
// TestEmitDeployFailedAudit_FirstTickInserts verifies that the first autopsy
384+
// tick for a deployment with no pre-existing deploy.failed audit row resolves
385+
// the team_id, runs the dedup EXISTS probe (false), then INSERTs the
386+
// deploy.failed audit row exactly once.
387+
func TestEmitDeployFailedAudit_FirstTickInserts(t *testing.T) {
388+
db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherRegexp))
389+
if err != nil {
390+
t.Fatalf("sqlmock.New: %v", err)
391+
}
392+
defer db.Close()
393+
394+
id := uuid.New()
395+
teamID := uuid.New()
396+
397+
mock.ExpectQuery(`SELECT team_id FROM deployments`).
398+
WithArgs(id).
399+
WillReturnRows(sqlmock.NewRows([]string{"team_id"}).AddRow(teamID))
400+
// Dedup probe: no existing deploy.failed row for this deployment.
401+
mock.ExpectQuery(`SELECT EXISTS`).
402+
WithArgs(auditKindDeployFailed, id.String()).
403+
WillReturnRows(sqlmock.NewRows([]string{"exists"}).AddRow(false))
404+
mock.ExpectExec(`INSERT INTO audit_log`).
405+
WillReturnResult(sqlmock.NewResult(0, 1))
406+
407+
if err := emitDeployFailedAudit(context.Background(), db, id, "ImagePullBackOff", "manifest unknown"); err != nil {
408+
t.Fatalf("emitDeployFailedAudit (first tick): %v", err)
409+
}
410+
if err := mock.ExpectationsWereMet(); err != nil {
411+
t.Errorf("unmet sqlmock expectations: %v", err)
412+
}
413+
}
414+
415+
// TestEmitDeployFailedAudit_SecondTickIsNoOp verifies the idempotency guard:
416+
// when a deploy.failed audit row already exists for the deployment (e.g. the
417+
// api emitted it synchronously, or a prior autopsy tick did), a subsequent
418+
// tick runs the dedup EXISTS probe (true) and performs NO INSERT — so the
419+
// email forwarder never sends a duplicate failure email per reconciler tick.
420+
func TestEmitDeployFailedAudit_SecondTickIsNoOp(t *testing.T) {
421+
db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherRegexp))
422+
if err != nil {
423+
t.Fatalf("sqlmock.New: %v", err)
424+
}
425+
defer db.Close()
426+
427+
id := uuid.New()
428+
teamID := uuid.New()
429+
430+
mock.ExpectQuery(`SELECT team_id FROM deployments`).
431+
WithArgs(id).
432+
WillReturnRows(sqlmock.NewRows([]string{"team_id"}).AddRow(teamID))
433+
// Dedup probe: a deploy.failed row already exists → emit must short-circuit.
434+
mock.ExpectQuery(`SELECT EXISTS`).
435+
WithArgs(auditKindDeployFailed, id.String()).
436+
WillReturnRows(sqlmock.NewRows([]string{"exists"}).AddRow(true))
437+
// NO ExpectExec(INSERT INTO audit_log) — a second INSERT would be an
438+
// unmet/unexpected expectation and fail the test.
439+
440+
if err := emitDeployFailedAudit(context.Background(), db, id, "ImagePullBackOff", "manifest unknown"); err != nil {
441+
t.Fatalf("emitDeployFailedAudit (second tick): %v", err)
442+
}
443+
if err := mock.ExpectationsWereMet(); err != nil {
444+
t.Errorf("unmet sqlmock expectations (duplicate INSERT?): %v", err)
445+
}
446+
}
447+
383448
// ── fakeAutopsyK8s stub ───────────────────────────────────────────────────────
384449

385450
type fakeAutopsyK8s struct {

0 commit comments

Comments
 (0)