Skip to content

Commit 6020e10

Browse files
authored
Support picking a port, use it in some tests. (#4212)
1 parent 2d33b97 commit 6020e10

File tree

6 files changed

+59
-52
lines changed

6 files changed

+59
-52
lines changed

build_runner/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
## 2.8.1-wip
22

3+
- Print the port that gets picked if you pass 0 for a port number, for example
4+
with `dart run build_runner serve web:0`.
35
- Improved warnings when an option is specified for an unknown builder.
46
- Bug fix: require `args` 2.5.0.
57
- Use `build` ^4.0.0.

build_runner/lib/src/commands/serve_command.dart

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,8 @@ class ServeCommand implements BuildRunnerCommand {
5858
} on SocketException catch (e) {
5959
if (e.address != null && e.port != null) {
6060
buildLog.error(
61-
'Error starting server at ${e.address!.address}:${e.port}, address '
62-
'is already in use. Please kill the server running on that port or '
63-
'serve on a different port and restart this process.',
61+
'Failed to start server on ${e.address!.address}:${e.port}, '
62+
'address in use.',
6463
);
6564
} else {
6665
buildLog.error('Error starting server on ${serveOptions.hostname}.');
@@ -92,7 +91,18 @@ class ServeCommand implements BuildRunnerCommand {
9291

9392
final completer = Completer<int>();
9493
handleBuildResultsStream(handler.buildResults, completer);
95-
_logServerPorts();
94+
95+
if (serveOptions.serveTargets.isEmpty) {
96+
buildLog.warning('Nothing to serve.');
97+
} else {
98+
for (final target in serveOptions.serveTargets) {
99+
final port = servers[target]!.port;
100+
buildLog.info(
101+
'Serving `${target.dir}` on http://${serveOptions.hostname}:$port',
102+
);
103+
}
104+
}
105+
96106
await handler.currentBuild;
97107
return await completer.future;
98108
} finally {
@@ -101,36 +111,18 @@ class ServeCommand implements BuildRunnerCommand {
101111
);
102112
}
103113
}
104-
105-
void _logServerPorts() async {
106-
// Warn if in serve mode with no servers.
107-
if (serveOptions.serveTargets.isEmpty) {
108-
buildLog.warning(
109-
'Found no known web directories to serve, but running in `serve` '
110-
'mode. You may expliclity provide a directory to serve with trailing '
111-
'args in <dir>[:<port>] format.',
112-
);
113-
} else {
114-
for (final target in serveOptions.serveTargets) {
115-
buildLog.info(
116-
'Serving `${target.dir}` on '
117-
'http://${serveOptions.hostname}:${target.port}',
118-
);
119-
}
120-
}
121-
}
122114
}
123115

124116
void _ensureBuildWebCompilersDependency(PackageGraph packageGraph) {
125117
if (!packageGraph.allPackages.containsKey('build_web_compilers')) {
126118
buildLog.warning('''
127-
Missing dev dependency on package:build_web_compilers, which is required to serve Dart compiled to JavaScript.
119+
Missing dev dependency on package:build_web_compilers, which is required to serve Dart compiled to JavaScript.
128120
129-
Please update your dev_dependencies section of your pubspec.yaml:
121+
Please update your dev_dependencies section of your pubspec.yaml:
130122
131-
dev_dependencies:
132-
build_runner: any
133-
build_test: any
134-
build_web_compilers: any''');
123+
dev_dependencies:
124+
build_runner: any
125+
build_test: any
126+
build_web_compilers: any''');
135127
}
136128
}

build_runner/lib/src/commands/test_command.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,11 @@ Missing dev dependency on package:build_test, which is required to run tests.
6060
6161
Please update your dev_dependencies section of your pubspec.yaml:
6262
63-
dev_dependencies:
64-
build_runner: any
65-
build_test: any
66-
# If you need to run web tests, you will also need this dependency.
67-
build_web_compilers: any''');
63+
dev_dependencies:
64+
build_runner: any
65+
build_test: any
66+
# If you need to run web tests, you will also need this dependency.
67+
build_web_compilers: any''');
6868
return ExitCode.config.code;
6969
}
7070

build_runner/test/common/build_runner_tester.dart

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,9 @@ ${result.stdout}${result.stderr}===
175175

176176
/// A running `build_runner` process.
177177
class BuildRunnerProcess {
178-
late final HttpClient _client = HttpClient();
179178
final TestProcess process;
179+
late final HttpClient _client = HttpClient();
180+
int? _port;
180181

181182
BuildRunnerProcess(this.process);
182183

@@ -188,8 +189,8 @@ class BuildRunnerProcess {
188189
///
189190
/// If the process exits instead, the test fails immediately.
190191
///
191-
/// Otherwise, waits until [pattern] appears.
192-
Future<void> expect(Pattern pattern, {Pattern? failOn}) async {
192+
/// Otherwise, waits until [pattern] appears, returns the matching line.
193+
Future<String> expect(Pattern pattern, {Pattern? failOn}) async {
193194
failOn ??= BuildLog.failurePattern;
194195
while (true) {
195196
String? line;
@@ -202,26 +203,36 @@ class BuildRunnerProcess {
202203
if (line.contains(failOn)) {
203204
fail('While expecting `$pattern`, got `$failOn`.');
204205
}
205-
if (line.contains(pattern)) return;
206+
if (line.contains(pattern)) return line;
206207
}
207208
}
208209

209210
/// Kills the process.
210211
Future<void> kill() => process.kill();
211212

212-
/// Requests [path] from the default server and expects it returns a 404
213+
// Expects the server to log that it is serving, records the port.
214+
Future<void> expectServing() async {
215+
final regexp = RegExp('Serving `web` on http://localhost:([0-9]+)');
216+
final line = await expect(regexp);
217+
final port = int.parse(regexp.firstMatch(line)!.group(1)!);
218+
_port = port;
219+
}
220+
221+
/// Requests [path] from the server and expects it returns a 404
213222
/// response.
214223
Future<void> expect404(String path) async {
215-
final request = await _client.get('localhost', 8080, path);
224+
if (_port == null) throw StateError('Call expectServing first.');
225+
final request = await _client.get('localhost', _port!, path);
216226
final response = await request.close();
217227
test.expect(response.statusCode, 404);
218228
await response.drain<void>();
219229
}
220230

221-
/// Requests [path] from the default server and expects it returns a 200
231+
/// Requests [path] from the server and expects it returns a 200
222232
/// response with the body [content].
223233
Future<void> expectContent(String path, String content) async {
224-
final request = await _client.get('localhost', 8080, path);
234+
if (_port == null) throw StateError('Call expectServing first.');
235+
final request = await _client.get('localhost', _port!, path);
225236
final response = await request.close();
226237
test.expect(response.statusCode, 200);
227238
test.expect(await utf8.decodeStream(response.cast<List<int>>()), content);

build_runner/test/integration_tests/serve_command_serve_only_required_test.dart

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
// TODO(davidmorgan): find unused port so this can run in parallel.
6-
@Tags(['slow'])
5+
@Tags(['integration'])
76
library;
87

98
import 'package:build_runner/src/logging/build_log.dart';
@@ -24,9 +23,13 @@ void main() async {
2423
files: {'web/a.txt': 'a', 'web/b.txt': 'b'},
2524
);
2625

27-
final serve = await tester.start('root_pkg', 'dart run build_runner serve');
26+
final serve = await tester.start(
27+
'root_pkg',
28+
'dart run build_runner serve web:0',
29+
);
2830

2931
// Initial build produces no output as the copy is not required.
32+
await serve.expectServing();
3033
await serve.expect(BuildLog.successPattern);
3134
await serve.expect404('a.txt.copy');
3235

build_runner/test/integration_tests/serve_command_test.dart

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
// TODO(davidmorgan): find unused port so this can run in parallel.
65
@Tags(['integration'])
76
library;
87

@@ -29,26 +28,26 @@ void main() async {
2928
'Missing dev dependency on package:build_web_compilers, '
3029
'which is required to serve Dart compiled to JavaScript.',
3130
);
32-
await serve.expect('Found no known web directories to serve');
31+
await serve.expect('Nothing to serve.');
3332
await serve.kill();
3433

3534
// Create some source to serve.
3635
tester.write('root_pkg/web/a.txt', 'a');
3736

38-
// Start a server on the same port, serve, check the error.
39-
final server = await HttpServer.bind('localhost', 8080);
37+
// Start a server serve on the same port, check the error.
38+
final server = await HttpServer.bind('localhost', 0);
4039
addTearDown(server.close);
4140
final output = await tester.run(
4241
'root_pkg',
43-
'dart run build_runner serve web:8080',
42+
'dart run build_runner serve web:${server.port}',
4443
expectExitCode: ExitCode.osError.code,
4544
);
4645
expect(
4746
output,
4847
allOf(
49-
contains('Error starting server'),
50-
contains('8080'),
51-
contains('address is already in use'),
48+
contains('Failed to start server'),
49+
contains('${server.port}'),
50+
contains('address in use'),
5251
),
5352
);
5453
await server.close();

0 commit comments

Comments
 (0)