Flutter Engine
The Flutter Engine
unit_test.h
Go to the documentation of this file.
1// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_UNIT_TEST_H_
6#define RUNTIME_VM_UNIT_TEST_H_
7
8#include <functional>
9
11
12#include "platform/globals.h"
13
14#include "vm/dart.h"
15#include "vm/dart_api_state.h"
16#include "vm/dart_entry.h"
17#include "vm/globals.h"
18#include "vm/isolate.h"
19#include "vm/longjump.h"
20#include "vm/object.h"
21#include "vm/object_store.h"
22#include "vm/simulator.h"
23#include "vm/zone.h"
24
25// The VM_UNIT_TEST_CASE macro is used for tests that do not need any
26// default isolate or zone functionality.
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, \
30 expectation); \
31 void Dart_Test##name()
32
33#define VM_UNIT_TEST_CASE(name) VM_UNIT_TEST_CASE_WITH_EXPECTATION(name, "Pass")
34
35// The UNIT_TEST_CASE macro is used for tests that do not require any
36// functionality provided by the VM. Tests declared using this macro will be run
37// after the VM is cleaned up.
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, \
41 expectation); \
42 void Dart_Test##name()
43
44#define UNIT_TEST_CASE(name) UNIT_TEST_CASE_WITH_EXPECTATION(name, "Pass")
45
46// The ISOLATE_UNIT_TEST_CASE macro is used for tests that need an isolate and
47// zone in order to test its functionality. This macro is used for tests that
48// are implemented using the VM code directly and do not use the Dart API
49// for calling into the VM. The safepoint execution state of threads using
50// this macro is transitioned from kThreadInNative to kThreadInVM.
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__); \
61 } \
62 static void Dart_TestHelper##name(Thread* thread)
63
64#define ISOLATE_UNIT_TEST_CASE(name) \
65 ISOLATE_UNIT_TEST_CASE_WITH_EXPECTATION(name, "Pass")
66
67// The TEST_CASE macro is used for tests that need an isolate and zone
68// in order to test its functionality. This macro is used for tests that
69// are implemented using the Dart API for calling into the VM. The safepoint
70// execution state of threads using this macro remains kThreadNative.
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__); \
82 } \
83 static void Dart_TestHelper##name(Thread* thread)
84
85#define TEST_CASE(name) TEST_CASE_WITH_EXPECTATION(name, "Pass")
86
87// The ASSEMBLER_TEST_GENERATE macro is used to generate a unit test
88// for the assembler.
89#define ASSEMBLER_TEST_GENERATE(name, assembler) \
90 void AssemblerTestGenerate##name(compiler::Assembler* assembler)
91
92// The ASSEMBLER_TEST_EXTERN macro is used to declare a unit test
93// for the assembler.
94#define ASSEMBLER_TEST_EXTERN(name) \
95 extern void AssemblerTestGenerate##name(compiler::Assembler* assembler);
96
97// The ASSEMBLER_TEST_RUN macro is used to execute the assembler unit
98// test generated using the ASSEMBLER_TEST_GENERATE macro.
99// C++ callee-saved registers are not preserved. Arguments may be passed in.
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; \
104 while (true) { \
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()); \
111 test.Assemble(); \
112 AssemblerTestRun##name(&test); \
113 return; \
114 } else { \
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++; \
119 } else { \
120 FATAL("Unexpected error: %s\n", error.ToErrorCString()); \
121 } \
122 } \
123 } \
124 } \
125 static void AssemblerTestRun##name(AssemblerTest* test)
126
127#define ASSEMBLER_TEST_RUN(name, test) \
128 ASSEMBLER_TEST_RUN_WITH_EXPECTATION(name, test, "Pass")
129
130#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
131// We don't have simulators for these architectures, but define the macros so
132// they can be used in architecture-independent tests.
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)
153// Running on actual ARM hardware, execute code natively.
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)
170#else
171// Not running on ARM hardware, call simulator to execute code.
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))
187#else
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))
202#endif // defined(ARCH_IS_64_BIT)
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, \
214 0, 0, false, true))
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, \
220 true))
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))
223#endif // defined(HOST_ARCH_ARM)
224#endif // defined(TARGET_ARCH_{ARM, ARM64})
225
226#define ZONE_STR(FMT, ...) \
227 OS::SCreate(Thread::Current()->zone(), FMT, __VA_ARGS__)
228
229inline Dart_Handle NewString(const char* str) {
230 return Dart_NewStringFromCString(str);
231}
232
233namespace dart {
234
235// Forward declarations.
236namespace compiler {
237class Assembler;
238}
239class CodeGenerator;
240class VirtualMemory;
241
242namespace bin {
243// Snapshot pieces if we link in a snapshot, otherwise initialized to nullptr.
244extern const uint8_t* vm_snapshot_data;
245extern const uint8_t* vm_snapshot_instructions;
246extern const uint8_t* core_isolate_snapshot_data;
247extern const uint8_t* core_isolate_snapshot_instructions;
248} // namespace bin
249
250extern const uint8_t* platform_strong_dill;
251extern const intptr_t platform_strong_dill_size;
252
253class TesterState : public AllStatic {
254 public:
255 static const uint8_t* vm_snapshot_data;
259 static const char** argv;
260 static int argc;
261};
262
264 public:
265 explicit KernelBufferList(const uint8_t* kernel_buffer)
266 : kernel_buffer_(kernel_buffer), next_(nullptr) {}
267
268 KernelBufferList(const uint8_t* kernel_buffer, KernelBufferList* next)
269 : kernel_buffer_(kernel_buffer), next_(next) {}
270
272 free(const_cast<uint8_t*>(kernel_buffer_));
273 if (next_ != nullptr) {
274 delete next_;
275 }
276 }
277
278 void AddBufferToList(const uint8_t* kernel_buffer);
279
280 private:
281 const uint8_t* kernel_buffer_;
282 KernelBufferList* next_;
283};
284
286 public:
287 explicit TestCaseBase(const char* name, const char* expectation);
288 virtual ~TestCaseBase() {}
289
290 const char* name() const { return name_; }
291 const char* expectation() const { return expectation_; }
292
293 virtual void Run() = 0;
294 void RunTest();
295
296 static void RunAll();
297 static void RunAllRaw();
298 static void CleanupState();
299 static void AddToKernelBuffers(const uint8_t* kernel_buffer);
300
301 protected:
304
305 private:
306 static TestCaseBase* first_;
307 static TestCaseBase* tail_;
308
309 TestCaseBase* next_;
310 const char* name_;
311 const char* expectation_;
312
313 DISALLOW_COPY_AND_ASSIGN(TestCaseBase);
314};
315
316#define USER_TEST_URI "test-lib"
317#define RESOLVED_USER_TEST_URI "file:///test-lib"
318#define CORELIB_TEST_URI "dart:test-lib"
319
321 public:
322 typedef void(RunEntry)();
323
324 TestCase(RunEntry* run, const char* name, const char* expectation)
325 : TestCaseBase(name, expectation), run_(run) {}
326
327 static char* CompileTestScriptWithDFE(
328 const char* url,
329 const char* source,
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);
336 static char* CompileTestScriptWithDFE(
337 const char* url,
338 int sourcefiles_count,
339 Dart_SourceFile sourcefiles[],
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);
347 const char* script,
349 const char* lib_uri = RESOLVED_USER_TEST_URI,
350 bool finalize = true,
351 bool allow_compile_errors = false);
353 const char* script,
354 Dart_NativeEntryResolver resolver = nullptr,
355 const char* lib_uri = RESOLVED_USER_TEST_URI,
356 bool finalize = true);
358 const char* lib_uri,
359 const char* script,
360 Dart_NativeEntryResolver resolver = nullptr);
362 int sourcefiles_count,
363 Dart_SourceFile sourcefiles[],
364 Dart_NativeEntryResolver resolver = nullptr,
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);
371 static Dart_Handle LoadCoreTestScript(const char* script,
372 Dart_NativeEntryResolver resolver);
373
375 const String& expr,
376 const Array& param_names,
377 const Array& param_values);
378
379 static Dart_Handle lib();
380 static const char* url();
382 uint8_t* buffer,
383 const char* name = nullptr) {
384 return CreateIsolate(buffer, 0, nullptr, name);
385 }
386 static Dart_Isolate CreateTestIsolate(const char* name = nullptr,
387 void* isolate_group_data = nullptr,
388 void* isolate_data = nullptr);
389 static Dart_Isolate CreateTestIsolateInGroup(const char* name,
390 Dart_Isolate parent,
391 void* group_data = nullptr,
392 void* isolate_data = nullptr);
393
395 Dart_Handle library,
397
398 virtual void Run();
399
400 // Sets |script| to be the source used at next reload.
401 static Dart_Handle SetReloadTestScript(const char* script);
402
403 // Initiates the reload.
404 static Dart_Handle TriggerReload(const uint8_t* kernel_buffer,
405 intptr_t kernel_buffer_size);
406 static Dart_Handle TriggerReload(const char* root_script_url);
407
408 // Helper function which reloads the current isolate using |script|.
409 static Dart_Handle ReloadTestScript(const char* script);
410
411 // Helper function which reloads the current isolate using |script|.
412 static Dart_Handle ReloadTestKernel(const uint8_t* kernel_buffer,
413 intptr_t kernel_buffer_size);
414
415 static void AddTestLib(const char* url, const char* source);
416 static const char* GetTestLib(const char* url);
417
418 private:
420 std::function<bool(IsolateGroup*, JSONStream*)> do_reload);
421
422 // |data_buffer| can either be snapshot data, or kernel binary data.
423 // If |data_buffer| is snapshot data, then |len| should be zero as snapshot
424 // size is encoded within them. If |len| is non-zero, then |data_buffer|
425 // will be treated as a kernel binary (but CreateIsolate will not
426 // take ownership of the buffer) and |instr_buffer| will be ignored.
427 static Dart_Isolate CreateIsolate(const uint8_t* data_buffer,
428 intptr_t len,
429 const uint8_t* instr_buffer,
430 const char* name,
431 void* group_data = nullptr,
432 void* isolate_data = nullptr);
433
434 static char* ValidateCompilationResult(Zone* zone,
436 const uint8_t** kernel_buffer,
437 intptr_t* kernel_buffer_size,
438 bool allow_compile_errors);
439
440 RunEntry* const run_;
441};
442
444 public:
445 typedef void(RunEntry)();
446
447 RawTestCase(RunEntry* run, const char* name, const char* expectation)
448 : TestCaseBase(name, expectation), run_(run) {
449 raw_test_ = true;
450 }
451 virtual void Run();
452
453 private:
454 RunEntry* const run_;
455};
456
458 public:
459 TestIsolateScope(void* isolate_group_data = nullptr,
460 void* isolate_data = nullptr) {
461 isolate_ = reinterpret_cast<Isolate*>(TestCase::CreateTestIsolate(
462 /*name=*/nullptr, isolate_group_data, isolate_data));
463 Dart_EnterScope(); // Create a Dart API scope for unit tests.
464 }
466 Dart_ExitScope(); // Exit the Dart API scope created for unit tests.
467 ASSERT(isolate_ == Isolate::Current());
469 isolate_ = nullptr;
470 }
471 Isolate* isolate() const { return isolate_; }
472
473 private:
474 Isolate* isolate_;
475
476 DISALLOW_COPY_AND_ASSIGN(TestIsolateScope);
477};
478
479// Ensures core libraries are initialized, thereby allowing vm/cc tests to
480// e.g. run functions using microtasks.
482
483template <typename T>
484struct is_void {
485 static constexpr bool value = false;
486};
487
488template <>
489struct is_void<void> {
490 static constexpr bool value = true;
491};
492
493template <typename T>
494struct is_double {
495 static constexpr bool value = false;
496};
497
498template <>
499struct is_double<double> {
500 static constexpr bool value = true;
501};
502
504 public:
506 : name_(name),
507 assembler_(assembler),
508 code_(Code::ZoneHandle(zone)),
509 disassembly_(zone->Alloc<char>(DISASSEMBLY_SIZE)) {
510 ASSERT(name != nullptr);
511 ASSERT(assembler != nullptr);
512 }
514
515 compiler::Assembler* assembler() const { return assembler_; }
516
517 const Code& code() const { return code_; }
518
519 uword payload_start() const { return code_.PayloadStart(); }
520 uword payload_size() const { return assembler_->CodeSize(); }
521 uword entry() const { return code_.EntryPoint(); }
522
523// Invoke/InvokeWithCodeAndThread is used to call assembler test functions
524// using the ABI calling convention.
525// ResultType is the return type of the assembler test function.
526// ArgNType is the type of the Nth argument.
527#if defined(USING_SIMULATOR)
528
529 // Since Simulator::Call always return a int64_t, bit_cast does not work
530 // on 32-bit platforms when returning an int32_t. Use static cast on the
531 // call site in 32-bit to get rid of the upper bits if needed.
532 template <typename ResultType>
534 const bool fp_return = is_double<ResultType>::value;
535 const bool fp_args = false;
536 Thread* thread = Thread::Current();
537 ASSERT(thread != nullptr);
538 return bit_cast<ResultType, int64_t>(Simulator::Current()->Call(
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));
541 }
542 template <typename ResultType, typename Arg1Type>
543 ResultType InvokeWithCodeAndThread(Arg1Type arg1) {
544 const bool fp_return = is_double<ResultType>::value;
545 const bool fp_args = is_double<Arg1Type>::value;
546 // TODO(fschneider): Support double arguments for simulator calls.
547 COMPILE_ASSERT(!fp_args);
548 Thread* thread = Thread::Current();
549 ASSERT(thread != nullptr);
550 return bit_cast<ResultType, int64_t>(Simulator::Current()->Call(
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));
554 }
555
556 template <typename ResultType, typename Arg1Type>
557 ResultType Invoke(Arg1Type arg1) {
559 const bool fp_args = false;
560 const bool fp_return = false;
561 return Simulator::Current()->Call(bit_cast<intptr_t, uword>(entry()),
562 static_cast<intptr_t>(arg1), 0, 0, 0,
563 fp_return, fp_args);
564 }
565
566 template <typename ResultType,
567 typename Arg1Type,
568 typename Arg2Type,
569 typename Arg3Type>
570 ResultType Invoke(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3) {
571 // TODO(fschneider): Support double arguments for simulator calls.
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,
581 fp_return, fp_args);
582 }
583#else
584 template <typename ResultType>
586 Thread* thread = Thread::Current();
587 ASSERT(thread != nullptr);
588 typedef ResultType (*FunctionType)(CodePtr, Thread*);
589 return reinterpret_cast<FunctionType>(entry())(code_.ptr(), thread);
590 }
591
592 template <typename ResultType, typename Arg1Type>
594 Thread* thread = Thread::Current();
595 ASSERT(thread != nullptr);
596 typedef ResultType (*FunctionType)(CodePtr, Thread*, Arg1Type);
597 return reinterpret_cast<FunctionType>(entry())(code_.ptr(), thread, arg1);
598 }
599
600 template <typename ResultType, typename Arg1Type>
601 ResultType Invoke(Arg1Type arg1) {
602 typedef ResultType (*FunctionType)(Arg1Type);
603 return reinterpret_cast<FunctionType>(entry())(arg1);
604 }
605
606 template <typename ResultType,
607 typename Arg1Type,
608 typename Arg2Type,
609 typename Arg3Type>
610 ResultType Invoke(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3) {
611 typedef ResultType (*FunctionType)(Arg1Type, Arg2Type, Arg3Type);
612 return reinterpret_cast<FunctionType>(entry())(arg1, arg2, arg3);
613 }
614#endif // defined(USING_SIMULATOR)
615
616 // Assemble test and set code_.
617 void Assemble();
618
619 // Disassembly of the code with relative branch/jump targets.
620 char* RelativeDisassembly() { return disassembly_; }
621
622 static const Code& Generate(
623 const char* name,
624 const std::function<void(compiler::Assembler* assembler)>& generator);
625
626 private:
627 const char* name_;
628 compiler::Assembler* assembler_;
629 Code& code_;
630 static constexpr intptr_t DISASSEMBLY_SIZE = 10240;
631 char* disassembly_;
632
633 DISALLOW_COPY_AND_ASSIGN(AssemblerTest);
634};
635
636class CompilerTest : public AllStatic {
637 public:
638 // Test the Compiler::CompileFunction functionality by checking the return
639 // value to see if no parse errors were reported.
640 static bool TestCompileFunction(const Function& function);
641};
642
643#define EXPECT_VALID(handle) \
644 do { \
645 Dart_Handle tmp_handle = (handle); \
646 if (!Api::IsValid(tmp_handle)) { \
647 dart::Expect(__FILE__, __LINE__) \
648 .Fail( \
649 "expected '%s' to be a valid handle but '%s' has already been " \
650 "freed\n", \
651 #handle, #handle); \
652 } \
653 if (Dart_IsError(tmp_handle)) { \
654 dart::Expect(__FILE__, __LINE__) \
655 .Fail( \
656 "expected '%s' to be a valid handle but found an error " \
657 "handle:\n" \
658 " '%s'\n", \
659 #handle, Dart_GetError(tmp_handle)); \
660 } \
661 } while (0)
662
663#define EXPECT_ERROR(handle, substring) \
664 do { \
665 Dart_Handle tmp_handle = (handle); \
666 if (Dart_IsError(tmp_handle)) { \
667 dart::Expect(__FILE__, __LINE__) \
668 .IsSubstring((substring), Dart_GetError(tmp_handle)); \
669 } else { \
670 dart::Expect(__FILE__, __LINE__) \
671 .Fail( \
672 "expected '%s' to be an error handle but found a valid " \
673 "handle.\n", \
674 #handle); \
675 } \
676 } while (0)
677
678#define EXPECT_TRUE(handle) \
679 do { \
680 Dart_Handle tmp_handle = (handle); \
681 if (Dart_IsBoolean(tmp_handle)) { \
682 bool value; \
683 Dart_BooleanValue(tmp_handle, &value); \
684 if (!value) { \
685 dart::Expect(__FILE__, __LINE__) \
686 .Fail("expected True, but was '%s'\n", #handle); \
687 } \
688 } else { \
689 dart::Expect(__FILE__, __LINE__) \
690 .Fail("expected True, but was '%s'\n", #handle); \
691 } \
692 } while (0)
693
694#define EXPECT_NULL(handle) \
695 do { \
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); \
700 } \
701 } while (0)
702
703#define EXPECT_NON_NULL(handle) \
704 do { \
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); \
709 } \
710 } while (0)
711
712// Elide a substring which starts with some prefix and ends with some postfix.
713//
714// Prefix is inclusive, postfix is exclusive.
715//
716// This is used to remove non-deterministic or fragile substrings from
717// JSON output.
718//
719// For example:
720//
721// prefix = "classes"
722// in = "\"id\":\"classes/46\""
723//
724// Yields:
725//
726// out = "\"id\":\"\""
727//
728// WARNING: This function is not safe to use if `in` is bigger than `out`!
729void ElideJSONSubstring(const char* prefix,
730 const char* in,
731 char* out,
732 const char* postfix = "\"");
733
734// Elide a substrings such as ",\"tokenPos\":4372,\"endTokenPos\":4430".
735//
736// Substring to be followed by "}".
737//
738// Modifies buffer in place.
739void StripTokenPositions(char* buffer);
740
741template <typename T>
742class SetFlagScope : public ValueObject {
743 public:
744 SetFlagScope(T* flag, T value) : flag_(flag), original_value_(*flag) {
745 *flag_ = value;
746 }
747
748 ~SetFlagScope() { *flag_ = original_value_; }
749
750 private:
751 T* flag_;
752 T original_value_;
753};
754
756 public:
758 : FLAG_background_compilation_(FLAG_background_compilation) {
759 FLAG_background_compilation = false;
760 }
761
763 FLAG_background_compilation = FLAG_background_compilation_;
764 }
765
766 private:
767 const bool FLAG_background_compilation_;
768};
769
770} // namespace dart
771
772#endif // RUNTIME_VM_UNIT_TEST_H_
static float next(float f)
uword payload_size() const
Definition: unit_test.h:520
ResultType Invoke(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3)
Definition: unit_test.h:610
uword entry() const
Definition: unit_test.h:521
ResultType InvokeWithCodeAndThread()
Definition: unit_test.h:585
ResultType InvokeWithCodeAndThread(Arg1Type arg1)
Definition: unit_test.h:593
compiler::Assembler * assembler() const
Definition: unit_test.h:515
char * RelativeDisassembly()
Definition: unit_test.h:620
uword payload_start() const
Definition: unit_test.h:519
const Code & code() const
Definition: unit_test.h:517
static const Code & Generate(const char *name, const std::function< void(compiler::Assembler *assembler)> &generator)
Definition: unit_test.cc:770
AssemblerTest(const char *name, compiler::Assembler *assembler, Zone *zone)
Definition: unit_test.h:505
ResultType Invoke(Arg1Type arg1)
Definition: unit_test.h:601
uword EntryPoint() const
Definition: object.h:6864
uword PayloadStart() const
Definition: object.h:6850
static bool TestCompileFunction(const Function &function)
Definition: unit_test.cc:781
static Isolate * Current()
Definition: isolate.h:986
KernelBufferList(const uint8_t *kernel_buffer)
Definition: unit_test.h:265
KernelBufferList(const uint8_t *kernel_buffer, KernelBufferList *next)
Definition: unit_test.h:268
void AddBufferToList(const uint8_t *kernel_buffer)
Definition: unit_test.cc:50
ObjectPtr ptr() const
Definition: object.h:332
RawTestCase(RunEntry *run, const char *name, const char *expectation)
Definition: unit_test.h:447
void() RunEntry()
Definition: unit_test.h:445
virtual void Run()
Definition: run_vm_tests.cc:57
SetFlagScope(T *flag, T value)
Definition: unit_test.h:744
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)
virtual void Run()=0
static void CleanupState()
Definition: unit_test.cc:94
const char * expectation() const
Definition: unit_test.h:291
static void AddToKernelBuffers(const uint8_t *kernel_buffer)
Definition: unit_test.cc:101
static void RunAllRaw()
Definition: unit_test.cc:72
const char * name() const
Definition: unit_test.h:290
static void RunAll()
Definition: unit_test.cc:83
virtual ~TestCaseBase()
Definition: unit_test.h:288
static KernelBufferList * current_kernel_buffers_
Definition: unit_test.h:302
TestCaseBase(const char *name, const char *expectation)
Definition: unit_test.cc:59
static Dart_Handle TriggerReload(const uint8_t *kernel_buffer, intptr_t kernel_buffer_size)
Definition: unit_test.cc:603
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)
Definition: unit_test.cc:490
static Dart_Handle lib()
Definition: unit_test.cc:643
static void AddTestLib(const char *url, const char *source)
Definition: unit_test.cc:189
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)
Definition: unit_test.cc:436
static Dart_Handle ReloadTestScript(const char *script)
Definition: unit_test.cc:613
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)
Definition: unit_test.cc:297
static Dart_Isolate CreateTestIsolateInGroup(const char *name, Dart_Isolate parent, void *group_data=nullptr, void *isolate_data=nullptr)
Definition: unit_test.cc:163
static Dart_Handle SetReloadTestScript(const char *script)
Definition: unit_test.cc:539
static const char * url()
Definition: unit_test.cc:185
void() RunEntry()
Definition: unit_test.h:322
static Dart_Handle LoadTestScriptWithErrors(const char *script, Dart_NativeEntryResolver resolver=nullptr, const char *lib_uri=RESOLVED_USER_TEST_URI, bool finalize=true)
Definition: unit_test.cc:428
virtual void Run()
Definition: run_vm_tests.cc:51
static Dart_Handle LoadTestLibrary(const char *lib_uri, const char *script, Dart_NativeEntryResolver resolver=nullptr)
Definition: unit_test.cc:455
static Dart_Handle ReloadTestKernel(const uint8_t *kernel_buffer, intptr_t kernel_buffer_size)
Definition: unit_test.cc:631
TestCase(RunEntry *run, const char *name, const char *expectation)
Definition: unit_test.h:324
static Dart_Handle library_handler(Dart_LibraryTag tag, Dart_Handle library, Dart_Handle url)
Definition: unit_test.cc:651
static Dart_Handle EvaluateExpression(const Library &lib, const String &expr, const Array &param_names, const Array &param_values)
Definition: unit_test.cc:660
static Dart_Isolate CreateTestIsolate(const char *name=nullptr, void *isolate_group_data=nullptr, void *isolate_data=nullptr)
Definition: unit_test.cc:140
static const char * GetTestLib(const char *url)
Definition: unit_test.cc:206
static Dart_Handle LoadCoreTestScript(const char *script, Dart_NativeEntryResolver resolver)
Definition: unit_test.cc:638
static Dart_Isolate CreateTestIsolateFromSnapshot(uint8_t *buffer, const char *name=nullptr)
Definition: unit_test.h:381
Isolate * isolate() const
Definition: unit_test.h:471
TestIsolateScope(void *isolate_group_data=nullptr, void *isolate_data=nullptr)
Definition: unit_test.h:459
static Dart_IsolateShutdownCallback shutdown_callback
Definition: unit_test.h:257
static Dart_IsolateGroupCreateCallback create_callback
Definition: unit_test.h:256
static const char ** argv
Definition: unit_test.h:259
static Dart_IsolateGroupCleanupCallback group_cleanup_callback
Definition: unit_test.h:258
static int argc
Definition: unit_test.h:260
static const uint8_t * vm_snapshot_data
Definition: unit_test.h:255
static Thread * Current()
Definition: thread.h:362
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)
Definition: dart_api.h:654
struct _Dart_Handle * Dart_Handle
Definition: dart_api.h:258
struct _Dart_Isolate * Dart_Isolate
Definition: dart_api.h:88
Dart_NativeFunction(* Dart_NativeEntryResolver)(Dart_Handle name, int num_of_arguments, bool *auto_setup_scope)
Definition: dart_api.h:3234
void(* Dart_IsolateGroupCleanupCallback)(void *isolate_group_data)
Definition: dart_api.h:745
Dart_LibraryTag
Definition: dart_api.h:3419
void(* Dart_IsolateShutdownCallback)(void *isolate_group_data, void *isolate_data)
Definition: dart_api.h:711
DART_EXPORT Dart_Handle Dart_NewStringFromCString(const char *str)
#define ASSERT(E)
SkBitmap source
Definition: examples.cpp:28
FlutterSemanticsFlag flag
uint8_t value
GAsyncResult * result
Dart_NativeFunction function
Definition: fuchsia.cc:51
const uint8_t * vm_snapshot_data
Definition: main_impl.cc:52
const uint8_t * vm_snapshot_instructions
Definition: main_impl.cc:53
const uint8_t * core_isolate_snapshot_data
Definition: main_impl.cc:54
const uint8_t * core_isolate_snapshot_instructions
Definition: main_impl.cc:55
Definition: dart_vm.cc:33
void ElideJSONSubstring(const char *prefix, const char *in, char *out, const char *postfix)
Definition: unit_test.cc:790
DART_EXPORT void Dart_EnterScope()
const uint8_t * platform_strong_dill
Definition: unit_test.cc:40
const char *const name
const intptr_t platform_strong_dill_size
Definition: unit_test.cc:41
uintptr_t uword
Definition: globals.h:501
void SetupCoreLibrariesForUnitTest()
Definition: unit_test.cc:149
DART_EXPORT void Dart_ExitScope()
static CompileType * ResultType(Definition *call)
DART_EXPORT void Dart_ShutdownIsolate()
void StripTokenPositions(char *buffer)
Definition: unit_test.cc:813
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
Definition: switches.h:126
Definition: run.py:1
#define T
Definition: precompiler.cc:65
static constexpr bool value
Definition: unit_test.h:495
static constexpr bool value
Definition: unit_test.h:485
Dart_Handle NewString(const char *str)
Definition: unit_test.h:229
#define RESOLVED_USER_TEST_URI
Definition: unit_test.h:317