Make Assets more robust across platforms (#14246)

diff --git a/packages/flutter_tools/lib/src/asset.dart b/packages/flutter_tools/lib/src/asset.dart
index b3dc4f3..22b3481 100644
--- a/packages/flutter_tools/lib/src/asset.dart
+++ b/packages/flutter_tools/lib/src/asset.dart
@@ -167,7 +167,7 @@
       }
       for (_Asset variant in assetVariants[asset]) {
         assert(variant.assetFileExists);
-        entries[variant.assetEntry] = new DevFSFileContent(variant.assetFile);
+        entries[variant.entryUri.path] = new DevFSFileContent(variant.assetFile);
       }
     }
 
@@ -177,7 +177,7 @@
     }
     for (_Asset asset in materialAssets) {
       assert(asset.assetFileExists);
-      entries[asset.assetEntry] = new DevFSFileContent(asset.assetFile);
+      entries[asset.entryUri.path] = new DevFSFileContent(asset.assetFile);
     }
 
     entries[_kAssetManifestJson] = _createAssetManifest(assetVariants);
@@ -199,38 +199,34 @@
 }
 
 class _Asset {
-  _Asset({ this.base, String assetEntry, this.relativePath, this.source })
-    : _assetEntry = assetEntry;
+  _Asset({ this.baseDir, this.relativeUri, this.entryUri });
 
-  final String _assetEntry;
+  final String baseDir;
 
-  final String base;
+  /// A platform-independent Uri where this asset can be found on disk on the
+  /// host system relative to [baseDir].
+  final Uri relativeUri;
 
-  /// The entry to list in the generated asset manifest.
-  String get assetEntry => _assetEntry ?? relativePath;
-
-  /// Where the resource is on disk relative to [base].
-  final String relativePath;
-
-  final String source;
+  /// A platform-independent Uri representing the entry for the asset manifest.
+  final Uri entryUri;
 
   File get assetFile {
-    return fs.file(source != null ? '$base/$source' : '$base/$relativePath');
+    return fs.file(fs.path.join(baseDir, fs.path.fromUri(relativeUri)));
   }
 
   bool get assetFileExists => assetFile.existsSync();
 
-  /// The delta between what the assetEntry is and the relativePath (e.g.,
+  /// The delta between what the entryUri is and the relativeUri (e.g.,
   /// packages/flutter_gallery).
-  String get symbolicPrefix {
-    if (_assetEntry == null || _assetEntry == relativePath)
+  Uri get symbolicPrefixUri {
+    if (entryUri == relativeUri)
       return null;
-    final int index = _assetEntry.indexOf(relativePath);
-    return index == -1 ? null : _assetEntry.substring(0, index);
+    final int index = entryUri.path.indexOf(relativeUri.path);
+    return index == -1 ? null : new Uri(path: entryUri.path.substring(0, index));
   }
 
   @override
-  String toString() => 'asset: $assetEntry';
+  String toString() => 'asset: $entryUri';
 
   @override
   bool operator ==(dynamic other) {
@@ -239,18 +235,16 @@
     if (other.runtimeType != runtimeType)
       return false;
     final _Asset otherAsset = other;
-    return otherAsset.base == base
-        && otherAsset.assetEntry == assetEntry
-        && otherAsset.relativePath == relativePath
-        && otherAsset.source == source;
+    return otherAsset.baseDir == baseDir
+        && otherAsset.relativeUri == relativeUri
+        && otherAsset.entryUri == entryUri;
   }
 
   @override
   int get hashCode {
-    return base.hashCode
-        ^assetEntry.hashCode
-        ^relativePath.hashCode
-        ^ source.hashCode;
+    return baseDir.hashCode
+        ^relativeUri.hashCode
+        ^ entryUri.hashCode;
   }
 }
 
@@ -272,11 +266,11 @@
 
   for (Map<String, dynamic> family in _getMaterialFonts(fontSet)) {
     for (Map<String, dynamic> font in family['fonts']) {
-      final String assetKey = font['asset'];
+      final Uri entryUri = fs.path.toUri(font['asset']);
       result.add(new _Asset(
-        base: fs.path.join(Cache.flutterRoot, 'bin', 'cache', 'artifacts', 'material_fonts'),
-        source: fs.path.basename(assetKey),
-        relativePath: assetKey
+        baseDir: fs.path.join(Cache.flutterRoot, 'bin', 'cache', 'artifacts', 'material_fonts'),
+        relativeUri: new Uri(path: entryUri.pathSegments.last),
+        entryUri: entryUri
       ));
     }
   }
@@ -361,8 +355,8 @@
   for (_Asset main in assetVariants.keys) {
     final List<String> variants = <String>[];
     for (_Asset variant in assetVariants[main])
-      variants.add(variant.assetEntry);
-    json[main.assetEntry] = variants;
+      variants.add(variant.entryUri.path);
+    json[main.entryUri.path] = variants;
   }
   return new DevFSStringContent(JSON.encode(json));
 }
