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