OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #ifndef RUNTIME_VM_UNIT_TEST_H_ | 5 #ifndef RUNTIME_VM_UNIT_TEST_H_ |
6 #define RUNTIME_VM_UNIT_TEST_H_ | 6 #define RUNTIME_VM_UNIT_TEST_H_ |
7 | 7 |
8 #include "include/dart_native_api.h" | 8 #include "include/dart_native_api.h" |
9 | 9 |
10 #include "platform/globals.h" | 10 #include "platform/globals.h" |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 // Populate node list with AST nodes. | 97 // Populate node list with AST nodes. |
98 #define CODEGEN_TEST_GENERATE(name, test) \ | 98 #define CODEGEN_TEST_GENERATE(name, test) \ |
99 static void CodeGenTestGenerate##name(CodeGenTest* test) | 99 static void CodeGenTestGenerate##name(CodeGenTest* test) |
100 | 100 |
101 // Populate node list with AST nodes, possibly using the provided function | 101 // Populate node list with AST nodes, possibly using the provided function |
102 // object built by a previous CODEGEN_TEST_GENERATE. | 102 // object built by a previous CODEGEN_TEST_GENERATE. |
103 #define CODEGEN_TEST2_GENERATE(name, function, test) \ | 103 #define CODEGEN_TEST2_GENERATE(name, function, test) \ |
104 static void CodeGenTestGenerate##name(const Function& function, \ | 104 static void CodeGenTestGenerate##name(const Function& function, \ |
105 CodeGenTest* test) | 105 CodeGenTest* test) |
106 | 106 |
107 | |
108 // Pass the name of test and the expected results as RawObject. | 107 // Pass the name of test and the expected results as RawObject. |
109 #define CODEGEN_TEST_RUN(name, expected) \ | 108 #define CODEGEN_TEST_RUN(name, expected) \ |
110 static void CodeGenTestRun##name(const Function& function); \ | 109 static void CodeGenTestRun##name(const Function& function); \ |
111 ISOLATE_UNIT_TEST_CASE(name) { \ | 110 ISOLATE_UNIT_TEST_CASE(name) { \ |
112 CodeGenTest __test__("" #name); \ | 111 CodeGenTest __test__("" #name); \ |
113 CodeGenTestGenerate##name(&__test__); \ | 112 CodeGenTestGenerate##name(&__test__); \ |
114 __test__.Compile(); \ | 113 __test__.Compile(); \ |
115 CodeGenTestRun##name(__test__.function()); \ | 114 CodeGenTestRun##name(__test__.function()); \ |
116 } \ | 115 } \ |
117 static void CodeGenTestRun##name(const Function& function) { \ | 116 static void CodeGenTestRun##name(const Function& function) { \ |
118 Object& result = Object::Handle(); \ | 117 Object& result = Object::Handle(); \ |
119 result = DartEntry::InvokeFunction(function, Object::empty_array()); \ | 118 result = DartEntry::InvokeFunction(function, Object::empty_array()); \ |
120 EXPECT(!result.IsError()); \ | 119 EXPECT(!result.IsError()); \ |
121 Instance& actual = Instance::Handle(); \ | 120 Instance& actual = Instance::Handle(); \ |
122 actual ^= result.raw(); \ | 121 actual ^= result.raw(); \ |
123 EXPECT(actual.CanonicalizeEquals(Instance::Handle(expected))); \ | 122 EXPECT(actual.CanonicalizeEquals(Instance::Handle(expected))); \ |
124 } | 123 } |
125 | 124 |
126 | |
127 // Pass the name of test, and use the generated function to call it | 125 // Pass the name of test, and use the generated function to call it |
128 // and evaluate its result. | 126 // and evaluate its result. |
129 #define CODEGEN_TEST_RAW_RUN(name, function) \ | 127 #define CODEGEN_TEST_RAW_RUN(name, function) \ |
130 static void CodeGenTestRun##name(const Function& function); \ | 128 static void CodeGenTestRun##name(const Function& function); \ |
131 ISOLATE_UNIT_TEST_CASE(name) { \ | 129 ISOLATE_UNIT_TEST_CASE(name) { \ |
132 CodeGenTest __test__("" #name); \ | 130 CodeGenTest __test__("" #name); \ |
133 CodeGenTestGenerate##name(&__test__); \ | 131 CodeGenTestGenerate##name(&__test__); \ |
134 __test__.Compile(); \ | 132 __test__.Compile(); \ |
135 CodeGenTestRun##name(__test__.function()); \ | 133 CodeGenTestRun##name(__test__.function()); \ |
136 } \ | 134 } \ |
137 static void CodeGenTestRun##name(const Function& function) | 135 static void CodeGenTestRun##name(const Function& function) |
138 | 136 |
139 | |
140 // Generate code for two sequences of AST nodes and execute the first one. | 137 // Generate code for two sequences of AST nodes and execute the first one. |
141 // The first one may reference the Function object generated by the second one. | 138 // The first one may reference the Function object generated by the second one. |
142 #define CODEGEN_TEST2_RUN(name1, name2, expected) \ | 139 #define CODEGEN_TEST2_RUN(name1, name2, expected) \ |
143 static void CodeGenTestRun##name1(const Function& function); \ | 140 static void CodeGenTestRun##name1(const Function& function); \ |
144 ISOLATE_UNIT_TEST_CASE(name1) { \ | 141 ISOLATE_UNIT_TEST_CASE(name1) { \ |
145 /* Generate code for name2 */ \ | 142 /* Generate code for name2 */ \ |
146 CodeGenTest __test2__("" #name2); \ | 143 CodeGenTest __test2__("" #name2); \ |
147 CodeGenTestGenerate##name2(&__test2__); \ | 144 CodeGenTestGenerate##name2(&__test2__); \ |
148 __test2__.Compile(); \ | 145 __test2__.Compile(); \ |
149 /* Generate code for name1, providing function2 */ \ | 146 /* Generate code for name1, providing function2 */ \ |
150 CodeGenTest __test1__("" #name1); \ | 147 CodeGenTest __test1__("" #name1); \ |
151 CodeGenTestGenerate##name1(__test2__.function(), &__test1__); \ | 148 CodeGenTestGenerate##name1(__test2__.function(), &__test1__); \ |
152 __test1__.Compile(); \ | 149 __test1__.Compile(); \ |
153 CodeGenTestRun##name1(__test1__.function()); \ | 150 CodeGenTestRun##name1(__test1__.function()); \ |
154 } \ | 151 } \ |
155 static void CodeGenTestRun##name1(const Function& function) { \ | 152 static void CodeGenTestRun##name1(const Function& function) { \ |
156 Object& result = Object::Handle(); \ | 153 Object& result = Object::Handle(); \ |
157 result = DartEntry::InvokeFunction(function, Object::empty_array()); \ | 154 result = DartEntry::InvokeFunction(function, Object::empty_array()); \ |
158 EXPECT(!result.IsError()); \ | 155 EXPECT(!result.IsError()); \ |
159 Instance& actual = Instance::Handle(); \ | 156 Instance& actual = Instance::Handle(); \ |
160 actual ^= result.raw(); \ | 157 actual ^= result.raw(); \ |
161 EXPECT(actual.CanonicalizeEquals(Instance::Handle(expected))); \ | 158 EXPECT(actual.CanonicalizeEquals(Instance::Handle(expected))); \ |
162 } | 159 } |
163 | 160 |
164 | |
165 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) | 161 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) |
166 #if defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64) | 162 #if defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64) |
167 // Running on actual ARM hardware, execute code natively. | 163 // Running on actual ARM hardware, execute code natively. |
168 #define EXECUTE_TEST_CODE_INT32(name, entry) reinterpret_cast<name>(entry)() | 164 #define EXECUTE_TEST_CODE_INT32(name, entry) reinterpret_cast<name>(entry)() |
169 #define EXECUTE_TEST_CODE_INT64(name, entry) reinterpret_cast<name>(entry)() | 165 #define EXECUTE_TEST_CODE_INT64(name, entry) reinterpret_cast<name>(entry)() |
170 #define EXECUTE_TEST_CODE_INT64_LL(name, entry, long_arg0, long_arg1) \ | 166 #define EXECUTE_TEST_CODE_INT64_LL(name, entry, long_arg0, long_arg1) \ |
171 reinterpret_cast<name>(entry)(long_arg0, long_arg1) | 167 reinterpret_cast<name>(entry)(long_arg0, long_arg1) |
172 #define EXECUTE_TEST_CODE_FLOAT(name, entry) reinterpret_cast<name>(entry)() | 168 #define EXECUTE_TEST_CODE_FLOAT(name, entry) reinterpret_cast<name>(entry)() |
173 #define EXECUTE_TEST_CODE_DOUBLE(name, entry) reinterpret_cast<name>(entry)() | 169 #define EXECUTE_TEST_CODE_DOUBLE(name, entry) reinterpret_cast<name>(entry)() |
174 #define EXECUTE_TEST_CODE_INT32_F(name, entry, float_arg) \ | 170 #define EXECUTE_TEST_CODE_INT32_F(name, entry, float_arg) \ |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 0, 0, false, true)) | 222 0, 0, false, true)) |
227 #define EXECUTE_TEST_CODE_INT32_D(name, entry, double_arg) \ | 223 #define EXECUTE_TEST_CODE_INT32_D(name, entry, double_arg) \ |
228 static_cast<int32_t>(Simulator::Current()->Call( \ | 224 static_cast<int32_t>(Simulator::Current()->Call( \ |
229 bit_cast<int32_t, uword>(entry), \ | 225 bit_cast<int32_t, uword>(entry), \ |
230 Utils::Low32Bits(bit_cast<int64_t, double>(double_arg)), \ | 226 Utils::Low32Bits(bit_cast<int64_t, double>(double_arg)), \ |
231 Utils::High32Bits(bit_cast<int64_t, double>(double_arg)), 0, 0, false, \ | 227 Utils::High32Bits(bit_cast<int64_t, double>(double_arg)), 0, 0, false, \ |
232 true)) | 228 true)) |
233 #endif // defined(HOST_ARCH_ARM) | 229 #endif // defined(HOST_ARCH_ARM) |
234 #endif // defined(TARGET_ARCH_{ARM, ARM64}) | 230 #endif // defined(TARGET_ARCH_{ARM, ARM64}) |
235 | 231 |
236 | |
237 inline Dart_Handle NewString(const char* str) { | 232 inline Dart_Handle NewString(const char* str) { |
238 return Dart_NewStringFromCString(str); | 233 return Dart_NewStringFromCString(str); |
239 } | 234 } |
240 | 235 |
241 | |
242 namespace dart { | 236 namespace dart { |
243 | 237 |
244 // Forward declarations. | 238 // Forward declarations. |
245 class Assembler; | 239 class Assembler; |
246 class CodeGenerator; | 240 class CodeGenerator; |
247 class VirtualMemory; | 241 class VirtualMemory; |
248 | 242 |
249 | |
250 namespace bin { | 243 namespace bin { |
251 // Snapshot pieces if we link in a snapshot, otherwise initialized to NULL. | 244 // Snapshot pieces if we link in a snapshot, otherwise initialized to NULL. |
252 extern const uint8_t* vm_snapshot_data; | 245 extern const uint8_t* vm_snapshot_data; |
253 extern const uint8_t* vm_snapshot_instructions; | 246 extern const uint8_t* vm_snapshot_instructions; |
254 extern const uint8_t* core_isolate_snapshot_data; | 247 extern const uint8_t* core_isolate_snapshot_data; |
255 extern const uint8_t* core_isolate_snapshot_instructions; | 248 extern const uint8_t* core_isolate_snapshot_instructions; |
256 } | 249 } // namespace bin |
257 | |
258 | 250 |
259 class TestCaseBase { | 251 class TestCaseBase { |
260 public: | 252 public: |
261 explicit TestCaseBase(const char* name); | 253 explicit TestCaseBase(const char* name); |
262 virtual ~TestCaseBase() {} | 254 virtual ~TestCaseBase() {} |
263 | 255 |
264 const char* name() const { return name_; } | 256 const char* name() const { return name_; } |
265 | 257 |
266 virtual void Run() = 0; | 258 virtual void Run() = 0; |
267 void RunTest(); | 259 void RunTest(); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 | 317 |
326 static void AddTestLib(const char* url, const char* source); | 318 static void AddTestLib(const char* url, const char* source); |
327 static const char* GetTestLib(const char* url); | 319 static const char* GetTestLib(const char* url); |
328 | 320 |
329 private: | 321 private: |
330 static Dart_Isolate CreateIsolate(const uint8_t* buffer, const char* name); | 322 static Dart_Isolate CreateIsolate(const uint8_t* buffer, const char* name); |
331 | 323 |
332 RunEntry* const run_; | 324 RunEntry* const run_; |
333 }; | 325 }; |
334 | 326 |
335 | |
336 class RawTestCase : TestCaseBase { | 327 class RawTestCase : TestCaseBase { |
337 public: | 328 public: |
338 typedef void(RunEntry)(); | 329 typedef void(RunEntry)(); |
339 | 330 |
340 RawTestCase(RunEntry* run, const char* name) : TestCaseBase(name), run_(run) { | 331 RawTestCase(RunEntry* run, const char* name) : TestCaseBase(name), run_(run) { |
341 raw_test_ = true; | 332 raw_test_ = true; |
342 } | 333 } |
343 virtual void Run(); | 334 virtual void Run(); |
344 | 335 |
345 private: | 336 private: |
346 RunEntry* const run_; | 337 RunEntry* const run_; |
347 }; | 338 }; |
348 | 339 |
349 | |
350 class TestIsolateScope { | 340 class TestIsolateScope { |
351 public: | 341 public: |
352 TestIsolateScope() { | 342 TestIsolateScope() { |
353 isolate_ = reinterpret_cast<Isolate*>(TestCase::CreateTestIsolate()); | 343 isolate_ = reinterpret_cast<Isolate*>(TestCase::CreateTestIsolate()); |
354 Dart_EnterScope(); // Create a Dart API scope for unit tests. | 344 Dart_EnterScope(); // Create a Dart API scope for unit tests. |
355 } | 345 } |
356 ~TestIsolateScope() { | 346 ~TestIsolateScope() { |
357 Dart_ExitScope(); // Exit the Dart API scope created for unit tests. | 347 Dart_ExitScope(); // Exit the Dart API scope created for unit tests. |
358 ASSERT(isolate_ == Isolate::Current()); | 348 ASSERT(isolate_ == Isolate::Current()); |
359 Dart_ShutdownIsolate(); | 349 Dart_ShutdownIsolate(); |
360 isolate_ = NULL; | 350 isolate_ = NULL; |
361 } | 351 } |
362 Isolate* isolate() const { return isolate_; } | 352 Isolate* isolate() const { return isolate_; } |
363 | 353 |
364 private: | 354 private: |
365 Isolate* isolate_; | 355 Isolate* isolate_; |
366 | 356 |
367 DISALLOW_COPY_AND_ASSIGN(TestIsolateScope); | 357 DISALLOW_COPY_AND_ASSIGN(TestIsolateScope); |
368 }; | 358 }; |
369 | 359 |
370 | |
371 template <typename T> | 360 template <typename T> |
372 struct is_void { | 361 struct is_void { |
373 static const bool value = false; | 362 static const bool value = false; |
374 }; | 363 }; |
375 | 364 |
376 | |
377 template <> | 365 template <> |
378 struct is_void<void> { | 366 struct is_void<void> { |
379 static const bool value = true; | 367 static const bool value = true; |
380 }; | 368 }; |
381 | 369 |
382 | |
383 template <typename T> | 370 template <typename T> |
384 struct is_double { | 371 struct is_double { |
385 static const bool value = false; | 372 static const bool value = false; |
386 }; | 373 }; |
387 | 374 |
388 | |
389 template <> | 375 template <> |
390 struct is_double<double> { | 376 struct is_double<double> { |
391 static const bool value = true; | 377 static const bool value = true; |
392 }; | 378 }; |
393 | 379 |
394 | |
395 class AssemblerTest { | 380 class AssemblerTest { |
396 public: | 381 public: |
397 AssemblerTest(const char* name, Assembler* assembler) | 382 AssemblerTest(const char* name, Assembler* assembler) |
398 : name_(name), assembler_(assembler), code_(Code::ZoneHandle()) { | 383 : name_(name), assembler_(assembler), code_(Code::ZoneHandle()) { |
399 ASSERT(name != NULL); | 384 ASSERT(name != NULL); |
400 ASSERT(assembler != NULL); | 385 ASSERT(assembler != NULL); |
401 } | 386 } |
402 ~AssemblerTest() {} | 387 ~AssemblerTest() {} |
403 | 388 |
404 Assembler* assembler() const { return assembler_; } | 389 Assembler* assembler() const { return assembler_; } |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
517 void Assemble(); | 502 void Assemble(); |
518 | 503 |
519 private: | 504 private: |
520 const char* name_; | 505 const char* name_; |
521 Assembler* assembler_; | 506 Assembler* assembler_; |
522 Code& code_; | 507 Code& code_; |
523 | 508 |
524 DISALLOW_COPY_AND_ASSIGN(AssemblerTest); | 509 DISALLOW_COPY_AND_ASSIGN(AssemblerTest); |
525 }; | 510 }; |
526 | 511 |
527 | |
528 class CodeGenTest { | 512 class CodeGenTest { |
529 public: | 513 public: |
530 explicit CodeGenTest(const char* name); | 514 explicit CodeGenTest(const char* name); |
531 ~CodeGenTest() {} | 515 ~CodeGenTest() {} |
532 | 516 |
533 // Accessors. | 517 // Accessors. |
534 const Function& function() const { return function_; } | 518 const Function& function() const { return function_; } |
535 | 519 |
536 SequenceNode* node_sequence() const { return node_sequence_; } | 520 SequenceNode* node_sequence() const { return node_sequence_; } |
537 | 521 |
538 void set_default_parameter_values(ZoneGrowableArray<const Instance*>* value) { | 522 void set_default_parameter_values(ZoneGrowableArray<const Instance*>* value) { |
539 default_parameter_values_ = value; | 523 default_parameter_values_ = value; |
540 } | 524 } |
541 | 525 |
542 // Compile test and set code in function. | 526 // Compile test and set code in function. |
543 void Compile(); | 527 void Compile(); |
544 | 528 |
545 private: | 529 private: |
546 Function& function_; | 530 Function& function_; |
547 SequenceNode* node_sequence_; | 531 SequenceNode* node_sequence_; |
548 ZoneGrowableArray<const Instance*>* default_parameter_values_; | 532 ZoneGrowableArray<const Instance*>* default_parameter_values_; |
549 | 533 |
550 DISALLOW_COPY_AND_ASSIGN(CodeGenTest); | 534 DISALLOW_COPY_AND_ASSIGN(CodeGenTest); |
551 }; | 535 }; |
552 | 536 |
553 | |
554 class CompilerTest : public AllStatic { | 537 class CompilerTest : public AllStatic { |
555 public: | 538 public: |
556 // Test the Compiler::CompileScript functionality by checking the return | 539 // Test the Compiler::CompileScript functionality by checking the return |
557 // value to see if no parse errors were reported. | 540 // value to see if no parse errors were reported. |
558 static bool TestCompileScript(const Library& library, const Script& script); | 541 static bool TestCompileScript(const Library& library, const Script& script); |
559 | 542 |
560 // Test the Compiler::CompileFunction functionality by checking the return | 543 // Test the Compiler::CompileFunction functionality by checking the return |
561 // value to see if no parse errors were reported. | 544 // value to see if no parse errors were reported. |
562 static bool TestCompileFunction(const Function& function); | 545 static bool TestCompileFunction(const Function& function); |
563 }; | 546 }; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 if (!value) { \ | 589 if (!value) { \ |
607 dart::Expect(__FILE__, __LINE__) \ | 590 dart::Expect(__FILE__, __LINE__) \ |
608 .Fail("expected True, but was '%s'\n", #handle); \ | 591 .Fail("expected True, but was '%s'\n", #handle); \ |
609 } \ | 592 } \ |
610 } else { \ | 593 } else { \ |
611 dart::Expect(__FILE__, __LINE__) \ | 594 dart::Expect(__FILE__, __LINE__) \ |
612 .Fail("expected True, but was '%s'\n", #handle); \ | 595 .Fail("expected True, but was '%s'\n", #handle); \ |
613 } \ | 596 } \ |
614 } while (0) | 597 } while (0) |
615 | 598 |
616 | |
617 // Elide a substring which starts with some prefix and ends with a ". | 599 // Elide a substring which starts with some prefix and ends with a ". |
618 // | 600 // |
619 // This is used to remove non-deterministic or fragile substrings from | 601 // This is used to remove non-deterministic or fragile substrings from |
620 // JSON output. | 602 // JSON output. |
621 // | 603 // |
622 // For example: | 604 // For example: |
623 // | 605 // |
624 // prefix = "classes" | 606 // prefix = "classes" |
625 // in = "\"id\":\"classes/46\"" | 607 // in = "\"id\":\"classes/46\"" |
626 // | 608 // |
627 // Yields: | 609 // Yields: |
628 // | 610 // |
629 // out = "\"id\":\"\"" | 611 // out = "\"id\":\"\"" |
630 // | 612 // |
631 void ElideJSONSubstring(const char* prefix, const char* in, char* out); | 613 void ElideJSONSubstring(const char* prefix, const char* in, char* out); |
632 | 614 |
633 | |
634 template <typename T> | 615 template <typename T> |
635 class SetFlagScope : public ValueObject { | 616 class SetFlagScope : public ValueObject { |
636 public: | 617 public: |
637 SetFlagScope(T* flag, T value) : flag_(flag), original_value_(*flag) { | 618 SetFlagScope(T* flag, T value) : flag_(flag), original_value_(*flag) { |
638 *flag_ = value; | 619 *flag_ = value; |
639 } | 620 } |
640 | 621 |
641 ~SetFlagScope() { *flag_ = original_value_; } | 622 ~SetFlagScope() { *flag_ = original_value_; } |
642 | 623 |
643 private: | 624 private: |
644 T* flag_; | 625 T* flag_; |
645 T original_value_; | 626 T original_value_; |
646 }; | 627 }; |
647 | 628 |
648 } // namespace dart | 629 } // namespace dart |
649 | 630 |
650 #endif // RUNTIME_VM_UNIT_TEST_H_ | 631 #endif // RUNTIME_VM_UNIT_TEST_H_ |
OLD | NEW |