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" ) // targetTotals reads one target's totals from a webhook database, all // zero when it has no row. func targetTotals( t *testing.T, db *gorm.DB, targetID string, ) database.TargetTotals { t.Helper() var rows []database.TargetTotals require.NoError(t, db.Where("target_id = ?", targetID). Find(&rows).Error) if len(rows) == 0 { return database.TargetTotals{TargetID: targetID} } return rows[0] } // TestUpdateDeliveryStatus_FinishTimeAndTargetTotals 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 its target's delivered or failed total. func TestUpdateDeliveryStatus_FinishTimeAndTargetTotals(t *testing.T) { t.Parallel() tests := []struct { status database.DeliveryStatus finished bool delivered int64 failed int64 }{ {database.DeliveryStatusRetrying, false, 0, 0}, {database.DeliveryStatusDelivered, true, 1, 0}, {database.DeliveryStatusFailed, true, 0, 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, `{}`) targetID := uuid.New().String() d := seedDelivery( t, db, event.ID, targetID, 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, database.TargetTotals{ TargetID: targetID, Delivered: tt.delivered, Failed: tt.failed, }, targetTotals(t, db, targetID)) }) } } // 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, `{}`) targetID := uuid.New().String() d := seedDelivery( t, db, event.ID, targetID, database.DeliveryStatusRetrying, ) require.NoError(t, db.Unscoped(). Delete(&database.Delivery{}, "id = ?", d.ID).Error) require.NoError(t, e.ExportUpdateDeliveryStatus( db, &d, database.DeliveryStatusFailed, )) assert.Equal(t, database.TargetTotals{TargetID: targetID}, targetTotals(t, db, targetID)) }