fix(test): make `evalModule` faster by caching spawned modules in the browser
This commit is contained in:
parent
d9036c6cf3
commit
67c79ba3f6
|
@ -0,0 +1,86 @@
|
|||
// This module provides a customFileHandler for karma
|
||||
// that serves files with urls like /packages_<timestamp>/...
|
||||
// with maximum cache.
|
||||
// We are using these urls when we spawn isolates
|
||||
// so that the isolates don't reload files every time.
|
||||
|
||||
var common = require('karma/lib/middleware/common');
|
||||
var fs = require('fs');
|
||||
|
||||
var DART_EVAL_PATH_RE = /.*\/packages_\d+\/(.*)$/;
|
||||
|
||||
module.exports = createFactory;
|
||||
|
||||
function createFactory(proxyPaths) {
|
||||
return {
|
||||
'framework:dart-evalcache': ['factory', dartEvalCacheFactory]
|
||||
};
|
||||
|
||||
function dartEvalCacheFactory(emitter, logger, customFileHandlers) {
|
||||
var filesPromise = new common.PromiseContainer();
|
||||
emitter.on('file_list_modified', function(files) {
|
||||
filesPromise.set(files);
|
||||
});
|
||||
|
||||
var serveFile = common.createServeFile(fs);
|
||||
var log = logger.create('dart-evalcache');
|
||||
|
||||
customFileHandlers.push({
|
||||
urlRegex: DART_EVAL_PATH_RE,
|
||||
handler: handler
|
||||
});
|
||||
|
||||
// See source_files handler
|
||||
function handler(request, response, fa, fb, basePath) {
|
||||
return filesPromise.then(function(files) {
|
||||
try {
|
||||
var requestedFilePath = mapUrlToFile(request.url, proxyPaths, basePath, log);
|
||||
// TODO(vojta): change served to be a map rather then an array
|
||||
var file = findByPath(files.served, requestedFilePath);
|
||||
if (file) {
|
||||
serveFile(file.contentPath || file.path, response, function() {
|
||||
common.setHeavyCacheHeaders(response);
|
||||
}, file.content);
|
||||
} else {
|
||||
response.writeHead(404);
|
||||
response.end('Not found');
|
||||
}
|
||||
} catch (e) {
|
||||
log.error(e.stack);
|
||||
response.writeHead(500);
|
||||
response.end('Error', e.stack);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function mapUrlToFile(url, proxyPaths, basePath, log) {
|
||||
var originalUrl = url;
|
||||
url = url.indexOf('?') > -1 ? url.substring(0, url.indexOf('?')) : url;
|
||||
var match = DART_EVAL_PATH_RE.exec(url);
|
||||
var packagePath = match[1];
|
||||
var result = null;
|
||||
var lastProxyFromLength = 0;
|
||||
Object.keys(proxyPaths).forEach(function(proxyFrom) {
|
||||
if (startsWith(packagePath, proxyFrom) && proxyFrom.length > lastProxyFromLength) {
|
||||
lastProxyFromLength = proxyFrom.length;
|
||||
result = proxyPaths[proxyFrom] + packagePath.substring(proxyFrom.length);
|
||||
}
|
||||
});
|
||||
return basePath + '/' + result;
|
||||
}
|
||||
|
||||
function startsWith(string, subString) {
|
||||
return string.length >= subString.length && string.slice(0, subString.length) === subString;
|
||||
}
|
||||
|
||||
function findByPath(files, path) {
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
if (files[i].path === path) {
|
||||
return files[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
|
@ -1,11 +1,41 @@
|
|||
var sauceConf = require('./sauce.conf');
|
||||
|
||||
var packageSources = {
|
||||
// Dependencies installed with `pub install`.
|
||||
'unittest': 'packages/unittest',
|
||||
'guinness': 'packages/guinness',
|
||||
'matcher': 'packages/matcher',
|
||||
'stack_trace': 'packages/stack_trace',
|
||||
'collection': 'packages/collection',
|
||||
'path': 'packages/path',
|
||||
'observe': 'packages/observe',
|
||||
'quiver': 'packages/quiver',
|
||||
'intl': 'packages/intl',
|
||||
'smoke': 'packages/smoke',
|
||||
'logging': 'packages/logging',
|
||||
'utf': 'packages/utf',
|
||||
|
||||
// Local dependencies, transpiled from the source.
|
||||
'angular2/test/': 'dist/dart/angular2/test/',
|
||||
'angular2': 'dist/dart/angular2/lib',
|
||||
'http': 'dist/dart/http/lib',
|
||||
'angular2_material': 'dist/dart/angular2_material/lib',
|
||||
'benchpress': 'dist/dart/benchpress/lib',
|
||||
'examples': 'dist/dart/examples/lib'
|
||||
};
|
||||
|
||||
var proxyPaths = {};
|
||||
Object.keys(packageSources).map(function(packageName) {
|
||||
var filePath = packageSources[packageName];
|
||||
proxyPaths['/packages/'+packageName] = '/base/'+filePath;
|
||||
});
|
||||
|
||||
// Karma configuration
|
||||
// Generated on Thu Sep 25 2014 11:52:02 GMT-0700 (PDT)
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
|
||||
frameworks: ['dart-unittest'],
|
||||
frameworks: ['dart-unittest', 'dart-evalcache'],
|
||||
|
||||
files: [
|
||||
// Init and configure guiness.
|
||||
|
@ -35,27 +65,18 @@ module.exports = function(config) {
|
|||
},
|
||||
|
||||
// Map packages to the correct urls where Karma serves them.
|
||||
proxies: {
|
||||
// Dependencies installed with `pub install`.
|
||||
'/packages/unittest': '/base/packages/unittest',
|
||||
'/packages/guinness': '/base/packages/guinness',
|
||||
'/packages/matcher': '/base/packages/matcher',
|
||||
'/packages/stack_trace': '/base/packages/stack_trace',
|
||||
'/packages/collection': '/base/packages/collection',
|
||||
'/packages/path': '/base/packages/path',
|
||||
|
||||
// Local dependencies, transpiled from the source.
|
||||
'/packages/angular2/test/': '/base/dist/dart/angular2/test/',
|
||||
'/packages/angular2': '/base/dist/dart/angular2/lib',
|
||||
'/packages/http': '/base/dist/dart/http/lib',
|
||||
'/packages/angular2_material': '/base/dist/dart/angular2_material/lib',
|
||||
'/packages/benchpress': '/base/dist/dart/benchpress/lib',
|
||||
'/packages/examples': '/base/dist/dart/examples/lib'
|
||||
},
|
||||
proxies: proxyPaths,
|
||||
|
||||
customLaunchers: sauceConf.customLaunchers,
|
||||
browsers: ['DartiumWithWebPlatform'],
|
||||
|
||||
port: 9877
|
||||
port: 9877,
|
||||
|
||||
plugins: [
|
||||
require('karma-dart'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-sauce-launcher'),
|
||||
require('./karma-dart-evalcache')(packageSources)
|
||||
]
|
||||
});
|
||||
};
|
||||
|
|
|
@ -13,7 +13,7 @@ createIsolateSource(String moduleSource, List<List<String>> moduleImports) {
|
|||
String modAlias = sourceImport[1];
|
||||
moduleSourceParts.add("import 'package:${modName}.dart' as ${modAlias};");
|
||||
});
|
||||
moduleSourceParts.add(moduleSource);
|
||||
moduleSourceParts.add(moduleSource);
|
||||
|
||||
return """
|
||||
import "dart:isolate";
|
||||
|
@ -26,6 +26,8 @@ main(List args, SendPort replyPort) {
|
|||
|
||||
}
|
||||
|
||||
var timeStamp = new DateTime.now().millisecondsSinceEpoch;
|
||||
|
||||
dynamic callModule(dynamic data) { return data.map( (a) => a+1); }
|
||||
|
||||
evalModule(String moduleSource, List<List<String>> moduleImports, List args) {
|
||||
|
@ -36,7 +38,11 @@ evalModule(String moduleSource, List<List<String>> moduleImports, List args) {
|
|||
receivePort.close();
|
||||
completer.complete(message);
|
||||
});
|
||||
var packageRoot = Uri.parse('/packages');
|
||||
// Note: we have a special karma plugin that sends files under
|
||||
// urls like /package_1234 as permanently cached.
|
||||
// With this, spawning multiple isolates gets faster as Darts does not
|
||||
// reload the files from the server.
|
||||
var packageRoot = Uri.parse('/packages_${timeStamp}');
|
||||
return Isolate.spawnUri(toDartDataUri(source), args, receivePort.sendPort, packageRoot: packageRoot).then( (isolate) {
|
||||
RawReceivePort errorPort;
|
||||
errorPort = new RawReceivePort( (message) {
|
||||
|
|
Loading…
Reference in New Issue