fix: harden embedded Pi lifecycle recovery
This commit is contained in:
@@ -61,14 +61,56 @@ func TestConfigureRestoresAndVerifiesOldSettingsAfterEveryPostSnapshotFailure(t
|
||||
}
|
||||
}
|
||||
|
||||
func TestSettingsRestoreDoesNotMaskExplicitDurabilityFailureWithMatchingReadback(t *testing.T) {
|
||||
old := Defaults{Provider: "old", Model: "old-model", Thinking: "low"}
|
||||
raw, _ := json.Marshal(old)
|
||||
fake := &configureRunner{
|
||||
failure: "restore-durability",
|
||||
settings: Defaults{Provider: "new", Model: "new-model", Thinking: "high"},
|
||||
settingsExist: true,
|
||||
settingsRaw: []byte(`{"provider":"new","model":"new-model","thinking":"high"}`),
|
||||
}
|
||||
snapshot := settingsFileSnapshot{Exists: true, RawBase64: base64.StdEncoding.EncodeToString(raw)}
|
||||
|
||||
err := restoreSettingsFile(context.Background(), fake, snapshot)
|
||||
|
||||
var recovery interface{ RecoveryRequired() bool }
|
||||
if err == nil || !errors.As(err, &recovery) || !recovery.RecoveryRequired() {
|
||||
t.Fatalf("restore error = %v; want typed recovery-required result", err)
|
||||
}
|
||||
if !fake.settingsExist || string(fake.settingsRaw) != string(raw) || fake.settings != old {
|
||||
t.Fatalf("restored state = exists:%t raw:%q value:%#v; want exact old bytes", fake.settingsExist, fake.settingsRaw, fake.settings)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigurePreservesTypedRecoveryRequiredErrorFromSettingsRestore(t *testing.T) {
|
||||
old := Defaults{Provider: "old", Model: "old-model", Thinking: "low"}
|
||||
raw, _ := json.Marshal(old)
|
||||
fake := &configureRunner{
|
||||
failure: "helper",
|
||||
restoreDurabilityFailure: true,
|
||||
settings: old,
|
||||
settingsExist: true,
|
||||
settingsRaw: raw,
|
||||
}
|
||||
|
||||
err := Configure(context.Background(), fake, Defaults{Provider: "new", Model: "new-model", Thinking: "high"})
|
||||
|
||||
var recovery interface{ RecoveryRequired() bool }
|
||||
if err == nil || !errors.As(err, &recovery) || !recovery.RecoveryRequired() {
|
||||
t.Fatalf("Configure() error = %v; want typed recovery-required result", err)
|
||||
}
|
||||
}
|
||||
|
||||
type configureRunner struct {
|
||||
failure string
|
||||
settings Defaults
|
||||
settingsExist bool
|
||||
settingsRaw []byte
|
||||
settingsReads int
|
||||
configReads int
|
||||
writes int
|
||||
failure string
|
||||
restoreDurabilityFailure bool
|
||||
settings Defaults
|
||||
settingsExist bool
|
||||
settingsRaw []byte
|
||||
settingsReads int
|
||||
configReads int
|
||||
writes int
|
||||
}
|
||||
|
||||
func (f *configureRunner) Run(_ context.Context, args []string, stdin io.Reader) (compose.Result, error) {
|
||||
@@ -103,6 +145,9 @@ func (f *configureRunner) Run(_ context.Context, args []string, stdin io.Reader)
|
||||
if payload.Exists {
|
||||
_ = json.Unmarshal(f.settingsRaw, &f.settings)
|
||||
}
|
||||
if f.failure == "restore-durability" || f.restoreDurabilityFailure {
|
||||
return compose.Result{ExitCode: 2}, errors.New("injected post-rename directory fsync failure")
|
||||
}
|
||||
return compose.Result{}, nil
|
||||
case strings.Contains(call, "settings-cli.js"):
|
||||
if strings.Contains(call, "--provider new") {
|
||||
|
||||
Reference in New Issue
Block a user