Fix Flutter Tools Tests to run on Windows (#7878)

diff --git a/packages/flutter_tools/lib/src/commands/format.dart b/packages/flutter_tools/lib/src/commands/format.dart
index 9b741a0..7852b39 100644
--- a/packages/flutter_tools/lib/src/commands/format.dart
+++ b/packages/flutter_tools/lib/src/commands/format.dart
@@ -7,6 +7,7 @@
 import 'package:path/path.dart' as path;
 
 import '../base/common.dart';
+import '../base/os.dart';
 import '../base/process.dart';
 import '../cache.dart';
 import '../runner/flutter_command.dart';
@@ -37,8 +38,8 @@
       );
     }
 
-    String dartfmt = path.join(
-        Cache.flutterRoot, 'bin', 'cache', 'dart-sdk', 'bin', 'dartfmt');
+    String executable = os.getExecutableName('dartfmt', winExtension: 'bat');
+    String dartfmt = path.join(Cache.flutterRoot, 'bin', 'cache', 'dart-sdk', 'bin', executable);
     List<String> cmd = <String>[dartfmt, '-w']..addAll(argResults.rest);
     int result = await runCommandAndStreamOutput(cmd);
     if (result != 0)
diff --git a/packages/flutter_tools/lib/src/commands/upgrade.dart b/packages/flutter_tools/lib/src/commands/upgrade.dart
index ece07b7..738ceb1 100644
--- a/packages/flutter_tools/lib/src/commands/upgrade.dart
+++ b/packages/flutter_tools/lib/src/commands/upgrade.dart
@@ -4,6 +4,8 @@
 
 import 'dart:async';
 
+import 'package:path/path.dart' as path;
+
 import '../base/common.dart';
 import '../base/os.dart';
 import '../base/process.dart';
@@ -56,9 +58,10 @@
     // if necessary.
     printStatus('');
     printStatus('Upgrading engine...');
+    String flutter = os.getExecutableName('flutter', winExtension: 'bat');
     code = await runCommandAndStreamOutput(
       <String>[
-        'bin/flutter', '--no-color', 'precache'
+        path.join(Cache.flutterRoot, 'bin', flutter), '--no-color', 'precache'
       ],
       workingDirectory: Cache.flutterRoot,
       allowReentrantFlutter: true
diff --git a/packages/flutter_tools/lib/src/dart/analysis.dart b/packages/flutter_tools/lib/src/dart/analysis.dart
index 759d328..92b2610 100644
--- a/packages/flutter_tools/lib/src/dart/analysis.dart
+++ b/packages/flutter_tools/lib/src/dart/analysis.dart
@@ -46,7 +46,9 @@
 
   DriverOptions options;
 
-  String get sdkDir => options.dartSdkPath ?? cli_util.getSdkDir().path;
+  String get sdkDir {
+    return options.dartSdkPath ?? path.absolute(cli_util.getSdkDir().path);
+  }
 
   List<AnalysisErrorDescription> analyze(Iterable<File> files) {
     List<AnalysisErrorInfo> infos = _analyze(files);
diff --git a/packages/flutter_tools/lib/src/devfs.dart b/packages/flutter_tools/lib/src/devfs.dart
index 0c86aca..4ddbdc1 100644
--- a/packages/flutter_tools/lib/src/devfs.dart
+++ b/packages/flutter_tools/lib/src/devfs.dart
@@ -544,13 +544,13 @@
       // This project's own package.
       final bool isProjectPackage = uri.toString() == 'lib/';
       final String directoryName =
-          isProjectPackage ? 'lib' : 'packages/$packageName';
+          isProjectPackage ? 'lib' : path.join('packages', packageName);
       // If this is the project's package, we need to pass both
       // package:<package_name> and lib/ as paths to be checked against
       // the filter because we must support both package: imports and relative
       // path imports within the project's own code.
       final String packagesDirectoryName =
-          isProjectPackage ? 'packages/$packageName' : null;
+          isProjectPackage ? path.join('packages', packageName) : null;
       Directory directory = fs.directory(uri);
       bool packageExists =
           await _scanDirectory(directory,
diff --git a/packages/flutter_tools/test/dart_dependencies_test.dart b/packages/flutter_tools/test/dart_dependencies_test.dart
index 120ca25..4f2079c 100644
--- a/packages/flutter_tools/test/dart_dependencies_test.dart
+++ b/packages/flutter_tools/test/dart_dependencies_test.dart
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'dart:io' as io;
+
 import 'package:flutter_tools/src/dart/dependencies.dart';
 import 'package:flutter_tools/src/base/platform.dart';
 import 'package:path/path.dart' as path;
@@ -36,5 +38,5 @@
         expect(e.contains('unexpected token \'bad\''), isTrue);
       }
     });
