@react-native-harness/platform-android 1.3.0 → 1.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/dist/__tests__/adb-wait.test.d.ts +2 -0
- package/dist/__tests__/adb-wait.test.d.ts.map +1 -0
- package/dist/__tests__/adb-wait.test.js +69 -0
- package/dist/__tests__/app-session.test.d.ts +2 -0
- package/dist/__tests__/app-session.test.d.ts.map +1 -0
- package/dist/__tests__/app-session.test.js +57 -0
- package/dist/__tests__/avd-config.test.js +58 -0
- package/dist/__tests__/crash-diagnostics.test.d.ts +2 -0
- package/dist/__tests__/crash-diagnostics.test.d.ts.map +1 -0
- package/dist/__tests__/crash-diagnostics.test.js +119 -0
- package/dist/__tests__/crash-reporter.test.d.ts +2 -0
- package/dist/__tests__/crash-reporter.test.d.ts.map +1 -0
- package/dist/__tests__/crash-reporter.test.js +150 -0
- package/dist/__tests__/emulator-startup.test.js +30 -3
- package/dist/__tests__/instance.test.js +139 -24
- package/dist/adb.d.ts +7 -1
- package/dist/adb.d.ts.map +1 -1
- package/dist/adb.js +72 -23
- package/dist/app-session.d.ts +26 -0
- package/dist/app-session.d.ts.map +1 -0
- package/dist/app-session.js +214 -0
- package/dist/avd-config.d.ts +1 -0
- package/dist/avd-config.d.ts.map +1 -1
- package/dist/avd-config.js +11 -0
- package/dist/crash-diagnostics.d.ts +40 -0
- package/dist/crash-diagnostics.d.ts.map +1 -0
- package/dist/crash-diagnostics.js +256 -0
- package/dist/crash-reporter.d.ts +12 -0
- package/dist/crash-reporter.d.ts.map +1 -0
- package/dist/crash-reporter.js +150 -0
- package/dist/emulator-startup.d.ts +23 -0
- package/dist/emulator-startup.d.ts.map +1 -1
- package/dist/emulator-startup.js +58 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/instance.d.ts +1 -1
- package/dist/instance.d.ts.map +1 -1
- package/dist/instance.js +51 -72
- package/dist/runner.d.ts +2 -2
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +1 -1
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/__tests__/adb-wait.test.ts +95 -0
- package/src/__tests__/app-session.test.ts +76 -0
- package/src/__tests__/avd-config.test.ts +70 -0
- package/src/__tests__/crash-diagnostics.test.ts +144 -0
- package/src/__tests__/crash-reporter.test.ts +167 -0
- package/src/__tests__/emulator-startup.test.ts +53 -6
- package/src/__tests__/instance.test.ts +226 -84
- package/src/adb.ts +129 -63
- package/src/app-session.ts +316 -0
- package/src/avd-config.ts +17 -0
- package/src/crash-diagnostics.ts +471 -0
- package/src/crash-reporter.ts +263 -0
- package/src/emulator-startup.ts +74 -0
- package/src/index.ts +1 -0
- package/src/instance.ts +84 -105
- package/src/runner.ts +11 -11
- package/test/setup.ts +1 -0
- package/src/app-monitor.ts +0 -577
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
DEFAULT_METRO_PORT,
|
|
4
4
|
type Config as HarnessConfig,
|
|
5
5
|
} from '@react-native-harness/config';
|
|
6
|
+
import type { Subprocess } from '@react-native-harness/tools';
|
|
6
7
|
import {
|
|
7
8
|
getAndroidEmulatorPlatformInstance,
|
|
8
9
|
getAndroidPhysicalDevicePlatformInstance,
|
|
@@ -11,6 +12,25 @@ import * as adb from '../adb.js';
|
|
|
11
12
|
import * as avdConfig from '../avd-config.js';
|
|
12
13
|
import * as sharedPrefs from '../shared-prefs.js';
|
|
13
14
|
import { HarnessAppPathError, HarnessEmulatorConfigError } from '../errors.js';
|
|
15
|
+
import * as emulatorStartup from '../emulator-startup.js';
|
|
16
|
+
const { getEmulatorCpuCores } = emulatorStartup;
|
|
17
|
+
|
|
18
|
+
const createLogcatProcess = (lines: string[] = []): Subprocess => {
|
|
19
|
+
// Mirrors nano-spawn's real Subprocess, which is both a Promise and an
|
|
20
|
+
// async iterable, since app-session.ts relies on it being thenable.
|
|
21
|
+
const process = Object.assign(Promise.resolve(undefined), {
|
|
22
|
+
nodeChildProcess: Promise.resolve({
|
|
23
|
+
kill: vi.fn(),
|
|
24
|
+
}),
|
|
25
|
+
[Symbol.asyncIterator]: async function* () {
|
|
26
|
+
for (const line of lines) {
|
|
27
|
+
yield line;
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
return process as unknown as Subprocess;
|
|
33
|
+
};
|
|
14
34
|
|
|
15
35
|
const harnessConfig = {
|
|
16
36
|
metroPort: DEFAULT_METRO_PORT,
|
|
@@ -27,17 +47,22 @@ describe('Android platform instance', () => {
|
|
|
27
47
|
beforeEach(async () => {
|
|
28
48
|
vi.restoreAllMocks();
|
|
29
49
|
vi.unstubAllEnvs();
|
|
50
|
+
vi.useRealTimers();
|
|
30
51
|
vi.spyOn(
|
|
31
52
|
await import('../environment.js'),
|
|
32
|
-
'ensureAndroidEmulatorAvailable'
|
|
53
|
+
'ensureAndroidEmulatorAvailable'
|
|
33
54
|
).mockResolvedValue('/tmp/android-sdk');
|
|
55
|
+
vi.spyOn(
|
|
56
|
+
emulatorStartup,
|
|
57
|
+
'warnIfEmulatorAccelerationUnavailable'
|
|
58
|
+
).mockResolvedValue(undefined);
|
|
34
59
|
});
|
|
35
60
|
|
|
36
61
|
it('reuses a running emulator and does not shut it down on dispose', async () => {
|
|
37
62
|
const ensureAndroidEmulatorEnvironment = vi
|
|
38
63
|
.spyOn(
|
|
39
64
|
await import('../environment.js'),
|
|
40
|
-
'ensureAndroidEmulatorEnvironment'
|
|
65
|
+
'ensureAndroidEmulatorEnvironment'
|
|
41
66
|
)
|
|
42
67
|
.mockResolvedValue('/tmp/android-sdk');
|
|
43
68
|
vi.spyOn(adb, 'getDeviceIds').mockResolvedValue(['emulator-5554']);
|
|
@@ -47,11 +72,12 @@ describe('Android platform instance', () => {
|
|
|
47
72
|
vi.spyOn(adb, 'reversePort').mockResolvedValue(undefined);
|
|
48
73
|
vi.spyOn(adb, 'setHideErrorDialogs').mockResolvedValue(undefined);
|
|
49
74
|
vi.spyOn(adb, 'getAppUid').mockResolvedValue(10234);
|
|
75
|
+
vi.spyOn(adb, 'getLogcatTimestamp').mockResolvedValue('01-01 00:00:00.000');
|
|
50
76
|
vi.spyOn(sharedPrefs, 'applyHarnessDebugHttpHost').mockResolvedValue(
|
|
51
|
-
undefined
|
|
77
|
+
undefined
|
|
52
78
|
);
|
|
53
79
|
vi.spyOn(sharedPrefs, 'clearHarnessDebugHttpHost').mockResolvedValue(
|
|
54
|
-
undefined
|
|
80
|
+
undefined
|
|
55
81
|
);
|
|
56
82
|
vi.spyOn(adb, 'stopApp').mockResolvedValue(undefined);
|
|
57
83
|
const stopEmulator = vi.spyOn(adb, 'stopEmulator').mockResolvedValue();
|
|
@@ -73,7 +99,7 @@ describe('Android platform instance', () => {
|
|
|
73
99
|
activityName: '.MainActivity',
|
|
74
100
|
},
|
|
75
101
|
harnessConfig,
|
|
76
|
-
init
|
|
102
|
+
init
|
|
77
103
|
);
|
|
78
104
|
|
|
79
105
|
await instance.dispose();
|
|
@@ -85,7 +111,7 @@ describe('Android platform instance', () => {
|
|
|
85
111
|
it('creates and boots an emulator when missing and shuts it down on dispose', async () => {
|
|
86
112
|
vi.spyOn(
|
|
87
113
|
await import('../environment.js'),
|
|
88
|
-
'ensureAndroidEmulatorEnvironment'
|
|
114
|
+
'ensureAndroidEmulatorEnvironment'
|
|
89
115
|
).mockResolvedValue('/tmp/android-sdk');
|
|
90
116
|
vi.spyOn(adb, 'getDeviceIds').mockResolvedValue([]);
|
|
91
117
|
vi.spyOn(adb, 'hasAvd').mockResolvedValue(false);
|
|
@@ -98,11 +124,12 @@ describe('Android platform instance', () => {
|
|
|
98
124
|
vi.spyOn(adb, 'reversePort').mockResolvedValue(undefined);
|
|
99
125
|
vi.spyOn(adb, 'setHideErrorDialogs').mockResolvedValue(undefined);
|
|
100
126
|
vi.spyOn(adb, 'getAppUid').mockResolvedValue(10234);
|
|
127
|
+
vi.spyOn(adb, 'getLogcatTimestamp').mockResolvedValue('01-01 00:00:00.000');
|
|
101
128
|
vi.spyOn(sharedPrefs, 'applyHarnessDebugHttpHost').mockResolvedValue(
|
|
102
|
-
undefined
|
|
129
|
+
undefined
|
|
103
130
|
);
|
|
104
131
|
vi.spyOn(sharedPrefs, 'clearHarnessDebugHttpHost').mockResolvedValue(
|
|
105
|
-
undefined
|
|
132
|
+
undefined
|
|
106
133
|
);
|
|
107
134
|
vi.spyOn(adb, 'stopApp').mockResolvedValue(undefined);
|
|
108
135
|
const stopEmulator = vi.spyOn(adb, 'stopEmulator').mockResolvedValue();
|
|
@@ -124,7 +151,7 @@ describe('Android platform instance', () => {
|
|
|
124
151
|
activityName: '.MainActivity',
|
|
125
152
|
},
|
|
126
153
|
harnessConfig,
|
|
127
|
-
init
|
|
154
|
+
init
|
|
128
155
|
);
|
|
129
156
|
|
|
130
157
|
expect(createAvd).toHaveBeenCalledWith({
|
|
@@ -145,7 +172,7 @@ describe('Android platform instance', () => {
|
|
|
145
172
|
const ensureAndroidEmulatorEnvironment = vi
|
|
146
173
|
.spyOn(
|
|
147
174
|
await import('../environment.js'),
|
|
148
|
-
'ensureAndroidEmulatorEnvironment'
|
|
175
|
+
'ensureAndroidEmulatorEnvironment'
|
|
149
176
|
)
|
|
150
177
|
.mockResolvedValue('/tmp/android-sdk');
|
|
151
178
|
vi.spyOn(adb, 'getDeviceIds').mockResolvedValue([]);
|
|
@@ -159,8 +186,9 @@ describe('Android platform instance', () => {
|
|
|
159
186
|
vi.spyOn(adb, 'reversePort').mockResolvedValue(undefined);
|
|
160
187
|
vi.spyOn(adb, 'setHideErrorDialogs').mockResolvedValue(undefined);
|
|
161
188
|
vi.spyOn(adb, 'getAppUid').mockResolvedValue(10234);
|
|
189
|
+
vi.spyOn(adb, 'getLogcatTimestamp').mockResolvedValue('01-01 00:00:00.000');
|
|
162
190
|
vi.spyOn(sharedPrefs, 'applyHarnessDebugHttpHost').mockResolvedValue(
|
|
163
|
-
undefined
|
|
191
|
+
undefined
|
|
164
192
|
);
|
|
165
193
|
|
|
166
194
|
await expect(
|
|
@@ -181,8 +209,8 @@ describe('Android platform instance', () => {
|
|
|
181
209
|
activityName: '.MainActivity',
|
|
182
210
|
},
|
|
183
211
|
harnessConfig,
|
|
184
|
-
init
|
|
185
|
-
)
|
|
212
|
+
init
|
|
213
|
+
)
|
|
186
214
|
).resolves.toBeDefined();
|
|
187
215
|
|
|
188
216
|
expect(ensureAndroidEmulatorEnvironment).toHaveBeenCalledWith(35);
|
|
@@ -194,11 +222,11 @@ describe('Android platform instance', () => {
|
|
|
194
222
|
vi.stubEnv('HARNESS_AVD_CACHING', 'true');
|
|
195
223
|
vi.spyOn(
|
|
196
224
|
await import('../environment.js'),
|
|
197
|
-
'getHostAndroidSystemImageArch'
|
|
225
|
+
'getHostAndroidSystemImageArch'
|
|
198
226
|
).mockReturnValue('arm64-v8a');
|
|
199
227
|
vi.spyOn(
|
|
200
228
|
await import('../environment.js'),
|
|
201
|
-
'ensureAndroidEmulatorEnvironment'
|
|
229
|
+
'ensureAndroidEmulatorEnvironment'
|
|
202
230
|
).mockResolvedValue('/tmp/android-sdk');
|
|
203
231
|
vi.spyOn(adb, 'getDeviceIds').mockResolvedValue([]);
|
|
204
232
|
vi.spyOn(adb, 'hasAvd').mockResolvedValue(true);
|
|
@@ -208,6 +236,7 @@ describe('Android platform instance', () => {
|
|
|
208
236
|
hwDeviceName: 'pixel_8',
|
|
209
237
|
diskDataPartitionSize: '1G',
|
|
210
238
|
vmHeapSize: '1G',
|
|
239
|
+
hwCpuNcore: String(getEmulatorCpuCores()),
|
|
211
240
|
});
|
|
212
241
|
vi.spyOn(adb, 'startEmulator').mockResolvedValue(undefined);
|
|
213
242
|
vi.spyOn(adb, 'waitForBoot').mockResolvedValue('emulator-5554');
|
|
@@ -215,8 +244,9 @@ describe('Android platform instance', () => {
|
|
|
215
244
|
vi.spyOn(adb, 'reversePort').mockResolvedValue(undefined);
|
|
216
245
|
vi.spyOn(adb, 'setHideErrorDialogs').mockResolvedValue(undefined);
|
|
217
246
|
vi.spyOn(adb, 'getAppUid').mockResolvedValue(10234);
|
|
247
|
+
vi.spyOn(adb, 'getLogcatTimestamp').mockResolvedValue('01-01 00:00:00.000');
|
|
218
248
|
vi.spyOn(sharedPrefs, 'applyHarnessDebugHttpHost').mockResolvedValue(
|
|
219
|
-
undefined
|
|
249
|
+
undefined
|
|
220
250
|
);
|
|
221
251
|
|
|
222
252
|
await expect(
|
|
@@ -238,14 +268,14 @@ describe('Android platform instance', () => {
|
|
|
238
268
|
activityName: '.MainActivity',
|
|
239
269
|
},
|
|
240
270
|
harnessConfig,
|
|
241
|
-
init
|
|
242
|
-
)
|
|
271
|
+
init
|
|
272
|
+
)
|
|
243
273
|
).resolves.toBeDefined();
|
|
244
274
|
|
|
245
275
|
expect(adb.startEmulator).toHaveBeenCalledTimes(1);
|
|
246
276
|
expect(adb.startEmulator).toHaveBeenCalledWith(
|
|
247
277
|
'Pixel_8_API_35',
|
|
248
|
-
'snapshot-reuse'
|
|
278
|
+
'snapshot-reuse'
|
|
249
279
|
);
|
|
250
280
|
});
|
|
251
281
|
|
|
@@ -253,7 +283,7 @@ describe('Android platform instance', () => {
|
|
|
253
283
|
vi.stubEnv('HARNESS_AVD_CACHING', 'true');
|
|
254
284
|
vi.spyOn(
|
|
255
285
|
await import('../environment.js'),
|
|
256
|
-
'ensureAndroidEmulatorEnvironment'
|
|
286
|
+
'ensureAndroidEmulatorEnvironment'
|
|
257
287
|
).mockResolvedValue('/tmp/android-sdk');
|
|
258
288
|
vi.spyOn(adb, 'getDeviceIds').mockResolvedValue([]);
|
|
259
289
|
vi.spyOn(adb, 'hasAvd').mockResolvedValue(true);
|
|
@@ -276,8 +306,9 @@ describe('Android platform instance', () => {
|
|
|
276
306
|
vi.spyOn(adb, 'reversePort').mockResolvedValue(undefined);
|
|
277
307
|
vi.spyOn(adb, 'setHideErrorDialogs').mockResolvedValue(undefined);
|
|
278
308
|
vi.spyOn(adb, 'getAppUid').mockResolvedValue(10234);
|
|
309
|
+
vi.spyOn(adb, 'getLogcatTimestamp').mockResolvedValue('01-01 00:00:00.000');
|
|
279
310
|
vi.spyOn(sharedPrefs, 'applyHarnessDebugHttpHost').mockResolvedValue(
|
|
280
|
-
undefined
|
|
311
|
+
undefined
|
|
281
312
|
);
|
|
282
313
|
|
|
283
314
|
await expect(
|
|
@@ -299,8 +330,8 @@ describe('Android platform instance', () => {
|
|
|
299
330
|
activityName: '.MainActivity',
|
|
300
331
|
},
|
|
301
332
|
harnessConfig,
|
|
302
|
-
init
|
|
303
|
-
)
|
|
333
|
+
init
|
|
334
|
+
)
|
|
304
335
|
).resolves.toBeDefined();
|
|
305
336
|
|
|
306
337
|
expect(deleteAvd).toHaveBeenCalledWith('Pixel_8_API_35');
|
|
@@ -308,17 +339,17 @@ describe('Android platform instance', () => {
|
|
|
308
339
|
expect(stopEmulator).toHaveBeenCalledWith('emulator-5554');
|
|
309
340
|
expect(waitForEmulatorDisconnect).toHaveBeenCalledWith(
|
|
310
341
|
'emulator-5554',
|
|
311
|
-
init.signal
|
|
342
|
+
init.signal
|
|
312
343
|
);
|
|
313
344
|
expect(adb.startEmulator).toHaveBeenNthCalledWith(
|
|
314
345
|
1,
|
|
315
346
|
'Pixel_8_API_35',
|
|
316
|
-
'clean-snapshot-generation'
|
|
347
|
+
'clean-snapshot-generation'
|
|
317
348
|
);
|
|
318
349
|
expect(adb.startEmulator).toHaveBeenNthCalledWith(
|
|
319
350
|
2,
|
|
320
351
|
'Pixel_8_API_35',
|
|
321
|
-
'snapshot-reuse'
|
|
352
|
+
'snapshot-reuse'
|
|
322
353
|
);
|
|
323
354
|
});
|
|
324
355
|
|
|
@@ -326,7 +357,7 @@ describe('Android platform instance', () => {
|
|
|
326
357
|
vi.stubEnv('HARNESS_AVD_CACHING', 'true');
|
|
327
358
|
vi.spyOn(
|
|
328
359
|
await import('../environment.js'),
|
|
329
|
-
'ensureAndroidEmulatorEnvironment'
|
|
360
|
+
'ensureAndroidEmulatorEnvironment'
|
|
330
361
|
).mockResolvedValue('/tmp/android-sdk');
|
|
331
362
|
vi.spyOn(adb, 'getDeviceIds').mockResolvedValue([]);
|
|
332
363
|
vi.spyOn(adb, 'hasAvd').mockResolvedValue(false);
|
|
@@ -343,8 +374,9 @@ describe('Android platform instance', () => {
|
|
|
343
374
|
vi.spyOn(adb, 'reversePort').mockResolvedValue(undefined);
|
|
344
375
|
vi.spyOn(adb, 'setHideErrorDialogs').mockResolvedValue(undefined);
|
|
345
376
|
vi.spyOn(adb, 'getAppUid').mockResolvedValue(10234);
|
|
377
|
+
vi.spyOn(adb, 'getLogcatTimestamp').mockResolvedValue('01-01 00:00:00.000');
|
|
346
378
|
vi.spyOn(sharedPrefs, 'applyHarnessDebugHttpHost').mockResolvedValue(
|
|
347
|
-
undefined
|
|
379
|
+
undefined
|
|
348
380
|
);
|
|
349
381
|
|
|
350
382
|
await expect(
|
|
@@ -366,24 +398,24 @@ describe('Android platform instance', () => {
|
|
|
366
398
|
activityName: '.MainActivity',
|
|
367
399
|
},
|
|
368
400
|
harnessConfig,
|
|
369
|
-
init
|
|
370
|
-
)
|
|
401
|
+
init
|
|
402
|
+
)
|
|
371
403
|
).resolves.toBeDefined();
|
|
372
404
|
|
|
373
405
|
expect(startEmulator).toHaveBeenNthCalledWith(
|
|
374
406
|
1,
|
|
375
407
|
'Pixel_8_API_35',
|
|
376
|
-
'clean-snapshot-generation'
|
|
408
|
+
'clean-snapshot-generation'
|
|
377
409
|
);
|
|
378
410
|
expect(stopEmulator).toHaveBeenCalledWith('emulator-5554');
|
|
379
411
|
expect(waitForEmulatorDisconnect).toHaveBeenCalledWith(
|
|
380
412
|
'emulator-5554',
|
|
381
|
-
init.signal
|
|
413
|
+
init.signal
|
|
382
414
|
);
|
|
383
415
|
expect(startEmulator).toHaveBeenNthCalledWith(
|
|
384
416
|
2,
|
|
385
417
|
'Pixel_8_API_35',
|
|
386
|
-
'snapshot-reuse'
|
|
418
|
+
'snapshot-reuse'
|
|
387
419
|
);
|
|
388
420
|
});
|
|
389
421
|
|
|
@@ -411,8 +443,8 @@ describe('Android platform instance', () => {
|
|
|
411
443
|
activityName: '.MainActivity',
|
|
412
444
|
},
|
|
413
445
|
harnessConfig,
|
|
414
|
-
init
|
|
415
|
-
)
|
|
446
|
+
init
|
|
447
|
+
)
|
|
416
448
|
).rejects.toBeInstanceOf(HarnessAppPathError);
|
|
417
449
|
});
|
|
418
450
|
|
|
@@ -441,8 +473,8 @@ describe('Android platform instance', () => {
|
|
|
441
473
|
activityName: '.MainActivity',
|
|
442
474
|
},
|
|
443
475
|
harnessConfig,
|
|
444
|
-
init
|
|
445
|
-
)
|
|
476
|
+
init
|
|
477
|
+
)
|
|
446
478
|
).rejects.toBeInstanceOf(HarnessAppPathError);
|
|
447
479
|
});
|
|
448
480
|
|
|
@@ -461,15 +493,16 @@ describe('Android platform instance', () => {
|
|
|
461
493
|
activityName: '.MainActivity',
|
|
462
494
|
},
|
|
463
495
|
harnessConfig,
|
|
464
|
-
init
|
|
465
|
-
)
|
|
496
|
+
init
|
|
497
|
+
)
|
|
466
498
|
).rejects.toBeInstanceOf(HarnessEmulatorConfigError);
|
|
467
499
|
});
|
|
468
500
|
|
|
469
|
-
it('
|
|
501
|
+
it('creates a real emulator app session when native crash detection is disabled', async () => {
|
|
502
|
+
vi.useFakeTimers();
|
|
470
503
|
vi.spyOn(
|
|
471
504
|
await import('../environment.js'),
|
|
472
|
-
'ensureAndroidEmulatorEnvironment'
|
|
505
|
+
'ensureAndroidEmulatorEnvironment'
|
|
473
506
|
).mockResolvedValue('/tmp/android-sdk');
|
|
474
507
|
vi.spyOn(adb, 'getDeviceIds').mockResolvedValue(['emulator-5554']);
|
|
475
508
|
vi.spyOn(adb, 'getEmulatorName').mockResolvedValue('Pixel_8_API_35');
|
|
@@ -478,9 +511,16 @@ describe('Android platform instance', () => {
|
|
|
478
511
|
vi.spyOn(adb, 'reversePort').mockResolvedValue(undefined);
|
|
479
512
|
vi.spyOn(adb, 'setHideErrorDialogs').mockResolvedValue(undefined);
|
|
480
513
|
vi.spyOn(adb, 'getAppUid').mockResolvedValue(10234);
|
|
514
|
+
vi.spyOn(adb, 'getLogcatTimestamp').mockResolvedValue('01-01 00:00:00.000');
|
|
481
515
|
vi.spyOn(sharedPrefs, 'applyHarnessDebugHttpHost').mockResolvedValue(
|
|
482
|
-
undefined
|
|
516
|
+
undefined
|
|
483
517
|
);
|
|
518
|
+
const stopApp = vi.spyOn(adb, 'stopApp').mockResolvedValue(undefined);
|
|
519
|
+
const startApp = vi.spyOn(adb, 'startApp').mockResolvedValue(undefined);
|
|
520
|
+
const getAppPid = vi.spyOn(adb, 'getAppPid').mockResolvedValue(4321);
|
|
521
|
+
const startLogcat = vi
|
|
522
|
+
.spyOn(adb, 'startLogcat')
|
|
523
|
+
.mockReturnValue(createLogcatProcess());
|
|
484
524
|
|
|
485
525
|
const instance = await getAndroidEmulatorPlatformInstance(
|
|
486
526
|
{
|
|
@@ -499,20 +539,113 @@ describe('Android platform instance', () => {
|
|
|
499
539
|
activityName: '.MainActivity',
|
|
500
540
|
},
|
|
501
541
|
harnessConfigWithoutNativeCrashDetection,
|
|
502
|
-
init
|
|
542
|
+
init
|
|
503
543
|
);
|
|
504
544
|
|
|
505
545
|
const listener = vi.fn();
|
|
506
|
-
const
|
|
546
|
+
const appSession = await instance.createAppSession();
|
|
547
|
+
appSession.addListener(listener);
|
|
548
|
+
await vi.advanceTimersByTimeAsync(0);
|
|
507
549
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
550
|
+
expect(startLogcat).toHaveBeenCalledWith(
|
|
551
|
+
'emulator-5554',
|
|
552
|
+
[
|
|
553
|
+
'logcat',
|
|
554
|
+
'-v',
|
|
555
|
+
'threadtime',
|
|
556
|
+
'-b',
|
|
557
|
+
'crash',
|
|
558
|
+
'--uid=10234',
|
|
559
|
+
'-T',
|
|
560
|
+
'01-01 00:00:00.000',
|
|
561
|
+
],
|
|
562
|
+
{ signal: expect.any(AbortSignal) }
|
|
563
|
+
);
|
|
564
|
+
expect(startLogcat.mock.invocationCallOrder[0]).toBeLessThan(
|
|
565
|
+
startApp.mock.invocationCallOrder[0]
|
|
566
|
+
);
|
|
567
|
+
await expect(appSession.getState()).resolves.toEqual({
|
|
568
|
+
status: 'running',
|
|
569
|
+
pid: 4321,
|
|
570
|
+
});
|
|
571
|
+
expect(getAppPid).toHaveBeenCalled();
|
|
572
|
+
expect(listener).not.toHaveBeenCalled();
|
|
573
|
+
expect(appSession.removeListener(listener)).toBeUndefined();
|
|
574
|
+
await expect(appSession.dispose()).resolves.toBeUndefined();
|
|
575
|
+
expect(stopApp).toHaveBeenCalled();
|
|
513
576
|
});
|
|
514
577
|
|
|
515
|
-
it('
|
|
578
|
+
it('reports an early Android crash from logcat before a PID poll succeeds', async () => {
|
|
579
|
+
vi.useFakeTimers();
|
|
580
|
+
vi.spyOn(
|
|
581
|
+
await import('../environment.js'),
|
|
582
|
+
'ensureAndroidEmulatorEnvironment'
|
|
583
|
+
).mockResolvedValue('/tmp/android-sdk');
|
|
584
|
+
vi.spyOn(adb, 'getDeviceIds').mockResolvedValue(['emulator-5554']);
|
|
585
|
+
vi.spyOn(adb, 'getEmulatorName').mockResolvedValue('Pixel_8_API_35');
|
|
586
|
+
vi.spyOn(adb, 'waitForBoot').mockResolvedValue('emulator-5554');
|
|
587
|
+
vi.spyOn(adb, 'isAppInstalled').mockResolvedValue(true);
|
|
588
|
+
vi.spyOn(adb, 'reversePort').mockResolvedValue(undefined);
|
|
589
|
+
vi.spyOn(adb, 'setHideErrorDialogs').mockResolvedValue(undefined);
|
|
590
|
+
vi.spyOn(adb, 'getAppUid').mockResolvedValue(10234);
|
|
591
|
+
vi.spyOn(adb, 'getLogcatTimestamp').mockResolvedValue('01-01 00:00:00.000');
|
|
592
|
+
vi.spyOn(sharedPrefs, 'applyHarnessDebugHttpHost').mockResolvedValue(
|
|
593
|
+
undefined
|
|
594
|
+
);
|
|
595
|
+
vi.spyOn(adb, 'stopApp').mockResolvedValue(undefined);
|
|
596
|
+
vi.spyOn(adb, 'startApp').mockResolvedValue(undefined);
|
|
597
|
+
vi.spyOn(adb, 'getAppPid').mockResolvedValue(null);
|
|
598
|
+
vi.spyOn(adb, 'startLogcat').mockReturnValue(
|
|
599
|
+
createLogcatProcess([
|
|
600
|
+
'--------- beginning of crash',
|
|
601
|
+
'Process: com.harnessplayground, PID: 7777',
|
|
602
|
+
'FATAL EXCEPTION: main',
|
|
603
|
+
])
|
|
604
|
+
);
|
|
605
|
+
|
|
606
|
+
const instance = await getAndroidEmulatorPlatformInstance(
|
|
607
|
+
{
|
|
608
|
+
name: 'android',
|
|
609
|
+
device: {
|
|
610
|
+
type: 'emulator',
|
|
611
|
+
name: 'Pixel_8_API_35',
|
|
612
|
+
avd: {
|
|
613
|
+
apiLevel: 35,
|
|
614
|
+
profile: 'pixel_8',
|
|
615
|
+
diskSize: '1G',
|
|
616
|
+
heapSize: '1G',
|
|
617
|
+
},
|
|
618
|
+
},
|
|
619
|
+
bundleId: 'com.harnessplayground',
|
|
620
|
+
activityName: '.MainActivity',
|
|
621
|
+
},
|
|
622
|
+
harnessConfig,
|
|
623
|
+
init
|
|
624
|
+
);
|
|
625
|
+
|
|
626
|
+
const listener = vi.fn();
|
|
627
|
+
const appSession = await instance.createAppSession();
|
|
628
|
+
appSession.addListener(listener);
|
|
629
|
+
|
|
630
|
+
await vi.advanceTimersByTimeAsync(0);
|
|
631
|
+
|
|
632
|
+
expect(appSession.getLogs().map((entry) => entry.line)).toEqual([
|
|
633
|
+
'--------- beginning of crash',
|
|
634
|
+
'Process: com.harnessplayground, PID: 7777',
|
|
635
|
+
'FATAL EXCEPTION: main',
|
|
636
|
+
]);
|
|
637
|
+
await expect(appSession.getState()).resolves.toMatchObject({
|
|
638
|
+
status: 'exited',
|
|
639
|
+
pid: 7777,
|
|
640
|
+
reason: 'observed-exit',
|
|
641
|
+
});
|
|
642
|
+
expect(listener).toHaveBeenCalledWith({ type: 'app_exited' });
|
|
643
|
+
|
|
644
|
+
await appSession.dispose();
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
it('creates a real physical-device app session when native crash detection is disabled', async () => {
|
|
648
|
+
vi.useFakeTimers();
|
|
516
649
|
vi.spyOn(adb, 'getDeviceIds').mockResolvedValue(['012345']);
|
|
517
650
|
vi.spyOn(adb, 'getDeviceInfo').mockResolvedValue({
|
|
518
651
|
manufacturer: 'motorola',
|
|
@@ -522,25 +655,16 @@ describe('Android platform instance', () => {
|
|
|
522
655
|
vi.spyOn(adb, 'reversePort').mockResolvedValue(undefined);
|
|
523
656
|
vi.spyOn(adb, 'setHideErrorDialogs').mockResolvedValue(undefined);
|
|
524
657
|
vi.spyOn(adb, 'getAppUid').mockResolvedValue(10234);
|
|
658
|
+
vi.spyOn(adb, 'getLogcatTimestamp').mockResolvedValue('01-01 00:00:00.000');
|
|
525
659
|
vi.spyOn(sharedPrefs, 'applyHarnessDebugHttpHost').mockResolvedValue(
|
|
526
|
-
undefined
|
|
660
|
+
undefined
|
|
527
661
|
);
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
type: 'physical',
|
|
535
|
-
manufacturer: 'motorola',
|
|
536
|
-
model: 'moto g72',
|
|
537
|
-
},
|
|
538
|
-
bundleId: 'com.harnessplayground',
|
|
539
|
-
activityName: '.MainActivity',
|
|
540
|
-
},
|
|
541
|
-
harnessConfigWithoutNativeCrashDetection,
|
|
542
|
-
),
|
|
543
|
-
).resolves.toBeDefined();
|
|
662
|
+
vi.spyOn(adb, 'stopApp').mockResolvedValue(undefined);
|
|
663
|
+
vi.spyOn(adb, 'startApp').mockResolvedValue(undefined);
|
|
664
|
+
vi.spyOn(adb, 'getAppPid').mockResolvedValue(8765);
|
|
665
|
+
const startLogcat = vi
|
|
666
|
+
.spyOn(adb, 'startLogcat')
|
|
667
|
+
.mockReturnValue(createLogcatProcess());
|
|
544
668
|
|
|
545
669
|
const instance = await getAndroidPhysicalDevicePlatformInstance(
|
|
546
670
|
{
|
|
@@ -553,23 +677,41 @@ describe('Android platform instance', () => {
|
|
|
553
677
|
bundleId: 'com.harnessplayground',
|
|
554
678
|
activityName: '.MainActivity',
|
|
555
679
|
},
|
|
556
|
-
harnessConfigWithoutNativeCrashDetection
|
|
680
|
+
harnessConfigWithoutNativeCrashDetection
|
|
557
681
|
);
|
|
558
682
|
|
|
559
683
|
const listener = vi.fn();
|
|
560
|
-
const
|
|
684
|
+
const appSession = await instance.createAppSession();
|
|
685
|
+
appSession.addListener(listener);
|
|
686
|
+
await vi.advanceTimersByTimeAsync(0);
|
|
561
687
|
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
688
|
+
expect(startLogcat).toHaveBeenCalledWith(
|
|
689
|
+
'012345',
|
|
690
|
+
[
|
|
691
|
+
'logcat',
|
|
692
|
+
'-v',
|
|
693
|
+
'threadtime',
|
|
694
|
+
'-b',
|
|
695
|
+
'crash',
|
|
696
|
+
'--uid=10234',
|
|
697
|
+
'-T',
|
|
698
|
+
'01-01 00:00:00.000',
|
|
699
|
+
],
|
|
700
|
+
{ signal: expect.any(AbortSignal) }
|
|
701
|
+
);
|
|
702
|
+
await expect(appSession.getState()).resolves.toEqual({
|
|
703
|
+
status: 'running',
|
|
704
|
+
pid: 8765,
|
|
705
|
+
});
|
|
706
|
+
expect(listener).not.toHaveBeenCalled();
|
|
707
|
+
expect(appSession.removeListener(listener)).toBeUndefined();
|
|
708
|
+
await expect(appSession.dispose()).resolves.toBeUndefined();
|
|
567
709
|
});
|
|
568
710
|
|
|
569
711
|
it('grants permissions when permissions are enabled for emulator', async () => {
|
|
570
712
|
vi.spyOn(
|
|
571
713
|
await import('../environment.js'),
|
|
572
|
-
'ensureAndroidEmulatorEnvironment'
|
|
714
|
+
'ensureAndroidEmulatorEnvironment'
|
|
573
715
|
).mockResolvedValue('/tmp/android-sdk');
|
|
574
716
|
vi.spyOn(adb, 'getDeviceIds').mockResolvedValue(['emulator-5554']);
|
|
575
717
|
vi.spyOn(adb, 'getEmulatorName').mockResolvedValue('Pixel_8_API_35');
|
|
@@ -579,7 +721,7 @@ describe('Android platform instance', () => {
|
|
|
579
721
|
vi.spyOn(adb, 'setHideErrorDialogs').mockResolvedValue(undefined);
|
|
580
722
|
vi.spyOn(adb, 'getAppUid').mockResolvedValue(10234);
|
|
581
723
|
vi.spyOn(sharedPrefs, 'applyHarnessDebugHttpHost').mockResolvedValue(
|
|
582
|
-
undefined
|
|
724
|
+
undefined
|
|
583
725
|
);
|
|
584
726
|
const grantPermissions = vi
|
|
585
727
|
.spyOn(adb, 'grantPermissions')
|
|
@@ -607,19 +749,19 @@ describe('Android platform instance', () => {
|
|
|
607
749
|
activityName: '.MainActivity',
|
|
608
750
|
},
|
|
609
751
|
harnessConfigWithPermissions,
|
|
610
|
-
init
|
|
752
|
+
init
|
|
611
753
|
);
|
|
612
754
|
|
|
613
755
|
expect(grantPermissions).toHaveBeenCalledWith(
|
|
614
756
|
'emulator-5554',
|
|
615
|
-
'com.harnessplayground'
|
|
757
|
+
'com.harnessplayground'
|
|
616
758
|
);
|
|
617
759
|
});
|
|
618
760
|
|
|
619
761
|
it('does not grant permissions when permissions are disabled for emulator', async () => {
|
|
620
762
|
vi.spyOn(
|
|
621
763
|
await import('../environment.js'),
|
|
622
|
-
'ensureAndroidEmulatorEnvironment'
|
|
764
|
+
'ensureAndroidEmulatorEnvironment'
|
|
623
765
|
).mockResolvedValue('/tmp/android-sdk');
|
|
624
766
|
vi.spyOn(adb, 'getDeviceIds').mockResolvedValue(['emulator-5554']);
|
|
625
767
|
vi.spyOn(adb, 'getEmulatorName').mockResolvedValue('Pixel_8_API_35');
|
|
@@ -629,7 +771,7 @@ describe('Android platform instance', () => {
|
|
|
629
771
|
vi.spyOn(adb, 'setHideErrorDialogs').mockResolvedValue(undefined);
|
|
630
772
|
vi.spyOn(adb, 'getAppUid').mockResolvedValue(10234);
|
|
631
773
|
vi.spyOn(sharedPrefs, 'applyHarnessDebugHttpHost').mockResolvedValue(
|
|
632
|
-
undefined
|
|
774
|
+
undefined
|
|
633
775
|
);
|
|
634
776
|
const grantPermissions = vi
|
|
635
777
|
.spyOn(adb, 'grantPermissions')
|
|
@@ -652,7 +794,7 @@ describe('Android platform instance', () => {
|
|
|
652
794
|
activityName: '.MainActivity',
|
|
653
795
|
},
|
|
654
796
|
harnessConfig,
|
|
655
|
-
init
|
|
797
|
+
init
|
|
656
798
|
);
|
|
657
799
|
|
|
658
800
|
expect(grantPermissions).not.toHaveBeenCalled();
|
|
@@ -669,7 +811,7 @@ describe('Android platform instance', () => {
|
|
|
669
811
|
vi.spyOn(adb, 'setHideErrorDialogs').mockResolvedValue(undefined);
|
|
670
812
|
vi.spyOn(adb, 'getAppUid').mockResolvedValue(10234);
|
|
671
813
|
vi.spyOn(sharedPrefs, 'applyHarnessDebugHttpHost').mockResolvedValue(
|
|
672
|
-
undefined
|
|
814
|
+
undefined
|
|
673
815
|
);
|
|
674
816
|
const grantPermissions = vi
|
|
675
817
|
.spyOn(adb, 'grantPermissions')
|
|
@@ -691,12 +833,12 @@ describe('Android platform instance', () => {
|
|
|
691
833
|
bundleId: 'com.harnessplayground',
|
|
692
834
|
activityName: '.MainActivity',
|
|
693
835
|
},
|
|
694
|
-
harnessConfigWithPermissions
|
|
836
|
+
harnessConfigWithPermissions
|
|
695
837
|
);
|
|
696
838
|
|
|
697
839
|
expect(grantPermissions).toHaveBeenCalledWith(
|
|
698
840
|
'012345',
|
|
699
|
-
'com.harnessplayground'
|
|
841
|
+
'com.harnessplayground'
|
|
700
842
|
);
|
|
701
843
|
});
|
|
702
844
|
});
|