Switch to URIs for breakpoints and unskip tests on Windows (#22510)

* Switch to URIs for breakpoints and unskip tests on Windows

addBreakpointWithScriptUri expects Uris. By coincidence, FS paths work on Mac/Linux but they fail on Windows. One of the issues in the skip comment is fixed, the other one seems not relevant here.

* Apply symlink resolution to all integration tests

The default temp folders we get include symlinks which breaks breakpoints.

* Save 🙄

* Fix typo
diff --git a/packages/flutter_tools/test/integration/expression_evaluation_test.dart b/packages/flutter_tools/test/integration/expression_evaluation_test.dart
index 3648669..e594f2a 100644
--- a/packages/flutter_tools/test/integration/expression_evaluation_test.dart
+++ b/packages/flutter_tools/test/integration/expression_evaluation_test.dart
@@ -6,13 +6,13 @@
 
 import 'package:file/file.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
-import 'package:flutter_tools/src/base/platform.dart';
 
 import 'package:vm_service_client/vm_service_client.dart';
 
 import '../src/common.dart';
 import 'test_data/basic_project.dart';
 import 'test_driver.dart';
+import 'test_utils.dart';
 
 void main() {
   group('expression evaluation', () {
@@ -21,7 +21,7 @@
     FlutterTestDriver _flutter;
 
     setUp(() async {
-      tempDir = fs.systemTempDirectory.createTempSync('flutter_expression_test.');
+      tempDir = createResolvedTempDirectorySync();
       await _project.setUpIn(tempDir);
       _flutter = FlutterTestDriver(tempDir);
     });
@@ -33,13 +33,13 @@
 
     Future<VMIsolate> breakInBuildMethod(FlutterTestDriver flutter) async {
       return _flutter.breakAt(
-          _project.buildMethodBreakpointFile,
+          Uri.file(_project.buildMethodBreakpointFile),
           _project.buildMethodBreakpointLine);
     }
 
     Future<VMIsolate> breakInTopLevelFunction(FlutterTestDriver flutter) async {
       return _flutter.breakAt(
-          _project.topLevelFunctionBreakpointFile,
+          Uri.file(_project.topLevelFunctionBreakpointFile),
           _project.topLevelFunctionBreakpointLine);
     }
 
@@ -108,8 +108,5 @@
       await breakInBuildMethod(_flutter);
       await evaluateComplexReturningExpressions();
     });
-    // TODO(dantup): Unskip after flutter-tester is fixed on Windows:
-    // https://github.com/flutter/flutter/issues/17833.
-    // https://github.com/flutter/flutter/issues/21348.
-  }, timeout: const Timeout.factor(6), skip: platform.isWindows);
+  }, timeout: const Timeout.factor(6));
 }
diff --git a/packages/flutter_tools/test/integration/flutter_attach_test.dart b/packages/flutter_tools/test/integration/flutter_attach_test.dart
index 61452b7..8b5cff8 100644
--- a/packages/flutter_tools/test/integration/flutter_attach_test.dart
+++ b/packages/flutter_tools/test/integration/flutter_attach_test.dart
@@ -8,6 +8,7 @@
 import '../src/common.dart';
 import 'test_data/basic_project.dart';
 import 'test_driver.dart';
