7514ce941e
Threads in the native or blocked states don't prevent safepoints, so they may run concurrently with a safepoint operation like GC. It is not safe for handles to be allocated while the GC is visiting them, so these threads must not allocate handles. Assert only threads in the VM or generated states, which prevent safepoints until they check in, may allocate handles. (Generated code does not allocate handles, but leaf runtime entries remain in the generated state.) Bug: https://github.com/dart-lang/sdk/issues/34883 Change-Id: I1a211778f7ef96b53a2405f0ee9dde7871b122b6 Reviewed-on: https://dart-review.googlesource.com/c/81540 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Siva Annamalai <asiva@google.com> Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
321 lines
7.7 KiB
C++
321 lines
7.7 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 "platform/assert.h"
|
|
#include "platform/text_buffer.h"
|
|
#include "vm/dart_api_impl.h"
|
|
#include "vm/json_stream.h"
|
|
#include "vm/unit_test.h"
|
|
|
|
namespace dart {
|
|
|
|
#ifndef PRODUCT
|
|
|
|
TEST_CASE(JSON_TextBuffer) {
|
|
TextBuffer w(5); // Small enough to make buffer grow at least once.
|
|
w.Printf("{ \"%s\" : %d", "length", 175);
|
|
EXPECT_STREQ("{ \"length\" : 175", w.buf());
|
|
w.Printf(", \"%s\" : \"%s\" }", "command", "stopIt");
|
|
EXPECT_STREQ("{ \"length\" : 175, \"command\" : \"stopIt\" }", w.buf());
|
|
}
|
|
|
|
TEST_CASE(JSON_JSONStream_Primitives) {
|
|
{
|
|
JSONStream js;
|
|
{ JSONObject jsobj(&js); }
|
|
EXPECT_STREQ("{}", js.ToCString());
|
|
}
|
|
{
|
|
JSONStream js;
|
|
{ JSONArray jsarr(&js); }
|
|
EXPECT_STREQ("[]", js.ToCString());
|
|
}
|
|
{
|
|
JSONStream js;
|
|
{
|
|
JSONArray jsarr(&js);
|
|
jsarr.AddValue(true);
|
|
}
|
|
EXPECT_STREQ("[true]", js.ToCString());
|
|
}
|
|
{
|
|
JSONStream js;
|
|
{
|
|
JSONArray jsarr(&js);
|
|
jsarr.AddValue(false);
|
|
}
|
|
EXPECT_STREQ("[false]", js.ToCString());
|
|
}
|
|
{
|
|
JSONStream js;
|
|
{
|
|
JSONArray jsarr(&js);
|
|
jsarr.AddValue(static_cast<intptr_t>(4));
|
|
}
|
|
EXPECT_STREQ("[4]", js.ToCString());
|
|
}
|
|
{
|
|
JSONStream js;
|
|
{
|
|
JSONArray jsarr(&js);
|
|
jsarr.AddValue(1.0);
|
|
}
|
|
EXPECT_STREQ("[1.000000]", js.ToCString());
|
|
}
|
|
{
|
|
JSONStream js;
|
|
{
|
|
JSONArray jsarr(&js);
|
|
jsarr.AddValue("hello");
|
|
}
|
|
EXPECT_STREQ("[\"hello\"]", js.ToCString());
|
|
}
|
|
{
|
|
JSONStream js;
|
|
{
|
|
JSONArray jsarr(&js);
|
|
jsarr.AddValueF("h%s", "elo");
|
|
}
|
|
EXPECT_STREQ("[\"helo\"]", js.ToCString());
|
|
}
|
|
}
|
|
|
|
TEST_CASE(JSON_JSONStream_Array) {
|
|
JSONStream js;
|
|
{
|
|
JSONArray jsarr(&js);
|
|
jsarr.AddValue(true);
|
|
jsarr.AddValue(false);
|
|
}
|
|
EXPECT_STREQ("[true,false]", js.ToCString());
|
|
}
|
|
|
|
TEST_CASE(JSON_JSONStream_Object) {
|
|
JSONStream js;
|
|
{
|
|
JSONObject jsobj(&js);
|
|
jsobj.AddProperty("key1", "a");
|
|
jsobj.AddProperty("key2", "b");
|
|
}
|
|
EXPECT_STREQ("{\"key1\":\"a\",\"key2\":\"b\"}", js.ToCString());
|
|
}
|
|
|
|
TEST_CASE(JSON_JSONStream_NestedObject) {
|
|
JSONStream js;
|
|
{
|
|
JSONObject jsobj(&js);
|
|
JSONObject jsobj1(&jsobj, "key");
|
|
jsobj1.AddProperty("key1", "d");
|
|
}
|
|
EXPECT_STREQ("{\"key\":{\"key1\":\"d\"}}", js.ToCString());
|
|
}
|
|
|
|
TEST_CASE(JSON_JSONStream_ObjectArray) {
|
|
JSONStream js;
|
|
{
|
|
JSONArray jsarr(&js);
|
|
{
|
|
JSONObject jsobj(&jsarr);
|
|
jsobj.AddProperty("key", "e");
|
|
}
|
|
{
|
|
JSONObject jsobj(&jsarr);
|
|
jsobj.AddProperty("yek", "f");
|
|
}
|
|
}
|
|
EXPECT_STREQ("[{\"key\":\"e\"},{\"yek\":\"f\"}]", js.ToCString());
|
|
}
|
|
|
|
TEST_CASE(JSON_JSONStream_ArrayArray) {
|
|
JSONStream js;
|
|
{
|
|
JSONArray jsarr(&js);
|
|
{
|
|
JSONArray jsarr1(&jsarr);
|
|
jsarr1.AddValue(static_cast<intptr_t>(4));
|
|
}
|
|
{
|
|
JSONArray jsarr1(&jsarr);
|
|
jsarr1.AddValue(false);
|
|
}
|
|
}
|
|
EXPECT_STREQ("[[4],[false]]", js.ToCString());
|
|
}
|
|
|
|
TEST_CASE(JSON_JSONStream_Printf) {
|
|
JSONStream js;
|
|
{
|
|
JSONArray jsarr(&js);
|
|
jsarr.AddValueF("%d %s", 2, "hello");
|
|
}
|
|
EXPECT_STREQ("[\"2 hello\"]", js.ToCString());
|
|
}
|
|
|
|
TEST_CASE(JSON_JSONStream_ObjectPrintf) {
|
|
JSONStream js;
|
|
{
|
|
JSONObject jsobj(&js);
|
|
jsobj.AddPropertyF("key", "%d %s", 2, "hello");
|
|
}
|
|
EXPECT_STREQ("{\"key\":\"2 hello\"}", js.ToCString());
|
|
}
|
|
|
|
ISOLATE_UNIT_TEST_CASE(JSON_JSONStream_DartObject) {
|
|
JSONStream js;
|
|
{
|
|
JSONArray jsarr(&js);
|
|
jsarr.AddValue(Object::Handle(Object::null()));
|
|
JSONObject jsobj(&jsarr);
|
|
jsobj.AddProperty("object_key", Object::Handle(Object::null()));
|
|
}
|
|
char buffer[1024];
|
|
ElideJSONSubstring("classes", js.ToCString(), buffer);
|
|
EXPECT_STREQ(
|
|
"[{\"type\":\"@Instance\","
|
|
"\"_vmType\":\"null\","
|
|
"\"class\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
|
|
"\"name\":\"Null\"},"
|
|
"\"kind\":\"Null\","
|
|
"\"fixedId\":true,"
|
|
"\"id\":\"objects\\/null\","
|
|
"\"valueAsString\":\"null\"},"
|
|
"{\"object_key\":"
|
|
"{\"type\":\"@Instance\","
|
|
"\"_vmType\":\"null\","
|
|
"\"class\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
|
|
"\"name\":\"Null\"},"
|
|
"\"kind\":\"Null\","
|
|
"\"fixedId\":true,"
|
|
"\"id\":\"objects\\/null\","
|
|
"\"valueAsString\":\"null\"}}]",
|
|
buffer);
|
|
}
|
|
|
|
TEST_CASE(JSON_JSONStream_EscapedString) {
|
|
JSONStream js;
|
|
{
|
|
JSONArray jsarr(&js);
|
|
jsarr.AddValue("Hel\"\"lo\r\n\t");
|
|
}
|
|
EXPECT_STREQ("[\"Hel\\\"\\\"lo\\r\\n\\t\"]", js.ToCString());
|
|
}
|
|
|
|
TEST_CASE(JSON_JSONStream_DartString) {
|
|
const char* kScriptChars =
|
|
"var ascii = 'Hello, World!';\n"
|
|
"var unicode = '\\u00CE\\u00F1\\u0163\\u00E9r\\u00F1\\u00E5\\u0163"
|
|
"\\u00EE\\u00F6\\u00F1\\u00E5\\u013C\\u00EE\\u017E\\u00E5\\u0163"
|
|
"\\u00EE\\u1EDD\\u00F1';\n"
|
|
"var surrogates = '\\u{1D11E}\\u{1D11E}\\u{1D11E}"
|
|
"\\u{1D11E}\\u{1D11E}';\n"
|
|
"var wrongEncoding = '\\u{1D11E}' + surrogates[0] + '\\u{1D11E}';"
|
|
"var nullInMiddle = 'This has\\u0000 four words.';";
|
|
|
|
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
|
|
EXPECT_VALID(lib);
|
|
|
|
Dart_Handle result;
|
|
TransitionNativeToVM transition1(thread);
|
|
String& obj = String::Handle();
|
|
TransitionVMToNative transition2(thread);
|
|
|
|
{
|
|
result = Dart_GetField(lib, NewString("ascii"));
|
|
EXPECT_VALID(result);
|
|
obj ^= Api::UnwrapHandle(result);
|
|
|
|
JSONStream js;
|
|
{
|
|
JSONObject jsobj(&js);
|
|
EXPECT(!jsobj.AddPropertyStr("ascii", obj));
|
|
}
|
|
EXPECT_STREQ("{\"ascii\":\"Hello, World!\"}", js.ToCString());
|
|
}
|
|
|
|
{
|
|
result = Dart_GetField(lib, NewString("ascii"));
|
|
EXPECT_VALID(result);
|
|
obj ^= Api::UnwrapHandle(result);
|
|
|
|
JSONStream js;
|
|
{
|
|
JSONObject jsobj(&js);
|
|
EXPECT(jsobj.AddPropertyStr("subrange", obj, 1, 4));
|
|
}
|
|
EXPECT_STREQ("{\"subrange\":\"ello\"}", js.ToCString());
|
|
}
|
|
|
|
{
|
|
result = Dart_GetField(lib, NewString("unicode"));
|
|
EXPECT_VALID(result);
|
|
obj ^= Api::UnwrapHandle(result);
|
|
|
|
JSONStream js;
|
|
{
|
|
JSONObject jsobj(&js);
|
|
EXPECT(!jsobj.AddPropertyStr("unicode", obj));
|
|
}
|
|
EXPECT_STREQ("{\"unicode\":\"Îñţérñåţîöñåļîžåţîờñ\"}", js.ToCString());
|
|
}
|
|
|
|
{
|
|
result = Dart_GetField(lib, NewString("surrogates"));
|
|
EXPECT_VALID(result);
|
|
obj ^= Api::UnwrapHandle(result);
|
|
|
|
JSONStream js;
|
|
{
|
|
JSONObject jsobj(&js);
|
|
EXPECT(!jsobj.AddPropertyStr("surrogates", obj));
|
|
}
|
|
EXPECT_STREQ("{\"surrogates\":\"𝄞𝄞𝄞𝄞𝄞\"}", js.ToCString());
|
|
}
|
|
|
|
{
|
|
result = Dart_GetField(lib, NewString("wrongEncoding"));
|
|
EXPECT_VALID(result);
|
|
obj ^= Api::UnwrapHandle(result);
|
|
|
|
JSONStream js;
|
|
{
|
|
JSONObject jsobj(&js);
|
|
EXPECT(!jsobj.AddPropertyStr("wrongEncoding", obj));
|
|
}
|
|
EXPECT_STREQ("{\"wrongEncoding\":\"𝄞\\uD834𝄞\"}", js.ToCString());
|
|
}
|
|
|
|
{
|
|
result = Dart_GetField(lib, NewString("nullInMiddle"));
|
|
EXPECT_VALID(result);
|
|
obj ^= Api::UnwrapHandle(result);
|
|
|
|
JSONStream js;
|
|
{
|
|
JSONObject jsobj(&js);
|
|
EXPECT(!jsobj.AddPropertyStr("nullInMiddle", obj));
|
|
}
|
|
EXPECT_STREQ("{\"nullInMiddle\":\"This has\\u0000 four words.\"}",
|
|
js.ToCString());
|
|
}
|
|
}
|
|
|
|
TEST_CASE(JSON_JSONStream_Params) {
|
|
const char* param_keys[] = {"dog", "cat"};
|
|
const char* param_values[] = {"apple", "banana"};
|
|
|
|
JSONStream js;
|
|
EXPECT(js.num_params() == 0);
|
|
js.SetParams(¶m_keys[0], ¶m_values[0], 2);
|
|
EXPECT(js.num_params() == 2);
|
|
EXPECT(!js.HasParam("lizard"));
|
|
EXPECT(js.HasParam("dog"));
|
|
EXPECT(js.HasParam("cat"));
|
|
EXPECT(js.ParamIs("cat", "banana"));
|
|
EXPECT(!js.ParamIs("dog", "banana"));
|
|
}
|
|
|
|
#endif // !PRODUCT
|
|
|
|
} // namespace dart
|