@react-native-harness/platform-android 1.4.0 → 1.4.1
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/package.json +4 -4
- package/dist/__tests__/adb-id.test.d.ts +0 -2
- package/dist/__tests__/adb-id.test.d.ts.map +0 -1
- package/dist/__tests__/adb-id.test.js +0 -41
- package/dist/__tests__/adb-wait.test.d.ts +0 -2
- package/dist/__tests__/adb-wait.test.d.ts.map +0 -1
- package/dist/__tests__/adb-wait.test.js +0 -69
- package/dist/__tests__/adb.test.d.ts +0 -2
- package/dist/__tests__/adb.test.d.ts.map +0 -1
- package/dist/__tests__/adb.test.js +0 -552
- package/dist/__tests__/app-monitor.test.d.ts +0 -2
- package/dist/__tests__/app-monitor.test.d.ts.map +0 -1
- package/dist/__tests__/app-monitor.test.js +0 -257
- package/dist/__tests__/app-session.test.d.ts +0 -2
- package/dist/__tests__/app-session.test.d.ts.map +0 -1
- package/dist/__tests__/app-session.test.js +0 -57
- package/dist/__tests__/avd-config.test.d.ts +0 -2
- package/dist/__tests__/avd-config.test.d.ts.map +0 -1
- package/dist/__tests__/avd-config.test.js +0 -232
- package/dist/__tests__/ci-action.test.d.ts +0 -2
- package/dist/__tests__/ci-action.test.d.ts.map +0 -1
- package/dist/__tests__/ci-action.test.js +0 -46
- package/dist/__tests__/crash-diagnostics.test.d.ts +0 -2
- package/dist/__tests__/crash-diagnostics.test.d.ts.map +0 -1
- package/dist/__tests__/crash-diagnostics.test.js +0 -119
- package/dist/__tests__/crash-parser.test.d.ts +0 -2
- package/dist/__tests__/crash-parser.test.d.ts.map +0 -1
- package/dist/__tests__/crash-parser.test.js +0 -45
- package/dist/__tests__/crash-reporter.test.d.ts +0 -2
- package/dist/__tests__/crash-reporter.test.d.ts.map +0 -1
- package/dist/__tests__/crash-reporter.test.js +0 -150
- package/dist/__tests__/emulator-startup.test.d.ts +0 -2
- package/dist/__tests__/emulator-startup.test.d.ts.map +0 -1
- package/dist/__tests__/emulator-startup.test.js +0 -47
- package/dist/__tests__/environment.test.d.ts +0 -2
- package/dist/__tests__/environment.test.d.ts.map +0 -1
- package/dist/__tests__/environment.test.js +0 -117
- package/dist/__tests__/instance.test.d.ts +0 -2
- package/dist/__tests__/instance.test.d.ts.map +0 -1
- package/dist/__tests__/instance.test.js +0 -599
- package/dist/__tests__/shared-prefs.test.d.ts +0 -2
- package/dist/__tests__/shared-prefs.test.d.ts.map +0 -1
- package/dist/__tests__/shared-prefs.test.js +0 -87
- package/dist/__tests__/targets.test.d.ts +0 -2
- package/dist/__tests__/targets.test.d.ts.map +0 -1
- package/dist/__tests__/targets.test.js +0 -49
- package/dist/tsconfig.lib.tsbuildinfo +0 -1
- package/src/__tests__/adb-id.test.ts +0 -51
- package/src/__tests__/adb-wait.test.ts +0 -95
- package/src/__tests__/app-session.test.ts +0 -76
- package/src/__tests__/avd-config.test.ts +0 -276
- package/src/__tests__/ci-action.test.ts +0 -81
- package/src/__tests__/crash-diagnostics.test.ts +0 -144
- package/src/__tests__/crash-parser.test.ts +0 -52
- package/src/__tests__/crash-reporter.test.ts +0 -167
- package/src/__tests__/emulator-startup.test.ts +0 -82
- package/src/__tests__/instance.test.ts +0 -844
- package/src/__tests__/shared-prefs.test.ts +0 -144
- package/src/__tests__/targets.test.ts +0 -53
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import {
|
|
3
|
-
getNormalizedAvdCacheConfig,
|
|
4
|
-
isAvdCompatible,
|
|
5
|
-
parseAvdConfig,
|
|
6
|
-
resolveAvdCachingEnabled,
|
|
7
|
-
} from '../avd-config.js';
|
|
8
|
-
import { AndroidPlatformConfigSchema } from '../config.js';
|
|
9
|
-
import { getEmulatorCpuCores } from '../emulator-startup.js';
|
|
10
|
-
|
|
11
|
-
const emulatorCpuCores = getEmulatorCpuCores();
|
|
12
|
-
|
|
13
|
-
describe('AVD config helpers', () => {
|
|
14
|
-
it('parses snapshot config from Android schema', () => {
|
|
15
|
-
const config = AndroidPlatformConfigSchema.parse({
|
|
16
|
-
name: 'android',
|
|
17
|
-
bundleId: 'com.example.app',
|
|
18
|
-
device: {
|
|
19
|
-
type: 'emulator',
|
|
20
|
-
name: 'Pixel_8_API_35',
|
|
21
|
-
avd: {
|
|
22
|
-
apiLevel: 35,
|
|
23
|
-
profile: 'pixel_8',
|
|
24
|
-
diskSize: '1G',
|
|
25
|
-
heapSize: '512M',
|
|
26
|
-
snapshot: {
|
|
27
|
-
enabled: true,
|
|
28
|
-
},
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
expect(config.device.type).toBe('emulator');
|
|
34
|
-
if (config.device.type === 'emulator') {
|
|
35
|
-
expect(config.device.avd?.snapshot?.enabled).toBe(true);
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('lets HARNESS_AVD_CACHING override config before interactive gating', () => {
|
|
40
|
-
expect(
|
|
41
|
-
resolveAvdCachingEnabled({
|
|
42
|
-
avd: {
|
|
43
|
-
apiLevel: 35,
|
|
44
|
-
profile: 'pixel_8',
|
|
45
|
-
diskSize: '1G',
|
|
46
|
-
heapSize: '1G',
|
|
47
|
-
snapshot: { enabled: false },
|
|
48
|
-
},
|
|
49
|
-
isInteractive: false,
|
|
50
|
-
env: {
|
|
51
|
-
HARNESS_AVD_CACHING: 'true',
|
|
52
|
-
},
|
|
53
|
-
})
|
|
54
|
-
).toBe(true);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('disables caching for interactive sessions even when requested', () => {
|
|
58
|
-
expect(
|
|
59
|
-
resolveAvdCachingEnabled({
|
|
60
|
-
avd: {
|
|
61
|
-
apiLevel: 35,
|
|
62
|
-
profile: 'pixel_8',
|
|
63
|
-
diskSize: '1G',
|
|
64
|
-
heapSize: '1G',
|
|
65
|
-
snapshot: { enabled: true },
|
|
66
|
-
},
|
|
67
|
-
isInteractive: true,
|
|
68
|
-
})
|
|
69
|
-
).toBe(false);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('parses config.ini and matches compatible AVD metadata', () => {
|
|
73
|
-
const avdConfig = parseAvdConfig(`
|
|
74
|
-
image.sysdir.1=system-images/android-35/default/x86_64/
|
|
75
|
-
abi.type=x86_64
|
|
76
|
-
hw.device.name=pixel_8
|
|
77
|
-
disk.dataPartition.size=1G
|
|
78
|
-
vm.heapSize=512M
|
|
79
|
-
hw.cpu.ncore=${emulatorCpuCores}
|
|
80
|
-
`);
|
|
81
|
-
|
|
82
|
-
expect(avdConfig.hwCpuNcore).toBe(String(emulatorCpuCores));
|
|
83
|
-
|
|
84
|
-
expect(
|
|
85
|
-
isAvdCompatible({
|
|
86
|
-
emulator: {
|
|
87
|
-
type: 'emulator',
|
|
88
|
-
name: 'Pixel_8_API_35',
|
|
89
|
-
avd: {
|
|
90
|
-
apiLevel: 35,
|
|
91
|
-
profile: 'pixel_8',
|
|
92
|
-
diskSize: '1G',
|
|
93
|
-
heapSize: '512M',
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
avdConfig,
|
|
97
|
-
hostArch: 'x86_64',
|
|
98
|
-
})
|
|
99
|
-
).toEqual({ compatible: true });
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('rejects AVDs missing hw.cpu.ncore', () => {
|
|
103
|
-
const avdConfig = parseAvdConfig(`
|
|
104
|
-
image.sysdir.1=system-images/android-35/default/x86_64/
|
|
105
|
-
abi.type=x86_64
|
|
106
|
-
hw.device.name=pixel_8
|
|
107
|
-
disk.dataPartition.size=1G
|
|
108
|
-
vm.heapSize=512M
|
|
109
|
-
`);
|
|
110
|
-
|
|
111
|
-
expect(
|
|
112
|
-
isAvdCompatible({
|
|
113
|
-
emulator: {
|
|
114
|
-
type: 'emulator',
|
|
115
|
-
name: 'Pixel_8_API_35',
|
|
116
|
-
avd: {
|
|
117
|
-
apiLevel: 35,
|
|
118
|
-
profile: 'pixel_8',
|
|
119
|
-
diskSize: '1G',
|
|
120
|
-
heapSize: '512M',
|
|
121
|
-
},
|
|
122
|
-
},
|
|
123
|
-
avdConfig,
|
|
124
|
-
hostArch: 'x86_64',
|
|
125
|
-
})
|
|
126
|
-
).toMatchObject({
|
|
127
|
-
compatible: false,
|
|
128
|
-
reason: `CPU core count mismatch: expected ${emulatorCpuCores}, got missing.`,
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
it('rejects AVDs with a different hw.cpu.ncore', () => {
|
|
133
|
-
const avdConfig = parseAvdConfig(`
|
|
134
|
-
image.sysdir.1=system-images/android-35/default/x86_64/
|
|
135
|
-
abi.type=x86_64
|
|
136
|
-
hw.device.name=pixel_8
|
|
137
|
-
disk.dataPartition.size=1G
|
|
138
|
-
vm.heapSize=512M
|
|
139
|
-
hw.cpu.ncore=${emulatorCpuCores === 4 ? 3 : 4}
|
|
140
|
-
`);
|
|
141
|
-
|
|
142
|
-
expect(
|
|
143
|
-
isAvdCompatible({
|
|
144
|
-
emulator: {
|
|
145
|
-
type: 'emulator',
|
|
146
|
-
name: 'Pixel_8_API_35',
|
|
147
|
-
avd: {
|
|
148
|
-
apiLevel: 35,
|
|
149
|
-
profile: 'pixel_8',
|
|
150
|
-
diskSize: '1G',
|
|
151
|
-
heapSize: '512M',
|
|
152
|
-
},
|
|
153
|
-
},
|
|
154
|
-
avdConfig,
|
|
155
|
-
hostArch: 'x86_64',
|
|
156
|
-
})
|
|
157
|
-
).toMatchObject({
|
|
158
|
-
compatible: false,
|
|
159
|
-
reason: `CPU core count mismatch: expected ${emulatorCpuCores}, got ${
|
|
160
|
-
emulatorCpuCores === 4 ? 3 : 4
|
|
161
|
-
}.`,
|
|
162
|
-
});
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
it('accepts disk partition sizes rewritten to bytes', () => {
|
|
166
|
-
const avdConfig = parseAvdConfig(`
|
|
167
|
-
image.sysdir.1=system-images/android-35/default/x86_64/
|
|
168
|
-
abi.type=x86_64
|
|
169
|
-
hw.device.name=pixel_8
|
|
170
|
-
disk.dataPartition.size=6442450944
|
|
171
|
-
vm.heapSize=512M
|
|
172
|
-
hw.cpu.ncore=${emulatorCpuCores}
|
|
173
|
-
`);
|
|
174
|
-
|
|
175
|
-
expect(
|
|
176
|
-
isAvdCompatible({
|
|
177
|
-
emulator: {
|
|
178
|
-
type: 'emulator',
|
|
179
|
-
name: 'Pixel_8_API_35',
|
|
180
|
-
avd: {
|
|
181
|
-
apiLevel: 35,
|
|
182
|
-
profile: 'pixel_8',
|
|
183
|
-
diskSize: '1G',
|
|
184
|
-
heapSize: '512M',
|
|
185
|
-
},
|
|
186
|
-
},
|
|
187
|
-
avdConfig,
|
|
188
|
-
hostArch: 'x86_64',
|
|
189
|
-
})
|
|
190
|
-
).toEqual({ compatible: true });
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
it('rejects smaller disk partitions even when sizes are normalized', () => {
|
|
194
|
-
const avdConfig = parseAvdConfig(`
|
|
195
|
-
image.sysdir.1=system-images/android-35/default/x86_64/
|
|
196
|
-
abi.type=x86_64
|
|
197
|
-
hw.device.name=pixel_8
|
|
198
|
-
disk.dataPartition.size=536870912
|
|
199
|
-
vm.heapSize=512M
|
|
200
|
-
`);
|
|
201
|
-
|
|
202
|
-
expect(
|
|
203
|
-
isAvdCompatible({
|
|
204
|
-
emulator: {
|
|
205
|
-
type: 'emulator',
|
|
206
|
-
name: 'Pixel_8_API_35',
|
|
207
|
-
avd: {
|
|
208
|
-
apiLevel: 35,
|
|
209
|
-
profile: 'pixel_8',
|
|
210
|
-
diskSize: '1G',
|
|
211
|
-
heapSize: '512M',
|
|
212
|
-
},
|
|
213
|
-
},
|
|
214
|
-
avdConfig,
|
|
215
|
-
hostArch: 'x86_64',
|
|
216
|
-
})
|
|
217
|
-
).toMatchObject({
|
|
218
|
-
compatible: false,
|
|
219
|
-
reason: 'Disk size mismatch: expected 1G, got 536870912.',
|
|
220
|
-
});
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
it('reports incompatibility when AVD metadata differs', () => {
|
|
224
|
-
const avdConfig = parseAvdConfig(`
|
|
225
|
-
image.sysdir.1=system-images/android-34/default/x86_64/
|
|
226
|
-
abi.type=x86_64
|
|
227
|
-
hw.device.name=pixel_7
|
|
228
|
-
disk.dataPartition.size=2G
|
|
229
|
-
vm.heapSize=1G
|
|
230
|
-
`);
|
|
231
|
-
|
|
232
|
-
expect(
|
|
233
|
-
isAvdCompatible({
|
|
234
|
-
emulator: {
|
|
235
|
-
type: 'emulator',
|
|
236
|
-
name: 'Pixel_8_API_35',
|
|
237
|
-
avd: {
|
|
238
|
-
apiLevel: 35,
|
|
239
|
-
profile: 'pixel_8',
|
|
240
|
-
diskSize: '1G',
|
|
241
|
-
heapSize: '512M',
|
|
242
|
-
},
|
|
243
|
-
},
|
|
244
|
-
avdConfig,
|
|
245
|
-
hostArch: 'x86_64',
|
|
246
|
-
})
|
|
247
|
-
).toMatchObject({
|
|
248
|
-
compatible: false,
|
|
249
|
-
});
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
it('normalizes AVD cache key input with name and host arch', () => {
|
|
253
|
-
expect(
|
|
254
|
-
getNormalizedAvdCacheConfig({
|
|
255
|
-
emulator: {
|
|
256
|
-
type: 'emulator',
|
|
257
|
-
name: 'Pixel_8_API_35',
|
|
258
|
-
avd: {
|
|
259
|
-
apiLevel: 35,
|
|
260
|
-
profile: ' Pixel_8 ',
|
|
261
|
-
diskSize: '1G',
|
|
262
|
-
heapSize: '512M',
|
|
263
|
-
},
|
|
264
|
-
},
|
|
265
|
-
hostArch: 'arm64-v8a',
|
|
266
|
-
})
|
|
267
|
-
).toEqual({
|
|
268
|
-
name: 'Pixel_8_API_35',
|
|
269
|
-
apiLevel: 35,
|
|
270
|
-
arch: 'arm64-v8a',
|
|
271
|
-
profile: 'pixel_8',
|
|
272
|
-
diskSize: '1g',
|
|
273
|
-
heapSize: '512m',
|
|
274
|
-
});
|
|
275
|
-
});
|
|
276
|
-
});
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { readFile } from 'node:fs/promises';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import { describe, expect, it } from 'vitest';
|
|
4
|
-
|
|
5
|
-
const workspaceRoot = path.resolve(import.meta.dirname, '../../../..');
|
|
6
|
-
|
|
7
|
-
describe('Android GitHub action config', () => {
|
|
8
|
-
it('does not duplicate Android SDK verification in the action YAML', async () => {
|
|
9
|
-
const [rootAction, packageAction] = await Promise.all([
|
|
10
|
-
readFile(path.join(workspaceRoot, 'action.yml'), 'utf8'),
|
|
11
|
-
readFile(
|
|
12
|
-
path.join(workspaceRoot, 'packages/github-action/src/action.yml'),
|
|
13
|
-
'utf8'
|
|
14
|
-
),
|
|
15
|
-
]);
|
|
16
|
-
|
|
17
|
-
for (const actionYaml of [rootAction, packageAction]) {
|
|
18
|
-
expect(actionYaml).not.toContain('Verify Android SDK packages');
|
|
19
|
-
expect(actionYaml).toContain(
|
|
20
|
-
"steps.avd-cache.outputs.cache-hit != 'true'"
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('removes the third-party emulator runner and maps cacheAvd to HARNESS_AVD_CACHING', async () => {
|
|
26
|
-
const [rootAction, packageAction] = await Promise.all([
|
|
27
|
-
readFile(path.join(workspaceRoot, 'action.yml'), 'utf8'),
|
|
28
|
-
readFile(
|
|
29
|
-
path.join(workspaceRoot, 'packages/github-action/src/action.yml'),
|
|
30
|
-
'utf8'
|
|
31
|
-
),
|
|
32
|
-
]);
|
|
33
|
-
|
|
34
|
-
for (const actionYaml of [rootAction, packageAction]) {
|
|
35
|
-
expect(actionYaml).not.toContain(
|
|
36
|
-
'reactivecircus/android-emulator-runner'
|
|
37
|
-
);
|
|
38
|
-
expect(actionYaml).toContain(
|
|
39
|
-
'HARNESS_AVD_CACHING: ${{ inputs.cacheAvd }}'
|
|
40
|
-
);
|
|
41
|
-
expect(actionYaml).toContain(
|
|
42
|
-
'fromJson(steps.load-config.outputs.config).action.avdCachingEnabled'
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('saves the AVD cache after the Harness run step', async () => {
|
|
48
|
-
const [rootAction, packageAction] = await Promise.all([
|
|
49
|
-
readFile(path.join(workspaceRoot, 'action.yml'), 'utf8'),
|
|
50
|
-
readFile(
|
|
51
|
-
path.join(workspaceRoot, 'packages/github-action/src/action.yml'),
|
|
52
|
-
'utf8'
|
|
53
|
-
),
|
|
54
|
-
]);
|
|
55
|
-
|
|
56
|
-
for (const actionYaml of [rootAction, packageAction]) {
|
|
57
|
-
expect(actionYaml.indexOf('- name: Run E2E tests')).toBeLessThan(
|
|
58
|
-
actionYaml.indexOf('- name: Save AVD cache')
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it('uses a cache key that includes the emulator name', async () => {
|
|
64
|
-
const [rootAction, packageAction] = await Promise.all([
|
|
65
|
-
readFile(path.join(workspaceRoot, 'action.yml'), 'utf8'),
|
|
66
|
-
readFile(
|
|
67
|
-
path.join(workspaceRoot, 'packages/github-action/src/action.yml'),
|
|
68
|
-
'utf8'
|
|
69
|
-
),
|
|
70
|
-
]);
|
|
71
|
-
|
|
72
|
-
for (const actionYaml of [rootAction, packageAction]) {
|
|
73
|
-
expect(actionYaml).toContain(
|
|
74
|
-
"AVD_NAME='${{ fromJson(steps.load-config.outputs.config).config.device.name }}'"
|
|
75
|
-
);
|
|
76
|
-
expect(actionYaml).toContain(
|
|
77
|
-
'CACHE_KEY="avd-$AVD_NAME-$ARCH-$AVD_CONFIG_HASH"'
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
});
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import {
|
|
3
|
-
collectDropboxArtifacts,
|
|
4
|
-
filterExitInfo,
|
|
5
|
-
getBestDropboxArtifact,
|
|
6
|
-
parseDropboxOutput,
|
|
7
|
-
} from '../crash-diagnostics.js';
|
|
8
|
-
|
|
9
|
-
const javaCrashDropbox = `
|
|
10
|
-
Drop box contents: 1 entries
|
|
11
|
-
Max entries: 1000
|
|
12
|
-
========================================
|
|
13
|
-
2026-03-12 10:30:45.123 data_app_crash (text, 500 bytes)
|
|
14
|
-
Process: com.harnessplayground
|
|
15
|
-
PID: 7777
|
|
16
|
-
Package: com.harnessplayground v1 (1.0)
|
|
17
|
-
java.lang.RuntimeException: boom
|
|
18
|
-
\tat com.harnessplayground.MainActivity.onCreate(MainActivity.kt:38)
|
|
19
|
-
`;
|
|
20
|
-
|
|
21
|
-
const nativeCrashDropbox = `
|
|
22
|
-
========================================
|
|
23
|
-
2026-03-12 10:31:10.456 data_app_native_crash (text, 800 bytes)
|
|
24
|
-
Process: com.harnessplayground
|
|
25
|
-
PID: 8888
|
|
26
|
-
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xdeadbeef
|
|
27
|
-
Abort message: 'JNI DETECTED ERROR IN APPLICATION'
|
|
28
|
-
backtrace:
|
|
29
|
-
#00 pc 00001234 /data/app/lib/libapp.so
|
|
30
|
-
`;
|
|
31
|
-
|
|
32
|
-
const deviceJavaCrashDropbox = `
|
|
33
|
-
Drop box contents: 8 entries
|
|
34
|
-
Searching for: data_app_crash
|
|
35
|
-
|
|
36
|
-
========================================
|
|
37
|
-
2026-05-29 10:22:34 data_app_crash (text, 1328 bytes)
|
|
38
|
-
SystemUptimeMs: 79467172
|
|
39
|
-
Process: com.harnessplayground
|
|
40
|
-
PID: 586
|
|
41
|
-
Package: com.harnessplayground v1 (1.0)
|
|
42
|
-
java.lang.RuntimeException: Intentional asynchronous Kotlin crash
|
|
43
|
-
\tat com.harnessplayground.PlaygroundCrashModule.crashFromKotlinAsync(PlaygroundCrashModule.kt:44)
|
|
44
|
-
`;
|
|
45
|
-
|
|
46
|
-
describe('collectDropboxArtifacts', () => {
|
|
47
|
-
it('matches harness playground crashes from merged per-tag dropbox output', async () => {
|
|
48
|
-
const artifacts = await collectDropboxArtifacts({
|
|
49
|
-
bundleId: 'com.harnessplayground',
|
|
50
|
-
getDropboxOutput: async () => deviceJavaCrashDropbox,
|
|
51
|
-
occurredAt: Date.now(),
|
|
52
|
-
pid: 586,
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
expect(artifacts).toHaveLength(1);
|
|
56
|
-
expect(artifacts[0]).toMatchObject({
|
|
57
|
-
artifactType: 'dropbox-crash',
|
|
58
|
-
pid: 586,
|
|
59
|
-
processName: 'com.harnessplayground',
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it('ignores Dropbox entries older than the session start time', async () => {
|
|
64
|
-
const artifacts = await collectDropboxArtifacts({
|
|
65
|
-
bundleId: 'com.harnessplayground',
|
|
66
|
-
getDropboxOutput: async () => deviceJavaCrashDropbox,
|
|
67
|
-
minOccurredAt: Date.parse('2026-05-29T10:22:35.000Z'),
|
|
68
|
-
occurredAt: Date.parse('2026-05-29T10:22:36.000Z'),
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
expect(artifacts).toHaveLength(0);
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
describe('parseDropboxOutput', () => {
|
|
76
|
-
it('parses java and native dropbox entries', () => {
|
|
77
|
-
const entries = parseDropboxOutput(`${javaCrashDropbox}\n${nativeCrashDropbox}`);
|
|
78
|
-
|
|
79
|
-
expect(entries).toHaveLength(2);
|
|
80
|
-
expect(entries[0]).toMatchObject({
|
|
81
|
-
tag: 'data_app_crash',
|
|
82
|
-
pid: 7777,
|
|
83
|
-
});
|
|
84
|
-
expect(entries[1]).toMatchObject({
|
|
85
|
-
tag: 'data_app_native_crash',
|
|
86
|
-
pid: 8888,
|
|
87
|
-
});
|
|
88
|
-
expect(entries[1]?.content).toContain('SIGSEGV');
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
describe('getBestDropboxArtifact', () => {
|
|
93
|
-
it('prefers the highest-scored artifact', () => {
|
|
94
|
-
const entries = parseDropboxOutput(`${javaCrashDropbox}\n${nativeCrashDropbox}`);
|
|
95
|
-
const artifacts = entries.map((entry, index) => ({
|
|
96
|
-
artifactType:
|
|
97
|
-
entry.tag === 'data_app_native_crash'
|
|
98
|
-
? ('dropbox-native-crash' as const)
|
|
99
|
-
: ('dropbox-crash' as const),
|
|
100
|
-
dropboxTag: entry.tag,
|
|
101
|
-
occurredAt: Date.now(),
|
|
102
|
-
score: index === 0 ? 100 : 300,
|
|
103
|
-
summary: entry.content,
|
|
104
|
-
pid: entry.pid,
|
|
105
|
-
processName: 'com.harnessplayground',
|
|
106
|
-
}));
|
|
107
|
-
|
|
108
|
-
expect(getBestDropboxArtifact(artifacts)?.dropboxTag).toBe(
|
|
109
|
-
'data_app_native_crash'
|
|
110
|
-
);
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
describe('filterExitInfo', () => {
|
|
115
|
-
it('returns matching exit-info records for the target package and pid', () => {
|
|
116
|
-
const output = `
|
|
117
|
-
ApplicationExitInfo #0:
|
|
118
|
-
package=com.harnessplayground pid=7777 realUid=10123
|
|
119
|
-
reason=4 (APP CRASH(NATIVE))
|
|
120
|
-
timestamp=2026-03-12 10:31:10.456
|
|
121
|
-
ApplicationExitInfo #1:
|
|
122
|
-
package=com.other.app pid=9999 realUid=10199
|
|
123
|
-
reason=10 (USER REQUESTED)
|
|
124
|
-
`;
|
|
125
|
-
|
|
126
|
-
const filtered = filterExitInfo({
|
|
127
|
-
output,
|
|
128
|
-
bundleId: 'com.harnessplayground',
|
|
129
|
-
pid: 7777,
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
expect(filtered).toContain('com.harnessplayground pid=7777');
|
|
133
|
-
expect(filtered).not.toContain('com.other.app');
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
it('returns null when no exit-info records exist', () => {
|
|
137
|
-
expect(
|
|
138
|
-
filterExitInfo({
|
|
139
|
-
output: 'No exit info records for com.harnessplayground',
|
|
140
|
-
bundleId: 'com.harnessplayground',
|
|
141
|
-
})
|
|
142
|
-
).toBeNull();
|
|
143
|
-
});
|
|
144
|
-
});
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { androidCrashParser } from '../crash-parser.js';
|
|
3
|
-
|
|
4
|
-
describe('androidCrashParser.parse', () => {
|
|
5
|
-
it('parses an AndroidRuntime crash block into a crash details object', () => {
|
|
6
|
-
expect(
|
|
7
|
-
androidCrashParser.parse({
|
|
8
|
-
contents: [
|
|
9
|
-
'--------- beginning of crash',
|
|
10
|
-
'03-12 11:35:09.000 1234 1234 E AndroidRuntime: Process: com.harnessplayground, PID: 1234',
|
|
11
|
-
'03-12 11:35:09.001 1234 1234 E AndroidRuntime: java.lang.RuntimeException: boom',
|
|
12
|
-
'03-12 11:35:09.002 1234 1234 E AndroidRuntime: at com.harnessplayground.MainActivity.onCreate(MainActivity.kt:42)',
|
|
13
|
-
].join('\n'),
|
|
14
|
-
bundleId: 'com.harnessplayground',
|
|
15
|
-
})
|
|
16
|
-
).toEqual({
|
|
17
|
-
source: 'logs',
|
|
18
|
-
summary: [
|
|
19
|
-
'--------- beginning of crash',
|
|
20
|
-
'03-12 11:35:09.000 1234 1234 E AndroidRuntime: Process: com.harnessplayground, PID: 1234',
|
|
21
|
-
'03-12 11:35:09.001 1234 1234 E AndroidRuntime: java.lang.RuntimeException: boom',
|
|
22
|
-
'03-12 11:35:09.002 1234 1234 E AndroidRuntime: at com.harnessplayground.MainActivity.onCreate(MainActivity.kt:42)',
|
|
23
|
-
].join('\n'),
|
|
24
|
-
signal: undefined,
|
|
25
|
-
exceptionType: 'java.lang.RuntimeException: boom',
|
|
26
|
-
processName: 'com.harnessplayground',
|
|
27
|
-
pid: 1234,
|
|
28
|
-
rawLines: [
|
|
29
|
-
'--------- beginning of crash',
|
|
30
|
-
'03-12 11:35:09.000 1234 1234 E AndroidRuntime: Process: com.harnessplayground, PID: 1234',
|
|
31
|
-
'03-12 11:35:09.001 1234 1234 E AndroidRuntime: java.lang.RuntimeException: boom',
|
|
32
|
-
'03-12 11:35:09.002 1234 1234 E AndroidRuntime: at com.harnessplayground.MainActivity.onCreate(MainActivity.kt:42)',
|
|
33
|
-
],
|
|
34
|
-
stackTrace: [
|
|
35
|
-
'03-12 11:35:09.002 1234 1234 E AndroidRuntime: at com.harnessplayground.MainActivity.onCreate(MainActivity.kt:42)',
|
|
36
|
-
],
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('extracts fatal signals from a native crash block', () => {
|
|
41
|
-
expect(
|
|
42
|
-
androidCrashParser.parse({
|
|
43
|
-
contents:
|
|
44
|
-
'03-12 11:35:08.000 1234 1234 F libc : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR) in tid 1234 (com.harnessplayground), pid 1234 (com.harnessplayground)',
|
|
45
|
-
bundleId: 'com.harnessplayground',
|
|
46
|
-
})
|
|
47
|
-
).toMatchObject({
|
|
48
|
-
signal: 'SIGSEGV',
|
|
49
|
-
processName: 'com.harnessplayground',
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
});
|