diff --git a/end-to-end/organization_token_test.go b/end-to-end/organization_token_test.go index fb5c86467..8572ee483 100644 --- a/end-to-end/organization_token_test.go +++ b/end-to-end/organization_token_test.go @@ -67,7 +67,7 @@ func TestOrganizationProvidedToken(t *testing.T) { require.NoErrorf(t, err, "Setup: could not wake distro up: %v. %s", err, out) } - const maxTimeout = 15 * time.Second + const maxTimeout = 30 * time.Second if !tc.wantAttached { time.Sleep(maxTimeout) diff --git a/gui/packages/ubuntupro/lib/pages/startup/agent_monitor.dart b/gui/packages/ubuntupro/lib/pages/startup/agent_monitor.dart index 9dee12778..962557e6f 100644 --- a/gui/packages/ubuntupro/lib/pages/startup/agent_monitor.dart +++ b/gui/packages/ubuntupro/lib/pages/startup/agent_monitor.dart @@ -79,7 +79,7 @@ class AgentStartupMonitor { /// The loop stops if a terminal condition is found or [timeout] expires. Stream start({ Duration interval = const Duration(seconds: 1), - Duration timeout = const Duration(seconds: 30), + Duration timeout = const Duration(seconds: 5), }) async* { if (_addrFilePath == null) { // Terminal state, cannot recover nor retry. @@ -127,10 +127,16 @@ class AgentStartupMonitor { // Terminal state, cannot recover nor retry. return AgentState.unknownEnv; case AgentAddrFileError.nonexistent: + // The directory must exist so we can watch for changes. This won't fail if the directory already exists. + final agentDir = await File(_addrFilePath!).parent.create(); + final watch = agentDir + .watch(events: FileSystemEvent.create) + .firstWhere((event) => event.path.contains(_addrFilePath!)); if (!await agentLauncher()) { // Terminal state, cannot recover nor retry. return AgentState.cannotStart; } + await watch; return AgentState.starting; // maybe a race condition allowed us to read the file before write completed? Retry. // ignore: switch_case_completes_normally diff --git a/gui/packages/ubuntupro/test/startup/agent_monitor_test.dart b/gui/packages/ubuntupro/test/startup/agent_monitor_test.dart index 6f8b4a5fd..68e2d1132 100644 --- a/gui/packages/ubuntupro/test/startup/agent_monitor_test.dart +++ b/gui/packages/ubuntupro/test/startup/agent_monitor_test.dart @@ -191,6 +191,32 @@ void main() { verify(mockClient.ping()).called(1); }); + test('timeout if never addr', () async { + final mockClient = MockAgentApiClient(); + // Fakes a successful ping. + when(mockClient.ping()).thenAnswer((_) async => true); + final monitor = AgentStartupMonitor( + /// A launch request will always succeed, but never writes the addr file. + agentLauncher: () async { + return true; + }, + clientFactory: (port) => mockClient, + appName: kAppName, + addrFileName: kAddrFileName, + onClient: (_) {}, + ); + + await expectLater( + monitor.start(interval: kInterval), + emitsInOrder([ + AgentState.querying, + // instead of waiting the addr file to show up forever, we are caught by our internal timeout. + AgentState.unreachable, + ]), + ); + verifyNever(mockClient.ping()); + }); + test('await async onClient callback', () async { final completeMe = Completer(); final mockClient = MockAgentApiClient(); diff --git a/gui/packages/ubuntupro/test/startup/startup_model_test.mocks.dart b/gui/packages/ubuntupro/test/startup/startup_model_test.mocks.dart index c7cd6a758..d0fc23031 100644 --- a/gui/packages/ubuntupro/test/startup/startup_model_test.mocks.dart +++ b/gui/packages/ubuntupro/test/startup/startup_model_test.mocks.dart @@ -61,7 +61,7 @@ class MockAgentStartupMonitor extends _i1.Mock @override _i4.Stream<_i3.AgentState> start({ Duration? interval = const Duration(seconds: 1), - Duration? timeout = const Duration(seconds: 30), + Duration? timeout = const Duration(seconds: 5), }) => (super.noSuchMethod( Invocation.method( diff --git a/gui/packages/ubuntupro/test/startup/startup_page_test.mocks.dart b/gui/packages/ubuntupro/test/startup/startup_page_test.mocks.dart index 07b451ece..fbf2e0226 100644 --- a/gui/packages/ubuntupro/test/startup/startup_page_test.mocks.dart +++ b/gui/packages/ubuntupro/test/startup/startup_page_test.mocks.dart @@ -73,7 +73,7 @@ class MockAgentStartupMonitor extends _i1.Mock @override _i5.Stream<_i4.AgentState> start({ Duration? interval = const Duration(seconds: 1), - Duration? timeout = const Duration(seconds: 30), + Duration? timeout = const Duration(seconds: 5), }) => (super.noSuchMethod( Invocation.method(