@@ -400,17 +394,17 @@
   for (Font font in manifest.fonts) {
     final List<FontAsset> packageFontAssets = <FontAsset>[];
     for (FontAsset fontAsset in font.fontAssets) {
-      final String assetPath = fontAsset.asset;
-      if (assetPath.startsWith('packages') &&
-          !fs.isFileSync(packageMap.map[packageName].resolve('../$assetPath').path)) {
+      final Uri assetUri = fontAsset.assetUri;
+      if (assetUri.pathSegments.first == 'packages' &&
+          !fs.isFileSync(fs.path.fromUri(packageMap.map[packageName].resolve('../${assetUri.path}')))) {
         packageFontAssets.add(new FontAsset(
-          fontAsset.asset,
+          fontAsset.assetUri,
           weight: fontAsset.weight,
           style: fontAsset.style,
         ));
       } else {
         packageFontAssets.add(new FontAsset(
-          'packages/$packageName/${fontAsset.asset}',
+          new Uri(pathSegments: <String>['packages', packageName]..addAll(assetUri.pathSegments)),
           weight: fontAsset.weight,
           style: fontAsset.style,
         ));
@@ -486,20 +480,25 @@
   final Map<_Asset, List<_Asset>> result = <_Asset, List<_Asset>>{};
 
   final _AssetDirectoryCache cache = new _AssetDirectoryCache(excludeDirs);
-  for (String assetName in flutterManifest.assets) {
+  for (Uri assetUri in flutterManifest.assets) {
     final _Asset asset = _resolveAsset(
       packageMap,
       assetBase,
-      assetName,
+      assetUri,
       packageName,
     );
     final List<_Asset> variants = <_Asset>[];
     for (String path in cache.variantsFor(asset.assetFile.path)) {
-      final String key = fs.path.relative(path, from: asset.base);
-      String assetEntry;
-      if (asset.symbolicPrefix != null)
-        assetEntry = fs.path.join(asset.symbolicPrefix, key);
-      variants.add(new _Asset(base: asset.base, assetEntry: assetEntry, relativePath: key));
+      final String relativePath = fs.path.relative(path, from: asset.baseDir);
+      final Uri relativeUri = fs.path.toUri(relativePath);
+      final Uri entryUri = asset.symbolicPrefixUri == null
+          ? relativeUri
+          : asset.symbolicPrefixUri.resolveUri(relativeUri);
+      variants.add(new _Asset(
+        baseDir: asset.baseDir,
+        entryUri: entryUri,
+        relativeUri: relativeUri,
+      ));
     }
 
     result[asset] = variants;
@@ -511,11 +510,11 @@
       final _Asset baseAsset = _resolveAsset(
         packageMap,
         assetBase,
-        fontAsset.asset,
+        fontAsset.assetUri,
         packageName,
       );
       if (!baseAsset.assetFileExists) {
-        printError('Error: unable to locate asset entry in pubspec.yaml: "${fontAsset.asset}".');
+        printError('Error: unable to locate asset entry in pubspec.yaml: "${fontAsset.assetUri}".');
         return null;
       }
 
@@ -528,47 +527,42 @@
 
 _Asset _resolveAsset(
   PackageMap packageMap,
-  String assetBase,
-  String asset,
+  String assetsBaseDir,
+  Uri assetUri,
   String packageName,
 ) {
-  if (asset.startsWith('packages/') && !fs.isFileSync(fs.path.join(assetBase, asset))) {
+  final String assetPath = fs.path.fromUri(assetUri);
+  if (assetUri.pathSegments.first == 'packages' && !fs.isFileSync(fs.path.join(assetsBaseDir, assetPath))) {
     // The asset is referenced in the pubspec.yaml as
     // 'packages/PACKAGE_NAME/PATH/TO/ASSET .
-    final _Asset packageAsset = _resolvePackageAsset(asset, packageMap);
+    final _Asset packageAsset = _resolvePackageAsset(assetUri, packageMap);
     if (packageAsset != null)
       return packageAsset;
   }
 
-  final String assetEntry = packageName != null
-    ? 'packages/$packageName/$asset' // Asset from, and declared in $packageName.
-    : null; // Asset from the current application.
-  return new _Asset(base: assetBase, assetEntry: assetEntry, relativePath: asset);
+  return new _Asset(
+    baseDir: assetsBaseDir,
+    entryUri: packageName == null
+        ? assetUri // Asset from the current application.
+        : new Uri(pathSegments: <String>['packages', packageName]..addAll(assetUri.pathSegments)), // Asset from, and declared in $packageName.
+    relativeUri: assetUri,
+  );
 }
 
-_Asset _resolvePackageAsset(String asset, PackageMap packageMap) {
-  assert(asset.startsWith('packages/'));
-  String packageKey = asset.substring('packages/'.length);
-  String relativeAsset = asset;
-
-  final int index = packageKey.indexOf('/');
-  if (index != -1) {
-    relativeAsset = packageKey.substring(index + 1);
-    packageKey = packageKey.substring(0, index);
-
-
-    final Uri uri = packageMap.map[packageKey];
-    if (uri != null && uri.scheme == 'file') {
-      final File file = fs.file(uri);
-      final String base = file.path.substring(0, file.path.length - 1);
+_Asset _resolvePackageAsset(Uri assetUri, PackageMap packageMap) {
+  assert(assetUri.pathSegments.first == 'packages');
+  if (assetUri.pathSegments.length > 1) {
+    final String packageName = assetUri.pathSegments[1];
+    final Uri packageUri = packageMap.map[packageName];
+    if (packageUri != null && packageUri.scheme == 'file') {
       return new _Asset(
-        base: base,
-        assetEntry: asset,
-        relativePath: relativeAsset,
+        baseDir: fs.path.fromUri(packageUri),
+        entryUri: assetUri,
+        relativeUri: new Uri(pathSegments: assetUri.pathSegments.sublist(2)),
       );
     }
   }
   printStatus('Error detected in pubspec.yaml:', emphasis: true);
-  printError('Could not resolve package $packageKey for asset $asset.\n');
+  printError('Could not resolve package for asset $assetUri.\n');
   return null;
 }
diff --git a/packages/flutter_tools/lib/src/flutter_manifest.dart b/packages/flutter_tools/lib/src/flutter_manifest.dart
index e26d9f1..30e5d6b 100644
--- a/packages/flutter_tools/lib/src/flutter_manifest.dart
+++ b/packages/flutter_tools/lib/src/flutter_manifest.dart
@@ -52,8 +52,8 @@
    return _flutterDescriptor['fonts'] ?? const <Map<String, dynamic>>[];
   }
 
-  List<String> get assets {
-    return _flutterDescriptor['assets'] ?? const <String>[];
+  List<Uri> get assets {
+    return _flutterDescriptor['assets']?.map(Uri.parse)?.toList() ?? const <Uri>[];
   }
 
   List<Font> _fonts;
@@ -89,7 +89,7 @@
         }
 
         fontAssets.add(new FontAsset(
-          asset,
+          Uri.parse(asset),
           weight: fontFile['weight'],
           style: fontFile['style'],
         ));
@@ -122,10 +122,10 @@
 }
 
 class FontAsset {
-  FontAsset(this.asset, {this.weight, this.style})
-    : assert(asset != null);
+  FontAsset(this.assetUri, {this.weight, this.style})
+    : assert(assetUri != null);
 
-  final String asset;
+  final Uri assetUri;
   final int weight;
   final String style;
 
@@ -137,12 +137,12 @@
     if (style != null)
       descriptor['style'] = style;
 
-    descriptor['asset'] = asset;
+    descriptor['asset'] = assetUri.path;
     return descriptor;
   }
 
   @override
-  String toString() => '$runtimeType(asset: $asset, weight; $weight, style: $style)';
+  String toString() => '$runtimeType(asset: ${assetUri.path}, weight; $weight, style: $style)';
 }
 
 Future<dynamic> _loadFlutterManifest(String manifestPath) async {
@@ -167,4 +167,4 @@
     printError(validator.errors.join('\n'));
     return false;
   }
-}
\ No newline at end of file
+}
diff --git a/packages/flutter_tools/test/asset_bundle_package_fonts_test.dart b/packages/flutter_tools/test/asset_bundle_package_fonts_test.dart
index 06d3059..509d706 100644
--- a/packages/flutter_tools/test/asset_bundle_package_fonts_test.dart
+++ b/packages/flutter_tools/test/asset_bundle_package_fonts_test.dart
@@ -6,7 +6,6 @@
 import 'dart:convert';
 
 import 'package:file/file.dart';
-import 'package:file/memory.dart';
 
 import 'package:flutter_tools/src/asset.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
@@ -92,6 +91,28 @@
       ..writeAsStringSync(font);
   }
 
+  // These tests do not use a memory file system because we want to ensure that
+  // asset bundles work correctly on Windows and Posix systems.
+  Directory tempDir;
+  Directory oldCurrentDir;
+
+  setUp(() async {
+    tempDir = await fs.systemTempDirectory.createTemp('asset_bundle_tests');
+    oldCurrentDir = fs.currentDirectory;
+    fs.currentDirectory = tempDir;
+  });
+
+  tearDown(() {
+    fs.currentDirectory = oldCurrentDir;
+    try {
+      tempDir?.deleteSync(recursive: true);
+      tempDir = null;
+    } on FileSystemException catch (e) {
+      // Do nothing, windows sometimes has trouble deleting.
+      print('Ignored exception during tearDown: $e');
+    }
+  });
+
   group('AssetBundle fonts from packages', () {
     testUsingContext('App includes neither font manifest nor fonts when no defines fonts', () async {
       establishFlutterRoot();
@@ -104,7 +125,7 @@
       await bundle.build(manifestPath: 'pubspec.yaml');
       expect(bundle.entries.length, 2); // LICENSE, AssetManifest
       expect(bundle.entries.containsKey('FontManifest.json'), false);
-    }, overrides: contextOverrides);
+    });
 
     testUsingContext('App font uses font file from package', () async {
       establishFlutterRoot();
@@ -129,7 +150,7 @@
         <String>['test_package'],
         expectedFontManifest,
       );
-    }, overrides: contextOverrides);
+    });
 
     testUsingContext('App font uses local font file and package font file', () async {
       establishFlutterRoot();
@@ -158,7 +179,7 @@
         <String>['test_package'],
         expectedFontManifest,
       );
-    }, overrides: contextOverrides);
+    });
 
     testUsingContext('App uses package font with own font file', () async {
       establishFlutterRoot();
@@ -188,7 +209,7 @@
         <String>['test_package'],
         expectedFontManifest,
       );
-    }, overrides: contextOverrides);
+    });
 
     testUsingContext('App uses package font with font file from another package', () async {
       establishFlutterRoot();
@@ -219,7 +240,7 @@
         <String>['test_package2'],
         expectedFontManifest,
       );
-    }, overrides: contextOverrides);
+    });
 
     testUsingContext('App uses package font with properties and own font file', () async {
       establishFlutterRoot();
@@ -251,7 +272,7 @@
         <String>['test_package'],
         expectedFontManifest,
       );
-    }, overrides: contextOverrides);
+    });
 
     testUsingContext('App uses local font and package font with own font file.', () async {
       establishFlutterRoot();
@@ -287,10 +308,6 @@
         <String>['test_package'],
         expectedFontManifest,
       );
-    }, overrides: contextOverrides);
+    });
   });
 }
