Skip to content

Commit b0155a7

Browse files
mkustermanncommit-bot@chromium.org
authored andcommitted
[vm/ffi] Add script to extract existing positive ffi tests into bundle to be used for flutter/flutter integration test
The `tests/ffi/prepare_flutter_bundle.dart` script will try to discover all synchronous, positive test from the "ffi" test suite, rewrite them slightly and output a directory which can be used in a flutter/flutter FFI integration test. We split the ffi test functions into two parts, because a subset of the C functions will issue calls to the VM via `dart_api.h`, which is not available for the flutter/flutter integration test. => We make `runtime/bin/ffi_test/ffi_test_functions.cc` a pure C library, usable without `dart_api.h` and move the remaining VM specific code to .../ffi_test_functions_special.cc contains. All tests from `tests/ffi/*_test.dart` will be included in the generated bundle, which * don't use async/isolates * don't rely on VM api * don't rely on DynamicLibrary.{process,executable} * don't take too long to execute The script can be used as follows: sdk % dart tests/ffi/prepare_flutter_bundle.dart foo Using SDK root: .../sdk The following tests will be included: aliasing_test.dart data_not_asan_test.dart data_test.dart extension_methods_test.dart external_typed_data_test.dart function_structs_test.dart negative_function_test.dart regress_37254_test.dart regress_39044_test.dart regress_39063_test.dart regress_39068_test.dart stacktrace_regress_37910_test.dart structs_test.dart variance_function_test.dart The following tests were filtered due to using dart_api.h/async/DynamicLibrary.{process,executable}/... function_callbacks_test.dart function_gc_test.dart function_test.dart object_gc_test.dart regress_37100_test.dart regress_37511_callbacks_test.dart regress_37511_test.dart regress_37780_test.dart Please copy generated files into FFI flutter test application * foo/lib/src/generated * foo/ios/Classes Change-Id: Ia13f97df3bbc90829bb8fde8265a7e1d2c0f8260 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/127006 Reviewed-by: Daco Harkes <dacoharkes@google.com> Commit-Queue: Martin Kustermann <kustermann@google.com>
1 parent f9327d3 commit b0155a7

18 files changed

+507
-269
lines changed

