182 lines
5.2 KiB
Dart
182 lines
5.2 KiB
Dart
/*
|
|
This file is part of KDDockWidgets.
|
|
|
|
SPDX-FileCopyrightText: 2023 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
|
|
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
|
|
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
|
*/
|
|
|
|
// A script that runs the tests but first ensures the bundle is built
|
|
|
|
import 'dart:io';
|
|
import 'src/flutter/utils.dart';
|
|
|
|
bool isAOT = false;
|
|
bool isASAN = false;
|
|
bool isLSAN = false;
|
|
bool useGDB = false;
|
|
bool ubsanPrintStacks = false;
|
|
|
|
String kddwSourceDir() {
|
|
return Platform.script.path.replaceAll("run_flutter_tests.dart", "");
|
|
}
|
|
|
|
Future<int> runTests(String? singleTestName, List<String> singleTestArgs,
|
|
String buildDir) async {
|
|
if (!await Directory(buildDir).exists()) {
|
|
final presetName = buildDir
|
|
.replaceAll(kddwSourceDir(), "")
|
|
.replaceAll("build-", "")
|
|
.replaceAll("/", "");
|
|
print("ERROR: Could not find $buildDir.\n"
|
|
"Be sure to build the preset: $presetName");
|
|
return -1;
|
|
}
|
|
|
|
if (singleTestName != null &&
|
|
!await File("$buildDir/bin/$singleTestName").exists()) {
|
|
print("ERROR: Could not find executable $buildDir/bin/$singleTestName\n");
|
|
return -1;
|
|
}
|
|
|
|
/// Make sure the C++ is built:
|
|
int result = await runCommand("ninja", [], workingDirectory: buildDir);
|
|
if (result != 0) {
|
|
print("Failed to build C++");
|
|
return result;
|
|
}
|
|
|
|
/// Make sure the flutter bundle is built:
|
|
final flutterEmbedderDir = "${kddwSourceDir()}/tests/flutter_tests_embedder/";
|
|
result = await runCommand(
|
|
"flutter", ["build", "bundle", "--suppress-analytics"],
|
|
workingDirectory: flutterEmbedderDir);
|
|
|
|
if (result != 0) {
|
|
print("Failed to build bundle");
|
|
return result;
|
|
}
|
|
|
|
if (isAOT) {
|
|
result = await runCommand(
|
|
"flutter", ["build", "linux", "--release", "--suppress-analytics"],
|
|
workingDirectory: flutterEmbedderDir);
|
|
|
|
if (result != 0) {
|
|
print("Failed to build AOT snapshot (libapp.so)");
|
|
return result;
|
|
}
|
|
}
|
|
|
|
final String aotValue = isAOT ? "1" : "0";
|
|
final String lsanValue = isLSAN ? "1" : "0";
|
|
final String asanOptions = "detect_leaks=$lsanValue";
|
|
final String ubsanOptions = ubsanPrintStacks ? "print_stacktrace=1" : "";
|
|
final String gensnapshotOptions = "--no-strip";
|
|
final String libraryPath = "$buildDir/lib/";
|
|
|
|
print("export KDDW_FLUTTER_TESTS_USE_AOT=$aotValue");
|
|
print("export ASAN_OPTIONS=$asanOptions");
|
|
if (ubsanPrintStacks) print("export UBSAN_OPTIONS=$ubsanOptions");
|
|
print("export DARTAGNAN_BINDINGSLIB_PATH=$libraryPath");
|
|
print("\n");
|
|
|
|
final env = {
|
|
"KDDW_FLUTTER_TESTS_USE_AOT": aotValue,
|
|
"ASAN_OPTIONS": asanOptions,
|
|
"EXTRA_GEN_SNAPSHOT_OPTIONS": gensnapshotOptions,
|
|
if (ubsanPrintStacks) "UBSAN_OPTIONS": ubsanOptions,
|
|
"DARTAGNAN_BINDINGSLIB_PATH": libraryPath
|
|
};
|
|
|
|
/// Now we can run the tests:
|
|
|
|
if (singleTestName == null) {
|
|
// Run everything:
|
|
return await runCommand("ctest", ["-j1", "--output-on-failure"],
|
|
workingDirectory: buildDir, env: env);
|
|
} else {
|
|
// Run a single test:
|
|
final String executableName = useGDB ? "gdb" : "bin/$singleTestName";
|
|
List<String> args = [
|
|
// "--disable-service-auth-codes",
|
|
// "--verbose-logging",
|
|
// "--start-paused"
|
|
if (useGDB) ...[
|
|
"-ex=run",
|
|
"--args",
|
|
"bin/$singleTestName",
|
|
...singleTestArgs
|
|
] else
|
|
...singleTestArgs
|
|
];
|
|
return await runCommand(executableName, args,
|
|
workingDirectory: buildDir, env: env);
|
|
}
|
|
}
|
|
|
|
void printUsage() {
|
|
print(
|
|
"Usage: dart run_flutter_tests.dart [--aot] [--asan] [--lsan] [--ubsan-stacktraces]");
|
|
print("Or specify a single test to run:");
|
|
print(
|
|
"dart run_flutter_tests.dart [--aot] [--asan] [--lsan] [--ubsan-stacktraces] [--gdb] <test_name> [args]");
|
|
print("Use asan_symbolize.py if --lsan isn't symbolizing libapp.so");
|
|
}
|
|
|
|
String calculateBuildDir() {
|
|
String result;
|
|
|
|
if (isAOT) {
|
|
result = "build-dev-flutter-aot";
|
|
} else {
|
|
result = "build-dev-flutter";
|
|
}
|
|
|
|
if (isASAN) result += "-asan";
|
|
|
|
print("Using $result");
|
|
return "${kddwSourceDir()}${result}/";
|
|
}
|
|
|
|
Future<void> main(List<String> args) async {
|
|
final _args = List<String>.from(args);
|
|
|
|
isLSAN = _args.remove("--lsan");
|
|
isASAN = _args.remove("--asan") || isLSAN;
|
|
isAOT =
|
|
_args.remove("--aot") || isLSAN; // LSAN requires AOT for simbolization
|
|
useGDB = _args.remove("--gdb");
|
|
ubsanPrintStacks = _args.remove("--ubsan-stacktraces");
|
|
final bool isHelp = _args.remove("--help") || _args.remove("-h");
|
|
|
|
if (isHelp) {
|
|
printUsage();
|
|
exit(0);
|
|
}
|
|
|
|
if (ubsanPrintStacks && !isASAN) {
|
|
print("ERROR: --ubsan-stacktraces requires --asan");
|
|
exit(1);
|
|
}
|
|
|
|
final String? singleTestName = _args.isEmpty ? null : _args.first;
|
|
List<String> singleTestArgs = _args.isEmpty ? [] : _args.sublist(1);
|
|
|
|
final result =
|
|
await runTests(singleTestName, singleTestArgs, calculateBuildDir());
|
|
final bool isSuccess = result == 0;
|
|
if (isSuccess)
|
|
print("SUCCESS!");
|
|
else
|
|
print("ERROR!");
|
|
|
|
if (isLSAN && !isAOT && !isSuccess) {
|
|
print("\nConsider using LSAN with AOT so you can get symbolized traces");
|
|
}
|
|
exit(result);
|
|
}
|