b87daa7351
This adds a target for running pkg/dynamic_modules/test/runner/main.dart from an aot snapshot, useful when repeating runs for local iteration. I'm not including it with other build targets or using it in the test_matrix because each bot only runs this script once, so it doesn't provide much savings there. Change-Id: I20fe50a82d2a59aca6a0e697658b26b5b7da97c8 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/480744 Reviewed-by: Alexander Markov <alexmarkov@google.com> Commit-Queue: Sigmund Cherem <sigmund@google.com>
196 lines
6.3 KiB
Dart
196 lines
6.3 KiB
Dart
// Copyright (c) 2024, 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.
|
|
|
|
/// Utilities used by various parts of the test harness.
|
|
library;
|
|
|
|
import 'dart:convert';
|
|
import 'dart:io';
|
|
import 'dart:ffi' show Abi;
|
|
|
|
/// Locate the root of the SDK repository.
|
|
///
|
|
/// Note: we don't search for the directory "sdk" because this may not be
|
|
/// available when running this test in a shard.
|
|
Uri repoRoot = (() {
|
|
var root = Platform.environment['REPO_ROOT'];
|
|
if (root != null) return Uri.base.resolve(root);
|
|
Uri script = Platform.script;
|
|
var segments = script.pathSegments;
|
|
var index = segments.lastIndexOf('pkg');
|
|
if (index == -1) {
|
|
index = segments.lastIndexOf(_outFolder); // running from snapshot
|
|
if (index == -1) {
|
|
exitCode = 1;
|
|
throw "error: cannot find the root of the Dart SDK";
|
|
}
|
|
}
|
|
return script.resolve("../" * (segments.length - index - 1));
|
|
})();
|
|
|
|
String _outFolder = Platform.isMacOS ? 'xcodebuild' : 'out';
|
|
|
|
String configuration = () {
|
|
var env = Platform.environment['DART_CONFIGURATION'];
|
|
if (env != null) return env;
|
|
var folderSegments = dartBin.resolve('.').pathSegments;
|
|
for (int i = folderSegments.length - 1; i > 0; i--) {
|
|
if (folderSegments[i] == _outFolder) {
|
|
var candidate = folderSegments[i + 1];
|
|
if (candidate.startsWith('Debug') ||
|
|
candidate.startsWith('Release') ||
|
|
candidate.startsWith('Product')) {
|
|
return candidate;
|
|
}
|
|
}
|
|
}
|
|
return 'ReleaseX64';
|
|
}();
|
|
|
|
// See also utils/gen_kernel/BUILD.gn:
|
|
// dartaotruntime has dart_product_config applied to it and is built in product
|
|
// mode in both release and product builds.
|
|
bool get useProduct => !configuration.startsWith('Debug');
|
|
|
|
String buildFolder = '$_outFolder/$configuration/';
|
|
String arch = Abi.current().toString().split('_')[1];
|
|
String _d8Path = (() {
|
|
if (Platform.isWindows) {
|
|
return 'third_party/d8/windows/$arch/d8.exe';
|
|
} else if (Platform.isLinux) {
|
|
return 'third_party/d8/linux/$arch/d8';
|
|
} else if (Platform.isMacOS) {
|
|
return 'third_party/d8/macos/$arch/d8';
|
|
} else {
|
|
throw UnsupportedError(
|
|
'Unsupported platform for running d8: '
|
|
'${Platform.operatingSystem}',
|
|
);
|
|
}
|
|
})();
|
|
|
|
Uri d8Uri = repoRoot.resolve(_d8Path);
|
|
Uri dartBin = Uri.file(Platform.resolvedExecutable);
|
|
Uri dartAotBin = dartBin.resolve(
|
|
Platform.isWindows ? 'dartaotruntime.exe' : 'dartaotruntime',
|
|
);
|
|
Uri ddcAotSnapshot = dartBin.resolve('snapshots/dartdevc_aot.dart.snapshot');
|
|
Uri kernelWorkerAotSnapshot = dartBin.resolve(
|
|
'snapshots/kernel_worker_aot.dart.snapshot',
|
|
);
|
|
Uri buildRootUri = repoRoot.resolve(buildFolder);
|
|
Uri ddcSdkOutline = buildRootUri.resolve('ddc_outline.dill');
|
|
Uri ddcSdkJs = buildRootUri.resolve('gen/utils/ddc/stable/sdk/ddc/dart_sdk.js');
|
|
Uri ddcPreamblesJs = repoRoot.resolve(
|
|
'sdk/lib/_internal/js_dev_runtime/private/preambles/d8.js',
|
|
);
|
|
Uri ddcSealNativeObjectJs = repoRoot.resolve(
|
|
'sdk/lib/_internal/js_runtime/lib/preambles/seal_native_object.js',
|
|
);
|
|
Uri ddcModuleLoaderJs = repoRoot.resolve(
|
|
'pkg/dev_compiler/lib/js/ddc/ddc_module_loader.js',
|
|
);
|
|
|
|
Uri genKernelSnapshot = buildRootUri.resolve(
|
|
'gen/gen_kernel_aot.dart.snapshot',
|
|
);
|
|
Uri genSnapshotBin = buildRootUri.resolve(
|
|
useProduct ? 'gen_snapshot_product' : 'gen_snapshot',
|
|
);
|
|
Uri dart2bytecodeSnapshot = buildRootUri.resolve(
|
|
'gen/dart2bytecode.dart.snapshot',
|
|
);
|
|
Uri aotRuntimeBin = buildRootUri.resolve(
|
|
useProduct ? 'dartaotruntime_product' : 'dartaotruntime',
|
|
);
|
|
Uri vmPlatformDill = buildRootUri.resolve('vm_platform.dill');
|
|
|
|
Uri dart2wasmSnapshot = dartBin.resolve('snapshots/dart2wasm_product.snapshot');
|
|
Uri dart2wasmPlatformDill = buildRootUri.resolve('dart2wasm_platform.dill');
|
|
Uri dart2wasmLibrariesSpec = repoRoot.resolve('sdk/lib/libraries.json');
|
|
Uri compileBenchmark = repoRoot.resolve('pkg/dart2wasm/tool/compile_benchmark');
|
|
Uri runBenchmark = repoRoot.resolve('pkg/dart2wasm/tool/run_benchmark');
|
|
|
|
// Encodes test results in the format expected by Dart's CI infrastructure.
|
|
class TestResultOutcome {
|
|
// This encoder must generate each output element on its own line.
|
|
final _encoder = JsonEncoder();
|
|
final String configuration;
|
|
final String suiteName;
|
|
final String testName;
|
|
late Duration elapsedTime;
|
|
final String expectedResult;
|
|
late bool matchedExpectations;
|
|
String testOutput;
|
|
|
|
TestResultOutcome({
|
|
required this.configuration,
|
|
this.suiteName = 'dynamic_modules',
|
|
required this.testName,
|
|
this.expectedResult = 'Pass',
|
|
this.testOutput = '',
|
|
});
|
|
|
|
String toRecordJson() => _encoder.convert({
|
|
'name': '$suiteName/$testName',
|
|
'configuration': configuration,
|
|
'suite': suiteName,
|
|
'test_name': testName,
|
|
'time_ms': elapsedTime.inMilliseconds,
|
|
'expected': expectedResult,
|
|
'result': matchedExpectations ? 'Pass' : 'Fail',
|
|
'matches': expectedResult == expectedResult,
|
|
});
|
|
|
|
String toLogJson() => _encoder.convert({
|
|
'name': '$suiteName/$testName',
|
|
'configuration': configuration,
|
|
'result': matchedExpectations ? 'Pass' : 'Fail',
|
|
'log': testOutput,
|
|
});
|
|
}
|
|
|
|
/// Runs [command] with [arguments] in [workingDirectory], and if [verbose] is
|
|
/// `true` then it logs the full command.
|
|
Future<ProcessResult> runProcess(
|
|
String command,
|
|
List<String> arguments,
|
|
String workingDirectory,
|
|
Logger logger,
|
|
String message,
|
|
) async {
|
|
logger.info(
|
|
'command:\n$command ${arguments.join(' ')} from $workingDirectory',
|
|
);
|
|
final result = await Process.run(
|
|
command,
|
|
arguments,
|
|
workingDirectory: workingDirectory,
|
|
);
|
|
logger.info('Exit code: ${result.exitCode}');
|
|
if (result.exitCode != 0) {
|
|
logger.warning('STDOUT: ${result.stdout}');
|
|
logger.warning('STDERR: ${result.stderr}');
|
|
throw 'Error on $message: $command ${arguments.join(' ')} from $workingDirectory\n\n'
|
|
'stdout:\n${result.stdout}\n\n'
|
|
'stderr:\n${result.stderr}';
|
|
} else {
|
|
logger.info('STDOUT: ${result.stdout}');
|
|
logger.info('STDERR: ${result.stderr}');
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/// API to easily control verbosity of the test harness.
|
|
class Logger {
|
|
final bool verbose;
|
|
Logger([this.verbose = false]);
|
|
void info(String message) {
|
|
if (verbose) print(message);
|
|
}
|
|
|
|
void warning(String message) => print(message);
|
|
void error(String message) => print(message);
|
|
}
|