common_test.dart 25.5 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
// @dart = 2.8

7 8
import 'package:file/memory.dart';
import 'package:flutter_tools/src/artifacts.dart';
9
import 'package:flutter_tools/src/base/file_system.dart';
10
import 'package:flutter_tools/src/base/logger.dart';
11
import 'package:flutter_tools/src/base/platform.dart';
12 13 14
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/build_system/build_system.dart';
import 'package:flutter_tools/src/build_system/exceptions.dart';
15
import 'package:flutter_tools/src/build_system/targets/common.dart';
16
import 'package:flutter_tools/src/build_system/targets/ios.dart';
17 18
import 'package:flutter_tools/src/compile.dart';

19
import '../../../src/common.dart';
20
import '../../../src/context.dart';
21
import '../../../src/fake_process_manager.dart';
22

23 24 25 26
const String kBoundaryKey = '4d2d9609-c662-4571-afde-31410f96caa6';
const String kElfAot = '--snapshot_kind=app-aot-elf';
const String kAssemblyAot = '--snapshot_kind=app-aot-assembly';

27
final Platform macPlatform = FakePlatform(operatingSystem: 'macos', environment: <String, String>{});
28
void main() {
29
  FakeProcessManager processManager;
30 31
  Environment androidEnvironment;
  Environment iosEnvironment;
32
  Artifacts artifacts;
33 34
  FileSystem fileSystem;
  Logger logger;
35 36

  setUp(() {
37
    processManager = FakeProcessManager.empty();
38 39
    logger = BufferLogger.test();
    artifacts = Artifacts.test();
40
    fileSystem = MemoryFileSystem.test();
41 42 43 44 45 46
    androidEnvironment = Environment.test(
      fileSystem.currentDirectory,
      defines: <String, String>{
        kBuildMode: getNameForBuildMode(BuildMode.profile),
        kTargetPlatform: getNameForTargetPlatform(TargetPlatform.android_arm),
      },
47
      inputs: <String, String>{},
48 49 50 51 52 53 54 55 56 57 58 59
      artifacts: artifacts,
      processManager: processManager,
      fileSystem: fileSystem,
      logger: logger,
    );
    androidEnvironment.buildDir.createSync(recursive: true);
    iosEnvironment = Environment.test(
      fileSystem.currentDirectory,
      defines: <String, String>{
        kBuildMode: getNameForBuildMode(BuildMode.profile),
        kTargetPlatform: getNameForTargetPlatform(TargetPlatform.ios),
      },
60
      inputs: <String, String>{},
61 62 63 64 65 66
      artifacts: artifacts,
      processManager: processManager,
      fileSystem: fileSystem,
      logger: logger,
    );
    iosEnvironment.buildDir.createSync(recursive: true);
67
  });
68

69
  testWithoutContext('KernelSnapshot throws error if missing build mode', () async {
70 71 72
    androidEnvironment.defines.remove(kBuildMode);
    expect(
      const KernelSnapshot().build(androidEnvironment),
73
      throwsA(isA<MissingDefineException>()));
74
  });
75

76
  testWithoutContext('KernelSnapshot handles null result from kernel compilation', () async {
77 78 79
    fileSystem.file('.dart_tool/package_config.json')
      ..createSync(recursive: true)
      ..writeAsStringSync('{"configVersion": 2, "packages":[]}');
80
    final String build = androidEnvironment.buildDir.path;
81 82 83 84 85
    final String flutterPatchedSdkPath = artifacts.getArtifactPath(
      Artifact.flutterPatchedSdkPath,
      platform: TargetPlatform.android_arm,
      mode: BuildMode.profile,
    );
86
    processManager.addCommands(<FakeCommand>[
87
      FakeCommand(command: <String>[
88
        artifacts.getHostArtifact(HostArtifact.engineDartBinary).path,
89
        '--disable-dart-dev',
90 91
        artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk),
        '--sdk-root',
92
        '$flutterPatchedSdkPath/',
93
        '--target=flutter',
94
        '--no-print-incremental-dependencies',
95
        ...buildModeOptions(BuildMode.profile, <String>[]),
96 97 98
        '--aot',
        '--tfa',
        '--packages',
99
        '/.dart_tool/package_config.json',
100 101 102 103
        '--output-dill',
        '$build/app.dill',
        '--depfile',
        '$build/kernel_snapshot.d',
104
        'file:///lib/main.dart',
105 106 107
      ], exitCode: 1),
    ]);

108
    await expectLater(() => const KernelSnapshot().build(androidEnvironment), throwsException);
109
    expect(processManager, hasNoRemainingExpectations);
110
  });
