Create generated tests inside the build directory

Patch Set 1 is a revert of r18295.

Review URL: https://codereview.chromium.org//12223074

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@18802 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
kustermann@google.com 2013-02-21 08:10:37 +00:00
parent 9a6210c6e6
commit d2c575c0b0
11 changed files with 305 additions and 871 deletions

View file

@ -21,7 +21,7 @@ var url = '';
main() {
useHtmlConfiguration();
url = "http://localhost:${window.location.port}/pkg/intl/lib/src/data/dates/";
url = "http://localhost:${window.location.port}/root_dart/pkg/intl/lib/src/data/dates/";
// Initialize one locale just so we know what the list is.
test('Run everything', () {
initializeDateFormatting("en_US", url).then(expectAsync1(runEverything));});

View file

@ -4,8 +4,8 @@ dom-modify-html.html and others in the dromaeo tests directory. -->
<html>
<head>
<script type="application/dart" src="dromaeo_noop/dromaeo_smoke.dart"></script>
<script src='../../pkg/browser/lib/dart.js'></script>
<script src='../../samples/third_party/dromaeo/htmlrunner.js'></script>
<script src='/root_dart/pkg/browser/lib/dart.js'></script>
<script src='/root_dart/samples/third_party/dromaeo/htmlrunner.js'></script>
</head>
<body>
</body>

View file

@ -24,7 +24,7 @@ void main() {
useHtmlConfiguration();
var scriptSrc = new ScriptElement();
scriptSrc.src = '../../../../pkg/browser/lib/dart.js';
scriptSrc.src = '/root_dart/pkg/browser/lib/dart.js';
document.head.children.add(scriptSrc);
document.body.innerHtml = '''${document.body.innerHtml}
<div id="main">

View file

@ -30,7 +30,8 @@ main() {
var port = crossOriginPort;
test('XHR Cross-domain', () {
var url = "http://localhost:$port/tests/html/xhr_cross_origin_data.txt";
var url = "http://localhost:$port/"
"root_dart/tests/html/xhr_cross_origin_data.txt";
var xhr = new HttpRequest();
xhr.open('GET', url, true);
var validate = expectAsync1((data) {
@ -49,7 +50,8 @@ main() {
});
test('XHR.get Cross-domain', () {
var url = "http://localhost:$port/tests/html/xhr_cross_origin_data.txt";
var url = "http://localhost:$port/"
"root_dart/tests/html/xhr_cross_origin_data.txt";
HttpRequest.request(url).then(expectAsync1((xhr) {
var data = json.parse(xhr.response);
expect(data, contains('feed'));
@ -59,7 +61,8 @@ main() {
});
test('XHR.getWithCredentials Cross-domain', () {
var url = "http://localhost:$port/tests/html/xhr_cross_origin_data.txt";
var url = "http://localhost:$port/"
"root_dart/tests/html/xhr_cross_origin_data.txt";
HttpRequest.request(url, withCredentials: true).then(expectAsync1((xhr) {
var data = json.parse(xhr.response);
expect(data, contains('feed'));

View file

@ -17,7 +17,7 @@ void fail(message) {
main() {
useHtmlIndividualConfiguration();
var url = "/tests/html/xhr_cross_origin_data.txt";
var url = "/root_dart/tests/html/xhr_cross_origin_data.txt";
void validate200Response(xhr) {
expect(xhr.status, equals(200));

View file

@ -73,6 +73,8 @@ main() {
}
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));

View file

@ -126,6 +126,10 @@ main() {
}
var testSuites = new List<TestSuite>();
// FIXME(kustermann,ricow): This is broken 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
@ -134,7 +138,6 @@ main() {
if (conf['runtime'].startsWith('ie')) {
maxBrowserProcesses = 1;
}
TestingServerRunner.setPackageRootDir(conf);
for (String key in selectors.keys) {
if (key == 'co19') {
testSuites.add(new Co19TestSuite(conf));

View file

@ -5,8 +5,6 @@
part of test_suite;
String getHtmlContents(String title,
Path controllerScript,
Path dartJsScript,
String scriptType,
Path sourceScript) =>
"""
@ -24,10 +22,13 @@ String getHtmlContents(String title,
</head>
<body>
<h1> Running $title </h1>
<script type="text/javascript" src="$controllerScript"></script>
<script type="text/javascript"
src="/root_dart/pkg/unittest/lib/test_controller.js">
</script>
<script type="$scriptType" src="$sourceScript" onerror="externalError(null)">
</script>
<script type="text/javascript" src="$dartJsScript"></script>
<script type="text/javascript"
src="/root_dart/pkg/browser/lib/dart.js"></script>
</body>
</html>
""";
@ -48,37 +49,27 @@ String getHtmlLayoutContents(String scriptType, String sourceScript) =>
</html>
""";
String wrapDartTestInLibrary(Path test, String testPath) =>
String wrapDartTestInLibrary(Path testRelativeToDart) =>
"""
library libraryWrapper;
part '${pathLib.relative(test.toNativePath(),
from: pathLib.dirname(testPath)).replaceAll('\\', '\\\\')}';
part '/$testRelativeToDart';
""";
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);
}
String dartTestWrapper(bool usePackageImport, String libraryPathComponent) {
// Tests inside "pkg" import unittest using "package:". All others use a
// relative path. The imports need to agree, so use a matching form here.
if (pathLib.split(pathLib.relative(libString,
from: dartHome.toNativePath())).contains("pkg")) {
var unitTest;
if (usePackageImport) {
unitTest = 'package:unittest';
} else {
unitTest = '/root_dart/pkg/unittest/lib';
}
return """
library test;
import '$unitTest/unittest.dart' as unittest;
import '$unitTest/html_config.dart' as config;
import '${pathLib.relative(libString, from: testPathDir).replaceAll(
'\\', '\\\\')}' as Test;
import '$libraryPathComponent' as Test;
main() {
config.useHtmlConfiguration();

View file

@ -4,6 +4,7 @@
library http_server;
import 'dart:async';
import 'dart:io';
import 'dart:isolate';
import 'dart:uri';
@ -12,6 +13,30 @@ import 'test_suite.dart'; // For TestUtils.
// expected number of arguments, so test.dart doesn't rely on the args library?
// See discussion on https://codereview.chromium.org/11931025/.
import 'vendored_pkg/args/args.dart';
import 'utils.dart';
/// Interface of the HTTP server:
///
/// /echo: This will stream the data received in the request stream back
/// to the client.
/// /root_dart/X: This will serve the corresponding file from the dart
/// directory (i.e. '$DartDirectory/X').
/// /root_build/X: This will serve the corresponding file from the build
/// directory (i.e. '$BuildDirectory/X').
/// /FOO/packages/BAR: This will serve the corresponding file from the packages
/// directory (i.e. '$BuildDirectory/packages/BAR')
///
/// In case a path does not refer to a file but rather to a directory, a
/// directory listing will be displayed.
const PREFIX_BUILDDIR = 'root_build';
const PREFIX_DARTDIR = 'root_dart';
// TODO(kustermann,ricow): We could change this to the following scheme:
// http://host:port/root_packages/X -> $BuildDir/packages/X
// Issue: 8368
main() {
/** Convenience method for local testing. */
@ -43,7 +68,11 @@ main() {
.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']);
var network = args['network'];
TestingServerRunner.startHttpServer(network,
port: int.parse(args['port']));
@ -63,98 +92,129 @@ main() {
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(
_packageRootDir = TestUtils.absolutePath(
new Path(TestUtils.buildDir(configuration)));
}
static setBuildDir(Map configuration) {
_buildDirectory = TestUtils.absolutePath(
new Path(TestUtils.buildDir(configuration)));
}
static startHttpServer(String host, {int allowedPort:-1, int port: 0}) {
var basePath = TestUtils.dartDir();
var httpServer = new HttpServer();
var packagesDirName = 'packages';
httpServer.onError = (e) {
// TODO(ricow): Once we have a debug log we should write this out there.
print('Test http server error: $e');
DebugLogger.error('HttpServer: an error occured: $e');
};
httpServer.defaultRequestHandler = (request, resp) {
var requestPath = new Path(request.path.substring(1)).canonicalize();
var path = basePath.join(requestPath);
var file = new File(path.toNativePath());
if (requestPath.segments().contains(packagesDirName)) {
// Essentially implement the packages path rewriting, so we don't have
// to pass environment variables to the browsers.
var requestPathStr = requestPath.toNativePath().substring(
requestPath.toNativePath().indexOf(packagesDirName));
path = packageRootDir.append(requestPathStr);
file = new File(path.toNativePath());
}
file.exists().then((exists) {
if (exists) {
if (allowedPort != -1) {
if (request.headers.value('Origin') != null) {
var origin = new Uri(request.headers.value('Origin'));
// Allow loading from http://*:$allowedPort in browsers.
var allowedOrigin =
'${origin.scheme}://${origin.domain}:${allowedPort}';
resp.headers.set("Access-Control-Allow-Origin", allowedOrigin);
resp.headers.set('Access-Control-Allow-Credentials', 'true');
}
} else {
// No allowedPort specified. Allow from anywhere (but cross-origin
// requests *with credentials* will fail because you can't use "*").
resp.headers.set("Access-Control-Allow-Origin", "*");
}
if (path.toNativePath().endsWith('.html')) {
resp.headers.set('Content-Type', 'text/html');
} else if (path.toNativePath().endsWith('.js')) {
resp.headers.set('Content-Type', 'application/javascript');
} else if (path.toNativePath().endsWith('.dart')) {
resp.headers.set('Content-Type', 'application/dart');
}
file.openInputStream().pipe(resp.outputStream);
} else {
var directory = new Directory.fromPath(path);
directory.exists().then((exists) {
if (!exists) {
sendNotFound(resp);
} else {
sendDirectoryListing(directory, request, resp);
}
});
}
});
httpServer.defaultRequestHandler = (request, response) {
handleFileOrDirectoryRequest(request, response, allowedPort);
};
// Echos back the contents of the request as the response data.
httpServer.addRequestHandler((req) => req.path == "/echo", (request, resp) {
resp.headers.set("Access-Control-Allow-Origin", "*");
request.inputStream.pipe(resp.outputStream);
});
httpServer.addRequestHandler(
(req) => req.path == "/echo", handleEchoRequest);
httpServer.listen(host, port);
serverList.add(httpServer);
}
static void sendNotFound(HttpResponse response) {
response.statusCode = HttpStatus.NOT_FOUND;
try {
response.outputStream.close();
} catch (e) {
if (e is StreamException) {
print('Test http_server error closing the response stream: $e');
static void handleFileOrDirectoryRequest(HttpRequest request,
HttpResponse response,
int allowedPort) {
var path = getFilePathFromRequestPath(request.path);
if (path != null) {
var file = new File.fromPath(path);
file.exists().then((exists) {
if (exists) {
sendFileContent(request, response, allowedPort, path, file);
} else {
var directory = new Directory.fromPath(path);
directory.exists().then((exists) {
if (exists) {
listDirectory(directory).then((entries) {
sendDirectoryListing(entries, request, response);
});
} else {
sendNotFound(request, response);
}
});
}
});
} else {
if (request.path == '/') {
var entries = [new _Entry('root_dart', 'root_dart/'),
new _Entry('root_build', 'root_build/'),
new _Entry('echo', 'echo')];
sendDirectoryListing(entries, request, response);
} else {
throw e;
sendNotFound(request, response);
}
}
}
static void handleEchoRequest(HttpRequest request, HttpResponse response) {
response.headers.set("Access-Control-Allow-Origin", "*");
request.inputStream.pipe(response.outputStream);
}
static Path getFilePathFromRequestPath(String urlRequestPath) {
// Go to the top of the file to see an explanation of the URL path scheme.
var requestPath = new Path(urlRequestPath.substring(1)).canonicalize();
var pathSegments = requestPath.segments();
if (pathSegments.length > 0) {
var basePath;
var relativePath;
if (pathSegments[0] == PREFIX_BUILDDIR) {
basePath = _buildDirectory;
relativePath = new Path(
pathSegments.getRange(1, pathSegments.length - 1).join('/'));
} else if (pathSegments[0] == PREFIX_DARTDIR) {
basePath = TestUtils.dartDir();
relativePath = new Path(
pathSegments.getRange(1, pathSegments.length - 1).join('/'));
}
var packagesDirName = 'packages';
var packagesIndex = pathSegments.indexOf(packagesDirName);
if (packagesIndex != -1) {
var start = packagesIndex + 1;
var length = pathSegments.length - start;
basePath = _packageRootDir.append(packagesDirName);
relativePath = new Path(
pathSegments.getRange(start, length).join('/'));
}
if (basePath != null && relativePath != null) {
return basePath.join(relativePath);
}
}
return null;
}
static Future<List<_Entry>> listDirectory(Directory directory) {
var completer = new Completer();
var entries = [];
directory.list()
..onFile = (filepath) {
var filename = new Path(filepath).filename;
entries.add(new _Entry(filename, filename));
}
..onDir = (dirpath) {
var filename = new Path(dirpath).filename;
entries.add(new _Entry(filename, '$filename/'));
}
..onDone = (_) {
completer.complete(entries);
};
return completer.future;
}
/**
* Sends a simple listing of all the files and sub-directories within
* directory.
@ -162,8 +222,9 @@ class TestingServerRunner {
* This is intended to make it easier to browse tests when manually running
* tests against this test server.
*/
static void sendDirectoryListing(Directory directory, HttpRequest request,
HttpResponse response) {
static void sendDirectoryListing(entries,
HttpRequest request,
HttpResponse response) {
response.headers.set('Content-Type', 'text/html');
var header = '''<!DOCTYPE html>
<html>
@ -181,30 +242,62 @@ class TestingServerRunner {
</body>
</html>''';
var entries = [];
directory.list()
..onFile = (filepath) {
var filename = new Path(filepath).filename;
entries.add(new _Entry(filename, filename));
}
..onDir = (dirpath) {
var filename = new Path(dirpath).filename;
entries.add(new _Entry(filename, '$filename/'));
}
..onDone = (_) {
var requestPath = new Path.raw(request.path);
entries.sort();
entries.sort();
response.outputStream.writeString(header);
for (var entry in entries) {
response.outputStream.writeString(
'<li><a href="${new Path(request.path).append(entry.name)}">'
'${entry.displayName}</a></li>');
}
response.outputStream.writeString(footer);
response.outputStream.close();
}
response.outputStream.writeString(header);
for (var entry in entries) {
response.outputStream.writeString(
'<li><a href="${requestPath.append(entry.name)}">'
'${entry.displayName}</a></li>');
}
response.outputStream.writeString(footer);
response.outputStream.close();
};
static void sendFileContent(HttpRequest request,
HttpResponse response,
int allowedPort,
Path path,
File file) {
if (allowedPort != -1) {
var origin = new Uri(request.headers.value('Origin'));
// Allow loading from http://*:$allowedPort in browsers.
var allowedOrigin =
'${origin.scheme}://${origin.domain}:${allowedPort}';
response.headers.set("Access-Control-Allow-Origin", allowedOrigin);
response.headers.set('Access-Control-Allow-Credentials', 'true');
} else {
// No allowedPort specified. Allow from anywhere (but cross-origin
// requests *with credentials* will fail because you can't use "*").
response.headers.set("Access-Control-Allow-Origin", "*");
}
if (path.filename.endsWith('.html')) {
response.headers.set('Content-Type', 'text/html');
} else if (path.filename.endsWith('.js')) {
response.headers.set('Content-Type', 'application/javascript');
} else if (path.filename.endsWith('.dart')) {
response.headers.set('Content-Type', 'application/dart');
}
file.openInputStream().pipe(response.outputStream);
}
static void sendNotFound(HttpRequest request, HttpResponse response) {
// NOTE: Since some tests deliberately try to access non-existent files.
// We might want to remove this warning (otherwise it will show
// up in the debug.log every time).
DebugLogger.warning('HttpServer: could not find file for request path: '
'"${request.path}"');
response.statusCode = HttpStatus.NOT_FOUND;
try {
response.outputStream.close();
} catch (e) {
if (e is StreamException) {
DebugLogger.warning('HttpServer: error while closing the response '
'stream: $e');
} else {
throw e;
}
}
}
static terminateHttpServers() {

View file

@ -23,9 +23,7 @@ import "multitest.dart";
import "status_file_parser.dart";
import "test_runner.dart";
import "utils.dart";
// TODO(efortuna,whess): Remove this import.
import 'vendored_pkg/path/path.dart' as pathLib;
import "http_server.dart" show PREFIX_BUILDDIR, PREFIX_DARTDIR;
part "browser_test.dart";
@ -812,7 +810,77 @@ class StandardTestSuite extends TestSuite {
};
}
/**
/**
* _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 relativeBuildDir = new Path(TestUtils.buildDir(configuration));
var buildDir = TestUtils.absolutePath(relativeBuildDir);
var dartDir = TestUtils.absolutePath(TestUtils.dartDir());
var fileString = file.toString();
if (fileString.startsWith(buildDir.toString())) {
var fileRelativeToBuildDir = file.relativeTo(buildDir);
return "/$PREFIX_BUILDDIR/$fileRelativeToBuildDir";
} else if (fileString.startsWith(dartDir.toString())) {
var fileRelativeToDartDir = file.relativeTo(dartDir);
return "/$PREFIX_DARTDIR/$fileRelativeToDartDir";
}
// Unreachable
Except.fail('This should be unreachable.');
}
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);
var requestPath = new Path(PREFIX_DARTDIR)
.join(filePath.relativeTo(TestUtils.dartDir()));
dartLibrary.writeStringSync(wrapDartTestInLibrary(requestPath));
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
@ -867,18 +935,9 @@ class StandardTestSuite extends TestSuite {
if (!isLibraryDefinition) {
dartLibraryFilename = new Path(tempDir).append(
'test_as_library.dart');
File file = new File(dartLibraryFilename.toNativePath());
RandomAccessFile dartLibrary = file.openSync(FileMode.WRITE);
dartLibrary.writeStringSync(
wrapDartTestInLibrary(filePath, file.name));
dartLibrary.closeSync();
_createLibraryWrapperFile(dartLibraryFilename, filePath);
}
File file = new File(dartWrapperFilename);
RandomAccessFile dartWrapper = file.openSync(FileMode.WRITE);
dartWrapper.writeStringSync(
dartTestWrapper(dartDir, file.name, dartLibraryFilename));
dartWrapper.closeSync();
_createWrapperFile(dartWrapperFilename, dartLibraryFilename);
} else {
dartWrapperFilename = filename;
// TODO(whesse): Once test.py is retired, adjust the relative path in
@ -895,8 +954,10 @@ class StandardTestSuite extends TestSuite {
}
htmlPath = '$tempDir/../$htmlFilename';
}
final String scriptPath = (compiler == 'none') ?
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;
@ -907,22 +968,13 @@ class StandardTestSuite extends TestSuite {
Path expectedOutput = null;
if (new File.fromPath(pngPath).existsSync()) {
expectedOutput = pngPath;
// TODO(efortuna): Unify path libraries in test.dart.
content = getHtmlLayoutContents(scriptType, pathLib.relative(scriptPath,
from: pathLib.dirname(htmlPath)));
content = getHtmlLayoutContents(scriptType, new Path("$scriptPath"));
} else if (new File.fromPath(txtPath).existsSync()) {
expectedOutput = txtPath;
content = getHtmlLayoutContents(scriptType, pathLib.relative(scriptPath,
from: pathLib.dirname(htmlPath)));
content = getHtmlLayoutContents(scriptType, new Path("$scriptPath"));
} else {
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));
content = getHtmlContents(filename, scriptType,
new Path("$scriptPath"));
}
htmlTest.writeStringSync(content);
htmlTest.closeSync();
@ -962,35 +1014,11 @@ class StandardTestSuite extends TestSuite {
commandSet = [];
}
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]}';
}
var htmlPath_subtest = _createUrlPathFromFile(new Path(htmlPath));
var fullHtmlPath = _getUriForBrowserTest(info, htmlPath_subtest,
subtestNames, subtestIndex);
List<String> args = <String>[];
if (TestUtils.usesWebDriver(runtime)) {
args = [
dartDir.append('tools/testing/run_selenium.py').toNativePath(),
@ -1125,8 +1153,7 @@ class StandardTestSuite extends TestSuite {
var minified = configuration['minified'] ? '-minified' : '';
var dirName = "${configuration['compiler']}-${configuration['runtime']}"
"$checked$minified";
Path generatedTestPath = new Path(dartDir.toNativePath())
.append(buildDir)
Path generatedTestPath = new Path(buildDir)
.append('generated_tests')
.append(dirName)
.append(testUniqueName);
@ -1816,6 +1843,10 @@ class TestUtils {
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'];
}

View file

@ -1,689 +0,0 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/// A comprehensive, cross-platform path manipulation library.
library path;
import 'dart:io' as io;
/// An internal builder for the current OS so we can provide a straight
/// functional interface and not require users to create one.
final _builder = new Builder();
/// Gets the path to the current working directory.
String get current => new io.Directory.current().path;
/// Gets the path separator for the current platform. On Mac and Linux, this
/// is `/`. On Windows, it's `\`.
String get separator => _builder.separator;
/// Converts [path] to an absolute path by resolving it relative to the current
/// working directory. If [path] is already an absolute path, just returns it.
///
/// path.absolute('foo/bar.txt'); // -> /your/current/dir/foo/bar.txt
String absolute(String path) => join(current, path);
/// Gets the part of [path] after the last separator.
///
/// path.basename('path/to/foo.dart'); // -> 'foo.dart'
/// path.basename('path/to'); // -> 'to'
///
/// Trailing separators are ignored.
///
/// builder.dirname('path/to/'); // -> 'to'
String basename(String path) => _builder.basename(path);
/// Gets the part of [path] after the last separator, and without any trailing
/// file extension.
///
/// path.basenameWithoutExtension('path/to/foo.dart'); // -> 'foo'
///
/// Trailing separators are ignored.
///
/// builder.dirname('path/to/foo.dart/'); // -> 'foo'
String basenameWithoutExtension(String path) =>
_builder.basenameWithoutExtension(path);
/// Gets the part of [path] before the last separator.
///
/// path.dirname('path/to/foo.dart'); // -> 'path/to'
/// path.dirname('path/to'); // -> 'to'
///
/// Trailing separators are ignored.
///
/// builder.dirname('path/to/'); // -> 'path'
String dirname(String path) => _builder.dirname(path);
/// Gets the file extension of [path]: the portion of [basename] from the last
/// `.` to the end (including the `.` itself).
///
/// path.extension('path/to/foo.dart'); // -> '.dart'
/// path.extension('path/to/foo'); // -> ''
/// path.extension('path.to/foo'); // -> ''
/// path.extension('path/to/foo.dart.js'); // -> '.js'
///
/// If the file name starts with a `.`, then that is not considered the
/// extension:
///
/// path.extension('~/.bashrc'); // -> ''
/// path.extension('~/.notes.txt'); // -> '.txt'
String extension(String path) => _builder.extension(path);
// TODO(nweiz): add a UNC example for Windows once issue 7323 is fixed.
/// Returns the root of [path], if it's absolute, or the empty string if it's
/// relative.
///
/// // Unix
/// path.rootPrefix('path/to/foo'); // -> ''
/// path.rootPrefix('/path/to/foo'); // -> '/'
///
/// // Windows
/// path.rootPrefix(r'path\to\foo'); // -> ''
/// path.rootPrefix(r'C:\path\to\foo'); // -> r'C:\'
String rootPrefix(String path) => _builder.rootPrefix(path);
/// Returns `true` if [path] is an absolute path and `false` if it is a
/// relative path. On POSIX systems, absolute paths start with a `/` (forward
/// slash). On Windows, an absolute path starts with `\\`, or a drive letter
/// followed by `:/` or `:\`.
bool isAbsolute(String path) => _builder.isAbsolute(path);
/// Returns `true` if [path] is a relative path and `false` if it is absolute.
/// On POSIX systems, absolute paths start with a `/` (forward slash). On
/// Windows, an absolute path starts with `\\`, or a drive letter followed by
/// `:/` or `:\`.
bool isRelative(String path) => _builder.isRelative(path);
/// Joins the given path parts into a single path using the current platform's
/// [separator]. Example:
///
/// path.join('path', 'to', 'foo'); // -> 'path/to/foo'
///
/// If any part ends in a path separator, then a redundant separator will not
/// be added:
///
/// path.join('path/', 'to', 'foo'); // -> 'path/to/foo
///
/// If a part is an absolute path, then anything before that will be ignored:
///
/// path.join('path', '/to', 'foo'); // -> '/to/foo'
String join(String part1, [String part2, String part3, String part4,
String part5, String part6, String part7, String part8]) =>
_builder.join(part1, part2, part3, part4, part5, part6, part7, part8);
// TODO(nweiz): add a UNC example for Windows once issue 7323 is fixed.
/// Splits [path] into its components using the current platform's [separator].
///
/// path.split('path/to/foo'); // -> ['path', 'to', 'foo']
///
/// The path will *not* be normalized before splitting.
///
/// path.split('path/../foo'); // -> ['path', '..', 'foo']
///
/// If [path] is absolute, the root directory will be the first element in the
/// array. Example:
///
/// // Unix
/// path.split('/path/to/foo'); // -> ['/', 'path', 'to', 'foo']
///
/// // Windows
/// path.split(r'C:\path\to\foo'); // -> [r'C:\', 'path', 'to', 'foo']
List<String> split(String path) => _builder.split(path);
/// Normalizes [path], simplifying it by handling `..`, and `.`, and
/// removing redundant path separators whenever possible.
///
/// path.normalize('path/./to/..//file.text'); // -> 'path/file.txt'
String normalize(String path) => _builder.normalize(path);
/// Attempts to convert [path] to an equivalent relative path from the current
/// directory.
///
/// // Given current directory is /root/path:
/// path.relative('/root/path/a/b.dart'); // -> 'a/b.dart'
/// path.relative('/root/other.dart'); // -> '../other.dart'
///
/// If the [from] argument is passed, [path] is made relative to that instead.
///
/// path.relative('/root/path/a/b.dart',
/// from: '/root/path'); // -> 'a/b.dart'
/// path.relative('/root/other.dart',
/// from: '/root/path'); // -> '../other.dart'
///
/// Since there is no relative path from one drive letter to another on Windows,
/// this will return an absolute path in that case.
///
/// path.relative(r'D:\other', from: r'C:\home'); // -> 'D:\other'
String relative(String path, {String from}) =>
_builder.relative(path, from: from);
/// Removes a trailing extension from the last part of [path].
///
/// withoutExtension('path/to/foo.dart'); // -> 'path/to/foo'
String withoutExtension(String path) => _builder.withoutExtension(path);
/// An instantiable class for manipulating paths. Unlike the top-level
/// functions, this lets you explicitly select what platform the paths will use.
class Builder {
/// Creates a new path builder for the given style and root directory.
///
/// If [style] is omitted, it uses the host operating system's path style. If
/// [root] is omitted, it defaults to the current working directory. If [root]
/// is relative, it is considered relative to the current working directory.
factory Builder({Style style, String root}) {
if (style == null) {
if (io.Platform.operatingSystem == 'windows') {
style = Style.windows;
} else {
style = Style.posix;
}
}
if (root == null) root = current;
return new Builder._(style, root);
}
Builder._(this.style, this.root);
/// The style of path that this builder works with.
final Style style;
/// The root directory that relative paths will be relative to.
final String root;
/// Gets the path separator for the builder's [style]. On Mac and Linux,
/// this is `/`. On Windows, it's `\`.
String get separator => style.separator;
/// Gets the part of [path] after the last separator on the builder's
/// platform.
///
/// builder.basename('path/to/foo.dart'); // -> 'foo.dart'
/// builder.basename('path/to'); // -> 'to'
///
/// Trailing separators are ignored.
///
/// builder.dirname('path/to/'); // -> 'to'
String basename(String path) => _parse(path).basename;
/// Gets the part of [path] after the last separator on the builder's
/// platform, and without any trailing file extension.
///
/// builder.basenameWithoutExtension('path/to/foo.dart'); // -> 'foo'
///
/// Trailing separators are ignored.
///
/// builder.dirname('path/to/foo.dart/'); // -> 'foo'
String basenameWithoutExtension(String path) =>
_parse(path).basenameWithoutExtension;
/// Gets the part of [path] before the last separator.
///
/// builder.dirname('path/to/foo.dart'); // -> 'path/to'
/// builder.dirname('path/to'); // -> 'path'
///
/// Trailing separators are ignored.
///
/// builder.dirname('path/to/'); // -> 'path'
String dirname(String path) {
var parsed = _parse(path);
parsed.removeTrailingSeparators();
if (parsed.parts.isEmpty) return parsed.root == null ? '.' : parsed.root;
if (parsed.parts.length == 1) {
return parsed.root == null ? '.' : parsed.root;
}
parsed.parts.removeLast();
parsed.separators.removeLast();
parsed.removeTrailingSeparators();
return parsed.toString();
}
/// Gets the file extension of [path]: the portion of [basename] from the last
/// `.` to the end (including the `.` itself).
///
/// builder.extension('path/to/foo.dart'); // -> '.dart'
/// builder.extension('path/to/foo'); // -> ''
/// builder.extension('path.to/foo'); // -> ''
/// builder.extension('path/to/foo.dart.js'); // -> '.js'
///
/// If the file name starts with a `.`, then it is not considered an
/// extension:
///
/// builder.extension('~/.bashrc'); // -> ''
/// builder.extension('~/.notes.txt'); // -> '.txt'
String extension(String path) => _parse(path).extension;
// TODO(nweiz): add a UNC example for Windows once issue 7323 is fixed.
/// Returns the root of [path], if it's absolute, or an empty string if it's
/// relative.
///
/// // Unix
/// builder.rootPrefix('path/to/foo'); // -> ''
/// builder.rootPrefix('/path/to/foo'); // -> '/'
///
/// // Windows
/// builder.rootPrefix(r'path\to\foo'); // -> ''
/// builder.rootPrefix(r'C:\path\to\foo'); // -> r'C:\'
String rootPrefix(String path) {
var root = _parse(path).root;
return root == null ? '' : root;
}
/// Returns `true` if [path] is an absolute path and `false` if it is a
/// relative path. On POSIX systems, absolute paths start with a `/` (forward
/// slash). On Windows, an absolute path starts with `\\`, or a drive letter
/// followed by `:/` or `:\`.
bool isAbsolute(String path) => _parse(path).isAbsolute;
/// Returns `true` if [path] is a relative path and `false` if it is absolute.
/// On POSIX systems, absolute paths start with a `/` (forward slash). On
/// Windows, an absolute path starts with `\\`, or a drive letter followed by
/// `:/` or `:\`.
bool isRelative(String path) => !isAbsolute(path);
/// Joins the given path parts into a single path. Example:
///
/// builder.join('path', 'to', 'foo'); // -> 'path/to/foo'
///
/// If any part ends in a path separator, then a redundant separator will not
/// be added:
///
/// builder.join('path/', 'to', 'foo'); // -> 'path/to/foo
///
/// If a part is an absolute path, then anything before that will be ignored:
///
/// builder.join('path', '/to', 'foo'); // -> '/to/foo'
///
String join(String part1, [String part2, String part3, String part4,
String part5, String part6, String part7, String part8]) {
var buffer = new StringBuffer();
var needsSeparator = false;
var parts = [part1, part2, part3, part4, part5, part6, part7, part8];
for (var i = 1; i < parts.length; i++) {
if (parts[i] != null && parts[i - 1] == null) {
throw new ArgumentError("join(): part ${i - 1} was null, but part $i "
"was not.");
}
}
for (var part in parts) {
if (part == null) continue;
if (this.isAbsolute(part)) {
// An absolute path discards everything before it.
buffer.clear();
buffer.add(part);
} else {
if (part.length > 0 && part[0].contains(style.separatorPattern)) {
// The part starts with a separator, so we don't need to add one.
} else if (needsSeparator) {
buffer.add(separator);
}
buffer.add(part);
}
// Unless this part ends with a separator, we'll need to add one before
// the next part.
needsSeparator = part.length > 0 &&
!part[part.length - 1].contains(style.separatorPattern);
}
return buffer.toString();
}
// TODO(nweiz): add a UNC example for Windows once issue 7323 is fixed.
/// Splits [path] into its components using the current platform's
/// [separator]. Example:
///
/// builder.split('path/to/foo'); // -> ['path', 'to', 'foo']
///
/// The path will *not* be normalized before splitting.
///
/// builder.split('path/../foo'); // -> ['path', '..', 'foo']
///
/// If [path] is absolute, the root directory will be the first element in the
/// array. Example:
///
/// // Unix
/// builder.split('/path/to/foo'); // -> ['/', 'path', 'to', 'foo']
///
/// // Windows
/// builder.split(r'C:\path\to\foo'); // -> [r'C:\', 'path', 'to', 'foo']
List<String> split(String path) {
var parsed = _parse(path);
// Filter out empty parts that exist due to multiple separators in a row.
parsed.parts = parsed.parts.where((part) => !part.isEmpty).toList();
if (parsed.root != null) parsed.parts.insertRange(0, 1, parsed.root);
return parsed.parts;
}
/// Normalizes [path], simplifying it by handling `..`, and `.`, and
/// removing redundant path separators whenever possible.
///
/// builder.normalize('path/./to/..//file.text'); // -> 'path/file.txt'
String normalize(String path) {
if (path == '') return path;
var parsed = _parse(path);
parsed.normalize();
return parsed.toString();
}
/// Creates a new path by appending the given path parts to the [root].
/// Equivalent to [join()] with [root] as the first argument. Example:
///
/// var builder = new Builder(root: 'root');
/// builder.resolve('path', 'to', 'foo'); // -> 'root/path/to/foo'
String resolve(String part1, [String part2, String part3, String part4,
String part5, String part6, String part7]) {
if (!?part2) return join(root, part1);
if (!?part3) return join(root, part1, part2);
if (!?part4) return join(root, part1, part2, part3);
if (!?part5) return join(root, part1, part2, part3, part4);
if (!?part6) return join(root, part1, part2, part3, part4, part5);
if (!?part7) return join(root, part1, part2, part3, part4, part5, part6);
return join(root, part1, part2, part3, part4, part5, part6, part7);
}
/// Attempts to convert [path] to an equivalent relative path relative to
/// [root].
///
/// var builder = new Builder(root: '/root/path');
/// builder.relative('/root/path/a/b.dart'); // -> 'a/b.dart'
/// builder.relative('/root/other.dart'); // -> '../other.dart'
///
/// If the [from] argument is passed, [path] is made relative to that instead.
///
/// builder.relative('/root/path/a/b.dart',
/// from: '/root/path'); // -> 'a/b.dart'
/// builder.relative('/root/other.dart',
/// from: '/root/path'); // -> '../other.dart'
///
/// Since there is no relative path from one drive letter to another on
/// Windows, this will return an absolute path in that case.
///
/// builder.relative(r'D:\other', from: r'C:\other'); // -> 'D:\other'
///
/// This will also return an absolute path if an absolute [path] is passed to
/// a builder with a relative [root].
///
/// var builder = new Builder(r'some/relative/path');
/// builder.relative(r'/absolute/path'); // -> '/absolute/path'
String relative(String path, {String from}) {
if (path == '') return '.';
from = from == null ? root : this.join(root, from);
// We can't determine the path from a relative path to an absolute path.
if (this.isRelative(from) && this.isAbsolute(path)) {
return this.normalize(path);
}
// If the given path is relative, resolve it relative to the root of the
// builder.
if (this.isRelative(path)) path = this.resolve(path);
// If the path is still relative and `from` is absolute, we're unable to
// find a path from `from` to `path`.
if (this.isRelative(path) && this.isAbsolute(from)) {
throw new ArgumentError('Unable to find a path to "$path" from "$from".');
}
var fromParsed = _parse(from)..normalize();
var pathParsed = _parse(path)..normalize();
// If the root prefixes don't match (for example, different drive letters
// on Windows), then there is no relative path, so just return the absolute
// one. In Windows, drive letters are case-insenstive and we allow
// calculation of relative paths, even if a path has not been normalized.
if (fromParsed.root != pathParsed.root &&
((fromParsed.root == null || pathParsed.root == null) ||
fromParsed.root.toLowerCase().replaceAll('/', '\\') !=
pathParsed.root.toLowerCase().replaceAll('/', '\\'))) {
return pathParsed.toString();
}
// Strip off their common prefix.
while (fromParsed.parts.length > 0 && pathParsed.parts.length > 0 &&
fromParsed.parts[0] == pathParsed.parts[0]) {
fromParsed.parts.removeAt(0);
fromParsed.separators.removeAt(0);
pathParsed.parts.removeAt(0);
pathParsed.separators.removeAt(0);
}
// If there are any directories left in the root path, we need to walk up
// out of them.
pathParsed.parts.insertRange(0, fromParsed.parts.length, '..');
pathParsed.separators.insertRange(0, fromParsed.parts.length,
style.separator);
// Corner case: the paths completely collapsed.
if (pathParsed.parts.length == 0) return '.';
// Make it relative.
pathParsed.root = '';
pathParsed.removeTrailingSeparators();
return pathParsed.toString();
}
/// Removes a trailing extension from the last part of [path].
///
/// builder.withoutExtension('path/to/foo.dart'); // -> 'path/to/foo'
String withoutExtension(String path) {
var parsed = _parse(path);
for (var i = parsed.parts.length - 1; i >= 0; i--) {
if (!parsed.parts[i].isEmpty) {
parsed.parts[i] = parsed.basenameWithoutExtension;
break;
}
}
return parsed.toString();
}
_ParsedPath _parse(String path) {
var before = path;
// Remove the root prefix, if any.
var root = style.getRoot(path);
if (root != null) path = path.substring(root.length);
// Split the parts on path separators.
var parts = [];
var separators = [];
var start = 0;
for (var match in style.separatorPattern.allMatches(path)) {
parts.add(path.substring(start, match.start));
separators.add(match[0]);
start = match.end;
}
// Add the final part, if any.
if (start < path.length) {
parts.add(path.substring(start));
separators.add('');
}
return new _ParsedPath(style, root, parts, separators);
}
}
/// An enum type describing a "flavor" of path.
class Style {
/// POSIX-style paths use "/" (forward slash) as separators. Absolute paths
/// start with "/". Used by UNIX, Linux, Mac OS X, and others.
static final posix = new Style._('posix', '/', '/', '/');
/// Windows paths use "\" (backslash) as separators. Absolute paths start with
/// a drive letter followed by a colon (example, "C:") or two backslashes
/// ("\\") for UNC paths.
// TODO(rnystrom): The UNC root prefix should include the drive name too, not
// just the "\\".
static final windows = new Style._('windows', '\\', r'[/\\]',
r'\\\\|[a-zA-Z]:[/\\]');
Style._(this.name, this.separator, String separatorPattern,
String rootPattern)
: separatorPattern = new RegExp(separatorPattern),
_rootPattern = new RegExp('^$rootPattern');
/// The name of this path style. Will be "posix" or "windows".
final String name;
/// The path separator for this style. On POSIX, this is `/`. On Windows,
/// it's `\`.
final String separator;
/// The [Pattern] that can be used to match a separator for a path in this
/// style. Windows allows both "/" and "\" as path separators even though
/// "\" is the canonical one.
final Pattern separatorPattern;
// TODO(nweiz): make this a Pattern when issue 7080 is fixed.
/// The [RegExp] that can be used to match the root prefix of an absolute
/// path in this style.
final RegExp _rootPattern;
/// Gets the root prefix of [path] if path is absolute. If [path] is relative,
/// returns `null`.
String getRoot(String path) {
var match = _rootPattern.firstMatch(path);
if (match == null) return null;
return match[0];
}
String toString() => name;
}
// TODO(rnystrom): Make this public?
class _ParsedPath {
/// The [Style] that was used to parse this path.
Style style;
/// The absolute root portion of the path, or `null` if the path is relative.
/// On POSIX systems, this will be `null` or "/". On Windows, it can be
/// `null`, "//" for a UNC path, or something like "C:\" for paths with drive
/// letters.
String root;
/// The path-separated parts of the path. All but the last will be
/// directories.
List<String> parts;
/// The path separators following each part. The last one will be an empty
/// string unless the path ends with a trailing separator.
List<String> separators;
/// The file extension of the last part, or "" if it doesn't have one.
String get extension => _splitExtension()[1];
/// `true` if this is an absolute path.
bool get isAbsolute => root != null;
_ParsedPath(this.style, this.root, this.parts, this.separators);
String get basename {
var copy = this.clone();
copy.removeTrailingSeparators();
if (copy.parts.isEmpty) return root == null ? '' : root;
return copy.parts.last;
}
String get basenameWithoutExtension {
var copy = this.clone();
copy.removeTrailingSeparators();
if (copy.parts.isEmpty) return root == null ? '' : root;
return copy._splitExtension()[0];
}
void removeTrailingSeparators() {
while (!parts.isEmpty && parts.last == '') {
parts.removeLast();
separators.removeLast();
}
if (separators.length > 0) separators[separators.length - 1] = '';
}
void normalize() {
// Handle '.', '..', and empty parts.
var leadingDoubles = 0;
var newParts = [];
for (var part in parts) {
if (part == '.' || part == '') {
// Do nothing. Ignore it.
} else if (part == '..') {
// Pop the last part off.
if (newParts.length > 0) {
newParts.removeLast();
} else {
// Backed out past the beginning, so preserve the "..".
leadingDoubles++;
}
} else {
newParts.add(part);
}
}
// A relative path can back out from the start directory.
if (!isAbsolute) {
newParts.insertRange(0, leadingDoubles, '..');
}
// If we collapsed down to nothing, do ".".
if (newParts.length == 0 && !isAbsolute) {
newParts.add('.');
}
// Canonicalize separators.
var newSeparators = [];
newSeparators.insertRange(0, newParts.length, style.separator);
parts = newParts;
separators = newSeparators;
// Normalize the Windows root if needed.
if (root != null && style == Style.windows) {
root = root.replaceAll('/', '\\');
}
removeTrailingSeparators();
}
String toString() {
var builder = new StringBuffer();
if (root != null) builder.add(root);
for (var i = 0; i < parts.length; i++) {
builder.add(parts[i]);
builder.add(separators[i]);
}
return builder.toString();
}
/// Splits the last part of the path into a two-element list. The first is
/// the name of the file without any extension. The second is the extension
/// or "" if it has none.
List<String> _splitExtension() {
if (parts.isEmpty) return ['', ''];
var file = parts.last;
if (file == '..') return ['..', ''];
var lastDot = file.lastIndexOf('.');
// If there is no dot, or it's the first character, like '.bashrc', it
// doesn't count.
if (lastDot <= 0) return [file, ''];
return [file.substring(0, lastDot), file.substring(lastDot)];
}
_ParsedPath clone() => new _ParsedPath(
style, root, new List.from(parts), new List.from(separators));
}