| // Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 |  | 
 | #include <stdio.h> | 
 | #include <stdlib.h> | 
 | #include <string.h> | 
 |  | 
 | // TODO(dartbug.com/40579): This requires static linking to either link | 
 | // dart.exe or dart_precompiled_runtime.exe on Windows. | 
 | // The sample currently fails on Windows in AOT mode. | 
 | #include "include/dart_api.h" | 
 | #include "include/dart_native_api.h" | 
 |  | 
 | #define CHECK(H)                                                               \ | 
 |   do {                                                                         \ | 
 |     Dart_Handle __handle__ = H;                                                \ | 
 |     if (Dart_IsError(__handle__)) {                                            \ | 
 |       const char* message = Dart_GetError(__handle__);                         \ | 
 |       fprintf(stderr, "Check \"" #H "\" failed: %s", message);                 \ | 
 |       abort();                                                                 \ | 
 |     }                                                                          \ | 
 |   } while (false) | 
 |  | 
 | #define ASSERT(E)                                                              \ | 
 |   if (!(E)) {                                                                  \ | 
 |     fprintf(stderr, "Assertion \"" #E "\" failed at %s:%d!\n", __FILE__,       \ | 
 |             __LINE__);                                                         \ | 
 |     abort();                                                                   \ | 
 |   } | 
 |  | 
 | static bool is_dart_precompiled_runtime = true; | 
 |  | 
 | // Some invalid accesses are allowed in AOT since we don't retain @pragma | 
 | // annotations. Therefore we skip the negative tests in AOT. | 
 | #define FAIL(name, result)                                                     \ | 
 |   if (!is_dart_precompiled_runtime) {                                          \ | 
 |     Fail(name, result);                                                        \ | 
 |   } | 
 |  | 
 | void Fail(const char* name, Dart_Handle result) { | 
 |   ASSERT(Dart_IsApiError(result)); | 
 |   const char* error = Dart_GetError(result); | 
 |   ASSERT(strstr(error, name)); | 
 |   ASSERT(strstr(error, "It is illegal to access")); | 
 | } | 
 |  | 
 | #define FAIL_INVOKE_FIELD(name, result)                                        \ | 
 |   if (!is_dart_precompiled_runtime) {                                          \ | 
 |     FailInvokeField(name, result);                                             \ | 
 |   } | 
 |  | 
 | static void FailInvokeField(const char* name, Dart_Handle result) { | 
 |   ASSERT(Dart_IsApiError(result)); | 
 |   const char* error = Dart_GetError(result); | 
 |   ASSERT(strstr(error, name)); | 
 |   ASSERT(strstr(error, "Entry-points do not allow invoking fields")); | 
 | } | 
 |  | 
 | static void FailClosurizeConstructor(const char* name, Dart_Handle result) { | 
 |   ASSERT(Dart_IsUnhandledExceptionError(result)); | 
 |   const char* error = Dart_GetError(result); | 
 |   ASSERT(strstr(error, name)); | 
 |   ASSERT(strstr(error, "No static getter")); | 
 | } | 
 |  | 
 | static void TestFields(Dart_Handle target) { | 
 |   FAIL("fld0", Dart_GetField(target, Dart_NewStringFromCString("fld0"))); | 
 |   FAIL("fld0", | 
 |        Dart_SetField(target, Dart_NewStringFromCString("fld0"), Dart_Null())); | 
 |  | 
 |   FAIL_INVOKE_FIELD( | 
 |       "fld0", | 
 |       Dart_Invoke(target, Dart_NewStringFromCString("fld0"), 0, nullptr)); | 
 |  | 
 |   CHECK(Dart_GetField(target, Dart_NewStringFromCString("fld1"))); | 
 |   CHECK(Dart_SetField(target, Dart_NewStringFromCString("fld1"), Dart_Null())); | 
 |   FAIL_INVOKE_FIELD( | 
 |       "fld1", | 
 |       Dart_Invoke(target, Dart_NewStringFromCString("fld1"), 0, nullptr)); | 
 |  | 
 |   CHECK(Dart_GetField(target, Dart_NewStringFromCString("fld2"))); | 
 |   FAIL("fld2", | 
 |        Dart_SetField(target, Dart_NewStringFromCString("fld2"), Dart_Null())); | 
 |   FAIL_INVOKE_FIELD( | 
 |       "fld2", | 
 |       Dart_Invoke(target, Dart_NewStringFromCString("fld2"), 0, nullptr)); | 
 |  | 
 |   FAIL("fld3", Dart_GetField(target, Dart_NewStringFromCString("fld3"))); | 
 |   CHECK(Dart_SetField(target, Dart_NewStringFromCString("fld3"), Dart_Null())); | 
 |   FAIL_INVOKE_FIELD( | 
 |       "fld3", | 
 |       Dart_Invoke(target, Dart_NewStringFromCString("fld3"), 0, nullptr)); | 
 | } | 
 |  | 
 | DART_EXPORT void RunTests() { | 
 |   is_dart_precompiled_runtime = Dart_IsPrecompiledRuntime(); | 
 |  | 
 |   Dart_Handle lib = Dart_RootLibrary(); | 
 |  | 
 |   //////// Test allocation and constructor invocation. | 
 |  | 
 |   FAIL("C", Dart_GetClass(lib, Dart_NewStringFromCString("C"))); | 
 |  | 
 |   Dart_Handle D_class = Dart_GetClass(lib, Dart_NewStringFromCString("D")); | 
 |   CHECK(D_class); | 
 |  | 
 |   CHECK(Dart_Allocate(D_class)); | 
 |  | 
 |   FAIL("D.", Dart_New(D_class, Dart_Null(), 0, nullptr)); | 
 |  | 
 |   CHECK(Dart_New(D_class, Dart_NewStringFromCString("defined"), 0, nullptr)); | 
 |   Dart_Handle D = | 
 |       Dart_New(D_class, Dart_NewStringFromCString("fact"), 0, nullptr); | 
 |   CHECK(D); | 
 |  | 
 |   //////// Test actions against methods | 
 |  | 
 |   FailClosurizeConstructor( | 
 |       "defined", Dart_GetField(D_class, Dart_NewStringFromCString("defined"))); | 
 |   FailClosurizeConstructor( | 
 |       "fact", Dart_GetField(D_class, Dart_NewStringFromCString("fact"))); | 
 |  | 
 |   FAIL("fn0", Dart_Invoke(D, Dart_NewStringFromCString("fn0"), 0, nullptr)); | 
 |  | 
 |   CHECK(Dart_Invoke(D, Dart_NewStringFromCString("fn1"), 0, nullptr)); | 
 |   FAIL("fn1", Dart_Invoke(D, Dart_NewStringFromCString("fn1_get"), 0, nullptr)); | 
 |   CHECK(Dart_Invoke(D, Dart_NewStringFromCString("fn1_call"), 0, nullptr)); | 
 |  | 
 |   FAIL("fn0", Dart_GetField(D, Dart_NewStringFromCString("fn0"))); | 
 |  | 
 |   CHECK(Dart_GetField(D, Dart_NewStringFromCString("fn1"))); | 
 |   CHECK(Dart_GetField(D, Dart_NewStringFromCString("fn1_get"))); | 
 |   FAIL("fn1", Dart_GetField(D, Dart_NewStringFromCString("fn1_call"))); | 
 |  | 
 |   FAIL("fn2", | 
 |        Dart_Invoke(D_class, Dart_NewStringFromCString("fn2"), 0, nullptr)); | 
 |  | 
 |   CHECK(Dart_Invoke(D_class, Dart_NewStringFromCString("fn3"), 0, nullptr)); | 
 |   CHECK( | 
 |       Dart_Invoke(D_class, Dart_NewStringFromCString("fn3_call"), 0, nullptr)); | 
 |   FAIL("fn3", | 
 |        Dart_Invoke(D_class, Dart_NewStringFromCString("fn3_get"), 0, nullptr)); | 
 |  | 
 |   FAIL("fn2", Dart_GetField(D_class, Dart_NewStringFromCString("fn2"))); | 
 |  | 
 |   CHECK(Dart_GetField(D_class, Dart_NewStringFromCString("fn3"))); | 
 |   FAIL("fn3_call", | 
 |        Dart_GetField(D_class, Dart_NewStringFromCString("fn3_call"))); | 
 |   CHECK(Dart_GetField(D_class, Dart_NewStringFromCString("fn3_get"))); | 
 |  | 
 |   FAIL("fn0", Dart_Invoke(lib, Dart_NewStringFromCString("fn0"), 0, nullptr)); | 
 |  | 
 |   CHECK(Dart_Invoke(lib, Dart_NewStringFromCString("fn1"), 0, nullptr)); | 
 |   FAIL("fn1", | 
 |        Dart_Invoke(lib, Dart_NewStringFromCString("fn1_get"), 0, nullptr)); | 
 |   CHECK(Dart_Invoke(lib, Dart_NewStringFromCString("fn1_call"), 0, nullptr)); | 
 |  | 
 |   FAIL("fn0", Dart_GetField(lib, Dart_NewStringFromCString("fn0"))); | 
 |  | 
 |   CHECK(Dart_GetField(lib, Dart_NewStringFromCString("fn1"))); | 
 |   CHECK(Dart_GetField(lib, Dart_NewStringFromCString("fn1_get"))); | 
 |   FAIL("fn1", Dart_GetField(lib, Dart_NewStringFromCString("fn1_call"))); | 
 |  | 
 |   //////// Test actions against fields | 
 |  | 
 |   TestFields(D); | 
 |  | 
 |   Dart_Handle F_class = Dart_GetClass(lib, Dart_NewStringFromCString("F")); | 
 |   TestFields(F_class); | 
 |  | 
 |   TestFields(lib); | 
 | } |