111

112
  testWithoutContext('KernelSnapshot does not use track widget creation on profile builds', () async {
113 114 115
    fileSystem.file('.dart_tool/package_config.json')
      ..createSync(recursive: true)
      ..writeAsStringSync('{"configVersion": 2, "packages":[]}');
116
    final String build = androidEnvironment.buildDir.path;
117 118 119 120 121
    final String flutterPatchedSdkPath = artifacts.getArtifactPath(
      Artifact.flutterPatchedSdkPath,
      platform: TargetPlatform.android_arm,
      mode: BuildMode.profile,
    );
122
    processManager.addCommands(<FakeCommand>[
123
      FakeCommand(command: <String>[
124
        artifacts.getHostArtifact(HostArtifact.engineDartBinary).path,
125
        '--disable-dart-dev',
126 127
        artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk),
        '--sdk-root',
128
        '$flutterPatchedSdkPath/',
129
        '--target=flutter',
130
        '--no-print-incremental-dependencies',
131
        ...buildModeOptions(BuildMode.profile, <String>[]),
132 133 134
        '--aot',
        '--tfa',
        '--packages',
135
        '/.dart_tool/package_config.json',
136 137 138 139
        '--output-dill',
        '$build/app.dill',
        '--depfile',
        '$build/kernel_snapshot.d',
140
        'file:///lib/main.dart',
141 142
      ], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/app.dill 0\n'),
    ]);
143

144
    await const KernelSnapshot().build(androidEnvironment);
145

146
    expect(processManager, hasNoRemainingExpectations);
147
  });
148

149
  testWithoutContext('KernelSnapshot correctly handles an empty string in ExtraFrontEndOptions', () async {
150 151 152
    fileSystem.file('.dart_tool/package_config.json')
      ..createSync(recursive: true)
      ..writeAsStringSync('{"configVersion": 2, "packages":[]}');
153
    final String build = androidEnvironment.buildDir.path;
154 155 156 157 158
    final String flutterPatchedSdkPath = artifacts.getArtifactPath(
      Artifact.flutterPatchedSdkPath,
      platform: TargetPlatform.android_arm,
      mode: BuildMode.profile,
    );
159
    processManager.addCommands(<FakeCommand>[
160
      FakeCommand(command: <String>[
161
        artifacts.getHostArtifact(HostArtifact.engineDartBinary).path,
162
        '--disable-dart-dev',
163 164
        artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk),
        '--sdk-root',
165
        '$flutterPatchedSdkPath/',
166
        '--target=flutter',
167
        '--no-print-incremental-dependencies',
168
        ...buildModeOptions(BuildMode.profile, <String>[]),
169 170 171
        '--aot',
        '--tfa',
        '--packages',
172
        '/.dart_tool/package_config.json',
173 174 175 176
        '--output-dill',
        '$build/app.dill',
        '--depfile',
        '$build/kernel_snapshot.d',
177
        'file:///lib/main.dart',
178 179 180 181 182 183
      ], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/app.dill 0\n'),
    ]);

    await const KernelSnapshot()
      .build(androidEnvironment..defines[kExtraFrontEndOptions] = '');

184
    expect(processManager, hasNoRemainingExpectations);
185
  });
186

