appium-mac2-driver 4.3.6 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/WebDriverAgentMac/IntegrationTests/AMSessionTests.m +14 -0
- package/WebDriverAgentMac/WebDriverAgentLib/Commands/FBSessionCommands.m +17 -5
- package/WebDriverAgentMac/WebDriverAgentLib/Routing/FBSession.m +5 -1
- package/build/lib/driver.d.ts +3 -0
- package/build/lib/driver.d.ts.map +1 -1
- package/build/lib/driver.js +52 -32
- package/build/lib/driver.js.map +1 -1
- package/build/lib/session-claim-handler.d.ts +41 -0
- package/build/lib/session-claim-handler.d.ts.map +1 -0
- package/build/lib/session-claim-handler.js +236 -0
- package/build/lib/session-claim-handler.js.map +1 -0
- package/build/lib/wda-mac.d.ts +6 -2
- package/build/lib/wda-mac.d.ts.map +1 -1
- package/build/lib/wda-mac.js +39 -9
- package/build/lib/wda-mac.js.map +1 -1
- package/lib/driver.ts +55 -31
- package/lib/session-claim-handler.ts +306 -0
- package/lib/wda-mac.ts +41 -10
- package/node_modules/appium-xcode/CHANGELOG.md +7 -0
- package/node_modules/appium-xcode/package.json +4 -4
- package/node_modules/async-lock/AUTHORS +21 -0
- package/node_modules/async-lock/History.md +132 -0
- package/node_modules/async-lock/LICENSE +22 -0
- package/node_modules/async-lock/README.md +177 -0
- package/node_modules/async-lock/index.js +2 -0
- package/node_modules/async-lock/lib/index.js +312 -0
- package/node_modules/async-lock/package.json +48 -0
- package/node_modules/bare-fs/binding.c +1 -1
- package/node_modules/bare-fs/index.js +30 -6
- package/node_modules/bare-fs/package.json +1 -1
- package/node_modules/bare-fs/prebuilds/android-arm/bare-fs.bare +0 -0
- package/node_modules/bare-fs/prebuilds/android-arm64/bare-fs.bare +0 -0
- package/node_modules/bare-fs/prebuilds/android-ia32/bare-fs.bare +0 -0
- package/node_modules/bare-fs/prebuilds/android-x64/bare-fs.bare +0 -0
- package/node_modules/bare-fs/prebuilds/darwin-arm64/bare-fs.bare +0 -0
- package/node_modules/bare-fs/prebuilds/darwin-x64/bare-fs.bare +0 -0
- package/node_modules/bare-fs/prebuilds/ios-arm64/bare-fs.bare +0 -0
- package/node_modules/bare-fs/prebuilds/ios-arm64-simulator/bare-fs.bare +0 -0
- package/node_modules/bare-fs/prebuilds/ios-x64-simulator/bare-fs.bare +0 -0
- package/node_modules/bare-fs/prebuilds/linux-arm64/bare-fs.bare +0 -0
- package/node_modules/bare-fs/prebuilds/linux-x64/bare-fs.bare +0 -0
- package/node_modules/bare-fs/prebuilds/win32-arm64/bare-fs.bare +0 -0
- package/node_modules/bare-fs/prebuilds/win32-x64/bare-fs.bare +0 -0
- package/node_modules/readable-stream/lib/internal/shims/process.js +19 -0
- package/node_modules/readable-stream/lib/internal/streams/destroy.js +1 -1
- package/node_modules/readable-stream/lib/internal/streams/duplexify.js +1 -1
- package/node_modules/readable-stream/lib/internal/streams/end-of-stream.js +1 -1
- package/node_modules/readable-stream/lib/internal/streams/from.js +1 -1
- package/node_modules/readable-stream/lib/internal/streams/legacy.js +6 -1
- package/node_modules/readable-stream/lib/internal/streams/pipeline.js +1 -1
- package/node_modules/readable-stream/lib/internal/streams/readable.js +1 -1
- package/node_modules/readable-stream/lib/internal/streams/writable.js +1 -1
- package/node_modules/readable-stream/package.json +3 -2
- package/node_modules/tar-stream/package.json +7 -7
- package/package.json +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [4.4.0](https://github.com/appium/appium-mac2-driver/compare/v4.3.6...v4.4.0) (2026-10-11)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
* enforce a single session, a new session replaces the previous one ([#426](https://github.com/appium/appium-mac2-driver/issues/426)) ([fb10372](https://github.com/appium/appium-mac2-driver/commit/fb10372c16d861fb7ff9463b345ba6fcb3f67387))
|
|
6
|
+
|
|
1
7
|
## [4.3.6](https://github.com/appium/appium-mac2-driver/compare/v4.3.5...v4.3.6) (2026-10-02)
|
|
2
8
|
|
|
3
9
|
### Bug Fixes
|
|
@@ -43,6 +43,20 @@ static NSString *const SETTINGS_BUNDLE_ID = @"com.apple.systempreferences";
|
|
|
43
43
|
[super tearDown];
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
- (void)testNewSessionOverridesThePreviousOne
|
|
47
|
+
{
|
|
48
|
+
NSString *oldId = self.session.identifier;
|
|
49
|
+
FBSession *newSession = [FBSession initWithApplication:nil];
|
|
50
|
+
XCTAssertNotEqualObjects(oldId, newSession.identifier);
|
|
51
|
+
XCTAssertEqual(FBSession.activeSession, newSession);
|
|
52
|
+
XCTAssertNil([FBSession sessionWithIdentifier:oldId]);
|
|
53
|
+
// Killing the stale session must not drop the active one
|
|
54
|
+
[self.session kill];
|
|
55
|
+
XCTAssertEqual(FBSession.activeSession, newSession);
|
|
56
|
+
[newSession kill];
|
|
57
|
+
XCTAssertNil(FBSession.activeSession);
|
|
58
|
+
}
|
|
59
|
+
|
|
46
60
|
- (void)testSettingsAppCanBeOpenedInScopeOfTheCurrentSession
|
|
47
61
|
{
|
|
48
62
|
[self.session launchApplicationWithBundleId:SETTINGS_BUNDLE_ID
|
|
@@ -99,9 +99,15 @@ const static NSString *CAPABILITIES_KEY = @"capabilities";
|
|
|
99
99
|
NSString *appPath = requirements[AM_APP_PATH_CAPABILITY];
|
|
100
100
|
NSString *deepLink = requirements[AM_INITIAL_DEEPLINK_URL_CAPABILITY];
|
|
101
101
|
BOOL noReset = [requirements[AM_NO_RESET_CAPABILITY] boolValue];
|
|
102
|
-
|
|
102
|
+
|
|
103
|
+
// XCTest is single-threaded, so there can only be one session. A new one always
|
|
104
|
+
// takes over, and the previous one must be gone before any app gets touched.
|
|
105
|
+
[FBSession.activeSession kill];
|
|
106
|
+
|
|
107
|
+
XCUIApplication *app = nil;
|
|
108
|
+
BOOL didLaunchApp = NO;
|
|
103
109
|
if (nil == bundleID && nil == appPath && nil == deepLink) {
|
|
104
|
-
|
|
110
|
+
// no app to manage
|
|
105
111
|
} else if (nil != deepLink) {
|
|
106
112
|
NSURL *url = [NSURL URLWithString:deepLink];
|
|
107
113
|
NSError *error;
|
|
@@ -113,13 +119,12 @@ const static NSString *CAPABILITIES_KEY = @"capabilities";
|
|
|
113
119
|
traceback:nil]);
|
|
114
120
|
}
|
|
115
121
|
if (nil != bundleID) {
|
|
116
|
-
|
|
122
|
+
app = [[XCUIApplication alloc] initWithBundleIdentifier:bundleID];
|
|
117
123
|
}
|
|
118
124
|
} else {
|
|
119
|
-
|
|
125
|
+
app = nil != appPath
|
|
120
126
|
? [[XCUIApplication alloc] initWithURL:[NSURL fileURLWithPath:appPath]]
|
|
121
127
|
: [[XCUIApplication alloc] initWithBundleIdentifier:bundleID];
|
|
122
|
-
session = [FBSession initWithApplication:app];
|
|
123
128
|
if (noReset && app.state > XCUIApplicationStateNotRunning) {
|
|
124
129
|
[app activate];
|
|
125
130
|
} else {
|
|
@@ -140,6 +145,7 @@ const static NSString *CAPABILITIES_KEY = @"capabilities";
|
|
|
140
145
|
}
|
|
141
146
|
app.launchEnvironment = [launchEnv copy];
|
|
142
147
|
[app launch];
|
|
148
|
+
didLaunchApp = YES;
|
|
143
149
|
if (app.state <= XCUIApplicationStateNotRunning) {
|
|
144
150
|
NSString *message = [NSString stringWithFormat:@"Failed to launch '%@' application", appPath ?: bundleID];
|
|
145
151
|
return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:message
|
|
@@ -149,6 +155,10 @@ const static NSString *CAPABILITIES_KEY = @"capabilities";
|
|
|
149
155
|
if (nil != bundleID && nil != appPath) {
|
|
150
156
|
NSString *realBundleID = app.am_bundleID;
|
|
151
157
|
if (![realBundleID isEqualToString:bundleID]) {
|
|
158
|
+
// no session owns the app, so don't leave it behind
|
|
159
|
+
if (didLaunchApp) {
|
|
160
|
+
[app terminate];
|
|
161
|
+
}
|
|
152
162
|
NSString *message = [NSString stringWithFormat:@"The bundle identifier %@ of the '%@' does not match to the one provided in capabilities: %@",
|
|
153
163
|
realBundleID, appPath, bundleID];
|
|
154
164
|
return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:message
|
|
@@ -156,6 +166,8 @@ const static NSString *CAPABILITIES_KEY = @"capabilities";
|
|
|
156
166
|
}
|
|
157
167
|
}
|
|
158
168
|
}
|
|
169
|
+
// The session is only registered once startup has fully succeeded
|
|
170
|
+
FBSession *session = [FBSession initWithApplication:app];
|
|
159
171
|
if (nil != requirements[AM_SKIP_APP_KILL_CAPABILITY]) {
|
|
160
172
|
session.skipAppTermination = [requirements[AM_SKIP_APP_KILL_CAPABILITY] boolValue];
|
|
161
173
|
} else if (nil == bundleID) {
|
|
@@ -72,6 +72,11 @@ static FBSession *_activeSession = nil;
|
|
|
72
72
|
[self.testedApplication terminate];
|
|
73
73
|
}
|
|
74
74
|
self.testedApplication = nil;
|
|
75
|
+
[self.elementCache reset];
|
|
76
|
+
// The recording belongs to the active session, so a stale one must not touch it
|
|
77
|
+
if (_activeSession != self) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
75
80
|
FBScreenRecordingContainer *screenRecordingContainer = FBScreenRecordingContainer.sharedInstance;
|
|
76
81
|
NSUUID *videoRecordingId = screenRecordingContainer.screenRecordingPromise.identifier;
|
|
77
82
|
if (nil != videoRecordingId) {
|
|
@@ -83,7 +88,6 @@ static FBSession *_activeSession = nil;
|
|
|
83
88
|
if (nil != screenRecordingContainer.screenRecordingPromise) {
|
|
84
89
|
[screenRecordingContainer reset];
|
|
85
90
|
}
|
|
86
|
-
[self.elementCache reset];
|
|
87
91
|
_activeSession = nil;
|
|
88
92
|
}
|
|
89
93
|
|
package/build/lib/driver.d.ts
CHANGED
|
@@ -268,6 +268,8 @@ export declare class Mac2Driver extends BaseDriver<Mac2Constraints, StringRecord
|
|
|
268
268
|
proxyReqRes: (...args: any) => any;
|
|
269
269
|
private isProxyActive;
|
|
270
270
|
private _wda;
|
|
271
|
+
private _wdaSessionId;
|
|
272
|
+
private _hasClaimedHost;
|
|
271
273
|
constructor(opts?: InitialOpts);
|
|
272
274
|
get wda(): WDAMacServer;
|
|
273
275
|
onSettingsUpdate(key: string, value: unknown): Promise<void>;
|
|
@@ -279,6 +281,7 @@ export declare class Mac2Driver extends BaseDriver<Mac2Constraints, StringRecord
|
|
|
279
281
|
getWindowRect(): Promise<any>;
|
|
280
282
|
createSession(w3cCaps1: W3CMac2DriverCaps, w3cCaps2?: W3CMac2DriverCaps, w3cCaps3?: W3CMac2DriverCaps, driverData?: DriverData[]): Promise<DefaultCreateSessionResult<Mac2Constraints>>;
|
|
281
283
|
deleteSession(): Promise<void>;
|
|
284
|
+
private teardownSession;
|
|
282
285
|
private resetState;
|
|
283
286
|
}
|
|
284
287
|
export default Mac2Driver;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../lib/driver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,0BAA0B,EAC1B,UAAU,EACV,WAAW,EACX,YAAY,EACZ,cAAc,EAGd,aAAa,EACd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAC,UAAU,
|
|
1
|
+
{"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../lib/driver.ts"],"names":[],"mappings":"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"}
|
package/build/lib/driver.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BaseDriver, DeviceSettings } from 'appium/driver.js';
|
|
1
|
+
import { BaseDriver, DeviceSettings, errors } from 'appium/driver.js';
|
|
2
2
|
import * as appManagemenetCommands from './commands/app-management.js';
|
|
3
3
|
import * as appleScriptCommands from './commands/applescript.js';
|
|
4
4
|
import * as auditCommands from './commands/audit.js';
|
|
@@ -15,6 +15,7 @@ import MAC2_CONSTRAINTS from './constraints.js';
|
|
|
15
15
|
import { executeMethodMap } from './execute-method-map.js';
|
|
16
16
|
import log from './logger.js';
|
|
17
17
|
import { newMethodMap } from './method-map.js';
|
|
18
|
+
import { sessionClaimHandler } from './session-claim-handler.js';
|
|
18
19
|
import { WDA_MAC_SERVER } from './wda-mac.js';
|
|
19
20
|
const NO_PROXY = [
|
|
20
21
|
['GET', new RegExp('^/session/[^/]+/appium')],
|
|
@@ -70,6 +71,8 @@ export class Mac2Driver extends BaseDriver {
|
|
|
70
71
|
proxyReqRes;
|
|
71
72
|
isProxyActive = false;
|
|
72
73
|
_wda = null;
|
|
74
|
+
_wdaSessionId = null;
|
|
75
|
+
_hasClaimedHost = false;
|
|
73
76
|
constructor(opts = {}) {
|
|
74
77
|
super(opts);
|
|
75
78
|
this.desiredCapConstraints = structuredClone(MAC2_CONSTRAINTS);
|
|
@@ -91,13 +94,18 @@ export class Mac2Driver extends BaseDriver {
|
|
|
91
94
|
if (!this._wda) {
|
|
92
95
|
throw new Error('WDA server is not initialized');
|
|
93
96
|
}
|
|
97
|
+
// The WDA server is shared and only supports a single session, so a newer
|
|
98
|
+
// session replaces this one. Never send commands on its behalf after that.
|
|
99
|
+
if (this._wdaSessionId && !this._wda.isSessionActive(this._wdaSessionId)) {
|
|
100
|
+
throw new errors.NoSuchDriverError('This session has been replaced by a newer one, because this driver only supports a single session');
|
|
101
|
+
}
|
|
94
102
|
return this._wda;
|
|
95
103
|
}
|
|
96
104
|
async onSettingsUpdate(key, value) {
|
|
97
105
|
if (!this._wda) {
|
|
98
106
|
return;
|
|
99
107
|
}
|
|
100
|
-
return await this.
|
|
108
|
+
return await this.wda.proxy.command('/appium/settings', 'POST', {
|
|
101
109
|
settings: { [key]: value },
|
|
102
110
|
});
|
|
103
111
|
}
|
|
@@ -113,10 +121,7 @@ export class Mac2Driver extends BaseDriver {
|
|
|
113
121
|
return true;
|
|
114
122
|
}
|
|
115
123
|
async proxyCommand(url, method, body = null) {
|
|
116
|
-
|
|
117
|
-
throw new Error('WDA server is not initialized');
|
|
118
|
-
}
|
|
119
|
-
return await this._wda.proxy.command(url, method, body);
|
|
124
|
+
return await this.wda.proxy.command(url, method, body);
|
|
120
125
|
}
|
|
121
126
|
async getStatus() {
|
|
122
127
|
if (!this._wda) {
|
|
@@ -126,10 +131,7 @@ export class Mac2Driver extends BaseDriver {
|
|
|
126
131
|
}
|
|
127
132
|
// needed to make image plugin work
|
|
128
133
|
async getWindowRect() {
|
|
129
|
-
|
|
130
|
-
throw new Error('WDA server is not initialized');
|
|
131
|
-
}
|
|
132
|
-
return await this._wda.proxy.command('/window/rect', 'GET');
|
|
134
|
+
return await this.wda.proxy.command('/window/rect', 'GET');
|
|
133
135
|
}
|
|
134
136
|
async createSession(w3cCaps1, w3cCaps2, w3cCaps3, driverData) {
|
|
135
137
|
const [sessionId, caps] = await super.createSession(w3cCaps1, w3cCaps2, w3cCaps3, driverData);
|
|
@@ -137,34 +139,49 @@ export class Mac2Driver extends BaseDriver {
|
|
|
137
139
|
this.caps = caps;
|
|
138
140
|
// oxlint-disable-next-line no-self-assign -- narrows this.opts' type for the rest of the method
|
|
139
141
|
this.opts = this.opts;
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
142
|
+
// The host supports a single session: the previous one has to quit first
|
|
143
|
+
await sessionClaimHandler.runExclusive(async () => {
|
|
144
|
+
// The session might have been deleted while it was waiting for its turn
|
|
145
|
+
if (!this._wda || !this.sessionId) {
|
|
146
|
+
throw new errors.NoSuchDriverError('The session has been deleted before it could start');
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
await sessionClaimHandler.registerActiveSession(this);
|
|
150
|
+
await sessionClaimHandler.claimHost(this);
|
|
151
|
+
this._hasClaimedHost = true;
|
|
152
|
+
const prerun = caps.prerun;
|
|
153
|
+
if (prerun) {
|
|
154
|
+
if (typeof prerun.command !== 'string' && typeof prerun.script !== 'string') {
|
|
155
|
+
throw new Error(`'prerun' capability value must either contain 'script' or 'command' entry of string type`);
|
|
156
|
+
}
|
|
157
|
+
log.info('Executing prerun AppleScript');
|
|
158
|
+
const output = await this.macosExecAppleScript(prerun.script, undefined, prerun.command);
|
|
159
|
+
if (output.trim()) {
|
|
160
|
+
log.info(`Prerun script output: ${output}`);
|
|
161
|
+
}
|
|
150
162
|
}
|
|
163
|
+
this._wdaSessionId = await this.wda.startSession(caps, {
|
|
164
|
+
reqBasePath: this.basePath,
|
|
165
|
+
});
|
|
151
166
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
throw e;
|
|
159
|
-
}
|
|
160
|
-
this.proxyReqRes = this.wda.proxy.proxyReqRes.bind(this._wda.proxy);
|
|
167
|
+
catch (e) {
|
|
168
|
+
await this.deleteSession();
|
|
169
|
+
throw e;
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
this.proxyReqRes = (...args) => this.wda.proxy.proxyReqRes.apply(this.wda.proxy, args);
|
|
161
173
|
this.isProxyActive = true;
|
|
162
174
|
return [sessionId, caps];
|
|
163
175
|
}
|
|
164
176
|
async deleteSession() {
|
|
177
|
+
sessionClaimHandler.unregisterActiveSession(this);
|
|
178
|
+
// A new session waits for the teardown to complete before it starts
|
|
179
|
+
await sessionClaimHandler.trackTeardown(async () => await this.teardownSession());
|
|
180
|
+
}
|
|
181
|
+
async teardownSession() {
|
|
165
182
|
await this._screenRecorder?.stop(true);
|
|
166
183
|
if (this._videoChunksBroadcaster.hasPublishers) {
|
|
167
|
-
if (this._wda) {
|
|
184
|
+
if (this._wda?.isSessionActive(this._wdaSessionId)) {
|
|
168
185
|
try {
|
|
169
186
|
await this.wda.proxy.command('/wda/video/stop', 'POST', {});
|
|
170
187
|
}
|
|
@@ -173,9 +190,10 @@ export class Mac2Driver extends BaseDriver {
|
|
|
173
190
|
await this._videoChunksBroadcaster.shutdown(5000);
|
|
174
191
|
}
|
|
175
192
|
if (this._wda) {
|
|
176
|
-
await this.
|
|
193
|
+
await this._wda.stopSession(this._wdaSessionId);
|
|
177
194
|
}
|
|
178
|
-
|
|
195
|
+
// Skip postrun if the host was never acquired, as the previous session might still be using it
|
|
196
|
+
const postrun = this._hasClaimedHost ? this.opts.postrun : undefined;
|
|
179
197
|
if (postrun) {
|
|
180
198
|
if (typeof postrun.command !== 'string' && typeof postrun.script !== 'string') {
|
|
181
199
|
log.error(`'postrun' capability value must either contain 'script' or 'command' entry of string type`);
|
|
@@ -198,6 +216,8 @@ export class Mac2Driver extends BaseDriver {
|
|
|
198
216
|
}
|
|
199
217
|
resetState() {
|
|
200
218
|
this._wda = null;
|
|
219
|
+
this._wdaSessionId = null;
|
|
220
|
+
this._hasClaimedHost = false;
|
|
201
221
|
this.isProxyActive = false;
|
|
202
222
|
this._videoChunksBroadcaster = new nativeScreenRecordingCommands.NativeVideoChunksBroadcaster(this.eventEmitter, this.log);
|
|
203
223
|
this._screenRecorder = null;
|
package/build/lib/driver.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"driver.js","sourceRoot":"","sources":["../../lib/driver.ts"],"names":[],"mappings":"AAaA,OAAO,EAAC,UAAU,EAAE,cAAc,EAAC,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"driver.js","sourceRoot":"","sources":["../../lib/driver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { IAppiumIpc } from '@appium/types';
|
|
2
|
+
import type { Mac2Driver } from './driver.js';
|
|
3
|
+
export type SessionIpcMessage = {
|
|
4
|
+
sessionId: string;
|
|
5
|
+
};
|
|
6
|
+
type IpcProvider = () => Promise<IAppiumIpc | undefined>;
|
|
7
|
+
/** Lets a new session make the previous one quit, over a driver-wide IPC (per-session IPCs are isolated). */
|
|
8
|
+
export declare class SessionClaimHandler {
|
|
9
|
+
private readonly getIpc;
|
|
10
|
+
private readonly releaseWaitMs;
|
|
11
|
+
static readonly CLAIMED_TOPIC = "mac2:sessionClaimed";
|
|
12
|
+
static readonly CONTENDED_TOPIC = "mac2:sessionContended";
|
|
13
|
+
static readonly RELEASED_TOPIC = "mac2:sessionReleased";
|
|
14
|
+
private static readonly STARTUP_LOCK_KEY;
|
|
15
|
+
private static readonly CONTENTION_PROBE_MS;
|
|
16
|
+
private static readonly DEFAULT_RELEASE_WAIT_MS;
|
|
17
|
+
private readonly startupLock;
|
|
18
|
+
private readonly pendingTeardowns;
|
|
19
|
+
private readonly subscriptionsBySessionId;
|
|
20
|
+
constructor(getIpc: IpcProvider, releaseWaitMs?: number);
|
|
21
|
+
/** Serializes session startups so the newest wins. Enter before registering the session. */
|
|
22
|
+
runExclusive<T>(fn: () => Promise<T>): Promise<T>;
|
|
23
|
+
/** Subscribe the session to claim messages from newer sessions. */
|
|
24
|
+
registerActiveSession(driver: Mac2Driver): Promise<void>;
|
|
25
|
+
/** Unsubscribe the session from claim messages. */
|
|
26
|
+
unregisterActiveSession(driver: Mac2Driver): void;
|
|
27
|
+
/** Tracks a session teardown, so that a new session does not start before it is complete. */
|
|
28
|
+
trackTeardown(teardown: () => Promise<void>): Promise<void>;
|
|
29
|
+
/** Make any other active session quit and wait until it has released the host. */
|
|
30
|
+
claimHost(driver: Mac2Driver): Promise<void>;
|
|
31
|
+
private waitForPendingTeardowns;
|
|
32
|
+
private requestRelease;
|
|
33
|
+
private dispatchClaimMessage;
|
|
34
|
+
private handleClaimMessage;
|
|
35
|
+
private terminateSession;
|
|
36
|
+
private publish;
|
|
37
|
+
private getPublisherId;
|
|
38
|
+
}
|
|
39
|
+
export declare const sessionClaimHandler: SessionClaimHandler;
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=session-claim-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-claim-handler.d.ts","sourceRoot":"","sources":["../../lib/session-claim-handler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAe,UAAU,EAA+B,MAAM,eAAe,CAAC;AAM1F,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,aAAa,CAAC;AAE5C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAGF,KAAK,WAAW,GAAG,MAAM,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;AAEzD,6GAA6G;AAC7G,qBAAa,mBAAmB;IAe5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAfhC,MAAM,CAAC,QAAQ,CAAC,aAAa,yBAAyB;IACtD,MAAM,CAAC,QAAQ,CAAC,eAAe,2BAA2B;IAC1D,MAAM,CAAC,QAAQ,CAAC,cAAc,0BAA0B;IAExD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAyB;IAEjE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAM;IACjD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAAS;IAExD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAmB;IAC/C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA4B;IAC7D,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAA0D;gBAGhF,MAAM,EAAE,WAAW,EACnB,aAAa,GAAE,MAAoD;IAGtF,4FAA4F;IACtF,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAIvD,mEAAmE;IAC7D,qBAAqB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB9D,mDAAmD;IACnD,uBAAuB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAUjD,6FAA6F;IACvF,aAAa,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBjE,kFAAkF;IAC5E,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;YAKpC,uBAAuB;YA2BvB,cAAc;YA8Ed,oBAAoB;YAapB,kBAAkB;YAqBlB,gBAAgB;YAmBhB,OAAO;IAgBrB,OAAO,CAAC,cAAc;CAGvB;AAgBD,eAAO,MAAM,mBAAmB,qBAAyC,CAAC"}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { setTimeout as delay } from 'node:timers/promises';
|
|
2
|
+
import { errors } from 'appium/driver.js';
|
|
3
|
+
import { node, util } from 'appium/support.js';
|
|
4
|
+
import AsyncLock from 'async-lock';
|
|
5
|
+
import { waitForCondition } from 'asyncbox';
|
|
6
|
+
/** Lets a new session make the previous one quit, over a driver-wide IPC (per-session IPCs are isolated). */
|
|
7
|
+
export class SessionClaimHandler {
|
|
8
|
+
getIpc;
|
|
9
|
+
releaseWaitMs;
|
|
10
|
+
static CLAIMED_TOPIC = 'mac2:sessionClaimed';
|
|
11
|
+
static CONTENDED_TOPIC = 'mac2:sessionContended';
|
|
12
|
+
static RELEASED_TOPIC = 'mac2:sessionReleased';
|
|
13
|
+
static STARTUP_LOCK_KEY = 'mac2:sessionStartup';
|
|
14
|
+
static CONTENTION_PROBE_MS = 10;
|
|
15
|
+
static DEFAULT_RELEASE_WAIT_MS = 15000;
|
|
16
|
+
startupLock = new AsyncLock();
|
|
17
|
+
pendingTeardowns = new Set();
|
|
18
|
+
subscriptionsBySessionId = new Map();
|
|
19
|
+
constructor(getIpc, releaseWaitMs = SessionClaimHandler.DEFAULT_RELEASE_WAIT_MS) {
|
|
20
|
+
this.getIpc = getIpc;
|
|
21
|
+
this.releaseWaitMs = releaseWaitMs;
|
|
22
|
+
}
|
|
23
|
+
/** Serializes session startups so the newest wins. Enter before registering the session. */
|
|
24
|
+
async runExclusive(fn) {
|
|
25
|
+
return await this.startupLock.acquire(SessionClaimHandler.STARTUP_LOCK_KEY, fn);
|
|
26
|
+
}
|
|
27
|
+
/** Subscribe the session to claim messages from newer sessions. */
|
|
28
|
+
async registerActiveSession(driver) {
|
|
29
|
+
const ipc = await this.getIpc();
|
|
30
|
+
const sessionId = driver.sessionId;
|
|
31
|
+
if (!ipc || !sessionId) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
this.unregisterActiveSession(driver);
|
|
35
|
+
const subscription = ipc.subscribe(SessionClaimHandler.CLAIMED_TOPIC, this.getPublisherId(driver));
|
|
36
|
+
subscription.on('message', (message) => {
|
|
37
|
+
void this.dispatchClaimMessage(driver, sessionId, message);
|
|
38
|
+
});
|
|
39
|
+
this.subscriptionsBySessionId.set(sessionId, subscription);
|
|
40
|
+
}
|
|
41
|
+
/** Unsubscribe the session from claim messages. */
|
|
42
|
+
unregisterActiveSession(driver) {
|
|
43
|
+
const sessionId = driver.sessionId;
|
|
44
|
+
if (!sessionId) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
this.subscriptionsBySessionId.get(sessionId)?.unsubscribe();
|
|
48
|
+
this.subscriptionsBySessionId.delete(sessionId);
|
|
49
|
+
}
|
|
50
|
+
/** Tracks a session teardown, so that a new session does not start before it is complete. */
|
|
51
|
+
async trackTeardown(teardown) {
|
|
52
|
+
const promise = teardown();
|
|
53
|
+
const tracked = (async () => {
|
|
54
|
+
try {
|
|
55
|
+
await promise;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// the failure is reported to the caller of trackTeardown()
|
|
59
|
+
}
|
|
60
|
+
})();
|
|
61
|
+
this.pendingTeardowns.add(tracked);
|
|
62
|
+
try {
|
|
63
|
+
await promise;
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
this.pendingTeardowns.delete(tracked);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** Make any other active session quit and wait until it has released the host. */
|
|
70
|
+
async claimHost(driver) {
|
|
71
|
+
await this.requestRelease(driver);
|
|
72
|
+
await this.waitForPendingTeardowns(driver);
|
|
73
|
+
}
|
|
74
|
+
async waitForPendingTeardowns(driver) {
|
|
75
|
+
if (this.pendingTeardowns.size === 0) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
driver.log.debug(`Waiting for ${util.pluralize('session', this.pendingTeardowns.size, true)} to finish quitting`);
|
|
79
|
+
const timer = new AbortController();
|
|
80
|
+
const timedOut = Symbol('timedOut');
|
|
81
|
+
const timeout = (async () => {
|
|
82
|
+
try {
|
|
83
|
+
return await delay(this.releaseWaitMs, timedOut, { signal: timer.signal });
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return undefined; // aborted
|
|
87
|
+
}
|
|
88
|
+
})();
|
|
89
|
+
try {
|
|
90
|
+
if ((await Promise.race([Promise.all(this.pendingTeardowns), timeout])) === timedOut) {
|
|
91
|
+
// Starting now could let the old teardown (e.g. postrun) interfere with this session
|
|
92
|
+
throw new errors.SessionNotCreatedError(`The previous session did not finish quitting within ${this.releaseWaitMs}ms`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
timer.abort();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async requestRelease(driver) {
|
|
100
|
+
const ipc = await this.getIpc();
|
|
101
|
+
if (!ipc) {
|
|
102
|
+
driver.log.debug('Driver-instance IPC is unavailable. Skipping the session claim.');
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const sessionId = driver.sessionId;
|
|
106
|
+
if (!sessionId) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const contendingSessionIds = new Set();
|
|
110
|
+
const releasedSessionIds = new Set();
|
|
111
|
+
const subscriptions = [];
|
|
112
|
+
try {
|
|
113
|
+
const contendedSubscription = ipc.subscribe(SessionClaimHandler.CONTENDED_TOPIC, this.getPublisherId(driver));
|
|
114
|
+
subscriptions.push(contendedSubscription);
|
|
115
|
+
const releasedSubscription = ipc.subscribe(SessionClaimHandler.RELEASED_TOPIC, this.getPublisherId(driver));
|
|
116
|
+
subscriptions.push(releasedSubscription);
|
|
117
|
+
contendedSubscription.on('message', (message) => {
|
|
118
|
+
if (message.data.sessionId !== sessionId) {
|
|
119
|
+
contendingSessionIds.add(message.data.sessionId);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
releasedSubscription.on('message', (message) => {
|
|
123
|
+
if (message.data.sessionId !== sessionId) {
|
|
124
|
+
releasedSessionIds.add(message.data.sessionId);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
await ipc.publish(SessionClaimHandler.CLAIMED_TOPIC, this.getPublisherId(driver), {
|
|
128
|
+
sessionId,
|
|
129
|
+
});
|
|
130
|
+
// Older sessions reply synchronously to the claim, so a short wait is enough to learn about them
|
|
131
|
+
await delay(SessionClaimHandler.CONTENTION_PROBE_MS);
|
|
132
|
+
if (contendingSessionIds.size === 0) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
await waitForCondition(() => [...contendingSessionIds].every((id) => releasedSessionIds.has(id)), {
|
|
137
|
+
waitMs: this.releaseWaitMs,
|
|
138
|
+
intervalMs: 50,
|
|
139
|
+
});
|
|
140
|
+
driver.log.debug(`Received release confirmation from ${util.pluralize('session', contendingSessionIds.size, true)}`);
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
const pendingSessionIds = [...contendingSessionIds].filter((id) => !releasedSessionIds.has(id));
|
|
144
|
+
// Starting now could let the old session interfere with this one
|
|
145
|
+
throw new errors.SessionNotCreatedError(`${util.pluralize('session', pendingSessionIds.length, true)} [${pendingSessionIds.join(', ')}] ` +
|
|
146
|
+
`did not quit within ${this.releaseWaitMs}ms`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
subscriptions.forEach((sub) => sub.unsubscribe());
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/** @internal Exposed for unit tests. */
|
|
154
|
+
resetForTesting() {
|
|
155
|
+
this.pendingTeardowns.clear();
|
|
156
|
+
for (const subscription of this.subscriptionsBySessionId.values()) {
|
|
157
|
+
subscription.unsubscribe();
|
|
158
|
+
}
|
|
159
|
+
this.subscriptionsBySessionId.clear();
|
|
160
|
+
}
|
|
161
|
+
async dispatchClaimMessage(driver, sessionId, message) {
|
|
162
|
+
try {
|
|
163
|
+
await this.handleClaimMessage(driver, sessionId, message);
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
167
|
+
driver.log.warn(`Could not handle the session claim IPC message for session '${sessionId}': ${msg}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
async handleClaimMessage(driver, sessionId, message) {
|
|
171
|
+
if (message.data.sessionId === sessionId || driver.sessionId !== sessionId) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
// Tell the claimer that it has to wait for us
|
|
175
|
+
await this.publish(driver, SessionClaimHandler.CONTENDED_TOPIC, sessionId);
|
|
176
|
+
driver.log.warn(`Session '${message.data.sessionId}' is starting, while this session ('${sessionId}') is still active. ` +
|
|
177
|
+
`Only one session at a time is supported, since XCTest is single-threaded. ` +
|
|
178
|
+
`Consider enabling the Appium server's '--session-override' flag and make sure to properly ` +
|
|
179
|
+
`quit the previous session before starting a new one. Terminating the obsolete session.`);
|
|
180
|
+
await this.terminateSession(driver, sessionId);
|
|
181
|
+
}
|
|
182
|
+
async terminateSession(driver, sessionId) {
|
|
183
|
+
const publisherId = this.getPublisherId(driver);
|
|
184
|
+
const { log } = driver;
|
|
185
|
+
try {
|
|
186
|
+
// Unlike deleteSession(), this also makes the server drop the session from its list
|
|
187
|
+
await driver.startUnexpectedShutdown(new errors.NoSuchDriverError('This session has been replaced by a newer one, because only a single session is supported'));
|
|
188
|
+
}
|
|
189
|
+
catch (err) {
|
|
190
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
191
|
+
log.warn(`Could not terminate session '${sessionId}' on IPC request: ${msg}`);
|
|
192
|
+
}
|
|
193
|
+
await this.publish(driver, SessionClaimHandler.RELEASED_TOPIC, sessionId, publisherId, log);
|
|
194
|
+
}
|
|
195
|
+
async publish(driver, topic, sessionId, publisherId = this.getPublisherId(driver), log = driver.log) {
|
|
196
|
+
try {
|
|
197
|
+
const ipc = await this.getIpc();
|
|
198
|
+
await ipc?.publish(topic, publisherId, { sessionId });
|
|
199
|
+
}
|
|
200
|
+
catch (err) {
|
|
201
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
202
|
+
log.warn(`Could not publish '${topic}' message for session '${sessionId}': ${msg}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
getPublisherId(driver) {
|
|
206
|
+
return node.getObjectId(driver);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
let sharedIpc;
|
|
210
|
+
async function loadSharedIpc() {
|
|
211
|
+
sharedIpc ??= (async () => {
|
|
212
|
+
try {
|
|
213
|
+
const { AppiumIpc } = (await import('appium/driver.js'));
|
|
214
|
+
return AppiumIpc ? new AppiumIpc() : undefined;
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
return undefined;
|
|
218
|
+
}
|
|
219
|
+
})();
|
|
220
|
+
return await sharedIpc;
|
|
221
|
+
}
|
|
222
|
+
export const sessionClaimHandler = new SessionClaimHandler(loadSharedIpc);
|
|
223
|
+
/**
|
|
224
|
+
* @internal Exposed for unit tests.
|
|
225
|
+
*/
|
|
226
|
+
export function setSharedIpcForTesting(ipc) {
|
|
227
|
+
sharedIpc = Promise.resolve(ipc);
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* @internal Exposed for unit tests.
|
|
231
|
+
*/
|
|
232
|
+
export function resetSharedIpcForTesting() {
|
|
233
|
+
sessionClaimHandler.resetForTesting();
|
|
234
|
+
sharedIpc = undefined;
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=session-claim-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-claim-handler.js","sourceRoot":"","sources":["../../lib/session-claim-handler.ts"],"names":[],"mappings":"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"}
|