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