Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
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
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 // Return true if non-nullable experiment is enabled.
419 static bool IsNNBD();
420
421 static const char* NullableTag() { return IsNNBD() ? "?" : ""; }
422 static const char* NullAssertTag() { return IsNNBD() ? "!" : ""; }
423 static const char* LateTag() { return IsNNBD() ? "late" : ""; }
424
425 private:
427 std::function<bool(IsolateGroup*, JSONStream*)> do_reload);
428
429 // |data_buffer| can either be snapshot data, or kernel binary data.
430 // If |data_buffer| is snapshot data, then |len| should be zero as snapshot
431 // size is encoded within them. If |len| is non-zero, then |data_buffer|
432 // will be treated as a kernel binary (but CreateIsolate will not
433 // take ownership of the buffer) and |instr_buffer| will be ignored.
434 static Dart_Isolate CreateIsolate(const uint8_t* data_buffer,
435 intptr_t len,
436 const uint8_t* instr_buffer,
437 const char* name,
438 void* group_data = nullptr,
439 void* isolate_data = nullptr);
440
441 static char* ValidateCompilationResult(Zone* zone,
443 const uint8_t** kernel_buffer,
444 intptr_t* kernel_buffer_size,
445 bool allow_compile_errors);
446
447 RunEntry* const run_;
448};
449
451 public:
452 typedef void(RunEntry)();
453
454 RawTestCase(RunEntry* run, const char* name, const char* expectation)
455 : TestCaseBase(name, expectation), run_(run) {
456 raw_test_ = true;
457 }
458 virtual void Run();
459
460 private:
461 RunEntry* const run_;
462};
463
465 public:
466 TestIsolateScope(void* isolate_group_data = nullptr,
467 void* isolate_data = nullptr) {
468 isolate_ = reinterpret_cast<Isolate*>(TestCase::CreateTestIsolate(
469 /*name=*/nullptr, isolate_group_data, isolate_data));
470 Dart_EnterScope(); // Create a Dart API scope for unit tests.
471 }
473 Dart_ExitScope(); // Exit the Dart API scope created for unit tests.
474 ASSERT(isolate_ == Isolate::Current());
476 isolate_ = nullptr;
477 }
478 Isolate* isolate() const { return isolate_; }
479
480 private:
481 Isolate* isolate_;
482
484};
485
486// Ensures core libraries are initialized, thereby allowing vm/cc tests to
487// e.g. run functions using microtasks.
489
490template <typename T>
491struct is_void {
492 static constexpr bool value = false;
493};
494
495template <>
496struct is_void<void> {
497 static constexpr bool value = true;
498};
499
500template <typename T>
501struct is_double {
502 static constexpr bool value = false;
503};
504
505template <>
506struct is_double<double> {
507 static constexpr bool value = true;
508};
509
511 public:
513 : name_(name),
514 assembler_(assembler),
515 code_(Code::ZoneHandle(zone)),
516 disassembly_(zone->Alloc<char>(DISASSEMBLY_SIZE)) {
517 ASSERT(name != nullptr);
518 ASSERT(assembler != nullptr);
519 }
521
522 compiler::Assembler* assembler() const { return assembler_; }
523
524 const Code& code() const { return code_; }
525
526 uword payload_start() const { return code_.PayloadStart(); }
527 uword payload_size() const { return assembler_->CodeSize(); }
528 uword entry() const { return code_.EntryPoint(); }
529
530// Invoke/InvokeWithCodeAndThread is used to call assembler test functions
531// using the ABI calling convention.
532// ResultType is the return type of the assembler test function.
533// ArgNType is the type of the Nth argument.
534#if defined(USING_SIMULATOR)
535
536 // Since Simulator::Call always return a int64_t, bit_cast does not work
537 // on 32-bit platforms when returning an int32_t. Use static cast on the
538 // call site in 32-bit to get rid of the upper bits if needed.
539 template <typename ResultType>
541 const bool fp_return = is_double<ResultType>::value;
542 const bool fp_args = false;
543 Thread* thread = Thread::Current();
544 ASSERT(thread != nullptr);
545 return bit_cast<ResultType, int64_t>(Simulator::Current()->Call(
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));
548 }
549 template <typename ResultType, typename Arg1Type>
550 ResultType InvokeWithCodeAndThread(Arg1Type arg1) {
551 const bool fp_return = is_double<ResultType>::value;
552 const bool fp_args = is_double<Arg1Type>::value;
553 // TODO(fschneider): Support double arguments for simulator calls.
554 COMPILE_ASSERT(!fp_args);
555 Thread* thread = Thread::Current();
556 ASSERT(thread != nullptr);
557 return bit_cast<ResultType, int64_t>(Simulator::Current()->Call(
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));
561 }
562
563 template <typename ResultType, typename Arg1Type>
564 ResultType Invoke(Arg1Type arg1) {
566 const bool fp_args = false;
567 const bool fp_return = false;
568 return Simulator::Current()->Call(bit_cast<intptr_t, uword>(entry()),
569 static_cast<intptr_t>(arg1), 0, 0, 0,
570 fp_return, fp_args);
571 }
572
573 template <typename ResultType,
574 typename Arg1Type,
575 typename Arg2Type,
576 typename Arg3Type>
577 ResultType Invoke(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3) {
578 // TODO(fschneider): Support double arguments for simulator calls.
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,
588 fp_return, fp_args);
589 }
590#else
591 template <typename ResultType>
593 Thread* thread = Thread::Current();
594 ASSERT(thread != nullptr);
595 typedef ResultType (*FunctionType)(CodePtr, Thread*);
596 return reinterpret_cast<FunctionType>(entry())(code_.ptr(), thread);
597 }
598
599 template <typename ResultType, typename Arg1Type>
601 Thread* thread = Thread::Current();
602 ASSERT(thread != nullptr);
603 typedef ResultType (*FunctionType)(CodePtr, Thread*, Arg1Type);
604 return reinterpret_cast<FunctionType>(entry())(code_.ptr(), thread, arg1);
605 }
606
607 template <typename ResultType, typename Arg1Type>
608 ResultType Invoke(Arg1Type arg1) {
609 typedef ResultType (*FunctionType)(Arg1Type);
610 return reinterpret_cast<FunctionType>(entry())(arg1);
611 }
612
613 template <typename ResultType,
614 typename Arg1Type,
615 typename Arg2Type,
616 typename Arg3Type>
617 ResultType Invoke(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3) {
618 typedef ResultType (*FunctionType)(Arg1Type, Arg2Type, Arg3Type);
619 return reinterpret_cast<FunctionType>(entry())(arg1, arg2, arg3);
620 }
621#endif // defined(USING_SIMULATOR)
622
623 // Assemble test and set code_.
624 void Assemble();
625
626 // Disassembly of the code with relative branch/jump targets.
627 char* RelativeDisassembly() { return disassembly_; }
628
629 static const Code& Generate(
630 const char* name,
631 const std::function<void(compiler::Assembler* assembler)>& generator);
632
633 private:
634 const char* name_;
635 compiler::Assembler* assembler_;
636 Code& code_;
637 static constexpr intptr_t DISASSEMBLY_SIZE = 10240;
638 char* disassembly_;
639
641};
642
643class CompilerTest : public AllStatic {
644 public:
645 // Test the Compiler::CompileFunction functionality by checking the return
646 // value to see if no parse errors were reported.
647 static bool TestCompileFunction(const Function& function);
648};
649
650#define EXPECT_VALID(handle) \
651 do { \
652 Dart_Handle tmp_handle = (handle); \
653 if (!Api::IsValid(tmp_handle)) { \
654 dart::Expect(__FILE__, __LINE__) \
655 .Fail( \
656 "expected '%s' to be a valid handle but '%s' has already been " \
657 "freed\n", \
658 #handle, #handle); \
659 } \
660 if (Dart_IsError(tmp_handle)) { \
661 dart::Expect(__FILE__, __LINE__) \
662 .Fail( \
663 "expected '%s' to be a valid handle but found an error " \
664 "handle:\n" \
665 " '%s'\n", \
666 #handle, Dart_GetError(tmp_handle)); \
667 } \
668 } while (0)
669
670#define EXPECT_ERROR(handle, substring) \
671 do { \
672 Dart_Handle tmp_handle = (handle); \
673 if (Dart_IsError(tmp_handle)) { \
674 dart::Expect(__FILE__, __LINE__) \
675 .IsSubstring((substring), Dart_GetError(tmp_handle)); \
676 } else { \
677 dart::Expect(__FILE__, __LINE__) \
678 .Fail( \
679 "expected '%s' to be an error handle but found a valid " \
680 "handle.\n", \
681 #handle); \
682 } \
683 } while (0)
684
685#define EXPECT_TRUE(handle) \
686 do { \
687 Dart_Handle tmp_handle = (handle); \
688 if (Dart_IsBoolean(tmp_handle)) { \
689 bool value; \
690 Dart_BooleanValue(tmp_handle, &value); \
691 if (!value) { \
692 dart::Expect(__FILE__, __LINE__) \
693 .Fail("expected True, but was '%s'\n", #handle); \
694 } \
695 } else { \
696 dart::Expect(__FILE__, __LINE__) \
697 .Fail("expected True, but was '%s'\n", #handle); \
698 } \
699 } while (0)
700
701#define EXPECT_NULL(handle) \
702 do { \
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); \
707 } \
708 } while (0)
709
710#define EXPECT_NON_NULL(handle) \
711 do { \
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); \
716 } \
717 } while (0)
718
719// Elide a substring which starts with some prefix and ends with some postfix.
720//
721// Prefix is inclusive, postfix is exclusive.
722//
723// This is used to remove non-deterministic or fragile substrings from
724// JSON output.
725//
726// For example:
727//
728// prefix = "classes"
729// in = "\"id\":\"classes/46\""
730//
731// Yields:
732//
733// out = "\"id\":\"\""
734//
735// WARNING: This function is not safe to use if `in` is bigger than `out`!
736void ElideJSONSubstring(const char* prefix,
737 const char* in,
738 char* out,
739 const char* postfix = "\"");
740
741// Elide a substrings such as ",\"tokenPos\":4372,\"endTokenPos\":4430".
742//
743// Substring to be followed by "}".
744//
745// Modifies buffer in place.
746void StripTokenPositions(char* buffer);
747
748template <typename T>
749class SetFlagScope : public ValueObject {
750 public:
751 SetFlagScope(T* flag, T value) : flag_(flag), original_value_(*flag) {
752 *flag_ = value;
753 }
754
755 ~SetFlagScope() { *flag_ = original_value_; }
756
757 private:
758 T* flag_;
759 T original_value_;
760};
761
763 public:
765 : FLAG_background_compilation_(FLAG_background_compilation) {
766 FLAG_background_compilation = false;
767 }
768
770 FLAG_background_compilation = FLAG_background_compilation_;
771 }
772
773 private:
774 const bool FLAG_background_compilation_;
775};
776
777} // namespace dart
778
779#endif // RUNTIME_VM_UNIT_TEST_H_
static float next(float f)
#define COMPILE_ASSERT(expr)
Definition assert.h:339
uword payload_size() const
Definition unit_test.h:527
ResultType Invoke(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3)
Definition unit_test.h:617
uword entry() const
Definition unit_test.h:528
ResultType InvokeWithCodeAndThread()
Definition unit_test.h:592
ResultType InvokeWithCodeAndThread(Arg1Type arg1)
Definition unit_test.h:600
compiler::Assembler * assembler() const
Definition unit_test.h:522
char * RelativeDisassembly()
Definition unit_test.h:627
uword payload_start() const
Definition unit_test.h:526
const Code & code() const
Definition unit_test.h:524
static const Code & Generate(const char *name, const std::function< void(compiler::Assembler *assembler)> &generator)
Definition unit_test.cc:756
AssemblerTest(const char *name, compiler::Assembler *assembler, Zone *zone)
Definition unit_test.h:512
ResultType Invoke(Arg1Type arg1)
Definition unit_test.h:608
uword EntryPoint() const
Definition object.h:6837
uword PayloadStart() const
Definition object.h:6823
static bool TestCompileFunction(const Function &function)
Definition unit_test.cc:767
static Isolate * Current()
Definition isolate.h:939
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:49
ObjectPtr ptr() const
Definition object.h:332
RawTestCase(RunEntry *run, const char *name, const char *expectation)
Definition unit_test.h:454
void() RunEntry()
Definition unit_test.h:452
virtual void Run()
SetFlagScope(T *flag, T value)
Definition unit_test.h:751
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:93
const char * expectation() const
Definition unit_test.h:291
static void AddToKernelBuffers(const uint8_t *kernel_buffer)
Definition unit_test.cc:100
static void RunAllRaw()
Definition unit_test.cc:71
const char * name() const
Definition unit_test.h:290
static void RunAll()
Definition unit_test.cc:82
virtual ~TestCaseBase()
Definition unit_test.h:288
static KernelBufferList * current_kernel_buffers_
Definition unit_test.h:302
static Dart_Handle TriggerReload(const uint8_t *kernel_buffer, intptr_t kernel_buffer_size)
Definition unit_test.cc:589
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:476
static Dart_Handle lib()
Definition unit_test.cc:629
static void AddTestLib(const char *url, const char *source)
Definition unit_test.cc:188
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:422
static const char * NullAssertTag()
Definition unit_test.h:422
static Dart_Handle ReloadTestScript(const char *script)
Definition unit_test.cc:599
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:300
static const char * LateTag()
Definition unit_test.h:423
static Dart_Isolate CreateTestIsolateInGroup(const char *name, Dart_Isolate parent, void *group_data=nullptr, void *isolate_data=nullptr)
Definition unit_test.cc:162
static Dart_Handle SetReloadTestScript(const char *script)
Definition unit_test.cc:525
static const char * url()
Definition unit_test.cc:184
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:414
virtual void Run()
static Dart_Handle LoadTestLibrary(const char *lib_uri, const char *script, Dart_NativeEntryResolver resolver=nullptr)
Definition unit_test.cc:441
static bool IsNNBD()
Definition unit_test.cc:217
static Dart_Handle ReloadTestKernel(const uint8_t *kernel_buffer, intptr_t kernel_buffer_size)
Definition unit_test.cc:617
TestCase(RunEntry *run, const char *name, const char *expectation)
Definition unit_test.h:324
static const char * NullableTag()
Definition unit_test.h:421
static Dart_Handle library_handler(Dart_LibraryTag tag, Dart_Handle library, Dart_Handle url)
Definition unit_test.cc:637
static Dart_Handle EvaluateExpression(const Library &lib, const String &expr, const Array &param_names, const Array &param_values)
Definition unit_test.cc:646
static Dart_Isolate CreateTestIsolate(const char *name=nullptr, void *isolate_group_data=nullptr, void *isolate_data=nullptr)
Definition unit_test.cc:139
static const char * GetTestLib(const char *url)
Definition unit_test.cc:205
static Dart_Handle LoadCoreTestScript(const char *script, Dart_NativeEntryResolver resolver)
Definition unit_test.cc:624
static Dart_Isolate CreateTestIsolateFromSnapshot(uint8_t *buffer, const char *name=nullptr)
Definition unit_test.h:381
Isolate * isolate() const
Definition unit_test.h:478
TestIsolateScope(void *isolate_group_data=nullptr, void *isolate_data=nullptr)
Definition unit_test.h:466
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:361
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:653
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:3225
void(* Dart_IsolateGroupCleanupCallback)(void *isolate_group_data)
Definition dart_api.h:744
Dart_LibraryTag
Definition dart_api.h:3339
void(* Dart_IsolateShutdownCallback)(void *isolate_group_data, void *isolate_data)
Definition dart_api.h:710
DART_EXPORT Dart_Handle Dart_NewStringFromCString(const char *str)
#define ASSERT(E)
SkBitmap source
Definition examples.cpp:28
FlutterSemanticsFlag flag
static const uint8_t buffer[]
uint8_t value
GAsyncResult * result
Dart_NativeFunction function
Definition fuchsia.cc:51
const uint8_t * vm_snapshot_data
Definition main_impl.cc:56
const uint8_t * vm_snapshot_instructions
Definition main_impl.cc:57
const uint8_t * core_isolate_snapshot_data
Definition main_impl.cc:58
const uint8_t * core_isolate_snapshot_instructions
Definition main_impl.cc:59
void ElideJSONSubstring(const char *prefix, const char *in, char *out, const char *postfix)
Definition unit_test.cc:776
DART_EXPORT void Dart_EnterScope()
const uint8_t * platform_strong_dill
Definition unit_test.cc:39
const char *const name
const intptr_t platform_strong_dill_size
Definition unit_test.cc:40
uintptr_t uword
Definition globals.h:501
void SetupCoreLibrariesForUnitTest()
Definition unit_test.cc:148
DART_EXPORT void Dart_ExitScope()
static CompileType * ResultType(Definition *call)
DART_EXPORT void Dart_ShutdownIsolate()
void StripTokenPositions(char *buffer)
Definition unit_test.cc:799
Definition run.py:1
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition globals.h:581
#define T
static constexpr bool value
Definition unit_test.h:502
static constexpr bool value
Definition unit_test.h:492
Dart_Handle NewString(const char *str)
Definition unit_test.h:229
#define RESOLVED_USER_TEST_URI
Definition unit_test.h:317