feat: notify when managed browsers exit
This commit is contained in:
+101
-8
@@ -129,7 +129,7 @@ func TestShellStartsInstanceAsynchronouslyAndAppliesResult(t *testing.T) {
|
||||
shell := NewShell(material.NewTheme())
|
||||
target := shell.rows[0]
|
||||
started := make(chan InstanceRow, 1)
|
||||
shell.OnStartInstance(func(_ context.Context, row InstanceRow, _ SettingsState) (InstanceStartOutcome, error) {
|
||||
shell.OnStartInstance(func(_ context.Context, row InstanceRow, _ SettingsState, _ uint64) (InstanceStartOutcome, error) {
|
||||
started <- row
|
||||
return InstanceStartOutcome{PID: 4242, RemoteDebugPort: 9666}, nil
|
||||
}, nil)
|
||||
@@ -165,7 +165,7 @@ func TestShellDoesNotStartTheSameInstanceTwiceWhilePending(t *testing.T) {
|
||||
entered := make(chan struct{}, 1)
|
||||
release := make(chan struct{})
|
||||
var calls atomic.Int32
|
||||
shell.OnStartInstance(func(_ context.Context, _ InstanceRow, _ SettingsState) (InstanceStartOutcome, error) {
|
||||
shell.OnStartInstance(func(_ context.Context, _ InstanceRow, _ SettingsState, _ uint64) (InstanceStartOutcome, error) {
|
||||
calls.Add(1)
|
||||
entered <- struct{}{}
|
||||
<-release
|
||||
@@ -196,7 +196,7 @@ func TestShellStopsManagedInstanceAsynchronouslyAndRestoresStartAction(t *testin
|
||||
shell := NewShell(material.NewTheme())
|
||||
target := shell.rows[0]
|
||||
stopped := make(chan InstanceRow, 1)
|
||||
shell.OnStopInstance(func(_ context.Context, row InstanceRow) error {
|
||||
shell.OnStopInstance(func(_ context.Context, row InstanceRow, _ uint64) error {
|
||||
stopped <- row
|
||||
return nil
|
||||
}, nil)
|
||||
@@ -233,7 +233,7 @@ func TestShellDoesNotStopTheSameInstanceTwiceOrExternalInstance(t *testing.T) {
|
||||
entered := make(chan struct{}, 1)
|
||||
release := make(chan struct{})
|
||||
var calls atomic.Int32
|
||||
shell.OnStopInstance(func(context.Context, InstanceRow) error {
|
||||
shell.OnStopInstance(func(context.Context, InstanceRow, uint64) error {
|
||||
calls.Add(1)
|
||||
entered <- struct{}{}
|
||||
<-release
|
||||
@@ -260,8 +260,8 @@ func TestShellDoesNotStopTheSameInstanceTwiceOrExternalInstance(t *testing.T) {
|
||||
|
||||
external := shell.rows[2]
|
||||
var externalStops atomic.Int32
|
||||
shell.OnStopInstance(func(context.Context, InstanceRow) error { externalStops.Add(1); return nil }, nil)
|
||||
shell.OnStartInstance(func(context.Context, InstanceRow, SettingsState) (InstanceStartOutcome, error) {
|
||||
shell.OnStopInstance(func(context.Context, InstanceRow, uint64) error { externalStops.Add(1); return nil }, nil)
|
||||
shell.OnStartInstance(func(context.Context, InstanceRow, SettingsState, uint64) (InstanceStartOutcome, error) {
|
||||
return InstanceStartOutcome{External: true, Source: "browser_message_window"}, nil
|
||||
}, nil)
|
||||
shell.requestInstanceAction(external.ID)
|
||||
@@ -273,7 +273,7 @@ func TestShellDoesNotStopTheSameInstanceTwiceOrExternalInstance(t *testing.T) {
|
||||
func TestShellRestoresManagedStatusAfterStopFailure(t *testing.T) {
|
||||
shell := NewShell(material.NewTheme())
|
||||
target := shell.rows[0]
|
||||
shell.OnStopInstance(func(context.Context, InstanceRow) error { return errors.New("permission denied") }, nil)
|
||||
shell.OnStopInstance(func(context.Context, InstanceRow, uint64) error { return errors.New("permission denied") }, nil)
|
||||
shell.requestInstanceAction(target.ID)
|
||||
var result instanceStopResult
|
||||
select {
|
||||
@@ -358,7 +358,7 @@ func TestShellNormalizesRemoteDebugStartPort(t *testing.T) {
|
||||
func TestShellMarksExternalAssociationWithoutManagingLifecycle(t *testing.T) {
|
||||
shell := NewShell(material.NewTheme())
|
||||
target := shell.rows[2]
|
||||
shell.OnStartInstance(func(_ context.Context, _ InstanceRow, _ SettingsState) (InstanceStartOutcome, error) {
|
||||
shell.OnStartInstance(func(_ context.Context, _ InstanceRow, _ SettingsState, _ uint64) (InstanceStartOutcome, error) {
|
||||
return InstanceStartOutcome{PID: 16108, RemoteDebugPort: 9668, External: true, Source: "browser_message_window"}, nil
|
||||
}, nil)
|
||||
|
||||
@@ -624,3 +624,96 @@ func TestShellSavesProxyFromAddressPicker(t *testing.T) {
|
||||
t.Fatalf("created proxy = %#v, selected %q, changes %d", shell.proxies, shell.settingsProxyID, changes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShellMarksUnexpectedManagedExitAndRestoresStartFocus(t *testing.T) {
|
||||
shell := NewShell(material.NewTheme())
|
||||
target := shell.rows[0]
|
||||
shell.startStates[target.ID] = &instanceStartState{request: 7}
|
||||
|
||||
shell.ReportManagedExit(ManagedInstanceExit{InstanceID: target.ID, LaunchGeneration: 7, PID: target.PID, ExitCode: 0})
|
||||
shell.consumeManagedExitResults()
|
||||
shell.presentUnexpectedExitIfReady()
|
||||
|
||||
row, ok := shell.instanceRow(target.ID)
|
||||
if !ok || row.Status != "已退出" || row.PID != 0 || row.RemoteDebugPort != 0 || row.OccupancySource != "" || !shell.unexpectedExitOpen || len(shell.unexpectedExits) != 1 {
|
||||
t.Fatalf("unexpected exit state = row %#v, dialog %v, notices %#v", row, shell.unexpectedExitOpen, shell.unexpectedExits)
|
||||
}
|
||||
if mode := instanceActionFor(row); !mode.enabled || mode.stop || mode.label != "启动" {
|
||||
t.Fatalf("action after unexpected exit = %#v", mode)
|
||||
}
|
||||
|
||||
shell.dismissUnexpectedExitNotice()
|
||||
if shell.unexpectedExitOpen || len(shell.unexpectedExits) != 0 || shell.focusStartID != target.ID {
|
||||
t.Fatalf("dismissed unexpected exit state = open %v, notices %#v, focus %q", shell.unexpectedExitOpen, shell.unexpectedExits, shell.focusStartID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShellDoesNotNotifyExpectedOrStaleManagedExit(t *testing.T) {
|
||||
shell := NewShell(material.NewTheme())
|
||||
target := shell.rows[0]
|
||||
shell.startStates[target.ID] = &instanceStartState{request: 3}
|
||||
|
||||
shell.ReportManagedExit(ManagedInstanceExit{InstanceID: target.ID, LaunchGeneration: 2, PID: target.PID, ExitCode: 0})
|
||||
shell.consumeManagedExitResults()
|
||||
if row, _ := shell.instanceRow(target.ID); row.Status != "运行中" || len(shell.unexpectedExits) != 0 {
|
||||
t.Fatalf("stale exit changed row = %#v, notices %#v", row, shell.unexpectedExits)
|
||||
}
|
||||
|
||||
shell.ReportManagedExit(ManagedInstanceExit{InstanceID: target.ID, LaunchGeneration: 3, PID: target.PID, ExitCode: 0, ExpectedStop: true})
|
||||
shell.consumeManagedExitResults()
|
||||
shell.presentUnexpectedExitIfReady()
|
||||
if row, _ := shell.instanceRow(target.ID); row.Status != "已退出" || len(shell.unexpectedExits) != 0 || shell.unexpectedExitOpen {
|
||||
t.Fatalf("expected exit state = row %#v, notices %#v, dialog %v", row, shell.unexpectedExits, shell.unexpectedExitOpen)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShellAppliesManagedExitThatArrivesDuringStart(t *testing.T) {
|
||||
shell := NewShell(material.NewTheme())
|
||||
target := shell.rows[0]
|
||||
target.Status = "启动中"
|
||||
target.PID = 0
|
||||
target.RemoteDebugPort = 0
|
||||
shell.rows[0] = target
|
||||
shell.startStates[target.ID] = &instanceStartState{request: 5, running: true}
|
||||
|
||||
shell.ReportManagedExit(ManagedInstanceExit{InstanceID: target.ID, LaunchGeneration: 5, PID: 5123, ExitCode: 1})
|
||||
shell.consumeManagedExitResults()
|
||||
if len(shell.pendingManagedExit) != 1 {
|
||||
t.Fatalf("pending managed exits = %#v", shell.pendingManagedExit)
|
||||
}
|
||||
|
||||
shell.startStates[target.ID].running = false
|
||||
shell.setInstanceRuntime(target.ID, "运行中", 5123, 9666, "chub_registry")
|
||||
if !shell.applyPendingManagedExit(target.ID, 5, 5123) {
|
||||
t.Fatal("pending managed exit was not applied")
|
||||
}
|
||||
shell.presentUnexpectedExitIfReady()
|
||||
if row, _ := shell.instanceRow(target.ID); row.Status != "已退出" || !shell.unexpectedExitOpen {
|
||||
t.Fatalf("quick exit after start = row %#v, dialog %v", row, shell.unexpectedExitOpen)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShellAggregatesManagedExitNoticesUntilOtherModalCloses(t *testing.T) {
|
||||
shell := NewShell(material.NewTheme())
|
||||
shell.SetInstances([]InstanceRow{
|
||||
{ID: "chrome", Name: "运营 Chrome", Browser: "Chrome", UserDataDir: t.TempDir(), PID: 4001, RemoteDebugPort: 9666, OccupancySource: "chub_registry", Status: "运行中"},
|
||||
{ID: "edge", Name: "审核 Edge", Browser: "Edge", UserDataDir: t.TempDir(), PID: 4002, RemoteDebugPort: 9667, OccupancySource: "chub_registry", Status: "运行中"},
|
||||
})
|
||||
shell.startStates["chrome"] = &instanceStartState{request: 1}
|
||||
shell.startStates["edge"] = &instanceStartState{request: 2}
|
||||
shell.editingID = "editing"
|
||||
|
||||
shell.ReportManagedExit(ManagedInstanceExit{InstanceID: "chrome", LaunchGeneration: 1, PID: 4001})
|
||||
shell.ReportManagedExit(ManagedInstanceExit{InstanceID: "edge", LaunchGeneration: 2, PID: 4002})
|
||||
shell.consumeManagedExitResults()
|
||||
shell.presentUnexpectedExitIfReady()
|
||||
if shell.unexpectedExitOpen || len(shell.unexpectedExits) != 2 {
|
||||
t.Fatalf("queued notices = open %v, notices %#v", shell.unexpectedExitOpen, shell.unexpectedExits)
|
||||
}
|
||||
|
||||
shell.editingID = ""
|
||||
shell.presentUnexpectedExitIfReady()
|
||||
if !shell.unexpectedExitOpen || len(shell.unexpectedExits) != 2 {
|
||||
t.Fatalf("aggregated notices = open %v, notices %#v", shell.unexpectedExitOpen, shell.unexpectedExits)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user