Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plumbing flags required for running tests with the DDC module system. #2295

Merged
merged 29 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
61f964b
Updating the legacy loader to use the new DDC module loader API
Markzipan Nov 27, 2023
e17f872
Adding tests and plumbing for the DDC module system.
Markzipan Nov 27, 2023
6a01aad
updating changelog
Markzipan Dec 1, 2023
2e4d0a2
Merge branch 'dart-lang:master' into ddc-test-plumbing
Markzipan Dec 1, 2023
188a5ae
Restructuring asset bundling and flags
Markzipan Dec 4, 2023
c055748
Restructuring asset bundling and flags
Markzipan Dec 4, 2023
cc66e55
Updating test sdk paths
Markzipan Dec 5, 2023
e37da6b
Moving the module format specifier to an enum and unioning static ass…
Markzipan Dec 7, 2023
dcbea77
Fixing analysis errors
Markzipan Dec 7, 2023
40ac194
Exposing utilities/ddc_names.dart
Markzipan Dec 7, 2023
83d5feb
removing extraneous export
Markzipan Dec 7, 2023
6d5bcfe
Fixing race condition without extraneous plumbing.
Markzipan Dec 12, 2023
2cff2ce
Extending tests and restructuring logic into helpers
Markzipan Dec 12, 2023
84ee640
Merge branch 'master' into ddc-test-plumbing
Markzipan Dec 12, 2023
77bd6eb
Extending sdk config tests and moving autorun functionality into the …
Markzipan Dec 13, 2023
43e6446
Merge branch 'master' into ddc-test-plumbing
Markzipan Dec 13, 2023
69fa508
Merge branch 'master' into ddc-test-plumbing
Markzipan Dec 14, 2023
7330d99
Fixing analysis errors
Markzipan Dec 14, 2023
b30a41f
adding missing DDC sound sdks to asset generator test
Markzipan Dec 14, 2023
5b9854e
Fixing ddc and amd paths
Markzipan Dec 14, 2023
c606696
Keeping the first instance of an app connection and extending timeouts
Markzipan Dec 18, 2023
dafca8a
formatting files
Markzipan Dec 19, 2023
819bcf5
Merge remote-tracking branch 'origin' into ddc-test-plumbing
Markzipan Jan 9, 2024
42c674e
Exposing utilities/ddc_names.dart
Markzipan Dec 7, 2023
f4ae7e2
Loosen `vm_service` constraints and prepare DWDS for release to 23.1.…
elliette Jan 9, 2024
4f143c9
Reset DWDS to version `23.2.0-wip` after release (#2334)
elliette Jan 10, 2024
ac28b96
Adding changelog
Markzipan Jan 10, 2024
e4c7df0
Merge remote-tracking branch 'origin/master' into ddc-test-plumbing
Markzipan Jan 10, 2024
dbcb892
Merge remote-tracking branch 'origin' into ddc-test-plumbing
Markzipan Jan 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions dwds/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
- Restructure `LoadStrategy` to provide build settings. - [#2270](https://github.com/dart-lang/webdev/pull/2270)
- Add `FrontendServerLegacyStrategyProvider` and update bootstrap generation logic for `LegacyStrategy` - [#2285](https://github.com/dart-lang/webdev/pull/2285)
- Tolerate failures to detect a dart execution context. - [#2286](https://github.com/dart-lang/webdev/pull/2286)
- Enabling tests that run with the DDC module system. - [#2295](https://github.com/dart-lang/webdev/pull/2295)

## 22.1.0
- Update `package:vm_service` constraint to `^13.0.0`. - [#2265](https://github.com/dart-lang/webdev/pull/2265)
Expand Down
2 changes: 2 additions & 0 deletions dwds/lib/dart_web_debug_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class Dwds {
required Stream<BuildResult> buildResults,
required ConnectionProvider chromeConnection,
required ToolConfiguration toolConfiguration,
Future? completeBeforeHandlingConnections,
Markzipan marked this conversation as resolved.
Show resolved Hide resolved
}) async {
globalToolConfiguration = toolConfiguration;
final debugSettings = toolConfiguration.debugSettings;
Expand Down Expand Up @@ -128,6 +129,7 @@ class Dwds {
injected,
debugSettings.spawnDds,
debugSettings.launchDevToolsInNewWindow,
completeBeforeHandlingConnections,
);

return Dwds._(
Expand Down
3 changes: 3 additions & 0 deletions dwds/lib/src/handlers/dev_handler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class DevHandler {
final bool _useSseForInjectedClient;
final bool _spawnDds;
final bool _launchDevToolsInNewWindow;
final Future? _completeBeforeHandlingConnections;
final ExpressionCompiler? _expressionCompiler;
final DwdsInjector _injected;

Expand All @@ -91,6 +92,7 @@ class DevHandler {
this._injected,
this._spawnDds,
this._launchDevToolsInNewWindow,
this._completeBeforeHandlingConnections,
) {
_subs.add(buildResults.listen(_emitBuildResults));
_listen();
Expand Down Expand Up @@ -494,6 +496,7 @@ class DevHandler {
: WebSocketSocketHandler();
_sseHandlers[uri.path] = handler;
final injectedConnections = handler.connections;
await _completeBeforeHandlingConnections;
while (await injectedConnections.hasNext) {
_handleConnection(await injectedConnections.next);
}
Expand Down
6 changes: 5 additions & 1 deletion dwds/lib/src/loaders/legacy.dart
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,11 @@ class LegacyStrategy extends LoadStrategy {
return '''
$_baseUrlScript
var scripts = ${const JsonEncoder.withIndent(" ").convert(scripts)};
window.\$dartLoader.loadScripts(scripts);
window.\$dartLoader.loadConfig.loadScriptFn = function(loader) {
loader.addScriptsToQueue(scripts, null);
loader.loadEnqueuedModules();
};
window.\$dartLoader.loader.nextAttempt();
''';
}

Expand Down
4 changes: 4 additions & 0 deletions dwds/lib/src/services/expression_compiler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ class CompilerOptions {
required this.canaryFeatures,
required this.experiments,
});

// TODO(markzipan): Remove this after DDC migrates to a single module system.
bool get usesDDCModuleSystem =>
Markzipan marked this conversation as resolved.
Show resolved Hide resolved
moduleFormat == 'ddc' || moduleFormat == 'legacy';
}

/// Result of compilation of dart expression to JavaScript
Expand Down
5 changes: 5 additions & 0 deletions dwds/lib/utilities.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Copyright (c) 2023, 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.

export 'src/utilities/ddc_names.dart';
99 changes: 92 additions & 7 deletions dwds/test/fixtures/context.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// 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.

import 'dart:async';
import 'dart:convert';
import 'dart:io';

Expand All @@ -14,8 +15,9 @@ import 'package:dwds/src/connections/app_connection.dart';
import 'package:dwds/src/connections/debug_connection.dart';
import 'package:dwds/src/debugging/webkit_debugger.dart';
import 'package:dwds/src/loaders/build_runner_require.dart';
import 'package:dwds/src/loaders/frontend_server_legacy.dart';
import 'package:dwds/src/loaders/frontend_server_require.dart';
import 'package:dwds/src/loaders/require.dart';
import 'package:dwds/src/loaders/strategy.dart';
import 'package:dwds/src/readers/proxy_server_asset_reader.dart';
import 'package:dwds/src/services/chrome_proxy_service.dart';
import 'package:dwds/src/services/expression_compiler_service.dart';
Expand Down Expand Up @@ -58,7 +60,17 @@ Matcher isRPCErrorWithCode(int code) =>
isA<RPCError>().having((e) => e.code, 'code', equals(code));
Matcher throwsRPCErrorWithCode(int code) => throwsA(isRPCErrorWithCode(code));

enum CompilationMode { buildDaemon, frontendServer }
enum CompilationMode {
buildDaemon,
// Uses DDC's AMD module system
frontendServer,
// Uses DDC's DDC/legacy module system
frontendServerDdc;
Markzipan marked this conversation as resolved.
Show resolved Hide resolved

bool get usesFrontendServer =>
Markzipan marked this conversation as resolved.
Show resolved Hide resolved
this == CompilationMode.frontendServer ||
this == CompilationMode.frontendServerDdc;
}

class TestContext {
final TestProject project;
Expand Down Expand Up @@ -204,7 +216,7 @@ class TestContext {
ExpressionCompiler? expressionCompiler;
AssetReader assetReader;
Stream<BuildResults> buildResults;
RequireStrategy requireStrategy;
LoadStrategy loadStrategy;
String basePath = '';
String filePathToServe = project.filePathToServe;

Expand Down Expand Up @@ -268,7 +280,7 @@ class TestContext {
expressionCompiler = ddcService;
}

requireStrategy = BuildRunnerRequireStrategyProvider(
loadStrategy = BuildRunnerRequireStrategyProvider(
assetHandler,
testSettings.reloadConfiguration,
assetReader,
Expand Down Expand Up @@ -332,7 +344,73 @@ class TestContext {
basePath = webRunner.devFS.assetServer.basePath;
assetReader = webRunner.devFS.assetServer;
_assetHandler = webRunner.devFS.assetServer.handleRequest;
requireStrategy = FrontendServerRequireStrategyProvider(
loadStrategy = FrontendServerRequireStrategyProvider(
testSettings.reloadConfiguration,
assetReader,
packageUriMapper,
() async => {},
buildSettings,
).strategy;

buildResults = const Stream<BuildResults>.empty();
}
break;
case CompilationMode.frontendServerDdc:
Markzipan marked this conversation as resolved.
Show resolved Hide resolved
{
filePathToServe = webCompatiblePath([
project.directoryToServe,
project.filePathToServe,
]);

_logger.info('Serving: $filePathToServe');

final entry = p.toUri(
p.join(project.webAssetsPath, project.dartEntryFileName),
);
final fileSystem = LocalFileSystem();
final packageUriMapper = await PackageUriMapper.create(
fileSystem,
project.packageConfigFile,
useDebuggerModuleNames: testSettings.useDebuggerModuleNames,
);

final compilerOptions = TestCompilerOptions(
nullSafety: project.nullSafety,
experiments: buildSettings.experiments,
canaryFeatures: buildSettings.canaryFeatures,
moduleFormat: 'ddc',
);

_webRunner = ResidentWebRunner(
mainUri: entry,
urlTunneler: debugSettings.urlEncoder,
projectDirectory: p.toUri(project.absolutePackageDirectory),
packageConfigFile: project.packageConfigFile,
packageUriMapper: packageUriMapper,
fileSystemRoots: [p.toUri(project.absolutePackageDirectory)],
fileSystemScheme: 'org-dartlang-app',
outputPath: outputDir.path,
compilerOptions: compilerOptions,
sdkLayout: sdkLayout,
verbose: testSettings.verboseCompiler,
);

final assetServerPort = await findUnusedPort();
await webRunner.run(
fileSystem,
appMetadata.hostname,
assetServerPort,
filePathToServe,
);

if (testSettings.enableExpressionEvaluation) {
expressionCompiler = webRunner.expressionCompiler;
}

basePath = webRunner.devFS.assetServer.basePath;
assetReader = webRunner.devFS.assetServer;
_assetHandler = webRunner.devFS.assetServer.handleRequest;
loadStrategy = FrontendServerLegacyStrategyProvider(
testSettings.reloadConfiguration,
assetReader,
packageUriMapper,
Expand Down Expand Up @@ -380,6 +458,10 @@ class TestContext {
),
);
}

// The debugger tab must be enabled and connected before certain
// listeners in DWDS run.
final tabConnectionCompleter = Completer();
final connection = ChromeConnection('localhost', debugPort);

_testServer = await TestServer.start(
Expand All @@ -389,11 +471,12 @@ class TestContext {
port: port,
assetHandler: assetHandler,
assetReader: assetReader,
strategy: requireStrategy,
strategy: loadStrategy,
target: project.directoryToServe,
buildResults: buildResults,
chromeConnection: () async => connection,
autoRun: testSettings.autoRun,
completeBeforeHandlingConnections: tabConnectionCompleter.future,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'l like to understand this better - could you please add a description in comments describing why it this needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a short description to the this PR's description.

Plumbing a handler through DWDS that restricts when page connection handlers are attached. This fixes a race condition I encountered (replicable by adding a Future.delayed(someDuration) just before [getTab](https://github.com/dart-lang/webdev/blob/63e09e5060813a971ec0f95472613d6958f75b95/dwds/test/fixtures/context.dart#L404)).

Basically, there's a race condition between two 'sister' async events that only succeeds if events happen to interleave.

Basically Promise Train A -> B -> C and Train X -> Y -> Z hangs iff the execution is not A -> X -> B -> Y (or something similar).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am curious about the exact details here (given that the plumbing changes the interface and will need a major version update) - could you please add more information on what exactly is the set of events and how it hangs? Also adding the comments in code so we can avoid this in the future.

);

_appUrl = basePath.isEmpty
Expand All @@ -406,7 +489,9 @@ class TestContext {
if (tab != null) {
_tabConnection = await tab.connect();
await tabConnection.runtime.enable();
await tabConnection.debugger.enable();
await tabConnection.debugger
.enable()
.then((_) => tabConnectionCompleter.complete());
} else {
throw StateError('Unable to connect to tab.');
}
Expand Down
6 changes: 4 additions & 2 deletions dwds/test/fixtures/server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import 'package:dwds/asset_reader.dart';
import 'package:dwds/dart_web_debug_service.dart';
import 'package:dwds/data/build_result.dart';
import 'package:dwds/src/config/tool_configuration.dart';
import 'package:dwds/src/loaders/require.dart';
import 'package:dwds/src/loaders/strategy.dart';
import 'package:dwds/src/utilities/server.dart';
import 'package:logging/logging.dart';
import 'package:shelf/shelf.dart';
Expand Down Expand Up @@ -62,12 +62,13 @@ class TestServer {
required AppMetadata appMetadata,
required Handler assetHandler,
required AssetReader assetReader,
required RequireStrategy strategy,
required LoadStrategy strategy,
required String target,
required Stream<daemon.BuildResults> buildResults,
required Future<ChromeConnection> Function() chromeConnection,
required bool autoRun,
int? port,
Future? completeBeforeHandlingConnections,
}) async {
var pipeline = const Pipeline();

Expand Down Expand Up @@ -100,6 +101,7 @@ class TestServer {
buildResults: filteredBuildResults,
chromeConnection: chromeConnection,
toolConfiguration: toolConfiguration,
completeBeforeHandlingConnections: completeBeforeHandlingConnections,
);

final server = await startHttpServer('localhost', port: port);
Expand Down
2 changes: 1 addition & 1 deletion dwds/test/fixtures/utilities.dart
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,8 @@ class TestCompilerOptions extends CompilerOptions {
required NullSafety nullSafety,
required super.canaryFeatures,
required List<String> experiments,
super.moduleFormat = 'amd',
Markzipan marked this conversation as resolved.
Show resolved Hide resolved
}) : super(
moduleFormat: 'amd',
soundNullSafety: nullSafety == NullSafety.sound,
experiments: const <String>[],
);
Expand Down
50 changes: 50 additions & 0 deletions dwds/test/frontend_server_ddc_evaluate_sound_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) 2023, 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.

@Tags(['daily'])
@TestOn('vm')
@Timeout(Duration(minutes: 5))

import 'dart:io';

import 'package:test/test.dart';
import 'package:test_common/test_sdk_configuration.dart';

import 'evaluate_common.dart';
import 'fixtures/context.dart';
import 'fixtures/project.dart';

void main() async {
// Enable verbose logging for debugging.
final debug = false;

final provider =
TestSdkConfigurationProvider(verbose: debug, ddcModuleSystem: true);
tearDownAll(provider.dispose);

for (var useDebuggerModuleNames in [false, true]) {
group('Debugger module names: $useDebuggerModuleNames |', () {
final nullSafety = NullSafety.sound;
group('${nullSafety.name} null safety | DDC module system |', () {
for (var indexBaseMode in IndexBaseMode.values) {
group(
'with ${indexBaseMode.name} |',
() {
testAll(
provider: provider,
compilationMode: CompilationMode.frontendServerDdc,
indexBaseMode: indexBaseMode,
nullSafety: nullSafety,
useDebuggerModuleNames: useDebuggerModuleNames,
debug: debug,
);
},
// https://github.com/dart-lang/sdk/issues/49277
skip: indexBaseMode == IndexBaseMode.base && Platform.isWindows,
);
}
});
});
}
}
5 changes: 4 additions & 1 deletion frontend_server_common/lib/src/asset_server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,13 @@ class TestAssetServer implements AssetReader {
int port,
UrlEncoder? urlTunneler,
PackageUriMapper packageUriMapper,
bool ddcModuleSystem,
) async {
final address = (await InternetAddress.lookup(hostname)).first;
final httpServer = await HttpServer.bind(address, port);
final sdkLayout = TestSdkLayout.createDefault(sdkDirectory);
final sdkLayout = ddcModuleSystem
Markzipan marked this conversation as resolved.
Show resolved Hide resolved
? TestSdkLayout.createDdcDefault(sdkDirectory)
: TestSdkLayout.createDefault(sdkDirectory);
final server = TestAssetServer(
index, httpServer, packageUriMapper, address, fileSystem, sdkLayout);
return server;
Expand Down
Loading
Loading