munin/internal/importer/postgres_test.go
2026-10-19 10:13:56 +02:00

107 lines
3.1 KiB
Go

package importer
import (
"bytes"
"context"
"os"
"testing"
"munin/internal/export"
"munin/internal/store"
)
// TestRoundTripPostgres prüft Export und Import gegen PostgreSQL: Ein Projekt
// wird als ZIP exportiert (derselbe Weg wie „als ZIP herunterladen“) und in
// einen zweiten, leeren Workspace importiert. Danach müssen dieselben Einträge
// mit demselben Inhalt dastehen.
//
// Läuft nur mit MUNIN_TEST_PG (siehe internal/store/postgres_test.go). Export
// und Import lesen und schreiben ausschließlich über den Store, sind also
// nicht an SQLite gebunden — dieser Test belegt das.
func TestRoundTripPostgres(t *testing.T) {
url := os.Getenv("MUNIN_TEST_PG")
if url == "" {
t.Skip("MUNIN_TEST_PG ist nicht gesetzt — PostgreSQL-Test übersprungen")
}
ctx := context.Background()
sp, err := store.NewPostgres(ctx, url)
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { sp.Close() })
// Zwei frische Workspace-Schemas, nach dem Test wieder weg.
open := func() *store.Store {
id := store.NewID()
s, err := sp.OpenWorkspace(id)
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() {
s.Close()
sp.DeleteWorkspace(id)
})
return s
}
source, target := open(), open()
// Quelle: ein Projekt mit Schlagworten, Verweis, Umlauten und einem
// kuratierten Eintrag.
project, err := source.CreateProject(ctx, "ws", "plattform", "Plattform", "")
if err != nil {
t.Fatal(err)
}
for _, e := range []store.EntryWrite{
{Slug: "deployment", Title: "Deployment-Prozess", Content: "Über die Pipeline, siehe [[vpn]].",
Tags: []string{"ops"}, Source: store.SourceHuman, Curated: true},
{Slug: "vpn", Title: "VPN-Zugang", Content: "Zugang über vpn.intern — Änderungen bei der IT.",
Tags: []string{"ops", "zugang"}, Source: store.SourceAgent},
} {
e.ProjectID = project.ID
if _, err := source.PutEntry(ctx, e); err != nil {
t.Fatal(err)
}
}
// Export als ZIP und wieder auspacken — wie Download und Upload.
files, err := export.ProjectFiles(ctx, source, project)
if err != nil {
t.Fatal(err)
}
var zip bytes.Buffer
if err := export.WriteZIP(&zip, files); err != nil {
t.Fatal(err)
}
read, err := ReadZip(zip.Bytes())
if err != nil {
t.Fatal(err)
}
targetProject, err := target.CreateProject(ctx, "ws", "plattform", "Plattform", "")
if err != nil {
t.Fatal(err)
}
report, err := Import(ctx, target, targetProject.ID, read, Options{Mode: ModeSkip})
if err != nil {
t.Fatal(err)
}
if report.Created != 2 || report.Failed != 0 {
t.Fatalf("Import: %d neu, %d Fehler, erwartet 2 neu und 0 Fehler: %+v", report.Created, report.Failed, report.Rows)
}
for _, slug := range []string{"deployment", "vpn"} {
before, err := source.EntryBySlug(ctx, project.ID, slug)
if err != nil {
t.Fatal(err)
}
after, err := target.EntryBySlug(ctx, targetProject.ID, slug)
if err != nil {
t.Fatalf("%s fehlt nach dem Import: %v", slug, err)
}
if after.Title != before.Title || after.Content != before.Content ||
after.Curated != before.Curated || len(after.Tags) != len(before.Tags) {
t.Errorf("%s unterscheidet sich:\nvorher: %+v\nnachher: %+v", slug, before, after)
}
}
}