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

import 'dart:async';
import 'dart:convert';

import 'package:file/file.dart';
9
import 'package:file/memory.dart';
10

11 12
import 'package:flutter_tools/src/asset.dart';
import 'package:flutter_tools/src/base/file_system.dart';
13

14
import 'package:flutter_tools/src/cache.dart';
15
import 'package:flutter_tools/src/globals.dart' as globals;
16

17 18 19
import '../src/common.dart';
import '../src/context.dart';
import '../src/pubspec_schema.dart';
20 21

void main() {
22 23 24 25 26 27
  String fixPath(String path) {
    // The in-memory file system is strict about slashes on Windows being the
    // correct way so until https://github.com/google/file.dart/issues/112 is
    // fixed we fix them here.
    // TODO(dantup): Remove this function once the above issue is fixed and
    // rolls into Flutter.
28
    return path?.replaceAll('/', globals.fs.path.separator);
29
  }
30
  void writePubspecFile(String path, String name, { List<String> assets }) {
31 32 33 34
    String assetsSection;
    if (assets == null) {
      assetsSection = '';
    } else {
35
      final StringBuffer buffer = StringBuffer();
36 37 38 39 40
      buffer.write('''
flutter:
     assets:
''');

41
      for (final String asset in assets) {
42 43 44 45 46 47 48
        buffer.write('''
       - $asset
''');
      }
      assetsSection = buffer.toString();
    }

49
    globals.fs.file(fixPath(path))
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
      ..createSync(recursive: true)
      ..writeAsStringSync('''
name: $name
dependencies:
  flutter:
    sdk: flutter
$assetsSection
''');
  }

  void establishFlutterRoot() {
    Cache.flutterRoot = getFlutterRoot();
  }

  void writePackagesFile(String packages) {
65
    globals.fs.file('.packages')
66 67 68 69
      ..createSync()
      ..writeAsStringSync(packages);
  }

70
  Future<void> buildAndVerifyAssets(
71 72 73 74
    List<String> assets,
    List<String> packages,
    String expectedAssetManifest,
  ) async {
75
    final AssetBundle bundle = AssetBundleFactory.instance.createBundle();
76 77
    await bundle.build(manifestPath: 'pubspec.yaml');

78 79
    for (final String packageName in packages) {
      for (final String asset in assets) {
80
        final String entryKey = Uri.encodeFull('packages/$packageName/$asset');
81
        expect(bundle.entries.containsKey(entryKey), true, reason: 'Cannot find key on bundle: $entryKey');
82
        expect(
83
          utf8.decode(await bundle.entries[entryKey].contentsAsBytes()),
84 85 86 87 88 89
          asset,
        );
      }
    }

    expect(
90
      utf8.decode(await bundle.entries['AssetManifest.json'].contentsAsBytes()),
91 92 93 94 95
      expectedAssetManifest,
    );
  }

  void writeAssets(String path, List<String> assets) {
96
    for (final String asset in assets) {
97
      final String fullPath = fixPath(globals.fs.path.join(path, asset));
98

99
      globals.fs.file(fullPath)
100 101 102 103 104
        ..createSync(recursive: true)
        ..writeAsStringSync(asset);
    }
  }

105
  FileSystem testFileSystem;
106 107

  setUp(() async {
108
    testFileSystem = MemoryFileSystem(
109
      style: globals.platform.isWindows
110 111 112 113
        ? FileSystemStyle.windows
        : FileSystemStyle.posix,
    );
    testFileSystem.currentDirectory = testFileSystem.systemTempDirectory.createTempSync('flutter_asset_bundle_test.');
114 115
  });

116 117
  group('AssetBundle assets from packages', () {
    testUsingContext('No assets are bundled when the package has no assets', () async {
118
      establishFlutterRoot();
119
      writeEmptySchemaFile(globals.fs);
120 121 122 123 124

      writePubspecFile('pubspec.yaml', 'test');
      writePackagesFile('test_package:p/p/lib/');
      writePubspecFile('p/p/pubspec.yaml', 'test_package');

125
      final AssetBundle bundle = AssetBundleFactory.instance.createBundle();
126
      await bundle.build(manifestPath: 'pubspec.yaml');
127
      expect(bundle.entries.length, 3); // LICENSE, AssetManifest, FontManifest
128
      const String expectedAssetManifest = '{}';
129
      expect(
130
        utf8.decode(await bundle.entries['AssetManifest.json'].contentsAsBytes()),
131 132
        expectedAssetManifest,
      );
133
      expect(
134
        utf8.decode(await bundle.entries['FontManifest.json'].contentsAsBytes()),
135 136
        '[]',
      );
137 138
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
139
      ProcessManager: () => FakeProcessManager.any(),
140
    });
141

142 143
    testUsingContext('No assets are bundled when the package has an asset that is not listed', () async {
      establishFlutterRoot();
144
      writeEmptySchemaFile(globals.fs);
145 146 147 148 149 150 151 152

      writePubspecFile('pubspec.yaml', 'test');
      writePackagesFile('test_package:p/p/lib/');
      writePubspecFile('p/p/pubspec.yaml', 'test_package');

      final List<String> assets = <String>['a/foo'];
      writeAssets('p/p/', assets);

153
      final AssetBundle bundle = AssetBundleFactory.instance.createBundle();
154
      await bundle.build(manifestPath: 'pubspec.yaml');
155
      expect(bundle.entries.length, 3); // LICENSE, AssetManifest, FontManifest
156
      const String expectedAssetManifest = '{}';
157
      expect(
158
        utf8.decode(await bundle.entries['AssetManifest.json'].contentsAsBytes()),
159 160
        expectedAssetManifest,
      );
161
      expect(
162
        utf8.decode(await bundle.entries['FontManifest.json'].contentsAsBytes()),
163 164
        '[]',
      );
165 166
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
167
      ProcessManager: () => FakeProcessManager.any(),
168
    });
169 170

    testUsingContext('One asset is bundled when the package has and lists one asset its pubspec', () async {
171
      establishFlutterRoot();
172
      writeEmptySchemaFile(globals.fs);
173 174 175 176 177 178 179 180 181 182 183 184 185

      writePubspecFile('pubspec.yaml', 'test');
      writePackagesFile('test_package:p/p/lib/');

      final List<String> assets = <String>['a/foo'];
      writePubspecFile(
        'p/p/pubspec.yaml',
        'test_package',
        assets: assets,
      );

      writeAssets('p/p/', assets);

186
      const String expectedAssetManifest = '{"packages/test_package/a/foo":'
187 188 189 190 191 192
          '["packages/test_package/a/foo"]}';
      await buildAndVerifyAssets(
        assets,
        <String>['test_package'],
        expectedAssetManifest,
      );
193 194
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
195
      ProcessManager: () => FakeProcessManager.any(),
196
    });
197

198
    testUsingContext("One asset is bundled when the package has one asset, listed in the app's pubspec", () async {
199
      establishFlutterRoot();
200
      writeEmptySchemaFile(globals.fs);
201 202 203 204 205 206 207 208 209 210 211 212 213

      final List<String> assetEntries = <String>['packages/test_package/a/foo'];
      writePubspecFile(
        'pubspec.yaml',
        'test',
        assets: assetEntries,
      );
      writePackagesFile('test_package:p/p/lib/');
      writePubspecFile('p/p/pubspec.yaml', 'test_package');

      final List<String> assets = <String>['a/foo'];
      writeAssets('p/p/lib/', assets);

214
      const String expectedAssetManifest = '{"packages/test_package/a/foo":'
215 216 217 218 219 220
          '["packages/test_package/a/foo"]}';
      await buildAndVerifyAssets(
        assets,
        <String>['test_package'],
        expectedAssetManifest,
      );
221 222
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
223
      ProcessManager: () => FakeProcessManager.any(),
224
    });
225

226
    testUsingContext('One asset and its variant are bundled when the package has an asset and a variant, and lists the asset in its pubspec', () async {
227
      establishFlutterRoot();
228
      writeEmptySchemaFile(globals.fs);
229 230 231 232 233 234 235 236 237 238 239 240

      writePubspecFile('pubspec.yaml', 'test');
      writePackagesFile('test_package:p/p/lib/');
      writePubspecFile(
        'p/p/pubspec.yaml',
        'test_package',
        assets: <String>['a/foo'],
      );

      final List<String> assets = <String>['a/foo', 'a/v/foo'];
      writeAssets('p/p/', assets);

241
      const String expectedManifest = '{"packages/test_package/a/foo":'
242 243 244 245 246 247 248
          '["packages/test_package/a/foo","packages/test_package/a/v/foo"]}';

      await buildAndVerifyAssets(
        assets,
        <String>['test_package'],
        expectedManifest,
      );
249 250
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
251
      ProcessManager: () => FakeProcessManager.any(),
252
    });
253

254
    testUsingContext('One asset and its variant are bundled when the package has an asset and a variant, and the app lists the asset in its pubspec', () async {
255
      establishFlutterRoot();
256
      writeEmptySchemaFile(globals.fs);
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271

      writePubspecFile(
        'pubspec.yaml',
        'test',
        assets: <String>['packages/test_package/a/foo'],
      );
      writePackagesFile('test_package:p/p/lib/');
      writePubspecFile(
        'p/p/pubspec.yaml',
        'test_package',
      );

      final List<String> assets = <String>['a/foo', 'a/v/foo'];
      writeAssets('p/p/lib/', assets);

272
      const String expectedManifest = '{"packages/test_package/a/foo":'
273 274 275 276 277 278 279
          '["packages/test_package/a/foo","packages/test_package/a/v/foo"]}';

      await buildAndVerifyAssets(
        assets,
        <String>['test_package'],
        expectedManifest,
      );
280 281
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
282
      ProcessManager: () => FakeProcessManager.any(),
283
    });
284

285
    testUsingContext('Two assets are bundled when the package has and lists two assets in its pubspec', () async {
286
      establishFlutterRoot();
287
      writeEmptySchemaFile(globals.fs);
288 289 290 291 292 293 294 295 296 297 298 299

      writePubspecFile('pubspec.yaml', 'test');
      writePackagesFile('test_package:p/p/lib/');

      final List<String> assets = <String>['a/foo', 'a/bar'];
      writePubspecFile(
        'p/p/pubspec.yaml',
        'test_package',
        assets: assets,
      );

      writeAssets('p/p/', assets);
300
      const String expectedAssetManifest =
301 302
          '{"packages/test_package/a/bar":["packages/test_package/a/bar"],'
          '"packages/test_package/a/foo":["packages/test_package/a/foo"]}';
303 304 305 306 307 308

      await buildAndVerifyAssets(
        assets,
        <String>['test_package'],
        expectedAssetManifest,
      );
309 310
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
311
      ProcessManager: () => FakeProcessManager.any(),
312
    });
313

314
    testUsingContext("Two assets are bundled when the package has two assets, listed in the app's pubspec", () async {
315
      establishFlutterRoot();
316
      writeEmptySchemaFile(globals.fs);
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335

      final List<String> assetEntries = <String>[
        'packages/test_package/a/foo',
        'packages/test_package/a/bar',
      ];
      writePubspecFile(
        'pubspec.yaml',
        'test',
         assets: assetEntries,
      );
      writePackagesFile('test_package:p/p/lib/');

      final List<String> assets = <String>['a/foo', 'a/bar'];
      writePubspecFile(
        'p/p/pubspec.yaml',
        'test_package',
      );

      writeAssets('p/p/lib/', assets);
336
      const String expectedAssetManifest =
337 338
          '{"packages/test_package/a/bar":["packages/test_package/a/bar"],'
          '"packages/test_package/a/foo":["packages/test_package/a/foo"]}';
339 340 341 342 343 344

      await buildAndVerifyAssets(
        assets,
        <String>['test_package'],
        expectedAssetManifest,
      );
345 346
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
347
      ProcessManager: () => FakeProcessManager.any(),
348
    });
349

350
    testUsingContext('Two assets are bundled when two packages each have and list an asset their pubspec', () async {
351
      establishFlutterRoot();
352
      writeEmptySchemaFile(globals.fs);
353

354 355 356 357
      writePubspecFile(
        'pubspec.yaml',
        'test',
      );
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
      writePackagesFile('test_package:p/p/lib/\ntest_package2:p2/p/lib/');
      writePubspecFile(
        'p/p/pubspec.yaml',
        'test_package',
        assets: <String>['a/foo'],
      );
      writePubspecFile(
        'p2/p/pubspec.yaml',
        'test_package2',
        assets: <String>['a/foo'],
      );

      final List<String> assets = <String>['a/foo', 'a/v/foo'];
      writeAssets('p/p/', assets);
      writeAssets('p2/p/', assets);

374
      const String expectedAssetManifest =
375 376 377 378 379 380 381 382 383 384
          '{"packages/test_package/a/foo":'
          '["packages/test_package/a/foo","packages/test_package/a/v/foo"],'
          '"packages/test_package2/a/foo":'
          '["packages/test_package2/a/foo","packages/test_package2/a/v/foo"]}';

      await buildAndVerifyAssets(
        assets,
        <String>['test_package', 'test_package2'],
        expectedAssetManifest,
      );
385 386
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
387
      ProcessManager: () => FakeProcessManager.any(),
388
    });
389

390
    testUsingContext("Two assets are bundled when two packages each have an asset, listed in the app's pubspec", () async {
391
      establishFlutterRoot();
392
      writeEmptySchemaFile(globals.fs);
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416

      final List<String> assetEntries = <String>[
        'packages/test_package/a/foo',
        'packages/test_package2/a/foo',
      ];
      writePubspecFile(
        'pubspec.yaml',
        'test',
        assets: assetEntries,
      );
      writePackagesFile('test_package:p/p/lib/\ntest_package2:p2/p/lib/');
      writePubspecFile(
        'p/p/pubspec.yaml',
        'test_package',
      );
      writePubspecFile(
        'p2/p/pubspec.yaml',
        'test_package2',
      );

      final List<String> assets = <String>['a/foo', 'a/v/foo'];
      writeAssets('p/p/lib/', assets);
      writeAssets('p2/p/lib/', assets);

417
      const String expectedAssetManifest =
418 419 420 421 422 423 424 425 426 427
          '{"packages/test_package/a/foo":'
          '["packages/test_package/a/foo","packages/test_package/a/v/foo"],'
          '"packages/test_package2/a/foo":'
          '["packages/test_package2/a/foo","packages/test_package2/a/v/foo"]}';

      await buildAndVerifyAssets(
        assets,
        <String>['test_package', 'test_package2'],
        expectedAssetManifest,
      );
428 429
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
430
      ProcessManager: () => FakeProcessManager.any(),
431
    });
432

433
    testUsingContext('One asset is bundled when the app depends on a package, listing in its pubspec an asset from another package', () async {
434
      establishFlutterRoot();
435
      writeEmptySchemaFile(globals.fs);
436 437 438 439 440 441 442 443
      writePubspecFile(
        'pubspec.yaml',
        'test',
      );
      writePackagesFile('test_package:p/p/lib/\ntest_package2:p2/p/lib/');
      writePubspecFile(
        'p/p/pubspec.yaml',
        'test_package',
444
        assets: <String>['packages/test_package2/a/foo'],
445 446 447 448 449 450 451 452 453
      );
      writePubspecFile(
        'p2/p/pubspec.yaml',
        'test_package2',
      );

      final List<String> assets = <String>['a/foo', 'a/v/foo'];
      writeAssets('p2/p/lib/', assets);

454
      const String expectedAssetManifest =
455 456 457 458 459 460 461 462
          '{"packages/test_package2/a/foo":'
          '["packages/test_package2/a/foo","packages/test_package2/a/v/foo"]}';

      await buildAndVerifyAssets(
        assets,
        <String>['test_package2'],
        expectedAssetManifest,
      );
463 464
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
465
      ProcessManager: () => FakeProcessManager.any(),
466
    });
467
  });
468 469 470

  testUsingContext('Asset paths can contain URL reserved characters', () async {
    establishFlutterRoot();
471
    writeEmptySchemaFile(globals.fs);
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492

    writePubspecFile('pubspec.yaml', 'test');
    writePackagesFile('test_package:p/p/lib/');

    final List<String> assets = <String>['a/foo', 'a/foo[x]'];
    writePubspecFile(
      'p/p/pubspec.yaml',
      'test_package',
      assets: assets,
    );

    writeAssets('p/p/', assets);
    const String expectedAssetManifest =
        '{"packages/test_package/a/foo":["packages/test_package/a/foo"],'
        '"packages/test_package/a/foo%5Bx%5D":["packages/test_package/a/foo%5Bx%5D"]}';

    await buildAndVerifyAssets(
      assets,
      <String>['test_package'],
      expectedAssetManifest,
    );
493 494
  }, overrides: <Type, Generator>{
    FileSystem: () => testFileSystem,
495
      ProcessManager: () => FakeProcessManager.any(),
496
  });
497 498

  group('AssetBundle assets from scanned paths', () {
499
    testUsingContext('Two assets are bundled when scanning their directory', () async {
500
      establishFlutterRoot();
501
      writeEmptySchemaFile(globals.fs);
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524

      writePubspecFile('pubspec.yaml', 'test');
      writePackagesFile('test_package:p/p/lib/');

      final List<String> assetsOnDisk = <String>['a/foo', 'a/bar'];
      final List<String> assetsOnManifest = <String>['a/'];

      writePubspecFile(
        'p/p/pubspec.yaml',
        'test_package',
        assets: assetsOnManifest,
      );

      writeAssets('p/p/', assetsOnDisk);
      const String expectedAssetManifest =
          '{"packages/test_package/a/bar":["packages/test_package/a/bar"],'
          '"packages/test_package/a/foo":["packages/test_package/a/foo"]}';

      await buildAndVerifyAssets(
        assetsOnDisk,
        <String>['test_package'],
        expectedAssetManifest,
      );
525 526
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
527
      ProcessManager: () => FakeProcessManager.any(),
528 529
    });

530
    testUsingContext('Two assets are bundled when listing one and scanning second directory', () async {
531
      establishFlutterRoot();
532
      writeEmptySchemaFile(globals.fs);
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555

      writePubspecFile('pubspec.yaml', 'test');
      writePackagesFile('test_package:p/p/lib/');

      final List<String> assetsOnDisk = <String>['a/foo', 'abc/bar'];
      final List<String> assetOnManifest = <String>['a/foo', 'abc/'];

      writePubspecFile(
        'p/p/pubspec.yaml',
        'test_package',
        assets: assetOnManifest,
      );

      writeAssets('p/p/', assetsOnDisk);
      const String expectedAssetManifest =
          '{"packages/test_package/abc/bar":["packages/test_package/abc/bar"],'
          '"packages/test_package/a/foo":["packages/test_package/a/foo"]}';

      await buildAndVerifyAssets(
        assetsOnDisk,
        <String>['test_package'],
        expectedAssetManifest,
      );
556 557
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
558
      ProcessManager: () => FakeProcessManager.any(),
559 560
    });

561
    testUsingContext('One asset is bundled with variant, scanning wrong directory', () async {
562
      establishFlutterRoot();
563
      writeEmptySchemaFile(globals.fs);
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581

      writePubspecFile('pubspec.yaml', 'test');
      writePackagesFile('test_package:p/p/lib/');

      final List<String> assetsOnDisk = <String>['a/foo','a/b/foo','a/bar'];
      final List<String> assetOnManifest = <String>['a','a/bar']; // can't list 'a' as asset, should be 'a/'

      writePubspecFile(
        'p/p/pubspec.yaml',
        'test_package',
        assets: assetOnManifest,
      );

      writeAssets('p/p/', assetsOnDisk);

      final AssetBundle bundle = AssetBundleFactory.instance.createBundle();
      await bundle.build(manifestPath: 'pubspec.yaml');
      assert(bundle.entries['AssetManifest.json'] == null,'Invalid pubspec.yaml should not generate AssetManifest.json'  );
582 583
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
584
      ProcessManager: () => FakeProcessManager.any(),
585 586 587 588
    });
  });

  group('AssetBundle assets from scanned paths with MemoryFileSystem', () {
589
    testUsingContext('One asset is bundled with variant, scanning directory', () async {
590
      establishFlutterRoot();
591
      writeEmptySchemaFile(globals.fs);
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613

      writePubspecFile('pubspec.yaml', 'test');
      writePackagesFile('test_package:p/p/lib/');

      final List<String> assetsOnDisk = <String>['a/foo','a/b/foo'];
      final List<String> assetOnManifest = <String>['a/',];

      writePubspecFile(
        'p/p/pubspec.yaml',
        'test_package',
        assets: assetOnManifest,
      );

      writeAssets('p/p/', assetsOnDisk);
      const String expectedAssetManifest =
          '{"packages/test_package/a/foo":["packages/test_package/a/foo","packages/test_package/a/b/foo"]}';

      await buildAndVerifyAssets(
        assetsOnDisk,
        <String>['test_package'],
        expectedAssetManifest,
      );
614 615
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
616
      ProcessManager: () => FakeProcessManager.any(),
617 618
    });

619
    testUsingContext('No asset is bundled with variant, no assets or directories are listed', () async {
620
      establishFlutterRoot();
621
      writeEmptySchemaFile(globals.fs);
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642

      writePubspecFile('pubspec.yaml', 'test');
      writePackagesFile('test_package:p/p/lib/');

      final List<String> assetsOnDisk = <String>['a/foo', 'a/b/foo'];
      final List<String> assetOnManifest = <String>[];

      writePubspecFile(
        'p/p/pubspec.yaml',
        'test_package',
        assets: assetOnManifest,
      );

      writeAssets('p/p/', assetsOnDisk);
      const String expectedAssetManifest = '{}';

      await buildAndVerifyAssets(
        assetOnManifest,
        <String>['test_package'],
        expectedAssetManifest,
      );
643 644
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
645
      ProcessManager: () => FakeProcessManager.any(),
646 647
    });

648
    testUsingContext('Expect error generating manifest, wrong non-existing directory is listed', () async {
649
      establishFlutterRoot();
650
      writeEmptySchemaFile(globals.fs);
651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676

      writePubspecFile('pubspec.yaml', 'test');
      writePackagesFile('test_package:p/p/lib/');

      final List<String> assetOnManifest = <String>['c/'];

      writePubspecFile(
        'p/p/pubspec.yaml',
        'test_package',
        assets: assetOnManifest,
      );

      try {
        await buildAndVerifyAssets(
          assetOnManifest,
          <String>['test_package'],
          null,
        );

        final Function watchdog = () async {
          assert(false, 'Code failed to detect missing directory. Test failed.');
        };
        watchdog();
      } catch (e) {
        // Test successful
      }
677 678
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
679
      ProcessManager: () => FakeProcessManager.any(),
680 681 682
    });

  });
683
}