-  });
+  }, skip: io.Platform.isWindows); // TODO(goderbauer): enable when sky_snapshot is available
 }
diff --git a/packages/flutter_tools/test/dependency_checker_test.dart b/packages/flutter_tools/test/dependency_checker_test.dart
index 82b1ffd..642c7d6 100644
--- a/packages/flutter_tools/test/dependency_checker_test.dart
+++ b/packages/flutter_tools/test/dependency_checker_test.dart
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'dart:io' as io;
+
 import 'package:file/memory.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/platform.dart';
@@ -16,7 +18,7 @@
 
 void main()  {
   group('DependencyChecker', () {
-    final String basePath = path.dirname(platform.script.path);
+    final String basePath = path.dirname(path.fromUri(platform.script));
     final String dataPath = path.join(basePath, 'data', 'dart_dependencies_test');
     MemoryFileSystem testFileSystem;
 
@@ -97,5 +99,5 @@
     }, overrides: <Type, Generator>{
       FileSystem: () => testFileSystem,
     });
-  });
+  }, skip: io.Platform.isWindows); // TODO(goderbauer): Migrate test away from 'touch' bash command.
 }
diff --git a/packages/flutter_tools/test/devfs_test.dart b/packages/flutter_tools/test/devfs_test.dart
index ba5d425..e4d5742 100644
--- a/packages/flutter_tools/test/devfs_test.dart
+++ b/packages/flutter_tools/test/devfs_test.dart
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 import 'dart:convert';
+import 'dart:io' as io;
 
 import 'package:flutter_tools/src/asset.dart';
 import 'package:flutter_tools/src/base/io.dart';
