From 86715a6e3f47b4938b558ee289e0b92f8c7550fb Mon Sep 17 00:00:00 2001 From: Bartek Pacia Date: Tue, 24 Oct 2023 20:11:18 +0200 Subject: [PATCH] fix possible race condition Before, PatrolServer.appReady was set once to true during the initial run, and it stayed like that in subsequent runs. This was a race conditions, and a temporary solution with 1 sec timeout was applied. Now the timeout is removed, and the logic should be fixed. --- .../example/ios/RunnerUITests/RunnerUITests.m | 8 +++- .../AutomatorServer/PatrolServer.swift | 2 +- .../Classes/ObjCPatrolAppServiceClient.swift | 47 ++++++++----------- 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/packages/patrol/example/ios/RunnerUITests/RunnerUITests.m b/packages/patrol/example/ios/RunnerUITests/RunnerUITests.m index a6c7c4b64e..976cd0e19a 100644 --- a/packages/patrol/example/ios/RunnerUITests/RunnerUITests.m +++ b/packages/patrol/example/ios/RunnerUITests/RunnerUITests.m @@ -100,12 +100,18 @@ @implementation __test_class /* Step 1 - dynamically create test cases */ IMP implementation = imp_implementationWithBlock(^(id _self) { + /* Reset server's appReady state, because new app process will be started */ + server.appReady = NO; + XCUIApplication *app = [[XCUIApplication alloc] init]; NSDictionary *args = @{ @"PATROL_INITIAL_RUN" : @"false" }; [app setLaunchEnvironment:args]; [app launch]; - // TODO: wait for patrolAppService to be ready + /* Spin the runloop waiting until the app reports that PatrolAppService is up */ + while (!server.appReady) { + [NSRunLoop.currentRunLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]]; + } __block BOOL callbacksSet = NO; [appServiceClient setDartLifecycleCallbacksState:callbacksState completion:^(NSError * _Nullable err) { diff --git a/packages/patrol/ios/Classes/AutomatorServer/PatrolServer.swift b/packages/patrol/ios/Classes/AutomatorServer/PatrolServer.swift index bbac95b1a6..c116498f7f 100644 --- a/packages/patrol/ios/Classes/AutomatorServer/PatrolServer.swift +++ b/packages/patrol/ios/Classes/AutomatorServer/PatrolServer.swift @@ -13,7 +13,7 @@ import Telegraph #endif @objc - public private(set) var appReady = false + public var appReady = false private let onLifecycleCallbackExecuted: (String) -> Void diff --git a/packages/patrol/ios/Classes/ObjCPatrolAppServiceClient.swift b/packages/patrol/ios/Classes/ObjCPatrolAppServiceClient.swift index b8c7b0b03a..085f902481 100644 --- a/packages/patrol/ios/Classes/ObjCPatrolAppServiceClient.swift +++ b/packages/patrol/ios/Classes/ObjCPatrolAppServiceClient.swift @@ -65,15 +65,13 @@ ) { NSLog("PatrolAppService.setDartLifecycleCallbacksState(\(state)") - DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { - let request = SetLifecycleCallbacksStateRequest(state: state) - self.client.setLifecycleCallbacksState(request: request) { result in - switch result { - case .success(_): - completion(nil) - case .failure(let error): - completion(error) - } + let request = SetLifecycleCallbacksStateRequest(state: state) + self.client.setLifecycleCallbacksState(request: request) { result in + switch result { + case .success(_): + completion(nil) + case .failure(let error): + completion(error) } } } @@ -81,24 +79,19 @@ @objc public func runDartTest( _ name: String, completion: @escaping (ObjCRunDartTestResponse?, Error?) -> Void ) { - // TODO: simple workaround - patrolAppService starts running too slowly. - // We should wait for appReady in the dynamically created test case method, - // before calling runDartTest() (in PATROL_INTEGRATION_TEST_IOS_MACRO) - DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { - NSLog("PatrolAppServiceClient.runDartTest(\(name))") - - let request = RunDartTestRequest(name: name) - self.client.runDartTest(request: request) { result in - switch result { - case .success(let result): - let testRespone = ObjCRunDartTestResponse( - passed: result.result == .success, - details: result.details - ) - completion(testRespone, nil) - case .failure(let error): - completion(nil, error) - } + NSLog("PatrolAppServiceClient.runDartTest(\(name))") + + let request = RunDartTestRequest(name: name) + self.client.runDartTest(request: request) { result in + switch result { + case .success(let result): + let testRespone = ObjCRunDartTestResponse( + passed: result.result == .success, + details: result.details + ) + completion(testRespone, nil) + case .failure(let error): + completion(nil, error) } } }