Stichprobenbasierter Scrub-Job: nimmt BAK-05s existing_in_storage, priorisiert nach eigenem scrub_state.last_scrubbed_at (nicht file_revisions.created_at, sonst kein echtes Rotationsverhalten), prueft Inhalt per SHA-256 gegen file_revisions.checksum_sha256. Meldung ueber echten dauerhaften /metrics-Endpunkt (Pull-Modell, OPS-03 scrapt, kein Push), Counter monoton steigend. Real registriert in Core metrics_sources, End-zu-Ende ueber OPS-03-Aggregator bestaetigt, realer Befund-Durchlauf mit absichtlich falscher Pruefsumme durchgefuehrt.
95 lines
3.4 KiB
Go
95 lines
3.4 KiB
Go
package scrub
|
|
|
|
import (
|
|
"context"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
)
|
|
|
|
func requireFileRevisionsFixture(t *testing.T) (pool *pgxpool.Pool, userID, docID string) {
|
|
t.Helper()
|
|
p := requireTestPool(t)
|
|
ctx := context.Background()
|
|
if _, err := p.Exec(ctx, `
|
|
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(), email TEXT NOT NULL UNIQUE, name TEXT NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
CREATE TABLE IF NOT EXISTS documents (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title TEXT NOT NULL,
|
|
created_by UUID NOT NULL REFERENCES users(id), created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
CREATE TABLE IF NOT EXISTS file_revisions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(), document_id UUID NOT NULL REFERENCES documents(id) ON DELETE CASCADE,
|
|
storage_key TEXT NOT NULL, checksum_sha256 TEXT NOT NULL, size_bytes BIGINT NOT NULL,
|
|
mime_type TEXT NOT NULL, revision_number INTEGER NOT NULL, created_by UUID NOT NULL REFERENCES users(id),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
`); err != nil {
|
|
t.Fatalf("file_revisions-fixture: %v", err)
|
|
}
|
|
var uid string
|
|
if err := p.QueryRow(ctx, `INSERT INTO users (email, name) VALUES ('scrub-test@example.test', 'Test') RETURNING id`).Scan(&uid); err != nil {
|
|
t.Fatalf("testbenutzer anlegen: %v", err)
|
|
}
|
|
var did string
|
|
if err := p.QueryRow(ctx, `INSERT INTO documents (title, created_by) VALUES ('doc', $1) RETURNING id`, uid).Scan(&did); err != nil {
|
|
t.Fatalf("testdokument anlegen: %v", err)
|
|
}
|
|
t.Cleanup(func() { _, _ = p.Exec(context.Background(), `TRUNCATE file_revisions, documents, users CASCADE`) })
|
|
return p, uid, did
|
|
}
|
|
|
|
// TestActualChecksum_MatchesRealFileContent ist Nachweis, dass
|
|
// ActualChecksum tatsaechlich den Dateiinhalt liest und hasht (kein
|
|
// Header-/Groessenvergleich).
|
|
func TestActualChecksum_MatchesRealFileContent(t *testing.T) {
|
|
baseDir := t.TempDir()
|
|
content := []byte("echter dateiinhalt fuer scrub-test")
|
|
path := filepath.Join(baseDir, "documents", "x", "revisions", "1")
|
|
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(path, content, 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
got, err := ActualChecksum(baseDir, "documents/x/revisions/1")
|
|
if err != nil {
|
|
t.Fatalf("actualChecksum: %v", err)
|
|
}
|
|
sum := sha256.Sum256(content)
|
|
want := hex.EncodeToString(sum[:])
|
|
if got != want {
|
|
t.Fatalf("checksum = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
// TestExpectedChecksums_ReadsRealFileRevisions ist Nachweis gegen echtes
|
|
// Postgres, kein Mock.
|
|
func TestExpectedChecksums_ReadsRealFileRevisions(t *testing.T) {
|
|
pool, uid, did := requireFileRevisionsFixture(t)
|
|
ctx := context.Background()
|
|
|
|
if _, err := pool.Exec(ctx, `
|
|
INSERT INTO file_revisions (document_id, storage_key, checksum_sha256, size_bytes, mime_type, revision_number, created_by)
|
|
VALUES ($1, 'documents/x/revisions/1', 'abc123', 10, 'text/plain', 1, $2)
|
|
`, did, uid); err != nil {
|
|
t.Fatalf("testrevision anlegen: %v", err)
|
|
}
|
|
|
|
got, err := ExpectedChecksums(ctx, pool, []string{"documents/x/revisions/1", "documents/fehlt/revisions/1"})
|
|
if err != nil {
|
|
t.Fatalf("expectedChecksums: %v", err)
|
|
}
|
|
if len(got) != 1 || got["documents/x/revisions/1"] != "abc123" {
|
|
t.Fatalf("unerwartetes ergebnis: %+v", got)
|
|
}
|
|
}
|