49 lines
1.8 KiB
Go
49 lines
1.8 KiB
Go
package appexport
|
|
|
|
import (
|
|
"io"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// busyGuard is the app-stop seam with another operation holding the marker.
|
|
type busyGuard struct{ begins []string }
|
|
|
|
func (g *busyGuard) Begin(opID string, _ []string) error {
|
|
g.begins = append(g.begins, opID)
|
|
return nil
|
|
}
|
|
func (g *busyGuard) End() {}
|
|
func (g *busyGuard) ReleaseFailed(...string) {}
|
|
func (g *busyGuard) BusyWith() string { return "unit-restore:bookstack" }
|
|
|
|
// R-1253: an export that stops its app is refused BEFORE anything starts while another operation holds the marker;
|
|
// an export that does not stop its app writes no marker and still runs. RED-PROOF (2026-10-24): with the BusyWith check
|
|
// removed from StartExport, the stop-first export starts (StartExport returns nil) and this fails.
|
|
func TestR1253_AStopFirstExportWaitsForTheOtherOperation(t *testing.T) {
|
|
stackDir := filepath.Join(t.TempDir(), "immich")
|
|
if err := os.MkdirAll(stackDir, 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
prov := &rtProvider{stackDir: stackDir, stacksDir: filepath.Dir(stackDir), deployed: true, running: true}
|
|
e := NewExporter(prov, log.New(io.Discard, "", 0), "test")
|
|
g := &busyGuard{}
|
|
e.SetStopGuard(g)
|
|
err := e.StartExport(ExportRequest{StackName: "immich", DestDrive: t.TempDir(), StopApp: true})
|
|
if err == nil {
|
|
t.Fatal("a stop-first export must be refused while a restore holds the app-stop marker")
|
|
}
|
|
if k, ok := err.(interface{ Key() string }); !ok || k.Key() != "err.appexport.another_operation_running" {
|
|
t.Fatalf("the refusal must carry its household sentence key, got %v", err)
|
|
}
|
|
if !strings.Contains(err.Error(), "visszaállítás") {
|
|
t.Fatalf("the Hungarian sentence must name the cause: %q", err.Error())
|
|
}
|
|
if len(g.begins) != 0 {
|
|
t.Fatalf("nothing may be marked or stopped, begins=%v", g.begins)
|
|
}
|
|
}
|