1 | // Copyright (c) 2019, 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 <stdio.h> |
6 | #include <stdlib.h> |
7 | #include <string.h> |
8 | #include "./include/dart_api.h" |
9 | #include "./include/dart_native_api.h" |
10 | |
11 | #define CHECK(H) \ |
12 | do { \ |
13 | Dart_Handle __handle__ = H; \ |
14 | if (Dart_IsError(__handle__)) { \ |
15 | const char* message = Dart_GetError(__handle__); \ |
16 | fprintf(stderr, "Check \"" #H "\" failed: %s", message); \ |
17 | abort(); \ |
18 | } \ |
19 | } while (false) |
20 | |
21 | #define ASSERT(E) \ |
22 | if (!(E)) { \ |
23 | fprintf(stderr, "Assertion \"" #E "\" failed at %s:%d!\n", __FILE__, \ |
24 | __LINE__); \ |
25 | abort(); \ |
26 | } |
27 | |
28 | bool isDartPrecompiledRuntime = true; |
29 | |
30 | // Some invalid accesses are allowed in AOT since we don't retain @pragma |
31 | // annotations. Therefore we skip the negative tests in AOT. |
32 | #define FAIL(name, result) \ |
33 | if (!isDartPrecompiledRuntime) { \ |
34 | Fail(name, result); \ |
35 | } |
36 | |
37 | void Fail(const char* name, Dart_Handle result) { |
38 | ASSERT(Dart_IsApiError(result)); |
39 | const char* error = Dart_GetError(result); |
40 | ASSERT(strstr(error, name)); |
41 | ASSERT(strstr(error, "It is illegal to access" )); |
42 | } |
43 | |
44 | #define FAIL_INVOKE_FIELD(name, result) \ |
45 | if (!isDartPrecompiledRuntime) { \ |
46 | FailInvokeField(name, result); \ |
47 | } |
48 | |
49 | void FailInvokeField(const char* name, Dart_Handle result) { |
50 | ASSERT(Dart_IsApiError(result)); |
51 | const char* error = Dart_GetError(result); |
52 | ASSERT(strstr(error, name)); |
53 | ASSERT(strstr(error, "Entry-points do not allow invoking fields" )); |
54 | } |
55 | |
56 | void FailClosurizeConstructor(const char* name, Dart_Handle result) { |
57 | ASSERT(Dart_IsUnhandledExceptionError(result)); |
58 | const char* error = Dart_GetError(result); |
59 | ASSERT(strstr(error, name)); |
60 | ASSERT(strstr(error, "No static getter" )); |
61 | } |
62 | |
63 | void TestFields(Dart_Handle target) { |
64 | FAIL("fld0" , Dart_GetField(target, Dart_NewStringFromCString("fld0" ))); |
65 | FAIL("fld0" , |
66 | Dart_SetField(target, Dart_NewStringFromCString("fld0" ), Dart_Null())); |
67 | |
68 | FAIL_INVOKE_FIELD( |
69 | "fld0" , |
70 | Dart_Invoke(target, Dart_NewStringFromCString("fld0" ), 0, nullptr)); |
71 | |
72 | CHECK(Dart_GetField(target, Dart_NewStringFromCString("fld1" ))); |
73 | CHECK(Dart_SetField(target, Dart_NewStringFromCString("fld1" ), Dart_Null())); |
74 | FAIL_INVOKE_FIELD( |
75 | "fld1" , |
76 | Dart_Invoke(target, Dart_NewStringFromCString("fld1" ), 0, nullptr)); |
77 | |
78 | CHECK(Dart_GetField(target, Dart_NewStringFromCString("fld2" ))); |
79 | FAIL("fld2" , |
80 | Dart_SetField(target, Dart_NewStringFromCString("fld2" ), Dart_Null())); |
81 | FAIL_INVOKE_FIELD( |
82 | "fld2" , |
83 | Dart_Invoke(target, Dart_NewStringFromCString("fld2" ), 0, nullptr)); |
84 | |
85 | FAIL("fld3" , Dart_GetField(target, Dart_NewStringFromCString("fld3" ))); |
86 | CHECK(Dart_SetField(target, Dart_NewStringFromCString("fld3" ), Dart_Null())); |
87 | FAIL_INVOKE_FIELD( |
88 | "fld3" , |
89 | Dart_Invoke(target, Dart_NewStringFromCString("fld3" ), 0, nullptr)); |
90 | } |
91 | |
92 | void RunTests(Dart_NativeArguments arguments) { |
93 | Dart_Handle lib = Dart_RootLibrary(); |
94 | |
95 | //////// Test allocation and constructor invocation. |
96 | |
97 | FAIL("C" , Dart_GetClass(lib, Dart_NewStringFromCString("C" ))); |
98 | |
99 | Dart_Handle D_class = Dart_GetClass(lib, Dart_NewStringFromCString("D" )); |
100 | CHECK(D_class); |
101 | |
102 | CHECK(Dart_Allocate(D_class)); |
103 | |
104 | FAIL("D." , Dart_New(D_class, Dart_Null(), 0, nullptr)); |
105 | |
106 | CHECK(Dart_New(D_class, Dart_NewStringFromCString("defined" ), 0, nullptr)); |
107 | Dart_Handle D = |
108 | Dart_New(D_class, Dart_NewStringFromCString("fact" ), 0, nullptr); |
109 | CHECK(D); |
110 | |
111 | //////// Test actions against methods |
112 | |
113 | FailClosurizeConstructor( |
114 | "defined" , Dart_GetField(D_class, Dart_NewStringFromCString("defined" ))); |
115 | FailClosurizeConstructor( |
116 | "fact" , Dart_GetField(D_class, Dart_NewStringFromCString("fact" ))); |
117 | |
118 | FAIL("fn0" , Dart_Invoke(D, Dart_NewStringFromCString("fn0" ), 0, nullptr)); |
119 | |
120 | CHECK(Dart_Invoke(D, Dart_NewStringFromCString("fn1" ), 0, nullptr)); |
121 | FAIL("fn1" , Dart_Invoke(D, Dart_NewStringFromCString("fn1_get" ), 0, nullptr)); |
122 | CHECK(Dart_Invoke(D, Dart_NewStringFromCString("fn1_call" ), 0, nullptr)); |
123 | |
124 | FAIL("fn0" , Dart_GetField(D, Dart_NewStringFromCString("fn0" ))); |
125 | |
126 | CHECK(Dart_GetField(D, Dart_NewStringFromCString("fn1" ))); |
127 | CHECK(Dart_GetField(D, Dart_NewStringFromCString("fn1_get" ))); |
128 | FAIL("fn1" , Dart_GetField(D, Dart_NewStringFromCString("fn1_call" ))); |
129 | |
130 | FAIL("fn2" , |
131 | Dart_Invoke(D_class, Dart_NewStringFromCString("fn2" ), 0, nullptr)); |
132 | |
133 | CHECK(Dart_Invoke(D_class, Dart_NewStringFromCString("fn3" ), 0, nullptr)); |
134 | CHECK( |
135 | Dart_Invoke(D_class, Dart_NewStringFromCString("fn3_call" ), 0, nullptr)); |
136 | FAIL("fn3" , |
137 | Dart_Invoke(D_class, Dart_NewStringFromCString("fn3_get" ), 0, nullptr)); |
138 | |
139 | FAIL("fn2" , Dart_GetField(D_class, Dart_NewStringFromCString("fn2" ))); |
140 | |
141 | CHECK(Dart_GetField(D_class, Dart_NewStringFromCString("fn3" ))); |
142 | FAIL("fn3_call" , |
143 | Dart_GetField(D_class, Dart_NewStringFromCString("fn3_call" ))); |
144 | CHECK(Dart_GetField(D_class, Dart_NewStringFromCString("fn3_get" ))); |
145 | |
146 | FAIL("fn0" , Dart_Invoke(lib, Dart_NewStringFromCString("fn0" ), 0, nullptr)); |
147 | |
148 | CHECK(Dart_Invoke(lib, Dart_NewStringFromCString("fn1" ), 0, nullptr)); |
149 | FAIL("fn1" , |
150 | Dart_Invoke(lib, Dart_NewStringFromCString("fn1_get" ), 0, nullptr)); |
151 | CHECK(Dart_Invoke(lib, Dart_NewStringFromCString("fn1_call" ), 0, nullptr)); |
152 | |
153 | FAIL("fn0" , Dart_GetField(lib, Dart_NewStringFromCString("fn0" ))); |
154 | |
155 | CHECK(Dart_GetField(lib, Dart_NewStringFromCString("fn1" ))); |
156 | CHECK(Dart_GetField(lib, Dart_NewStringFromCString("fn1_get" ))); |
157 | FAIL("fn1" , Dart_GetField(lib, Dart_NewStringFromCString("fn1_call" ))); |
158 | |
159 | //////// Test actions against fields |
160 | |
161 | TestFields(D); |
162 | |
163 | Dart_Handle F_class = Dart_GetClass(lib, Dart_NewStringFromCString("F" )); |
164 | TestFields(F_class); |
165 | |
166 | TestFields(lib); |
167 | } |
168 | |
169 | Dart_NativeFunction ResolveName(Dart_Handle name, |
170 | int argc, |
171 | bool* auto_setup_scope) { |
172 | if (auto_setup_scope == NULL) { |
173 | return NULL; |
174 | } |
175 | *auto_setup_scope = true; |
176 | return RunTests; |
177 | } |
178 | |
179 | DART_EXPORT Dart_Handle |
180 | entrypoints_verification_test_extension_Init(Dart_Handle parent_library) { |
181 | isDartPrecompiledRuntime = Dart_IsPrecompiledRuntime(); |
182 | |
183 | if (Dart_IsError(parent_library)) { |
184 | return parent_library; |
185 | } |
186 | |
187 | Dart_Handle result_code = |
188 | Dart_SetNativeResolver(parent_library, ResolveName, NULL); |
189 | if (Dart_IsError(result_code)) { |
190 | return result_code; |
191 | } |
192 | |
193 | return Dart_Null(); |
194 | } |
195 | |