1// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "include/dart_api.h"
6#include "platform/assert.h"
7#include "vm/dart_api_impl.h"
8#include "vm/unit_test.h"
9
10namespace dart {
11
12#define FUNCTION_NAME(name) UnhandledExcp_##name
13#define REGISTER_FUNCTION(name, count) {"" #name, FUNCTION_NAME(name), count},
14
15void FUNCTION_NAME(Unhandled_equals)(Dart_NativeArguments args) {
16 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
17 TransitionNativeToVM transition(arguments->thread());
18 Zone* zone = arguments->thread()->zone();
19 const Instance& expected =
20 Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
21 const Instance& actual =
22 Instance::CheckedHandle(zone, arguments->NativeArgAt(1));
23 if (!expected.CanonicalizeEquals(actual)) {
24 OS::PrintErr("expected: '%s' actual: '%s'\n", expected.ToCString(),
25 actual.ToCString());
26 FATAL("Unhandled_equals fails.\n");
27 }
28}
29
30void FUNCTION_NAME(Unhandled_invoke)(Dart_NativeArguments args) {
31 // Invoke the specified entry point.
32 Dart_Handle cls = Dart_GetClass(TestCase::lib(), NewString("Second"));
33 Dart_Handle result = Dart_Invoke(cls, NewString("method2"), 0, NULL);
34 ASSERT(Dart_IsError(result));
35 ASSERT(Dart_ErrorHasException(result));
36 return;
37}
38
39void FUNCTION_NAME(Unhandled_invoke2)(Dart_NativeArguments args) {
40 // Invoke the specified entry point.
41 Dart_Handle cls = Dart_GetClass(TestCase::lib(), NewString("Second"));
42 Dart_Handle result = Dart_Invoke(cls, NewString("method2"), 0, NULL);
43 ASSERT(Dart_IsError(result));
44 ASSERT(Dart_ErrorHasException(result));
45 Dart_Handle exception = Dart_ErrorGetException(result);
46 ASSERT(!Dart_IsError(exception));
47 Dart_ThrowException(exception);
48 UNREACHABLE();
49 return;
50}
51
52// List all native functions implemented in the vm or core boot strap dart
53// libraries so that we can resolve the native function to it's entry
54// point.
55#define UNHANDLED_NATIVE_LIST(V) \
56 V(Unhandled_equals, 2) \
57 V(Unhandled_invoke, 0) \
58 V(Unhandled_invoke2, 0)
59
60static struct NativeEntries {
61 const char* name_;
62 Dart_NativeFunction function_;
63 int argument_count_;
64} BuiltinEntries[] = {UNHANDLED_NATIVE_LIST(REGISTER_FUNCTION)};
65
66static Dart_NativeFunction native_lookup(Dart_Handle name,
67 int argument_count,
68 bool* auto_setup_scope) {
69 ASSERT(auto_setup_scope != NULL);
70 *auto_setup_scope = true;
71 TransitionNativeToVM transition(Thread::Current());
72 const Object& obj = Object::Handle(Api::UnwrapHandle(name));
73 ASSERT(obj.IsString());
74 const char* function_name = obj.ToCString();
75 ASSERT(function_name != NULL);
76 int num_entries = sizeof(BuiltinEntries) / sizeof(struct NativeEntries);
77 for (int i = 0; i < num_entries; i++) {
78 struct NativeEntries* entry = &(BuiltinEntries[i]);
79 if ((strcmp(function_name, entry->name_) == 0) &&
80 (argument_count == entry->argument_count_)) {
81 return reinterpret_cast<Dart_NativeFunction>(entry->function_);
82 }
83 }
84 return NULL;
85}
86
87// Unit test case to verify unhandled exceptions.
88TEST_CASE(UnhandledExceptions) {
89 const char* kScriptChars =
90 "class UnhandledExceptions {\n"
91 " static equals(var obj1, var obj2) native \"Unhandled_equals\";"
92 " static invoke() native \"Unhandled_invoke\";\n"
93 " static invoke2() native \"Unhandled_invoke2\";\n"
94 "}\n"
95 "class Second {\n"
96 " Second() { }\n"
97 " static int method1(int param) {\n"
98 " UnhandledExceptions.invoke();\n"
99 " return 2;\n"
100 " }\n"
101 " static int method2() {\n"
102 " throw new Second();\n"
103 " }\n"
104 " static int method3(int param) {\n"
105 " try {\n"
106 " UnhandledExceptions.invoke2();\n"
107 " } on Second catch (e) {\n"
108 " return 3;\n"
109 " }\n"
110 " return 2;\n"
111 " }\n"
112 "}\n"
113 "testMain() {\n"
114 " UnhandledExceptions.equals(2, Second.method1(1));\n"
115 " UnhandledExceptions.equals(3, Second.method3(1));\n"
116 "}";
117 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, native_lookup);
118 EXPECT_VALID(Dart_Invoke(lib, NewString("testMain"), 0, NULL));
119}
120
121} // namespace dart
122