1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <gtest/gtest.h>
17
18 #include <vector>
19
20 #include "assembly-parser.h"
21 #include "libpandafile/value.h"
22 #include "runtime/entrypoints/entrypoints.h"
23 #include "runtime/include/method.h"
24 #include "runtime/include/runtime.h"
25
26 namespace panda::test {
27
separator()28 inline std::string separator()
29 {
30 #ifdef _WIN32
31 return "\\";
32 #else
33 return "/";
34 #endif
35 }
36
37 class PandaExceptionTest : public testing::Test {
38 protected:
39 enum class ExType { INT = 0, JIT };
40
PandaExceptionTest()41 PandaExceptionTest()
42 {
43 options_.SetHeapSizeLimit(64_MB);
44 options_.SetInternalMemorySizeLimit(64_MB);
45
46 options_.SetShouldInitializeIntrinsics(false);
47
48 options_.SetBootClassSpaces({"core"});
49 options_.SetRuntimeType("core");
50
51 options_.SetGcType("gen-gc");
52
53 auto exec_path = panda::os::file::File::GetExecutablePath();
54 std::string panda_std_lib =
55 exec_path.Value() + separator() + ".." + separator() + "pandastdlib" + separator() + "pandastdlib.bin";
56 options_.SetBootPandaFiles({panda_std_lib});
57 }
58
~PandaExceptionTest()59 ~PandaExceptionTest()
60 {
61 thread_->ManagedCodeEnd();
62 Runtime::Destroy();
63 }
64
CreateRuntime(ExType ex_type)65 inline void CreateRuntime(ExType ex_type)
66 {
67 switch (ex_type) {
68 case ExType::INT: {
69 options_.SetCompilerEnableJit(false);
70 break;
71 }
72
73 case ExType::JIT: {
74 options_.SetCompilerEnableJit(true);
75 options_.SetCompilerHotnessThreshold(0);
76 break;
77 }
78 default: {
79 UNREACHABLE();
80 }
81 }
82
83 Runtime::Create(options_);
84
85 thread_ = panda::MTManagedThread::GetCurrent();
86 thread_->ManagedCodeBegin();
87 }
88
89 panda::MTManagedThread *thread_ {nullptr};
90 RuntimeOptions options_;
91 };
92
93 /**
94 * This test is a core test that's supposed
95 * to provoke the AbstractMethodException, to catch it,
96 * and to return 0 as the result.
97 */
TEST_F(PandaExceptionTest,AbstractMethodStaticCallShortINT)98 TEST_F(PandaExceptionTest, AbstractMethodStaticCallShortINT)
99 {
100 CreateRuntime(ExType::INT);
101
102 auto source = R"(
103 .record panda.AbstractMethodError <external>
104
105 .record panda.Exception <external>
106
107 .record R {}
108
109 .function void R.ctor(R a0) <ctor> {
110 return.void
111 }
112
113 .function void R.CauseAbstractMethodException(R a0) <noimpl>
114
115 .record ProvokeAbstractMethodException {
116 }
117
118 .function i32 ProvokeAbstractMethodException.main() <static> {
119 try_begin:
120 initobj R.ctor
121 sta.obj v0
122 call.short R.CauseAbstractMethodException, v0
123 try_end:
124 jmp no_exceptions
125 handler_begin_incorrect:
126 movi v0, 0x2
127 lda v0
128 return
129 handler_begin_correct:
130 movi v0, 0x0
131 lda v0
132 return
133 no_exceptions:
134 movi v0, 0xffffffffffffffff
135 lda v0
136 return
137
138 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
139 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
140 }
141 )";
142
143 pandasm::Parser parser;
144 auto res = parser.Parse(source);
145 ASSERT_TRUE(res);
146 auto pf = pandasm::AsmEmitter::Emit(res.Value());
147 ASSERT_NE(pf, nullptr);
148
149 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
150
151 class_linker->AddPandaFile(std::move(pf));
152
153 PandaString descriptor;
154
155 Class *klass =
156 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
157 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
158 ASSERT_NE(klass, nullptr);
159
160 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
161 ASSERT_NE(method, nullptr);
162
163 std::vector<Value> args;
164 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
165
166 int64_t expected_result = 0;
167 int64_t unexpected_exception = 2;
168 int64_t no_exceptions = -1;
169
170 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
171 << "AbstractMethod exception should have been thrown, but another has";
172 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
173 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
174 }
175
176 /**
177 * This test is a core test that's supposed
178 * to provoke the AbstractMethodException, to catch it,
179 * and to return 0 as the result.
180 */
TEST_F(PandaExceptionTest,AbstractMethodStaticCallShortJIT)181 TEST_F(PandaExceptionTest, AbstractMethodStaticCallShortJIT)
182 {
183 CreateRuntime(ExType::JIT);
184
185 auto source = R"(
186 .record panda.AbstractMethodError <external>
187
188 .record panda.Exception <external>
189
190 .record R {}
191
192 .function void R.ctor(R a0) <ctor> {
193 return.void
194 }
195
196 .function void R.CauseAbstractMethodException(R a0) <noimpl>
197
198 .record ProvokeAbstractMethodException {
199 }
200
201 .function i32 ProvokeAbstractMethodException.main() <static> {
202 try_begin:
203 initobj R.ctor
204 sta.obj v0
205 call.short R.CauseAbstractMethodException, v0
206 try_end:
207 jmp no_exceptions
208 handler_begin_incorrect:
209 movi v0, 0x2
210 lda v0
211 return
212 handler_begin_correct:
213 movi v0, 0x0
214 lda v0
215 return
216 no_exceptions:
217 movi v0, 0xffffffffffffffff
218 lda v0
219 return
220
221 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
222 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
223 }
224 )";
225
226 pandasm::Parser parser;
227 auto res = parser.Parse(source);
228 ASSERT_TRUE(res);
229 auto pf = pandasm::AsmEmitter::Emit(res.Value());
230 ASSERT_NE(pf, nullptr);
231
232 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
233
234 class_linker->AddPandaFile(std::move(pf));
235
236 PandaString descriptor;
237
238 Class *klass =
239 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
240 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
241 ASSERT_NE(klass, nullptr);
242
243 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
244 ASSERT_NE(method, nullptr);
245
246 std::vector<Value> args;
247 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
248
249 int64_t expected_result = 0;
250 int64_t unexpected_exception = 2;
251 int64_t no_exceptions = -1;
252
253 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
254 << "AbstractMethod exception should have been thrown, but another has";
255 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
256 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
257 }
258
259 /**
260 * This test is a core test that's supposed
261 * to provoke the AbstractMethodException, to catch it,
262 * and to return 0 as the result.
263 */
TEST_F(PandaExceptionTest,AbstractMethodStaticCallINT)264 TEST_F(PandaExceptionTest, AbstractMethodStaticCallINT)
265 {
266 CreateRuntime(ExType::INT);
267
268 auto source = R"(
269 .record panda.AbstractMethodError <external>
270
271 .record panda.Exception <external>
272
273 .record R {}
274
275 .function void R.ctor(R a0) <ctor> {
276 return.void
277 }
278
279 .function void R.CauseAbstractMethodException(R a0, i32 a1, i32 a2, i32 a3) <noimpl>
280
281 .record ProvokeAbstractMethodException {
282 }
283
284 .function i32 ProvokeAbstractMethodException.main() <static> {
285 try_begin:
286 movi v1, 1
287 movi v2, 2
288 movi v3, 3
289 initobj R.ctor
290 sta.obj v0
291 call R.CauseAbstractMethodException, v0, v1, v2, v3
292 try_end:
293 jmp no_exceptions
294 handler_begin_incorrect:
295 movi v0, 0x2
296 lda v0
297 return
298 handler_begin_correct:
299 movi v0, 0x0
300 lda v0
301 return
302 no_exceptions:
303 movi v0, 0xffffffffffffffff
304 lda v0
305 return
306
307 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
308 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
309 }
310 )";
311
312 pandasm::Parser parser;
313 auto res = parser.Parse(source);
314 ASSERT_TRUE(res);
315 auto pf = pandasm::AsmEmitter::Emit(res.Value());
316 ASSERT_NE(pf, nullptr);
317
318 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
319
320 class_linker->AddPandaFile(std::move(pf));
321
322 PandaString descriptor;
323
324 Class *klass =
325 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
326 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
327 ASSERT_NE(klass, nullptr);
328
329 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
330 ASSERT_NE(method, nullptr);
331
332 std::vector<Value> args;
333 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
334
335 int64_t expected_result = 0;
336 int64_t unexpected_exception = 2;
337 int64_t no_exceptions = -1;
338
339 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
340 << "AbstractMethod exception should have been thrown, but another has";
341 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
342 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
343 }
344
345 /**
346 * This test is a core test that's supposed
347 * to provoke the AbstractMethodException, to catch it,
348 * and to return 0 as the result.
349 */
TEST_F(PandaExceptionTest,AbstractMethodStaticCallJIT)350 TEST_F(PandaExceptionTest, AbstractMethodStaticCallJIT)
351 {
352 CreateRuntime(ExType::JIT);
353
354 auto source = R"(
355 .record panda.AbstractMethodError <external>
356
357 .record panda.Exception <external>
358
359 .record R {}
360
361 .function void R.ctor(R a0) <ctor> {
362 return.void
363 }
364
365 .function void R.CauseAbstractMethodException(R a0, i32 a1, i32 a2, i32 a3) <noimpl>
366
367 .record ProvokeAbstractMethodException {
368 }
369
370 .function i32 ProvokeAbstractMethodException.main() <static> {
371 try_begin:
372 movi v1, 1
373 movi v2, 2
374 movi v3, 3
375 initobj R.ctor
376 sta.obj v0
377 call R.CauseAbstractMethodException, v0, v1, v2, v3
378 try_end:
379 jmp no_exceptions
380 handler_begin_incorrect:
381 movi v0, 0x2
382 lda v0
383 return
384 handler_begin_correct:
385 movi v0, 0x0
386 lda v0
387 return
388 no_exceptions:
389 movi v0, 0xffffffffffffffff
390 lda v0
391 return
392
393 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
394 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
395 }
396 )";
397
398 pandasm::Parser parser;
399 auto res = parser.Parse(source);
400 ASSERT_TRUE(res);
401 auto pf = pandasm::AsmEmitter::Emit(res.Value());
402 ASSERT_NE(pf, nullptr);
403
404 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
405
406 class_linker->AddPandaFile(std::move(pf));
407
408 PandaString descriptor;
409
410 Class *klass =
411 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
412 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
413 ASSERT_NE(klass, nullptr);
414
415 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
416 ASSERT_NE(method, nullptr);
417
418 std::vector<Value> args;
419 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
420
421 int64_t expected_result = 0;
422 int64_t unexpected_exception = 2;
423 int64_t no_exceptions = -1;
424
425 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
426 << "AbstractMethod exception should have been thrown, but another has";
427 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
428 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
429 }
430
431 /**
432 * This test is a core test that's supposed
433 * to provoke the AbstractMethodException, to catch it,
434 * and to return 0 as the result.
435 */
TEST_F(PandaExceptionTest,AbstractMethodStaticCallRangeINT)436 TEST_F(PandaExceptionTest, AbstractMethodStaticCallRangeINT)
437 {
438 CreateRuntime(ExType::INT);
439
440 auto source = R"(
441 .record panda.AbstractMethodError <external>
442
443 .record panda.Exception <external>
444
445 .record R {}
446
447 .function void R.ctor(R a0) <ctor> {
448 return.void
449 }
450
451 .function void R.CauseAbstractMethodException(R a0, i32 a1, i32 a2, i32 a3, i32 a4) <noimpl>
452
453 .record ProvokeAbstractMethodException {
454 }
455
456 .function i32 ProvokeAbstractMethodException.main() <static> {
457 try_begin:
458 initobj R.ctor
459 sta.obj v0
460 movi v1, 1
461 movi v2, 2
462 movi v3, 3
463 movi v4, 4
464 call.range R.CauseAbstractMethodException, v0
465 try_end:
466 jmp no_exceptions
467 handler_begin_incorrect:
468 movi v0, 0x2
469 lda v0
470 return
471 handler_begin_correct:
472 movi v0, 0x0
473 lda v0
474 return
475 no_exceptions:
476 movi v0, 0xffffffffffffffff
477 lda v0
478 return
479
480 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
481 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
482 }
483 )";
484
485 pandasm::Parser parser;
486 auto res = parser.Parse(source);
487 ASSERT_TRUE(res);
488 auto pf = pandasm::AsmEmitter::Emit(res.Value());
489 ASSERT_NE(pf, nullptr);
490
491 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
492
493 class_linker->AddPandaFile(std::move(pf));
494
495 PandaString descriptor;
496
497 Class *klass =
498 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
499 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
500 ASSERT_NE(klass, nullptr);
501
502 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
503 ASSERT_NE(method, nullptr);
504
505 std::vector<Value> args;
506 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
507
508 int64_t expected_result = 0;
509 int64_t unexpected_exception = 2;
510 int64_t no_exceptions = -1;
511
512 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
513 << "AbstractMethod exception should have been thrown, but another has";
514 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
515 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
516 }
517
518 /**
519 * This test is a core test that's supposed
520 * to provoke the AbstractMethodException, to catch it,
521 * and to return 0 as the result.
522 */
TEST_F(PandaExceptionTest,AbstractMethodStaticCallRangeJIT)523 TEST_F(PandaExceptionTest, AbstractMethodStaticCallRangeJIT)
524 {
525 CreateRuntime(ExType::JIT);
526
527 auto source = R"(
528 .record panda.AbstractMethodError <external>
529
530 .record panda.Exception <external>
531
532 .record R {}
533
534 .function void R.ctor(R a0) <ctor> {
535 return.void
536 }
537
538 .function void R.CauseAbstractMethodException(R a0, i32 a1, i32 a2, i32 a3, i32 a4) <noimpl>
539
540 .record ProvokeAbstractMethodException {
541 }
542
543 .function i32 ProvokeAbstractMethodException.main() <static> {
544 try_begin:
545 initobj R.ctor
546 sta.obj v0
547 movi v1, 1
548 movi v2, 2
549 movi v3, 3
550 movi v4, 4
551 call.range R.CauseAbstractMethodException, v0
552 try_end:
553 jmp no_exceptions
554 handler_begin_incorrect:
555 movi v0, 0x2
556 lda v0
557 return
558 handler_begin_correct:
559 movi v0, 0x0
560 lda v0
561 return
562 no_exceptions:
563 movi v0, 0xffffffffffffffff
564 lda v0
565 return
566
567 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
568 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
569 }
570 )";
571
572 pandasm::Parser parser;
573 auto res = parser.Parse(source);
574 ASSERT_TRUE(res);
575 auto pf = pandasm::AsmEmitter::Emit(res.Value());
576 ASSERT_NE(pf, nullptr);
577
578 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
579
580 class_linker->AddPandaFile(std::move(pf));
581
582 PandaString descriptor;
583
584 Class *klass =
585 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
586 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
587 ASSERT_NE(klass, nullptr);
588
589 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
590 ASSERT_NE(method, nullptr);
591
592 std::vector<Value> args;
593 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
594
595 int64_t expected_result = 0;
596 int64_t unexpected_exception = 2;
597 int64_t no_exceptions = -1;
598
599 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
600 << "AbstractMethod exception should have been thrown, but another has";
601 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
602 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
603 }
604
605 /**
606 * This test is a core test that's supposed
607 * to provoke the AbstractMethodException, to catch it,
608 * and to return 0 as the result.
609 */
TEST_F(PandaExceptionTest,AbstractMethodStaticCallAccShortINT)610 TEST_F(PandaExceptionTest, AbstractMethodStaticCallAccShortINT)
611 {
612 CreateRuntime(ExType::INT);
613
614 auto source = R"(
615 .record panda.AbstractMethodError <external>
616
617 .record panda.Exception <external>
618
619 .record R {}
620
621 .function void R.ctor(R a0) <ctor> {
622 return.void
623 }
624
625 .function void R.CauseAbstractMethodException(R a0) <noimpl>
626
627 .record ProvokeAbstractMethodException {
628 }
629
630 .function i32 ProvokeAbstractMethodException.main() <static> {
631 try_begin:
632 movi v0, 1
633 initobj R.ctor
634 call.acc.short R.CauseAbstractMethodException, v0, 0
635 try_end:
636 jmp no_exceptions
637 handler_begin_incorrect:
638 movi v0, 0x2
639 lda v0
640 return
641 handler_begin_correct:
642 movi v0, 0x0
643 lda v0
644 return
645 no_exceptions:
646 movi v0, 0xffffffffffffffff
647 lda v0
648 return
649
650 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
651 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
652 }
653 )";
654
655 pandasm::Parser parser;
656 auto res = parser.Parse(source);
657 ASSERT_TRUE(res);
658 auto pf = pandasm::AsmEmitter::Emit(res.Value());
659 ASSERT_NE(pf, nullptr);
660
661 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
662
663 class_linker->AddPandaFile(std::move(pf));
664
665 PandaString descriptor;
666
667 Class *klass =
668 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
669 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
670 ASSERT_NE(klass, nullptr);
671
672 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
673 ASSERT_NE(method, nullptr);
674
675 std::vector<Value> args;
676 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
677
678 int64_t expected_result = 0;
679 int64_t unexpected_exception = 2;
680 int64_t no_exceptions = -1;
681
682 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
683 << "AbstractMethod exception should have been thrown, but another has";
684 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
685 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
686 }
687
688 /**
689 * This test is a core test that's supposed
690 * to provoke the AbstractMethodException, to catch it,
691 * and to return 0 as the result.
692 */
TEST_F(PandaExceptionTest,AbstractMethodStaticCallAccShortJIT)693 TEST_F(PandaExceptionTest, AbstractMethodStaticCallAccShortJIT)
694 {
695 CreateRuntime(ExType::JIT);
696
697 auto source = R"(
698 .record panda.AbstractMethodError <external>
699
700 .record panda.Exception <external>
701
702 .record R {}
703
704 .function void R.ctor(R a0) <ctor> {
705 return.void
706 }
707
708 .function void R.CauseAbstractMethodException(R a0) <noimpl>
709
710 .record ProvokeAbstractMethodException {
711 }
712
713 .function i32 ProvokeAbstractMethodException.main() <static> {
714 try_begin:
715 movi v0, 1
716 initobj R.ctor
717 call.acc.short R.CauseAbstractMethodException, v0, 0
718 try_end:
719 jmp no_exceptions
720 handler_begin_incorrect:
721 movi v0, 0x2
722 lda v0
723 return
724 handler_begin_correct:
725 movi v0, 0x0
726 lda v0
727 return
728 no_exceptions:
729 movi v0, 0xffffffffffffffff
730 lda v0
731 return
732
733 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
734 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
735 }
736 )";
737
738 pandasm::Parser parser;
739 auto res = parser.Parse(source);
740 ASSERT_TRUE(res);
741 auto pf = pandasm::AsmEmitter::Emit(res.Value());
742 ASSERT_NE(pf, nullptr);
743
744 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
745
746 class_linker->AddPandaFile(std::move(pf));
747
748 PandaString descriptor;
749
750 Class *klass =
751 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
752 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
753 ASSERT_NE(klass, nullptr);
754
755 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
756 ASSERT_NE(method, nullptr);
757
758 std::vector<Value> args;
759 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
760
761 int64_t expected_result = 0;
762 int64_t unexpected_exception = 2;
763 int64_t no_exceptions = -1;
764
765 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
766 << "AbstractMethod exception should have been thrown, but another has";
767 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
768 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
769 }
770
771 /**
772 * This test is a core test that's supposed
773 * to provoke the AbstractMethodException, to catch it,
774 * and to return 0 as the result.
775 */
TEST_F(PandaExceptionTest,AbstractMethodStaticCallAccINT)776 TEST_F(PandaExceptionTest, AbstractMethodStaticCallAccINT)
777 {
778 CreateRuntime(ExType::INT);
779
780 auto source = R"(
781 .record panda.AbstractMethodError <external>
782
783 .record panda.Exception <external>
784
785 .record R {}
786
787 .function void R.ctor(R a0) <ctor> {
788 return.void
789 }
790
791 .function void R.CauseAbstractMethodException(R a0, i32 a1, i32 a2, i32 a3) <noimpl>
792
793 .record ProvokeAbstractMethodException {
794 }
795
796 .function i32 ProvokeAbstractMethodException.main() <static> {
797 try_begin:
798 movi v0, 1
799 movi v1, 2
800 movi v2, 3
801 initobj R.ctor
802 call.acc R.CauseAbstractMethodException, v0, v1, v2, 0
803 try_end:
804 jmp no_exceptions
805 handler_begin_incorrect:
806 movi v0, 0x2
807 lda v0
808 return
809 handler_begin_correct:
810 movi v0, 0x0
811 lda v0
812 return
813 no_exceptions:
814 movi v0, 0xffffffffffffffff
815 lda v0
816 return
817
818 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
819 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
820 }
821 )";
822
823 pandasm::Parser parser;
824 auto res = parser.Parse(source);
825 ASSERT_TRUE(res);
826 auto pf = pandasm::AsmEmitter::Emit(res.Value());
827 ASSERT_NE(pf, nullptr);
828
829 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
830
831 class_linker->AddPandaFile(std::move(pf));
832
833 PandaString descriptor;
834
835 Class *klass =
836 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
837 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
838 ASSERT_NE(klass, nullptr);
839
840 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
841 ASSERT_NE(method, nullptr);
842
843 std::vector<Value> args;
844 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
845
846 int64_t expected_result = 0;
847 int64_t unexpected_exception = 2;
848 int64_t no_exceptions = -1;
849
850 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
851 << "AbstractMethod exception should have been thrown, but another has";
852 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
853 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
854 }
855
856 /**
857 * This test is a core test that's supposed
858 * to provoke the AbstractMethodException, to catch it,
859 * and to return 0 as the result.
860 */
TEST_F(PandaExceptionTest,AbstractMethodStaticCallAccJIT)861 TEST_F(PandaExceptionTest, AbstractMethodStaticCallAccJIT)
862 {
863 CreateRuntime(ExType::JIT);
864
865 auto source = R"(
866 .record panda.AbstractMethodError <external>
867
868 .record panda.Exception <external>
869
870 .record R {}
871
872 .function void R.ctor(R a0) <ctor> {
873 return.void
874 }
875
876 .function void R.CauseAbstractMethodException(R a0, i32 a1, i32 a2, i32 a3) <noimpl>
877
878 .record ProvokeAbstractMethodException {
879 }
880
881 .function i32 ProvokeAbstractMethodException.main() <static> {
882 try_begin:
883 movi v0, 1
884 movi v1, 2
885 movi v2, 3
886 initobj R.ctor
887 call.acc R.CauseAbstractMethodException, v0, v1, v2, 0
888 try_end:
889 jmp no_exceptions
890 handler_begin_incorrect:
891 movi v0, 0x2
892 lda v0
893 return
894 handler_begin_correct:
895 movi v0, 0x0
896 lda v0
897 return
898 no_exceptions:
899 movi v0, 0xffffffffffffffff
900 lda v0
901 return
902
903 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
904 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
905 }
906 )";
907
908 pandasm::Parser parser;
909 auto res = parser.Parse(source);
910 ASSERT_TRUE(res);
911 auto pf = pandasm::AsmEmitter::Emit(res.Value());
912 ASSERT_NE(pf, nullptr);
913
914 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
915
916 class_linker->AddPandaFile(std::move(pf));
917
918 PandaString descriptor;
919
920 Class *klass =
921 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
922 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
923 ASSERT_NE(klass, nullptr);
924
925 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
926 ASSERT_NE(method, nullptr);
927
928 std::vector<Value> args;
929 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
930
931 int64_t expected_result = 0;
932 int64_t unexpected_exception = 2;
933 int64_t no_exceptions = -1;
934
935 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
936 << "AbstractMethod exception should have been thrown, but another has";
937 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
938 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
939 }
940
941 /**
942 * This test is a core test that's supposed
943 * to provoke the AbstractMethodException, to catch it,
944 * and to return 0 as the result.
945 */
TEST_F(PandaExceptionTest,AbstractMethodVirtualCallShortINT)946 TEST_F(PandaExceptionTest, AbstractMethodVirtualCallShortINT)
947 {
948 CreateRuntime(ExType::INT);
949
950 auto source = R"(
951 .record panda.AbstractMethodError <external>
952
953 .record panda.Exception <external>
954
955 .record R {}
956
957 .function void R.ctor(R a0) <ctor> {
958 return.void
959 }
960
961 .function void R.CauseAbstractMethodException(R a0) <noimpl>
962
963 .record ProvokeAbstractMethodException {
964 }
965
966 .function i32 ProvokeAbstractMethodException.main() <static> {
967 try_begin:
968 initobj R.ctor
969 sta.obj v0
970 call.virt.short R.CauseAbstractMethodException, v0
971 try_end:
972 jmp no_exceptions
973 handler_begin_incorrect:
974 movi v0, 0x2
975 lda v0
976 return
977 handler_begin_correct:
978 movi v0, 0x0
979 lda v0
980 return
981 no_exceptions:
982 movi v0, 0xffffffffffffffff
983 lda v0
984 return
985
986 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
987 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
988 }
989 )";
990
991 pandasm::Parser parser;
992 auto res = parser.Parse(source);
993 ASSERT_TRUE(res);
994 auto pf = pandasm::AsmEmitter::Emit(res.Value());
995 ASSERT_NE(pf, nullptr);
996
997 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
998
999 class_linker->AddPandaFile(std::move(pf));
1000
1001 PandaString descriptor;
1002
1003 Class *klass =
1004 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
1005 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
1006 ASSERT_NE(klass, nullptr);
1007
1008 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
1009 ASSERT_NE(method, nullptr);
1010
1011 std::vector<Value> args;
1012 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
1013
1014 int64_t expected_result = 0;
1015 int64_t unexpected_exception = 2;
1016 int64_t no_exceptions = -1;
1017
1018 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
1019 << "AbstractMethod exception should have been thrown, but another has";
1020 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
1021 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
1022 }
1023
1024 /**
1025 * This test is a core test that's supposed
1026 * to provoke the AbstractMethodException, to catch it,
1027 * and to return 0 as the result.
1028 */
TEST_F(PandaExceptionTest,AbstractMethodVirtualCallShortJIT)1029 TEST_F(PandaExceptionTest, AbstractMethodVirtualCallShortJIT)
1030 {
1031 CreateRuntime(ExType::JIT);
1032
1033 auto source = R"(
1034 .record panda.AbstractMethodError <external>
1035
1036 .record panda.Exception <external>
1037
1038 .record R {}
1039
1040 .function void R.ctor(R a0) <ctor> {
1041 return.void
1042 }
1043
1044 .function void R.CauseAbstractMethodException(R a0) <noimpl>
1045
1046 .record ProvokeAbstractMethodException {
1047 }
1048
1049 .function i32 ProvokeAbstractMethodException.main() <static> {
1050 try_begin:
1051 initobj R.ctor
1052 sta.obj v0
1053 call.virt.short R.CauseAbstractMethodException, v0
1054 try_end:
1055 jmp no_exceptions
1056 handler_begin_incorrect:
1057 movi v0, 0x2
1058 lda v0
1059 return
1060 handler_begin_correct:
1061 movi v0, 0x0
1062 lda v0
1063 return
1064 no_exceptions:
1065 movi v0, 0xffffffffffffffff
1066 lda v0
1067 return
1068
1069 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
1070 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
1071 }
1072 )";
1073
1074 pandasm::Parser parser;
1075 auto res = parser.Parse(source);
1076 ASSERT_TRUE(res);
1077 auto pf = pandasm::AsmEmitter::Emit(res.Value());
1078 ASSERT_NE(pf, nullptr);
1079
1080 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
1081
1082 class_linker->AddPandaFile(std::move(pf));
1083
1084 PandaString descriptor;
1085
1086 Class *klass =
1087 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
1088 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
1089 ASSERT_NE(klass, nullptr);
1090
1091 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
1092 ASSERT_NE(method, nullptr);
1093
1094 std::vector<Value> args;
1095 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
1096
1097 int64_t expected_result = 0;
1098 int64_t unexpected_exception = 2;
1099 int64_t no_exceptions = -1;
1100
1101 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
1102 << "AbstractMethod exception should have been thrown, but another has";
1103 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
1104 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
1105 }
1106
1107 /**
1108 * This test is a core test that's supposed
1109 * to provoke the AbstractMethodException, to catch it,
1110 * and to return 0 as the result.
1111 */
TEST_F(PandaExceptionTest,AbstractMethodVirtualCallINT)1112 TEST_F(PandaExceptionTest, AbstractMethodVirtualCallINT)
1113 {
1114 CreateRuntime(ExType::INT);
1115
1116 auto source = R"(
1117 .record panda.AbstractMethodError <external>
1118
1119 .record panda.Exception <external>
1120
1121 .record R {}
1122
1123 .function void R.ctor(R a0) <ctor> {
1124 return.void
1125 }
1126
1127 .function void R.CauseAbstractMethodException(R a0, i32 a1, i32 a2, i32 a3) <noimpl>
1128
1129 .record ProvokeAbstractMethodException {
1130 }
1131
1132 .function i32 ProvokeAbstractMethodException.main() <static> {
1133 try_begin:
1134 movi v1, 1
1135 movi v2, 2
1136 movi v3, 3
1137 initobj R.ctor
1138 sta.obj v0
1139 call.virt R.CauseAbstractMethodException, v0, v1, v2, v3
1140 try_end:
1141 jmp no_exceptions
1142 handler_begin_incorrect:
1143 movi v0, 0x2
1144 lda v0
1145 return
1146 handler_begin_correct:
1147 movi v0, 0x0
1148 lda v0
1149 return
1150 no_exceptions:
1151 movi v0, 0xffffffffffffffff
1152 lda v0
1153 return
1154
1155 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
1156 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
1157 }
1158 )";
1159
1160 pandasm::Parser parser;
1161 auto res = parser.Parse(source);
1162 ASSERT_TRUE(res);
1163 auto pf = pandasm::AsmEmitter::Emit(res.Value());
1164 ASSERT_NE(pf, nullptr);
1165
1166 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
1167
1168 class_linker->AddPandaFile(std::move(pf));
1169
1170 PandaString descriptor;
1171
1172 Class *klass =
1173 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
1174 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
1175 ASSERT_NE(klass, nullptr);
1176
1177 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
1178 ASSERT_NE(method, nullptr);
1179
1180 std::vector<Value> args;
1181 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
1182
1183 int64_t expected_result = 0;
1184 int64_t unexpected_exception = 2;
1185 int64_t no_exceptions = -1;
1186
1187 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
1188 << "AbstractMethod exception should have been thrown, but another has";
1189 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
1190 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
1191 }
1192
1193 /**
1194 * This test is a core test that's supposed
1195 * to provoke the AbstractMethodException, to catch it,
1196 * and to return 0 as the result.
1197 */
TEST_F(PandaExceptionTest,AbstractMethodVirtualCallJIT)1198 TEST_F(PandaExceptionTest, AbstractMethodVirtualCallJIT)
1199 {
1200 CreateRuntime(ExType::JIT);
1201
1202 auto source = R"(
1203 .record panda.AbstractMethodError <external>
1204
1205 .record panda.Exception <external>
1206
1207 .record R {}
1208
1209 .function void R.ctor(R a0) <ctor> {
1210 return.void
1211 }
1212
1213 .function void R.CauseAbstractMethodException(R a0, i32 a1, i32 a2, i32 a3) <noimpl>
1214
1215 .record ProvokeAbstractMethodException {
1216 }
1217
1218 .function i32 ProvokeAbstractMethodException.main() <static> {
1219 try_begin:
1220 movi v1, 1
1221 movi v2, 2
1222 movi v3, 3
1223 initobj R.ctor
1224 sta.obj v0
1225 call.virt R.CauseAbstractMethodException, v0, v1, v2, v3
1226 try_end:
1227 jmp no_exceptions
1228 handler_begin_incorrect:
1229 movi v0, 0x2
1230 lda v0
1231 return
1232 handler_begin_correct:
1233 movi v0, 0x0
1234 lda v0
1235 return
1236 no_exceptions:
1237 movi v0, 0xffffffffffffffff
1238 lda v0
1239 return
1240
1241 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
1242 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
1243 }
1244 )";
1245
1246 pandasm::Parser parser;
1247 auto res = parser.Parse(source);
1248 ASSERT_TRUE(res);
1249 auto pf = pandasm::AsmEmitter::Emit(res.Value());
1250 ASSERT_NE(pf, nullptr);
1251
1252 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
1253
1254 class_linker->AddPandaFile(std::move(pf));
1255
1256 PandaString descriptor;
1257
1258 Class *klass =
1259 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
1260 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
1261 ASSERT_NE(klass, nullptr);
1262
1263 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
1264 ASSERT_NE(method, nullptr);
1265
1266 std::vector<Value> args;
1267 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
1268
1269 int64_t expected_result = 0;
1270 int64_t unexpected_exception = 2;
1271 int64_t no_exceptions = -1;
1272
1273 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
1274 << "AbstractMethod exception should have been thrown, but another has";
1275 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
1276 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
1277 }
1278
1279 /**
1280 * This test is a core test that's supposed
1281 * to provoke the AbstractMethodException, to catch it,
1282 * and to return 0 as the result.
1283 */
TEST_F(PandaExceptionTest,AbstractMethodVirtualCallRangeINT)1284 TEST_F(PandaExceptionTest, AbstractMethodVirtualCallRangeINT)
1285 {
1286 CreateRuntime(ExType::INT);
1287
1288 auto source = R"(
1289 .record panda.AbstractMethodError <external>
1290
1291 .record panda.Exception <external>
1292
1293 .record R {}
1294
1295 .function void R.ctor(R a0) <ctor> {
1296 return.void
1297 }
1298
1299 .function void R.CauseAbstractMethodException(R a0, i32 a1, i32 a2, i32 a3, i32 a4) <noimpl>
1300
1301 .record ProvokeAbstractMethodException {
1302 }
1303
1304 .function i32 ProvokeAbstractMethodException.main() <static> {
1305 try_begin:
1306 initobj R.ctor
1307 sta.obj v0
1308 movi v1, 1
1309 movi v2, 2
1310 movi v3, 3
1311 movi v4, 4
1312 call.virt.range R.CauseAbstractMethodException, v0
1313 try_end:
1314 jmp no_exceptions
1315 handler_begin_incorrect:
1316 movi v0, 0x2
1317 lda v0
1318 return
1319 handler_begin_correct:
1320 movi v0, 0x0
1321 lda v0
1322 return
1323 no_exceptions:
1324 movi v0, 0xffffffffffffffff
1325 lda v0
1326 return
1327
1328 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
1329 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
1330 }
1331 )";
1332
1333 pandasm::Parser parser;
1334 auto res = parser.Parse(source);
1335 ASSERT_TRUE(res);
1336 auto pf = pandasm::AsmEmitter::Emit(res.Value());
1337 ASSERT_NE(pf, nullptr);
1338
1339 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
1340
1341 class_linker->AddPandaFile(std::move(pf));
1342
1343 PandaString descriptor;
1344
1345 Class *klass =
1346 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
1347 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
1348 ASSERT_NE(klass, nullptr);
1349
1350 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
1351 ASSERT_NE(method, nullptr);
1352
1353 std::vector<Value> args;
1354 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
1355
1356 int64_t expected_result = 0;
1357 int64_t unexpected_exception = 2;
1358 int64_t no_exceptions = -1;
1359
1360 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
1361 << "AbstractMethod exception should have been thrown, but another has";
1362 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
1363 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
1364 }
1365
1366 /**
1367 * This test is a core test that's supposed
1368 * to provoke the AbstractMethodException, to catch it,
1369 * and to return 0 as the result.
1370 */
TEST_F(PandaExceptionTest,AbstractMethodVirtualCallRangeJIT)1371 TEST_F(PandaExceptionTest, AbstractMethodVirtualCallRangeJIT)
1372 {
1373 CreateRuntime(ExType::JIT);
1374
1375 auto source = R"(
1376 .record panda.AbstractMethodError <external>
1377
1378 .record panda.Exception <external>
1379
1380 .record R {}
1381
1382 .function void R.ctor(R a0) <ctor> {
1383 return.void
1384 }
1385
1386 .function void R.CauseAbstractMethodException(R a0, i32 a1, i32 a2, i32 a3, i32 a4) <noimpl>
1387
1388 .record ProvokeAbstractMethodException {
1389 }
1390
1391 .function i32 ProvokeAbstractMethodException.main() <static> {
1392 try_begin:
1393 initobj R.ctor
1394 sta.obj v0
1395 movi v1, 1
1396 movi v2, 2
1397 movi v3, 3
1398 movi v4, 4
1399 call.virt.range R.CauseAbstractMethodException, v0
1400 try_end:
1401 jmp no_exceptions
1402 handler_begin_incorrect:
1403 movi v0, 0x2
1404 lda v0
1405 return
1406 handler_begin_correct:
1407 movi v0, 0x0
1408 lda v0
1409 return
1410 no_exceptions:
1411 movi v0, 0xffffffffffffffff
1412 lda v0
1413 return
1414
1415 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
1416 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
1417 }
1418 )";
1419
1420 pandasm::Parser parser;
1421 auto res = parser.Parse(source);
1422 ASSERT_TRUE(res);
1423 auto pf = pandasm::AsmEmitter::Emit(res.Value());
1424 ASSERT_NE(pf, nullptr);
1425
1426 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
1427
1428 class_linker->AddPandaFile(std::move(pf));
1429
1430 PandaString descriptor;
1431
1432 Class *klass =
1433 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
1434 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
1435 ASSERT_NE(klass, nullptr);
1436
1437 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
1438 ASSERT_NE(method, nullptr);
1439
1440 std::vector<Value> args;
1441 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
1442
1443 int64_t expected_result = 0;
1444 int64_t unexpected_exception = 2;
1445 int64_t no_exceptions = -1;
1446
1447 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
1448 << "AbstractMethod exception should have been thrown, but another has";
1449 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
1450 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
1451 }
1452
1453 /**
1454 * This test is a core test that's supposed
1455 * to provoke the AbstractMethodException, to catch it,
1456 * and to return 0 as the result.
1457 */
TEST_F(PandaExceptionTest,AbstractMethodVirtualCallAccShortINT)1458 TEST_F(PandaExceptionTest, AbstractMethodVirtualCallAccShortINT)
1459 {
1460 CreateRuntime(ExType::INT);
1461
1462 auto source = R"(
1463 .record panda.AbstractMethodError <external>
1464
1465 .record panda.Exception <external>
1466
1467 .record R {}
1468
1469 .function void R.ctor(R a0) <ctor> {
1470 return.void
1471 }
1472
1473 .function void R.CauseAbstractMethodException(R a0) <noimpl>
1474
1475 .record ProvokeAbstractMethodException {
1476 }
1477
1478 .function i32 ProvokeAbstractMethodException.main() <static> {
1479 try_begin:
1480 movi v0, 1
1481 initobj R.ctor
1482 call.virt.acc.short R.CauseAbstractMethodException, v0, 0
1483 try_end:
1484 jmp no_exceptions
1485 handler_begin_incorrect:
1486 movi v0, 0x2
1487 lda v0
1488 return
1489 handler_begin_correct:
1490 movi v0, 0x0
1491 lda v0
1492 return
1493 no_exceptions:
1494 movi v0, 0xffffffffffffffff
1495 lda v0
1496 return
1497
1498 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
1499 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
1500 }
1501 )";
1502
1503 pandasm::Parser parser;
1504 auto res = parser.Parse(source);
1505 ASSERT_TRUE(res);
1506 auto pf = pandasm::AsmEmitter::Emit(res.Value());
1507 ASSERT_NE(pf, nullptr);
1508
1509 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
1510
1511 class_linker->AddPandaFile(std::move(pf));
1512
1513 PandaString descriptor;
1514
1515 Class *klass =
1516 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
1517 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
1518 ASSERT_NE(klass, nullptr);
1519
1520 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
1521 ASSERT_NE(method, nullptr);
1522
1523 std::vector<Value> args;
1524 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
1525
1526 int64_t expected_result = 0;
1527 int64_t unexpected_exception = 2;
1528 int64_t no_exceptions = -1;
1529
1530 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
1531 << "AbstractMethod exception should have been thrown, but another has";
1532 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
1533 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
1534 }
1535
1536 /**
1537 * This test is a core test that's supposed
1538 * to provoke the AbstractMethodException, to catch it,
1539 * and to return 0 as the result.
1540 */
TEST_F(PandaExceptionTest,AbstractMethodVirtualCallAccShortJIT)1541 TEST_F(PandaExceptionTest, AbstractMethodVirtualCallAccShortJIT)
1542 {
1543 CreateRuntime(ExType::JIT);
1544
1545 auto source = R"(
1546 .record panda.AbstractMethodError <external>
1547
1548 .record panda.Exception <external>
1549
1550 .record R {}
1551
1552 .function void R.ctor(R a0) <ctor> {
1553 return.void
1554 }
1555
1556 .function void R.CauseAbstractMethodException(R a0) <noimpl>
1557
1558 .record ProvokeAbstractMethodException {
1559 }
1560
1561 .function i32 ProvokeAbstractMethodException.main() <static> {
1562 try_begin:
1563 movi v0, 1
1564 initobj R.ctor
1565 call.virt.acc.short R.CauseAbstractMethodException, v0, 0
1566 try_end:
1567 jmp no_exceptions
1568 handler_begin_incorrect:
1569 movi v0, 0x2
1570 lda v0
1571 return
1572 handler_begin_correct:
1573 movi v0, 0x0
1574 lda v0
1575 return
1576 no_exceptions:
1577 movi v0, 0xffffffffffffffff
1578 lda v0
1579 return
1580
1581 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
1582 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
1583 }
1584 )";
1585
1586 pandasm::Parser parser;
1587 auto res = parser.Parse(source);
1588 ASSERT_TRUE(res);
1589 auto pf = pandasm::AsmEmitter::Emit(res.Value());
1590 ASSERT_NE(pf, nullptr);
1591
1592 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
1593
1594 class_linker->AddPandaFile(std::move(pf));
1595
1596 PandaString descriptor;
1597
1598 Class *klass =
1599 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
1600 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
1601 ASSERT_NE(klass, nullptr);
1602
1603 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
1604 ASSERT_NE(method, nullptr);
1605
1606 std::vector<Value> args;
1607 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
1608
1609 int64_t expected_result = 0;
1610 int64_t unexpected_exception = 2;
1611 int64_t no_exceptions = -1;
1612
1613 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
1614 << "AbstractMethod exception should have been thrown, but another has";
1615 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
1616 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
1617 }
1618
1619 /**
1620 * This test is a core test that's supposed
1621 * to provoke the AbstractMethodException, to catch it,
1622 * and to return 0 as the result.
1623 */
TEST_F(PandaExceptionTest,AbstractMethodVirtualCallAccINT)1624 TEST_F(PandaExceptionTest, AbstractMethodVirtualCallAccINT)
1625 {
1626 CreateRuntime(ExType::INT);
1627
1628 auto source = R"(
1629 .record panda.AbstractMethodError <external>
1630
1631 .record panda.Exception <external>
1632
1633 .record R {}
1634
1635 .function void R.ctor(R a0) <ctor> {
1636 return.void
1637 }
1638
1639 .function void R.CauseAbstractMethodException(R a0, i32 a1, i32 a2, i32 a3) <noimpl>
1640
1641 .record ProvokeAbstractMethodException {
1642 }
1643
1644 .function i32 ProvokeAbstractMethodException.main() <static> {
1645 try_begin:
1646 movi v0, 1
1647 movi v1, 2
1648 movi v2, 3
1649 initobj R.ctor
1650 call.virt.acc R.CauseAbstractMethodException, v0, v1, v2, 0
1651 try_end:
1652 jmp no_exceptions
1653 handler_begin_incorrect:
1654 movi v0, 0x2
1655 lda v0
1656 return
1657 handler_begin_correct:
1658 movi v0, 0x0
1659 lda v0
1660 return
1661 no_exceptions:
1662 movi v0, 0xffffffffffffffff
1663 lda v0
1664 return
1665
1666 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
1667 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
1668 }
1669 )";
1670
1671 pandasm::Parser parser;
1672 auto res = parser.Parse(source);
1673 ASSERT_TRUE(res);
1674 auto pf = pandasm::AsmEmitter::Emit(res.Value());
1675 ASSERT_NE(pf, nullptr);
1676
1677 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
1678
1679 class_linker->AddPandaFile(std::move(pf));
1680
1681 PandaString descriptor;
1682
1683 Class *klass =
1684 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
1685 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
1686 ASSERT_NE(klass, nullptr);
1687
1688 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
1689 ASSERT_NE(method, nullptr);
1690
1691 std::vector<Value> args;
1692 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
1693
1694 int64_t expected_result = 0;
1695 int64_t unexpected_exception = 2;
1696 int64_t no_exceptions = -1;
1697
1698 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
1699 << "AbstractMethod exception should have been thrown, but another has";
1700 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
1701 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
1702 }
1703
1704 /**
1705 * This test is a core test that's supposed
1706 * to provoke the AbstractMethodException, to catch it,
1707 * and to return 0 as the result.
1708 */
TEST_F(PandaExceptionTest,AbstractMethodVirtualCallAccJIT)1709 TEST_F(PandaExceptionTest, AbstractMethodVirtualCallAccJIT)
1710 {
1711 CreateRuntime(ExType::JIT);
1712
1713 auto source = R"(
1714 .record panda.AbstractMethodError <external>
1715
1716 .record panda.Exception <external>
1717
1718 .record R {}
1719
1720 .function void R.ctor(R a0) <ctor> {
1721 return.void
1722 }
1723
1724 .function void R.CauseAbstractMethodException(R a0, i32 a1, i32 a2, i32 a3) <noimpl>
1725
1726 .record ProvokeAbstractMethodException {
1727 }
1728
1729 .function i32 ProvokeAbstractMethodException.main() <static> {
1730 try_begin:
1731 movi v0, 1
1732 movi v1, 2
1733 movi v2, 3
1734 initobj R.ctor
1735 call.virt.acc R.CauseAbstractMethodException, v0, v1, v2, 0
1736 try_end:
1737 jmp no_exceptions
1738 handler_begin_incorrect:
1739 movi v0, 0x2
1740 lda v0
1741 return
1742 handler_begin_correct:
1743 movi v0, 0x0
1744 lda v0
1745 return
1746 no_exceptions:
1747 movi v0, 0xffffffffffffffff
1748 lda v0
1749 return
1750
1751 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
1752 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
1753 }
1754 )";
1755
1756 pandasm::Parser parser;
1757 auto res = parser.Parse(source);
1758 ASSERT_TRUE(res);
1759 auto pf = pandasm::AsmEmitter::Emit(res.Value());
1760 ASSERT_NE(pf, nullptr);
1761
1762 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
1763
1764 class_linker->AddPandaFile(std::move(pf));
1765
1766 PandaString descriptor;
1767
1768 Class *klass =
1769 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
1770 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
1771 ASSERT_NE(klass, nullptr);
1772
1773 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
1774 ASSERT_NE(method, nullptr);
1775
1776 std::vector<Value> args;
1777 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
1778
1779 int64_t expected_result = 0;
1780 int64_t unexpected_exception = 2;
1781 int64_t no_exceptions = -1;
1782
1783 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
1784 << "AbstractMethod exception should have been thrown, but another has";
1785 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
1786 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
1787 }
1788
1789 /**
1790 * This test is a core test that's supposed
1791 * to provoke the AbstractMethodException, to catch it,
1792 * and to return 0 as the result.
1793 */
TEST_F(PandaExceptionTest,AbstractMethodInitObjectShortINT)1794 TEST_F(PandaExceptionTest, AbstractMethodInitObjectShortINT)
1795 {
1796 CreateRuntime(ExType::INT);
1797
1798 auto source = R"(
1799 .record panda.AbstractMethodError <external>
1800
1801 .record panda.Exception <external>
1802
1803 .record R {}
1804
1805 .function void R.ctor(R a0) <noimpl>
1806
1807 .record ProvokeAbstractMethodException {
1808 }
1809
1810 .function i32 ProvokeAbstractMethodException.main() <static> {
1811 try_begin:
1812 initobj.short R.ctor
1813 sta.obj v0
1814 try_end:
1815 jmp no_exceptions
1816 handler_begin_incorrect:
1817 movi v0, 0x2
1818 lda v0
1819 return
1820 handler_begin_correct:
1821 movi v0, 0x0
1822 lda v0
1823 return
1824 no_exceptions:
1825 movi v0, 0xffffffffffffffff
1826 lda v0
1827 return
1828
1829 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
1830 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
1831 }
1832 )";
1833
1834 pandasm::Parser parser;
1835 auto res = parser.Parse(source);
1836 ASSERT_TRUE(res);
1837 auto pf = pandasm::AsmEmitter::Emit(res.Value());
1838 ASSERT_NE(pf, nullptr);
1839
1840 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
1841
1842 class_linker->AddPandaFile(std::move(pf));
1843
1844 PandaString descriptor;
1845
1846 Class *klass =
1847 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
1848 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
1849 ASSERT_NE(klass, nullptr);
1850
1851 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
1852 ASSERT_NE(method, nullptr);
1853
1854 std::vector<Value> args;
1855 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
1856
1857 int64_t expected_result = 0;
1858 int64_t unexpected_exception = 2;
1859 int64_t no_exceptions = -1;
1860
1861 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
1862 << "AbstractMethod exception should have been thrown, but another has";
1863 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
1864 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
1865 }
1866
1867 /**
1868 * This test is a core test that's supposed
1869 * to provoke the AbstractMethodException, to catch it,
1870 * and to return 0 as the result.
1871 */
TEST_F(PandaExceptionTest,AbstractMethodInitObjectShortJIT)1872 TEST_F(PandaExceptionTest, AbstractMethodInitObjectShortJIT)
1873 {
1874 CreateRuntime(ExType::JIT);
1875
1876 auto source = R"(
1877 .record panda.AbstractMethodError <external>
1878
1879 .record panda.Exception <external>
1880
1881 .record R {}
1882
1883 .function void R.ctor(R a0) <noimpl>
1884
1885 .record ProvokeAbstractMethodException {
1886 }
1887
1888 .function i32 ProvokeAbstractMethodException.main() <static> {
1889 try_begin:
1890 initobj.short R.ctor
1891 sta.obj v0
1892 try_end:
1893 jmp no_exceptions
1894 handler_begin_incorrect:
1895 movi v0, 0x2
1896 lda v0
1897 return
1898 handler_begin_correct:
1899 movi v0, 0x0
1900 lda v0
1901 return
1902 no_exceptions:
1903 movi v0, 0xffffffffffffffff
1904 lda v0
1905 return
1906
1907 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
1908 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
1909 }
1910 )";
1911
1912 pandasm::Parser parser;
1913 auto res = parser.Parse(source);
1914 ASSERT_TRUE(res);
1915 auto pf = pandasm::AsmEmitter::Emit(res.Value());
1916 ASSERT_NE(pf, nullptr);
1917
1918 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
1919
1920 class_linker->AddPandaFile(std::move(pf));
1921
1922 PandaString descriptor;
1923
1924 Class *klass =
1925 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
1926 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
1927 ASSERT_NE(klass, nullptr);
1928
1929 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
1930 ASSERT_NE(method, nullptr);
1931
1932 std::vector<Value> args;
1933 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
1934
1935 int64_t expected_result = 0;
1936 int64_t unexpected_exception = 2;
1937 int64_t no_exceptions = -1;
1938
1939 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
1940 << "AbstractMethod exception should have been thrown, but another has";
1941 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
1942 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
1943 }
1944
1945 /**
1946 * This test is a core test that's supposed
1947 * to provoke the AbstractMethodException, to catch it,
1948 * and to return 0 as the result.
1949 */
TEST_F(PandaExceptionTest,AbstractMethodInitObjectINT)1950 TEST_F(PandaExceptionTest, AbstractMethodInitObjectINT)
1951 {
1952 CreateRuntime(ExType::INT);
1953
1954 auto source = R"(
1955 .record panda.AbstractMethodError <external>
1956
1957 .record panda.Exception <external>
1958
1959 .record R {}
1960
1961 .function void R.ctor(R a0, i32 a1, i32 a2, i32 a3, i32 a4) <noimpl>
1962
1963 .record ProvokeAbstractMethodException {
1964 }
1965
1966 .function i32 ProvokeAbstractMethodException.main() <static> {
1967 try_begin:
1968 movi v0, 0
1969 movi v1, 1
1970 movi v2, 2
1971 movi v3, 3
1972 initobj R.ctor, v0, v1, v2, v3
1973 sta.obj v0
1974 try_end:
1975 jmp no_exceptions
1976 handler_begin_incorrect:
1977 movi v0, 0x2
1978 lda v0
1979 return
1980 handler_begin_correct:
1981 movi v0, 0x0
1982 lda v0
1983 return
1984 no_exceptions:
1985 movi v0, 0xffffffffffffffff
1986 lda v0
1987 return
1988
1989 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
1990 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
1991 }
1992 )";
1993
1994 pandasm::Parser parser;
1995 auto res = parser.Parse(source);
1996 ASSERT_TRUE(res);
1997 auto pf = pandasm::AsmEmitter::Emit(res.Value());
1998 ASSERT_NE(pf, nullptr);
1999
2000 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
2001
2002 class_linker->AddPandaFile(std::move(pf));
2003
2004 PandaString descriptor;
2005
2006 Class *klass =
2007 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
2008 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
2009 ASSERT_NE(klass, nullptr);
2010
2011 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
2012 ASSERT_NE(method, nullptr);
2013
2014 std::vector<Value> args;
2015 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
2016
2017 int64_t expected_result = 0;
2018 int64_t unexpected_exception = 2;
2019 int64_t no_exceptions = -1;
2020
2021 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
2022 << "AbstractMethod exception should have been thrown, but another has";
2023 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
2024 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
2025 }
2026
2027 /**
2028 * This test is a core test that's supposed
2029 * to provoke the AbstractMethodException, to catch it,
2030 * and to return 0 as the result.
2031 */
TEST_F(PandaExceptionTest,AbstractMethodInitObjectJIT)2032 TEST_F(PandaExceptionTest, AbstractMethodInitObjectJIT)
2033 {
2034 CreateRuntime(ExType::JIT);
2035
2036 auto source = R"(
2037 .record panda.AbstractMethodError <external>
2038
2039 .record panda.Exception <external>
2040
2041 .record R {}
2042
2043 .function void R.ctor(R a0, i32 a1, i32 a2, i32 a3, i32 a4) <noimpl>
2044
2045 .record ProvokeAbstractMethodException {
2046 }
2047
2048 .function i32 ProvokeAbstractMethodException.main() <static> {
2049 try_begin:
2050 movi v0, 0
2051 movi v1, 1
2052 movi v2, 2
2053 movi v3, 3
2054 initobj R.ctor, v0, v1, v2, v3
2055 sta.obj v0
2056 try_end:
2057 jmp no_exceptions
2058 handler_begin_incorrect:
2059 movi v0, 0x2
2060 lda v0
2061 return
2062 handler_begin_correct:
2063 movi v0, 0x0
2064 lda v0
2065 return
2066 no_exceptions:
2067 movi v0, 0xffffffffffffffff
2068 lda v0
2069 return
2070
2071 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
2072 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
2073 }
2074 )";
2075
2076 pandasm::Parser parser;
2077 auto res = parser.Parse(source);
2078 ASSERT_TRUE(res);
2079 auto pf = pandasm::AsmEmitter::Emit(res.Value());
2080 ASSERT_NE(pf, nullptr);
2081
2082 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
2083
2084 class_linker->AddPandaFile(std::move(pf));
2085
2086 PandaString descriptor;
2087
2088 Class *klass =
2089 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
2090 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
2091 ASSERT_NE(klass, nullptr);
2092
2093 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
2094 ASSERT_NE(method, nullptr);
2095
2096 std::vector<Value> args;
2097 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
2098
2099 int64_t expected_result = 0;
2100 int64_t unexpected_exception = 2;
2101 int64_t no_exceptions = -1;
2102
2103 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
2104 << "AbstractMethod exception should have been thrown, but another has";
2105 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
2106 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
2107 }
2108
2109 /**
2110 * This test is a core test that's supposed
2111 * to provoke the AbstractMethodException, to catch it,
2112 * and to return 0 as the result.
2113 */
TEST_F(PandaExceptionTest,AbstractMethodInitObjectRangeINT)2114 TEST_F(PandaExceptionTest, AbstractMethodInitObjectRangeINT)
2115 {
2116 CreateRuntime(ExType::INT);
2117
2118 auto source = R"(
2119 .record panda.AbstractMethodError <external>
2120
2121 .record panda.Exception <external>
2122
2123 .record R {}
2124
2125 .function void R.ctor(R a0, i32 a1, i32 a2, i32 a3, i32 a4, i32 a5) <noimpl>
2126
2127 .record ProvokeAbstractMethodException {
2128 }
2129
2130 .function i32 ProvokeAbstractMethodException.main() <static> {
2131 try_begin:
2132 movi v0, 0
2133 movi v1, 1
2134 movi v2, 2
2135 movi v3, 3
2136 movi v4, 4
2137 initobj.range R.ctor, v0
2138 sta.obj v0
2139 try_end:
2140 jmp no_exceptions
2141 handler_begin_incorrect:
2142 movi v0, 0x2
2143 lda v0
2144 return
2145 handler_begin_correct:
2146 movi v0, 0x0
2147 lda v0
2148 return
2149 no_exceptions:
2150 movi v0, 0xffffffffffffffff
2151 lda v0
2152 return
2153
2154 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
2155 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
2156 }
2157 )";
2158
2159 pandasm::Parser parser;
2160 auto res = parser.Parse(source);
2161 ASSERT_TRUE(res);
2162 auto pf = pandasm::AsmEmitter::Emit(res.Value());
2163 ASSERT_NE(pf, nullptr);
2164
2165 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
2166
2167 class_linker->AddPandaFile(std::move(pf));
2168
2169 PandaString descriptor;
2170
2171 Class *klass =
2172 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
2173 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
2174 ASSERT_NE(klass, nullptr);
2175
2176 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
2177 ASSERT_NE(method, nullptr);
2178
2179 std::vector<Value> args;
2180 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
2181
2182 int64_t expected_result = 0;
2183 int64_t unexpected_exception = 2;
2184 int64_t no_exceptions = -1;
2185
2186 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
2187 << "AbstractMethod exception should have been thrown, but another has";
2188 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
2189 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
2190 }
2191
2192 /**
2193 * This test is a core test that's supposed
2194 * to provoke the AbstractMethodException, to catch it,
2195 * and to return 0 as the result.
2196 */
TEST_F(PandaExceptionTest,AbstractMethodInitObjectRangeJIT)2197 TEST_F(PandaExceptionTest, AbstractMethodInitObjectRangeJIT)
2198 {
2199 CreateRuntime(ExType::JIT);
2200
2201 auto source = R"(
2202 .record panda.AbstractMethodError <external>
2203
2204 .record panda.Exception <external>
2205
2206 .record R {}
2207
2208 .function void R.ctor(R a0, i32 a1, i32 a2, i32 a3, i32 a4, i32 a5) <noimpl>
2209
2210 .record ProvokeAbstractMethodException {
2211 }
2212
2213 .function i32 ProvokeAbstractMethodException.main() <static> {
2214 try_begin:
2215 movi v0, 0
2216 movi v1, 1
2217 movi v2, 2
2218 movi v3, 3
2219 movi v4, 4
2220 initobj.range R.ctor, v0
2221 sta.obj v0
2222 try_end:
2223 jmp no_exceptions
2224 handler_begin_incorrect:
2225 movi v0, 0x2
2226 lda v0
2227 return
2228 handler_begin_correct:
2229 movi v0, 0x0
2230 lda v0
2231 return
2232 no_exceptions:
2233 movi v0, 0xffffffffffffffff
2234 lda v0
2235 return
2236
2237 .catch panda.AbstractMethodError, try_begin, try_end, handler_begin_correct
2238 .catch panda.Exception, try_begin, try_end, handler_begin_incorrect
2239 }
2240 )";
2241
2242 pandasm::Parser parser;
2243 auto res = parser.Parse(source);
2244 ASSERT_TRUE(res);
2245 auto pf = pandasm::AsmEmitter::Emit(res.Value());
2246 ASSERT_NE(pf, nullptr);
2247
2248 ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
2249
2250 class_linker->AddPandaFile(std::move(pf));
2251
2252 PandaString descriptor;
2253
2254 Class *klass =
2255 class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY)
2256 ->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("ProvokeAbstractMethodException"), &descriptor));
2257 ASSERT_NE(klass, nullptr);
2258
2259 Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("main"));
2260 ASSERT_NE(method, nullptr);
2261
2262 std::vector<Value> args;
2263 Value result = method->Invoke(ManagedThread::GetCurrent(), args.data());
2264
2265 int64_t expected_result = 0;
2266 int64_t unexpected_exception = 2;
2267 int64_t no_exceptions = -1;
2268
2269 ASSERT_NE(result.GetAs<int64_t>(), unexpected_exception)
2270 << "AbstractMethod exception should have been thrown, but another has";
2271 ASSERT_NE(result.GetAs<int64_t>(), no_exceptions) << "No exceptions were thrown";
2272 ASSERT_EQ(result.GetAs<int64_t>(), expected_result) << "Unexpected error";
2273 }
2274
2275 } // namespace panda::test