-
-Map<Type, Generator> get contextOverrides {
-  return <Type, Generator>{FileSystem: () => new MemoryFileSystem()};
-}
diff --git a/packages/flutter_tools/test/asset_bundle_package_test.dart b/packages/flutter_tools/test/asset_bundle_package_test.dart
index 179e27c..ee40de2 100644
--- a/packages/flutter_tools/test/asset_bundle_package_test.dart
+++ b/packages/flutter_tools/test/asset_bundle_package_test.dart
@@ -6,7 +6,6 @@
 import 'dart:convert';
 
 import 'package:file/file.dart';
-import 'package:file/memory.dart';
 
 import 'package:flutter_tools/src/asset.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
@@ -93,6 +92,28 @@
     }
   }
 
+  // These tests do not use a memory file system because we want to ensure that
+  // asset bundles work correctly on Windows and Posix systems.
+  Directory tempDir;
+  Directory oldCurrentDir;
+
+  setUp(() async {
+    tempDir = await fs.systemTempDirectory.createTemp('asset_bundle_tests');
+    oldCurrentDir = fs.currentDirectory;
+    fs.currentDirectory = tempDir;
+  });
+
+  tearDown(() {
+    fs.currentDirectory = oldCurrentDir;
+    try {
+      tempDir?.deleteSync(recursive: true);
+      tempDir = null;
+    } on FileSystemException catch (e) {
+      // Do nothing, windows sometimes has trouble deleting.
+      print('Ignored exception during tearDown: $e');
+    }
+  });
+
   group('AssetBundle assets from packages', () {
     testUsingContext('No assets are bundled when the package has no assets', () async {
       establishFlutterRoot();
@@ -109,7 +130,7 @@
         UTF8.decode(await bundle.entries['AssetManifest.json'].contentsAsBytes()),
         expectedAssetManifest,
       );
-    }, overrides: contextOverrides);
+    });
 
     testUsingContext('No assets are bundled when the package has an asset that is not listed', () async {
       establishFlutterRoot();
@@ -130,7 +151,7 @@
         expectedAssetManifest,
       );
 
-    }, overrides: contextOverrides);
+    });
 
     testUsingContext('One asset is bundled when the package has and lists one asset its pubspec', () async {
       establishFlutterRoot();
@@ -154,7 +175,7 @@
         <String>['test_package'],
         expectedAssetManifest,
       );
-    }, overrides: contextOverrides);
+    });
 
     testUsingContext("One asset is bundled when the package has one asset, listed in the app's pubspec", () async {
       establishFlutterRoot();
@@ -178,7 +199,7 @@
         <String>['test_package'],
         expectedAssetManifest,
       );
-    }, overrides: contextOverrides);
+    });
 
     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 {
       establishFlutterRoot();
@@ -202,7 +223,7 @@
         <String>['test_package'],
         expectedManifest,
       );
