blob: bb5a0ec058e54fcfd904200169b90a4cd71791df [file]
// 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.
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../dart/resolution/context_collection_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(FfiFromFunctionInvalidCodeTest);
});
}
/// Exercises `_validateFromFunction` with broken input at each argument
/// position, pinning the diagnostics reported there. The failure these tests
/// guard against is a crash, including on code another diagnostic already
/// flags.
///
/// https://github.com/dart-lang/sdk/issues/44773
@reflectiveTest
class FfiFromFunctionInvalidCodeTest extends PubPackageResolutionTest {
test_fromFunction_exceptionalReturn_prefix() async {
await resolveTestCodeWithDiagnostics(r'''
import 'dart:ffi';
import 'dart:math' as prefix;
int f(int x) => x;
void main() {
Pointer.fromFunction<Int32 Function(Int32)>(f, prefix);
// ^^^^^^
// [diag.prefixIdentifierNotFollowedByDot] The name 'prefix' refers to an import prefix, so it must be followed by '.'.
// [diag.mustBeASubtype] The type 'InvalidType' must be a subtype of 'Int32' for 'fromFunction'.
// [diag.argumentMustBeAConstant] Argument 'exceptionalReturn' must be a constant.
}
''');
}
test_fromFunction_exceptionalReturn_undefinedNamedParameter() async {
await resolveTestCodeWithDiagnostics(r'''
import 'dart:ffi';
int f(int x) => x;
void main() {
Pointer.fromFunction<Int32 Function(Int32)>(f, exceptional: 1);
// ^^^^^^^^^^^
// [diag.undefinedNamedParameter] The named parameter 'exceptional' isn't defined.
}
''');
}
test_fromFunction_exceptionalReturn_unresolvedIdentifier() async {
await resolveTestCodeWithDiagnostics(r'''
import 'dart:ffi';
int f(int x) => x;
void main() {
Pointer.fromFunction<Int32 Function(Int32)>(f, undefinedConst);
// ^^^^^^^^^^^^^^
// [diag.undefinedUnqualifiedNameReadNotFound] Undefined name 'undefinedConst'.
// [diag.mustBeASubtype] The type 'InvalidType' must be a subtype of 'Int32' for 'fromFunction'.
// [diag.argumentMustBeAConstant] Argument 'exceptionalReturn' must be a constant.
}
''');
}
test_fromFunction_function_prefix() async {
await resolveTestCodeWithDiagnostics(r'''
import 'dart:ffi';
import 'dart:math' as prefix;
void main() {
Pointer.fromFunction<Void Function()>(prefix);
// ^^^^^^
// [diag.prefixIdentifierNotFollowedByDot] The name 'prefix' refers to an import prefix, so it must be followed by '.'.
// [diag.mustBeASubtype] The type 'InvalidType' must be a subtype of 'Void Function()' for 'fromFunction'.
}
''');
}
test_fromFunction_function_unresolvedIdentifier() async {
await resolveTestCodeWithDiagnostics(r'''
import 'dart:ffi';
void main() {
Pointer.fromFunction<Void Function()>(undefinedFn);
// ^^^^^^^^^^^
// [diag.undefinedUnqualifiedNameReadNotFound] Undefined name 'undefinedFn'.
// [diag.mustBeASubtype] The type 'InvalidType' must be a subtype of 'Void Function()' for 'fromFunction'.
}
''');
}
test_fromFunction_typeArgument_none() async {
await resolveTestCodeWithDiagnostics(r'''
import 'dart:ffi';
int f(int x) => x;
void main() {
Pointer.fromFunction(f);
// ^^^^^^^^^^^^
// [diag.mustBeANativeFunctionType] The type 'Function' given to 'fromFunction' must be a valid 'dart:ffi' native function type.
}
''');
}
test_fromFunction_typeArgument_unresolved() async {
await resolveTestCodeWithDiagnostics(r'''
import 'dart:ffi';
int f(int x) => x;
void main() {
Pointer.fromFunction<Unresolved Function()>(f, 0);
// ^^^^^^^^^^
// [diag.undefinedClass] Undefined class 'Unresolved'.
// ^^^^^^^^^^^^^^^^^^^^^
// [diag.mustBeANativeFunctionType] The type 'InvalidType Function()' given to 'fromFunction' must be a valid 'dart:ffi' native function type.
}
''');
}
test_fromFunction_typeArgument_wrongCount() async {
await resolveTestCodeWithDiagnostics(r'''
import 'dart:ffi';
int f(int x) => x;
void main() {
Pointer.fromFunction<Int32 Function(Int32), Int8>(f, 0);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// [diag.wrongNumberOfTypeArgumentsElement] The method 'fromFunction' is declared with 1 type parameters, but 2 type arguments are given.
// ^^^^^^^^^^^^^^^^^^^^^
// [diag.mustBeANativeFunctionType] The type 'dynamic' given to 'fromFunction' must be a valid 'dart:ffi' native function type.
}
''');
}
}