187
  testWithoutContext('KernelSnapshot correctly forwards ExtraFrontEndOptions', () async {
188 189 190
    fileSystem.file('.dart_tool/package_config.json')
      ..createSync(recursive: true)
      ..writeAsStringSync('{"configVersion": 2, "packages":[]}');
191
    final String build = androidEnvironment.buildDir.path;
192 193 194 195 196
    final String flutterPatchedSdkPath = artifacts.getArtifactPath(
      Artifact.flutterPatchedSdkPath,
      platform: TargetPlatform.android_arm,
      mode: BuildMode.profile,
    );
197
    processManager.addCommands(<FakeCommand>[
198
      FakeCommand(command: <String>[
199
        artifacts.getHostArtifact(HostArtifact.engineDartBinary).path,
200
        '--disable-dart-dev',
201 202
        artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk),
        '--sdk-root',
203
        '$flutterPatchedSdkPath/',
204
        '--target=flutter',
205
        '--no-print-incremental-dependencies',
206
        ...buildModeOptions(BuildMode.profile, <String>[]),
207 208 209
        '--aot',
        '--tfa',
        '--packages',
210
        '/.dart_tool/package_config.json',
211 212 213 214 215 216
        '--output-dill',
        '$build/app.dill',
        '--depfile',
        '$build/kernel_snapshot.d',
        'foo',
        'bar',
217
        'file:///lib/main.dart',
218 219 220 221 222 223
      ], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/app.dill 0\n'),
    ]);

    await const KernelSnapshot()
      .build(androidEnvironment..defines[kExtraFrontEndOptions] = 'foo,bar');

224
    expect(processManager, hasNoRemainingExpectations);
225
  });
226

227
  testWithoutContext('KernelSnapshot can disable track-widget-creation on debug builds', () async {
228 229 230
    fileSystem.file('.dart_tool/package_config.json')
      ..createSync(recursive: true)
      ..writeAsStringSync('{"configVersion": 2, "packages":[]}');
231
    final String build = androidEnvironment.buildDir.path;
232 233 234 235 236
    final String flutterPatchedSdkPath = artifacts.getArtifactPath(
      Artifact.flutterPatchedSdkPath,
      platform: TargetPlatform.android_arm,
      mode: BuildMode.debug,
    );
237
    processManager.addCommands(<FakeCommand>[
238
      FakeCommand(command: <String>[
239
        artifacts.getHostArtifact(HostArtifact.engineDartBinary).path,
240
        '--disable-dart-dev',
241 242
        artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk),
        '--sdk-root',
243
        '$flutterPatchedSdkPath/',
244
        '--target=flutter',
245
        '--no-print-incremental-dependencies',
246
        ...buildModeOptions(BuildMode.debug, <String>[]),
247 248
        '--no-link-platform',
        '--packages',
249
        '/.dart_tool/package_config.json',
250 251 252 253
        '--output-dill',
        '$build/app.dill',
        '--depfile',
        '$build/kernel_snapshot.d',
254
        'file:///lib/main.dart',
255 256
      ], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/app.dill 0\n'),
    ]);
257

258
    await const KernelSnapshot().build(androidEnvironment
259
      ..defines[kBuildMode] = getNameForBuildMode(BuildMode.debug)
260
      ..defines[kTrackWidgetCreation] = 'false');
261

262
    expect(processManager, hasNoRemainingExpectations);
263
  });
264

265
  testWithoutContext('KernelSnapshot forces platform linking on debug for darwin target platforms', () async {
266 267 268
    fileSystem.file('.dart_tool/package_config.json')
      ..createSync(recursive: true)
      ..writeAsStringSync('{"configVersion": 2, "packages":[]}');
269
    final String build = androidEnvironment.buildDir.path;
270 271 272 273 274
    final String flutterPatchedSdkPath = artifacts.getArtifactPath(
      Artifact.flutterPatchedSdkPath,
      platform: TargetPlatform.darwin,
      mode: BuildMode.debug,
    );
275
    processManager.addCommands(<FakeCommand>[
276
      FakeCommand(command: <String>[
277
        artifacts.getHostArtifact(HostArtifact.engineDartBinary).path,
278
        '--disable-dart-dev',
279 280
        artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk),
        '--sdk-root',
281
        '$flutterPatchedSdkPath/',
282
        '--target=flutter',
283
        '--no-print-incremental-dependencies',
284
        ...buildModeOptions(BuildMode.debug, <String>[]),
285
        '--packages',
286
        '/.dart_tool/package_config.json',
287 288 289 290
        '--output-dill',
        '$build/app.dill',
        '--depfile',
        '$build/kernel_snapshot.d',
291
        'file:///lib/main.dart',
292 293
      ], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/app.dill 0\n'),
    ]);
294 295

    await const KernelSnapshot().build(androidEnvironment
296
      ..defines[kTargetPlatform]  = getNameForTargetPlatform(TargetPlatform.darwin)
297
      ..defines[kBuildMode] = getNameForBuildMode(BuildMode.debug)
298
      ..defines[kTrackWidgetCreation] = 'false'
299 300
    );

301
    expect(processManager, hasNoRemainingExpectations);
302
  });