-    }, overrides: contextOverrides);
+    });
 
     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 {
       establishFlutterRoot();
@@ -229,7 +250,7 @@
         <String>['test_package'],
         expectedManifest,
       );
-    }, overrides: contextOverrides);
+    });
 
     testUsingContext('Two assets are bundled when the package has and lists two assets in its pubspec', () async {
       establishFlutterRoot();
@@ -254,7 +275,7 @@
         <String>['test_package'],
         expectedAssetManifest,
       );
-    }, overrides: contextOverrides);
+    });
 
     testUsingContext("Two assets are bundled when the package has two assets, listed in the app's pubspec", () async {
       establishFlutterRoot();
@@ -286,7 +307,7 @@
         <String>['test_package'],
         expectedAssetManifest,
       );
-    }, overrides: contextOverrides);
+    });
 
     testUsingContext('Two assets are bundled when two packages each have and list an asset their pubspec', () async {
       establishFlutterRoot();
@@ -322,7 +343,7 @@
         <String>['test_package', 'test_package2'],
         expectedAssetManifest,
       );
-    }, overrides: contextOverrides);
+    });
 
     testUsingContext("Two assets are bundled when two packages each have an asset, listed in the app's pubspec", () async {
       establishFlutterRoot();
@@ -361,7 +382,7 @@
         <String>['test_package', 'test_package2'],
         expectedAssetManifest,
       );
-    }, overrides: contextOverrides);
+    });
 
     testUsingContext('One asset is bundled when the app depends on a package, listing in its pubspec an asset from another package', () async {
       establishFlutterRoot();
@@ -392,10 +413,6 @@
         <String>['test_package2'],
         expectedAssetManifest,
       );
-    }, overrides: contextOverrides);
+    });
   });
 }
