2018-09-11 22:27:47 +00:00
|
|
|
// Copyright (c) Facebook, Inc. and its affiliates.
|
2018-05-31 22:31:03 +00:00
|
|
|
|
|
|
|
// This source code is licensed under the MIT license found in the
|
|
|
|
// LICENSE file in the root directory of this source tree.
|
2016-09-12 23:35:15 +00:00
|
|
|
#include <string>
|
2015-09-14 14:35:58 +00:00
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <folly/json.h>
|
2016-11-01 18:38:43 +00:00
|
|
|
#include <jschelpers/Value.h>
|
2016-09-12 23:35:15 +00:00
|
|
|
|
2016-09-19 11:43:09 +00:00
|
|
|
#ifdef WITH_FBJSCEXTENSION
|
2016-09-12 23:35:15 +00:00
|
|
|
#undef ASSERT
|
|
|
|
#include <JavaScriptCore/config.h>
|
|
|
|
#include "OpaqueJSString.h"
|
2016-09-19 11:43:09 +00:00
|
|
|
#endif
|
2016-09-12 23:35:15 +00:00
|
|
|
|
|
|
|
#include <stdexcept>
|
2015-09-14 14:35:58 +00:00
|
|
|
|
|
|
|
using namespace facebook::react;
|
|
|
|
|
2016-09-12 23:35:15 +00:00
|
|
|
#ifdef ANDROID
|
|
|
|
#include <android/looper.h>
|
2016-10-14 20:24:02 +00:00
|
|
|
static void prepare() {
|
2016-09-12 23:35:15 +00:00
|
|
|
ALooper_prepare(0);
|
|
|
|
}
|
|
|
|
#else
|
2016-11-18 14:25:29 +00:00
|
|
|
static void prepare() {}
|
2016-09-12 23:35:15 +00:00
|
|
|
#endif
|
|
|
|
|
2015-09-14 14:35:58 +00:00
|
|
|
TEST(Value, Undefined) {
|
2016-09-12 23:35:15 +00:00
|
|
|
prepare();
|
2016-11-22 14:05:38 +00:00
|
|
|
JSGlobalContextRef ctx = JSC_JSGlobalContextCreateInGroup(false, nullptr, nullptr);
|
2016-11-18 14:25:24 +00:00
|
|
|
auto v = Value::makeUndefined(ctx);
|
2016-11-22 14:05:38 +00:00
|
|
|
auto s = String::adopt(ctx, JSC_JSValueToStringCopy(ctx, v, nullptr));
|
2015-09-14 14:35:58 +00:00
|
|
|
EXPECT_EQ("undefined", s.str());
|
2016-11-22 14:05:38 +00:00
|
|
|
JSC_JSGlobalContextRelease(ctx);
|
2015-09-14 14:35:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(Value, FromJSON) {
|
2016-09-12 23:35:15 +00:00
|
|
|
prepare();
|
2016-11-22 14:05:38 +00:00
|
|
|
JSGlobalContextRef ctx = JSC_JSGlobalContextCreateInGroup(false, nullptr, nullptr);
|
2016-11-18 14:25:29 +00:00
|
|
|
String s(ctx, "{\"a\": 4}");
|
2017-06-06 10:04:56 +00:00
|
|
|
Value v(Value::fromJSON(s));
|
2016-11-22 14:05:38 +00:00
|
|
|
EXPECT_TRUE(v.isObject());
|
|
|
|
JSC_JSGlobalContextRelease(ctx);
|
2015-09-14 14:35:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(Value, ToJSONString) {
|
2016-09-12 23:35:15 +00:00
|
|
|
prepare();
|
2016-11-22 14:05:38 +00:00
|
|
|
JSGlobalContextRef ctx = JSC_JSGlobalContextCreateInGroup(false, nullptr, nullptr);
|
2016-11-18 14:25:29 +00:00
|
|
|
String s(ctx, "{\"a\": 4}");
|
2017-06-06 10:04:56 +00:00
|
|
|
Value v(Value::fromJSON(s));
|
2015-09-14 14:35:58 +00:00
|
|
|
folly::dynamic dyn = folly::parseJson(v.toJSONString());
|
2016-07-25 19:19:46 +00:00
|
|
|
ASSERT_NE(nullptr, dyn);
|
|
|
|
EXPECT_TRUE(dyn.isObject());
|
|
|
|
auto val = dyn.at("a");
|
2015-09-14 14:35:58 +00:00
|
|
|
ASSERT_NE(nullptr, val);
|
2017-08-18 21:43:28 +00:00
|
|
|
ASSERT_TRUE(val.isNumber());
|
|
|
|
EXPECT_EQ(4, val.asInt());
|
2016-07-25 19:19:46 +00:00
|
|
|
EXPECT_EQ(4.0f, val.asDouble());
|
2016-09-12 23:35:15 +00:00
|
|
|
|
2016-11-22 14:05:38 +00:00
|
|
|
JSC_JSGlobalContextRelease(ctx);
|
2015-09-14 14:35:58 +00:00
|
|
|
}
|
|
|
|
|
2016-09-19 11:43:09 +00:00
|
|
|
#ifdef WITH_FBJSCEXTENSION
|
2016-09-12 23:35:15 +00:00
|
|
|
// Just test that handling invalid data doesn't crash.
|
|
|
|
TEST(Value, FromBadUtf8) {
|
|
|
|
prepare();
|
2016-11-22 14:05:38 +00:00
|
|
|
JSGlobalContextRef ctx = JSC_JSGlobalContextCreateInGroup(false, nullptr, nullptr);
|
2016-09-12 23:35:15 +00:00
|
|
|
// 110xxxxx 10xxxxxx
|
|
|
|
auto dyn = folly::dynamic("\xC0");
|
|
|
|
Value::fromDynamic(ctx, dyn);
|
|
|
|
dyn = folly::dynamic("\xC0\x00");
|
|
|
|
Value::fromDynamic(ctx, dyn);
|
|
|
|
// 1110xxxx 10xxxxxx 10xxxxxx
|
|
|
|
dyn = "\xE0";
|
|
|
|
Value::fromDynamic(ctx, dyn);
|
|
|
|
Value(ctx, Value::fromDynamic(ctx, dyn)).toJSONString();
|
|
|
|
dyn = "\xE0\x00";
|
|
|
|
Value::fromDynamic(ctx, dyn);
|
|
|
|
Value(ctx, Value::fromDynamic(ctx, dyn)).toJSONString();
|
|
|
|
dyn = "\xE0\x00\x00";
|
|
|
|
Value::fromDynamic(ctx, dyn);
|
|
|
|
Value(ctx, Value::fromDynamic(ctx, dyn)).toJSONString();
|
|
|
|
dyn = "\xE0\xA0\x00";
|
|
|
|
Value::fromDynamic(ctx, dyn);
|
|
|
|
// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
|
|
|
dyn = "\xF0";
|
|
|
|
Value::fromDynamic(ctx, dyn);
|
|
|
|
Value(ctx, Value::fromDynamic(ctx, dyn)).toJSONString();
|
|
|
|
dyn = "\xF0\x00\x00\x00";
|
|
|
|
Value::fromDynamic(ctx, dyn);
|
|
|
|
dyn = "\xF0\x80\x80\x00";
|
|
|
|
Value::fromDynamic(ctx, dyn);
|
|
|
|
Value(ctx, Value::fromDynamic(ctx, dyn)).toJSONString();
|
2016-11-22 14:05:38 +00:00
|
|
|
JSC_JSGlobalContextRelease(ctx);
|
2016-09-12 23:35:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Just test that handling invalid data doesn't crash.
|
|
|
|
TEST(Value, BadUtf16) {
|
|
|
|
prepare();
|
2016-11-22 14:05:38 +00:00
|
|
|
JSGlobalContextRef ctx = JSC_JSGlobalContextCreateInGroup(false, nullptr, nullptr);
|
2016-09-12 23:35:15 +00:00
|
|
|
UChar buf[] = { 0xDD00, 0xDD00, 0xDD00, 0x1111 };
|
|
|
|
JSStringRef ref = OpaqueJSString::create(buf, 4).leakRef();
|
|
|
|
Value v(ctx, ref);
|
|
|
|
v.toJSONString(0);
|
2016-11-22 14:05:38 +00:00
|
|
|
JSC_JSGlobalContextRelease(ctx);
|
2016-09-12 23:35:15 +00:00
|
|
|
}
|
2016-09-19 11:43:09 +00:00
|
|
|
#endif
|