Skip to content

Commit 940e662

Browse files
authored
Remove webdev dependency from dwds (#486)
Towards #475 No longer depend on webdev for building and serving, instead create a simple test server and make use of the build daemon.
1 parent e1ac87a commit 940e662

File tree

11 files changed

+179
-45
lines changed

11 files changed

+179
-45
lines changed

_test/pubspec.yaml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,3 @@ dependencies:
1515
dev_dependencies:
1616
build_runner: ^1.0.0
1717
build_web_compilers: '>=1.0.0 <3.0.0'
18-
19-
dependency_overrides:
20-
webdev:
21-
path: ../webdev
22-
dwds:
23-
path: ../dwds

dwds/pubspec.yaml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ dependencies:
1818
pedantic: ^1.5.0
1919
pub_semver: ^1.4.2
2020
shelf: ^0.7.0
21+
shelf_proxy: ^0.1.0+6
2122
shelf_web_socket: ^0.2.0
2223
source_maps: ^0.10.0
2324
vm_service_lib: 3.20.0+02
@@ -31,11 +32,7 @@ dev_dependencies:
3132
built_value_generator: ^6.4.0
3233
graphs: ^0.2.0
3334
js: ^0.6.1
35+
sse: ^2.0.2
3436
test: ^1.6.0
3537
uuid: ^2.0.0
3638
webdriver: ^2.0.0
37-
webdev: ^2.0.0
38-
39-
dependency_overrides:
40-
webdev:
41-
path: ../webdev

dwds/test/chrome_proxy_service_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import 'package:test/test.dart';
1515
import 'package:vm_service_lib/vm_service_lib.dart';
1616
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
1717

18-
import 'test_context.dart';
18+
import 'fixtures/context.dart';
1919

2020
final context = TestContext();
2121
ChromeProxyService get service => context.chromeProxyService;

dwds/test/debug_service_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import 'dart:io';
77
import 'package:dwds/src/services/debug_service.dart';
88
import 'package:test/test.dart';
99

10-
import 'test_context.dart';
10+
import 'fixtures/context.dart';
1111

1212
final context = TestContext();
1313
DebugService get debugService => context.debugService;

dwds/test/debugger_test.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import 'package:dwds/src/debugging/location.dart';
1111
import 'package:source_maps/parser.dart';
1212
import 'package:test/test.dart';
1313

14-
import 'debugger_data.dart';
15-
import 'fakes.dart';
16-
import 'test_context.dart';
14+
import 'fixtures/context.dart';
15+
import 'fixtures/debugger_data.dart';
16+
import 'fixtures/fakes.dart';
1717

1818
final context = TestContext();
1919
AppInspector inspector;

dwds/test/test_context.dart renamed to dwds/test/fixtures/context.dart

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1+
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
15
import 'dart:async';
2-
import 'dart:convert';
36
import 'dart:io';
47

8+
import 'package:build_daemon/client.dart';
9+
import 'package:build_daemon/data/build_status.dart';
10+
import 'package:build_daemon/data/build_target.dart';
11+
import 'package:dwds/dwds.dart';
512
import 'package:dwds/src/services/chrome_proxy_service.dart';
613
import 'package:dwds/src/services/debug_service.dart';
714
import 'package:dwds/src/utilities/shared.dart';
@@ -11,21 +18,25 @@ import 'package:test/test.dart';
1118
import 'package:webdriver/io.dart';
1219
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
1320

21+
import 'server.dart';
22+
import 'utilities.dart';
23+
1424
class TestContext {
1525
String appUrl;
1626
DebugService debugService;
1727
ChromeProxyService get chromeProxyService =>
1828
debugService.chromeProxyService as ChromeProxyService;
1929
WipConnection tabConnection;
20-
Process webdev;
30+
TestServer testServer;
31+
BuildDaemonClient daemonClient;
2132
WebDriver webDriver;
2233
Process chromeDriver;
2334
int port;
2435

25-
/// The directory in which we run pub serve.
26-
String directory;
36+
/// Top level directory in which we run the test server..
37+
String workingDirectory;
2738

28-
/// The path to pass to webdev serve.
39+
/// The path to build and serve.
2940
String pathToServe;
3041

3142
/// The path part of the application URL.
@@ -35,7 +46,8 @@ class TestContext {
3546
{String directory,
3647
this.path = 'hello_world/index.html',
3748
this.pathToServe = 'example'}) {
38-
this.directory = directory ?? p.relative('../_test', from: p.current);
49+
workingDirectory = p.normalize(
50+
p.absolute(directory ?? p.relative('../_test', from: p.current)));
3951
}
4052

4153
Future<void> setUp() async {
@@ -48,26 +60,28 @@ class TestContext {
4860
'Could not start ChromeDriver. Is it installed?\nError: $e');
4961
}
5062

51-
await Process.run('pub', ['get'], workingDirectory: directory);
52-
53-
webdev = await Process.start(
54-
'pub', ['run', 'webdev', 'serve', '$pathToServe:$port'],
55-
workingDirectory: directory);
56-
webdev.stderr
57-
.transform(const Utf8Decoder())
58-
.transform(const LineSplitter())
59-
.listen(print);
60-
var assetReadyCompleter = Completer();
61-
webdev.stdout
62-
.transform(const Utf8Decoder())
63-
.transform(const LineSplitter())
64-
.listen((line) {
65-
if (line.contains('$port') && !assetReadyCompleter.isCompleted) {
66-
assetReadyCompleter.complete();
67-
}
68-
printOnFailure(line);
69-
});
70-
await assetReadyCompleter.future.timeout(Duration(seconds: 60));
63+
await Process.run('pub', ['get'], workingDirectory: workingDirectory);
64+
65+
daemonClient = await connectClient(
66+
workingDirectory, [], (log) => printOnFailure(log.toString()));
67+
testServer = await TestServer.start(
68+
'localhost',
69+
port,
70+
daemonPort(workingDirectory),
71+
pathToServe,
72+
ReloadConfiguration.none,
73+
false,
74+
daemonClient.buildResults,
75+
);
76+
daemonClient.registerBuildTarget(
77+
DefaultBuildTarget((b) => b..target = pathToServe));
78+
daemonClient.startBuild();
79+
80+
await daemonClient.buildResults
81+
.firstWhere((results) => results.results
82+
.any((result) => result.status == BuildStatus.succeeded))
83+
.timeout(Duration(seconds: 60));
84+
7185
appUrl = 'http://localhost:$port/$path';
7286
var debugPort = await findUnusedPort();
7387
var capabilities = Capabilities.chrome
@@ -108,8 +122,8 @@ class TestContext {
108122
}
109123

110124
Future<Null> tearDown() async {
111-
webdev.kill();
112-
await webdev.exitCode;
125+
await daemonClient.close();
126+
await testServer.stop();
113127
await webDriver?.quit();
114128
chromeDriver.kill();
115129
}
File renamed without changes.
File renamed without changes.

dwds/test/fixtures/server.dart

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:io';
6+
7+
import 'package:build_daemon/data/build_status.dart';
8+
import 'package:dwds/dwds.dart';
9+
import 'package:http_multi_server/http_multi_server.dart';
10+
import 'package:shelf/shelf.dart';
11+
import 'package:shelf/shelf_io.dart' as shelf_io;
12+
13+
class TestServer {
14+
final HttpServer _server;
15+
final String target;
16+
final Dwds dwds;
17+
final Stream<BuildResult> buildResults;
18+
19+
TestServer._(
20+
this.target,
21+
this._server,
22+
this.dwds,
23+
this.buildResults,
24+
bool autoRun,
25+
) {
26+
if (autoRun) {
27+
dwds.connectedApps.listen((connection) {
28+
connection.runMain();
29+
});
30+
}
31+
}
32+
33+
String get host => _server.address.host;
34+
int get port => _server.port;
35+
36+
Future<void> stop() async {
37+
await dwds.stop();
38+
await _server.close(force: true);
39+
}
40+
41+
static Future<TestServer> start(
42+
String hostname,
43+
int port,
44+
int assetServerPort,
45+
String target,
46+
ReloadConfiguration reload,
47+
bool startDevTools,
48+
Stream<BuildResults> buildResults,
49+
) async {
50+
var pipeline = const Pipeline();
51+
52+
var filteredBuildResults = buildResults.asyncMap<BuildResult>((results) =>
53+
results.results.firstWhere((result) => result.target == target));
54+
55+
var dwds = await Dwds.start(
56+
hostname: hostname,
57+
applicationPort: port,
58+
applicationTarget: target,
59+
assetServerPort: assetServerPort,
60+
buildResults: filteredBuildResults,
61+
chromeConnection: () async => null,
62+
logWriter: (level, message) => print(message),
63+
reloadConfiguration: reload,
64+
serveDevTools: startDevTools,
65+
verbose: true,
66+
);
67+
68+
var server = await HttpMultiServer.bind(hostname, port);
69+
shelf_io.serveRequests(server, pipeline.addHandler(dwds.handler));
70+
return TestServer._(
71+
target,
72+
server,
73+
dwds,
74+
filteredBuildResults,
75+
true,
76+
);
77+
}
78+
}

dwds/test/fixtures/utilities.dart

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:io';
6+
7+
import 'package:build_daemon/client.dart';
8+
import 'package:build_daemon/constants.dart';
9+
import 'package:build_daemon/data/server_log.dart';
10+
import 'package:path/path.dart' as p;
11+
12+
/// Connects to the `build_runner` daemon.
13+
Future<BuildDaemonClient> connectClient(String workingDirectory,
14+
List<String> options, Function(ServerLog) logHandler) =>
15+
BuildDaemonClient.connect(
16+
workingDirectory,
17+
// On Windows we need to call the snapshot directly otherwise
18+
// the process will start in a disjoint cmd without access to
19+
// STDIO. We also want to ensure the version of pub is consistent with
20+
// the SDK that was used to launch webdev.
21+
[dartPath, pubSnapshot]
22+
..addAll(['run', 'build_runner', 'daemon'])
23+
..addAll(options),
24+
logHandler: logHandler);
25+
26+
/// The path to the root directory of the SDK.
27+
final String _sdkDir = (() {
28+
// The Dart executable is in "/path/to/sdk/bin/dart", so two levels up is
29+
// "/path/to/sdk".
30+
var aboveExecutable = p.dirname(p.dirname(Platform.resolvedExecutable));
31+
assert(FileSystemEntity.isFileSync(p.join(aboveExecutable, 'version')));
32+
return aboveExecutable;
33+
})();
34+
35+
final String dartPath = p.join(_sdkDir, 'bin', 'dart');
36+
final String pubSnapshot =
37+
p.join(_sdkDir, 'bin', 'snapshots', 'pub.dart.snapshot');
38+
final String pubPath =
39+
p.join(_sdkDir, 'bin', Platform.isWindows ? 'pub.bat' : 'pub');
40+
41+
/// Returns the port of the daemon asset server.
42+
int daemonPort(String workingDirectory) {
43+
var portFile = File(_assetServerPortFilePath(workingDirectory));
44+
if (!portFile.existsSync()) {
45+
throw Exception('Unable to read daemon asset port file.');
46+
}
47+
return int.parse(portFile.readAsStringSync());
48+
}
49+
50+
String _assetServerPortFilePath(String workingDirectory) =>
51+
'${daemonWorkspace(workingDirectory)}/.asset_server_port';

0 commit comments

Comments
 (0)