fix(ios): the clear-state guard checks the bundle that was cleared

A bool only said that something was cleared, so Launch(ctx, otherBundle,
clearState=true) passed the guard and reported a reset that had reached a
different app. Record what was cleared and compare against the bundle
being launched.
This commit is contained in:
pj committed 2026-08-16 01:04:58 +05:30
1 parent 99b9fe23f5
commit 6beea91046
2 files changed
+12 -10

No files matched your search

+1 -1
View File
@@ -83,7 +83,6 @@ func NewDevice(ctx context.Context, options DeviceOptions) (*Driver, error) {
coreDeviceID: options.CoreDeviceID, coreDeviceID: options.CoreDeviceID,
bundleID: options.BundleID, bundleID: options.BundleID,
appPath: options.AppPath, appPath: options.AppPath,
clearStateAtStartup: options.ClearState,
output: output, output: output,
doubleTapGapMilliseconds: gap, doubleTapGapMilliseconds: gap,
deviceMode: true, deviceMode: true,
@@ -137,6 +136,7 @@ func NewDevice(ctx context.Context, options DeviceOptions) (*Driver, error) {
d.Close() d.Close()
return nil, err return nil, err
} }
d.clearedBundleID = options.BundleID
} }
if err := d.bringUpDevice(ctx); err != nil { if err := d.bringUpDevice(ctx); err != nil {
+11 -9
View File
@@ -102,11 +102,12 @@ type Driver struct {
appPath string appPath string
output io.Writer output io.Writer
// clearStateAtStartup records that New (or NewDevice) reset the app to // clearedBundleID names the app New (or NewDevice) reset to first-launch
// first-launch state before attaching, which is the only point in a run // state before attaching, which is the only point in a run where clearing
// where clearing is safe. Launch refuses a clear-state request the driver // is safe. Launch refuses a clear-state request for anything else rather
// was not built for rather than reinstalling under a live session. // than reinstalling under a live session or reporting a reset that only
clearStateAtStartup bool // ever reached another bundle.
clearedBundleID string
screenWidth int screenWidth int
screenHeight int screenHeight int
@@ -233,7 +234,6 @@ func New(ctx context.Context, options Options) (*Driver, error) {
udid: options.UniqueDeviceIdentifier, udid: options.UniqueDeviceIdentifier,
bundleID: options.BundleID, bundleID: options.BundleID,
appPath: options.AppPath, appPath: options.AppPath,
clearStateAtStartup: options.ClearState,
output: output, output: output,
doubleTapGapMilliseconds: gap, doubleTapGapMilliseconds: gap,
spawnChild: options.spawnChild, spawnChild: options.spawnChild,
@@ -295,6 +295,7 @@ func New(ctx context.Context, options Options) (*Driver, error) {
driverInstance.Close() driverInstance.Close()
return nil, err return nil, err
} }
driverInstance.clearedBundleID = options.BundleID
} }
if err := driverInstance.bringUp(ctx); err != nil { if err := driverInstance.bringUp(ctx); err != nil {
@@ -524,12 +525,13 @@ func (d *Driver) Launch(ctx context.Context, bundleID string, clearState bool, e
// loudly rather than silently dropping the request. // loudly rather than silently dropping the request.
return errors.New("ios companion: launch with environment variables is unsupported on this backend") return errors.New("ios companion: launch with environment variables is unsupported on this backend")
} }
if clearState && !d.clearStateAtStartup { if clearState && (d.clearedBundleID == "" || d.clearedBundleID != d.bundleID) {
// Clearing here would uninstall and reinstall the app underneath a live // Clearing here would uninstall and reinstall the app underneath a live
// automation session, which is what races FrontBoard's registration and // automation session, which is what races FrontBoard's registration and
// leaves the session launching a bundle FrontBoard has not registered. // leaves the session launching a bundle FrontBoard has not registered.
return errors.New("ios companion: clear-state must be requested when the driver is created (Options.ClearState); " + return fmt.Errorf("ios companion: clear-state must be requested when the driver is created (Options.ClearState) "+
"this backend clears the app before its automation session exists") "for the bundle being launched; this backend cleared %q before its automation session existed, not %q",
d.clearedBundleID, d.bundleID)
} }
// Terminate first so the launch is a clean cold start regardless of the // Terminate first so the launch is a clean cold start regardless of the