-
-Map<Type, Generator> get contextOverrides {
-  return <Type, Generator>{FileSystem: () => new MemoryFileSystem()};
-}
diff --git a/packages/flutter_tools/test/asset_bundle_test.dart b/packages/flutter_tools/test/asset_bundle_test.dart
index 6f5fe04..57f8421 100644
--- a/packages/flutter_tools/test/asset_bundle_test.dart
+++ b/packages/flutter_tools/test/asset_bundle_test.dart
@@ -5,7 +5,6 @@
 import 'dart:convert';
 
 import 'package:file/file.dart';
-import 'package:file/memory.dart';
 
 import 'package:flutter_tools/src/asset.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
@@ -76,6 +75,28 @@
   });
 
   group('AssetBundle.build', () {
+    // These tests do not use a memory file system because we want to ensure that
+    // asset bundles work correctly on Windows and Posix systems.
+    Directory tempDir;
+    Directory oldCurrentDir;
+
+    setUp(() async {
+      tempDir = await fs.systemTempDirectory.createTemp('asset_bundle_tests');
+      oldCurrentDir = fs.currentDirectory;
+      fs.currentDirectory = tempDir;
+    });
+
+    tearDown(() {
+      fs.currentDirectory = oldCurrentDir;
+      try {
+        tempDir?.deleteSync(recursive: true);
+        tempDir = null;
+      } on FileSystemException catch (e) {
+        // Do nothing, windows sometimes has trouble deleting.
+        print('Ignored exception during tearDown: $e');
+      }
+    });
+
     test('nonempty', () async {
       final AssetBundle ab = new AssetBundle();
       expect(await ab.build(), 0);
@@ -95,7 +116,7 @@
         UTF8.decode(await bundle.entries['AssetManifest.json'].contentsAsBytes()),
         expectedAssetManifest,
       );
-    }, overrides: <Type, Generator>{FileSystem: () => new MemoryFileSystem(),});
+    });
   });
 
 }
