Public source validation / validate (push) Failing after 3m8s
72 lines
3.0 KiB
Go
72 lines
3.0 KiB
Go
package alert
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/itworx/pulse/internal/database"
|
|
)
|
|
|
|
func TestPostgreSQLAlertOperationsAreRevisionSafeAndRestartable(t *testing.T) {
|
|
dsn := os.Getenv("PULSE_TEST_DATABASE_URL")
|
|
if dsn == "" {
|
|
t.Skip("PULSE_TEST_DATABASE_URL is not set")
|
|
}
|
|
ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second)
|
|
defer cancel()
|
|
pool, err := database.NewPool(ctx, database.Config{URL: dsn, MaxConns: 8, MinConns: 1})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer pool.Close()
|
|
if err := database.Migrate(ctx, pool); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
document, registry := validDocument(t)
|
|
document.Enabled = true
|
|
rules := Repository{Pool: pool, Registry: registry}
|
|
created, version, err := rules.Create(ctx, "operations-integration", document, "operations test")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
store := StateRepository{Pool: pool}
|
|
base := time.Date(2026, time.January, 4, 12, 0, 0, 0, time.UTC)
|
|
policy := Policy{PendingSeconds: 0, ResolveSeconds: 0, UnknownBehavior: UnknownRetain}
|
|
firing, _, _, err := store.ApplyObservation(ctx, StateInput{RuleID: created.ID, RuleVersionID: version.ID, Fingerprint: "operations:test", Policy: policy, Observation: observation(base, "evaluation-1", true)})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if firing.State != StateFiring {
|
|
t.Fatalf("state = %s", firing.State)
|
|
}
|
|
ack, occurrence, duplicate, err := store.AcknowledgeRevision(ctx, firing.ID, "operator", "ack-operation-1", base.Add(time.Second), firing.Revision)
|
|
if err != nil || duplicate || ack.State != StateAcknowledged || occurrence.EventType != "acknowledge" {
|
|
t.Fatalf("ack result=%#v occurrence=%#v duplicate=%v err=%v", ack, occurrence, duplicate, err)
|
|
}
|
|
retry, _, duplicate, err := store.AcknowledgeRevision(ctx, firing.ID, "operator", "ack-operation-1", base.Add(time.Second), firing.Revision)
|
|
if err != nil || !duplicate || retry.Revision != ack.Revision {
|
|
t.Fatalf("ack retry=%#v duplicate=%v err=%v", retry, duplicate, err)
|
|
}
|
|
restarted := StateRepository{Pool: pool}
|
|
persisted, err := restarted.GetInstance(ctx, firing.ID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if persisted.State != StateAcknowledged || persisted.AcknowledgedBy != "operator" {
|
|
t.Fatalf("ack did not survive restart: %#v", persisted)
|
|
}
|
|
unack, occurrence, duplicate, err := restarted.Unacknowledge(ctx, firing.ID, "operator", "unack-operation-1", base.Add(2*time.Second), ack.Revision)
|
|
if err != nil || duplicate || unack.State != StateFiring || unack.AcknowledgedBy != "" || occurrence.EventType != "unacknowledge" {
|
|
t.Fatalf("unack result=%#v occurrence=%#v duplicate=%v err=%v", unack, occurrence, duplicate, err)
|
|
}
|
|
resolved, _, _, err := restarted.ApplyObservation(ctx, StateInput{RuleID: created.ID, RuleVersionID: version.ID, Fingerprint: "operations:test", Policy: policy, Observation: observation(base.Add(3*time.Second), "evaluation-2", false)})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if resolved.State != StateResolved {
|
|
t.Fatalf("resolved state was lost after unacknowledge: %#v", resolved)
|
|
}
|
|
}
|