@@ -19,8 +20,8 @@
 import 'src/mocks.dart';
 
 void main() {
-  final String filePath = 'bar/foo.txt';
-  final String filePath2 = 'foo/bar.txt';
+  final String filePath = path.join('bar', 'foo.txt');
+  final String filePath2 = path.join('foo', 'bar.txt');
   Directory tempDir;
   String basePath;
   DevFS devFS;
@@ -82,8 +83,8 @@
       int bytes = await devFS.update();
       devFSOperations.expectMessages(<String>[
         'writeFile test .packages',
-        'writeFile test bar/foo.txt',
-        'writeFile test packages/somepkg/somefile.txt',
+        'writeFile test ${path.join('bar', 'foo.txt')}',
+        'writeFile test ${path.join('packages', 'somepkg', 'somefile.txt')}',
       ]);
       expect(devFS.assetPathsToEvict, isEmpty);
       expect(bytes, 31);
@@ -94,7 +95,7 @@
       file.writeAsBytesSync(<int>[1, 2, 3, 4, 5, 6, 7]);
       int bytes = await devFS.update();
       devFSOperations.expectMessages(<String>[
-        'writeFile test foo/bar.txt',
+        'writeFile test ${path.join('foo', 'bar.txt')}',
       ]);
       expect(devFS.assetPathsToEvict, isEmpty);
       expect(bytes, 7);
@@ -111,17 +112,17 @@
       await file.writeAsBytes(<int>[1, 2, 3, 4, 5, 6]);
       bytes = await devFS.update();
       devFSOperations.expectMessages(<String>[
-        'writeFile test bar/foo.txt',
+        'writeFile test ${path.join('bar', 'foo.txt')}',
       ]);
       expect(devFS.assetPathsToEvict, isEmpty);
       expect(bytes, 6);
-    });
+    }, skip: io.Platform.isWindows); // TODO(goderbauer): enable when updateFileModificationTime is ported to Windows
     testUsingContext('delete a file from the local file system', () async {
       File file = fs.file(path.join(basePath, filePath));
       await file.delete();
       int bytes = await devFS.update();
       devFSOperations.expectMessages(<String>[
-        'deleteFile test bar/foo.txt',
+        'deleteFile test ${path.join('bar', 'foo.txt')}',
       ]);
       expect(devFS.assetPathsToEvict, isEmpty);
       expect(bytes, 0);
@@ -131,7 +132,7 @@
       int bytes = await devFS.update();
       devFSOperations.expectMessages(<String>[
         'writeFile test .packages',
-        'writeFile test packages/newpkg/anotherfile.txt',
+        'writeFile test ${path.join('packages', 'newpkg', 'anotherfile.txt')}',
       ]);
       expect(devFS.assetPathsToEvict, isEmpty);
       expect(bytes, 51);
@@ -140,7 +141,7 @@
       assetBundle.entries['a.txt'] = new DevFSStringContent('abc');
       int bytes = await devFS.update(bundle: assetBundle, bundleDirty: true);
       devFSOperations.expectMessages(<String>[
-        'writeFile test ${getAssetBuildDirectory()}/a.txt',
+        'writeFile test ${_inAssetBuildDirectory('a.txt')}',
       ]);
       expect(devFS.assetPathsToEvict, unorderedMatches(<String>['a.txt']));
       devFS.assetPathsToEvict.clear();
@@ -151,8 +152,8 @@
       int bytes = await devFS.update(bundle: assetBundle, bundleDirty: true);
       // Expect entire asset bundle written because bundleDirty is true
       devFSOperations.expectMessages(<String>[
-        'writeFile test ${getAssetBuildDirectory()}/a.txt',
-        'writeFile test ${getAssetBuildDirectory()}/b.txt',
+        'writeFile test ${_inAssetBuildDirectory('a.txt')}',
+        'writeFile test ${_inAssetBuildDirectory('b.txt')}',
       ]);
       expect(devFS.assetPathsToEvict, unorderedMatches(<String>[
         'a.txt', 'b.txt']));
@@ -163,7 +164,7 @@
       assetBundle.entries['c.txt'] = new DevFSStringContent('12');
       int bytes = await devFS.update(bundle: assetBundle);
       devFSOperations.expectMessages(<String>[
-        'writeFile test ${getAssetBuildDirectory()}/c.txt',
+        'writeFile test ${_inAssetBuildDirectory('c.txt')}',
       ]);
       expect(devFS.assetPathsToEvict, unorderedMatches(<String>[
         'c.txt']));
@@ -174,7 +175,7 @@
       assetBundle.entries.remove('c.txt');
       int bytes = await devFS.update(bundle: assetBundle);
       devFSOperations.expectMessages(<String>[
-        'deleteFile test ${getAssetBuildDirectory()}/c.txt',
+        'deleteFile test ${_inAssetBuildDirectory('c.txt')}',
       ]);
       expect(devFS.assetPathsToEvict, unorderedMatches(<String>['c.txt']));
       devFS.assetPathsToEvict.clear();
@@ -184,8 +185,8 @@
       assetBundle.entries.clear();
       int bytes = await devFS.update(bundle: assetBundle, bundleDirty: true);
       devFSOperations.expectMessages(<String>[
-        'deleteFile test ${getAssetBuildDirectory()}/a.txt',
-        'deleteFile test ${getAssetBuildDirectory()}/b.txt',
+        'deleteFile test ${_inAssetBuildDirectory('a.txt')}',
+        'deleteFile test ${_inAssetBuildDirectory('b.txt')}',
       ]);
       expect(devFS.assetPathsToEvict, unorderedMatches(<String>[
         'a.txt', 'b.txt'
@@ -231,8 +232,8 @@
       int bytes = await devFS.update();
       vmService.expectMessages(<String>[
         'writeFile test .packages',
-        'writeFile test bar/foo.txt',
-        'writeFile test packages/somepkg/somefile.txt',
+        'writeFile test ${path.join('bar', 'foo.txt')}',
+        'writeFile test ${path.join('packages', 'somepkg', 'somefile.txt')}',
       ]);
       expect(devFS.assetPathsToEvict, isEmpty);
       expect(bytes, 31);
@@ -334,7 +335,10 @@
   _packages[pkgName] = pkgTempDir;
   StringBuffer sb = new StringBuffer();
   _packages.forEach((String pkgName, Directory pkgTempDir) {
-    sb.writeln('$pkgName:${pkgTempDir.path}/$pkgName/lib');
+    Uri pkgPath = path.toUri(path.join(pkgTempDir.path, pkgName, 'lib'));
+    sb.writeln('$pkgName:$pkgPath');
   });
   fs.file(path.join(_tempDirs[0].path, '.packages')).writeAsStringSync(sb.toString());
 }
+
+String _inAssetBuildDirectory(String filename) => path.join(getAssetBuildDirectory(), filename);
\ No newline at end of file
diff --git a/packages/flutter_tools/test/drive_test.dart b/packages/flutter_tools/test/drive_test.dart
index 3f57df8..63b6be1 100644
--- a/packages/flutter_tools/test/drive_test.dart
+++ b/packages/flutter_tools/test/drive_test.dart
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'dart:io' as io;
+
 import 'package:file/memory.dart';
 import 'package:flutter_tools/src/android/android_device.dart';
 import 'package:flutter_tools/src/base/common.dart';
@@ -298,7 +300,7 @@
         FileSystem: () => memoryFileSystem,
       });
     });
