mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-04 20:17:09 +00:00
test(ios): cover the session replacement a wedged launch needs
This commit is contained in:
1 parent
d64781ce39
commit
8baea14245
1 file changed
+97
@@ -951,6 +951,103 @@ func TestLaunchLeavesATighterCallerDeadlineAlone(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wedgedUntilRestartCompanion models the session a refused launch leaves
|
||||||
|
// behind: the refusal is never reported, and no later launch is answered until
|
||||||
|
// the session itself is replaced.
|
||||||
|
type wedgedUntilRestartCompanion struct {
|
||||||
|
fakeCompanion
|
||||||
|
mutex sync.Mutex
|
||||||
|
replaced bool
|
||||||
|
attempted int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *wedgedUntilRestartCompanion) replaceSession() {
|
||||||
|
w.mutex.Lock()
|
||||||
|
defer w.mutex.Unlock()
|
||||||
|
w.replaced = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *wedgedUntilRestartCompanion) launchAttempts() int {
|
||||||
|
w.mutex.Lock()
|
||||||
|
defer w.mutex.Unlock()
|
||||||
|
return w.attempted
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *wedgedUntilRestartCompanion) Launch(ctx context.Context, _ string, _ bool) error {
|
||||||
|
w.mutex.Lock()
|
||||||
|
w.attempted++
|
||||||
|
replaced := w.replaced
|
||||||
|
w.mutex.Unlock()
|
||||||
|
if replaced {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
<-ctx.Done()
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestLaunchReplacesTheSessionAfterALaunchBlowsItsBound covers the FrontBoard
|
||||||
|
// race: a clear-state reinstall the simulator has not finished registering
|
||||||
|
// makes the session refuse the launch, and XCTest answers that refusal with
|
||||||
|
// minutes of diagnostics instead of an error, so the bound expires and every
|
||||||
|
// later call queues behind the same wedge. Calling launch again on that session
|
||||||
|
// cannot work; the run only recovers if the session is replaced first.
|
||||||
|
func TestLaunchReplacesTheSessionAfterALaunchBlowsItsBound(t *testing.T) {
|
||||||
|
previous := launchTimeout
|
||||||
|
launchTimeout = 100 * time.Millisecond
|
||||||
|
defer func() { launchTimeout = previous }()
|
||||||
|
|
||||||
|
companion := &wedgedUntilRestartCompanion{}
|
||||||
|
output := &bytes.Buffer{}
|
||||||
|
d := newTestDriver(companion)
|
||||||
|
d.output = output
|
||||||
|
restarts := 0
|
||||||
|
d.restart = func(context.Context) error {
|
||||||
|
restarts++
|
||||||
|
companion.replaceSession()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := d.Launch(context.Background(), "", false, nil); err != nil {
|
||||||
|
t.Fatalf("Launch: %v", err)
|
||||||
|
}
|
||||||
|
if restarts != 1 {
|
||||||
|
t.Fatalf("session restarts = %d, want exactly 1", restarts)
|
||||||
|
}
|
||||||
|
if attempts := companion.launchAttempts(); attempts != 2 {
|
||||||
|
t.Fatalf("launch attempts = %d, want 2: one that wedged and one on the replaced session", attempts)
|
||||||
|
}
|
||||||
|
if !strings.Contains(output.String(), "restarting the session") {
|
||||||
|
t.Fatalf("the recovery was silent, so a run that needed it never says so; output was %q", output.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestLaunchKeepsTheSessionWhenTheCallersOwnDeadlineExpires holds the recovery
|
||||||
|
// to the driver's own bound. Spending a session restart on a caller that has
|
||||||
|
// already run out of budget cannot produce a launch, only a later failure.
|
||||||
|
func TestLaunchKeepsTheSessionWhenTheCallersOwnDeadlineExpires(t *testing.T) {
|
||||||
|
previous := launchTimeout
|
||||||
|
launchTimeout = 30 * time.Second
|
||||||
|
defer func() { launchTimeout = previous }()
|
||||||
|
|
||||||
|
companion := &wedgedUntilRestartCompanion{}
|
||||||
|
d := newTestDriver(companion)
|
||||||
|
restarts := 0
|
||||||
|
d.restart = func(context.Context) error {
|
||||||
|
restarts++
|
||||||
|
companion.replaceSession()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
|
||||||
|
defer cancel()
|
||||||
|
if err := d.Launch(ctx, "", false, nil); !errors.Is(err, context.DeadlineExceeded) {
|
||||||
|
t.Fatalf("err = %v, want a deadline-exceeded error", err)
|
||||||
|
}
|
||||||
|
if restarts != 0 {
|
||||||
|
t.Fatalf("session restarts = %d, want 0", restarts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// newLockTestOptions builds New options that dial a seamed companion, so the
|
// newLockTestOptions builds New options that dial a seamed companion, so the
|
||||||
// device-lock tests exercise New without spawning anything.
|
// device-lock tests exercise New without spawning anything.
|
||||||
func newLockTestOptions(t *testing.T, udid string) Options {
|
func newLockTestOptions(t *testing.T, udid string) Options {
|
||||||
|
|||||||
Reference in new issue
Block a user