runtime/bin/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,6 +1122,7 @@ shared_library("ffi_test_functions") {
11221122
]
11231123
sources = [
11241124
"ffi_test/ffi_test_functions.cc",
1125+
"ffi_test/ffi_test_functions_special.cc",
11251126
]
11261127
if (is_win && current_cpu == "x64") {
11271128
sources += [ "ffi_test/clobber_x64_win.S" ]

runtime/bin/ffi_test/ffi_test_dynamic_library.cc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
#include "include/dart_api.h"
5+
#if defined(_WIN32)
6+
#define DART_EXPORT extern "C" __declspec(dllexport)
7+
#else
8+
#define DART_EXPORT \
9+
extern "C" __attribute__((visibility("default"))) __attribute((used))
10+
#endif
611

712
DART_EXPORT int return42() {
813
return 42;

runtime/bin/ffi_test/ffi_test_functions.cc

Lines changed: 9 additions & 244 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,17 @@
77
#include <stddef.h>
88
#include <stdlib.h>
99
#include <sys/types.h>
10-
#include <csignal>
1110

12-
#include "platform/globals.h"
13-
#if defined(HOST_OS_WINDOWS)
14-
#include <psapi.h>
15-
#else
16-
#include <unistd.h>
17-
18-
// Only OK to use here because this is test code.
19-
#include <condition_variable> // NOLINT(build/c++11)
20-
#include <functional> // NOLINT(build/c++11)
21-
#include <mutex> // NOLINT(build/c++11)
22-
#include <thread> // NOLINT(build/c++11)
23-
#endif
24-
25-
#include <setjmp.h>
26-
#include <signal.h>
11+
#include <cmath>
2712
#include <iostream>
2813
#include <limits>
2914

30-
#include "include/dart_api.h"
31-
#include "include/dart_native_api.h"
15+
#if defined(_WIN32)
16+
#define DART_EXPORT extern "C" __declspec(dllexport)
17+
#else
18+
#define DART_EXPORT \
19+
extern "C" __attribute__((visibility("default"))) __attribute((used))
20+
#endif
3221

3322
namespace dart {
3423

@@ -108,7 +97,7 @@ DART_EXPORT intptr_t TakeMinInt16(int16_t x) {
10897
}
10998

11099
DART_EXPORT intptr_t TakeMinInt32(int32_t x) {
111-
const int64_t expected = kMinInt32;
100+
const int64_t expected = INT32_MIN;
112101
const int64_t received = x;
113102
return expected == received ? 1 : 0;
114103
}
@@ -509,125 +498,6 @@ DART_EXPORT float InventFloatValue() {
509498
return retval;
510499
}
511500

512-
////////////////////////////////////////////////////////////////////////////////
513-
// Functions for stress-testing.
514-
515-
DART_EXPORT int64_t MinInt64() {
516-
Dart_ExecuteInternalCommand("gc-on-nth-allocation",
517-
reinterpret_cast<void*>(1));
518-
return 0x8000000000000000;
519-
}
520-
521-
DART_EXPORT int64_t MinInt32() {
522-
Dart_ExecuteInternalCommand("gc-on-nth-allocation",
523-
reinterpret_cast<void*>(1));
524-
return 0x80000000;
525-
}
526-
527-
DART_EXPORT double SmallDouble() {
528-
Dart_ExecuteInternalCommand("gc-on-nth-allocation",
529-
reinterpret_cast<void*>(1));
530-
return 0x80000000 * -1.0;
531-
}
532-
533-
// Requires boxing on 32-bit and 64-bit systems, even if the top 32-bits are
534-
// truncated.
535-
DART_EXPORT void* LargePointer() {
536-
Dart_ExecuteInternalCommand("gc-on-nth-allocation",
537-
reinterpret_cast<void*>(1));
538-
uint64_t origin = 0x8100000082000000;
539-
return reinterpret_cast<void*>(origin);
540-
}
541-
542-
DART_EXPORT void TriggerGC(uint64_t count) {
543-
Dart_ExecuteInternalCommand("gc-now", nullptr);
544-
}
545-
546-
DART_EXPORT void CollectOnNthAllocation(intptr_t num_allocations) {
547-
Dart_ExecuteInternalCommand("gc-on-nth-allocation",
548-
reinterpret_cast<void*>(num_allocations));
549-
}
550-
551-
// Triggers GC. Has 11 dummy arguments as unboxed odd integers which should be
552-
// ignored by GC.
553-
DART_EXPORT void Regress37069(uint64_t a,
554-
uint64_t b,
555-
uint64_t c,
556-
uint64_t d,
557-
uint64_t e,
558-
uint64_t f,
559-
uint64_t g,
560-
uint64_t h,
561-
uint64_t i,
562-
uint64_t j,
563-
uint64_t k) {
564-
Dart_ExecuteInternalCommand("gc-now", nullptr);
565-
}
566-
567-
#if !defined(HOST_OS_WINDOWS)
568-
DART_EXPORT void* UnprotectCodeOtherThread(void* isolate,
569-
std::condition_variable* var,
570-
std::mutex* mut) {
571-
std::function<void()> callback = [&]() {
572-
mut->lock();
573-
var->notify_all();
574-
mut->unlock();
575-
576-
// Wait for mutator thread to continue (and block) before leaving the
577-
// safepoint.
578-
while (Dart_ExecuteInternalCommand("is-mutator-in-native", isolate) !=
579-
nullptr) {
580-
usleep(10 * 1000 /*10 ms*/);
581-
}
582-
};
583-
584-
struct {
585-
void* isolate;
586-
std::function<void()>* callback;
587-
} args = {.isolate = isolate, .callback = &callback};
588-
589-
Dart_ExecuteInternalCommand("run-in-safepoint-and-rw-code", &args);
590-
return nullptr;
591-
}
592-
593-
struct HelperThreadState {
594-
std::mutex mutex;
595-
std::condition_variable cvar;
596-
std::unique_ptr<std::thread> helper;
597-
};
598-
599-
DART_EXPORT void* TestUnprotectCode(void (*fn)(void*)) {
600-
HelperThreadState* state = new HelperThreadState;
601-
602-
{
603-
std::unique_lock<std::mutex> lock(state->mutex); // locks the mutex
604-
state->helper.reset(new std::thread(UnprotectCodeOtherThread,
605-
Dart_CurrentIsolate(), &state->cvar,
606-
&state->mutex));
607-
608-
state->cvar.wait(lock);
609-
}
610-
611-
if (fn != nullptr) {
612-
fn(state);
613-
return nullptr;
614-
} else {
615-
return state;
616-
}
617-
}
618-
619-
DART_EXPORT void WaitForHelper(HelperThreadState* helper) {
620-
helper->helper->join();
621-
delete helper;
622-
}
623-
#else
624-
// Our version of VSC++ doesn't support std::thread yet.
625-
DART_EXPORT void WaitForHelper(void* helper) {}
626-
DART_EXPORT void* TestUnprotectCode(void (*fn)(void)) {
627-
return nullptr;
628-
}
629-
#endif
630-
631501
////////////////////////////////////////////////////////////////////////////////
632502
// Tests for callbacks.
633503

@@ -663,7 +533,7 @@ DART_EXPORT int TestSimpleMultiply(double (*fn)(double)) {
663533
}
664534

665535
DART_EXPORT int TestSimpleMultiplyFloat(float (*fn)(float)) {
666-
CHECK(std::abs(fn(2.0) - 2.0 * 1.337) < 0.001);
536+
CHECK(::std::abs(fn(2.0) - 2.0 * 1.337) < 0.001);
667537
return 0;
668538
}
669539

@@ -741,24 +611,6 @@ DART_EXPORT int TestNullPointers(int64_t* (*fn)(int64_t* ptr)) {
741611
return 0;
742612
}
743613

744-
// Defined in ffi_test_functions.S.
745-
//
746-
// Clobbers some registers with special meaning in Dart before re-entry, for
747-
// stress-testing. Not used on 32-bit Windows due to complications with Windows
748-
// "safeseh".
749-
#if defined(TARGET_OS_WINDOWS) && defined(HOST_ARCH_IA32)
750-
void ClobberAndCall(void (*fn)()) {
751-
fn();
752-
}
753-
#else
754-
extern "C" void ClobberAndCall(void (*fn)());
755-
#endif
756-
757-
DART_EXPORT int TestGC(void (*do_gc)()) {
758-
ClobberAndCall(do_gc);
759-
return 0;
760-
}
761-
762614
DART_EXPORT int TestReturnVoid(int (*return_void)()) {
763615
CHECK_EQ(return_void(), 0);
764616
return 0;
@@ -779,93 +631,6 @@ DART_EXPORT int TestThrowException(int (*fn)()) {
779631
return 0;
780632
}
781633

782-
struct CallbackTestData {
783-
int success;
784-
void (*callback)();
785-
};
786-
787-
#if defined(TARGET_OS_LINUX)
788-
789-
thread_local sigjmp_buf buf;
790-
void CallbackTestSignalHandler(int) {
791-
siglongjmp(buf, 1);
792-
}
793-
794-
int ExpectAbort(void (*fn)()) {
795-
fprintf(stderr, "**** EXPECT STACKTRACE TO FOLLOW. THIS IS OK. ****\n");
796-
797-
struct sigaction old_action = {};
798-
int result = __sigsetjmp(buf, /*savesigs=*/1);
799-
if (result == 0) {
800-
// Install signal handler.
801-
struct sigaction handler = {};
802-
handler.sa_handler = CallbackTestSignalHandler;
803-
sigemptyset(&handler.sa_mask);
804-
handler.sa_flags = 0;
805-
806-
sigaction(SIGABRT, &handler, &old_action);
807-
808-
fn();
809-
} else {
810-
// Caught the setjmp.
811-
sigaction(SIGABRT, &old_action, NULL);
812-
exit(0);
813-
}
814-
fprintf(stderr, "Expected abort!!!\n");
815-
exit(1);
816-
}
817-
818-
void* TestCallbackOnThreadOutsideIsolate(void* parameter) {
819-
CallbackTestData* data = reinterpret_cast<CallbackTestData*>(parameter);
820-
data->success = ExpectAbort(data->callback);
821-
return NULL;
822-
}
823-
824-
int TestCallbackOtherThreadHelper(void* (*tester)(void*), void (*fn)()) {
825-
CallbackTestData data = {1, fn};
826-
pthread_attr_t attr;
827-
int result = pthread_attr_init(&attr);
828-
CHECK_EQ(result, 0);
829-
830-
pthread_t tid;
831-
result = pthread_create(&tid, &attr, tester, &data);
832-
CHECK_EQ(result, 0);
833-
834-
result = pthread_attr_destroy(&attr);
835-
CHECK_EQ(result, 0);
836-
837-
void* retval;
838-
result = pthread_join(tid, &retval);
839-
840-
// Doesn't actually return because the other thread will exit when the test is
841-
// finished.
842-
return 1;
843-
}
844-
845-
// Run a callback on another thread and verify that it triggers SIGABRT.
846-
DART_EXPORT int TestCallbackWrongThread(void (*fn)()) {
847-
return TestCallbackOtherThreadHelper(&TestCallbackOnThreadOutsideIsolate, fn);
848-
}
849-
850-
// Verify that we get SIGABRT when invoking a native callback outside an
851-
// isolate.
852-
DART_EXPORT int TestCallbackOutsideIsolate(void (*fn)()) {
853-
Dart_Isolate current = Dart_CurrentIsolate();
854-
855-
Dart_ExitIsolate();
856-
CallbackTestData data = {1, fn};
857-
TestCallbackOnThreadOutsideIsolate(&data);
858-
Dart_EnterIsolate(current);
859-
860-
return data.success;
861-
}
862-
863-
DART_EXPORT int TestCallbackWrongIsolate(void (*fn)()) {
864-
return ExpectAbort(fn);
865-
}
866-
867-
#endif // defined(TARGET_OS_LINUX)
868-
869634
// Receives some pointer (Pointer<NativeType> in Dart) and writes some bits.
870635
DART_EXPORT void NativeTypePointerParam(void* p) {
871636
uint8_t* p2 = reinterpret_cast<uint8_t*>(p);

0 commit comments

Comments
 (0)