Skip to content

Add experimental test fixtures and tests #1937

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

Merged
Merged
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion dwds/lib/src/services/expression_compiler_service.dart
Original file line number Diff line number Diff line change
@@ -95,7 +95,7 @@ class _Compiler {
moduleFormat,
if (verbose) '--verbose',
soundNullSafety ? '--sound-null-safety' : '--no-sound-null-safety',
for (var experiment in experiments) '--enable-experiment=$experiment',
for (final experiment in experiments) '--enable-experiment=$experiment',
];

_logger.info('Starting...');
25 changes: 15 additions & 10 deletions dwds/test/fixtures/context.dart
Original file line number Diff line number Diff line change
@@ -199,6 +199,7 @@ class TestContext {
bool launchChrome = true,
bool isFlutterApp = false,
bool isInternalBuild = false,
List<String> experiments = const <String>[],
Copy link
Contributor

Choose a reason for hiding this comment

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

I feel like this parameter makes more sense as part of the TestContext constructors since the experiments are tied to the package being used

Copy link
Contributor Author

@annagrin annagrin Feb 4, 2023

Choose a reason for hiding this comment

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

I am not sure they are always tied to the package - I can imagine an experiment that does not need changes to the code, just the compilation of it. I'll ask Nick to confirm.

Copy link
Contributor

Choose a reason for hiding this comment

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

That makes sense!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Confirmed with Nick, indeed we can have experiments that work on the same code.

}) async {
// Generate missing SDK assets if needed.
final sdkConfigurationProvider =
@@ -264,6 +265,8 @@ class TestContext {
'--define',
'build_web_compilers|ddc=generate-full-dill=true',
],
for (final experiment in experiments)
'--enable-experiment=$experiment',
'--verbose',
];
_daemonClient =
@@ -293,6 +296,7 @@ class TestContext {
port,
verbose: verboseCompiler,
sdkConfigurationProvider: sdkConfigurationProvider,
experiments: experiments,
);
expressionCompiler = ddcService;
}
@@ -319,16 +323,17 @@ class TestContext {
);

_webRunner = ResidentWebRunner(
entry,
urlEncoder,
p.toUri(workingDirectory),
_packageConfigFile,
packageUriMapper,
[p.toUri(workingDirectory)],
'org-dartlang-app',
outputDir.path,
nullSafety == NullSafety.sound,
verboseCompiler,
mainUri: entry,
urlTunneler: urlEncoder,
projectDirectory: p.toUri(workingDirectory),
packageConfigFile: _packageConfigFile,
packageUriMapper: packageUriMapper,
fileSystemRoots: [p.toUri(workingDirectory)],
fileSystemScheme: 'org-dartlang-app',
outputPath: outputDir.path,
soundNullSafety: nullSafety == NullSafety.sound,
experiments: experiments,
verbose: verboseCompiler,
);

final assetServerPort = await findUnusedPort();
133 changes: 133 additions & 0 deletions dwds/test/records_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// Copyright (c) 2020, 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.

@TestOn('vm')
@Timeout(Duration(minutes: 2))

import 'package:dwds/src/connections/debug_connection.dart';
import 'package:dwds/src/services/chrome_proxy_service.dart';
import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart';

import 'fixtures/context.dart';
import 'fixtures/logging.dart';

class TestSetup {
TestContext context;

TestSetup.sound()
: context = TestContext.withSoundNullSafety(
packageName: '_experimentSound',
webAssetsPath: 'web',
dartEntryFileName: 'main.dart',
htmlEntryFileName: 'index.html',
);

ChromeProxyService get service =>
fetchChromeProxyService(context.debugConnection);
}

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

for (var compilationMode in CompilationMode.values) {
await _runTests(
compilationMode: compilationMode,
debug: debug,
);
}
}

Future<void> _runTests({
required CompilationMode compilationMode,
required bool debug,
}) async {
final setup = TestSetup.sound();
final context = setup.context;
late VmServiceInterface service;
late Stream<Event> stream;
late String isolateId;
late ScriptRef mainScript;

onBreakPoint(breakPointId, body) => _onBreakPoint(
setup,
stream,
isolateId,
mainScript,
breakPointId,
body,
);

group('$compilationMode |', () {
setUpAll(() async {
setCurrentLogWriter(debug: debug);
await context.setUp(
compilationMode: compilationMode,
enableExpressionEvaluation: true,
verboseCompiler: debug,
experiments: ['records'],
);
service = setup.service;

final vm = await service.getVM();
isolateId = vm.isolates!.first.id!;
final scripts = await service.getScripts(isolateId);

await service.streamListen('Debug');
stream = service.onEvent('Debug');

mainScript = scripts.scripts!
.firstWhere((each) => each.uri!.contains('main.dart'));
});

tearDownAll(context.tearDown);

setUp(() => setCurrentLogWriter(debug: debug));
tearDown(() => service.resume(isolateId));

test('simple records', () async {
await onBreakPoint('printSimpleLocal', (event) async {
final frame = event.topFrame!.index!;
final result = await service.evaluateInFrame(
isolateId,
frame,
'record',
);

expect(result, isA<InstanceRef>());
return result as InstanceRef;
});
});
});
}