303

304
  testWithoutContext('KernelSnapshot does use track widget creation on debug builds', () async {
305 306 307
    fileSystem.file('.dart_tool/package_config.json')
      ..createSync(recursive: true)
      ..writeAsStringSync('{"configVersion": 2, "packages":[]}');
308
    final Environment testEnvironment = Environment.test(
309
      fileSystem.currentDirectory,
310
      defines: <String, String>{
311
        kBuildMode: getNameForBuildMode(BuildMode.debug),
312
        kTargetPlatform: getNameForTargetPlatform(TargetPlatform.android_arm),
313
      },
314 315
      processManager: processManager,
      artifacts: artifacts,
316 317
      fileSystem: fileSystem,
      logger: logger,
318 319
    );
    final String build = testEnvironment.buildDir.path;
320 321 322 323 324
    final String flutterPatchedSdkPath = artifacts.getArtifactPath(
      Artifact.flutterPatchedSdkPath,
      platform: TargetPlatform.android_arm,
      mode: BuildMode.debug,
    );
325
    processManager.addCommands(<FakeCommand>[
326
      FakeCommand(command: <String>[
327
        artifacts.getHostArtifact(HostArtifact.engineDartBinary).path,
328
        '--disable-dart-dev',
329 330
        artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk),
        '--sdk-root',
331
        '$flutterPatchedSdkPath/',
332
        '--target=flutter',
333
        '--no-print-incremental-dependencies',
334
        ...buildModeOptions(BuildMode.debug, <String>[]),
335 336 337
        '--track-widget-creation',
        '--no-link-platform',
        '--packages',
338
        '/.dart_tool/package_config.json',
339 340 341 342
        '--output-dill',
        '$build/app.dill',
        '--depfile',
        '$build/kernel_snapshot.d',
343
        'file:///lib/main.dart',
344 345 346 347 348
      ], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey /build/653e11a8e6908714056a57cd6b4f602a/app.dill 0\n'),
    ]);

    await const KernelSnapshot().build(testEnvironment);

349
    expect(processManager, hasNoRemainingExpectations);
350
  });
351

352
  testUsingContext('AotElfProfile Produces correct output directory', () async {
353
    final String build = androidEnvironment.buildDir.path;
354
    processManager.addCommands(<FakeCommand>[
355
      FakeCommand(command: <String>[
356 357 358 359 360
        artifacts.getArtifactPath(
          Artifact.genSnapshot,
          platform: TargetPlatform.android_arm,
          mode: BuildMode.profile,
        ),
361 362 363 364 365 366 367 368 369 370 371
        '--deterministic',
        kElfAot,
        '--elf=$build/app.so',
        '--strip',
        '--no-sim-use-hardfp',
        '--no-use-integer-division',
        '$build/app.dill',
      ])
    ]);
    androidEnvironment.buildDir.childFile('app.dill').createSync(recursive: true);

372
    await const AotElfProfile(TargetPlatform.android_arm).build(androidEnvironment);
373

374
    expect(processManager, hasNoRemainingExpectations);
375
  });
376

377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401
  testUsingContext('AotElfRelease configures gen_snapshot with code size directory', () async {
    androidEnvironment.defines[kCodeSizeDirectory] = 'code_size_1';
    final String build = androidEnvironment.buildDir.path;
    processManager.addCommands(<FakeCommand>[
      FakeCommand(command: <String>[
        artifacts.getArtifactPath(
          Artifact.genSnapshot,
          platform: TargetPlatform.android_arm,
          mode: BuildMode.profile,
        ),
        '--deterministic',
        '--write-v8-snapshot-profile-to=code_size_1/snapshot.android-arm.json',
        '--trace-precompiler-to=code_size_1/trace.android-arm.json',
        kElfAot,
        '--elf=$build/app.so',
        '--strip',
        '--no-sim-use-hardfp',
        '--no-use-integer-division',
        '$build/app.dill',
      ])
    ]);
    androidEnvironment.buildDir.childFile('app.dill').createSync(recursive: true);

    await const AotElfRelease(TargetPlatform.android_arm).build(androidEnvironment);

402
    expect(processManager, hasNoRemainingExpectations);
403 404
  });

