1 | // Copyright 2014 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | import 'package:file/memory.dart' ; |
6 | import 'package:flutter_tools/src/artifacts.dart'; |
7 | import 'package:flutter_tools/src/base/file_system.dart'; |
8 | import 'package:flutter_tools/src/base/logger.dart'; |
9 | import 'package:flutter_tools/src/base/platform.dart'; |
10 | import 'package:flutter_tools/src/base/user_messages.dart'; |
11 | import 'package:flutter_tools/src/runner/local_engine.dart'; |
12 | |
13 | import '../../src/common.dart'; |
14 | |
15 | const String kEngineRoot = '/flutter/engine' ; |
16 | const String kArbitraryEngineRoot = '/arbitrary/engine' ; |
17 | const String kPackageConfig = '.dart_tool/package_config.json' ; |
18 | |
19 | void main() { |
20 | testWithoutContext('works if --local-engine is specified and --local-engine-src-path ' |
21 | 'is determined by sky_engine' , () async { |
22 | final FileSystem fileSystem = MemoryFileSystem.test(); |
23 | fileSystem |
24 | .directory(' $kArbitraryEngineRoot/src/out/ios_debug/gen/dart-pkg/sky_engine/lib/' ) |
25 | .createSync(recursive: true); |
26 | fileSystem |
27 | .directory(' $kArbitraryEngineRoot/src/out/host_debug' ) |
28 | .createSync(recursive: true); |
29 | fileSystem |
30 | .file(kPackageConfig) |
31 | ..createSync(recursive: true) |
32 | ..writeAsStringSync(''' |
33 | { |
34 | "configVersion": 2, |
35 | "packages": [ |
36 | { |
37 | "name": "sky_engine", |
38 | "rootUri": "file://$kArbitraryEngineRoot/src/out/ios_debug/gen/dart-pkg/sky_engine", |
39 | "packageUri": "lib/" |
40 | } |
41 | ] |
42 | } |
43 | '''); |
44 | fileSystem |
45 | .file('bin/cache/pkg/sky_engine/lib') |
46 | .createSync(recursive: true); |
47 | |
48 | final BufferLogger logger = BufferLogger.test(); |
49 | final LocalEngineLocator localEngineLocator = LocalEngineLocator( |
50 | fileSystem: fileSystem, |
51 | flutterRoot: '', |
52 | logger: logger, |
53 | userMessages: UserMessages(), |
54 | platform: FakePlatform(environment: <String, String>{}), |
55 | ); |
56 | |
57 | expect( |
58 | await localEngineLocator.findEnginePath(localEngine: 'ios_debug', localHostEngine: 'host_debug'), |
59 | matchesEngineBuildPaths( |
60 | hostEngine: '/arbitrary/engine/src/out/host_debug', |
61 | targetEngine: '/arbitrary/engine/src/out/ios_debug', |
62 | ), |
63 | ); |
64 | expect(logger.traceText, contains('Local engine source at /arbitrary/engine/src')); |
65 | |
66 | // Verify that this also works if the sky_engine path is a symlink to the engine root. |
67 | fileSystem.link('/symlink').createSync(kArbitraryEngineRoot); |
68 | fileSystem |
69 | .file(kPackageConfig) |
70 | ..createSync(recursive: true) |
71 | ..writeAsStringSync(''' |
72 | { |
73 | "configVersion": 2, |
74 | "packages": [ |
75 | { |
76 | "name": "sky_engine", |
77 | "rootUri": "file:///symlink/src/out/ios_debug/gen/dart-pkg/sky_engine/", |
78 | "packageUri": "lib/" |
79 | } |
80 | ] |
81 | } |
82 | '''); |
83 | |
84 | expect( |
85 | await localEngineLocator.findEnginePath(localEngine: 'ios_debug', localHostEngine: 'host_debug'), |
86 | matchesEngineBuildPaths( |
87 | hostEngine: '/symlink/src/out/host_debug', |
88 | targetEngine: '/symlink/src/out/ios_debug', |
89 | ), |
90 | ); |
91 | expect(logger.traceText, contains('Local engine source at /symlink/src')); |
92 | }); |
93 | |
94 | testWithoutContext('works if --local-engine is specified and --local-engine-src-path ' |
95 | 'is specified', () async { |
96 | final FileSystem fileSystem = MemoryFileSystem.test(); |
97 | // Intentionally do not create a package_config to verify that it is not required. |
98 | fileSystem.directory('$kArbitraryEngineRoot/src/out/ios_debug').createSync(recursive: true); |
99 | fileSystem.directory('$kArbitraryEngineRoot/src/out/host_debug').createSync(recursive: true); |
100 | |
101 | final BufferLogger logger = BufferLogger.test(); |
102 | final LocalEngineLocator localEngineLocator = LocalEngineLocator( |
103 | fileSystem: fileSystem, |
104 | flutterRoot: '', |
105 | logger: logger, |
106 | userMessages: UserMessages(), |
107 | platform: FakePlatform(environment: <String, String>{}), |
108 | ); |
109 | |
110 | expect( |
111 | await localEngineLocator.findEnginePath(engineSourcePath: '$kArbitraryEngineRoot/src', localEngine: 'ios_debug', localHostEngine: 'host_debug'), |
112 | matchesEngineBuildPaths( |
113 | hostEngine: '/arbitrary/engine/src/out/host_debug', |
114 | targetEngine: '/arbitrary/engine/src/out/ios_debug', |
115 | ), |
116 | ); |
117 | expect(logger.traceText, contains('Local engine source at /arbitrary/engine/src')); |
118 | }); |
119 | |
120 | testWithoutContext('works if --local-engine is specified and --local-engine-host is specified', () async { |
121 | final FileSystem fileSystem = MemoryFileSystem.test(); |
122 | final Directory localEngine = fileSystem |
123 | .directory('$kArbitraryEngineRoot/src/out/android_debug_unopt_arm64/') |
124 | ..createSync(recursive: true); |
125 | fileSystem.directory('$kArbitraryEngineRoot/src/out/host_debug_unopt_arm64/').createSync(recursive: true); |
126 | |
127 | final BufferLogger logger = BufferLogger.test(); |
128 | final LocalEngineLocator localEngineLocator = LocalEngineLocator( |
129 | fileSystem: fileSystem, |
130 | flutterRoot: 'flutter/flutter', |
131 | logger: logger, |
132 | userMessages: UserMessages(), |
133 | platform: FakePlatform(environment: <String, String>{}), |
134 | ); |
135 | |
136 | expect( |
137 | await localEngineLocator.findEnginePath(localEngine: localEngine.path, localHostEngine: 'host_debug_unopt_arm64'), |
138 | matchesEngineBuildPaths( |
139 | hostEngine: '/arbitrary/engine/src/out/host_debug_unopt_arm64', |
140 | targetEngine: '/arbitrary/engine/src/out/android_debug_unopt_arm64', |
141 | ), |
142 | ); |
143 | expect(logger.traceText, contains('Local engine source at /arbitrary/engine/src')); |
144 | }); |
145 | |
146 | testWithoutContext('fails if --local-engine-host is omitted', () async { |
147 | final FileSystem fileSystem = MemoryFileSystem.test(); |
148 | final Directory localEngine = fileSystem |
149 | .directory('$kArbitraryEngineRoot/src/out/android_debug_unopt_arm64/') |
150 | ..createSync(recursive: true); |
151 | fileSystem.directory('$kArbitraryEngineRoot/src/out/host_debug_unopt/').createSync(recursive: true); |
152 | |
153 | final BufferLogger logger = BufferLogger.test(); |
154 | final LocalEngineLocator localEngineLocator = LocalEngineLocator( |
155 | fileSystem: fileSystem, |
156 | flutterRoot: 'flutter/flutter', |
157 | logger: logger, |
158 | userMessages: UserMessages(), |
159 | platform: FakePlatform(environment: <String, String>{}), |
160 | ); |
161 | |
162 | await expectLater( |
163 | localEngineLocator.findEnginePath(localEngine: localEngine.path), |
164 | throwsToolExit(message: 'You are using a locally built engine (--local-engine) but have not specified --local-engine-host'), |
165 | ); |
166 | }); |
167 | |
168 | testWithoutContext('works if --local-engine is specified and --local-engine-src-path ' |
169 | 'is determined by --local-engine', () async { |
170 | final FileSystem fileSystem = MemoryFileSystem.test(); |
171 | final Directory localEngine = fileSystem |
172 | .directory('$kArbitraryEngineRoot/src/out/ios_debug/') |
173 | ..createSync(recursive: true); |
174 | fileSystem.directory('$kArbitraryEngineRoot/src/out/host_debug/').createSync(recursive: true); |
175 | |
176 | final BufferLogger logger = BufferLogger.test(); |
177 | final LocalEngineLocator localEngineLocator = LocalEngineLocator( |
178 | fileSystem: fileSystem, |
179 | flutterRoot: 'flutter/flutter', |
180 | logger: logger, |
181 | userMessages: UserMessages(), |
182 | platform: FakePlatform(environment: <String, String>{}), |
183 | ); |
184 | |
185 | expect( |
186 | await localEngineLocator.findEnginePath(localEngine: localEngine.path, localHostEngine: 'host_debug'), |
187 | matchesEngineBuildPaths( |
188 | hostEngine: '/arbitrary/engine/src/out/host_debug', |
189 | targetEngine: '/arbitrary/engine/src/out/ios_debug', |
190 | ), |
191 | ); |
192 | expect(logger.traceText, contains('Parsed engine source from local engine as /arbitrary/engine/src')); |
193 | expect(logger.traceText, contains('Local engine source at /arbitrary/engine/src')); |
194 | }); |
195 | |
196 | testWithoutContext('works if local engine is host engine', () async { |
197 | final FileSystem fileSystem = MemoryFileSystem.test(); |
198 | final Directory localEngine = fileSystem |
199 | .directory('$kArbitraryEngineRoot/src/out/host_debug/') |
200 | ..createSync(recursive: true); |
201 | |
202 | final BufferLogger logger = BufferLogger.test(); |
203 | final LocalEngineLocator localEngineLocator = LocalEngineLocator( |
204 | fileSystem: fileSystem, |
205 | flutterRoot: 'flutter/flutter', |
206 | logger: logger, |
207 | userMessages: UserMessages(), |
208 | platform: FakePlatform(environment: <String, String>{}), |
209 | ); |
210 | |
211 | expect( |
212 | await localEngineLocator.findEnginePath(localEngine: localEngine.path, localHostEngine: localEngine.path), |
213 | matchesEngineBuildPaths( |
214 | hostEngine: '/arbitrary/engine/src/out/host_debug', |
215 | targetEngine: '/arbitrary/engine/src/out/host_debug', |
216 | ), |
217 | ); |
218 | expect(logger.traceText, contains('Local engine source at /arbitrary/engine/src')); |
219 | }); |
220 | |
221 | testWithoutContext('works if local engine is host engine with suffixes', () async { |
222 | final FileSystem fileSystem = MemoryFileSystem.test(); |
223 | final Directory localEngine = fileSystem |
224 | .directory('$kArbitraryEngineRoot/src/out/host_debug_unopt_arm64/') |
225 | ..createSync(recursive: true); |
226 | |
227 | final BufferLogger logger = BufferLogger.test(); |
228 | final LocalEngineLocator localEngineLocator = LocalEngineLocator( |
229 | fileSystem: fileSystem, |
230 | flutterRoot: 'flutter/flutter', |
231 | logger: logger, |
232 | userMessages: UserMessages(), |
233 | platform: FakePlatform(environment: <String, String>{}), |
234 | ); |
235 | |
236 | expect( |
237 | await localEngineLocator.findEnginePath(localEngine: localEngine.path, localHostEngine: localEngine.path), |
238 | matchesEngineBuildPaths( |
239 | hostEngine: '/arbitrary/engine/src/out/host_debug_unopt_arm64', |
240 | targetEngine: '/arbitrary/engine/src/out/host_debug_unopt_arm64', |
241 | ), |
242 | ); |
243 | }); |
244 | |
245 | testWithoutContext('works if local engine is simulator', () async { |
246 | final FileSystem fileSystem = MemoryFileSystem.test(); |
247 | final Directory localEngine = fileSystem |
248 | .directory('$kArbitraryEngineRoot/src/out/ios_debug_sim/') |
249 | ..createSync(recursive: true); |
250 | fileSystem |
251 | .directory('$kArbitraryEngineRoot/src/out/host_debug/') |
252 | .createSync(recursive: true); |
253 | |
254 | final BufferLogger logger = BufferLogger.test(); |
255 | final LocalEngineLocator localEngineLocator = LocalEngineLocator( |
256 | fileSystem: fileSystem, |
257 | flutterRoot: 'flutter/flutter', |
258 | logger: logger, |
259 | userMessages: UserMessages(), |
260 | platform: FakePlatform(environment: <String, String>{}), |
261 | ); |
262 | |
263 | expect( |
264 | await localEngineLocator.findEnginePath(localEngine: localEngine.path, localHostEngine: 'host_debug'), |
265 | matchesEngineBuildPaths( |
266 | hostEngine: '/arbitrary/engine/src/out/host_debug', |
267 | targetEngine: '/arbitrary/engine/src/out/ios_debug_sim', |
268 | ), |
269 | ); |
270 | }); |
271 | |
272 | testWithoutContext('works if local engine is simulator unoptimized', |
273 | () async { |
274 | final FileSystem fileSystem = MemoryFileSystem.test(); |
275 | final Directory localEngine = fileSystem |
276 | .directory('$kArbitraryEngineRoot/src/out/ios_debug_sim_unopt/') |
277 | ..createSync(recursive: true); |
278 | fileSystem |
279 | .directory('$kArbitraryEngineRoot/src/out/host_debug_unopt/') |
280 | .createSync(recursive: true); |
281 | |
282 | final BufferLogger logger = BufferLogger.test(); |
283 | final LocalEngineLocator localEngineLocator = LocalEngineLocator( |
284 | fileSystem: fileSystem, |
285 | flutterRoot: 'flutter/flutter', |
286 | logger: logger, |
287 | userMessages: UserMessages(), |
288 | platform: FakePlatform(environment: <String, String>{}), |
289 | ); |
290 | |
291 | expect( |
292 | await localEngineLocator.findEnginePath(localEngine: localEngine.path, localHostEngine: 'host_debug_unopt'), |
293 | matchesEngineBuildPaths( |
294 | hostEngine: '/arbitrary/engine/src/out/host_debug_unopt', |
295 | targetEngine: '/arbitrary/engine/src/out/ios_debug_sim_unopt', |
296 | ), |
297 | ); |
298 | }); |
299 | |
300 | testWithoutContext('fails if host_debug does not exist', () async { |
301 | final FileSystem fileSystem = MemoryFileSystem.test(); |
302 | final Directory localEngine = fileSystem |
303 | .directory('$kArbitraryEngineRoot/src/out/ios_debug/') |
304 | ..createSync(recursive: true); |
305 | |
306 | final LocalEngineLocator localEngineLocator = LocalEngineLocator( |
307 | fileSystem: fileSystem, |
308 | flutterRoot: 'flutter/flutter', |
309 | logger: BufferLogger.test(), |
310 | userMessages: UserMessages(), |
311 | platform: FakePlatform(environment: <String, String>{}), |
312 | ); |
313 | |
314 | await expectToolExitLater( |
315 | localEngineLocator.findEnginePath(localEngine: localEngine.path, localHostEngine: 'host_debug'), |
316 | contains('No Flutter engine build found at /arbitrary/engine/src/out/host_debug'), |
317 | ); |
318 | }); |
319 | |
320 | testWithoutContext('works if --local-engine is specified and --local-engine-src-path ' |
321 | 'is determined by flutter root', () async { |
322 | final FileSystem fileSystem = MemoryFileSystem.test(); |
323 | fileSystem |
324 | .file(kPackageConfig) |
325 | .createSync(recursive: true); |
326 | fileSystem |
327 | .directory('$kEngineRoot/src/out/ios_debug') |
328 | .createSync(recursive: true); |
329 | fileSystem |
330 | .directory('$kEngineRoot/src/out/host_debug') |
331 | .createSync(recursive: true); |
332 | fileSystem |
333 | .file('bin/cache/pkg/sky_engine/lib') |
334 | .createSync(recursive: true); |
335 | |
336 | final BufferLogger logger = BufferLogger.test(); |
337 | final LocalEngineLocator localEngineLocator = LocalEngineLocator( |
338 | fileSystem: fileSystem, |
339 | flutterRoot: 'flutter/flutter', |
340 | logger: logger, |
341 | userMessages: UserMessages(), |
342 | platform: FakePlatform(environment: <String, String>{}), |
343 | ); |
344 | |
345 | expect( |
346 | await localEngineLocator.findEnginePath(localEngine: 'ios_debug', localHostEngine: 'host_debug'), |
347 | matchesEngineBuildPaths( |
348 | hostEngine: 'flutter/engine/src/out/host_debug', |
349 | targetEngine: 'flutter/engine/src/out/ios_debug', |
350 | ), |
351 | ); |
352 | expect(logger.traceText, contains('Local engine source at flutter/engine/src')); |
353 | }); |
354 | |
355 | testWithoutContext('fails if --local-engine is specified and --local-engine-src-path ' |
356 | 'cannot be determined', () async { |
357 | final FileSystem fileSystem = MemoryFileSystem.test(); |
358 | |
359 | final LocalEngineLocator localEngineLocator = LocalEngineLocator( |
360 | fileSystem: fileSystem, |
361 | flutterRoot: 'flutter/flutter', |
362 | logger: BufferLogger.test(), |
363 | userMessages: UserMessages(), |
364 | platform: FakePlatform(environment: <String, String>{}), |
365 | ); |
366 | |
367 | await expectToolExitLater( |
368 | localEngineLocator.findEnginePath(localEngine: '/path/to/nothing', localHostEngine: '/path/to/nothing'), |
369 | contains('Unable to detect local Flutter engine src directory'), |
370 | ); |
371 | }); |
372 | |
373 | testWithoutContext('works for local web engine', () async { |
374 | final FileSystem fileSystem = MemoryFileSystem.test(); |
375 | final Directory localWasmEngine = fileSystem |
376 | .directory('$kArbitraryEngineRoot/src/out/wasm_whatever/') |
377 | ..createSync(recursive: true); |
378 | final Directory localWebEngine = fileSystem |
379 | .directory('$kArbitraryEngineRoot/src/out/web_whatever/') |
380 | ..createSync(recursive: true); |
381 | |
382 | final BufferLogger wasmLogger = BufferLogger.test(); |
383 | final LocalEngineLocator localWasmEngineLocator = LocalEngineLocator( |
384 | fileSystem: fileSystem, |
385 | flutterRoot: 'flutter/flutter', |
386 | logger: wasmLogger, |
387 | userMessages: UserMessages(), |
388 | platform: FakePlatform(environment: <String, String>{}), |
389 | ); |
390 | |
391 | expect( |
392 | await localWasmEngineLocator.findEnginePath(localEngine: localWasmEngine.path, localHostEngine: localWasmEngine.path), |
393 | matchesEngineBuildPaths( |
394 | hostEngine: '/arbitrary/engine/src/out/wasm_whatever', |
395 | targetEngine: '/arbitrary/engine/src/out/wasm_whatever', |
396 | ), |
397 | ); |
398 | expect(wasmLogger.traceText, contains('Local engine source at /arbitrary/engine/src')); |
399 | |
400 | final BufferLogger webLogger = BufferLogger.test(); |
401 | final LocalEngineLocator localWebEngineLocator = LocalEngineLocator( |
402 | fileSystem: fileSystem, |
403 | flutterRoot: 'flutter/flutter', |
404 | logger: webLogger, |
405 | userMessages: UserMessages(), |
406 | platform: FakePlatform(environment: <String, String>{}), |
407 | ); |
408 | |
409 | expect( |
410 | await localWebEngineLocator.findEnginePath(localEngine: localWebEngine.path, localHostEngine: localWebEngine.path), |
411 | matchesEngineBuildPaths( |
412 | hostEngine: '/arbitrary/engine/src/out/web_whatever', |
413 | targetEngine: '/arbitrary/engine/src/out/web_whatever', |
414 | ), |
415 | ); |
416 | expect(webLogger.traceText, contains('Local engine source at /arbitrary/engine/src')); |
417 | }); |
418 | |
419 | test('returns null without throwing if nothing is specified', () async { |
420 | final LocalEngineLocator localWebEngineLocator = LocalEngineLocator( |
421 | fileSystem: MemoryFileSystem.test(), |
422 | flutterRoot: 'flutter/flutter', |
423 | logger: BufferLogger.test(), |
424 | userMessages: UserMessages(), |
425 | platform: FakePlatform(environment: <String, String>{}), |
426 | ); |
427 | |
428 | final EngineBuildPaths? paths = await localWebEngineLocator.findEnginePath(); |
429 | expect(paths, isNull); |
430 | }); |
431 | |
432 | test('throws if nothing is specified but the FLUTTER_ENGINE environment variable is set', () async { |
433 | final LocalEngineLocator localWebEngineLocator = LocalEngineLocator( |
434 | fileSystem: MemoryFileSystem.test(), |
435 | flutterRoot: 'flutter/flutter', |
436 | logger: BufferLogger.test(), |
437 | userMessages: UserMessages(), |
438 | platform: FakePlatform(environment: <String, String>{'FLUTTER_ENGINE': 'blah'}), |
439 | ); |
440 | |
441 | await expectToolExitLater( |
442 | localWebEngineLocator.findEnginePath(), |
443 | contains('Unable to detect a Flutter engine build directory in blah'), |
444 | ); |
445 | }); |
446 | } |
447 | |
448 | Matcher matchesEngineBuildPaths({ |
449 | String? hostEngine, |
450 | String? targetEngine, |
451 | }) { |
452 | return const TypeMatcher<EngineBuildPaths>() |
453 | .having((EngineBuildPaths paths) => paths.hostEngine, 'hostEngine', hostEngine) |
454 | .having((EngineBuildPaths paths) => paths.targetEngine, 'targetEngine', targetEngine); |
455 | } |
456 | |