package delivery_test import ( "testing" "time" "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gorm.io/gorm" "sneak.berlin/go/webhooker/internal/database" ) // failureTotal reads the running failure total of a webhook database. func failureTotal(t *testing.T, db *gorm.DB) int64 { t.Helper() var totals database.Totals require.NoError(t, db.Take(&totals).Error) return totals.Failures } // TestUpdateDeliveryStatus_FinishTimeAndFailureTotal pins what a status // write records for the webhook page's statistics: the time a delivery // finished, set only when it becomes delivered or failed, and one more // on the failure total when it fails. func TestUpdateDeliveryStatus_FinishTimeAndFailureTotal(t *testing.T) { t.Parallel() tests := []struct { status database.DeliveryStatus finished bool failures int64 }{ {database.DeliveryStatusRetrying, false, 0}, {database.DeliveryStatusDelivered, true, 0}, {database.DeliveryStatusFailed, true, 1}, } for _, tt := range tests { t.Run(string(tt.status), func(t *testing.T) { t.Parallel() db := testWebhookDB(t) e := testEngine(t, 1) event := seedEvent(t, db, `{}`) d := seedDelivery( t, db, event.ID, uuid.New().String(), database.DeliveryStatusPending, ) before := time.Now() require.NoError(t, e.ExportUpdateDeliveryStatus( db, &d, tt.status, )) var stored database.Delivery require.NoError(t, db.First(&stored, "id = ?", d.ID).Error) assert.Equal(t, tt.status, stored.Status) if tt.finished { require.NotNil(t, stored.FinishedAt) assert.False(t, stored.FinishedAt.Before(before)) } else { assert.Nil(t, stored.FinishedAt) } assert.Equal(t, tt.failures, failureTotal(t, db)) }) } } // TestUpdateDeliveryStatus_DeletedDeliveryIsNotCounted covers a // delivery retention deleted while the engine still held it. Failing // it afterwards writes no row, so it adds no failure either: retention // has already counted what it removed. func TestUpdateDeliveryStatus_DeletedDeliveryIsNotCounted(t *testing.T) { t.Parallel() db := testWebhookDB(t) e := testEngine(t, 1) event := seedEvent(t, db, `{}`) d := seedDelivery( t, db, event.ID, uuid.New().String(), database.DeliveryStatusRetrying, ) require.NoError(t, db.Unscoped(). Delete(&database.Delivery{}, "id = ?", d.ID).Error) require.NoError(t, e.ExportUpdateDeliveryStatus( db, &d, database.DeliveryStatusFailed, )) assert.Zero(t, failureTotal(t, db)) }