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);
434 static Dart_Isolate CreateIsolate(
const uint8_t* data_buffer,
436 const uint8_t* instr_buffer,
438 void* group_data =
nullptr,
439 void* isolate_data =
nullptr);
441 static char* ValidateCompilationResult(
Zone* zone,
443 const uint8_t** kernel_buffer,
444 intptr_t* kernel_buffer_size,
445 bool allow_compile_errors);
467 void* isolate_data =
nullptr) {
469 nullptr, isolate_group_data, isolate_data));
492 static constexpr bool value =
false;
502 static constexpr bool value =
false;
515 code_(
Code::ZoneHandle(zone)),
516 disassembly_(zone->Alloc<char>(DISASSEMBLY_SIZE)) {
534#if defined(USING_SIMULATOR)
539 template <
typename ResultType>
542 const bool fp_args =
false;
544 ASSERT(thread !=
nullptr);
546 bit_cast<intptr_t, uword>(
entry()),
static_cast<intptr_t
>(code_.
ptr()),
547 reinterpret_cast<intptr_t
>(thread), 0, 0, fp_return, fp_args));
549 template <
typename ResultType,
typename Arg1Type>
556 ASSERT(thread !=
nullptr);
558 bit_cast<intptr_t, uword>(
entry()),
static_cast<intptr_t
>(code_.
ptr()),
559 reinterpret_cast<intptr_t
>(thread),
reinterpret_cast<intptr_t
>(arg1), 0,
560 fp_return, fp_args));
563 template <
typename ResultType,
typename Arg1Type>
566 const bool fp_args =
false;
567 const bool fp_return =
false;
569 static_cast<intptr_t
>(arg1), 0, 0, 0,
583 const bool fp_args =
false;
584 const bool fp_return =
false;
586 bit_cast<intptr_t, uword>(
entry()),
static_cast<intptr_t
>(arg1),
587 static_cast<intptr_t
>(arg2),
reinterpret_cast<intptr_t
>(arg3), 0,
591 template <
typename ResultType>
594 ASSERT(thread !=
nullptr);
599 template <
typename ResultType,
typename Arg1Type>
602 ASSERT(thread !=
nullptr);
607 template <
typename ResultType,
typename Arg1Type>
637 static constexpr intptr_t DISASSEMBLY_SIZE = 10240;
650#define EXPECT_VALID(handle) \
652 Dart_Handle tmp_handle = (handle); \
653 if (!Api::IsValid(tmp_handle)) { \
654 dart::Expect(__FILE__, __LINE__) \
656 "expected '%s' to be a valid handle but '%s' has already been " \
660 if (Dart_IsError(tmp_handle)) { \
661 dart::Expect(__FILE__, __LINE__) \
663 "expected '%s' to be a valid handle but found an error " \
666 #handle, Dart_GetError(tmp_handle)); \
670#define EXPECT_ERROR(handle, substring) \
672 Dart_Handle tmp_handle = (handle); \
673 if (Dart_IsError(tmp_handle)) { \
674 dart::Expect(__FILE__, __LINE__) \
675 .IsSubstring((substring), Dart_GetError(tmp_handle)); \
677 dart::Expect(__FILE__, __LINE__) \
679 "expected '%s' to be an error handle but found a valid " \
685#define EXPECT_TRUE(handle) \
687 Dart_Handle tmp_handle = (handle); \
688 if (Dart_IsBoolean(tmp_handle)) { \
690 Dart_BooleanValue(tmp_handle, &value); \
692 dart::Expect(__FILE__, __LINE__) \
693 .Fail("expected True, but was '%s'\n", #handle); \
696 dart::Expect(__FILE__, __LINE__) \
697 .Fail("expected True, but was '%s'\n", #handle); \
701#define EXPECT_NULL(handle) \
703 Dart_Handle tmp_handle = (handle); \
704 if (!Dart_IsNull(tmp_handle)) { \
705 dart::Expect(__FILE__, __LINE__) \
706 .Fail("expected '%s' to be a null handle.\n", #handle); \
710#define EXPECT_NON_NULL(handle) \
712 Dart_Handle tmp_handle = (handle); \
713 if (Dart_IsNull(tmp_handle)) { \
714 dart::Expect(__FILE__, __LINE__) \
715 .Fail("expected '%s' to be a non-null handle.\n", #handle); \
739 const char* postfix =
"\"");
765 : FLAG_background_compilation_(FLAG_background_compilation) {
766 FLAG_background_compilation =
false;
770 FLAG_background_compilation = FLAG_background_compilation_;
774 const bool FLAG_background_compilation_;
static float next(float f)
#define COMPILE_ASSERT(expr)
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_
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 const char * NullAssertTag()
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 const char * LateTag()
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 const char * NullableTag()
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
static const uint8_t buffer[]
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)
static constexpr bool value
static constexpr bool value
Dart_Handle NewString(const char *str)
#define RESOLVED_USER_TEST_URI