bb7ee3d0fb
Review URL: https://chromiumcodereview.appspot.com//9384027 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@4244 260f80e4-7a28-3924-810f-c04153c831b5
3737 lines
118 KiB
C++
3737 lines
118 KiB
C++
// Copyright (c) 2012, 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 "include/dart_api.h"
|
|
#include "platform/assert.h"
|
|
#include "platform/utils.h"
|
|
#include "vm/class_finalizer.h"
|
|
#include "vm/dart_api_impl.h"
|
|
#include "vm/dart_api_state.h"
|
|
#include "vm/thread.h"
|
|
#include "vm/unit_test.h"
|
|
#include "vm/verifier.h"
|
|
|
|
namespace dart {
|
|
|
|
// Only ia32 and x64 can run execution tests.
|
|
#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
|
|
|
|
TEST_CASE(ErrorHandles) {
|
|
const char* kScriptChars =
|
|
"class TestClass {\n"
|
|
" static void testMain() {\n"
|
|
" throw new Exception(\"bad news\");\n"
|
|
" }\n"
|
|
"}\n";
|
|
|
|
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
|
|
|
Dart_Handle instance = Dart_True();
|
|
Dart_Handle error = Api::NewError("myerror");
|
|
Dart_Handle exception = Dart_InvokeStatic(lib,
|
|
Dart_NewString("TestClass"),
|
|
Dart_NewString("testMain"),
|
|
0,
|
|
NULL);
|
|
|
|
EXPECT(!Dart_IsError(instance));
|
|
EXPECT(Dart_IsError(error));
|
|
EXPECT(Dart_IsError(exception));
|
|
|
|
EXPECT(!Dart_ErrorHasException(instance));
|
|
EXPECT(!Dart_ErrorHasException(error));
|
|
EXPECT(Dart_ErrorHasException(exception));
|
|
|
|
EXPECT_STREQ("", Dart_GetError(instance));
|
|
EXPECT_STREQ("myerror", Dart_GetError(error));
|
|
EXPECT_STREQ(
|
|
"Unhandled exception:\n"
|
|
"Exception: bad news\n"
|
|
" 0. Function: 'TestClass.testMain' url: 'dart:test-lib' line:3 col:5\n",
|
|
Dart_GetError(exception));
|
|
|
|
EXPECT(Dart_IsError(Dart_ErrorGetException(instance)));
|
|
EXPECT(Dart_IsError(Dart_ErrorGetException(error)));
|
|
EXPECT_VALID(Dart_ErrorGetException(exception));
|
|
|
|
EXPECT(Dart_IsError(Dart_ErrorGetStacktrace(instance)));
|
|
EXPECT(Dart_IsError(Dart_ErrorGetStacktrace(error)));
|
|
EXPECT_VALID(Dart_ErrorGetStacktrace(exception));
|
|
}
|
|
|
|
|
|
void PropagateErrorNative(Dart_NativeArguments args) {
|
|
Dart_EnterScope();
|
|
Dart_Handle closure = Dart_GetNativeArgument(args, 0);
|
|
EXPECT(Dart_IsClosure(closure));
|
|
Dart_Handle result = Dart_InvokeClosure(closure, 0, NULL);
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_PropagateError(result);
|
|
EXPECT_VALID(result); // We do not expect to reach here.
|
|
UNREACHABLE();
|
|
}
|
|
|
|
|
|
static Dart_NativeFunction PropagateError_native_lookup(
|
|
Dart_Handle name, int argument_count) {
|
|
return reinterpret_cast<Dart_NativeFunction>(&PropagateErrorNative);
|
|
}
|
|
|
|
|
|
TEST_CASE(Dart_PropagateError) {
|
|
const char* kScriptChars =
|
|
"class Test {\n"
|
|
" static void raiseCompileError() {\n"
|
|
" return badIdent;\n"
|
|
" }\n"
|
|
"\n"
|
|
" static void throwException() {\n"
|
|
" throw new Exception('myException');\n"
|
|
" }\n"
|
|
" static void nativeFunc(closure) native 'Test_nativeFunc';\n"
|
|
"\n"
|
|
" static void Func1() {\n"
|
|
" nativeFunc(() => raiseCompileError());\n"
|
|
" }\n"
|
|
"\n"
|
|
" static void Func2() {\n"
|
|
" nativeFunc(() => throwException());\n"
|
|
" }\n"
|
|
"}\n";
|
|
Dart_Handle lib = TestCase::LoadTestScript(
|
|
kScriptChars, &PropagateError_native_lookup);
|
|
Dart_Handle result;
|
|
|
|
result = Dart_InvokeStatic(lib,
|
|
Dart_NewString("Test"),
|
|
Dart_NewString("Func1"),
|
|
0,
|
|
NULL);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT(!Dart_ErrorHasException(result));
|
|
EXPECT_SUBSTRING("badIdent", Dart_GetError(result));
|
|
|
|
result = Dart_InvokeStatic(lib,
|
|
Dart_NewString("Test"),
|
|
Dart_NewString("Func2"),
|
|
0,
|
|
NULL);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT(Dart_ErrorHasException(result));
|
|
EXPECT_SUBSTRING("myException", Dart_GetError(result));
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
TEST_CASE(Dart_Error) {
|
|
Dart_Handle error = Dart_Error("An %s", "error");
|
|
EXPECT(Dart_IsError(error));
|
|
EXPECT_STREQ("An error", Dart_GetError(error));
|
|
}
|
|
|
|
|
|
TEST_CASE(Null) {
|
|
Dart_Handle null = Dart_Null();
|
|
EXPECT_VALID(null);
|
|
EXPECT(Dart_IsNull(null));
|
|
|
|
Dart_Handle str = Dart_NewString("test");
|
|
EXPECT_VALID(str);
|
|
EXPECT(!Dart_IsNull(str));
|
|
}
|
|
|
|
|
|
TEST_CASE(IsSame) {
|
|
bool same = false;
|
|
Dart_Handle five = Dart_NewString("5");
|
|
Dart_Handle five_again = Dart_NewString("5");
|
|
Dart_Handle seven = Dart_NewString("7");
|
|
|
|
// Same objects.
|
|
EXPECT_VALID(Dart_IsSame(five, five, &same));
|
|
EXPECT(same);
|
|
|
|
// Equal objects.
|
|
EXPECT_VALID(Dart_IsSame(five, five_again, &same));
|
|
EXPECT(!same);
|
|
|
|
// Different objects.
|
|
EXPECT_VALID(Dart_IsSame(five, seven, &same));
|
|
EXPECT(!same);
|
|
|
|
// Non-instance objects.
|
|
{
|
|
DARTSCOPE_NOCHECKS(Isolate::Current());
|
|
const Object& cls1 = Object::Handle(Object::null_class());
|
|
const Object& cls2 = Object::Handle(Object::class_class());
|
|
Dart_Handle class1 = Api::NewLocalHandle(cls1);
|
|
Dart_Handle class2 = Api::NewLocalHandle(cls2);
|
|
|
|
EXPECT_VALID(Dart_IsSame(class1, class1, &same));
|
|
EXPECT(same);
|
|
|
|
EXPECT_VALID(Dart_IsSame(class1, class2, &same));
|
|
EXPECT(!same);
|
|
}
|
|
}
|
|
|
|
|
|
// Only ia32 and x64 can run execution tests.
|
|
#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
|
|
|
|
TEST_CASE(ObjectEquals) {
|
|
bool equal = false;
|
|
Dart_Handle five = Dart_NewString("5");
|
|
Dart_Handle five_again = Dart_NewString("5");
|
|
Dart_Handle seven = Dart_NewString("7");
|
|
|
|
// Same objects.
|
|
EXPECT_VALID(Dart_ObjectEquals(five, five, &equal));
|
|
EXPECT(equal);
|
|
|
|
// Equal objects.
|
|
EXPECT_VALID(Dart_ObjectEquals(five, five_again, &equal));
|
|
EXPECT(equal);
|
|
|
|
// Different objects.
|
|
EXPECT_VALID(Dart_ObjectEquals(five, seven, &equal));
|
|
EXPECT(!equal);
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
TEST_CASE(BooleanValues) {
|
|
Dart_Handle str = Dart_NewString("test");
|
|
EXPECT(!Dart_IsBoolean(str));
|
|
|
|
bool value = false;
|
|
Dart_Handle result = Dart_BooleanValue(str, &value);
|
|
EXPECT(Dart_IsError(result));
|
|
|
|
Dart_Handle val1 = Dart_NewBoolean(true);
|
|
EXPECT(Dart_IsBoolean(val1));
|
|
|
|
result = Dart_BooleanValue(val1, &value);
|
|
EXPECT_VALID(result);
|
|
EXPECT(value);
|
|
|
|
Dart_Handle val2 = Dart_NewBoolean(false);
|
|
EXPECT(Dart_IsBoolean(val2));
|
|
|
|
result = Dart_BooleanValue(val2, &value);
|
|
EXPECT_VALID(result);
|
|
EXPECT(!value);
|
|
}
|
|
|
|
|
|
TEST_CASE(BooleanConstants) {
|
|
Dart_Handle true_handle = Dart_True();
|
|
EXPECT_VALID(true_handle);
|
|
EXPECT(Dart_IsBoolean(true_handle));
|
|
|
|
bool value = false;
|
|
Dart_Handle result = Dart_BooleanValue(true_handle, &value);
|
|
EXPECT_VALID(result);
|
|
EXPECT(value);
|
|
|
|
Dart_Handle false_handle = Dart_False();
|
|
EXPECT_VALID(false_handle);
|
|
EXPECT(Dart_IsBoolean(false_handle));
|
|
|
|
result = Dart_BooleanValue(false_handle, &value);
|
|
EXPECT_VALID(result);
|
|
EXPECT(!value);
|
|
}
|
|
|
|
|
|
TEST_CASE(DoubleValues) {
|
|
const double kDoubleVal1 = 201.29;
|
|
const double kDoubleVal2 = 101.19;
|
|
Dart_Handle val1 = Dart_NewDouble(kDoubleVal1);
|
|
EXPECT(Dart_IsDouble(val1));
|
|
Dart_Handle val2 = Dart_NewDouble(kDoubleVal2);
|
|
EXPECT(Dart_IsDouble(val2));
|
|
double out1, out2;
|
|
Dart_Handle result = Dart_DoubleValue(val1, &out1);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(kDoubleVal1, out1);
|
|
result = Dart_DoubleValue(val2, &out2);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(kDoubleVal2, out2);
|
|
}
|
|
|
|
|
|
// Only ia32 and x64 can run execution tests.
|
|
#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
|
|
|
|
TEST_CASE(NumberValues) {
|
|
// TODO(antonm): add various kinds of ints (smi, mint, bigint).
|
|
const char* kScriptChars =
|
|
"class NumberValuesHelper {\n"
|
|
" static int getInt() { return 1; }\n"
|
|
" static double getDouble() { return 1.0; }\n"
|
|
" static bool getBool() { return false; }\n"
|
|
" static getNull() { return null; }\n"
|
|
"}\n";
|
|
Dart_Handle result;
|
|
// Create a test library and Load up a test script in it.
|
|
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
|
|
|
Dart_Handle class_name = Dart_NewString("NumberValuesHelper");
|
|
// Check int case.
|
|
result = Dart_InvokeStatic(lib,
|
|
class_name,
|
|
Dart_NewString("getInt"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(result);
|
|
EXPECT(Dart_IsNumber(result));
|
|
|
|
// Check double case.
|
|
result = Dart_InvokeStatic(lib,
|
|
class_name,
|
|
Dart_NewString("getDouble"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(result);
|
|
EXPECT(Dart_IsNumber(result));
|
|
|
|
// Check bool case.
|
|
result = Dart_InvokeStatic(lib,
|
|
class_name,
|
|
Dart_NewString("getBool"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(result);
|
|
EXPECT(!Dart_IsNumber(result));
|
|
|
|
// Check null case.
|
|
result = Dart_InvokeStatic(lib,
|
|
class_name,
|
|
Dart_NewString("getNull"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(result);
|
|
EXPECT(!Dart_IsNumber(result));
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
TEST_CASE(IntegerValues) {
|
|
const int64_t kIntegerVal1 = 100;
|
|
const int64_t kIntegerVal2 = 0xffffffff;
|
|
const char* kIntegerVal3 = "0x123456789123456789123456789";
|
|
|
|
Dart_Handle val1 = Dart_NewInteger(kIntegerVal1);
|
|
EXPECT(Dart_IsInteger(val1));
|
|
bool fits = false;
|
|
Dart_Handle result = Dart_IntegerFitsIntoInt64(val1, &fits);
|
|
EXPECT_VALID(result);
|
|
EXPECT(fits);
|
|
|
|
Dart_Handle val2 = Dart_NewInteger(kIntegerVal2);
|
|
EXPECT(Dart_IsInteger(val2));
|
|
result = Dart_IntegerFitsIntoInt64(val2, &fits);
|
|
EXPECT_VALID(result);
|
|
EXPECT(fits);
|
|
|
|
Dart_Handle val3 = Dart_NewIntegerFromHexCString(kIntegerVal3);
|
|
EXPECT(Dart_IsInteger(val3));
|
|
result = Dart_IntegerFitsIntoInt64(val3, &fits);
|
|
EXPECT_VALID(result);
|
|
EXPECT(!fits);
|
|
|
|
int64_t out = 0;
|
|
result = Dart_IntegerToInt64(val1, &out);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(kIntegerVal1, out);
|
|
|
|
result = Dart_IntegerToInt64(val2, &out);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(kIntegerVal2, out);
|
|
|
|
const char* chars = NULL;
|
|
result = Dart_IntegerToHexCString(val3, &chars);
|
|
EXPECT_VALID(result);
|
|
EXPECT(!strcmp(kIntegerVal3, chars));
|
|
}
|
|
|
|
|
|
TEST_CASE(IntegerFitsIntoInt64) {
|
|
Dart_Handle max = Dart_NewInteger(kMaxInt64);
|
|
EXPECT(Dart_IsInteger(max));
|
|
bool fits = false;
|
|
Dart_Handle result = Dart_IntegerFitsIntoInt64(max, &fits);
|
|
EXPECT_VALID(result);
|
|
EXPECT(fits);
|
|
|
|
Dart_Handle above_max = Dart_NewIntegerFromHexCString("0x8000000000000000");
|
|
EXPECT(Dart_IsInteger(above_max));
|
|
fits = true;
|
|
result = Dart_IntegerFitsIntoInt64(above_max, &fits);
|
|
EXPECT_VALID(result);
|
|
EXPECT(!fits);
|
|
|
|
Dart_Handle min = Dart_NewInteger(kMaxInt64);
|
|
EXPECT(Dart_IsInteger(min));
|
|
fits = false;
|
|
result = Dart_IntegerFitsIntoInt64(min, &fits);
|
|
EXPECT_VALID(result);
|
|
EXPECT(fits);
|
|
|
|
Dart_Handle below_min = Dart_NewIntegerFromHexCString("-0x8000000000000001");
|
|
EXPECT(Dart_IsInteger(below_min));
|
|
fits = true;
|
|
result = Dart_IntegerFitsIntoInt64(below_min, &fits);
|
|
EXPECT_VALID(result);
|
|
EXPECT(!fits);
|
|
}
|
|
|
|
|
|
TEST_CASE(IntegerFitsIntoUint64) {
|
|
Dart_Handle max = Dart_NewIntegerFromHexCString("0xFFFFFFFFFFFFFFFF");
|
|
EXPECT(Dart_IsInteger(max));
|
|
bool fits = false;
|
|
Dart_Handle result = Dart_IntegerFitsIntoUint64(max, &fits);
|
|
EXPECT_VALID(result);
|
|
EXPECT(fits);
|
|
|
|
Dart_Handle above_max = Dart_NewIntegerFromHexCString("0x10000000000000000");
|
|
EXPECT(Dart_IsInteger(above_max));
|
|
fits = true;
|
|
result = Dart_IntegerFitsIntoUint64(above_max, &fits);
|
|
EXPECT_VALID(result);
|
|
EXPECT(!fits);
|
|
|
|
Dart_Handle min = Dart_NewInteger(0);
|
|
EXPECT(Dart_IsInteger(min));
|
|
fits = false;
|
|
result = Dart_IntegerFitsIntoUint64(min, &fits);
|
|
EXPECT_VALID(result);
|
|
EXPECT(fits);
|
|
|
|
Dart_Handle below_min = Dart_NewIntegerFromHexCString("-1");
|
|
EXPECT(Dart_IsInteger(below_min));
|
|
fits = true;
|
|
result = Dart_IntegerFitsIntoUint64(below_min, &fits);
|
|
EXPECT_VALID(result);
|
|
EXPECT(!fits);
|
|
}
|
|
|
|
|
|
TEST_CASE(ArrayValues) {
|
|
const int kArrayLength = 10;
|
|
Dart_Handle str = Dart_NewString("test");
|
|
EXPECT(!Dart_IsList(str));
|
|
Dart_Handle val = Dart_NewList(kArrayLength);
|
|
EXPECT(Dart_IsList(val));
|
|
intptr_t len = 0;
|
|
Dart_Handle result = Dart_ListLength(val, &len);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(kArrayLength, len);
|
|
|
|
// Check invalid array access.
|
|
result = Dart_ListSetAt(val, (kArrayLength + 10), Dart_NewInteger(10));
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_ListSetAt(val, -10, Dart_NewInteger(10));
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_ListGetAt(val, (kArrayLength + 10));
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_ListGetAt(val, -10);
|
|
EXPECT(Dart_IsError(result));
|
|
|
|
for (int i = 0; i < kArrayLength; i++) {
|
|
result = Dart_ListSetAt(val, i, Dart_NewInteger(i));
|
|
EXPECT_VALID(result);
|
|
}
|
|
for (int i = 0; i < kArrayLength; i++) {
|
|
result = Dart_ListGetAt(val, i);
|
|
EXPECT_VALID(result);
|
|
int64_t value;
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(i, value);
|
|
}
|
|
}
|
|
|
|
|
|
TEST_CASE(IsString) {
|
|
uint8_t data8[] = { 'o', 'n', 'e', 0xFF };
|
|
|
|
Dart_Handle str8 = Dart_NewString8(data8, ARRAY_SIZE(data8));
|
|
EXPECT_VALID(str8);
|
|
EXPECT(Dart_IsString(str8));
|
|
EXPECT(Dart_IsString8(str8));
|
|
EXPECT(Dart_IsString16(str8));
|
|
EXPECT(!Dart_IsExternalString(str8));
|
|
|
|
Dart_Handle ext8 = Dart_NewExternalString8(data8, ARRAY_SIZE(data8),
|
|
NULL, NULL);
|
|
EXPECT_VALID(ext8);
|
|
EXPECT(Dart_IsString(ext8));
|
|
EXPECT(Dart_IsString8(ext8));
|
|
EXPECT(Dart_IsString16(ext8));
|
|
EXPECT(Dart_IsExternalString(ext8));
|
|
|
|
uint16_t data16[] = { 't', 'w', 'o', 0xFFFF };
|
|
|
|
Dart_Handle str16 = Dart_NewString16(data16, ARRAY_SIZE(data16));
|
|
EXPECT_VALID(str16);
|
|
EXPECT(Dart_IsString(str16));
|
|
EXPECT(!Dart_IsString8(str16));
|
|
EXPECT(Dart_IsString16(str16));
|
|
EXPECT(!Dart_IsExternalString(str16));
|
|
|
|
Dart_Handle ext16 = Dart_NewExternalString16(data16, ARRAY_SIZE(data16),
|
|
NULL, NULL);
|
|
EXPECT_VALID(ext16);
|
|
EXPECT(Dart_IsString(ext16));
|
|
EXPECT(!Dart_IsString8(ext16));
|
|
EXPECT(Dart_IsString16(ext16));
|
|
EXPECT(Dart_IsExternalString(ext16));
|
|
|
|
uint32_t data32[] = { 'f', 'o', 'u', 'r', 0x10FFFF };
|
|
|
|
Dart_Handle str32 = Dart_NewString32(data32, ARRAY_SIZE(data32));
|
|
EXPECT_VALID(str32);
|
|
EXPECT(Dart_IsString(str32));
|
|
EXPECT(!Dart_IsString8(str32));
|
|
EXPECT(!Dart_IsString16(str32));
|
|
EXPECT(!Dart_IsExternalString(str32));
|
|
|
|
Dart_Handle ext32 = Dart_NewExternalString32(data32, ARRAY_SIZE(data32),
|
|
NULL, NULL);
|
|
EXPECT_VALID(ext32);
|
|
EXPECT(Dart_IsString(ext32));
|
|
EXPECT(!Dart_IsString8(ext32));
|
|
EXPECT(!Dart_IsString16(ext32));
|
|
EXPECT(Dart_IsExternalString(ext32));
|
|
}
|
|
|
|
|
|
TEST_CASE(ExternalStringGetPeer) {
|
|
Dart_Handle result;
|
|
|
|
uint8_t data8[] = { 'o', 'n', 'e', 0xFF };
|
|
int peer_data = 123;
|
|
void* peer = NULL;
|
|
|
|
// Success.
|
|
Dart_Handle ext8 = Dart_NewExternalString8(data8, ARRAY_SIZE(data8),
|
|
&peer_data, NULL);
|
|
EXPECT_VALID(ext8);
|
|
|
|
result = Dart_ExternalStringGetPeer(ext8, &peer);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(&peer_data, peer);
|
|
|
|
// NULL peer.
|
|
result = Dart_ExternalStringGetPeer(ext8, NULL);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Dart_ExternalStringGetPeer expects argument 'peer' to be "
|
|
"non-null.", Dart_GetError(result));
|
|
|
|
// String is not external.
|
|
peer = NULL;
|
|
Dart_Handle str8 = Dart_NewString8(data8, ARRAY_SIZE(data8));
|
|
EXPECT_VALID(str8);
|
|
result = Dart_ExternalStringGetPeer(str8, &peer);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Dart_ExternalStringGetPeer expects argument 'object' to be "
|
|
"an external String.", Dart_GetError(result));
|
|
EXPECT(peer == NULL);
|
|
|
|
// Not a String.
|
|
peer = NULL;
|
|
result = Dart_ExternalStringGetPeer(Dart_True(), &peer);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Dart_ExternalStringGetPeer expects argument 'object' to be "
|
|
"of type String.", Dart_GetError(result));
|
|
EXPECT(peer == NULL);
|
|
}
|
|
|
|
|
|
// Only ia32 and x64 can run execution tests.
|
|
#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
|
|
|
|
static void ExternalStringCallbackFinalizer(void* peer) {
|
|
*static_cast<int*>(peer) *= 2;
|
|
}
|
|
|
|
|
|
TEST_CASE(ExternalStringCallback) {
|
|
int peer8 = 40;
|
|
int peer16 = 41;
|
|
int peer32 = 42;
|
|
|
|
{
|
|
Dart_EnterScope();
|
|
|
|
uint8_t data8[] = { 'h', 'e', 'l', 'l', 'o' };
|
|
Dart_Handle obj8 = Dart_NewExternalString8(
|
|
data8,
|
|
ARRAY_SIZE(data8),
|
|
&peer8,
|
|
ExternalStringCallbackFinalizer);
|
|
EXPECT_VALID(obj8);
|
|
void* api_peer8 = NULL;
|
|
EXPECT_VALID(Dart_ExternalStringGetPeer(obj8, &api_peer8));
|
|
EXPECT_EQ(api_peer8, &peer8);
|
|
|
|
uint16_t data16[] = { 'h', 'e', 'l', 'l', 'o' };
|
|
Dart_Handle obj16 = Dart_NewExternalString16(
|
|
data16,
|
|
ARRAY_SIZE(data16),
|
|
&peer16,
|
|
ExternalStringCallbackFinalizer);
|
|
EXPECT_VALID(obj16);
|
|
void* api_peer16 = NULL;
|
|
EXPECT_VALID(Dart_ExternalStringGetPeer(obj16, &api_peer16));
|
|
EXPECT_EQ(api_peer16, &peer16);
|
|
|
|
uint32_t data32[] = { 'h', 'e', 'l', 'l', 'o' };
|
|
Dart_Handle obj32 = Dart_NewExternalString32(
|
|
data32,
|
|
ARRAY_SIZE(data32),
|
|
&peer32,
|
|
ExternalStringCallbackFinalizer);
|
|
EXPECT_VALID(obj32);
|
|
void* api_peer32 = NULL;
|
|
EXPECT_VALID(Dart_ExternalStringGetPeer(obj32, &api_peer32));
|
|
EXPECT_EQ(api_peer32, &peer32);
|
|
|
|
Dart_ExitScope();
|
|
}
|
|
|
|
EXPECT_EQ(peer8, 40);
|
|
EXPECT_EQ(peer16, 41);
|
|
EXPECT_EQ(peer32, 42);
|
|
Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
|
|
EXPECT_EQ(peer8, 40);
|
|
EXPECT_EQ(peer16, 41);
|
|
EXPECT_EQ(peer32, 42);
|
|
Isolate::Current()->heap()->CollectGarbage(Heap::kNew);
|
|
EXPECT_EQ(peer8, 80);
|
|
EXPECT_EQ(peer16, 82);
|
|
EXPECT_EQ(peer32, 84);
|
|
}
|
|
|
|
|
|
TEST_CASE(ListAccess) {
|
|
const char* kScriptChars =
|
|
"class ListAccessTest {"
|
|
" ListAccessTest() {}"
|
|
" static List testMain() {"
|
|
" List a = new List();"
|
|
" a.add(10);"
|
|
" a.add(20);"
|
|
" a.add(30);"
|
|
" return a;"
|
|
" }"
|
|
"}";
|
|
Dart_Handle result;
|
|
|
|
// Create a test library and Load up a test script in it.
|
|
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
|
|
|
// Invoke a function which returns an object of type InstanceOf..
|
|
result = Dart_InvokeStatic(lib,
|
|
Dart_NewString("ListAccessTest"),
|
|
Dart_NewString("testMain"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(result);
|
|
|
|
// First ensure that the returned object is an array.
|
|
Dart_Handle ListAccessTestObj = result;
|
|
|
|
EXPECT(Dart_IsList(ListAccessTestObj));
|
|
|
|
// Get length of array object.
|
|
intptr_t len = 0;
|
|
result = Dart_ListLength(ListAccessTestObj, &len);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(3, len);
|
|
|
|
// Access elements in the array.
|
|
int64_t value;
|
|
|
|
result = Dart_ListGetAt(ListAccessTestObj, 0);
|
|
EXPECT_VALID(result);
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(10, value);
|
|
|
|
result = Dart_ListGetAt(ListAccessTestObj, 1);
|
|
EXPECT_VALID(result);
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(20, value);
|
|
|
|
result = Dart_ListGetAt(ListAccessTestObj, 2);
|
|
EXPECT_VALID(result);
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(30, value);
|
|
|
|
// Set some elements in the array.
|
|
result = Dart_ListSetAt(ListAccessTestObj, 0, Dart_NewInteger(0));
|
|
EXPECT_VALID(result);
|
|
result = Dart_ListSetAt(ListAccessTestObj, 1, Dart_NewInteger(1));
|
|
EXPECT_VALID(result);
|
|
result = Dart_ListSetAt(ListAccessTestObj, 2, Dart_NewInteger(2));
|
|
EXPECT_VALID(result);
|
|
|
|
// Get length of array object.
|
|
result = Dart_ListLength(ListAccessTestObj, &len);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(3, len);
|
|
|
|
// Now try and access these elements in the array.
|
|
result = Dart_ListGetAt(ListAccessTestObj, 0);
|
|
EXPECT_VALID(result);
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(0, value);
|
|
|
|
result = Dart_ListGetAt(ListAccessTestObj, 1);
|
|
EXPECT_VALID(result);
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(1, value);
|
|
|
|
result = Dart_ListGetAt(ListAccessTestObj, 2);
|
|
EXPECT_VALID(result);
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(2, value);
|
|
|
|
uint8_t native_array[3];
|
|
result = Dart_ListGetAsBytes(ListAccessTestObj, 0, native_array, 3);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(0, native_array[0]);
|
|
EXPECT_EQ(1, native_array[1]);
|
|
EXPECT_EQ(2, native_array[2]);
|
|
|
|
native_array[0] = 10;
|
|
native_array[1] = 20;
|
|
native_array[2] = 30;
|
|
result = Dart_ListSetAsBytes(ListAccessTestObj, 0, native_array, 3);
|
|
EXPECT_VALID(result);
|
|
result = Dart_ListGetAsBytes(ListAccessTestObj, 0, native_array, 3);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(10, native_array[0]);
|
|
EXPECT_EQ(20, native_array[1]);
|
|
EXPECT_EQ(30, native_array[2]);
|
|
result = Dart_ListGetAt(ListAccessTestObj, 2);
|
|
EXPECT_VALID(result);
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(30, value);
|
|
|
|
// Check if we get an exception when accessing beyond limit.
|
|
result = Dart_ListGetAt(ListAccessTestObj, 4);
|
|
EXPECT(Dart_IsError(result));
|
|
}
|
|
|
|
|
|
TEST_CASE(ByteArrayAccess) {
|
|
Dart_Handle byte_array1 = Dart_NewByteArray(10);
|
|
EXPECT_VALID(byte_array1);
|
|
EXPECT(Dart_IsByteArray(byte_array1));
|
|
EXPECT(Dart_IsList(byte_array1));
|
|
|
|
intptr_t length = 0;
|
|
Dart_Handle result = Dart_ListLength(byte_array1, &length);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(10, length);
|
|
|
|
result = Dart_ListSetAt(byte_array1, -1, Dart_NewInteger(1));
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_ByteArraySetUint8At(byte_array1, -1, 1);
|
|
EXPECT(Dart_IsError(result));
|
|
|
|
result = Dart_ListSetAt(byte_array1, 10, Dart_NewInteger(1));
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_ByteArraySetUint8At(byte_array1, 10, 1);
|
|
EXPECT(Dart_IsError(result));
|
|
|
|
// Set through the List API.
|
|
for (intptr_t i = 0; i < 10; ++i) {
|
|
EXPECT_VALID(Dart_ListSetAt(byte_array1, i, Dart_NewInteger(i + 1)));
|
|
}
|
|
for (intptr_t i = 0; i < 10; ++i) {
|
|
// Get through the List API.
|
|
Dart_Handle integer_obj = Dart_ListGetAt(byte_array1, i);
|
|
EXPECT_VALID(integer_obj);
|
|
int64_t int64_t_value = -1;
|
|
EXPECT_VALID(Dart_IntegerToInt64(integer_obj, &int64_t_value));
|
|
EXPECT_EQ(i + 1, int64_t_value);
|
|
// Get through the ByteArray API.
|
|
uint8_t uint8_t_value = 0xFF;
|
|
EXPECT_VALID(Dart_ByteArrayGetUint8At(byte_array1, i, &uint8_t_value));
|
|
EXPECT_EQ(i + 1, uint8_t_value);
|
|
}
|
|
|
|
// Set through the ByteArray API.
|
|
for (intptr_t i = 0; i < 10; ++i) {
|
|
EXPECT_VALID(Dart_ByteArraySetUint8At(byte_array1, i, i + 2));
|
|
}
|
|
for (intptr_t i = 0; i < 10; ++i) {
|
|
// Get through the List API.
|
|
Dart_Handle integer_obj = Dart_ListGetAt(byte_array1, i);
|
|
EXPECT_VALID(integer_obj);
|
|
int64_t int64_t_value = -1;
|
|
EXPECT_VALID(Dart_IntegerToInt64(integer_obj, &int64_t_value));
|
|
EXPECT_EQ(i + 2, int64_t_value);
|
|
// Get through the ByteArray API.
|
|
uint8_t uint8_t_value = 0xFF;
|
|
EXPECT_VALID(Dart_ByteArrayGetUint8At(byte_array1, i, &uint8_t_value));
|
|
EXPECT_EQ(i + 2, uint8_t_value);
|
|
}
|
|
|
|
Dart_Handle byte_array2 = Dart_NewByteArray(10);
|
|
bool is_equal = false;
|
|
Dart_ObjectEquals(byte_array1, byte_array2, &is_equal);
|
|
EXPECT(!is_equal);
|
|
|
|
// Set through the List API.
|
|
for (intptr_t i = 0; i < 10; ++i) {
|
|
result = Dart_ListSetAt(byte_array2, i, Dart_NewInteger(i + 2));
|
|
EXPECT_VALID(result);
|
|
}
|
|
for (intptr_t i = 0; i < 10; ++i) {
|
|
// Get through the List API.
|
|
Dart_Handle e1 = Dart_ListGetAt(byte_array1, i);
|
|
Dart_Handle e2 = Dart_ListGetAt(byte_array2, i);
|
|
is_equal = false;
|
|
Dart_ObjectEquals(e1, e2, &is_equal);
|
|
EXPECT(is_equal);
|
|
// Get through the ByteArray API.
|
|
uint8_t v1 = 0xFF;
|
|
uint8_t v2 = 0XFF;
|
|
EXPECT_VALID(Dart_ByteArrayGetUint8At(byte_array1, i, &v1));
|
|
EXPECT_VALID(Dart_ByteArrayGetUint8At(byte_array2, i, &v2));
|
|
EXPECT_NE(v1, 0xFF);
|
|
EXPECT_NE(v2, 0xFF);
|
|
EXPECT_EQ(v1, v2);
|
|
}
|
|
|
|
byte_array2 = Dart_NewByteArray(10);
|
|
is_equal = false;
|
|
Dart_ObjectEquals(byte_array1, byte_array2, &is_equal);
|
|
EXPECT(!is_equal);
|
|
|
|
// Set through the ByteArray API.
|
|
for (intptr_t i = 0; i < 10; ++i) {
|
|
result = Dart_ByteArraySetUint8At(byte_array2, i, i + 2);
|
|
EXPECT_VALID(result);
|
|
}
|
|
for (intptr_t i = 0; i < 10; ++i) {
|
|
// Get through the List API.
|
|
Dart_Handle e1 = Dart_ListGetAt(byte_array1, i);
|
|
Dart_Handle e2 = Dart_ListGetAt(byte_array2, i);
|
|
is_equal = false;
|
|
Dart_ObjectEquals(e1, e2, &is_equal);
|
|
EXPECT(is_equal);
|
|
// Get through the ByteArray API.
|
|
uint8_t v1 = 0xFF;
|
|
uint8_t v2 = 0XFF;
|
|
EXPECT_VALID(Dart_ByteArrayGetUint8At(byte_array1, i, &v1));
|
|
EXPECT_VALID(Dart_ByteArrayGetUint8At(byte_array2, i, &v2));
|
|
EXPECT_NE(v1, 0xFF);
|
|
EXPECT_NE(v2, 0xFF);
|
|
EXPECT_EQ(v1, v2);
|
|
}
|
|
|
|
uint8_t data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
|
result = Dart_ListSetAsBytes(byte_array1, 0, data, 10);
|
|
EXPECT_VALID(result);
|
|
for (intptr_t i = 0; i < 10; ++i) {
|
|
Dart_Handle integer_obj = Dart_ListGetAt(byte_array1, i);
|
|
EXPECT_VALID(integer_obj);
|
|
int64_t int64_t_value = -1;
|
|
EXPECT_VALID(Dart_IntegerToInt64(integer_obj, &int64_t_value));
|
|
EXPECT_EQ(i, int64_t_value);
|
|
uint8_t uint8_t_value = 0xFF;
|
|
EXPECT_VALID(Dart_ByteArrayGetUint8At(byte_array1, i, &uint8_t_value));
|
|
EXPECT_EQ(i, uint8_t_value);
|
|
}
|
|
|
|
for (intptr_t i = 0; i < 10; ++i) {
|
|
EXPECT_VALID(Dart_ListSetAt(byte_array1, i, Dart_NewInteger(10 - i)));
|
|
}
|
|
Dart_ListGetAsBytes(byte_array1, 0, data, 10);
|
|
for (intptr_t i = 0; i < 10; ++i) {
|
|
Dart_Handle integer_obj = Dart_ListGetAt(byte_array1, i);
|
|
EXPECT_VALID(integer_obj);
|
|
int64_t int64_t_value = -1;
|
|
EXPECT_VALID(Dart_IntegerToInt64(integer_obj, &int64_t_value));
|
|
EXPECT_EQ(10 - i, int64_t_value);
|
|
uint8_t uint8_t_value = 0xFF;
|
|
EXPECT_VALID(Dart_ByteArrayGetUint8At(byte_array1, i, &uint8_t_value));
|
|
EXPECT_EQ(10 - i, uint8_t_value);
|
|
}
|
|
|
|
for (intptr_t i = 0; i < 10; ++i) {
|
|
EXPECT_VALID(Dart_ByteArraySetUint8At(byte_array1, i, 10 + i));
|
|
}
|
|
Dart_ListGetAsBytes(byte_array1, 0, data, 10);
|
|
for (intptr_t i = 0; i < 10; ++i) {
|
|
Dart_Handle integer_obj = Dart_ListGetAt(byte_array1, i);
|
|
EXPECT_VALID(integer_obj);
|
|
int64_t int64_t_value = -1;
|
|
EXPECT_VALID(Dart_IntegerToInt64(integer_obj, &int64_t_value));
|
|
EXPECT_EQ(10 + i, int64_t_value);
|
|
uint8_t uint8_t_value = 0xFF;
|
|
EXPECT_VALID(Dart_ByteArrayGetUint8At(byte_array1, i, &uint8_t_value));
|
|
EXPECT_EQ(10 + i, uint8_t_value);
|
|
}
|
|
}
|
|
|
|
|
|
TEST_CASE(ByteArrayAlignedMultiByteAccess) {
|
|
intptr_t length = 16;
|
|
Dart_Handle byte_array = Dart_NewByteArray(length);
|
|
intptr_t api_length = 0;
|
|
EXPECT_VALID(Dart_ListLength(byte_array, &api_length));
|
|
EXPECT_EQ(length, api_length);
|
|
|
|
// 4-byte aligned sets.
|
|
|
|
EXPECT_VALID(Dart_ByteArraySetFloat32At(byte_array, 0, FLT_MIN));
|
|
EXPECT_VALID(Dart_ByteArraySetFloat32At(byte_array, 4, FLT_MAX));
|
|
|
|
float float_value = 0.0f;
|
|
EXPECT_VALID(Dart_ByteArrayGetFloat32At(byte_array, 0, &float_value));
|
|
EXPECT_EQ(FLT_MIN, float_value);
|
|
|
|
float_value = 0.0f;
|
|
EXPECT_VALID(Dart_ByteArrayGetFloat32At(byte_array, 4, &float_value));
|
|
EXPECT_EQ(FLT_MAX, float_value);
|
|
|
|
EXPECT_VALID(Dart_ByteArraySetFloat32At(byte_array, 0, 0.0f));
|
|
float_value = FLT_MAX;
|
|
EXPECT_VALID(Dart_ByteArrayGetFloat32At(byte_array, 0, &float_value));
|
|
EXPECT_EQ(0.0f, float_value);
|
|
|
|
EXPECT_VALID(Dart_ByteArraySetFloat32At(byte_array, 4, 1.0f));
|
|
float_value = FLT_MAX;
|
|
EXPECT_VALID(Dart_ByteArrayGetFloat32At(byte_array, 4, &float_value));
|
|
EXPECT_EQ(1.0f, float_value);
|
|
|
|
EXPECT_VALID(Dart_ByteArraySetFloat32At(byte_array, 0, -1.0f));
|
|
float_value = FLT_MAX;
|
|
EXPECT_VALID(Dart_ByteArrayGetFloat32At(byte_array, 0, &float_value));
|
|
EXPECT_EQ(-1.0f, float_value);
|
|
|
|
// 8-byte aligned sets.
|
|
|
|
EXPECT_VALID(Dart_ByteArraySetFloat64At(byte_array, 0, DBL_MIN));
|
|
EXPECT_VALID(Dart_ByteArraySetFloat64At(byte_array, 8, DBL_MAX));
|
|
|
|
double double_value = 0.0;
|
|
EXPECT_VALID(Dart_ByteArrayGetFloat64At(byte_array, 0, &double_value));
|
|
EXPECT_EQ(DBL_MIN, double_value);
|
|
|
|
double_value = 0.0;
|
|
EXPECT_VALID(Dart_ByteArrayGetFloat64At(byte_array, 8, &double_value));
|
|
EXPECT_EQ(DBL_MAX, double_value);
|
|
|
|
EXPECT_VALID(Dart_ByteArraySetFloat64At(byte_array, 0, 0.0));
|
|
double_value = DBL_MAX;
|
|
EXPECT_VALID(Dart_ByteArrayGetFloat64At(byte_array, 0, &double_value));
|
|
EXPECT_EQ(0.0, double_value);
|
|
|
|
EXPECT_VALID(Dart_ByteArraySetFloat64At(byte_array, 8, 1.0));
|
|
double_value = DBL_MAX;
|
|
EXPECT_VALID(Dart_ByteArrayGetFloat64At(byte_array, 8, &double_value));
|
|
EXPECT_EQ(1.0, double_value);
|
|
}
|
|
|
|
|
|
TEST_CASE(ByteArrayMisalignedMultiByteAccess) {
|
|
intptr_t length = 17;
|
|
Dart_Handle byte_array = Dart_NewByteArray(length);
|
|
intptr_t api_length = 0;
|
|
EXPECT_VALID(Dart_ListLength(byte_array, &api_length));
|
|
EXPECT_EQ(length, api_length);
|
|
|
|
// 4-byte misaligned sets.
|
|
|
|
EXPECT_VALID(Dart_ByteArraySetFloat32At(byte_array, 1, FLT_MIN));
|
|
EXPECT_VALID(Dart_ByteArraySetFloat32At(byte_array, 5, FLT_MAX));
|
|
|
|
float float_value = 0.0f;
|
|
EXPECT_VALID(Dart_ByteArrayGetFloat32At(byte_array, 1, &float_value));
|
|
EXPECT_EQ(FLT_MIN, float_value);
|
|
|
|
float_value = 0.0f;
|
|
EXPECT_VALID(Dart_ByteArrayGetFloat32At(byte_array, 5, &float_value));
|
|
EXPECT_EQ(FLT_MAX, float_value);
|
|
|
|
EXPECT_VALID(Dart_ByteArraySetFloat32At(byte_array, 1, 0.0f));
|
|
float_value = FLT_MAX;
|
|
EXPECT_VALID(Dart_ByteArrayGetFloat32At(byte_array, 1, &float_value));
|
|
EXPECT_EQ(0.0f, float_value);
|
|
|
|
EXPECT_VALID(Dart_ByteArraySetFloat32At(byte_array, 5, -0.0f));
|
|
float_value = FLT_MAX;
|
|
EXPECT_VALID(Dart_ByteArrayGetFloat32At(byte_array, 5, &float_value));
|
|
EXPECT_EQ(-0.0f, float_value);
|
|
|
|
EXPECT_VALID(Dart_ByteArraySetFloat32At(byte_array, 5, 1.0f));
|
|
float_value = FLT_MAX;
|
|
EXPECT_VALID(Dart_ByteArrayGetFloat32At(byte_array, 5, &float_value));
|
|
EXPECT_EQ(1.0f, float_value);
|
|
|
|
EXPECT_VALID(Dart_ByteArraySetFloat32At(byte_array, 1, -1.0f));
|
|
float_value = FLT_MAX;
|
|
EXPECT_VALID(Dart_ByteArrayGetFloat32At(byte_array, 1, &float_value));
|
|
EXPECT_EQ(-1.0f, float_value);
|
|
|
|
// 8-byte misaligned sets.
|
|
|
|
EXPECT_VALID(Dart_ByteArraySetFloat64At(byte_array, 1, DBL_MIN));
|
|
EXPECT_VALID(Dart_ByteArraySetFloat64At(byte_array, 9, DBL_MAX));
|
|
|
|
double double_value = 0.0;
|
|
EXPECT_VALID(Dart_ByteArrayGetFloat64At(byte_array, 1, &double_value));
|
|
EXPECT_EQ(DBL_MIN, double_value);
|
|
|
|
double_value = 0.0;
|
|
EXPECT_VALID(Dart_ByteArrayGetFloat64At(byte_array, 9, &double_value));
|
|
EXPECT_EQ(DBL_MAX, double_value);
|
|
|
|
EXPECT_VALID(Dart_ByteArraySetFloat64At(byte_array, 1, 0.0));
|
|
double_value = DBL_MAX;
|
|
EXPECT_VALID(Dart_ByteArrayGetFloat64At(byte_array, 1, &double_value));
|
|
EXPECT_EQ(0.0, double_value);
|
|
|
|
EXPECT_VALID(Dart_ByteArraySetFloat64At(byte_array, 9, -0.0));
|
|
double_value = DBL_MAX;
|
|
EXPECT_VALID(Dart_ByteArrayGetFloat64At(byte_array, 9, &double_value));
|
|
EXPECT_EQ(-0.0, double_value);
|
|
|
|
EXPECT_VALID(Dart_ByteArraySetFloat64At(byte_array, 9, 1.0));
|
|
double_value = DBL_MAX;
|
|
EXPECT_VALID(Dart_ByteArrayGetFloat64At(byte_array, 9, &double_value));
|
|
EXPECT_EQ(1.0, double_value);
|
|
|
|
EXPECT_VALID(Dart_ByteArraySetFloat64At(byte_array, 1, -1.0));
|
|
double_value = DBL_MAX;
|
|
EXPECT_VALID(Dart_ByteArrayGetFloat64At(byte_array, 1, &double_value));
|
|
EXPECT_EQ(-1.0, double_value);
|
|
}
|
|
|
|
|
|
TEST_CASE(ExternalByteArrayAccess) {
|
|
uint8_t data[] = { 0, 11, 22, 33, 44, 55, 66, 77 };
|
|
intptr_t data_length = ARRAY_SIZE(data);
|
|
|
|
Dart_Handle obj = Dart_NewExternalByteArray(data, data_length, NULL, NULL);
|
|
EXPECT_VALID(obj);
|
|
EXPECT(Dart_IsByteArray(obj));
|
|
EXPECT(Dart_IsList(obj));
|
|
|
|
void* peer = &data; // just a non-NULL value
|
|
EXPECT_VALID(Dart_ExternalByteArrayGetPeer(obj, &peer));
|
|
EXPECT(peer == NULL);
|
|
|
|
intptr_t list_length = 0;
|
|
EXPECT_VALID(Dart_ListLength(obj, &list_length));
|
|
EXPECT_EQ(data_length, list_length);
|
|
|
|
// Load and check values from underlying array and API.
|
|
for (intptr_t i = 0; i < list_length; ++i) {
|
|
EXPECT_EQ(11 * i, data[i]);
|
|
Dart_Handle elt = Dart_ListGetAt(obj, i);
|
|
EXPECT_VALID(elt);
|
|
int64_t value = 0;
|
|
EXPECT_VALID(Dart_IntegerToInt64(elt, &value));
|
|
EXPECT_EQ(data[i], value);
|
|
}
|
|
|
|
// Write values through the underlying array.
|
|
for (intptr_t i = 0; i < data_length; ++i) {
|
|
data[i] *= 2;
|
|
}
|
|
// Read them back through the API.
|
|
for (intptr_t i = 0; i < list_length; ++i) {
|
|
Dart_Handle elt = Dart_ListGetAt(obj, i);
|
|
EXPECT_VALID(elt);
|
|
int64_t value = 0;
|
|
EXPECT_VALID(Dart_IntegerToInt64(elt, &value));
|
|
EXPECT_EQ(22 * i, value);
|
|
}
|
|
|
|
// Write values through the API.
|
|
for (intptr_t i = 0; i < list_length; ++i) {
|
|
Dart_Handle value = Dart_NewInteger(33 * i);
|
|
EXPECT_VALID(value);
|
|
EXPECT_VALID(Dart_ListSetAt(obj, i, value));
|
|
}
|
|
// Read them back through the underlying array.
|
|
for (intptr_t i = 0; i < data_length; ++i) {
|
|
EXPECT_EQ(33 * i, data[i]);
|
|
}
|
|
}
|
|
|
|
|
|
static void ExternalByteArrayCallbackFinalizer(void* peer) {
|
|
*static_cast<int*>(peer) = 42;
|
|
}
|
|
|
|
|
|
TEST_CASE(ExternalByteArrayCallback) {
|
|
int peer = 0;
|
|
{
|
|
Dart_EnterScope();
|
|
uint8_t data[] = { 1, 2, 3, 4 };
|
|
Dart_Handle obj = Dart_NewExternalByteArray(
|
|
data,
|
|
ARRAY_SIZE(data),
|
|
&peer,
|
|
ExternalByteArrayCallbackFinalizer);
|
|
EXPECT_VALID(obj);
|
|
void* api_peer = NULL;
|
|
EXPECT_VALID(Dart_ExternalByteArrayGetPeer(obj, &api_peer));
|
|
EXPECT_EQ(api_peer, &peer);
|
|
Dart_ExitScope();
|
|
}
|
|
EXPECT(peer == 0);
|
|
Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
|
|
EXPECT(peer == 0);
|
|
Isolate::Current()->heap()->CollectGarbage(Heap::kNew);
|
|
EXPECT(peer == 42);
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
// Unit test for entering a scope, creating a local handle and exiting
|
|
// the scope.
|
|
UNIT_TEST_CASE(EnterExitScope) {
|
|
TestIsolateScope __test_isolate__;
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
EXPECT(isolate != NULL);
|
|
ApiState* state = isolate->api_state();
|
|
EXPECT(state != NULL);
|
|
ApiLocalScope* scope = state->top_scope();
|
|
Dart_EnterScope();
|
|
{
|
|
EXPECT(state->top_scope() != NULL);
|
|
DARTSCOPE_NOCHECKS(isolate);
|
|
const String& str1 = String::Handle(String::New("Test String"));
|
|
Dart_Handle ref = Api::NewLocalHandle(str1);
|
|
String& str2 = String::Handle();
|
|
str2 ^= Api::UnwrapHandle(ref);
|
|
EXPECT(str1.Equals(str2));
|
|
}
|
|
Dart_ExitScope();
|
|
EXPECT(scope == state->top_scope());
|
|
}
|
|
|
|
|
|
// Unit test for creating and deleting persistent handles.
|
|
UNIT_TEST_CASE(PersistentHandles) {
|
|
const char* kTestString1 = "Test String1";
|
|
const char* kTestString2 = "Test String2";
|
|
TestCase::CreateTestIsolate();
|
|
Isolate* isolate = Isolate::Current();
|
|
EXPECT(isolate != NULL);
|
|
ApiState* state = isolate->api_state();
|
|
EXPECT(state != NULL);
|
|
ApiLocalScope* scope = state->top_scope();
|
|
Dart_Handle handles[2000];
|
|
Dart_EnterScope();
|
|
{
|
|
DARTSCOPE_NOCHECKS(isolate);
|
|
const String& str1 = String::Handle(String::New(kTestString1));
|
|
Dart_Handle ref1 = Api::NewLocalHandle(str1);
|
|
for (int i = 0; i < 1000; i++) {
|
|
handles[i] = Dart_NewPersistentHandle(ref1);
|
|
}
|
|
Dart_EnterScope();
|
|
const String& str2 = String::Handle(String::New(kTestString2));
|
|
Dart_Handle ref2 = Api::NewLocalHandle(str2);
|
|
for (int i = 1000; i < 2000; i++) {
|
|
handles[i] = Dart_NewPersistentHandle(ref2);
|
|
}
|
|
for (int i = 500; i < 1500; i++) {
|
|
Dart_DeletePersistentHandle(handles[i]);
|
|
}
|
|
for (int i = 500; i < 1000; i++) {
|
|
handles[i] = Dart_NewPersistentHandle(ref2);
|
|
}
|
|
for (int i = 1000; i < 1500; i++) {
|
|
handles[i] = Dart_NewPersistentHandle(ref1);
|
|
}
|
|
VERIFY_ON_TRANSITION;
|
|
Dart_ExitScope();
|
|
}
|
|
Dart_ExitScope();
|
|
{
|
|
DARTSCOPE_NOCHECKS(isolate);
|
|
for (int i = 0; i < 500; i++) {
|
|
String& str = String::Handle();
|
|
str ^= Api::UnwrapHandle(handles[i]);
|
|
EXPECT(str.Equals(kTestString1));
|
|
}
|
|
for (int i = 500; i < 1000; i++) {
|
|
String& str = String::Handle();
|
|
str ^= Api::UnwrapHandle(handles[i]);
|
|
EXPECT(str.Equals(kTestString2));
|
|
}
|
|
for (int i = 1000; i < 1500; i++) {
|
|
String& str = String::Handle();
|
|
str ^= Api::UnwrapHandle(handles[i]);
|
|
EXPECT(str.Equals(kTestString1));
|
|
}
|
|
for (int i = 1500; i < 2000; i++) {
|
|
String& str = String::Handle();
|
|
str ^= Api::UnwrapHandle(handles[i]);
|
|
EXPECT(str.Equals(kTestString2));
|
|
}
|
|
}
|
|
EXPECT(scope == state->top_scope());
|
|
EXPECT_EQ(2000, state->CountPersistentHandles());
|
|
Dart_ShutdownIsolate();
|
|
}
|
|
|
|
|
|
// Test that we are able to create a persistent handle from a
|
|
// persistent handle.
|
|
UNIT_TEST_CASE(NewPersistentHandle_FromPersistentHandle) {
|
|
TestIsolateScope __test_isolate__;
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
EXPECT(isolate != NULL);
|
|
ApiState* state = isolate->api_state();
|
|
EXPECT(state != NULL);
|
|
|
|
// Start with a known persistent handle.
|
|
Dart_Handle obj1 = Dart_True();
|
|
EXPECT(state->IsValidPersistentHandle(obj1));
|
|
|
|
// And use it to allocate a second persistent handle.
|
|
Dart_Handle obj2 = Dart_NewPersistentHandle(obj1);
|
|
EXPECT(state->IsValidPersistentHandle(obj2));
|
|
|
|
// Make sure that the value transferred.
|
|
EXPECT(Dart_IsBoolean(obj2));
|
|
bool value = false;
|
|
Dart_Handle result = Dart_BooleanValue(obj2, &value);
|
|
EXPECT_VALID(result);
|
|
EXPECT(value);
|
|
}
|
|
|
|
|
|
// Only ia32 and x64 can run execution tests.
|
|
#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
|
|
|
|
TEST_CASE(WeakPersistentHandle) {
|
|
Dart_Handle weak_new_ref = Dart_Null();
|
|
EXPECT(Dart_IsNull(weak_new_ref));
|
|
|
|
Dart_Handle weak_old_ref = Dart_Null();
|
|
EXPECT(Dart_IsNull(weak_old_ref));
|
|
|
|
bool is_same;
|
|
|
|
{
|
|
Dart_EnterScope();
|
|
|
|
// create an object in new space
|
|
Dart_Handle new_ref = Dart_NewString("new string");
|
|
EXPECT_VALID(new_ref);
|
|
|
|
// create an object in old space
|
|
Dart_Handle old_ref;
|
|
{
|
|
DARTSCOPE(Isolate::Current());
|
|
const String& str =
|
|
String::Handle(String::New("old string", Heap::kOld));
|
|
old_ref = Api::NewLocalHandle(str);
|
|
EXPECT_VALID(old_ref);
|
|
}
|
|
|
|
// create a weak ref to the new space object
|
|
weak_new_ref = Dart_NewWeakPersistentHandle(new_ref, NULL, NULL);
|
|
EXPECT_VALID(weak_new_ref);
|
|
EXPECT(!Dart_IsNull(weak_new_ref));
|
|
|
|
// create a weak ref to the old space object
|
|
weak_old_ref = Dart_NewWeakPersistentHandle(old_ref, NULL, NULL);
|
|
EXPECT_VALID(weak_old_ref);
|
|
EXPECT(!Dart_IsNull(weak_old_ref));
|
|
|
|
// garbage collect new space
|
|
Isolate::Current()->heap()->CollectGarbage(Heap::kNew);
|
|
|
|
// nothing should be invalidated or cleared
|
|
EXPECT_VALID(new_ref);
|
|
EXPECT(!Dart_IsNull(new_ref));
|
|
EXPECT_VALID(old_ref);
|
|
EXPECT(!Dart_IsNull(old_ref));
|
|
|
|
EXPECT_VALID(weak_new_ref);
|
|
EXPECT(!Dart_IsNull(weak_new_ref));
|
|
is_same = false;
|
|
EXPECT_VALID(Dart_IsSame(new_ref, weak_new_ref, &is_same));
|
|
EXPECT(is_same);
|
|
|
|
EXPECT_VALID(weak_old_ref);
|
|
EXPECT(!Dart_IsNull(weak_old_ref));
|
|
is_same = false;
|
|
EXPECT_VALID(Dart_IsSame(old_ref, weak_old_ref, &is_same));
|
|
EXPECT(is_same);
|
|
|
|
// garbage collect old space
|
|
Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
|
|
|
|
// nothing should be invalidated or cleared
|
|
EXPECT_VALID(new_ref);
|
|
EXPECT(!Dart_IsNull(new_ref));
|
|
EXPECT_VALID(old_ref);
|
|
EXPECT(!Dart_IsNull(old_ref));
|
|
|
|
EXPECT_VALID(weak_new_ref);
|
|
EXPECT(!Dart_IsNull(weak_new_ref));
|
|
is_same = false;
|
|
EXPECT_VALID(Dart_IsSame(new_ref, weak_new_ref, &is_same));
|
|
EXPECT(is_same);
|
|
|
|
EXPECT_VALID(weak_old_ref);
|
|
EXPECT(!Dart_IsNull(weak_old_ref));
|
|
is_same = false;
|
|
EXPECT_VALID(Dart_IsSame(old_ref, weak_old_ref, &is_same));
|
|
EXPECT(is_same);
|
|
|
|
// delete local (strong) references
|
|
Dart_ExitScope();
|
|
}
|
|
|
|
// garbage collect new space again
|
|
Isolate::Current()->heap()->CollectGarbage(Heap::kNew);
|
|
|
|
// weak ref to new space object should now be cleared
|
|
EXPECT_VALID(weak_new_ref);
|
|
EXPECT(Dart_IsNull(weak_new_ref));
|
|
EXPECT_VALID(weak_old_ref);
|
|
EXPECT(!Dart_IsNull(weak_old_ref));
|
|
|
|
// garbage collect old space again
|
|
Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
|
|
|
|
// weak ref to old space object should now be cleared
|
|
EXPECT_VALID(weak_new_ref);
|
|
EXPECT(Dart_IsNull(weak_new_ref));
|
|
EXPECT_VALID(weak_old_ref);
|
|
EXPECT(Dart_IsNull(weak_old_ref));
|
|
|
|
Dart_DeletePersistentHandle(weak_new_ref);
|
|
Dart_DeletePersistentHandle(weak_old_ref);
|
|
}
|
|
|
|
|
|
static void WeakPersistentHandlePeerFinalizer(Dart_Handle handle, void* peer) {
|
|
*static_cast<int*>(peer) = 42;
|
|
}
|
|
|
|
|
|
TEST_CASE(WeakPersistentHandleCallback) {
|
|
Dart_Handle weak_ref = Dart_Null();
|
|
EXPECT(Dart_IsNull(weak_ref));
|
|
int* peer = new int();
|
|
{
|
|
Dart_EnterScope();
|
|
Dart_Handle obj = Dart_NewString("new string");
|
|
EXPECT_VALID(obj);
|
|
weak_ref = Dart_NewWeakPersistentHandle(obj, peer,
|
|
WeakPersistentHandlePeerFinalizer);
|
|
Dart_ExitScope();
|
|
}
|
|
EXPECT_VALID(weak_ref);
|
|
EXPECT(*peer == 0);
|
|
Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
|
|
EXPECT(*peer == 0);
|
|
Isolate::Current()->heap()->CollectGarbage(Heap::kNew);
|
|
EXPECT(*peer == 42);
|
|
delete peer;
|
|
Dart_DeletePersistentHandle(weak_ref);
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
// Unit test for creating multiple scopes and local handles within them.
|
|
// Ensure that the local handles get all cleaned out when exiting the
|
|
// scope.
|
|
UNIT_TEST_CASE(LocalHandles) {
|
|
TestCase::CreateTestIsolate();
|
|
Isolate* isolate = Isolate::Current();
|
|
EXPECT(isolate != NULL);
|
|
ApiState* state = isolate->api_state();
|
|
EXPECT(state != NULL);
|
|
ApiLocalScope* scope = state->top_scope();
|
|
Dart_Handle handles[300];
|
|
{
|
|
DARTSCOPE_NOCHECKS(isolate);
|
|
Smi& val = Smi::Handle();
|
|
|
|
// Start a new scope and allocate some local handles.
|
|
Dart_EnterScope();
|
|
for (int i = 0; i < 100; i++) {
|
|
val ^= Smi::New(i);
|
|
handles[i] = Api::NewLocalHandle(val);
|
|
}
|
|
EXPECT_EQ(100, state->CountLocalHandles());
|
|
for (int i = 0; i < 100; i++) {
|
|
val ^= Api::UnwrapHandle(handles[i]);
|
|
EXPECT_EQ(i, val.Value());
|
|
}
|
|
// Start another scope and allocate some more local handles.
|
|
{
|
|
Dart_EnterScope();
|
|
for (int i = 100; i < 200; i++) {
|
|
val ^= Smi::New(i);
|
|
handles[i] = Api::NewLocalHandle(val);
|
|
}
|
|
EXPECT_EQ(200, state->CountLocalHandles());
|
|
for (int i = 100; i < 200; i++) {
|
|
val ^= Api::UnwrapHandle(handles[i]);
|
|
EXPECT_EQ(i, val.Value());
|
|
}
|
|
|
|
// Start another scope and allocate some more local handles.
|
|
{
|
|
Dart_EnterScope();
|
|
for (int i = 200; i < 300; i++) {
|
|
val ^= Smi::New(i);
|
|
handles[i] = Api::NewLocalHandle(val);
|
|
}
|
|
EXPECT_EQ(300, state->CountLocalHandles());
|
|
for (int i = 200; i < 300; i++) {
|
|
val ^= Api::UnwrapHandle(handles[i]);
|
|
EXPECT_EQ(i, val.Value());
|
|
}
|
|
EXPECT_EQ(300, state->CountLocalHandles());
|
|
VERIFY_ON_TRANSITION;
|
|
Dart_ExitScope();
|
|
}
|
|
EXPECT_EQ(200, state->CountLocalHandles());
|
|
Dart_ExitScope();
|
|
}
|
|
EXPECT_EQ(100, state->CountLocalHandles());
|
|
Dart_ExitScope();
|
|
}
|
|
EXPECT_EQ(0, state->CountLocalHandles());
|
|
EXPECT(scope == state->top_scope());
|
|
Dart_ShutdownIsolate();
|
|
}
|
|
|
|
|
|
// Unit test for creating multiple scopes and allocating objects in the
|
|
// zone for the scope. Ensure that the memory is freed when the scope
|
|
// exits.
|
|
UNIT_TEST_CASE(LocalZoneMemory) {
|
|
TestCase::CreateTestIsolate();
|
|
Isolate* isolate = Isolate::Current();
|
|
EXPECT(isolate != NULL);
|
|
ApiState* state = isolate->api_state();
|
|
EXPECT(state != NULL);
|
|
ApiLocalScope* scope = state->top_scope();
|
|
{
|
|
// Start a new scope and allocate some memory.
|
|
Dart_EnterScope();
|
|
for (int i = 0; i < 100; i++) {
|
|
Api::Allocate(16);
|
|
}
|
|
EXPECT_EQ(1600, state->ZoneSizeInBytes());
|
|
// Start another scope and allocate some more memory.
|
|
{
|
|
Dart_EnterScope();
|
|
for (int i = 0; i < 100; i++) {
|
|
Api::Allocate(16);
|
|
}
|
|
EXPECT_EQ(3200, state->ZoneSizeInBytes());
|
|
{
|
|
// Start another scope and allocate some more memory.
|
|
{
|
|
Dart_EnterScope();
|
|
for (int i = 0; i < 200; i++) {
|
|
Api::Allocate(16);
|
|
}
|
|
EXPECT_EQ(6400, state->ZoneSizeInBytes());
|
|
Dart_ExitScope();
|
|
}
|
|
}
|
|
EXPECT_EQ(3200, state->ZoneSizeInBytes());
|
|
Dart_ExitScope();
|
|
}
|
|
EXPECT_EQ(1600, state->ZoneSizeInBytes());
|
|
Dart_ExitScope();
|
|
}
|
|
EXPECT_EQ(0, state->ZoneSizeInBytes());
|
|
EXPECT(scope == state->top_scope());
|
|
Dart_ShutdownIsolate();
|
|
}
|
|
|
|
|
|
UNIT_TEST_CASE(Isolates) {
|
|
// This test currently assumes that the Dart_Isolate type is an opaque
|
|
// representation of Isolate*.
|
|
Dart_Isolate iso_1 = TestCase::CreateTestIsolate();
|
|
EXPECT_EQ(iso_1, Api::CastIsolate(Isolate::Current()));
|
|
Dart_Isolate isolate = Dart_CurrentIsolate();
|
|
EXPECT_EQ(iso_1, isolate);
|
|
Dart_ExitIsolate();
|
|
EXPECT(NULL == Dart_CurrentIsolate());
|
|
Dart_Isolate iso_2 = TestCase::CreateTestIsolate();
|
|
EXPECT_EQ(iso_2, Dart_CurrentIsolate());
|
|
Dart_ExitIsolate();
|
|
EXPECT(NULL == Dart_CurrentIsolate());
|
|
Dart_EnterIsolate(iso_2);
|
|
EXPECT_EQ(iso_2, Dart_CurrentIsolate());
|
|
Dart_ShutdownIsolate();
|
|
EXPECT(NULL == Dart_CurrentIsolate());
|
|
Dart_EnterIsolate(iso_1);
|
|
EXPECT_EQ(iso_1, Dart_CurrentIsolate());
|
|
Dart_ShutdownIsolate();
|
|
EXPECT(NULL == Dart_CurrentIsolate());
|
|
}
|
|
|
|
|
|
static void MyMessageNotifyCallback(Dart_Isolate dest_isolate) {
|
|
}
|
|
|
|
|
|
UNIT_TEST_CASE(SetMessageCallbacks) {
|
|
Dart_Isolate dart_isolate = TestCase::CreateTestIsolate();
|
|
Dart_SetMessageNotifyCallback(&MyMessageNotifyCallback);
|
|
Isolate* isolate = reinterpret_cast<Isolate*>(dart_isolate);
|
|
EXPECT_EQ(&MyMessageNotifyCallback, isolate->message_notify_callback());
|
|
Dart_ShutdownIsolate();
|
|
}
|
|
|
|
|
|
// Only ia32 and x64 can run execution tests.
|
|
#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
|
|
|
|
TEST_CASE(FieldAccess) {
|
|
const char* kScriptChars =
|
|
"class Fields {\n"
|
|
" Fields(int i, int j) : fld1 = i, fld2 = j {}\n"
|
|
" int fld1;\n"
|
|
" final int fld2;\n"
|
|
" static int fld3;\n"
|
|
" static final int fld4 = 10;\n"
|
|
"}\n"
|
|
"class FieldsTest {\n"
|
|
" static Fields testMain() {\n"
|
|
" Fields obj = new Fields(10, 20);\n"
|
|
" return obj;\n"
|
|
" }\n"
|
|
"}\n";
|
|
Dart_Handle result;
|
|
// Create a test library and Load up a test script in it.
|
|
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
|
|
|
// Invoke a function which returns an object.
|
|
Dart_Handle retobj = Dart_InvokeStatic(lib,
|
|
Dart_NewString("FieldsTest"),
|
|
Dart_NewString("testMain"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(retobj);
|
|
|
|
// Now access and set various static fields of Fields class.
|
|
Dart_Handle cls = Dart_GetClass(lib, Dart_NewString("Fields"));
|
|
EXPECT_VALID(cls);
|
|
result = Dart_GetStaticField(cls, Dart_NewString("fld1"));
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_GetInstanceField(retobj, Dart_NewString("fld3"));
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_GetStaticField(cls, Dart_NewString("fld4"));
|
|
EXPECT_VALID(result);
|
|
int64_t value = 0;
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_EQ(10, value);
|
|
result = Dart_SetStaticField(cls,
|
|
Dart_NewString("fld4"),
|
|
Dart_NewInteger(20));
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_GetStaticField(cls, Dart_NewString("fld3"));
|
|
EXPECT_VALID(result);
|
|
result = Dart_SetStaticField(cls,
|
|
Dart_NewString("fld3"),
|
|
Dart_NewInteger(200));
|
|
EXPECT_VALID(result);
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_EQ(200, value);
|
|
|
|
// Now access and set various instance fields of the returned object.
|
|
result = Dart_GetInstanceField(retobj, Dart_NewString("fld3"));
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_GetInstanceField(retobj, Dart_NewString("fld1"));
|
|
EXPECT_VALID(result);
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_EQ(10, value);
|
|
result = Dart_GetInstanceField(retobj, Dart_NewString("fld2"));
|
|
EXPECT_VALID(result);
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_EQ(20, value);
|
|
result = Dart_SetInstanceField(retobj,
|
|
Dart_NewString("fld2"),
|
|
Dart_NewInteger(40));
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_SetInstanceField(retobj,
|
|
Dart_NewString("fld1"),
|
|
Dart_NewInteger(40));
|
|
EXPECT_VALID(result);
|
|
result = Dart_GetInstanceField(retobj, Dart_NewString("fld1"));
|
|
EXPECT_VALID(result);
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_EQ(40, value);
|
|
}
|
|
|
|
|
|
TEST_CASE(HiddenFieldAccess) {
|
|
const char* kScriptChars =
|
|
"class HiddenFields {\n"
|
|
" HiddenFields(int i, int j) : _fld1 = i, _fld2 = j {}\n"
|
|
" int _fld1;\n"
|
|
" final int _fld2;\n"
|
|
" static int _fld3;\n"
|
|
" static final int _fld4 = 10;\n"
|
|
"}\n"
|
|
"class HiddenFieldsTest {\n"
|
|
" static HiddenFields testMain() {\n"
|
|
" HiddenFields obj = new HiddenFields(10, 20);\n"
|
|
" return obj;\n"
|
|
" }\n"
|
|
"}\n";
|
|
Dart_Handle result;
|
|
// Load up a test script which extends the native wrapper class.
|
|
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
|
|
|
// Invoke a function which returns an object.
|
|
Dart_Handle retobj = Dart_InvokeStatic(lib,
|
|
Dart_NewString("HiddenFieldsTest"),
|
|
Dart_NewString("testMain"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(retobj);
|
|
|
|
// Now access and set various static fields of HiddenFields class.
|
|
Dart_Handle cls = Dart_GetClass(lib, Dart_NewString("HiddenFields"));
|
|
EXPECT_VALID(cls);
|
|
result = Dart_GetStaticField(cls, Dart_NewString("_fld1"));
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_GetInstanceField(retobj, Dart_NewString("_fld3"));
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_GetStaticField(cls, Dart_NewString("_fld4"));
|
|
EXPECT_VALID(result);
|
|
int64_t value = 0;
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_EQ(10, value);
|
|
result = Dart_SetStaticField(cls,
|
|
Dart_NewString("_fld4"),
|
|
Dart_NewInteger(20));
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_GetStaticField(cls, Dart_NewString("_fld3"));
|
|
EXPECT_VALID(result);
|
|
result = Dart_SetStaticField(cls,
|
|
Dart_NewString("_fld3"),
|
|
Dart_NewInteger(200));
|
|
EXPECT_VALID(result);
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_EQ(200, value);
|
|
|
|
// Now access and set various instance fields of the returned object.
|
|
result = Dart_GetInstanceField(retobj, Dart_NewString("_fld3"));
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_GetInstanceField(retobj, Dart_NewString("_fld1"));
|
|
EXPECT_VALID(result);
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_EQ(10, value);
|
|
result = Dart_GetInstanceField(retobj, Dart_NewString("_fld2"));
|
|
EXPECT_VALID(result);
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_EQ(20, value);
|
|
result = Dart_SetInstanceField(retobj,
|
|
Dart_NewString("_fld2"),
|
|
Dart_NewInteger(40));
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_SetInstanceField(retobj,
|
|
Dart_NewString("_fld1"),
|
|
Dart_NewInteger(40));
|
|
EXPECT_VALID(result);
|
|
result = Dart_GetInstanceField(retobj, Dart_NewString("_fld1"));
|
|
EXPECT_VALID(result);
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_EQ(40, value);
|
|
}
|
|
|
|
|
|
void NativeFieldLookup(Dart_NativeArguments args) {
|
|
UNREACHABLE();
|
|
}
|
|
|
|
|
|
static Dart_NativeFunction native_field_lookup(Dart_Handle name,
|
|
int argument_count) {
|
|
return reinterpret_cast<Dart_NativeFunction>(&NativeFieldLookup);
|
|
}
|
|
|
|
|
|
TEST_CASE(InjectNativeFields1) {
|
|
const char* kScriptChars =
|
|
"class NativeFields extends NativeFieldsWrapper {\n"
|
|
" NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
|
|
" int fld1;\n"
|
|
" final int fld2;\n"
|
|
" static int fld3;\n"
|
|
" static final int fld4 = 10;\n"
|
|
"}\n"
|
|
"class NativeFieldsTest {\n"
|
|
" static NativeFields testMain() {\n"
|
|
" NativeFields obj = new NativeFields(10, 20);\n"
|
|
" return obj;\n"
|
|
" }\n"
|
|
"}\n";
|
|
Dart_Handle result;
|
|
|
|
const int kNumNativeFields = 4;
|
|
|
|
// Create a test library.
|
|
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars,
|
|
native_field_lookup);
|
|
|
|
// Create a native wrapper class with native fields.
|
|
result = Dart_CreateNativeWrapperClass(
|
|
lib,
|
|
Dart_NewString("NativeFieldsWrapper"),
|
|
kNumNativeFields);
|
|
|
|
// Load up a test script in the test library.
|
|
|
|
// Invoke a function which returns an object of type NativeFields.
|
|
result = Dart_InvokeStatic(lib,
|
|
Dart_NewString("NativeFieldsTest"),
|
|
Dart_NewString("testMain"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(result);
|
|
DARTSCOPE_NOCHECKS(Isolate::Current());
|
|
Instance& obj = Instance::Handle();
|
|
obj ^= Api::UnwrapHandle(result);
|
|
const Class& cls = Class::Handle(obj.clazz());
|
|
// We expect the newly created "NativeFields" object to have
|
|
// 2 dart instance fields (fld1, fld2) and kNumNativeFields native fields.
|
|
// Hence the size of an instance of "NativeFields" should be
|
|
// (kNumNativeFields + 2) * kWordSize + size of object header.
|
|
// We check to make sure the instance size computed by the VM matches
|
|
// our expectations.
|
|
intptr_t header_size = sizeof(RawObject);
|
|
EXPECT_EQ(Utils::RoundUp(((kNumNativeFields + 2) * kWordSize) + header_size,
|
|
kObjectAlignment),
|
|
cls.instance_size());
|
|
}
|
|
|
|
|
|
TEST_CASE(InjectNativeFields2) {
|
|
const char* kScriptChars =
|
|
"class NativeFields extends NativeFieldsWrapper {\n"
|
|
" NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
|
|
" int fld1;\n"
|
|
" final int fld2;\n"
|
|
" static int fld3;\n"
|
|
" static final int fld4 = 10;\n"
|
|
"}\n"
|
|
"class NativeFieldsTest {\n"
|
|
" static NativeFields testMain() {\n"
|
|
" NativeFields obj = new NativeFields(10, 20);\n"
|
|
" return obj;\n"
|
|
" }\n"
|
|
"}\n";
|
|
Dart_Handle result;
|
|
// Create a test library and Load up a test script in it.
|
|
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
|
|
|
// Invoke a function which returns an object of type NativeFields.
|
|
result = Dart_InvokeStatic(lib,
|
|
Dart_NewString("NativeFieldsTest"),
|
|
Dart_NewString("testMain"),
|
|
0,
|
|
NULL);
|
|
// We expect this to fail as class "NativeFields" extends
|
|
// "NativeFieldsWrapper" and there is no definition of it either
|
|
// in the dart code or through the native field injection mechanism.
|
|
EXPECT(Dart_IsError(result));
|
|
}
|
|
|
|
|
|
TEST_CASE(InjectNativeFields3) {
|
|
const char* kScriptChars =
|
|
"#import('dart:nativewrappers');"
|
|
"class NativeFields extends NativeFieldWrapperClass2 {\n"
|
|
" NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
|
|
" int fld1;\n"
|
|
" final int fld2;\n"
|
|
" static int fld3;\n"
|
|
" static final int fld4 = 10;\n"
|
|
"}\n"
|
|
"class NativeFieldsTest {\n"
|
|
" static NativeFields testMain() {\n"
|
|
" NativeFields obj = new NativeFields(10, 20);\n"
|
|
" return obj;\n"
|
|
" }\n"
|
|
"}\n";
|
|
Dart_Handle result;
|
|
const int kNumNativeFields = 2;
|
|
|
|
// Load up a test script in the test library.
|
|
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars,
|
|
native_field_lookup);
|
|
|
|
// Invoke a function which returns an object of type NativeFields.
|
|
result = Dart_InvokeStatic(lib,
|
|
Dart_NewString("NativeFieldsTest"),
|
|
Dart_NewString("testMain"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(result);
|
|
DARTSCOPE_NOCHECKS(Isolate::Current());
|
|
Instance& obj = Instance::Handle();
|
|
obj ^= Api::UnwrapHandle(result);
|
|
const Class& cls = Class::Handle(obj.clazz());
|
|
// We expect the newly created "NativeFields" object to have
|
|
// 2 dart instance fields (fld1, fld2) and kNumNativeFields native fields.
|
|
// Hence the size of an instance of "NativeFields" should be
|
|
// (kNumNativeFields + 2) * kWordSize + size of object header.
|
|
// We check to make sure the instance size computed by the VM matches
|
|
// our expectations.
|
|
intptr_t header_size = sizeof(RawObject);
|
|
EXPECT_EQ(Utils::RoundUp(((kNumNativeFields + 2) * kWordSize) + header_size,
|
|
kObjectAlignment),
|
|
cls.instance_size());
|
|
}
|
|
|
|
|
|
TEST_CASE(InjectNativeFields4) {
|
|
const char* kScriptChars =
|
|
"#import('dart:nativewrappers');"
|
|
"class NativeFields extends NativeFieldWrapperClass2 {\n"
|
|
" NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
|
|
" int fld1;\n"
|
|
" final int fld2;\n"
|
|
" static int fld3;\n"
|
|
" static final int fld4 = 10;\n"
|
|
"}\n"
|
|
"class NativeFieldsTest {\n"
|
|
" static NativeFields testMain() {\n"
|
|
" NativeFields obj = new NativeFields(10, 20);\n"
|
|
" return obj;\n"
|
|
" }\n"
|
|
"}\n";
|
|
Dart_Handle result;
|
|
// Load up a test script in the test library.
|
|
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
|
|
|
// Invoke a function which returns an object of type NativeFields.
|
|
result = Dart_InvokeStatic(lib,
|
|
Dart_NewString("NativeFieldsTest"),
|
|
Dart_NewString("testMain"),
|
|
0,
|
|
NULL);
|
|
// We expect the test script to fail finalization with the error below:
|
|
EXPECT(Dart_IsError(result));
|
|
Dart_Handle expected_error = Dart_Error(
|
|
"'dart:test-lib': Error: line 1 pos 38: "
|
|
"class 'NativeFields' is trying to extend a native fields class, "
|
|
"but library '%s' has no native resolvers",
|
|
TestCase::url());
|
|
EXPECT_SUBSTRING(Dart_GetError(expected_error), Dart_GetError(result));
|
|
}
|
|
|
|
|
|
static void TestNativeFields(Dart_Handle retobj) {
|
|
// Access and set various instance fields of the object.
|
|
Dart_Handle result = Dart_GetInstanceField(retobj, Dart_NewString("fld3"));
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_GetInstanceField(retobj, Dart_NewString("fld0"));
|
|
EXPECT_VALID(result);
|
|
EXPECT(Dart_IsNull(result));
|
|
result = Dart_GetInstanceField(retobj, Dart_NewString("fld1"));
|
|
EXPECT_VALID(result);
|
|
int64_t value = 0;
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_EQ(10, value);
|
|
result = Dart_GetInstanceField(retobj, Dart_NewString("fld2"));
|
|
EXPECT_VALID(result);
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_EQ(20, value);
|
|
result = Dart_SetInstanceField(retobj,
|
|
Dart_NewString("fld2"),
|
|
Dart_NewInteger(40));
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_SetInstanceField(retobj,
|
|
Dart_NewString("fld1"),
|
|
Dart_NewInteger(40));
|
|
EXPECT_VALID(result);
|
|
result = Dart_GetInstanceField(retobj, Dart_NewString("fld1"));
|
|
EXPECT_VALID(result);
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_EQ(40, value);
|
|
|
|
// Now access and set various native instance fields of the returned object.
|
|
const int kNativeFld0 = 0;
|
|
const int kNativeFld1 = 1;
|
|
const int kNativeFld2 = 2;
|
|
const int kNativeFld3 = 3;
|
|
const int kNativeFld4 = 4;
|
|
intptr_t field_value = 0;
|
|
result = Dart_GetNativeInstanceField(retobj, kNativeFld4, &field_value);
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_GetNativeInstanceField(retobj, kNativeFld0, &field_value);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(0, field_value);
|
|
result = Dart_GetNativeInstanceField(retobj, kNativeFld1, &field_value);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(0, field_value);
|
|
result = Dart_GetNativeInstanceField(retobj, kNativeFld2, &field_value);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(0, field_value);
|
|
result = Dart_GetNativeInstanceField(retobj, kNativeFld3, &field_value);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(0, field_value);
|
|
result = Dart_SetNativeInstanceField(retobj, kNativeFld4, 40);
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_SetNativeInstanceField(retobj, kNativeFld0, 4);
|
|
EXPECT_VALID(result);
|
|
result = Dart_SetNativeInstanceField(retobj, kNativeFld1, 40);
|
|
EXPECT_VALID(result);
|
|
result = Dart_SetNativeInstanceField(retobj, kNativeFld2, 400);
|
|
EXPECT_VALID(result);
|
|
result = Dart_SetNativeInstanceField(retobj, kNativeFld3, 4000);
|
|
EXPECT_VALID(result);
|
|
result = Dart_GetNativeInstanceField(retobj, kNativeFld3, &field_value);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(4000, field_value);
|
|
|
|
// Now re-access various dart instance fields of the returned object
|
|
// to ensure that there was no corruption while setting native fields.
|
|
result = Dart_GetInstanceField(retobj, Dart_NewString("fld1"));
|
|
EXPECT_VALID(result);
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_EQ(40, value);
|
|
result = Dart_GetInstanceField(retobj, Dart_NewString("fld2"));
|
|
EXPECT_VALID(result);
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_EQ(20, value);
|
|
}
|
|
|
|
|
|
TEST_CASE(NativeFieldAccess) {
|
|
const char* kScriptChars =
|
|
"class NativeFields extends NativeFieldsWrapper {\n"
|
|
" NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
|
|
" int fld0;\n"
|
|
" int fld1;\n"
|
|
" final int fld2;\n"
|
|
" static int fld3;\n"
|
|
" static final int fld4 = 10;\n"
|
|
"}\n"
|
|
"class NativeFieldsTest {\n"
|
|
" static NativeFields testMain() {\n"
|
|
" NativeFields obj = new NativeFields(10, 20);\n"
|
|
" return obj;\n"
|
|
" }\n"
|
|
"}\n";
|
|
Dart_Handle result;
|
|
const int kNumNativeFields = 4;
|
|
|
|
// Create a test library.
|
|
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars,
|
|
native_field_lookup);
|
|
|
|
// Create a native wrapper class with native fields.
|
|
result = Dart_CreateNativeWrapperClass(
|
|
lib,
|
|
Dart_NewString("NativeFieldsWrapper"),
|
|
kNumNativeFields);
|
|
|
|
// Load up a test script in it.
|
|
|
|
// Invoke a function which returns an object of type NativeFields.
|
|
Dart_Handle retobj = Dart_InvokeStatic(lib,
|
|
Dart_NewString("NativeFieldsTest"),
|
|
Dart_NewString("testMain"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(retobj);
|
|
|
|
// Now access and set various instance fields of the returned object.
|
|
TestNativeFields(retobj);
|
|
}
|
|
|
|
|
|
TEST_CASE(ImplicitNativeFieldAccess) {
|
|
const char* kScriptChars =
|
|
"#import('dart:nativewrappers');"
|
|
"class NativeFields extends NativeFieldWrapperClass4 {\n"
|
|
" NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
|
|
" int fld0;\n"
|
|
" int fld1;\n"
|
|
" final int fld2;\n"
|
|
" static int fld3;\n"
|
|
" static final int fld4 = 10;\n"
|
|
"}\n"
|
|
"class NativeFieldsTest {\n"
|
|
" static NativeFields testMain() {\n"
|
|
" NativeFields obj = new NativeFields(10, 20);\n"
|
|
" return obj;\n"
|
|
" }\n"
|
|
"}\n";
|
|
// Load up a test script in the test library.
|
|
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars,
|
|
native_field_lookup);
|
|
|
|
// Invoke a function which returns an object of type NativeFields.
|
|
Dart_Handle retobj = Dart_InvokeStatic(lib,
|
|
Dart_NewString("NativeFieldsTest"),
|
|
Dart_NewString("testMain"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(retobj);
|
|
|
|
// Now access and set various instance fields of the returned object.
|
|
TestNativeFields(retobj);
|
|
}
|
|
|
|
|
|
TEST_CASE(NegativeNativeFieldAccess) {
|
|
const char* kScriptChars =
|
|
"class NativeFields {\n"
|
|
" NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
|
|
" int fld1;\n"
|
|
" final int fld2;\n"
|
|
" static int fld3;\n"
|
|
" static final int fld4 = 10;\n"
|
|
"}\n"
|
|
"class NativeFieldsTest {\n"
|
|
" static NativeFields testMain1() {\n"
|
|
" NativeFields obj = new NativeFields(10, 20);\n"
|
|
" return obj;\n"
|
|
" }\n"
|
|
" static Function testMain2() {\n"
|
|
" return function() {};\n"
|
|
" }\n"
|
|
"}\n";
|
|
Dart_Handle result;
|
|
DARTSCOPE_NOCHECKS(Isolate::Current());
|
|
|
|
// Create a test library and Load up a test script in it.
|
|
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
|
|
|
// Invoke a function which returns an object of type NativeFields.
|
|
Dart_Handle retobj = Dart_InvokeStatic(lib,
|
|
Dart_NewString("NativeFieldsTest"),
|
|
Dart_NewString("testMain1"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(retobj);
|
|
|
|
// Now access and set various native instance fields of the returned object.
|
|
// All of these tests are expected to return failure as there are no
|
|
// native fields in an instance of NativeFields.
|
|
const int kNativeFld0 = 0;
|
|
const int kNativeFld1 = 1;
|
|
const int kNativeFld2 = 2;
|
|
const int kNativeFld3 = 3;
|
|
const int kNativeFld4 = 4;
|
|
intptr_t value = 0;
|
|
result = Dart_GetNativeInstanceField(retobj, kNativeFld4, &value);
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_GetNativeInstanceField(retobj, kNativeFld0, &value);
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_GetNativeInstanceField(retobj, kNativeFld1, &value);
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_GetNativeInstanceField(retobj, kNativeFld2, &value);
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_SetNativeInstanceField(retobj, kNativeFld4, 40);
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_SetNativeInstanceField(retobj, kNativeFld3, 40);
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_SetNativeInstanceField(retobj, kNativeFld0, 400);
|
|
EXPECT(Dart_IsError(result));
|
|
|
|
// Invoke a function which returns a closure object.
|
|
retobj = Dart_InvokeStatic(lib,
|
|
Dart_NewString("NativeFieldsTest"),
|
|
Dart_NewString("testMain2"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(retobj);
|
|
result = Dart_GetNativeInstanceField(retobj, kNativeFld4, &value);
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_GetNativeInstanceField(retobj, kNativeFld0, &value);
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_GetNativeInstanceField(retobj, kNativeFld1, &value);
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_GetNativeInstanceField(retobj, kNativeFld2, &value);
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_SetNativeInstanceField(retobj, kNativeFld4, 40);
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_SetNativeInstanceField(retobj, kNativeFld3, 40);
|
|
EXPECT(Dart_IsError(result));
|
|
result = Dart_SetNativeInstanceField(retobj, kNativeFld0, 400);
|
|
EXPECT(Dart_IsError(result));
|
|
}
|
|
|
|
|
|
TEST_CASE(GetStaticField_RunsInitializer) {
|
|
const char* kScriptChars =
|
|
"class TestClass {\n"
|
|
" static final int fld1 = 7;\n"
|
|
" static int fld2 = 11;\n"
|
|
" static void testMain() {\n"
|
|
" }\n"
|
|
"}\n";
|
|
Dart_Handle result;
|
|
// Create a test library and Load up a test script in it.
|
|
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
|
|
|
// Invoke a function which returns an object.
|
|
result = Dart_InvokeStatic(lib,
|
|
Dart_NewString("TestClass"),
|
|
Dart_NewString("testMain"),
|
|
0,
|
|
NULL);
|
|
|
|
Dart_Handle cls = Dart_GetClass(lib, Dart_NewString("TestClass"));
|
|
EXPECT_VALID(cls);
|
|
|
|
// For uninitialized fields, the getter is returned
|
|
result = Dart_GetStaticField(cls, Dart_NewString("fld1"));
|
|
EXPECT_VALID(result);
|
|
int64_t value = 0;
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_EQ(7, value);
|
|
|
|
result = Dart_GetStaticField(cls, Dart_NewString("fld2"));
|
|
EXPECT_VALID(result);
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_EQ(11, value);
|
|
|
|
// Overwrite fld2
|
|
result = Dart_SetStaticField(cls,
|
|
Dart_NewString("fld2"),
|
|
Dart_NewInteger(13));
|
|
EXPECT_VALID(result);
|
|
|
|
// We now get the new value for fld2, not the initializer
|
|
result = Dart_GetStaticField(cls, Dart_NewString("fld2"));
|
|
EXPECT_VALID(result);
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_EQ(13, value);
|
|
}
|
|
|
|
|
|
TEST_CASE(StaticFieldNotFound) {
|
|
const char* kScriptChars =
|
|
"class TestClass {\n"
|
|
" static void testMain() {\n"
|
|
" }\n"
|
|
"}\n";
|
|
Dart_Handle result;
|
|
// Create a test library and Load up a test script in it.
|
|
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
|
|
|
// Invoke a function.
|
|
result = Dart_InvokeStatic(lib,
|
|
Dart_NewString("TestClass"),
|
|
Dart_NewString("testMain"),
|
|
0,
|
|
NULL);
|
|
|
|
Dart_Handle cls = Dart_GetClass(lib, Dart_NewString("TestClass"));
|
|
EXPECT_VALID(cls);
|
|
|
|
result = Dart_GetStaticField(cls, Dart_NewString("not_found"));
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Specified field is not found in the class",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_SetStaticField(cls,
|
|
Dart_NewString("not_found"),
|
|
Dart_NewInteger(13));
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Specified field is not found in the class",
|
|
Dart_GetError(result));
|
|
}
|
|
|
|
|
|
TEST_CASE(InvokeDynamic) {
|
|
const char* kScriptChars =
|
|
"class InvokeDynamic {\n"
|
|
" InvokeDynamic(int i, int j) : fld1 = i, fld2 = j {}\n"
|
|
" int method1(int i) { return i + fld1 + fld2 + fld4; }\n"
|
|
" static int method2(int i) { return i + fld4; }\n"
|
|
" int fld1;\n"
|
|
" final int fld2;\n"
|
|
" static final int fld4 = 10;\n"
|
|
"}\n"
|
|
"class InvokeDynamicTest {\n"
|
|
" static InvokeDynamic testMain() {\n"
|
|
" InvokeDynamic obj = new InvokeDynamic(10, 20);\n"
|
|
" return obj;\n"
|
|
" }\n"
|
|
"}\n";
|
|
Dart_Handle result;
|
|
DARTSCOPE_NOCHECKS(Isolate::Current());
|
|
|
|
// Create a test library and Load up a test script in it.
|
|
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
|
|
|
// Invoke a function which returns an object of type InvokeDynamic.
|
|
Dart_Handle retobj = Dart_InvokeStatic(lib,
|
|
Dart_NewString("InvokeDynamicTest"),
|
|
Dart_NewString("testMain"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(retobj);
|
|
|
|
|
|
// Now invoke a dynamic method and check the result.
|
|
Dart_Handle dart_arguments[1];
|
|
dart_arguments[0] = Dart_NewInteger(1);
|
|
result = Dart_InvokeDynamic(retobj,
|
|
Dart_NewString("method1"),
|
|
1,
|
|
dart_arguments);
|
|
EXPECT_VALID(result);
|
|
EXPECT(Dart_IsInteger(result));
|
|
int64_t value = 0;
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_EQ(41, value);
|
|
|
|
result = Dart_InvokeDynamic(retobj, Dart_NewString("method2"), 0, NULL);
|
|
EXPECT(Dart_IsError(result));
|
|
|
|
result = Dart_InvokeDynamic(retobj, Dart_NewString("method1"), 0, NULL);
|
|
EXPECT(Dart_IsError(result));
|
|
}
|
|
|
|
|
|
TEST_CASE(InvokeClosure) {
|
|
const char* kScriptChars =
|
|
"class InvokeClosure {\n"
|
|
" InvokeClosure(int i, int j) : fld1 = i, fld2 = j {}\n"
|
|
" Function method1(int i) {\n"
|
|
" f(int j) => j + i + fld1 + fld2 + fld4; \n"
|
|
" return f;\n"
|
|
" }\n"
|
|
" static Function method2(int i) {\n"
|
|
" n(int j) => true + i + fld4; \n"
|
|
" return n;\n"
|
|
" }\n"
|
|
" int fld1;\n"
|
|
" final int fld2;\n"
|
|
" static final int fld4 = 10;\n"
|
|
"}\n"
|
|
"class InvokeClosureTest {\n"
|
|
" static Function testMain1() {\n"
|
|
" InvokeClosure obj = new InvokeClosure(10, 20);\n"
|
|
" return obj.method1(10);\n"
|
|
" }\n"
|
|
" static Function testMain2() {\n"
|
|
" return InvokeClosure.method2(10);\n"
|
|
" }\n"
|
|
"}\n";
|
|
Dart_Handle result;
|
|
DARTSCOPE_NOCHECKS(Isolate::Current());
|
|
|
|
// Create a test library and Load up a test script in it.
|
|
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
|
|
|
// Invoke a function which returns a closure.
|
|
Dart_Handle retobj = Dart_InvokeStatic(lib,
|
|
Dart_NewString("InvokeClosureTest"),
|
|
Dart_NewString("testMain1"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(retobj);
|
|
|
|
EXPECT(Dart_IsClosure(retobj));
|
|
EXPECT(!Dart_IsClosure(Dart_NewInteger(101)));
|
|
|
|
// Now invoke the closure and check the result.
|
|
Dart_Handle dart_arguments[1];
|
|
dart_arguments[0] = Dart_NewInteger(1);
|
|
result = Dart_InvokeClosure(retobj, 1, dart_arguments);
|
|
EXPECT_VALID(result);
|
|
EXPECT(Dart_IsInteger(result));
|
|
int64_t value = 0;
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_EQ(51, value);
|
|
|
|
// Invoke closure with wrong number of args, should result in exception.
|
|
result = Dart_InvokeClosure(retobj, 0, NULL);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT(Dart_ErrorHasException(result));
|
|
|
|
// Invoke a function which returns a closure.
|
|
retobj = Dart_InvokeStatic(lib,
|
|
Dart_NewString("InvokeClosureTest"),
|
|
Dart_NewString("testMain2"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(retobj);
|
|
|
|
EXPECT(Dart_IsClosure(retobj));
|
|
EXPECT(!Dart_IsClosure(Dart_NewString("abcdef")));
|
|
|
|
// Now invoke the closure and check the result (should be an exception).
|
|
dart_arguments[0] = Dart_NewInteger(1);
|
|
result = Dart_InvokeClosure(retobj, 1, dart_arguments);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT(Dart_ErrorHasException(result));
|
|
}
|
|
|
|
|
|
void ExceptionNative(Dart_NativeArguments args) {
|
|
Dart_Handle param = Dart_GetNativeArgument(args, 0);
|
|
Dart_EnterScope(); // Start a Dart API scope for invoking API functions.
|
|
char* str = reinterpret_cast<char*>(Api::Allocate(1024));
|
|
str[0] = 0;
|
|
Dart_ThrowException(param);
|
|
UNREACHABLE();
|
|
}
|
|
|
|
|
|
static Dart_NativeFunction native_lookup(Dart_Handle name, int argument_count) {
|
|
return reinterpret_cast<Dart_NativeFunction>(&ExceptionNative);
|
|
}
|
|
|
|
|
|
TEST_CASE(ThrowException) {
|
|
const char* kScriptChars =
|
|
"class ThrowException {\n"
|
|
" ThrowException(int i) : fld1 = i {}\n"
|
|
" int method1(int i) native \"ThrowException_native\";"
|
|
" int method2() {\n"
|
|
" try { method1(10); } catch(var a) { return 5; } return 10;\n"
|
|
" }\n"
|
|
" int fld1;\n"
|
|
"}\n"
|
|
"class ThrowExceptionTest {\n"
|
|
" static ThrowException testMain() {\n"
|
|
" ThrowException obj = new ThrowException(10);\n"
|
|
" return obj;\n"
|
|
" }\n"
|
|
"}\n";
|
|
Dart_Handle result;
|
|
Isolate* isolate = Isolate::Current();
|
|
EXPECT(isolate != NULL);
|
|
ApiState* state = isolate->api_state();
|
|
EXPECT(state != NULL);
|
|
intptr_t size = state->ZoneSizeInBytes();
|
|
Dart_EnterScope(); // Start a Dart API scope for invoking API functions.
|
|
|
|
// Load up a test script which extends the native wrapper class.
|
|
Dart_Handle lib = TestCase::LoadTestScript(
|
|
kScriptChars,
|
|
reinterpret_cast<Dart_NativeEntryResolver>(native_lookup));
|
|
|
|
// Invoke a function which returns an object of type ThrowException.
|
|
Dart_Handle retobj = Dart_InvokeStatic(lib,
|
|
Dart_NewString("ThrowExceptionTest"),
|
|
Dart_NewString("testMain"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(retobj);
|
|
|
|
// Throwing an exception here should result in an error.
|
|
result = Dart_ThrowException(retobj);
|
|
EXPECT(Dart_IsError(result));
|
|
|
|
// Now invoke method2 which invokes a natve method where it is
|
|
// ok to throw an exception, check the result which would indicate
|
|
// if an exception was thrown or not.
|
|
result = Dart_InvokeDynamic(retobj, Dart_NewString("method2"), 0, NULL);
|
|
EXPECT_VALID(result);
|
|
EXPECT(Dart_IsInteger(result));
|
|
int64_t value = 0;
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_EQ(5, value);
|
|
|
|
Dart_ExitScope(); // Exit the Dart API scope.
|
|
EXPECT_EQ(size, state->ZoneSizeInBytes());
|
|
}
|
|
|
|
|
|
void NativeArgumentCounter(Dart_NativeArguments args) {
|
|
Dart_EnterScope();
|
|
int count = Dart_GetNativeArgumentCount(args);
|
|
Dart_SetReturnValue(args, Dart_NewInteger(count));
|
|
Dart_ExitScope();
|
|
}
|
|
|
|
|
|
static Dart_NativeFunction gnac_lookup(Dart_Handle name, int argument_count) {
|
|
return reinterpret_cast<Dart_NativeFunction>(&NativeArgumentCounter);
|
|
}
|
|
|
|
|
|
TEST_CASE(GetNativeArgumentCount) {
|
|
const char* kScriptChars =
|
|
"class MyObject {"
|
|
" int method1(int i, int j) native 'Name_Does_Not_Matter';"
|
|
"}"
|
|
"class Test {"
|
|
" static testMain() {"
|
|
" MyObject obj = new MyObject();"
|
|
" return obj.method1(77, 125);"
|
|
" }"
|
|
"}";
|
|
|
|
Dart_Handle lib = TestCase::LoadTestScript(
|
|
kScriptChars,
|
|
reinterpret_cast<Dart_NativeEntryResolver>(gnac_lookup));
|
|
|
|
Dart_Handle result = Dart_InvokeStatic(lib,
|
|
Dart_NewString("Test"),
|
|
Dart_NewString("testMain"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(result);
|
|
EXPECT(Dart_IsInteger(result));
|
|
|
|
int64_t value = 0;
|
|
result = Dart_IntegerToInt64(result, &value);
|
|
EXPECT_VALID(result);
|
|
EXPECT_EQ(3, value);
|
|
}
|
|
|
|
|
|
TEST_CASE(GetClass) {
|
|
const char* kScriptChars =
|
|
"class DoesExist {"
|
|
"}";
|
|
|
|
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
|
|
|
// Lookup a class that does exist.
|
|
Dart_Handle cls = Dart_GetClass(lib, Dart_NewString("DoesExist"));
|
|
EXPECT_VALID(cls);
|
|
|
|
// Lookup a class that does not exist.
|
|
cls = Dart_GetClass(lib, Dart_NewString("DoesNotExist"));
|
|
EXPECT(Dart_IsError(cls));
|
|
EXPECT_STREQ("Class 'DoesNotExist' not found in library 'dart:test-lib'.",
|
|
Dart_GetError(cls));
|
|
}
|
|
|
|
|
|
TEST_CASE(InstanceOf) {
|
|
const char* kScriptChars =
|
|
"class OtherClass {\n"
|
|
" static returnNull() { return null; }\n"
|
|
"}\n"
|
|
"class InstanceOfTest {\n"
|
|
" InstanceOfTest() {}\n"
|
|
" static InstanceOfTest testMain() {\n"
|
|
" return new InstanceOfTest();\n"
|
|
" }\n"
|
|
"}\n";
|
|
Dart_Handle result;
|
|
// Create a test library and Load up a test script in it.
|
|
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
|
|
|
// Invoke a function which returns an object of type InstanceOf..
|
|
Dart_Handle instanceOfTestObj =
|
|
Dart_InvokeStatic(lib,
|
|
Dart_NewString("InstanceOfTest"),
|
|
Dart_NewString("testMain"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(instanceOfTestObj);
|
|
|
|
// Fetch InstanceOfTest class.
|
|
Dart_Handle cls = Dart_GetClass(lib, Dart_NewString("InstanceOfTest"));
|
|
EXPECT_VALID(cls);
|
|
|
|
// Now check instanceOfTestObj reported as an instance of
|
|
// InstanceOfTest class.
|
|
bool is_instance = false;
|
|
result = Dart_ObjectIsType(instanceOfTestObj, cls, &is_instance);
|
|
EXPECT_VALID(result);
|
|
EXPECT(is_instance);
|
|
|
|
// Fetch OtherClass and check if instanceOfTestObj is instance of it.
|
|
Dart_Handle otherClass = Dart_GetClass(lib, Dart_NewString("OtherClass"));
|
|
EXPECT_VALID(otherClass);
|
|
|
|
result = Dart_ObjectIsType(instanceOfTestObj, otherClass, &is_instance);
|
|
EXPECT_VALID(result);
|
|
EXPECT(!is_instance);
|
|
|
|
// Check that primitives are not instances of InstanceOfTest class.
|
|
result = Dart_ObjectIsType(Dart_NewString("a string"), otherClass,
|
|
&is_instance);
|
|
EXPECT_VALID(result);
|
|
EXPECT(!is_instance);
|
|
|
|
result = Dart_ObjectIsType(Dart_NewInteger(42), otherClass, &is_instance);
|
|
EXPECT_VALID(result);
|
|
EXPECT(!is_instance);
|
|
|
|
result = Dart_ObjectIsType(Dart_NewBoolean(true), otherClass, &is_instance);
|
|
EXPECT_VALID(result);
|
|
EXPECT(!is_instance);
|
|
|
|
// Check that null is not an instance of InstanceOfTest class.
|
|
Dart_Handle null = Dart_InvokeStatic(lib,
|
|
Dart_NewString("OtherClass"),
|
|
Dart_NewString("returnNull"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(null);
|
|
|
|
result = Dart_ObjectIsType(null, otherClass, &is_instance);
|
|
EXPECT_VALID(result);
|
|
EXPECT(!is_instance);
|
|
|
|
// Check that error is returned if null is passed as a class argument.
|
|
result = Dart_ObjectIsType(null, null, &is_instance);
|
|
EXPECT(Dart_IsError(result));
|
|
}
|
|
|
|
|
|
TEST_CASE(NullReceiver) {
|
|
DARTSCOPE_NOCHECKS(Isolate::Current());
|
|
|
|
Dart_Handle function_name = Dart_NewString("toString");
|
|
const int number_of_arguments = 0;
|
|
Dart_Handle null_receiver = Api::NewLocalHandle(Object::Handle());
|
|
Dart_Handle result = Dart_InvokeDynamic(null_receiver,
|
|
function_name,
|
|
number_of_arguments,
|
|
NULL);
|
|
EXPECT_VALID(result);
|
|
EXPECT(Dart_IsString(result));
|
|
|
|
// Should throw a NullPointerException. Disabled due to bug 5415268.
|
|
/*
|
|
Dart_Handle function_name2 = Dart_NewString("NoNoNo");
|
|
result = Dart_InvokeDynamic(null_receiver,
|
|
function_name2,
|
|
number_of_arguments,
|
|
dart_arguments);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT(Dart_ErrorHasException(result)); */
|
|
}
|
|
|
|
|
|
static Dart_Handle library_handler(Dart_LibraryTag tag,
|
|
Dart_Handle library,
|
|
Dart_Handle url,
|
|
Dart_Handle import_url_map) {
|
|
if (tag == kCanonicalizeUrl) {
|
|
return url;
|
|
}
|
|
return Api::Success();
|
|
}
|
|
|
|
|
|
TEST_CASE(LoadScript) {
|
|
const char* kScriptChars =
|
|
"main() {"
|
|
" return 12345;"
|
|
"}";
|
|
Dart_Handle url = Dart_NewString(TestCase::url());
|
|
Dart_Handle source = Dart_NewString(kScriptChars);
|
|
Dart_Handle error = Dart_Error("incoming error");
|
|
Dart_Handle result;
|
|
Dart_Handle import_map = Dart_NewList(0);
|
|
|
|
result = Dart_LoadScript(Dart_Null(), source, library_handler, import_map);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Dart_LoadScript expects argument 'url' to be non-null.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LoadScript(Dart_True(), source, library_handler, import_map);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Dart_LoadScript expects argument 'url' to be of type String.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LoadScript(error, source, library_handler, import_map);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("incoming error", Dart_GetError(result));
|
|
|
|
result = Dart_LoadScript(url, Dart_Null(), library_handler, import_map);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Dart_LoadScript expects argument 'source' to be non-null.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LoadScript(url, Dart_True(), library_handler, import_map);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ(
|
|
"Dart_LoadScript expects argument 'source' to be of type String.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LoadScript(url, error, library_handler, import_map);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("incoming error", Dart_GetError(result));
|
|
|
|
// Load a script successfully.
|
|
result = Dart_LoadScript(url, source, library_handler, import_map);
|
|
EXPECT_VALID(result);
|
|
|
|
result = Dart_InvokeStatic(result,
|
|
Dart_NewString(""),
|
|
Dart_NewString("main"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(result);
|
|
EXPECT(Dart_IsInteger(result));
|
|
int64_t value = 0;
|
|
EXPECT_VALID(Dart_IntegerToInt64(result, &value));
|
|
EXPECT_EQ(12345, value);
|
|
|
|
// Further calls to LoadScript are errors.
|
|
result = Dart_LoadScript(url, source, library_handler, import_map);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Dart_LoadScript: "
|
|
"A script has already been loaded from 'dart:test-lib'.",
|
|
Dart_GetError(result));
|
|
}
|
|
|
|
|
|
static const char* var_mapping[] = {
|
|
"GOOGLE3", ".",
|
|
"ABC", "lala",
|
|
"var1", "",
|
|
"var2", "winner",
|
|
};
|
|
static int index = 0;
|
|
|
|
|
|
static Dart_Handle import_library_handler(Dart_LibraryTag tag,
|
|
Dart_Handle library,
|
|
Dart_Handle url,
|
|
Dart_Handle import_url_map) {
|
|
if (tag == kCanonicalizeUrl) {
|
|
return url;
|
|
}
|
|
EXPECT(Dart_IsString(url));
|
|
const char* cstr = NULL;
|
|
EXPECT_VALID(Dart_StringToCString(url, &cstr));
|
|
switch (index) {
|
|
case 0:
|
|
EXPECT_STREQ("./weird.dart", cstr);
|
|
break;
|
|
case 1:
|
|
EXPECT_STREQ("abclaladef", cstr);
|
|
break;
|
|
case 2:
|
|
EXPECT_STREQ("winner", cstr);
|
|
break;
|
|
case 3:
|
|
EXPECT_STREQ("abclaladef/extra_weird.dart", cstr);
|
|
break;
|
|
case 4:
|
|
EXPECT_STREQ("winnerwinner", cstr);
|
|
break;
|
|
default:
|
|
EXPECT(false);
|
|
return Api::NewError("invalid callback");
|
|
}
|
|
index += 1;
|
|
return Api::Success();
|
|
}
|
|
|
|
|
|
TEST_CASE(LoadImportScript) {
|
|
const char* kScriptChars =
|
|
"#import('$GOOGLE3/weird.dart');"
|
|
"#import('abc${ABC}def');"
|
|
"#import('${var1}$var2');"
|
|
"#import('abc${ABC}def/extra_weird.dart');"
|
|
"#import('$var2$var2');"
|
|
"main() {"
|
|
" return 12345;"
|
|
"}";
|
|
Dart_Handle url = Dart_NewString(TestCase::url());
|
|
Dart_Handle source = Dart_NewString(kScriptChars);
|
|
intptr_t length = (sizeof(var_mapping) / sizeof(var_mapping[0]));
|
|
Dart_Handle import_map = Dart_NewList(length);
|
|
for (intptr_t i = 0; i < length; i++) {
|
|
Dart_ListSetAt(import_map, i, Dart_NewString(var_mapping[i]));
|
|
}
|
|
Dart_Handle result = Dart_LoadScript(url,
|
|
source,
|
|
import_library_handler,
|
|
import_map);
|
|
EXPECT(!Dart_IsError(result));
|
|
}
|
|
|
|
|
|
TEST_CASE(LoadImportScriptError1) {
|
|
const char* kScriptChars =
|
|
"#import('abc${DEF}def/extra_weird.dart');"
|
|
"main() {"
|
|
" return 12345;"
|
|
"}";
|
|
Dart_Handle url = Dart_NewString(TestCase::url());
|
|
Dart_Handle source = Dart_NewString(kScriptChars);
|
|
Dart_Handle import_map = Dart_NewList(0);
|
|
Dart_Handle result = Dart_LoadScript(url,
|
|
source,
|
|
import_library_handler,
|
|
import_map);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT(strstr(Dart_GetError(result),
|
|
"import variable 'DEF' has not been defined"));
|
|
}
|
|
|
|
|
|
TEST_CASE(LoadImportScriptError2) {
|
|
const char* kScriptChars =
|
|
"#import('abc${ABC/extra_weird.dart');"
|
|
"main() {"
|
|
" return 12345;"
|
|
"}";
|
|
Dart_Handle url = Dart_NewString(TestCase::url());
|
|
Dart_Handle source = Dart_NewString(kScriptChars);
|
|
intptr_t length = (sizeof(var_mapping) / sizeof(var_mapping[0]));
|
|
Dart_Handle import_map = Dart_NewList(length);
|
|
for (intptr_t i = 0; i < length; i++) {
|
|
Dart_ListSetAt(import_map, i, Dart_NewString(var_mapping[i]));
|
|
}
|
|
Dart_Handle result = Dart_LoadScript(url,
|
|
source,
|
|
import_library_handler,
|
|
import_map);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT(strstr(Dart_GetError(result), "'}' expected"));
|
|
}
|
|
|
|
|
|
TEST_CASE(LoadScript_CompileError) {
|
|
const char* kScriptChars =
|
|
")";
|
|
Dart_Handle url = Dart_NewString(TestCase::url());
|
|
Dart_Handle source = Dart_NewString(kScriptChars);
|
|
Dart_Handle import_map = Dart_NewList(0);
|
|
Dart_Handle result = Dart_LoadScript(url,
|
|
source,
|
|
library_handler,
|
|
import_map);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT(strstr(Dart_GetError(result), "unexpected token ')'"));
|
|
}
|
|
|
|
|
|
TEST_CASE(LookupLibrary) {
|
|
const char* kScriptChars =
|
|
"#import('library1.dart');"
|
|
"main() {}";
|
|
const char* kLibrary1Chars =
|
|
"#library('library1.dart');"
|
|
"#import('library2.dart');";
|
|
|
|
// Create a test library and Load up a test script in it.
|
|
Dart_Handle url = Dart_NewString(TestCase::url());
|
|
Dart_Handle source = Dart_NewString(kScriptChars);
|
|
Dart_Handle import_map = Dart_NewList(0);
|
|
Dart_Handle result = Dart_LoadScript(url,
|
|
source,
|
|
library_handler,
|
|
import_map);
|
|
EXPECT_VALID(result);
|
|
|
|
url = Dart_NewString("library1.dart");
|
|
source = Dart_NewString(kLibrary1Chars);
|
|
result = Dart_LoadLibrary(url, source, import_map);
|
|
EXPECT_VALID(result);
|
|
|
|
result = Dart_LookupLibrary(url);
|
|
EXPECT_VALID(result);
|
|
|
|
result = Dart_LookupLibrary(Dart_Null());
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Dart_LookupLibrary expects argument 'url' to be non-null.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LookupLibrary(Dart_True());
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ(
|
|
"Dart_LookupLibrary expects argument 'url' to be of type String.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LookupLibrary(Dart_Error("incoming error"));
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("incoming error", Dart_GetError(result));
|
|
|
|
url = Dart_NewString("noodles.dart");
|
|
result = Dart_LookupLibrary(url);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Dart_LookupLibrary: library 'noodles.dart' not found.",
|
|
Dart_GetError(result));
|
|
}
|
|
|
|
|
|
TEST_CASE(LibraryUrl) {
|
|
const char* kLibrary1Chars =
|
|
"#library('library1_name');";
|
|
Dart_Handle url = Dart_NewString("library1_url");
|
|
Dart_Handle source = Dart_NewString(kLibrary1Chars);
|
|
Dart_Handle import_map = Dart_NewList(0);
|
|
Dart_Handle lib = Dart_LoadLibrary(url, source, import_map);
|
|
Dart_Handle error = Dart_Error("incoming error");
|
|
EXPECT_VALID(lib);
|
|
|
|
Dart_Handle result = Dart_LibraryUrl(Dart_Null());
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Dart_LibraryUrl expects argument 'library' to be non-null.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LibraryUrl(Dart_True());
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ(
|
|
"Dart_LibraryUrl expects argument 'library' to be of type Library.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LibraryUrl(error);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("incoming error", Dart_GetError(result));
|
|
|
|
result = Dart_LibraryUrl(lib);
|
|
EXPECT_VALID(result);
|
|
EXPECT(Dart_IsString(result));
|
|
const char* cstr = NULL;
|
|
EXPECT_VALID(Dart_StringToCString(result, &cstr));
|
|
EXPECT_STREQ("library1_url", cstr);
|
|
}
|
|
|
|
|
|
TEST_CASE(LibraryImportLibrary) {
|
|
const char* kLibrary1Chars =
|
|
"#library('library1_name');";
|
|
const char* kLibrary2Chars =
|
|
"#library('library2_name');";
|
|
Dart_Handle error = Dart_Error("incoming error");
|
|
Dart_Handle result;
|
|
|
|
Dart_Handle url = Dart_NewString("library1_url");
|
|
Dart_Handle source = Dart_NewString(kLibrary1Chars);
|
|
Dart_Handle import_map = Dart_NewList(0);
|
|
Dart_Handle lib1 = Dart_LoadLibrary(url, source, import_map);
|
|
EXPECT_VALID(lib1);
|
|
|
|
url = Dart_NewString("library2_url");
|
|
source = Dart_NewString(kLibrary2Chars);
|
|
Dart_Handle lib2 = Dart_LoadLibrary(url, source, import_map);
|
|
EXPECT_VALID(lib2);
|
|
|
|
result = Dart_LibraryImportLibrary(Dart_Null(), lib2);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ(
|
|
"Dart_LibraryImportLibrary expects argument 'library' to be non-null.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LibraryImportLibrary(Dart_True(), lib2);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Dart_LibraryImportLibrary expects argument 'library' to be of "
|
|
"type Library.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LibraryImportLibrary(error, lib2);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("incoming error", Dart_GetError(result));
|
|
|
|
result = Dart_LibraryImportLibrary(lib1, Dart_Null());
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ(
|
|
"Dart_LibraryImportLibrary expects argument 'import' to be non-null.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LibraryImportLibrary(lib1, Dart_True());
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Dart_LibraryImportLibrary expects argument 'import' to be of "
|
|
"type Library.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LibraryImportLibrary(lib1, error);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("incoming error", Dart_GetError(result));
|
|
|
|
result = Dart_LibraryImportLibrary(lib1, lib2);
|
|
EXPECT_VALID(result);
|
|
}
|
|
|
|
|
|
|
|
TEST_CASE(LoadLibrary) {
|
|
const char* kLibrary1Chars =
|
|
"#library('library1_name');";
|
|
Dart_Handle error = Dart_Error("incoming error");
|
|
Dart_Handle result;
|
|
|
|
Dart_Handle url = Dart_NewString("library1_url");
|
|
Dart_Handle source = Dart_NewString(kLibrary1Chars);
|
|
Dart_Handle import_map = Dart_NewList(0);
|
|
|
|
result = Dart_LoadLibrary(Dart_Null(), source, import_map);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Dart_LoadLibrary expects argument 'url' to be non-null.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LoadLibrary(Dart_True(), source, import_map);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Dart_LoadLibrary expects argument 'url' to be of type String.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LoadLibrary(error, source, import_map);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("incoming error", Dart_GetError(result));
|
|
|
|
result = Dart_LoadLibrary(url, Dart_Null(), import_map);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Dart_LoadLibrary expects argument 'source' to be non-null.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LoadLibrary(url, Dart_True(), import_map);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ(
|
|
"Dart_LoadLibrary expects argument 'source' to be of type String.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LoadLibrary(url, error, import_map);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("incoming error", Dart_GetError(result));
|
|
|
|
// Success.
|
|
result = Dart_LoadLibrary(url, source, import_map);
|
|
EXPECT_VALID(result);
|
|
EXPECT(Dart_IsLibrary(result));
|
|
|
|
// Duplicate library load fails.
|
|
result = Dart_LoadLibrary(url, source, import_map);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ(
|
|
"Dart_LoadLibrary: library 'library1_url' has already been loaded.",
|
|
Dart_GetError(result));
|
|
}
|
|
|
|
|
|
TEST_CASE(LoadLibrary_CompileError) {
|
|
const char* kLibrary1Chars =
|
|
"#library('library1_name');"
|
|
")";
|
|
Dart_Handle url = Dart_NewString("library1_url");
|
|
Dart_Handle source = Dart_NewString(kLibrary1Chars);
|
|
Dart_Handle import_map = Dart_NewList(0);
|
|
Dart_Handle result = Dart_LoadLibrary(url, source, import_map);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT(strstr(Dart_GetError(result), "unexpected token ')'"));
|
|
}
|
|
|
|
|
|
TEST_CASE(LoadSource) {
|
|
const char* kLibrary1Chars =
|
|
"#library('library1_name');";
|
|
const char* kSourceChars =
|
|
"// Something innocuous";
|
|
const char* kBadSourceChars =
|
|
")";
|
|
Dart_Handle error = Dart_Error("incoming error");
|
|
Dart_Handle result;
|
|
|
|
// Load up a library.
|
|
Dart_Handle url = Dart_NewString("library1_url");
|
|
Dart_Handle source = Dart_NewString(kLibrary1Chars);
|
|
Dart_Handle import_map = Dart_NewList(0);
|
|
Dart_Handle lib = Dart_LoadLibrary(url, source, import_map);
|
|
EXPECT_VALID(lib);
|
|
EXPECT(Dart_IsLibrary(lib));
|
|
|
|
url = Dart_NewString("source_url");
|
|
source = Dart_NewString(kSourceChars);
|
|
|
|
result = Dart_LoadSource(Dart_Null(), url, source);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Dart_LoadSource expects argument 'library' to be non-null.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LoadSource(Dart_True(), url, source);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ(
|
|
"Dart_LoadSource expects argument 'library' to be of type Library.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LoadSource(error, url, source);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("incoming error", Dart_GetError(result));
|
|
|
|
result = Dart_LoadSource(lib, Dart_Null(), source);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Dart_LoadSource expects argument 'url' to be non-null.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LoadSource(lib, Dart_True(), source);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Dart_LoadSource expects argument 'url' to be of type String.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LoadSource(lib, error, source);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("incoming error", Dart_GetError(result));
|
|
|
|
result = Dart_LoadSource(lib, url, Dart_Null());
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Dart_LoadSource expects argument 'source' to be non-null.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LoadSource(lib, url, Dart_True());
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ(
|
|
"Dart_LoadSource expects argument 'source' to be of type String.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_LoadSource(lib, error, source);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("incoming error", Dart_GetError(result));
|
|
|
|
// Success.
|
|
result = Dart_LoadSource(lib, url, source);
|
|
EXPECT_VALID(result);
|
|
EXPECT(Dart_IsLibrary(result));
|
|
bool same = false;
|
|
EXPECT_VALID(Dart_IsSame(lib, result, &same));
|
|
EXPECT(same);
|
|
|
|
// Duplicate calls are okay.
|
|
result = Dart_LoadSource(lib, url, source);
|
|
EXPECT_VALID(result);
|
|
EXPECT(Dart_IsLibrary(result));
|
|
same = false;
|
|
EXPECT_VALID(Dart_IsSame(lib, result, &same));
|
|
EXPECT(same);
|
|
|
|
// Language errors are detected.
|
|
source = Dart_NewString(kBadSourceChars);
|
|
result = Dart_LoadSource(lib, url, source);
|
|
EXPECT(Dart_IsError(result));
|
|
}
|
|
|
|
|
|
static void MyNativeFunction1(Dart_NativeArguments args) {
|
|
Dart_EnterScope();
|
|
Dart_SetReturnValue(args, Dart_NewInteger(654321));
|
|
Dart_ExitScope();
|
|
}
|
|
|
|
|
|
static void MyNativeFunction2(Dart_NativeArguments args) {
|
|
Dart_EnterScope();
|
|
Dart_SetReturnValue(args, Dart_NewInteger(123456));
|
|
Dart_ExitScope();
|
|
}
|
|
|
|
|
|
static Dart_NativeFunction MyNativeResolver1(Dart_Handle name,
|
|
int arg_count) {
|
|
return &MyNativeFunction1;
|
|
}
|
|
|
|
|
|
static Dart_NativeFunction MyNativeResolver2(Dart_Handle name,
|
|
int arg_count) {
|
|
return &MyNativeFunction2;
|
|
}
|
|
|
|
|
|
TEST_CASE(SetNativeResolver) {
|
|
const char* kScriptChars =
|
|
"class Test {"
|
|
" static foo() native \"SomeNativeFunction\";"
|
|
" static bar() native \"SomeNativeFunction2\";"
|
|
" static baz() native \"SomeNativeFunction3\";"
|
|
"}";
|
|
Dart_Handle error = Dart_Error("incoming error");
|
|
Dart_Handle result;
|
|
|
|
// Load a test script.
|
|
Dart_Handle url = Dart_NewString(TestCase::url());
|
|
Dart_Handle source = Dart_NewString(kScriptChars);
|
|
Dart_Handle import_map = Dart_NewList(0);
|
|
Dart_Handle lib = Dart_LoadScript(url, source, library_handler, import_map);
|
|
EXPECT_VALID(lib);
|
|
EXPECT(Dart_IsLibrary(lib));
|
|
|
|
result = Dart_SetNativeResolver(Dart_Null(), &MyNativeResolver1);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ(
|
|
"Dart_SetNativeResolver expects argument 'library' to be non-null.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_SetNativeResolver(Dart_True(), &MyNativeResolver1);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Dart_SetNativeResolver expects argument 'library' to be of "
|
|
"type Library.",
|
|
Dart_GetError(result));
|
|
|
|
result = Dart_SetNativeResolver(error, &MyNativeResolver1);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("incoming error", Dart_GetError(result));
|
|
|
|
result = Dart_SetNativeResolver(lib, &MyNativeResolver1);
|
|
EXPECT_VALID(result);
|
|
|
|
// Call a function and make sure native resolution works.
|
|
result = Dart_InvokeStatic(lib,
|
|
Dart_NewString("Test"),
|
|
Dart_NewString("foo"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(result);
|
|
EXPECT(Dart_IsInteger(result));
|
|
int64_t value = 0;
|
|
EXPECT_VALID(Dart_IntegerToInt64(result, &value));
|
|
EXPECT_EQ(654321, value);
|
|
|
|
// A second call succeeds.
|
|
result = Dart_SetNativeResolver(lib, &MyNativeResolver2);
|
|
EXPECT_VALID(result);
|
|
|
|
// 'foo' has already been resolved so gets the old value.
|
|
result = Dart_InvokeStatic(lib,
|
|
Dart_NewString("Test"),
|
|
Dart_NewString("foo"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(result);
|
|
EXPECT(Dart_IsInteger(result));
|
|
value = 0;
|
|
EXPECT_VALID(Dart_IntegerToInt64(result, &value));
|
|
EXPECT_EQ(654321, value);
|
|
|
|
// 'bar' has not yet been resolved so gets the new value.
|
|
result = Dart_InvokeStatic(lib,
|
|
Dart_NewString("Test"),
|
|
Dart_NewString("bar"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(result);
|
|
EXPECT(Dart_IsInteger(result));
|
|
value = 0;
|
|
EXPECT_VALID(Dart_IntegerToInt64(result, &value));
|
|
EXPECT_EQ(123456, value);
|
|
|
|
// A NULL resolver is okay, but resolution will fail.
|
|
result = Dart_SetNativeResolver(lib, NULL);
|
|
EXPECT_VALID(result);
|
|
|
|
result = Dart_InvokeStatic(lib,
|
|
Dart_NewString("Test"),
|
|
Dart_NewString("baz"),
|
|
0,
|
|
NULL);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT(strstr(Dart_GetError(result),
|
|
"native function 'SomeNativeFunction3' cannot be found"));
|
|
}
|
|
|
|
|
|
TEST_CASE(ImportLibrary1) {
|
|
const char* kScriptChars =
|
|
"#import('library1.dart');"
|
|
"#import('library2.dart');"
|
|
"var foo; // library2 defines foo, so should be error."
|
|
"main() {}";
|
|
const char* kLibrary1Chars =
|
|
"#library('library1.dart');"
|
|
"#import('library2.dart');"
|
|
"var foo1;";
|
|
const char* kLibrary2Chars =
|
|
"#library('library2.dart');"
|
|
"var foo;";
|
|
Dart_Handle result;
|
|
// Create a test library and Load up a test script in it.
|
|
Dart_Handle url = Dart_NewString(TestCase::url());
|
|
Dart_Handle source = Dart_NewString(kScriptChars);
|
|
Dart_Handle import_map = Dart_NewList(0);
|
|
result = Dart_LoadScript(url, source, library_handler, import_map);
|
|
|
|
url = Dart_NewString("library1.dart");
|
|
source = Dart_NewString(kLibrary1Chars);
|
|
Dart_LoadLibrary(url, source, import_map);
|
|
|
|
url = Dart_NewString("library2.dart");
|
|
source = Dart_NewString(kLibrary2Chars);
|
|
Dart_LoadLibrary(url, source, import_map);
|
|
|
|
result = Dart_InvokeStatic(result,
|
|
Dart_NewString(""),
|
|
Dart_NewString("main"),
|
|
0,
|
|
NULL);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Duplicate definition : 'foo' is defined in"
|
|
" 'library2.dart' and 'dart:test-lib'\n",
|
|
Dart_GetError(result));
|
|
}
|
|
|
|
|
|
TEST_CASE(ImportLibrary2) {
|
|
const char* kScriptChars =
|
|
"#import('library1.dart');"
|
|
"var foo;"
|
|
"main() {}";
|
|
const char* kLibrary1Chars =
|
|
"#library('library1.dart');"
|
|
"#import('library2.dart');"
|
|
"var foo1;";
|
|
const char* kLibrary2Chars =
|
|
"#library('library2.dart');"
|
|
"#import('library1.dart');"
|
|
"var foo;";
|
|
Dart_Handle result;
|
|
// Create a test library and Load up a test script in it.
|
|
Dart_Handle url = Dart_NewString(TestCase::url());
|
|
Dart_Handle source = Dart_NewString(kScriptChars);
|
|
Dart_Handle import_map = Dart_NewList(0);
|
|
result = Dart_LoadScript(url, source, library_handler, import_map);
|
|
|
|
url = Dart_NewString("library1.dart");
|
|
source = Dart_NewString(kLibrary1Chars);
|
|
Dart_LoadLibrary(url, source, import_map);
|
|
|
|
url = Dart_NewString("library2.dart");
|
|
source = Dart_NewString(kLibrary2Chars);
|
|
Dart_LoadLibrary(url, source, import_map);
|
|
|
|
result = Dart_InvokeStatic(result,
|
|
Dart_NewString(""),
|
|
Dart_NewString("main"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(result);
|
|
}
|
|
|
|
|
|
TEST_CASE(ImportLibrary3) {
|
|
const char* kScriptChars =
|
|
"#import('library2.dart');"
|
|
"#import('library1.dart');"
|
|
"var foo_top = 10; // foo has dup def. So should be an error."
|
|
"main() {}";
|
|
const char* kLibrary1Chars =
|
|
"#library('library1.dart');"
|
|
"var foo;";
|
|
const char* kLibrary2Chars =
|
|
"#library('library2.dart');"
|
|
"var foo;";
|
|
Dart_Handle result;
|
|
|
|
// Create a test library and Load up a test script in it.
|
|
Dart_Handle url = Dart_NewString(TestCase::url());
|
|
Dart_Handle source = Dart_NewString(kScriptChars);
|
|
Dart_Handle import_map = Dart_NewList(0);
|
|
result = Dart_LoadScript(url, source, library_handler, import_map);
|
|
|
|
url = Dart_NewString("library2.dart");
|
|
source = Dart_NewString(kLibrary2Chars);
|
|
Dart_LoadLibrary(url, source, import_map);
|
|
|
|
url = Dart_NewString("library1.dart");
|
|
source = Dart_NewString(kLibrary1Chars);
|
|
Dart_LoadLibrary(url, source, import_map);
|
|
|
|
result = Dart_InvokeStatic(result,
|
|
Dart_NewString(""),
|
|
Dart_NewString("main"),
|
|
0,
|
|
NULL);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Duplicate definition : 'foo' is defined in"
|
|
" 'library1.dart' and 'library2.dart'\n",
|
|
Dart_GetError(result));
|
|
}
|
|
|
|
|
|
TEST_CASE(ImportLibrary4) {
|
|
const char* kScriptChars =
|
|
"#import('libraryA.dart');"
|
|
"#import('libraryB.dart');"
|
|
"#import('libraryD.dart');"
|
|
"#import('libraryE.dart');"
|
|
"var fooApp;"
|
|
"main() {}";
|
|
const char* kLibraryAChars =
|
|
"#library('libraryA.dart');"
|
|
"#import('libraryC.dart');"
|
|
"var fooA;";
|
|
const char* kLibraryBChars =
|
|
"#library('libraryB.dart');"
|
|
"#import('libraryC.dart');"
|
|
"var fooB;";
|
|
const char* kLibraryCChars =
|
|
"#library('libraryC.dart');"
|
|
"var fooC;";
|
|
const char* kLibraryDChars =
|
|
"#library('libraryD.dart');"
|
|
"#import('libraryF.dart');"
|
|
"var fooD;";
|
|
const char* kLibraryEChars =
|
|
"#library('libraryE.dart');"
|
|
"#import('libraryC.dart');"
|
|
"#import('libraryF.dart');"
|
|
"var fooE = 10; //fooC has duplicate def. so should be an error.";
|
|
const char* kLibraryFChars =
|
|
"#library('libraryF.dart');"
|
|
"var fooC;";
|
|
Dart_Handle result;
|
|
|
|
// Create a test library and Load up a test script in it.
|
|
Dart_Handle url = Dart_NewString(TestCase::url());
|
|
Dart_Handle source = Dart_NewString(kScriptChars);
|
|
Dart_Handle import_map = Dart_NewList(0);
|
|
result = Dart_LoadScript(url, source, library_handler, import_map);
|
|
|
|
url = Dart_NewString("libraryA.dart");
|
|
source = Dart_NewString(kLibraryAChars);
|
|
Dart_LoadLibrary(url, source, import_map);
|
|
|
|
url = Dart_NewString("libraryC.dart");
|
|
source = Dart_NewString(kLibraryCChars);
|
|
Dart_LoadLibrary(url, source, import_map);
|
|
|
|
url = Dart_NewString("libraryB.dart");
|
|
source = Dart_NewString(kLibraryBChars);
|
|
Dart_LoadLibrary(url, source, import_map);
|
|
|
|
url = Dart_NewString("libraryD.dart");
|
|
source = Dart_NewString(kLibraryDChars);
|
|
Dart_LoadLibrary(url, source, import_map);
|
|
|
|
url = Dart_NewString("libraryF.dart");
|
|
source = Dart_NewString(kLibraryFChars);
|
|
Dart_LoadLibrary(url, source, import_map);
|
|
|
|
url = Dart_NewString("libraryE.dart");
|
|
source = Dart_NewString(kLibraryEChars);
|
|
Dart_LoadLibrary(url, source, import_map);
|
|
|
|
result = Dart_InvokeStatic(result,
|
|
Dart_NewString(""),
|
|
Dart_NewString("main"),
|
|
0,
|
|
NULL);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT_STREQ("Duplicate definition : 'fooC' is defined in"
|
|
" 'libraryF.dart' and 'libraryC.dart'\n",
|
|
Dart_GetError(result));
|
|
}
|
|
|
|
|
|
TEST_CASE(ImportLibrary5) {
|
|
const char* kScriptChars =
|
|
"#import('lib.dart');"
|
|
"interface Y {"
|
|
" void set handler(void callback(List<int> x));"
|
|
"}"
|
|
"void main() {}";
|
|
const char* kLibraryChars =
|
|
"#library('lib.dart');"
|
|
"interface X {"
|
|
" void set handler(void callback(List<int> x));"
|
|
"}";
|
|
Dart_Handle result;
|
|
|
|
// Create a test library and Load up a test script in it.
|
|
Dart_Handle url = Dart_NewString(TestCase::url());
|
|
Dart_Handle source = Dart_NewString(kScriptChars);
|
|
Dart_Handle import_map = Dart_NewList(0);
|
|
result = Dart_LoadScript(url, source, library_handler, import_map);
|
|
|
|
url = Dart_NewString("lib.dart");
|
|
source = Dart_NewString(kLibraryChars);
|
|
Dart_LoadLibrary(url, source, import_map);
|
|
|
|
result = Dart_InvokeStatic(result,
|
|
Dart_NewString(""),
|
|
Dart_NewString("main"),
|
|
0,
|
|
NULL);
|
|
EXPECT_VALID(result);
|
|
}
|
|
|
|
|
|
void NewNativePort_send123(Dart_Port dest_port_id,
|
|
Dart_Port reply_port_id,
|
|
Dart_CObject *message) {
|
|
// Gets a null message.
|
|
EXPECT_NOTNULL(message);
|
|
EXPECT_EQ(Dart_CObject::kNull, message->type);
|
|
|
|
// Post integer value.
|
|
Dart_CObject response;
|
|
response.type = Dart_CObject::kInt32;
|
|
response.value.as_int32 = 123;
|
|
Dart_PostCObject(reply_port_id, &response);
|
|
}
|
|
|
|
|
|
void NewNativePort_send321(Dart_Port dest_port_id,
|
|
Dart_Port reply_port_id,
|
|
Dart_CObject* message) {
|
|
// Gets a null message.
|
|
EXPECT_NOTNULL(message);
|
|
EXPECT_EQ(Dart_CObject::kNull, message->type);
|
|
|
|
// Post integer value.
|
|
Dart_CObject response;
|
|
response.type = Dart_CObject::kInt32;
|
|
response.value.as_int32 = 321;
|
|
Dart_PostCObject(reply_port_id, &response);
|
|
}
|
|
|
|
|
|
UNIT_TEST_CASE(NewNativePort) {
|
|
// Create a port with a bogus handler.
|
|
Dart_Port error_port = Dart_NewNativePort("Foo", NULL, true);
|
|
EXPECT_EQ(kIllegalPort, error_port);
|
|
|
|
// Create the port w/o a current isolate, just to make sure that works.
|
|
Dart_Port port_id1 =
|
|
Dart_NewNativePort("Port123", NewNativePort_send123, true);
|
|
|
|
TestIsolateScope __test_isolate__;
|
|
const char* kScriptChars =
|
|
"void callPort(SendPort port) {\n"
|
|
" port.call(null).receive((message, replyTo) {\n"
|
|
" throw new Exception(message);\n"
|
|
" });\n"
|
|
"}\n";
|
|
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
|
Dart_EnterScope();
|
|
|
|
// Create a port w/ a current isolate, to make sure that works too.
|
|
Dart_Port port_id2 =
|
|
Dart_NewNativePort("Port321", NewNativePort_send321, true);
|
|
|
|
Dart_Handle send_port1 = Dart_NewSendPort(port_id1);
|
|
EXPECT_VALID(send_port1);
|
|
Dart_Handle send_port2 = Dart_NewSendPort(port_id2);
|
|
EXPECT_VALID(send_port2);
|
|
|
|
// Test first port.
|
|
Dart_Handle dart_args[1];
|
|
dart_args[0] = send_port1;
|
|
Dart_Handle result = Dart_InvokeStatic(lib,
|
|
Dart_NewString(""),
|
|
Dart_NewString("callPort"),
|
|
1,
|
|
dart_args);
|
|
EXPECT_VALID(result);
|
|
result = Dart_RunLoop();
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT(Dart_ErrorHasException(result));
|
|
EXPECT_SUBSTRING("Exception: 123\n", Dart_GetError(result));
|
|
|
|
// result second port.
|
|
dart_args[0] = send_port2;
|
|
result = Dart_InvokeStatic(lib,
|
|
Dart_NewString(""),
|
|
Dart_NewString("callPort"),
|
|
1,
|
|
dart_args);
|
|
EXPECT_VALID(result);
|
|
result = Dart_RunLoop();
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT(Dart_ErrorHasException(result));
|
|
EXPECT_SUBSTRING("Exception: 321\n", Dart_GetError(result));
|
|
|
|
Dart_ExitScope();
|
|
|
|
// Delete the native ports.
|
|
EXPECT(Dart_CloseNativePort(port_id1));
|
|
EXPECT(Dart_CloseNativePort(port_id2));
|
|
}
|
|
|
|
|
|
static bool RunLoopTestCallback(const char* name_prefix,
|
|
void* data, char** error) {
|
|
const char* kScriptChars =
|
|
"#import('builtin');\n"
|
|
"class MyIsolate extends Isolate {\n"
|
|
" MyIsolate() : super() { }\n"
|
|
" void main() {\n"
|
|
" port.receive((message, replyTo) {\n"
|
|
" if (message) {\n"
|
|
" throw new Exception('MakeChildExit');\n"
|
|
" } else {\n"
|
|
" replyTo.call('hello');\n"
|
|
" port.close();\n"
|
|
" }\n"
|
|
" });\n"
|
|
" }\n"
|
|
"}\n"
|
|
"\n"
|
|
"void main(exc_child, exc_parent) {\n"
|
|
" new MyIsolate().spawn().then((port) {\n"
|
|
" port.call(exc_child).receive((message, replyTo) {\n"
|
|
" if (message != 'hello') throw new Exception('ShouldNotHappen');\n"
|
|
" if (exc_parent) throw new Exception('MakeParentExit');\n"
|
|
" });\n"
|
|
" });\n"
|
|
"}\n";
|
|
|
|
if (Dart_CurrentIsolate() != NULL) {
|
|
Dart_ExitIsolate();
|
|
}
|
|
Dart_Isolate isolate = TestCase::CreateTestIsolate();
|
|
ASSERT(isolate != NULL);
|
|
Dart_EnterScope();
|
|
Dart_Handle url = Dart_NewString(TestCase::url());
|
|
Dart_Handle source = Dart_NewString(kScriptChars);
|
|
Dart_Handle import_map = Dart_NewList(0);
|
|
Dart_Handle lib = Dart_LoadScript(url,
|
|
source,
|
|
TestCase::library_handler,
|
|
import_map);
|
|
EXPECT_VALID(lib);
|
|
Dart_ExitScope();
|
|
return true;
|
|
}
|
|
|
|
|
|
// Common code for RunLoop_Success/RunLoop_Failure.
|
|
static void RunLoopTest(bool throw_exception_child,
|
|
bool throw_exception_parent) {
|
|
Dart_IsolateCreateCallback saved = Isolate::CreateCallback();
|
|
Isolate::SetCreateCallback(RunLoopTestCallback);
|
|
RunLoopTestCallback(NULL, NULL, NULL);
|
|
|
|
Dart_EnterScope();
|
|
Dart_Handle lib = Dart_LookupLibrary(Dart_NewString(TestCase::url()));
|
|
EXPECT_VALID(lib);
|
|
|
|
Dart_Handle result;
|
|
Dart_Handle args[2];
|
|
args[0] = (throw_exception_child ? Dart_True() : Dart_False());
|
|
args[1] = (throw_exception_parent ? Dart_True() : Dart_False());
|
|
result = Dart_InvokeStatic(lib,
|
|
Dart_NewString(""),
|
|
Dart_NewString("main"),
|
|
2,
|
|
args);
|
|
EXPECT_VALID(result);
|
|
result = Dart_RunLoop();
|
|
if (throw_exception_parent) {
|
|
EXPECT(Dart_IsError(result));
|
|
// TODO(turnidge): Once EXPECT_SUBSTRING is submitted use it here.
|
|
} else {
|
|
EXPECT_VALID(result);
|
|
}
|
|
|
|
Dart_ExitScope();
|
|
Dart_ShutdownIsolate();
|
|
|
|
Isolate::SetCreateCallback(saved);
|
|
}
|
|
|
|
|
|
UNIT_TEST_CASE(RunLoop_Success) {
|
|
RunLoopTest(false, false);
|
|
}
|
|
|
|
|
|
// This test exits the vm. Listed as FAIL in vm.status.
|
|
UNIT_TEST_CASE(RunLoop_ExceptionChild) {
|
|
RunLoopTest(true, false);
|
|
}
|
|
|
|
|
|
UNIT_TEST_CASE(RunLoop_ExceptionParent) {
|
|
RunLoopTest(false, true);
|
|
}
|
|
|
|
|
|
// Utility functions and variables for test case IsolateInterrupt starts here.
|
|
static Monitor* sync = NULL;
|
|
static Dart_Isolate shared_isolate = NULL;
|
|
static bool main_entered = false;
|
|
|
|
|
|
void MarkMainEntered(Dart_NativeArguments args) {
|
|
Dart_EnterScope(); // Start a Dart API scope for invoking API functions.
|
|
// Indicate that main has been entered.
|
|
{
|
|
MonitorLocker ml(sync);
|
|
main_entered = true;
|
|
ml.Notify();
|
|
}
|
|
Dart_SetReturnValue(args, Dart_Null());
|
|
Dart_ExitScope();
|
|
}
|
|
|
|
|
|
static Dart_NativeFunction IsolateInterruptTestNativeLookup(
|
|
Dart_Handle name, int argument_count) {
|
|
return reinterpret_cast<Dart_NativeFunction>(&MarkMainEntered);
|
|
}
|
|
|
|
|
|
void BusyLoop_start(uword unused) {
|
|
// TODO(turnidge): Get rid of call to 'function' after interrupts
|
|
// are checked on backward branches.
|
|
const char* kScriptChars =
|
|
"class Native {\n"
|
|
" static void markMainEntered() native 'MarkMainEntered';\n"
|
|
"}\n"
|
|
"void function([foo='hi']) {\n"
|
|
"}\n"
|
|
"\n"
|
|
"void main() {\n"
|
|
" Native.markMainEntered();\n"
|
|
" while (true) {\n" // Infinite loop.
|
|
" function();\n"
|
|
" }\n"
|
|
"}\n";
|
|
|
|
|
|
// Tell the other thread that shared_isolate is created.
|
|
Dart_Handle lib;
|
|
{
|
|
sync->Enter();
|
|
char* error = NULL;
|
|
shared_isolate = Dart_CreateIsolate(NULL, NULL, NULL, &error);
|
|
EXPECT(shared_isolate != NULL);
|
|
Dart_EnterScope();
|
|
Dart_Handle url = Dart_NewString(TestCase::url());
|
|
Dart_Handle source = Dart_NewString(kScriptChars);
|
|
Dart_Handle import_map = Dart_NewList(0);
|
|
lib = Dart_LoadScript(url, source, TestCase::library_handler, import_map);
|
|
EXPECT_VALID(lib);
|
|
Dart_Handle result = Dart_SetNativeResolver(
|
|
lib, &IsolateInterruptTestNativeLookup);
|
|
DART_CHECK_VALID(result);
|
|
|
|
sync->Notify();
|
|
sync->Exit();
|
|
}
|
|
|
|
Dart_Handle result = Dart_InvokeStatic(lib,
|
|
Dart_NewString(""),
|
|
Dart_NewString("main"),
|
|
0,
|
|
NULL);
|
|
EXPECT(Dart_IsError(result));
|
|
EXPECT(Dart_ErrorHasException(result));
|
|
EXPECT_SUBSTRING("Unhandled exception:\nfoo\n",
|
|
Dart_GetError(result));
|
|
|
|
Dart_ExitScope();
|
|
Dart_ShutdownIsolate();
|
|
|
|
// Tell the other thread that we are done (don't use MonitorLocker
|
|
// as there is no current isolate any more).
|
|
sync->Enter();
|
|
shared_isolate = NULL;
|
|
sync->Notify();
|
|
sync->Exit();
|
|
}
|
|
|
|
|
|
// This callback handles isolate interrupts for the IsolateInterrupt
|
|
// test. It ignores the first two interrupts and throws an exception
|
|
// on the third interrupt.
|
|
const int kInterruptCount = 10;
|
|
static int interrupt_count = 0;
|
|
static bool IsolateInterruptTestCallback() {
|
|
OS::Print(" ========== Interrupt callback called #%d\n", interrupt_count + 1);
|
|
{
|
|
MonitorLocker ml(sync);
|
|
interrupt_count++;
|
|
ml.Notify();
|
|
}
|
|
if (interrupt_count == kInterruptCount) {
|
|
Dart_EnterScope();
|
|
Dart_Handle lib = Dart_LookupLibrary(Dart_NewString(TestCase::url()));
|
|
EXPECT_VALID(lib);
|
|
Dart_Handle exc = Dart_NewString("foo");
|
|
EXPECT_VALID(exc);
|
|
Dart_Handle result = Dart_ThrowException(exc);
|
|
EXPECT_VALID(result);
|
|
UNREACHABLE(); // Dart_ThrowException only returns if it gets an error.
|
|
return false;
|
|
}
|
|
ASSERT(interrupt_count < kInterruptCount);
|
|
return true;
|
|
}
|
|
|
|
|
|
TEST_CASE(IsolateInterrupt) {
|
|
Dart_IsolateInterruptCallback saved = Isolate::InterruptCallback();
|
|
Isolate::SetInterruptCallback(IsolateInterruptTestCallback);
|
|
|
|
sync = new Monitor();
|
|
int result = Thread::Start(BusyLoop_start, 0);
|
|
EXPECT_EQ(0, result);
|
|
|
|
{
|
|
MonitorLocker ml(sync);
|
|
// Wait for the other isolate to enter main.
|
|
while (!main_entered) {
|
|
ml.Wait();
|
|
}
|
|
}
|
|
|
|
// Send a number of interrupts to the other isolate. All but the
|
|
// last allow execution to continue. The last causes an exception in
|
|
// the isolate.
|
|
for (int i = 0; i < kInterruptCount; i++) {
|
|
// Space out the interrupts a bit.
|
|
OS::Sleep(i + 1);
|
|
Dart_InterruptIsolate(shared_isolate);
|
|
{
|
|
MonitorLocker ml(sync);
|
|
// Wait for interrupt_count to be increased.
|
|
while (interrupt_count == i) {
|
|
ml.Wait();
|
|
}
|
|
OS::Print(" ========== Interrupt processed #%d\n", interrupt_count);
|
|
}
|
|
}
|
|
|
|
{
|
|
MonitorLocker ml(sync);
|
|
// Wait for our isolate to finish.
|
|
while (shared_isolate != NULL) {
|
|
ml.Wait();
|
|
}
|
|
}
|
|
|
|
// We should have received the expected number of interrupts.
|
|
EXPECT_EQ(kInterruptCount, interrupt_count);
|
|
|
|
// Give the spawned thread enough time to properly exit.
|
|
Isolate::SetInterruptCallback(saved);
|
|
}
|
|
|
|
#endif // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64).
|
|
|
|
} // namespace dart
|