Version 0.3.5.1

svn merge -c 18295  https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@18300 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/tools/VERSION b/tools/VERSION
index da7071a..a9a13b7 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 0
 MINOR 3
 BUILD 5
-PATCH 0
+PATCH 1
diff --git a/tools/test-runtime.dart b/tools/test-runtime.dart
index 2077a06..036c861 100755
--- a/tools/test-runtime.dart
+++ b/tools/test-runtime.dart
@@ -73,8 +73,6 @@
   }
 
   var testSuites = new List<TestSuite>();
-  TestingServerRunner.setBuildDir(firstConf);
-  TestingServerRunner.setPackageRootDir(firstConf);
   for (var conf in configurations) {
     if (selectors.containsKey('co19')) {
       testSuites.add(new Co19TestSuite(conf));
diff --git a/tools/test.dart b/tools/test.dart
index da3a85e..12cff10 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -126,10 +126,6 @@
   }
 
   var testSuites = new List<TestSuite>();
-  // FIXME(kustermann,ricow): This is boken and should be fixed ASAP.
-  // Issue: 8366
-  TestingServerRunner.setBuildDir(firstConf);
-  TestingServerRunner.setPackageRootDir(firstConf);
   var maxBrowserProcesses = maxProcesses;
   for (var conf in configurations) {
     // There should not be more than one InternetExplorerDriver instance
@@ -138,6 +134,7 @@
     if (conf['runtime'].startsWith('ie')) {
       maxBrowserProcesses = 1;
     }
+    TestingServerRunner.setPackageRootDir(conf);
     for (String key in selectors.keys) {
       if (key == 'co19') {
         testSuites.add(new Co19TestSuite(conf));
diff --git a/tools/testing/dart/browser_test.dart b/tools/testing/dart/browser_test.dart
index ad9f972..6bfc93a 100644
--- a/tools/testing/dart/browser_test.dart
+++ b/tools/testing/dart/browser_test.dart
@@ -5,6 +5,8 @@
 part of test_suite;
 
 String getHtmlContents(String title,
+                       Path controllerScript,
+                       Path dartJsScript,
                        String scriptType,
                        Path sourceScript) =>
 """
@@ -22,11 +24,10 @@
 </head>
 <body>
   <h1> Running $title </h1>
-  <script type="text/javascript" src="/pkg/unittest/lib/test_controller.js">
-  </script>
+  <script type="text/javascript" src="$controllerScript"></script>
   <script type="$scriptType" src="$sourceScript" onerror="externalError(null)">
   </script>
-  <script type="text/javascript" src="/pkg/browser/lib/dart.js"></script>
+  <script type="text/javascript" src="$dartJsScript"></script>
 </body>
 </html>
 """;
@@ -47,27 +48,37 @@
 </html>
 """;
 
-String wrapDartTestInLibrary(Path testRelativeToDart) =>
+String wrapDartTestInLibrary(Path test, String testPath) =>
 """
 library libraryWrapper;
-part '/$testRelativeToDart';
+part '${pathLib.relative(test.toNativePath(),
+    from: pathLib.dirname(testPath)).replaceAll('\\', '\\\\')}';
 """;
 
-String dartTestWrapper(bool usePackageImport, String libraryPathComponent) {
+String dartTestWrapper(Path dartHome, String testPath, Path library) {
+  var testPathDir = pathLib.dirname(testPath);
+  var dartHomePath = dartHome.toNativePath();
+  // TODO(efortuna): Unify path libraries used in test.dart.
+  var unitTest = pathLib.relative(pathLib.join(dartHomePath,
+    'pkg/unittest/lib'), from: testPathDir).replaceAll('\\', '\\\\');
+
+  var libString = library.toNativePath();
+  if (!pathLib.isAbsolute(libString)) {
+    libString = pathLib.join(dartHome.toNativePath(), libString);
+  }
   // Tests inside "pkg" import unittest using "package:". All others use a
   // relative path. The imports need to agree, so use a matching form here.
-  var unitTest;
-  if (usePackageImport) {
+  if (pathLib.split(pathLib.relative(libString,
+      from: dartHome.toNativePath())).contains("pkg")) {
     unitTest = 'package:unittest';
-  } else {
-    unitTest = '/pkg/unittest/lib';
   }
   return """
 library test;
 
 import '$unitTest/unittest.dart' as unittest;
 import '$unitTest/html_config.dart' as config;
-import '$libraryPathComponent' as Test;
+import '${pathLib.relative(libString, from: testPathDir).replaceAll(
+    '\\', '\\\\')}' as Test;
 
 main() {
   config.useHtmlConfiguration();
diff --git a/tools/testing/dart/http_server.dart b/tools/testing/dart/http_server.dart
index 6966ab3..84a5b77 100644
--- a/tools/testing/dart/http_server.dart
+++ b/tools/testing/dart/http_server.dart
@@ -40,11 +40,7 @@
         .join(new Path('../../test.dart'))
         .canonicalize()
         .toNativePath();
-    // Note: args['package-root'] is always the build directory. We have the
-    // implicit assumption that it contains the 'packages' subdirectory.
-    // TODO: We should probably rename 'package-root' to 'build-directory'.
     TestingServerRunner._packageRootDir = new Path(args['package-root']);
-    TestingServerRunner._buildDirectory = new Path(args['package-root']);
     TestingServerRunner.startHttpServer('127.0.0.1',
         port: int.parse(args['port']));
     print('Server listening on port '
@@ -63,22 +59,16 @@
 class TestingServerRunner {
   static List serverList = [];
   static Path _packageRootDir = null;
-  static Path _buildDirectory = null;
 
   // Added as a getter so that the function will be called again each time the
   // default request handler closure is executed.
   static Path get packageRootDir => _packageRootDir;
-  static Path get buildDirectory => _buildDirectory;
 
   static setPackageRootDir(Map configuration) {
     _packageRootDir = TestUtils.currentWorkingDirectory.join(
         new Path(TestUtils.buildDir(configuration)));
   }
 
-  static setBuildDir(Map configuration) {
-    _buildDirectory = new Path(TestUtils.buildDir(configuration));
-  }
-
   static startHttpServer(String host, {int allowedPort:-1, int port: 0}) {
     var basePath = TestUtils.dartDir();
     var httpServer = new HttpServer();
@@ -88,23 +78,10 @@
       print('Test http server error: $e');
     };
     httpServer.defaultRequestHandler = (request, resp) {
-      // TODO(kustermann,ricow): We could change this to the following scheme:
-      // http://host:port/root_dart/X     -> $DartDir/X
-      // http://host:port/root_build/X    -> $BuildDir/X
-      // http://host:port/root_packages/X -> $BuildDir/packages/X
-      // Issue: 8368
-
       var requestPath = new Path(request.path.substring(1)).canonicalize();
       var path = basePath.join(requestPath);
       var file = new File(path.toNativePath());
-      // Since the build directory may not be located directly beneath the dart
-      // root directory (if we pass it in, e.g., for dartium testing) we serve
-      // files from the build directory explicitly. Please note that if
-      // buildDirectory has the same name as a directory inside the dart repo
-      // we will server files from the buildDirectory.
-      if (requestPath.toString().startsWith(buildDirectory.toString())) {
-        file = new File(requestPath.toNativePath());
-      }
+
       if (requestPath.segments().contains(packagesDirName)) {
         // Essentially implement the packages path rewriting, so we don't have
         // to pass environment variables to the browsers.
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 11b9ef1..894fb5a 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -812,78 +812,7 @@
     };
   }
 
-
-  /**
-   * _createUrlPathFromFile takes a [file], which is either located in the dart
-   * or in the build directory, and will return a String representing
-   * the relative path to either the dart or the build directory.
-   * Thus, the returned [String] will be the path component of the URL
-   * corresponding to [file] (the http server serves files relative to the
-   * dart/build directories).
-   */
-  String _createUrlPathFromFile(Path file) {
-    file = TestUtils.absolutePath(file);
-    var fileString = file.toString();
-    
-    var relativeBuildDir = new Path(TestUtils.buildDir(configuration));
-    var buildDir = TestUtils.absolutePath(relativeBuildDir);
-    var dartDir = TestUtils.dartDir();
-
-    var pathComponent;
-    if (fileString.startsWith(buildDir.toString())) {
-      var fileRelativeToBuildDir = file.relativeTo(buildDir);
-      pathComponent = "$relativeBuildDir/$fileRelativeToBuildDir";
-    } else if (fileString.startsWith(dartDir.toString())) {
-      pathComponent = file.relativeTo(dartDir);
-    } else {
-      // Unreachable
-      Except.isTrue(false);
-    }
-    return "/$pathComponent";
-  }
-
-  void _getUriForBrowserTest(TestInformation info,
-                            String pathComponent,
-                            subtestNames,
-                            subtestIndex) {
-    // Note: If we run test.py with the "--list" option, no http servers
-    // will be started. Therefore serverList is an empty list in this
-    // case. So we use PORT/CROSS_ORIGIN_PORT instead of real ports.
-    var serverPort = "PORT";
-    var crossOriginPort = "CROSS_ORIGIN_PORT";
-    if (!configuration['list']) {
-      serverPort = serverList[0].port.toString();
-      crossOriginPort = serverList[1].port.toString();
-    }
-
-    var url= 'http://127.0.0.1:$serverPort$pathComponent'
-        '?crossOriginPort=$crossOriginPort';
-    if (info.optionsFromFile['isMultiHtmlTest'] && subtestNames.length > 0) {
-      url= '${url}&group=${subtestNames[subtestIndex]}';
-    }
-    return url;
-  }
-
-  void _createWrapperFile(String dartWrapperFilename, dartLibraryFilename) {
-    File file = new File(dartWrapperFilename);
-    RandomAccessFile dartWrapper = file.openSync(FileMode.WRITE);
-
-    var usePackageImport = dartLibraryFilename.segments().contains("pkg");
-    var libraryPathComponent = _createUrlPathFromFile(dartLibraryFilename);
-    dartWrapper.writeStringSync(dartTestWrapper(usePackageImport,
-                                                libraryPathComponent));
-    dartWrapper.closeSync();
-  }
-
-  void _createLibraryWrapperFile(Path dartLibraryFilename, filePath) {
-    File file = new File(dartLibraryFilename.toNativePath());
-    RandomAccessFile dartLibrary = file.openSync(FileMode.WRITE);
-    dartLibrary.writeStringSync(
-        wrapDartTestInLibrary(filePath.relativeTo(TestUtils.dartDir())));
-    dartLibrary.closeSync();
-  }
-
-  /**
+ /**
    * The [StandardTestSuite] has support for tests that
    * compile a test from Dart to JavaScript, and then run the resulting
    * JavaScript.  This function creates a working directory to hold the
@@ -938,9 +867,18 @@
         if (!isLibraryDefinition) {
           dartLibraryFilename = new Path(tempDir).append(
               'test_as_library.dart');
-          _createLibraryWrapperFile(dartLibraryFilename, filePath);
+          File file = new File(dartLibraryFilename.toNativePath());
+          RandomAccessFile dartLibrary = file.openSync(FileMode.WRITE);
+          dartLibrary.writeStringSync(
+              wrapDartTestInLibrary(filePath, file.name));
+          dartLibrary.closeSync();
         }
-        _createWrapperFile(dartWrapperFilename, dartLibraryFilename);
+
+        File file = new File(dartWrapperFilename);
+        RandomAccessFile dartWrapper = file.openSync(FileMode.WRITE);
+        dartWrapper.writeStringSync(
+            dartTestWrapper(dartDir, file.name, dartLibraryFilename));
+        dartWrapper.closeSync();
       } else {
         dartWrapperFilename = filename;
         // TODO(whesse): Once test.py is retired, adjust the relative path in
@@ -957,10 +895,8 @@
         }
         htmlPath = '$tempDir/../$htmlFilename';
       }
-      String scriptPath = (compiler == 'none') ?
+      final String scriptPath = (compiler == 'none') ?
           dartWrapperFilename : compiledDartWrapperFilename;
-      scriptPath = _createUrlPathFromFile(new Path(scriptPath));
-
       // Create the HTML file for the test.
       RandomAccessFile htmlTest = new File(htmlPath).openSync(FileMode.WRITE);
       String content = null;
@@ -971,13 +907,22 @@
       Path expectedOutput = null;
       if (new File.fromPath(pngPath).existsSync()) {
         expectedOutput = pngPath;
-        content = getHtmlLayoutContents(scriptType, new Path("$scriptPath"));
+        // TODO(efortuna): Unify path libraries in test.dart.
+        content = getHtmlLayoutContents(scriptType, pathLib.relative(scriptPath,
+            from: pathLib.dirname(htmlPath)));
       } else if (new File.fromPath(txtPath).existsSync()) {
         expectedOutput = txtPath;
-        content = getHtmlLayoutContents(scriptType, new Path("$scriptPath"));
+        content = getHtmlLayoutContents(scriptType, pathLib.relative(scriptPath,
+            from: pathLib.dirname(htmlPath)));
       } else {
-        content = getHtmlContents(filename, scriptType,
-            new Path("$scriptPath"));
+        final htmlLocation = new Path(htmlPath);
+        content = getHtmlContents(
+          filename,
+          dartDir.append('pkg/unittest/lib/test_controller.js')
+              .relativeTo(htmlLocation),
+          dartDir.append('pkg/browser/lib/dart.js').relativeTo(htmlLocation),
+          scriptType,
+          new Path(scriptPath).relativeTo(htmlLocation));
       }
       htmlTest.writeStringSync(content);
       htmlTest.closeSync();
@@ -1017,11 +962,35 @@
           commandSet = [];
         }
 
-        var htmlPath_subtest = _createUrlPathFromFile(new Path(htmlPath));
-        var fullHtmlPath = _getUriForBrowserTest(info, htmlPath_subtest,
-                                                 subtestNames, subtestIndex);
-
         List<String> args = <String>[];
+        var basePath = TestUtils.dartDir().toString();
+        if (!htmlPath.startsWith('/') && !htmlPath.startsWith('http')) {
+          htmlPath = '/$htmlPath';
+        }
+        htmlPath = htmlPath.startsWith(basePath) ?
+            htmlPath.substring(basePath.length) : htmlPath;
+        String fullHtmlPath = htmlPath;
+        var searchStr = '?';
+        if (!htmlPath.startsWith('http')) {
+          // Note: If we run test.py with the "--list" option, no http servers
+          // will be started. Therefore serverList is an empty list in this
+          // case. So we use PORT/CROSS_ORIGIN_PORT instead of real ports.
+          var serverPort = "PORT";
+          var crossOriginPort = "CROSS_ORIGIN_PORT";
+          if (!configuration['list']) {
+            serverPort = serverList[0].port.toString();
+            crossOriginPort = serverList[1].port.toString();
+          }
+          fullHtmlPath = 'http://127.0.0.1:$serverPort$htmlPath${searchStr}'
+              'crossOriginPort=$crossOriginPort';
+          searchStr = '&';
+        }
+        if (info.optionsFromFile['isMultiHtmlTest']
+            && subtestNames.length > 0) {
+          fullHtmlPath = '${fullHtmlPath}${searchStr}group='
+              '${subtestNames[subtestIndex]}';
+        }
+
         if (TestUtils.usesWebDriver(runtime)) {
           args = [
               dartDir.append('tools/testing/run_selenium.py').toNativePath(),
@@ -1156,7 +1125,8 @@
     var minified = configuration['minified'] ? '-minified' : '';
     var dirName = "${configuration['compiler']}-${configuration['runtime']}"
                   "$checked$minified";
-    Path generatedTestPath = new Path(buildDir)
+    Path generatedTestPath = new Path(dartDir.toNativePath())
+        .append(buildDir)
         .append('generated_tests')
         .append(dirName)
         .append(testUniqueName);
@@ -1846,10 +1816,6 @@
       const ['d8', 'jsshell'].contains(runtime);
 
   static String buildDir(Map configuration) {
-    // FIXME(kustermann,ricow): Our code assumes that the returned 'buildDir'
-    // is relative to the current working directory.
-    // Thus, if we pass in an absolute path (e.g. '--build-directory=/tmp/out')
-    // we get into trouble.
     if (configuration['build_directory'] != '') {
       return configuration['build_directory'];
     }