[vm/ffi] Migrate legacy multi-test files to Process.run

Migrates vmspecific_enable_ffi_test.dart and
abi_specific_int_incomplete_aot_test.dart away from legacy multi-test
markers. Since these tests verify VM/gen_snapshot compile-time errors
(not CFE errors), they cannot use // [cfe] expectations. Instead, they
now spawn a subprocess and verify the expected error is produced.

- vmspecific_enable_ffi_test: Runs helper with --enable-ffi=false, checks for error
- abi_specific_int_incomplete_aot_test: Compiles helper with `dart compile aot-snapshot`, checks for error

Both tests self-spawn AOT tooling (gen_snapshot) or the JIT `dart` CLI,
so they only run on the dartkp host bots and are skipped elsewhere
(ia32, android, fuchsia, qemu) via tests/ffi/ffi.status.

Fixes https://github.com/dart-lang/sdk/issues/60212

Change-Id: Ib2482c3172b20a4366f984da33544fc515b540c4
Cq-Include-Trybots: dart/try:vm-aot-android-debug-arm64c-try,vm-aot-android-debug-arm_x64-try,vm-aot-linux-debug-arm64-try,vm-aot-linux-debug-x64-try,vm-aot-linux-debug-x64c-try,vm-aot-mac-debug-arm64-try,vm-aot-mac-debug-x64-try,vm-aot-obfuscate-linux-release-x64-try,vm-aot-optimization-level-linux-release-x64-try,vm-aot-win-debug-arm64-try,vm-aot-win-debug-x64-try,vm-aot-win-debug-x64c-try,vm-asan-linux-release-arm64-try,vm-asan-linux-release-x64-try,vm-asan-mac-release-arm64-try,vm-asan-win-release-x64-try,vm-ffi-qemu-linux-release-arm-try,vm-ffi-qemu-linux-release-riscv64-try,vm-fuchsia-release-x64-try,vm-msan-linux-release-arm64-try,vm-msan-linux-release-x64-try,vm-tsan-linux-release-arm64-try,vm-tsan-linux-release-x64-try,vm-tsan-mac-release-arm64-try,vm-ubsan-linux-release-arm64-try,vm-ubsan-linux-release-x64-try,vm-ubsan-mac-release-arm64-try,vm-ubsan-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/508020
Commit-Queue: Samuel Rawlins <srawlins@google.com>
Auto-Submit: Ankit Ranjan <ankitranjandev@gmail.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
This commit is contained in:
Ankit Ranjan
2026-06-11 07:25:59 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent e171e636d5
commit 6de2588d56
5 changed files with 160 additions and 32 deletions
@@ -1,26 +1,91 @@
// Copyright (c) 2021, 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.
//
// Tests that using an AbiSpecificInteger with an incomplete mapping produces
// a compile-time error during AOT compilation.
//
// Uses pkg/vm/tool/gen_kernel and the build directory's gen_snapshot rather
// than `dart compile aot-snapshot`, because the test bots do not build the
// full SDK (gen_kernel_aot.dart.snapshot).
// Formatting can break multitests, so don't format them.
// dart format off
import 'dart:io';
// SharedObjects=ffi_test_functions
import 'package:expect/expect.dart';
import 'package:path/path.dart' as path;
import 'dart:ffi';
final _execSuffix = Platform.isWindows ? '.exe' : '';
final _batSuffix = Platform.isWindows ? '.bat' : '';
// We want at least 1 mapping to satisfy the static checks.
const notTestingOn = Abi.fuchsiaArm64;
@AbiSpecificIntegerMapping({
notTestingOn: Int8(),
})
final class Incomplete extends AbiSpecificInteger {
const Incomplete();
String _findGenSnapshot(String buildDir) {
final possiblePaths = [
// No cross compilation.
path.join(buildDir, 'gen_snapshot$_execSuffix'),
// ${MODE}SIMARM_X64 for X64->SIMARM cross compilation.
path.join('${buildDir}_X64', 'gen_snapshot$_execSuffix'),
// ${MODE}XARM64/clang_x64 for X64->ARM64 cross compilation.
path.join(buildDir, 'clang_x64', 'gen_snapshot$_execSuffix'),
];
for (final p in possiblePaths) {
if (File(p).existsSync()) {
return p;
}
}
throw 'Could not find gen_snapshot for build directory $buildDir';
}
void main() {
// Any use that causes the class to be used, causes a compile-time error
// during loading of the class.
nullptr.cast<Incomplete>(); //# 1: compile-time error
final buildDir = path.dirname(Platform.executable);
final sdkDir = path.dirname(path.dirname(buildDir));
final genKernel = path.join(
sdkDir,
'pkg',
'vm',
'tool',
'gen_kernel$_batSuffix',
);
final genSnapshot = _findGenSnapshot(buildDir);
final platformDill = path.join(buildDir, 'vm_platform.dill');
final helperPath = path.join(
sdkDir,
'tests',
'ffi',
'abi_specific_int_incomplete_aot_test_helper.dart',
);
final tempDir = Directory.systemTemp.createTempSync('abi_incomplete_aot');
try {
final dillPath = path.join(tempDir.path, 'out.dill');
// Compiling the helper to kernel should succeed; the incomplete ABI
// mapping is only detected by the VM precompiler.
final kernelResult = Process.runSync(genKernel, [
'--aot',
'--platform=$platformDill',
'-o',
dillPath,
helperPath,
]);
Expect.equals(
0,
kernelResult.exitCode,
'gen_kernel failed: ${kernelResult.stdout}\n${kernelResult.stderr}',
);
// AOT compiling the kernel file should fail with a compile-time error
// about the incomplete ABI mapping.
final snapshotResult = Process.runSync(genSnapshot, [
'--snapshot-kind=app-aot-elf',
'--elf=${path.join(tempDir.path, 'out.so')}',
dillPath,
]);
Expect.notEquals(0, snapshotResult.exitCode);
final stderr = snapshotResult.stderr.toString();
Expect.isTrue(
stderr.contains("AbiSpecificInteger 'Incomplete' is missing mapping for"),
'Expected error about missing ABI mapping, got: $stderr',
);
} finally {
tempDir.deleteSync(recursive: true);
}
}
@@ -0,0 +1,24 @@
// Copyright (c) 2026, 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.
//
// Helper for abi_specific_int_incomplete_aot_test.dart.
// This file has an AbiSpecificInteger with an incomplete mapping.
// During AOT compilation for any ABI other than fuchsiaArm64, gen_snapshot
// should fail with an error about the missing mapping.
import 'dart:ffi';
// We want at least 1 mapping to satisfy the static checks.
const notTestingOn = Abi.fuchsiaArm64;
@AbiSpecificIntegerMapping({notTestingOn: Int8()})
final class Incomplete extends AbiSpecificInteger {
const Incomplete();
}
void main() {
// Any use that causes the class to be used, causes a compile-time error
// during loading of the class.
nullptr.cast<Incomplete>();
}
+13 -7
View File
@@ -12,6 +12,9 @@ function_structs_by_value_generated_ret_leaf_test: Pass, Slow # https://dartbug.
function_structs_by_value_generated_ret_test: Pass, Slow # https://dartbug.com/47303 https://dartbug.com/45007
native_assets/asset_*: Pass, Slow # https://dartbug.com/56330
[ $arch == ia32 ]
abi_specific_int_incomplete_aot_test: SkipByDesign # No AOT mode on IA32.
[ $arch == simarm64_arm64 ]
function_structs_by_value_generated_args_native_test: Pass, Slow
@@ -41,6 +44,10 @@ native_assets/asset_*: SkipByDesign # Only intended to run from source. https://
native_assets/infer_native_assets_yaml_*: SkipByDesign # Only intended to run from source. https://dartbug.com/51265
vmspecific_leaf_call_test: Skip # https://dartbug.com/46125: Snapshot fails to generate.
[ $compiler != dartkp ]
abi_specific_int_incomplete_aot_test: SkipByDesign # Self-spawns gen_kernel/gen_snapshot, which are only built on AOT (dartkp) bots.
vmspecific_enable_ffi_test: SkipByDesign # Self-spawns the JIT dart executable, so the harness compiler is irrelevant; runs once on the dartkp bots.
[ $mode == debug ]
function_callbacks_structs_by_value_generated_test: Pass, Slow
@@ -49,10 +56,13 @@ regress_47594_test: Skip # Profiler is not available in Product.
[ $system == android ]
*: Pass, Slow # https://github.com/dart-lang/sdk/issues/38489
abi_specific_int_incomplete_aot_test: Skip # Needs gen_kernel and gen_snapshot.
regress_47594_test: Skip # DartDev is not available on Android.
vmspecific_enable_ffi_test: Skip # Needs access to Dart executable.
vmspecific_native_finalizer_isolate_groups_test: Skip # SpawnUri not available on Android tester.
[ $system == fuchsia ]
abi_specific_int_incomplete_aot_test: SkipByDesign # Needs gen_kernel and gen_snapshot.
async_void_function_callbacks_test/*: Skip # Test harness doesn't support multitest with Fuchsia
exceptional_return_const_test/*: Skip # Test harness doesn't support multitest with Fuchsia
ffi_induce_a_crash_test/*: Skip # Test harness doesn't support multitest with Fuchsia
@@ -72,7 +82,7 @@ run_isolate_group_run_test: Skip # gen_snapshot requires experimental-shared-dat
static_checks/*: SkipByDesign # Expecting compile time failures in multi tests doesn't work on the Fuchsia test runner.
threading_test: Skip # gen_snapshot requires experimental-shared-data flag
unaligned_test/*: Skip # Test harness doesn't support multitest with Fuchsia
vmspecific_enable_ffi_test/*: Skip # Test harness doesn't support multitest with Fuchsia
vmspecific_enable_ffi_test: SkipByDesign # Needs access to Dart executable.
vmspecific_function_callbacks_exit_test/*: Skip # Test harness doesn't support multitest with Fuchsia
vmspecific_highmem_32bit_test/*: Skip # Test harness doesn't support multitest with Fuchsia
vmspecific_leaf_call_test/*: Skip # Test harness doesn't support multitest with Fuchsia
@@ -85,8 +95,10 @@ regress_47594_test: Skip # DynamicLibrary.process() is not available on Windows.
ffi_induce_a_crash_test: SkipByDesign
[ $qemu ]
abi_specific_int_incomplete_aot_test: SkipByDesign # Needs gen_kernel and gen_snapshot.
function_callbacks_leaf_test: SkipByDesign # Needs access to Dart executable
native_assets/*: SkipByDesign # Only intended to run on host oses with AOT binaries available, not available on QEMU.
vmspecific_enable_ffi_test: SkipByDesign # Needs access to Dart executable.
[ $arch != simarm64_arm64 && $simulator ]
*: Skip # FFI not yet supported on the arm simulator.
@@ -103,9 +115,6 @@ many_listener_callbacks_test: Pass, Slow
[ $compiler == app_jitk || $sanitizer == asan ]
vmspecific_function_callbacks_exit_test: SkipByDesign
[ $compiler == dart2analyzer || $compiler == fasta ]
vmspecific_enable_ffi_test: SkipByDesign # This is a check for VM only.
[ $compiler == dartk || $system == android ]
native_assets/asset_*: SkipByDesign # Only intended to run on host oses with AOT binaries available.
@@ -115,9 +124,6 @@ native_assets/infer_native_assets_yaml_*: SkipByDesign # Only intended to run fr
[ $compiler == dartkp || $arch == arm64 && $system == fuchsia ]
abi_specific_int_incomplete_jit_test: SkipByDesign # Only intended to run in JIT mode.
[ $compiler != dartkp || $arch == arm64 && $system == fuchsia ]
abi_specific_int_incomplete_aot_test: SkipByDesign # Only intended to run in AOT mode.
[ $runtime == dart_precompiled || $runtime == vm ]
callback_unwind_error_test: Crash # https://github.com/dart-lang/sdk/issues/39487
+27 -10
View File
@@ -3,19 +3,36 @@
// BSD-style license that can be found in the LICENSE file.
//
// Dart test program for testing the --enable-ffi=false flag.
//
// VMOptions=--enable-ffi=false
// Formatting can break multitests, so don't format them.
// dart format off
import 'dart:io';
import 'dart:ffi'; //# 01: compile-time error
import 'package:expect/expect.dart';
import 'package:path/path.dart' as path;
import 'package:ffi/ffi.dart'; //# 01: compile-time error
final _execSuffix = Platform.isWindows ? '.exe' : '';
void main() {
Pointer<Int8> p = //# 01: compile-time error
calloc(); //# 01: compile-time error
print(p.address); //# 01: compile-time error
calloc.free(p); //# 01: compile-time error
final buildDir = path.dirname(Platform.executable);
final sdkDir = path.dirname(path.dirname(buildDir));
// Use the JIT `dart` executable from the build directory rather than
// `Platform.executable`, which is the AOT runtime under dartkp and cannot run
// the source helper.
final dartExecutable = path.join(buildDir, 'dart$_execSuffix');
final helperPath = path.join(
sdkDir,
'tests',
'ffi',
'vmspecific_enable_ffi_test_helper.dart',
);
final result = Process.runSync(dartExecutable, [
'--enable-ffi=false',
helperPath,
]);
Expect.equals(254, result.exitCode);
Expect.contains(
'import of dart:ffi is not supported in the current Dart runtime',
result.stderr,
);
}
@@ -0,0 +1,16 @@
// Copyright (c) 2026, 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.
//
// Helper for vmspecific_enable_ffi_test.dart.
// This file imports dart:ffi and should fail to load when --enable-ffi=false.
import 'dart:ffi';
import 'package:ffi/ffi.dart';
void main() {
Pointer<Int8> p = calloc();
print(p.address);
calloc.free(p);
}