blob: ebb780ea5242859603340ff36e9308a1d740a509 [file] [edit]
// Copyright (c) 2025, 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 'package:dwds_test_common/logging.dart';
import 'package:dwds_test_common/test_sdk_configuration.dart';
import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart';
import 'fixtures/context.dart';
import 'fixtures/project.dart';
import 'fixtures/utilities.dart';
const originalString = 'Hello World!';
const newString = 'Bonjour le monde!';
void runTests({
required TestSdkConfigurationProvider provider,
required CompilationMode compilationMode,
}) {
final project = TestProject.testHotReload;
final context = TestContext(project, provider);
Future<void> recompile() async {
await context.recompile(fullRestart: false);
}
Future<void> makeEditAndRecompile() async {
await context.makeEdits([
(
file: 'library1.dart',
originalString: originalString,
newString: newString,
),
]);
await recompile();
}
// Call the method `evaluate` in the program and wait for `expectedString` to
// be printed to the console.
Future<void> callEvaluateAndWaitForLog(String expectedString) async {
final client = context.debugConnection.vmService;
final completer = Completer<void>();
final subscription = context.webkitDebugger.onConsoleAPICalled.listen((e) {
if (e.args.first.value == expectedString) {
completer.complete();
}
});
final vm = await client.getVM();
final isolate = await client.getIsolate(vm.isolates!.first.id!);
final rootLib = isolate.rootLib;
await client.evaluate(isolate.id!, rootLib!.id!, 'evaluate()');
await completer.future.timeout(
const Duration(minutes: 1),
onTimeout: () {
throw TimeoutException(
"Failed to find log: '$expectedString' in console.",
);
},
);
await subscription.cancel();
}
group('Injected client', () {
late VmService fakeClient;
setUp(() async {
setCurrentLogWriter(debug: provider.verbose);
await context.setUp(
testSettings: TestSettings(
enableExpressionEvaluation: true,
compilationMode: compilationMode,
moduleFormat: provider.ddcModuleFormat,
canaryFeatures: provider.canaryFeatures,
),
);
fakeClient = await context.connectFakeClient();
});
tearDown(() async {
await context.tearDown();
});
test('can hot reload', () async {
final client = context.debugConnection.vmService;
await makeEditAndRecompile();
final vm = await client.getVM();
final isolate = await client.getIsolate(vm.isolates!.first.id!);
final report = await fakeClient.reloadSources(isolate.id!);
expect(report.success, true);
await callEvaluateAndWaitForLog(newString);
});
test('can hot reload with no changes, hot reload with changes, and '
'hot reload again with no changes', () async {
final client = context.debugConnection.vmService;
// Empty hot reload.
await recompile();
final vm = await client.getVM();
final isolate = await client.getIsolate(vm.isolates!.first.id!);
var report = await fakeClient.reloadSources(isolate.id!);
expect(report.success, true);
await callEvaluateAndWaitForLog(originalString);
// Hot reload.
await makeEditAndRecompile();
report = await fakeClient.reloadSources(isolate.id!);
expect(report.success, true);
await callEvaluateAndWaitForLog(newString);
// Empty hot reload.
await recompile();
report = await fakeClient.reloadSources(isolate.id!);
expect(report.success, true);
await callEvaluateAndWaitForLog(newString);
});
}, timeout: const Timeout.factor(2));
}