405
  testUsingContext('AotElfProfile throws error if missing build mode', () async {
406
    androidEnvironment.defines.remove(kBuildMode);
407

408
    expect(const AotElfProfile(TargetPlatform.android_arm).build(androidEnvironment),
409
      throwsA(isA<MissingDefineException>()));
410
  });
411

412
  testUsingContext('AotElfProfile throws error if missing target platform', () async {
413
    androidEnvironment.defines.remove(kTargetPlatform);
414

415
    expect(const AotElfProfile(TargetPlatform.android_arm).build(androidEnvironment),
416
      throwsA(isA<MissingDefineException>()));
417
  });
418

419
  testUsingContext('AotAssemblyProfile throws error if missing build mode', () async {
420
    iosEnvironment.defines.remove(kBuildMode);
421

422
    expect(const AotAssemblyProfile().build(iosEnvironment),
423
      throwsA(isA<MissingDefineException>()));
424 425 426 427 428 429
  }, overrides: <Type, Generator>{
    Platform: () => macPlatform,
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

430

431
  testUsingContext('AotAssemblyProfile throws error if missing target platform', () async {
432
    iosEnvironment.defines.remove(kTargetPlatform);
433

434
    expect(const AotAssemblyProfile().build(iosEnvironment),
435
      throwsA(isA<MissingDefineException>()));
436 437 438 439 440
  }, overrides: <Type, Generator>{
    Platform: () => macPlatform,
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });
441

442
  testUsingContext('AotAssemblyProfile throws error if built for non-iOS platform', () async {
443
    expect(const AotAssemblyProfile().build(androidEnvironment), throwsException);
444 445 446 447 448
  }, overrides: <Type, Generator>{
    Platform: () => macPlatform,
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });
449

450
  testUsingContext('AotAssemblyProfile generates multiple arches and lipos together', () async {
451
    final String build = iosEnvironment.buildDir.path;
452
    processManager.addCommands(<FakeCommand>[
453 454
      FakeCommand(command: <String>[
        // This path is not known by the cache due to the iOS gen_snapshot split.
455
        'Artifact.genSnapshot.TargetPlatform.ios.profile_armv7',
456 457 458 459 460 461 462 463 464 465
        '--deterministic',
        kAssemblyAot,
        '--assembly=$build/armv7/snapshot_assembly.S',
        '--strip',
        '--no-sim-use-hardfp',
        '--no-use-integer-division',
        '$build/app.dill',
      ]),
      FakeCommand(command: <String>[
        // This path is not known by the cache due to the iOS gen_snapshot split.
466
        'Artifact.genSnapshot.TargetPlatform.ios.profile_arm64',
467 468 469 470 471 472 473 474 475 476 477
        '--deterministic',
        kAssemblyAot,
        '--assembly=$build/arm64/snapshot_assembly.S',
        '--strip',
        '$build/app.dill',
      ]),
      FakeCommand(command: <String>[
        'xcrun',
        'cc',
        '-arch',
        'armv7',
478
        '-miphoneos-version-min=9.0',
479
        '-isysroot',
480
        'path/to/iPhoneOS.sdk',
481 482 483 484 485 486 487 488 489 490
        '-c',
        '$build/armv7/snapshot_assembly.S',
        '-o',
        '$build/armv7/snapshot_assembly.o',
      ]),
      FakeCommand(command: <String>[
        'xcrun',
        'cc',
        '-arch',
        'arm64',
491
        '-miphoneos-version-min=9.0',
492
        '-isysroot',
493
        'path/to/iPhoneOS.sdk',
494 495 496 497 498 499 500 501 502 503
        '-c',
        '$build/arm64/snapshot_assembly.S',
        '-o',
        '$build/arm64/snapshot_assembly.o',
      ]),
      FakeCommand(command: <String>[
        'xcrun',
        'clang',
        '-arch',
        'armv7',
504
        '-miphoneos-version-min=9.0',
505 506
        '-isysroot',
        'path/to/iPhoneOS.sdk',
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
        '-dynamiclib',
        '-Xlinker',
        '-rpath',
        '-Xlinker',
        '@executable_path/Frameworks',
        '-Xlinker',
        '-rpath',
        '-Xlinker',
        '@loader_path/Frameworks',
        '-install_name',
        '@rpath/App.framework/App',
        '-o',
        '$build/armv7/App.framework/App',
        '$build/armv7/snapshot_assembly.o',
      ]),
      FakeCommand(command: <String>[
        'xcrun',
        'clang',
        '-arch',
        'arm64',
527
        '-miphoneos-version-min=9.0',
528 529
        '-isysroot',
        'path/to/iPhoneOS.sdk',
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553
        '-dynamiclib',
        '-Xlinker',
        '-rpath',
        '-Xlinker',
        '@executable_path/Frameworks',
        '-Xlinker',
        '-rpath',
        '-Xlinker',
        '@loader_path/Frameworks',
        '-install_name',
        '@rpath/App.framework/App',
        '-o',
        '$build/arm64/App.framework/App',
        '$build/arm64/snapshot_assembly.o',
      ]),
      FakeCommand(command: <String>[
        'lipo',
        '$build/armv7/App.framework/App',
        '$build/arm64/App.framework/App',
        '-create',
        '-output',
        '$build/App.framework/App',
      ]),
    ]);
554
    iosEnvironment.defines[kIosArchs] ='armv7 arm64';
555
    iosEnvironment.defines[kSdkRoot] = 'path/to/iPhoneOS.sdk';
556

557
    await const AotAssemblyProfile().build(iosEnvironment);
558

559
    expect(processManager, hasNoRemainingExpectations);
560 561 562 563 564
  }, overrides: <Type, Generator>{
    Platform: () => macPlatform,
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });
565

566
  testUsingContext('AotAssemblyProfile with bitcode sends correct argument to snapshotter (one arch)', () async {
567
    iosEnvironment.defines[kIosArchs] = 'arm64';
568
    iosEnvironment.defines[kBitcodeFlag] = 'true';
569
    iosEnvironment.defines[kSdkRoot] = 'path/to/iPhoneOS.sdk';
570
    final String build = iosEnvironment.buildDir.path;
571
    processManager.addCommands(<FakeCommand>[
572 573
      FakeCommand(command: <String>[
        // This path is not known by the cache due to the iOS gen_snapshot split.
574
        'Artifact.genSnapshot.TargetPlatform.ios.profile_arm64',
575 576 577 578 579 580 581 582 583 584 585
        '--deterministic',
        kAssemblyAot,
        '--assembly=$build/arm64/snapshot_assembly.S',
        '--strip',
        '$build/app.dill',
      ]),
      FakeCommand(command: <String>[
        'xcrun',
        'cc',
        '-arch',
        'arm64',
586
        '-miphoneos-version-min=9.0',
587
        '-isysroot',
588
        'path/to/iPhoneOS.sdk',
589 590 591 592 593 594 595 596 597 598
        // Contains bitcode flag.
        '-fembed-bitcode',
        '-c',
        '$build/arm64/snapshot_assembly.S',
        '-o',
        '$build/arm64/snapshot_assembly.o',
      ]),
      FakeCommand(command: <String>[
        'xcrun',
        'clang',
599 600
        '-arch',
        'arm64',
601
        '-miphoneos-version-min=9.0',
602 603
        '-isysroot',
        'path/to/iPhoneOS.sdk',
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631
        '-dynamiclib',
        '-Xlinker',
        '-rpath',
        '-Xlinker',
        '@executable_path/Frameworks',
        '-Xlinker',
        '-rpath',
        '-Xlinker',
        '@loader_path/Frameworks',
        '-install_name',
        '@rpath/App.framework/App',
        // Contains bitcode flag.
        '-fembed-bitcode',
        '-o',
        '$build/arm64/App.framework/App',
        '$build/arm64/snapshot_assembly.o',
      ]),
      FakeCommand(command: <String>[
        'lipo',
        '$build/arm64/App.framework/App',
        '-create',
        '-output',
        '$build/App.framework/App',
      ]),
    ]);

    await const AotAssemblyProfile().build(iosEnvironment);

632
    expect(processManager, hasNoRemainingExpectations);
633 634 635 636 637 638 639 640 641
  }, overrides: <Type, Generator>{
    Platform: () => macPlatform,
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('AotAssemblyRelease configures gen_snapshot with code size directory', () async {
    iosEnvironment.defines[kCodeSizeDirectory] = 'code_size_1';
    iosEnvironment.defines[kIosArchs] = 'arm64';
642
    iosEnvironment.defines[kSdkRoot] = 'path/to/iPhoneOS.sdk';
643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661
    iosEnvironment.defines[kBitcodeFlag] = 'true';
    final String build = iosEnvironment.buildDir.path;
    processManager.addCommands(<FakeCommand>[
      FakeCommand(command: <String>[
        // This path is not known by the cache due to the iOS gen_snapshot split.
        'Artifact.genSnapshot.TargetPlatform.ios.profile_arm64',
        '--deterministic',
        '--write-v8-snapshot-profile-to=code_size_1/snapshot.arm64.json',
        '--trace-precompiler-to=code_size_1/trace.arm64.json',
        kAssemblyAot,
        '--assembly=$build/arm64/snapshot_assembly.S',
        '--strip',
        '$build/app.dill',
      ]),
      FakeCommand(command: <String>[
        'xcrun',
        'cc',
        '-arch',
        'arm64',
662
        '-miphoneos-version-min=9.0',
663
        '-isysroot',
664
        'path/to/iPhoneOS.sdk',
665 666 667 668 669 670 671 672 673 674
        // Contains bitcode flag.
        '-fembed-bitcode',
        '-c',
        '$build/arm64/snapshot_assembly.S',
        '-o',
        '$build/arm64/snapshot_assembly.o',
      ]),
      FakeCommand(command: <String>[
        'xcrun',
        'clang',
675 676
        '-arch',
        'arm64',
677
        '-miphoneos-version-min=9.0',
678 679
        '-isysroot',
        'path/to/iPhoneOS.sdk',
680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704
        '-dynamiclib',
        '-Xlinker',
        '-rpath',
        '-Xlinker',
        '@executable_path/Frameworks',
        '-Xlinker',
        '-rpath',
        '-Xlinker',
        '@loader_path/Frameworks',
        '-install_name',
        '@rpath/App.framework/App',
        // Contains bitcode flag.
        '-fembed-bitcode',
        '-o',
        '$build/arm64/App.framework/App',
        '$build/arm64/snapshot_assembly.o',
      ]),
      FakeCommand(command: <String>[
        'lipo',
        '$build/arm64/App.framework/App',
        '-create',
        '-output',
        '$build/App.framework/App',
      ]),
    ]);
705

706
    await const AotAssemblyProfile().build(iosEnvironment);
707

708
    expect(processManager, hasNoRemainingExpectations);
709 710 711 712 713
  }, overrides: <Type, Generator>{
    Platform: () => macPlatform,
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });
714

715
  testUsingContext('kExtraGenSnapshotOptions passes values to gen_snapshot', () async {
716
    androidEnvironment.defines[kExtraGenSnapshotOptions] = 'foo,bar,baz=2';
717 718
    androidEnvironment.defines[kBuildMode] = getNameForBuildMode(BuildMode.profile);
    final String build = androidEnvironment.buildDir.path;
719

720
    processManager.addCommands(<FakeCommand>[
721
      FakeCommand(command: <String>[
722 723 724 725 726
        artifacts.getArtifactPath(
          Artifact.genSnapshot,
          platform: TargetPlatform.android_arm,
          mode: BuildMode.profile,
        ),
727
        '--deterministic',
728 729 730
        'foo',
        'bar',
        'baz=2',
731 732 733 734 735 736 737 738
        kElfAot,
        '--elf=$build/app.so',
        '--strip',
        '--no-sim-use-hardfp',
        '--no-use-integer-division',
        '$build/app.dill',
      ]),
    ]);
739

740
    await const AotElfRelease(TargetPlatform.android_arm).build(androidEnvironment);
741

742
    expect(processManager, hasNoRemainingExpectations);
743
  });
744
}