+import 'test_utils.dart';
 
 void main() {
   FlutterTestDriver _flutterRun, _flutterAttach;
@@ -15,7 +16,7 @@
   Directory tempDir;
 
   setUp(() async {
-    tempDir = fs.systemTempDirectory.createTempSync('flutter_attach_test.');
+    tempDir = createResolvedTempDirectorySync();
     await _project.setUpIn(tempDir);
     _flutterRun = FlutterTestDriver(tempDir, logPrefix: 'RUN');
     _flutterAttach = FlutterTestDriver(tempDir, logPrefix: 'ATTACH');
diff --git a/packages/flutter_tools/test/integration/flutter_run_test.dart b/packages/flutter_tools/test/integration/flutter_run_test.dart
index 7cbc97b..2f1a577 100644
--- a/packages/flutter_tools/test/integration/flutter_run_test.dart
+++ b/packages/flutter_tools/test/integration/flutter_run_test.dart
@@ -9,6 +9,7 @@
 
 import '../src/common.dart';
 import 'test_data/basic_project.dart';
+import 'test_utils.dart';
 
 void main() {
   group('flutter_run', () {
@@ -16,7 +17,7 @@
     final BasicProject _project = BasicProject();
 
     setUp(() async {
-      tempDir = fs.systemTempDirectory.createTempSync('flutter_run_integration_test.');
+      tempDir = createResolvedTempDirectorySync();
       await _project.setUpIn(tempDir);
     });
 
diff --git a/packages/flutter_tools/test/integration/hot_reload_test.dart b/packages/flutter_tools/test/integration/hot_reload_test.dart
index a2b4f12..3abe5c3 100644
--- a/packages/flutter_tools/test/integration/hot_reload_test.dart
+++ b/packages/flutter_tools/test/integration/hot_reload_test.dart
@@ -9,6 +9,7 @@
 import '../src/common.dart';
 import 'test_data/basic_project.dart';
 import 'test_driver.dart';
+import 'test_utils.dart';
 
 void main() {
   group('hot', () {
@@ -17,7 +18,7 @@
     FlutterTestDriver _flutter;
 
     setUp(() async {
-      tempDir = fs.systemTempDirectory.createTempSync('flutter_hot_reload_test_app.');
+      tempDir = createResolvedTempDirectorySync();
       await _project.setUpIn(tempDir);
       _flutter = FlutterTestDriver(tempDir);
     });
@@ -37,12 +38,10 @@
       await _flutter.hotRestart();
     });
 
-    test('reload hits breakpoints with file:// prefixes after reload', () async {
+    test('reload hits breakpoints after reload', () async {
       await _flutter.run(withDebugger: true);
-
-      // Hit breakpoint using a file:// URI.
       final VMIsolate isolate = await _flutter.breakAt(
-          Uri.file(_project.breakpointFile).toString(),
+          Uri.file(_project.breakpointFile),
           _project.breakpointLine);
       expect(isolate.pauseEvent, isInstanceOf<VMPauseBreakpointEvent>());
     });
diff --git a/packages/flutter_tools/test/integration/lifetime_test.dart b/packages/flutter_tools/test/integration/lifetime_test.dart
index 76aa644..aab6d1a 100644
--- a/packages/flutter_tools/test/integration/lifetime_test.dart
+++ b/packages/flutter_tools/test/integration/lifetime_test.dart
@@ -10,6 +10,7 @@
 import '../src/common.dart';
 import 'test_data/basic_project.dart';
 import 'test_driver.dart';
+import 'test_utils.dart';
 
 /// This duration is arbitrary but is ideally:
 /// a) long enough to ensure that if the app is crashing at startup, we notice
@@ -23,7 +24,7 @@
     Directory tempDir;
 
     setUp(() async {
-      tempDir = fs.systemTempDirectory.createTempSync('flutter_lifetime_test.');
+      tempDir = createResolvedTempDirectorySync();
       await _project.setUpIn(tempDir);
       _flutter = FlutterTestDriver(tempDir);
     });
diff --git a/packages/flutter_tools/test/integration/test_data/test_project.dart b/packages/flutter_tools/test/integration/test_data/test_project.dart
index 65637d1..0968bce 100644
--- a/packages/flutter_tools/test/integration/test_data/test_project.dart
+++ b/packages/flutter_tools/test/integration/test_data/test_project.dart
@@ -16,8 +16,8 @@
   String get main;
 
   // Valid locations for a breakpoint for tests that just need to break somewhere.
-  String get breakpointFile => fs.file(fs.path.join(
-      dir.path, 'lib', 'main.dart')).resolveSymbolicLinksSync();
+  String get breakpointFile => fs.path.join(
+      dir.path, 'lib', 'main.dart');
   int get breakpointLine => lineContaining(main, '// BREAKPOINT');
 
   Future<void> setUpIn(Directory dir) async {
diff --git a/packages/flutter_tools/test/integration/test_driver.dart b/packages/flutter_tools/test/integration/test_driver.dart
index d4a94e8..a6f535e 100644
--- a/packages/flutter_tools/test/integration/test_driver.dart
+++ b/packages/flutter_tools/test/integration/test_driver.dart
@@ -237,10 +237,10 @@
     return await vm.isolates.single.load();
   }
 
-  Future<void> addBreakpoint(String path, int line) async {
+  Future<void> addBreakpoint(Uri uri, int line) async {
     final VMIsolate isolate = await getFlutterIsolate();
-    _debugPrint('Sending breakpoint for $path:$line');
-    await isolate.addBreakpoint(path, line);
+    _debugPrint('Sending breakpoint for $uri:$line');
+    await isolate.addBreakpoint(uri, line);
   }
 
   Future<VMIsolate> waitForPause() async {
@@ -266,15 +266,15 @@
     return wait ? waitForPause() : null;
   }
 
-  Future<VMIsolate> breakAt(String path, int line, { bool restart = false }) async {
+  Future<VMIsolate> breakAt(Uri uri, int line, { bool restart = false }) async {
     if (restart) {
       // For a hot restart, we need to send the breakpoints after the restart
       // so we need to pause during the restart to avoid races.
       await hotRestart(pause: true);
-      await addBreakpoint(path, line);
+      await addBreakpoint(uri, line);
       return resume();
     } else {
-      await addBreakpoint(path, line);
+      await addBreakpoint(uri, line);
       await hotReload();
       return waitForPause();
     }
diff --git a/packages/flutter_tools/test/integration/test_utils.dart b/packages/flutter_tools/test/integration/test_utils.dart
index b75543a..a2b6eb2 100644
--- a/packages/flutter_tools/test/integration/test_utils.dart
+++ b/packages/flutter_tools/test/integration/test_utils.dart
@@ -11,6 +11,14 @@
 
 import '../src/common.dart';
 
+/// Creates a temporary directory but resolves any symlinks to return the real
+/// underlying path to avoid issues with breakpoints/hot reload.
+/// https://github.com/flutter/flutter/pull/21741
+Directory createResolvedTempDirectorySync() {
+  final Directory tempDir = fs.systemTempDirectory.createTempSync('flutter_expression_test.');
+  return fs.directory(tempDir.resolveSymbolicLinksSync());
+}
+
 void writeFile(String path, String content) {
   fs.file(path)
     ..createSync(recursive: true)