5#ifndef RUNTIME_VM_UNIT_TEST_H_
6#define RUNTIME_VM_UNIT_TEST_H_
27#define VM_UNIT_TEST_CASE_WITH_EXPECTATION(name, expectation) \
28 void Dart_Test##name(); \
29 static const dart::TestCase kRegister##name(Dart_Test##name, #name, \
31 void Dart_Test##name()
33#define VM_UNIT_TEST_CASE(name) VM_UNIT_TEST_CASE_WITH_EXPECTATION(name, "Pass")
38#define UNIT_TEST_CASE_WITH_EXPECTATION(name, expectation) \
39 void Dart_Test##name(); \
40 static const dart::RawTestCase kRegister##name(Dart_Test##name, #name, \
42 void Dart_Test##name()
44#define UNIT_TEST_CASE(name) UNIT_TEST_CASE_WITH_EXPECTATION(name, "Pass")
51#define ISOLATE_UNIT_TEST_CASE_WITH_EXPECTATION(name, expectation) \
52 static void Dart_TestHelper##name(Thread* thread); \
53 VM_UNIT_TEST_CASE_WITH_EXPECTATION(name, expectation) { \
54 TestIsolateScope __test_isolate__; \
55 Thread* __thread__ = Thread::Current(); \
56 ASSERT(__thread__->isolate() == __test_isolate__.isolate()); \
57 TransitionNativeToVM transition(__thread__); \
58 StackZone __zone__(__thread__); \
59 HandleScope __hs__(__thread__); \
60 Dart_TestHelper##name(__thread__); \
62 static void Dart_TestHelper##name(Thread* thread)
64#define ISOLATE_UNIT_TEST_CASE(name) \
65 ISOLATE_UNIT_TEST_CASE_WITH_EXPECTATION(name, "Pass")
71#define TEST_CASE_WITH_EXPECTATION(name, expectation) \
72 static void Dart_TestHelper##name(Thread* thread); \
73 VM_UNIT_TEST_CASE_WITH_EXPECTATION(name, expectation) { \
74 TestIsolateScope __test_isolate__; \
75 Thread* __thread__ = Thread::Current(); \
76 ASSERT(__thread__->isolate() == __test_isolate__.isolate()); \
77 TransitionNativeToVM transition1(__thread__); \
78 StackZone __zone__(__thread__); \
79 HandleScope __hs__(__thread__); \
80 TransitionVMToNative transition2(__thread__); \
81 Dart_TestHelper##name(__thread__); \
83 static void Dart_TestHelper##name(Thread* thread)
85#define TEST_CASE(name) TEST_CASE_WITH_EXPECTATION(name, "Pass")
89#define ASSEMBLER_TEST_GENERATE(name, assembler) \
90 void AssemblerTestGenerate##name(compiler::Assembler* assembler)
94#define ASSEMBLER_TEST_EXTERN(name) \
95 extern void AssemblerTestGenerate##name(compiler::Assembler* assembler);
100#define ASSEMBLER_TEST_RUN_WITH_EXPECTATION(name, test, expectation) \
101 static void AssemblerTestRun##name(AssemblerTest* test); \
102 ISOLATE_UNIT_TEST_CASE_WITH_EXPECTATION(Assembler_##name, expectation) { \
103 volatile intptr_t far_branch_level = 0; \
105 LongJumpScope jump(thread); \
106 if (setjmp(*jump.Set()) == 0) { \
107 compiler::ObjectPoolBuilder object_pool_builder; \
108 compiler::Assembler assembler(&object_pool_builder, far_branch_level); \
109 AssemblerTest test("" #name, &assembler, thread->zone()); \
110 AssemblerTestGenerate##name(test.assembler()); \
112 AssemblerTestRun##name(&test); \
115 const Error& error = Error::Handle(thread->StealStickyError()); \
116 if (error.ptr() == Object::branch_offset_error().ptr()) { \
117 RELEASE_ASSERT(far_branch_level < 2); \
118 far_branch_level++; \
120 FATAL("Unexpected error: %s\n", error.ToErrorCString()); \
125 static void AssemblerTestRun##name(AssemblerTest* test)
127#define ASSEMBLER_TEST_RUN(name, test) \
128 ASSEMBLER_TEST_RUN_WITH_EXPECTATION(name, test, "Pass")
130#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
133#define EXECUTE_TEST_CODE_INT32(name, entry) reinterpret_cast<name>(entry)()
134#define EXECUTE_TEST_CODE_INT64(name, entry) reinterpret_cast<name>(entry)()
135#define EXECUTE_TEST_CODE_INT64_LL(name, entry, long_arg0, long_arg1) \
136 reinterpret_cast<name>(entry)(long_arg0, long_arg1)
137#define EXECUTE_TEST_CODE_FLOAT(name, entry) reinterpret_cast<name>(entry)()
138#define EXECUTE_TEST_CODE_DOUBLE(name, entry) reinterpret_cast<name>(entry)()
139#define EXECUTE_TEST_CODE_INT32_F(name, entry, float_arg) \
140 reinterpret_cast<name>(entry)(float_arg)
141#define EXECUTE_TEST_CODE_INT32_D(name, entry, double_arg) \
142 reinterpret_cast<name>(entry)(double_arg)
143#define EXECUTE_TEST_CODE_INTPTR_INTPTR(name, entry, pointer_arg) \
144 reinterpret_cast<name>(entry)(pointer_arg)
145#define EXECUTE_TEST_CODE_INT32_INTPTR(name, entry, pointer_arg) \
146 reinterpret_cast<name>(entry)(pointer_arg)
147#define EXECUTE_TEST_CODE_UWORD_UWORD_UINT32(name, entry, arg0, arg1) \
148 reinterpret_cast<name>(entry)(arg0, arg1)
149#elif defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) || \
150 defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
151#if defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64) || \
152 defined(HOST_ARCH_RISCV32) || defined(HOST_ARCH_RISCV64)
154#define EXECUTE_TEST_CODE_INT32(name, entry) reinterpret_cast<name>(entry)()
155#define EXECUTE_TEST_CODE_INT64(name, entry) reinterpret_cast<name>(entry)()
156#define EXECUTE_TEST_CODE_INT64_LL(name, entry, long_arg0, long_arg1) \
157 reinterpret_cast<name>(entry)(long_arg0, long_arg1)
158#define EXECUTE_TEST_CODE_FLOAT(name, entry) reinterpret_cast<name>(entry)()
159#define EXECUTE_TEST_CODE_DOUBLE(name, entry) reinterpret_cast<name>(entry)()
160#define EXECUTE_TEST_CODE_INT32_F(name, entry, float_arg) \
161 reinterpret_cast<name>(entry)(float_arg)
162#define EXECUTE_TEST_CODE_INT32_D(name, entry, double_arg) \
163 reinterpret_cast<name>(entry)(double_arg)
164#define EXECUTE_TEST_CODE_INTPTR_INTPTR(name, entry, pointer_arg) \
165 reinterpret_cast<name>(entry)(pointer_arg)
166#define EXECUTE_TEST_CODE_INT32_INTPTR(name, entry, pointer_arg) \
167 reinterpret_cast<name>(entry)(pointer_arg)
168#define EXECUTE_TEST_CODE_UWORD_UWORD_UINT32(name, entry, arg0, arg1) \
169 reinterpret_cast<name>(entry)(arg0, arg1)
172#if defined(ARCH_IS_64_BIT)
173#define EXECUTE_TEST_CODE_INT64(name, entry) \
174 static_cast<int64_t>( \
175 Simulator::Current()->Call(bit_cast<int64_t, uword>(entry), 0, 0, 0, 0))
176#define EXECUTE_TEST_CODE_DOUBLE(name, entry) \
177 bit_cast<double, int64_t>(Simulator::Current()->Call( \
178 bit_cast<int64_t, uword>(entry), 0, 0, 0, 0, true))
179#define EXECUTE_TEST_CODE_INTPTR_INTPTR(name, entry, pointer_arg) \
180 static_cast<intptr_t>(Simulator::Current()->Call( \
181 bit_cast<int64_t, uword>(entry), \
182 bit_cast<int64_t, intptr_t>(pointer_arg), 0, 0, 0))
183#define EXECUTE_TEST_CODE_INT32_INTPTR(name, entry, pointer_arg) \
184 static_cast<int32_t>(Simulator::Current()->Call( \
185 bit_cast<int64_t, uword>(entry), \
186 bit_cast<int64_t, intptr_t>(pointer_arg), 0, 0, 0))
188#define EXECUTE_TEST_CODE_INT32(name, entry) \
189 static_cast<int32_t>( \
190 Simulator::Current()->Call(bit_cast<int32_t, uword>(entry), 0, 0, 0, 0))
191#define EXECUTE_TEST_CODE_DOUBLE(name, entry) \
192 bit_cast<double, int64_t>(Simulator::Current()->Call( \
193 bit_cast<int32_t, uword>(entry), 0, 0, 0, 0, true))
194#define EXECUTE_TEST_CODE_INTPTR_INTPTR(name, entry, pointer_arg) \
195 static_cast<intptr_t>(Simulator::Current()->Call( \
196 bit_cast<int32_t, uword>(entry), \
197 bit_cast<int32_t, intptr_t>(pointer_arg), 0, 0, 0))
198#define EXECUTE_TEST_CODE_INT32_INTPTR(name, entry, pointer_arg) \
199 static_cast<int32_t>(Simulator::Current()->Call( \
200 bit_cast<int32_t, uword>(entry), \
201 bit_cast<int32_t, intptr_t>(pointer_arg), 0, 0, 0))
203#define EXECUTE_TEST_CODE_INT64_LL(name, entry, long_arg0, long_arg1) \
204 static_cast<int64_t>(Simulator::Current()->Call( \
205 bit_cast<int32_t, uword>(entry), Utils::Low32Bits(long_arg0), \
206 Utils::High32Bits(long_arg0), Utils::Low32Bits(long_arg1), \
207 Utils::High32Bits(long_arg1)))
208#define EXECUTE_TEST_CODE_FLOAT(name, entry) \
209 bit_cast<float, int32_t>(Simulator::Current()->Call( \
210 bit_cast<int32_t, uword>(entry), 0, 0, 0, 0, true))
211#define EXECUTE_TEST_CODE_INT32_F(name, entry, float_arg) \
212 static_cast<int32_t>(Simulator::Current()->Call( \
213 bit_cast<int32_t, uword>(entry), bit_cast<int32_t, float>(float_arg), 0, \
215#define EXECUTE_TEST_CODE_INT32_D(name, entry, double_arg) \
216 static_cast<int32_t>(Simulator::Current()->Call( \
217 bit_cast<int32_t, uword>(entry), \
218 Utils::Low32Bits(bit_cast<int64_t, double>(double_arg)), \
219 Utils::High32Bits(bit_cast<int64_t, double>(double_arg)), 0, 0, false, \
221#define EXECUTE_TEST_CODE_UWORD_UWORD_UINT32(name, entry, arg0, arg1) \
222 static_cast<uint32_t>(Simulator::Current()->Call(entry, arg0, arg1, 0, 0))
226#define ZONE_STR(FMT, ...) \
227 OS::SCreate(Thread::Current()->zone(), FMT, __VA_ARGS__)
266 : kernel_buffer_(kernel_buffer), next_(nullptr) {}
269 : kernel_buffer_(kernel_buffer), next_(
next) {}
272 free(
const_cast<uint8_t*
>(kernel_buffer_));
273 if (next_ !=
nullptr) {
281 const uint8_t* kernel_buffer_;
290 const char*
name()
const {
return name_; }
311 const char* expectation_;
316#define USER_TEST_URI "test-lib"
317#define RESOLVED_USER_TEST_URI "file:///test-lib"
318#define CORELIB_TEST_URI "dart:test-lib"
330 const uint8_t** kernel_buffer,
331 intptr_t* kernel_buffer_size,
332 bool incrementally =
true,
333 bool allow_compile_errors =
false,
334 const char* multiroot_filepaths =
nullptr,
335 const char* multiroot_scheme =
nullptr);
338 int sourcefiles_count,
340 const uint8_t** kernel_buffer,
341 intptr_t* kernel_buffer_size,
342 bool incrementally =
true,
343 bool allow_compile_errors =
false,
344 const char* multiroot_filepaths =
nullptr,
345 const char* multiroot_scheme =
nullptr);
350 bool finalize =
true,
351 bool allow_compile_errors =
false);
356 bool finalize =
true);
362 int sourcefiles_count,
365 bool finalize =
true,
366 bool incrementally =
true,
367 bool allow_compile_errors =
false,
368 const char* entry_script_uri =
nullptr,
369 const char* multiroot_filepaths =
nullptr,
370 const char* multiroot_scheme =
nullptr);
376 const Array& param_names,
377 const Array& param_values);
380 static const char*
url();
383 const char*
name =
nullptr) {
384 return CreateIsolate(
buffer, 0,
nullptr,
name);
387 void* isolate_group_data =
nullptr,
388 void* isolate_data =
nullptr);
391 void* group_data =
nullptr,
392 void* isolate_data =
nullptr);
405 intptr_t kernel_buffer_size);
413 intptr_t kernel_buffer_size);
427 static Dart_Isolate CreateIsolate(
const uint8_t* data_buffer,
429 const uint8_t* instr_buffer,
431 void* group_data =
nullptr,
432 void* isolate_data =
nullptr);
434 static char* ValidateCompilationResult(
Zone* zone,
436 const uint8_t** kernel_buffer,
437 intptr_t* kernel_buffer_size,
438 bool allow_compile_errors);
460 void* isolate_data =
nullptr) {
462 nullptr, isolate_group_data, isolate_data));
485 static constexpr bool value =
false;
495 static constexpr bool value =
false;
508 code_(
Code::ZoneHandle(zone)),
509 disassembly_(zone->Alloc<char>(DISASSEMBLY_SIZE)) {
527#if defined(USING_SIMULATOR)
532 template <
typename ResultType>
535 const bool fp_args =
false;
537 ASSERT(thread !=
nullptr);
539 bit_cast<intptr_t, uword>(
entry()),
static_cast<intptr_t
>(code_.
ptr()),
540 reinterpret_cast<intptr_t
>(thread), 0, 0, fp_return, fp_args));
542 template <
typename ResultType,
typename Arg1Type>
549 ASSERT(thread !=
nullptr);
551 bit_cast<intptr_t, uword>(
entry()),
static_cast<intptr_t
>(code_.
ptr()),
552 reinterpret_cast<intptr_t
>(thread),
reinterpret_cast<intptr_t
>(arg1), 0,
553 fp_return, fp_args));
556 template <
typename ResultType,
typename Arg1Type>
559 const bool fp_args =
false;
560 const bool fp_return =
false;
562 static_cast<intptr_t
>(arg1), 0, 0, 0,
576 const bool fp_args =
false;
577 const bool fp_return =
false;
579 bit_cast<intptr_t, uword>(
entry()),
static_cast<intptr_t
>(arg1),
580 static_cast<intptr_t
>(arg2),
reinterpret_cast<intptr_t
>(arg3), 0,
584 template <
typename ResultType>
587 ASSERT(thread !=
nullptr);
592 template <
typename ResultType,
typename Arg1Type>
595 ASSERT(thread !=
nullptr);
600 template <
typename ResultType,
typename Arg1Type>
630 static constexpr intptr_t DISASSEMBLY_SIZE = 10240;
643#define EXPECT_VALID(handle) \
645 Dart_Handle tmp_handle = (handle); \
646 if (!Api::IsValid(tmp_handle)) { \
647 dart::Expect(__FILE__, __LINE__) \
649 "expected '%s' to be a valid handle but '%s' has already been " \
653 if (Dart_IsError(tmp_handle)) { \
654 dart::Expect(__FILE__, __LINE__) \
656 "expected '%s' to be a valid handle but found an error " \
659 #handle, Dart_GetError(tmp_handle)); \
663#define EXPECT_ERROR(handle, substring) \
665 Dart_Handle tmp_handle = (handle); \
666 if (Dart_IsError(tmp_handle)) { \
667 dart::Expect(__FILE__, __LINE__) \
668 .IsSubstring((substring), Dart_GetError(tmp_handle)); \
670 dart::Expect(__FILE__, __LINE__) \
672 "expected '%s' to be an error handle but found a valid " \
678#define EXPECT_TRUE(handle) \
680 Dart_Handle tmp_handle = (handle); \
681 if (Dart_IsBoolean(tmp_handle)) { \
683 Dart_BooleanValue(tmp_handle, &value); \
685 dart::Expect(__FILE__, __LINE__) \
686 .Fail("expected True, but was '%s'\n", #handle); \
689 dart::Expect(__FILE__, __LINE__) \
690 .Fail("expected True, but was '%s'\n", #handle); \
694#define EXPECT_NULL(handle) \
696 Dart_Handle tmp_handle = (handle); \
697 if (!Dart_IsNull(tmp_handle)) { \
698 dart::Expect(__FILE__, __LINE__) \
699 .Fail("expected '%s' to be a null handle.\n", #handle); \
703#define EXPECT_NON_NULL(handle) \
705 Dart_Handle tmp_handle = (handle); \
706 if (Dart_IsNull(tmp_handle)) { \
707 dart::Expect(__FILE__, __LINE__) \
708 .Fail("expected '%s' to be a non-null handle.\n", #handle); \
732 const char* postfix =
"\"");
758 : FLAG_background_compilation_(FLAG_background_compilation) {
759 FLAG_background_compilation =
false;
763 FLAG_background_compilation = FLAG_background_compilation_;
767 const bool FLAG_background_compilation_;
static float next(float f)
uword payload_size() const
ResultType Invoke(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3)
ResultType InvokeWithCodeAndThread()
ResultType InvokeWithCodeAndThread(Arg1Type arg1)
compiler::Assembler * assembler() const
char * RelativeDisassembly()
uword payload_start() const
const Code & code() const
static const Code & Generate(const char *name, const std::function< void(compiler::Assembler *assembler)> &generator)
AssemblerTest(const char *name, compiler::Assembler *assembler, Zone *zone)
ResultType Invoke(Arg1Type arg1)
uword PayloadStart() const
static bool TestCompileFunction(const Function &function)
DisableBackgroundCompilationScope()
~DisableBackgroundCompilationScope()
static Isolate * Current()
KernelBufferList(const uint8_t *kernel_buffer)
KernelBufferList(const uint8_t *kernel_buffer, KernelBufferList *next)
void AddBufferToList(const uint8_t *kernel_buffer)
RawTestCase(RunEntry *run, const char *name, const char *expectation)
SetFlagScope(T *flag, T value)
static Simulator * Current()
int64_t Call(int32_t entry, int32_t parameter0, int32_t parameter1, int32_t parameter2, int32_t parameter3, bool fp_return=false, bool fp_args=false)
static void CleanupState()
const char * expectation() const
static void AddToKernelBuffers(const uint8_t *kernel_buffer)
const char * name() const
static KernelBufferList * current_kernel_buffers_
TestCaseBase(const char *name, const char *expectation)
static Dart_Handle TriggerReload(const uint8_t *kernel_buffer, intptr_t kernel_buffer_size)
static Dart_Handle LoadTestScriptWithDFE(int sourcefiles_count, Dart_SourceFile sourcefiles[], Dart_NativeEntryResolver resolver=nullptr, bool finalize=true, bool incrementally=true, bool allow_compile_errors=false, const char *entry_script_uri=nullptr, const char *multiroot_filepaths=nullptr, const char *multiroot_scheme=nullptr)
static void AddTestLib(const char *url, const char *source)
static Dart_Handle LoadTestScript(const char *script, Dart_NativeEntryResolver resolver, const char *lib_uri=RESOLVED_USER_TEST_URI, bool finalize=true, bool allow_compile_errors=false)
static Dart_Handle ReloadTestScript(const char *script)
static char * CompileTestScriptWithDFE(const char *url, const char *source, const uint8_t **kernel_buffer, intptr_t *kernel_buffer_size, bool incrementally=true, bool allow_compile_errors=false, const char *multiroot_filepaths=nullptr, const char *multiroot_scheme=nullptr)
static Dart_Isolate CreateTestIsolateInGroup(const char *name, Dart_Isolate parent, void *group_data=nullptr, void *isolate_data=nullptr)
static Dart_Handle SetReloadTestScript(const char *script)
static const char * url()
static Dart_Handle LoadTestScriptWithErrors(const char *script, Dart_NativeEntryResolver resolver=nullptr, const char *lib_uri=RESOLVED_USER_TEST_URI, bool finalize=true)
static Dart_Handle LoadTestLibrary(const char *lib_uri, const char *script, Dart_NativeEntryResolver resolver=nullptr)
static Dart_Handle ReloadTestKernel(const uint8_t *kernel_buffer, intptr_t kernel_buffer_size)
TestCase(RunEntry *run, const char *name, const char *expectation)
static Dart_Handle library_handler(Dart_LibraryTag tag, Dart_Handle library, Dart_Handle url)
static Dart_Handle EvaluateExpression(const Library &lib, const String &expr, const Array ¶m_names, const Array ¶m_values)
static Dart_Isolate CreateTestIsolate(const char *name=nullptr, void *isolate_group_data=nullptr, void *isolate_data=nullptr)
static const char * GetTestLib(const char *url)
static Dart_Handle LoadCoreTestScript(const char *script, Dart_NativeEntryResolver resolver)
static Dart_Isolate CreateTestIsolateFromSnapshot(uint8_t *buffer, const char *name=nullptr)
Isolate * isolate() const
TestIsolateScope(void *isolate_group_data=nullptr, void *isolate_data=nullptr)
static Dart_IsolateShutdownCallback shutdown_callback
static Dart_IsolateGroupCreateCallback create_callback
static const char ** argv
static Dart_IsolateGroupCleanupCallback group_cleanup_callback
static const uint8_t * vm_snapshot_data
static Thread * Current()
intptr_t CodeSize() const
Dart_Isolate(* Dart_IsolateGroupCreateCallback)(const char *script_uri, const char *main, const char *package_root, const char *package_config, Dart_IsolateFlags *flags, void *isolate_data, char **error)
struct _Dart_Handle * Dart_Handle
struct _Dart_Isolate * Dart_Isolate
Dart_NativeFunction(* Dart_NativeEntryResolver)(Dart_Handle name, int num_of_arguments, bool *auto_setup_scope)
void(* Dart_IsolateGroupCleanupCallback)(void *isolate_group_data)
void(* Dart_IsolateShutdownCallback)(void *isolate_group_data, void *isolate_data)
DART_EXPORT Dart_Handle Dart_NewStringFromCString(const char *str)
FlutterSemanticsFlag flag
Dart_NativeFunction function
const uint8_t * vm_snapshot_data
const uint8_t * vm_snapshot_instructions
const uint8_t * core_isolate_snapshot_data
const uint8_t * core_isolate_snapshot_instructions
void ElideJSONSubstring(const char *prefix, const char *in, char *out, const char *postfix)
DART_EXPORT void Dart_EnterScope()
const uint8_t * platform_strong_dill
const intptr_t platform_strong_dill_size
void SetupCoreLibrariesForUnitTest()
DART_EXPORT void Dart_ExitScope()
static CompileType * ResultType(Definition *call)
DART_EXPORT void Dart_ShutdownIsolate()
void StripTokenPositions(char *buffer)
COMPILE_ASSERT(kUnreachableReference==WeakTable::kNoValue)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
static constexpr bool value
static constexpr bool value
Dart_Handle NewString(const char *str)
#define RESOLVED_USER_TEST_URI