@@ -11,22 +11,27 @@ import 'package:node_preamble/preamble.dart' as preamble;
1111import 'package:package_resolver/package_resolver.dart' ;
1212import 'package:path/path.dart' as p;
1313import 'package:stream_channel/stream_channel.dart' ;
14+ import 'package:yaml/yaml.dart' ;
1415
1516import '../../backend/test_platform.dart' ;
1617import '../../util/io.dart' ;
1718import '../../util/stack_trace_mapper.dart' ;
1819import '../../utils.dart' ;
20+ import '../application_exception.dart' ;
1921import '../compiler_pool.dart' ;
2022import '../configuration.dart' ;
2123import '../configuration/suite.dart' ;
24+ import '../executable_settings.dart' ;
2225import '../load_exception.dart' ;
26+ import '../plugin/customizable_platform.dart' ;
2327import '../plugin/environment.dart' ;
2428import '../plugin/platform.dart' ;
2529import '../plugin/platform_helpers.dart' ;
2630import '../runner_suite.dart' ;
2731
2832/// A platform that loads tests in Node.js processes.
29- class NodePlatform extends PlatformPlugin {
33+ class NodePlatform extends PlatformPlugin
34+ implements CustomizablePlatform <ExecutableSettings > {
3035 /// The test runner configuration.
3136 final Configuration _config;
3237
@@ -39,22 +44,41 @@ class NodePlatform extends PlatformPlugin {
3944 /// The HTTP client to use when fetching JS files for `pub serve` .
4045 final HttpClient _http;
4146
42- /// The Node executable to use.
43- String get _executable => Platform .isWindows ? "node.exe" : "node" ;
47+ /// Executable settings for [TestPlatform.nodeJS] and platforms that extend
48+ /// it.
49+ final _settings = {
50+ TestPlatform .nodeJS: new ExecutableSettings (
51+ linuxExecutable: "node" ,
52+ macOSExecutable: "node" ,
53+ windowsExecutable: "node.exe" )
54+ };
4455
4556 NodePlatform ()
4657 : _config = Configuration .current,
4758 _http =
4859 Configuration .current.pubServeUrl == null ? null : new HttpClient ();
4960
61+ ExecutableSettings parsePlatformSettings (YamlMap settings) =>
62+ new ExecutableSettings .parse (settings);
63+
64+ ExecutableSettings mergePlatformSettings (
65+ ExecutableSettings settings1, ExecutableSettings settings2) =>
66+ settings1.merge (settings2);
67+
68+ void customizePlatform (TestPlatform platform, ExecutableSettings settings) {
69+ var oldSettings = _settings[platform] ?? _settings[platform.root];
70+ if (oldSettings != null ) settings = oldSettings.merge (settings);
71+ _settings[platform] = settings;
72+ }
73+
5074 StreamChannel loadChannel (String path, TestPlatform platform) =>
5175 throw new UnimplementedError ();
5276
5377 Future <RunnerSuite > load (String path, TestPlatform platform,
5478 SuiteConfiguration suiteConfig, Object message) async {
5579 assert (platform == TestPlatform .nodeJS);
5680
57- var pair = await _loadChannel (path, suiteConfig);
81+ var pair = await _loadChannel (path, platform, suiteConfig);
5882 var controller = await deserializeSuite (path, platform, suiteConfig,
5983 new PluginEnvironment (), pair.first, message,
6084 mapper: pair.last);
@@ -65,9 +89,9 @@ class NodePlatform extends PlatformPlugin {
6589 ///
6690 /// Returns that channel along with a [StackTraceMapper] representing the
6791 /// source map for the compiled suite.
68- Future <Pair <StreamChannel , StackTraceMapper >> _loadChannel (
69- String path , SuiteConfiguration suiteConfig) async {
70- var pair = await _spawnProcess (path, suiteConfig);
92+ Future <Pair <StreamChannel , StackTraceMapper >> _loadChannel (String path,
93+ TestPlatform platform , SuiteConfiguration suiteConfig) async {
94+ var pair = await _spawnProcess (path, platform, suiteConfig);
7195 var process = pair.first;
7296
7397 // Node normally doesn't emit any standard error, but if it does we forward
@@ -91,8 +115,8 @@ class NodePlatform extends PlatformPlugin {
91115 ///
92116 /// Returns that channel along with a [StackTraceMapper] representing the
93117 /// source map for the compiled suite.
94- Future <Pair <Process , StackTraceMapper >> _spawnProcess (
95- String path , SuiteConfiguration suiteConfig) async {
118+ Future <Pair <Process , StackTraceMapper >> _spawnProcess (String path,
119+ TestPlatform platform , SuiteConfiguration suiteConfig) async {
96120 var dir = new Directory (_compiledDir).createTempSync ('test_' ).path;
97121 var jsPath = p.join (dir, p.basename (path) + ".node_test.dart.js" );
98122
@@ -122,7 +146,7 @@ class NodePlatform extends PlatformPlugin {
122146 sdkRoot: p.toUri (sdkDir));
123147 }
124148
125- return new Pair (await Process . start (_executable, [ jsPath] ), mapper);
149+ return new Pair (await _startProcess (platform, jsPath), mapper);
126150 }
127151
128152 var url = _config.pubServeUrl.resolveUri (
@@ -141,7 +165,20 @@ class NodePlatform extends PlatformPlugin {
141165 sdkRoot: p.toUri ('packages/\$ sdk' ));
142166 }
143167
144- return new Pair (await Process .start (_executable, [jsPath]), mapper);
168+ return new Pair (await _startProcess (platform, jsPath), mapper);
169+ }
170+
171+ /// Starts the Node.js process for [platform] with [jsPath] .
172+ Future <Process > _startProcess (TestPlatform platform, String jsPath) async {
173+ try {
174+ return await Process .start (_settings[platform].executable, [jsPath]);
175+ } catch (error, stackTrace) {
176+ await new Future .error (
177+ new ApplicationException (
178+ "Failed to run ${platform .name }: ${getErrorMessage (error )}" ),
179+ stackTrace);
180+ return null ;
181+ }
145182 }
146183
147184 /// Runs an HTTP GET on [url] .
0 commit comments