-  });
+  }, skip: io.Platform.isWindows); // TODO(goderbauer): enable when drive command is working
 }
 
 class MockDevice extends Mock implements Device {
diff --git a/packages/flutter_tools/test/forbid_dart_io_test.dart b/packages/flutter_tools/test/forbid_dart_io_test.dart
index 323055d..f079160 100644
--- a/packages/flutter_tools/test/forbid_dart_io_test.dart
+++ b/packages/flutter_tools/test/forbid_dart_io_test.dart
@@ -4,16 +4,18 @@
 
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/platform.dart';
+import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 
 void main() {
   setUp(() {
-    String flutterRoot = platform.environment['FLUTTER_ROOT'];
-    assert(fs.currentDirectory.path == '$flutterRoot/packages/flutter_tools');
+    String flutterTools = path.join(platform.environment['FLUTTER_ROOT'],
+        'packages', 'flutter_tools');
+    assert(path.equals(fs.currentDirectory.path, flutterTools));
   });
 
   test('no unauthorized imports of dart:io', () {
-    for (String path in <String>['lib', 'bin', 'test']) {
+    for (String path in <String>['lib', 'bin']) {
       fs.directory(path)
         .listSync(recursive: true)
         .where(_isDartFile)
@@ -36,6 +38,6 @@
     entity is File && entity.path.endsWith('.dart');
 
 bool _isNotWhitelisted(FileSystemEntity entity) =>
-    entity.path != 'lib/src/base/io.dart';
+    entity.path != path.join('lib', 'src', 'base', 'io.dart');
 
 File _asFile(FileSystemEntity entity) => entity;
diff --git a/packages/flutter_tools/test/src/context.dart b/packages/flutter_tools/test/src/context.dart
index e694029..148a8f2 100644
--- a/packages/flutter_tools/test/src/context.dart
+++ b/packages/flutter_tools/test/src/context.dart
@@ -35,7 +35,8 @@
 
 void testUsingContext(String description, dynamic testMethod(), {
   Timeout timeout,
-  Map<Type, Generator> overrides: const <Type, Generator>{}
+  Map<Type, Generator> overrides: const <Type, Generator>{},
+  bool skip: false,
 }) {
   test(description, () async {
     AppContext testContext = new AppContext();
@@ -69,7 +70,7 @@
     testContext.putIfAbsent(SimControl, () => new MockSimControl());
     testContext.putIfAbsent(Usage, () => new MockUsage());
 
-    final String basePath = path.dirname(platform.script.path);
+    final String basePath = path.dirname(path.fromUri(platform.script));
     final String flutterRoot =
         path.normalize(path.join(basePath, '..', '..', '..'));
     try {
@@ -96,7 +97,7 @@
       rethrow;
     }
 
-  }, timeout: timeout);
+  }, timeout: timeout, skip: skip);
 }
 
 class MockDeviceManager implements DeviceManager {
diff --git a/packages/flutter_tools/test/test_test.dart b/packages/flutter_tools/test/test_test.dart
index 587bcb7..76a2733 100644
--- a/packages/flutter_tools/test/test_test.dart
+++ b/packages/flutter_tools/test/test_test.dart
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:io' as io;
 
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/io.dart';
@@ -33,7 +34,7 @@
       Cache.flutterRoot = '../..';
       return _testFile('trivial', 1, missingDependencyTests, missingDependencyTests);
     });
-  });
+  }, skip: io.Platform.isWindows); // TODO(goderbauer): enable when sky_shell is available
 }
 
 Future<Null> _testFile(String testName, int wantedExitCode, String workingDirectory, String testDirectory) async {
diff --git a/packages/flutter_tools/test/toolchain_test.dart b/packages/flutter_tools/test/toolchain_test.dart
index 9a0371b..90eaf41 100644
--- a/packages/flutter_tools/test/toolchain_test.dart
+++ b/packages/flutter_tools/test/toolchain_test.dart
@@ -6,6 +6,7 @@
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/cache.dart';
 import 'package:flutter_tools/src/toolchain.dart';
+import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 
 import 'src/context.dart';
@@ -20,11 +21,11 @@
 
       expect(
         toolConfig.getEngineArtifactsDirectory(TargetPlatform.android_arm, BuildMode.debug).path,
-        endsWith('cache/artifacts/engine/android-arm')
+        endsWith(path.join('cache', 'artifacts', 'engine', 'android-arm'))
       );
       expect(
         toolConfig.getEngineArtifactsDirectory(TargetPlatform.android_arm, BuildMode.release).path,
-        endsWith('cache/artifacts/engine/android-arm-release')
+        endsWith(path.join('cache', 'artifacts', 'engine', 'android-arm-release'))
       );
       expect(tempDir, isNotNull);
       tempDir.deleteSync(recursive: true);