R-1253 (P2): an export that stops its app refuses while another operation (a restore) holds the app-stop marker — its Undo is never replaced. Commit only.
gates / gates (push) Successful in 1m28s
gates / gates (push) Successful in 1m28s
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user