diff --git a/packages/flutter_tools/test/asset_bundle_variant_test.dart b/packages/flutter_tools/test/asset_bundle_variant_test.dart
index fea16ce..b6c4dcb 100644
--- a/packages/flutter_tools/test/asset_bundle_variant_test.dart
+++ b/packages/flutter_tools/test/asset_bundle_variant_test.dart
@@ -5,7 +5,6 @@
 import 'dart:convert';
 
 import 'package:file/file.dart';
-import 'package:file/memory.dart';
 
 import 'package:flutter_tools/src/asset.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
@@ -17,6 +16,28 @@
 import 'src/context.dart';
 
 void main()  {
+  // These tests do not use a memory file system because we want to ensure that
+  // asset bundles work correctly on Windows and Posix systems.
+  Directory tempDir;
+  Directory oldCurrentDir;
+
+  setUp(() async {
+    tempDir = await fs.systemTempDirectory.createTemp('asset_bundle_tests');
+    oldCurrentDir = fs.currentDirectory;
+    fs.currentDirectory = tempDir;
+  });
+
+  tearDown(() {
+    fs.currentDirectory = oldCurrentDir;
+    try {
+      tempDir?.deleteSync(recursive: true);
+      tempDir = null;
+    } on FileSystemException catch (e) {
+      // Do nothing, windows sometimes has trouble deleting.
+      print('Ignored exception during tearDown: $e');
+    }
+  });
+
   group('AssetBundle asset variants', () {
     testUsingContext('main asset and variants', () async {
       // Setting flutterRoot here so that it picks up the MemoryFileSystem's
@@ -59,19 +80,17 @@
         expect(UTF8.decode(await bundle.entries[asset].contentsAsBytes()), asset);
       }
 
-      fs.file('/a/b/c/foo').deleteSync();
+      fs.file('a/b/c/foo').deleteSync();
       bundle = new AssetBundle();
       await bundle.build(manifestPath: 'pubspec.yaml');
 
       // Now the main asset file, /a/b/c/foo, does not exist. This is OK because
       // the /a/b/c/*/foo variants do exist.
-      expect(bundle.entries.containsKey('/a/b/c/foo'), false);
+      expect(bundle.entries.containsKey('a/b/c/foo'), false);
       for (String asset in assets.skip(1)) {
         expect(bundle.entries.containsKey(asset), true);
         expect(UTF8.decode(await bundle.entries[asset].contentsAsBytes()), asset);
       }
-    }, overrides: <Type, Generator>{
-      FileSystem: () => new MemoryFileSystem(),
     });
 
   });