Future<void> _onBreakPoint(
TestSetup setup,
Stream<Event> stream,
String isolateId,
ScriptRef script,
String breakPointId,
Future<void> Function(Event event) body,
) async {
final context = setup.context;
final service = setup.service;

Breakpoint? bp;
try {
final line =
await context.findBreakpointLine(breakPointId, isolateId, script);
bp = await service.addBreakpointWithScriptUri(isolateId, script.uri!, line);

final event =
await stream.firstWhere((e) => e.kind == EventKind.kPauseBreakpoint);

await body(event);
} finally {
// Remove breakpoint so it doesn't impact other tests or retries.
if (bp != null) {
await service.removeBreakpoint(isolateId, bp.id!);
}
}
}
17 changes: 17 additions & 0 deletions fixtures/_experimentSound/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: _experiment
version: 1.0.0
description: >-
A fake package used for testing experimental language features.
publish_to: none

environment:
sdk: ">=3.0.0-134.0.dev<4.0.0"

dependencies:
intl: ^0.17.0
path: ^1.8.2

dev_dependencies:
build_runner: ^2.4.0
build_web_compilers: ^4.0.0

7 changes: 7 additions & 0 deletions fixtures/_experimentSound/web/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<html>

<head>
<script defer src="main.dart.js"></script>
</head>

</html>
21 changes: 21 additions & 0 deletions fixtures/_experimentSound/web/main.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// 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.

import 'dart:async';
import 'dart:core';
import 'dart:html';

void main() {
// for evaluation
Timer.periodic(const Duration(seconds: 1), (_) {
printSimpleLocal();
});

document.body!.appendText('Program is running!');
}

void printSimpleLocal() {
final record = (true, 3);
print(record); // Breakpoint: printSimpleLocal
}
5 changes: 4 additions & 1 deletion frontend_server_common/lib/src/frontend_server_client.dart
Original file line number Diff line number Diff line change
@@ -260,6 +260,7 @@ class ResidentCompiler {
required this.fileSystemScheme,
required this.platformDill,
required this.soundNullSafety,
this.experiments = const <String>[],
this.verbose = false,
CompilerMessageConsumer compilerMessageConsumer = defaultConsumer,
}) : _stdoutHandler = StdoutHandler(consumer: compilerMessageConsumer);
@@ -271,6 +272,7 @@ class ResidentCompiler {
final String fileSystemScheme;
final String platformDill;
final bool soundNullSafety;
final List<String> experiments;
final bool verbose;

/// The path to the root of the Dart SDK used to compile.
@@ -390,7 +392,8 @@ class ResidentCompiler {
'--experimental-emit-debug-metadata',
if (soundNullSafety) '--sound-null-safety',
if (!soundNullSafety) '--no-sound-null-safety',
if (verbose) '--verbose'
if (verbose) '--verbose',
for (final experiment in experiments) '--enable-experiment=$experiment',
];

_logger.info(args.join(' '));
28 changes: 16 additions & 12 deletions frontend_server_common/lib/src/resident_runner.dart
Original file line number Diff line number Diff line change
@@ -25,17 +25,19 @@ final Uri summaryDillSound =
class ResidentWebRunner {
final _logger = Logger('ResidentWebRunner');

ResidentWebRunner(
this.mainUri,
this.urlTunneler,
this.projectDirectory,
this.packageConfigFile,
this.packageUriMapper,
this.fileSystemRoots,
this.fileSystemScheme,
this.outputPath,
this.soundNullSafety,
bool verbose) {
ResidentWebRunner({
required this.mainUri,
required this.urlTunneler,
required this.projectDirectory,
required this.packageConfigFile,
required this.packageUriMapper,
required this.fileSystemRoots,
required this.fileSystemScheme,
required this.outputPath,
required this.soundNullSafety,
this.experiments = const <String>[],
bool verbose = false,
}) {
generator = ResidentCompiler(
dartSdkPath,
projectDirectory: projectDirectory,
@@ -45,8 +47,9 @@ class ResidentWebRunner {
soundNullSafety ? '$summaryDillSound' : '$summaryDillUnsound',
fileSystemRoots: fileSystemRoots,
fileSystemScheme: fileSystemScheme,
verbose: verbose,
soundNullSafety: soundNullSafety,
experiments: experiments,
verbose: verbose,
);
expressionCompiler = TestExpressionCompiler(generator);
}
@@ -60,6 +63,7 @@ class ResidentWebRunner {
final List<Uri> fileSystemRoots;
final String fileSystemScheme;
final bool soundNullSafety;
final List<String> experiments;

late ResidentCompiler generator;
late ExpressionCompiler expressionCompiler;
2 changes: 1 addition & 1 deletion webdev/lib/src/command/shared.dart
Original file line number Diff line number Diff line change
@@ -89,7 +89,7 @@ List<String> buildRunnerArgs(
..add('build_web_compilers|ddc=generate-full-dill=true');
}

for (var experiment in configuration.experiments) {
for (final experiment in configuration.experiments) {
arguments.add('--enable-experiment=$experiment');
}