diff --git a/packages/flutter_tools/test/flutter_manifest_test.dart b/packages/flutter_tools/test/flutter_manifest_test.dart
index 3644ad6..ee7e0e6 100644
--- a/packages/flutter_tools/test/flutter_manifest_test.dart
+++ b/packages/flutter_tools/test/flutter_manifest_test.dart
@@ -69,7 +69,9 @@
     - a/bar
 ''';
       final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest);
-      expect(flutterManifest.assets, <String>['a/foo', 'a/bar']);
+      expect(flutterManifest.assets.length, 2);
+      expect(flutterManifest.assets[0], Uri.parse('a/foo'));
+      expect(flutterManifest.assets[1], Uri.parse('a/bar'));
     });
 
     test('has one font family with one asset', () async {
@@ -97,7 +99,7 @@
       final List<FontAsset> assets = font.fontAssets;
       expect(assets.length, 1);
       final FontAsset fontAsset = assets[0];
-      expect(fontAsset.asset, 'a/bar');
+      expect(fontAsset.assetUri.path, 'a/bar');
       expect(fontAsset.weight, isNull);
       expect(fontAsset.style, isNull);
     });
@@ -130,11 +132,11 @@
       final List<FontAsset> assets = font.fontAssets;
       expect(assets.length, 2);
       final FontAsset fontAsset0 = assets[0];
-      expect(fontAsset0.asset, 'a/bar');
+      expect(fontAsset0.assetUri.path, 'a/bar');
       expect(fontAsset0.weight, isNull);
       expect(fontAsset0.style, isNull);
       final FontAsset fontAsset1 = assets[1];
-      expect(fontAsset1.asset, 'a/bar');
+      expect(fontAsset1.assetUri.path, 'a/bar');
       expect(fontAsset1.weight, 400);
       expect(fontAsset1.style, isNull);
     });
@@ -168,11 +170,11 @@
       final List<FontAsset> assets = font.fontAssets;
       expect(assets.length, 2);
       final FontAsset fontAsset0 = assets[0];
-      expect(fontAsset0.asset, 'a/bar');
+      expect(fontAsset0.assetUri.path, 'a/bar');
       expect(fontAsset0.weight, isNull);
       expect(fontAsset0.style, isNull);
       final FontAsset fontAsset1 = assets[1];
-      expect(fontAsset1.asset, 'a/bar');
+      expect(fontAsset1.assetUri.path, 'a/bar');
       expect(fontAsset1.weight, 400);
       expect(fontAsset1.style, 'italic');
     });
@@ -214,11 +216,11 @@
       final List<FontAsset> fooAassets = fooFont.fontAssets;
       expect(fooAassets.length, 2);
       final FontAsset fooFontAsset0 = fooAassets[0];
-      expect(fooFontAsset0.asset, 'a/bar');
+      expect(fooFontAsset0.assetUri.path, 'a/bar');
       expect(fooFontAsset0.weight, isNull);
       expect(fooFontAsset0.style, isNull);
       final FontAsset fooFontAsset1 = fooAassets[1];
-      expect(fooFontAsset1.asset, 'a/bar');
+      expect(fooFontAsset1.assetUri.path, 'a/bar');
       expect(fooFontAsset1.weight, 400);
       expect(fooFontAsset1.style, 'italic');
 
@@ -229,11 +231,11 @@
       final List<FontAsset> barAssets = barFont.fontAssets;
       expect(barAssets.length, 2);
       final FontAsset barFontAsset0 = barAssets[0];
-      expect(barFontAsset0.asset, 'a/baz');
+      expect(barFontAsset0.assetUri.path, 'a/baz');
       expect(barFontAsset0.weight, isNull);
       expect(barFontAsset0.style, isNull);
       final FontAsset barFontAsset1 = barAssets[1];
-      expect(barFontAsset1.asset, 'a/baz');
+      expect(barFontAsset1.assetUri.path, 'a/baz');
       expect(barFontAsset1.weight, 400);
       expect(barFontAsset1.style, 'italic');
     });
@@ -274,11 +276,11 @@
       final List<FontAsset> fooAassets = fooFont.fontAssets;
       expect(fooAassets.length, 2);
       final FontAsset fooFontAsset0 = fooAassets[0];
-      expect(fooFontAsset0.asset, 'a/bar');
+      expect(fooFontAsset0.assetUri.path, 'a/bar');
       expect(fooFontAsset0.weight, isNull);
       expect(fooFontAsset0.style, isNull);
       final FontAsset fooFontAsset1 = fooAassets[1];
-      expect(fooFontAsset1.asset, 'a/bar');
+      expect(fooFontAsset1.assetUri.path, 'a/bar');
       expect(fooFontAsset1.weight, 400);
       expect(fooFontAsset1.style, 'italic');
     });
@@ -314,11 +316,11 @@
       final List<FontAsset> fooAassets = fooFont.fontAssets;
       expect(fooAassets.length, 2);
       final FontAsset fooFontAsset0 = fooAassets[0];
-      expect(fooFontAsset0.asset, 'a/bar');
+      expect(fooFontAsset0.assetUri.path, 'a/bar');
       expect(fooFontAsset0.weight, isNull);
       expect(fooFontAsset0.style, isNull);
       final FontAsset fooFontAsset1 = fooAassets[1];
-      expect(fooFontAsset1.asset, 'a/bar');
+      expect(fooFontAsset1.assetUri.path, 'a/bar');
       expect(fooFontAsset1.weight, 400);
       expect(fooFontAsset1.style, 'italic');
     });