Commit ce3ce2f6 authored by Johannes Henkel's avatar Johannes Henkel Committed by Commit Bot

[DevTools] Roll inspector_protocol (V8) (strtod)

New revision: 7a44a37f66b58358dd8ab85ccde1998fafa95e53

Upstream review:
https://chromium-review.googlesource.com/c/deps/inspector_protocol/+/1899564

Previously, we used a wrapper library, v8-inspector-protocol-encoding.h
to inject the string<->number conversion into the cbor parser. This
meant that the unittests, in
third_party/inspector_protocol/crdtp/json_test.cc inadvertently did
not run with the same string<->number conversion code. Thus, we missed
that the production implementation would return INF for out of range
double literals, as opposed to rejecting the incoming JSON.
When switching the library to the build dependency on json_platform_v8.cc
as it's in this change, the test immediately failed which made it
trivial to fix the implementation.

Old implementation:
https://chromium-review.googlesource.com/c/v8/v8/+/1913424/6/src/inspector/v8-inspector-protocol-encoding.cc

New implementation (checks std::isfinite):
https://chromium-review.googlesource.com/c/v8/v8/+/1913424/6/third_party/inspector_protocol/crdtp/json_platform_v8.cc

Change-Id: Ia48fe1f4e359eea47d0ede9ceadea1fd635292e0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1913424Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Commit-Queue: Johannes Henkel <johannes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65219}
parent bd9efe1f
...@@ -143,8 +143,6 @@ v8_source_set("inspector") { ...@@ -143,8 +143,6 @@ v8_source_set("inspector") {
"v8-heap-profiler-agent-impl.h", "v8-heap-profiler-agent-impl.h",
"v8-inspector-impl.cc", "v8-inspector-impl.cc",
"v8-inspector-impl.h", "v8-inspector-impl.h",
"v8-inspector-protocol-encoding.cc",
"v8-inspector-protocol-encoding.h",
"v8-inspector-session-impl.cc", "v8-inspector-session-impl.cc",
"v8-inspector-session-impl.h", "v8-inspector-session-impl.h",
"v8-profiler-agent-impl.cc", "v8-profiler-agent-impl.cc",
......
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/inspector/v8-inspector-protocol-encoding.h"
#include <cmath>
#include "../../third_party/inspector_protocol/crdtp/json.h"
#include "src/numbers/conversions.h"
#include "src/utils/vector.h"
namespace v8_inspector {
namespace {
using v8_crdtp::span;
using v8_crdtp::Status;
class Platform : public v8_crdtp::json::Platform {
// Parses |str| into |result|. Returns false iff there are
// leftover characters or parsing errors.
bool StrToD(const char* str, double* result) const override {
*result = v8::internal::StringToDouble(str, v8::internal::NO_FLAGS);
return !std::isnan(*result);
}
// Prints |value| in a format suitable for JSON.
std::unique_ptr<char[]> DToStr(double value) const override {
v8::internal::ScopedVector<char> buffer(
v8::internal::kDoubleToCStringMinBufferSize);
const char* str = v8::internal::DoubleToCString(value, buffer);
if (str == nullptr) return nullptr;
std::unique_ptr<char[]> result(new char[strlen(str) + 1]);
memcpy(result.get(), str, strlen(str) + 1);
DCHECK_EQ(0, result[strlen(str)]);
return result;
}
};
} // namespace
Status ConvertCBORToJSON(span<uint8_t> cbor, std::vector<uint8_t>* json) {
Platform platform;
return v8_crdtp::json::ConvertCBORToJSON(platform, cbor, json);
}
Status ConvertJSONToCBOR(span<uint8_t> json, std::vector<uint8_t>* cbor) {
Platform platform;
return v8_crdtp::json::ConvertJSONToCBOR(platform, json, cbor);
}
Status ConvertJSONToCBOR(span<uint16_t> json, std::vector<uint8_t>* cbor) {
Platform platform;
return v8_crdtp::json::ConvertJSONToCBOR(platform, json, cbor);
}
} // namespace v8_inspector
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_INSPECTOR_V8_INSPECTOR_PROTOCOL_ENCODING_H_
#define V8_INSPECTOR_V8_INSPECTOR_PROTOCOL_ENCODING_H_
#include "../../third_party/inspector_protocol/crdtp/span.h"
#include "../../third_party/inspector_protocol/crdtp/status.h"
namespace v8_inspector {
v8_crdtp::Status ConvertCBORToJSON(v8_crdtp::span<uint8_t> cbor,
std::vector<uint8_t>* json);
v8_crdtp::Status ConvertJSONToCBOR(v8_crdtp::span<uint8_t> json,
std::vector<uint8_t>* cbor);
v8_crdtp::Status ConvertJSONToCBOR(v8_crdtp::span<uint16_t> json,
std::vector<uint8_t>* cbor);
} // namespace v8_inspector
#endif // V8_INSPECTOR_V8_INSPECTOR_PROTOCOL_ENCODING_H_
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "src/inspector/v8-inspector-session-impl.h" #include "src/inspector/v8-inspector-session-impl.h"
#include "../../third_party/inspector_protocol/crdtp/cbor.h"
#include "../../third_party/inspector_protocol/crdtp/json.h"
#include "src/base/logging.h" #include "src/base/logging.h"
#include "src/base/macros.h" #include "src/base/macros.h"
#include "src/inspector/injected-script.h" #include "src/inspector/injected-script.h"
...@@ -17,7 +19,6 @@ ...@@ -17,7 +19,6 @@
#include "src/inspector/v8-debugger.h" #include "src/inspector/v8-debugger.h"
#include "src/inspector/v8-heap-profiler-agent-impl.h" #include "src/inspector/v8-heap-profiler-agent-impl.h"
#include "src/inspector/v8-inspector-impl.h" #include "src/inspector/v8-inspector-impl.h"
#include "src/inspector/v8-inspector-protocol-encoding.h"
#include "src/inspector/v8-profiler-agent-impl.h" #include "src/inspector/v8-profiler-agent-impl.h"
#include "src/inspector/v8-runtime-agent-impl.h" #include "src/inspector/v8-runtime-agent-impl.h"
#include "src/inspector/v8-schema-agent-impl.h" #include "src/inspector/v8-schema-agent-impl.h"
...@@ -26,14 +27,16 @@ namespace v8_inspector { ...@@ -26,14 +27,16 @@ namespace v8_inspector {
namespace { namespace {
using v8_crdtp::span; using v8_crdtp::span;
using v8_crdtp::SpanFrom; using v8_crdtp::SpanFrom;
using IPEStatus = v8_crdtp::Status; using v8_crdtp::Status;
using v8_crdtp::json::ConvertCBORToJSON;
using v8_crdtp::json::ConvertJSONToCBOR;
bool IsCBORMessage(const StringView& msg) { bool IsCBORMessage(const StringView& msg) {
return msg.is8Bit() && msg.length() >= 2 && msg.characters8()[0] == 0xd8 && return msg.is8Bit() && msg.length() >= 2 && msg.characters8()[0] == 0xd8 &&
msg.characters8()[1] == 0x5a; msg.characters8()[1] == 0x5a;
} }
IPEStatus ConvertToCBOR(const StringView& state, std::vector<uint8_t>* cbor) { Status ConvertToCBOR(const StringView& state, std::vector<uint8_t>* cbor) {
return state.is8Bit() return state.is8Bit()
? ConvertJSONToCBOR( ? ConvertJSONToCBOR(
span<uint8_t>(state.characters8(), state.length()), cbor) span<uint8_t>(state.characters8(), state.length()), cbor)
...@@ -168,7 +171,7 @@ std::unique_ptr<StringBuffer> V8InspectorSessionImpl::serializeForFrontend( ...@@ -168,7 +171,7 @@ std::unique_ptr<StringBuffer> V8InspectorSessionImpl::serializeForFrontend(
return std::unique_ptr<StringBuffer>( return std::unique_ptr<StringBuffer>(
new BinaryStringBuffer(std::move(cbor))); new BinaryStringBuffer(std::move(cbor)));
std::vector<uint8_t> json; std::vector<uint8_t> json;
IPEStatus status = ConvertCBORToJSON(SpanFrom(cbor), &json); Status status = ConvertCBORToJSON(SpanFrom(cbor), &json);
DCHECK(status.ok()); DCHECK(status.ok());
USE(status); USE(status);
String16 string16(reinterpret_cast<const char*>(json.data()), json.size()); String16 string16(reinterpret_cast<const char*>(json.data()), json.size());
......
...@@ -4,6 +4,12 @@ ...@@ -4,6 +4,12 @@
import("../../gni/v8.gni") import("../../gni/v8.gni")
config("crdtp_config") {
visibility = [ "../../src/inspector:*" ]
configs = [ "../../:internal_config" ]
include_dirs = [ "../../include" ]
}
v8_source_set("crdtp") { v8_source_set("crdtp") {
sources = [ sources = [
"crdtp/cbor.cc", "crdtp/cbor.cc",
...@@ -12,37 +18,59 @@ v8_source_set("crdtp") { ...@@ -12,37 +18,59 @@ v8_source_set("crdtp") {
"crdtp/glue.h", "crdtp/glue.h",
"crdtp/json.cc", "crdtp/json.cc",
"crdtp/json.h", "crdtp/json.h",
"crdtp/json_platform.h",
"crdtp/parser_handler.h", "crdtp/parser_handler.h",
"crdtp/span.h", "crdtp/span.h",
"crdtp/status.cc", "crdtp/status.cc",
"crdtp/status.h", "crdtp/status.h",
] ]
configs = [ "../../:internal_config" ] configs = [ ":crdtp_config" ]
deps = [
":crdtp_platform",
]
} }
# crdtp_test is part of the unittests, defined in # A small adapter library which only :crdtp may depend on.
# test/unittests/BUILD.gn. v8_source_set("crdtp_platform") {
visibility = [ ":crdtp" ]
sources = [
"crdtp/json_platform.h",
"crdtp/json_platform_v8.cc",
]
public_deps = [
"../..:v8_libbase",
]
configs = [ ":crdtp_config" ]
}
# These tests are linked into test/unittests.
v8_source_set("crdtp_test") { v8_source_set("crdtp_test") {
testonly = true
sources = [ sources = [
"crdtp/cbor_test.cc", "crdtp/cbor_test.cc",
"crdtp/glue_test.cc", "crdtp/glue_test.cc",
"crdtp/json_test.cc", "crdtp/json_test.cc",
"crdtp/span_test.cc", "crdtp/span_test.cc",
"crdtp/status_test.cc", "crdtp/status_test.cc",
"crdtp/test_platform.cc",
"crdtp/test_platform.h",
]
configs = [
"../..:external_config",
"../..:internal_config_base",
] ]
configs = [ ":crdtp_config" ]
deps = [ deps = [
":crdtp_test_platform",
]
testonly = true
}
# A small adapter library which only :crdtp_test may depend on.
v8_source_set("crdtp_test_platform") {
sources = [
"crdtp/test_platform.h",
"crdtp/test_platform_v8.cc",
]
configs = [ ":crdtp_config" ]
public_deps = [
":crdtp", ":crdtp",
"../..:v8_libbase", "../..:v8_libbase",
"../../src/inspector:inspector_string_conversions", "../../src/inspector:inspector_string_conversions",
"//testing/gmock", "//testing/gmock",
"//testing/gtest", "//testing/gtest",
] ]
testonly = true
} }
...@@ -14,21 +14,5 @@ https://cs.chromium.org/chromium/src/v8/third_party/inspector_protocol/ ...@@ -14,21 +14,5 @@ https://cs.chromium.org/chromium/src/v8/third_party/inspector_protocol/
See also [Contributing to Chrome Devtools Protocol](https://docs.google.com/document/d/1c-COD2kaK__5iMM5SEx-PzNA7HFmgttcYfOHHX0HaOM/edit). See also [Contributing to Chrome Devtools Protocol](https://docs.google.com/document/d/1c-COD2kaK__5iMM5SEx-PzNA7HFmgttcYfOHHX0HaOM/edit).
We're working on enabling standalone builds for parts of this package for To build and run the tests of the crdtp library, see
testing and development. [CRDTP - Chrome DevTools Protocol](crdtp/README.md).
If you're familiar with
[Chromium's development process](https://www.chromium.org/developers/contributing-code)
and have the depot_tools installed, you may use these commands
to fetch the package (and dependencies) and build and run the tests:
fetch inspector_protocol
cd src
gn gen out/Release
ninja -C out/Release encoding_test bindings_test
out/Release/encoding_test
out/Release/bindings_test
You'll probably also need to install g++, since Clang uses this to find the
standard C++ headers. E.g.,
sudo apt-get install g++-8
...@@ -2,7 +2,7 @@ Name: inspector protocol ...@@ -2,7 +2,7 @@ Name: inspector protocol
Short Name: inspector_protocol Short Name: inspector_protocol
URL: https://chromium.googlesource.com/deps/inspector_protocol/ URL: https://chromium.googlesource.com/deps/inspector_protocol/
Version: 0 Version: 0
Revision: 4c2a3acaea9f2e7958081dd361f81e20e9eff5e7 Revision: 7a44a37f66b58358dd8ab85ccde1998fafa95e53
License: BSD License: BSD
License File: LICENSE License File: LICENSE
Security Critical: no Security Critical: no
......
...@@ -22,42 +22,6 @@ ...@@ -22,42 +22,6 @@
using testing::ElementsAreArray; using testing::ElementsAreArray;
namespace v8_crdtp { namespace v8_crdtp {
namespace {
class TestPlatform : public json::Platform {
bool StrToD(const char* str, double* result) const override {
// This is not thread-safe
// (see https://en.cppreference.com/w/cpp/locale/setlocale)
// but good enough for a unittest.
const char* saved_locale = std::setlocale(LC_NUMERIC, nullptr);
char* end;
*result = std::strtod(str, &end);
std::setlocale(LC_NUMERIC, saved_locale);
if (errno == ERANGE) {
// errno must be reset, e.g. see the example here:
// https://en.cppreference.com/w/cpp/string/byte/strtof
errno = 0;
return false;
}
return end == str + strlen(str);
}
std::unique_ptr<char[]> DToStr(double value) const override {
std::stringstream ss;
ss.imbue(std::locale("C"));
ss << value;
std::string str = ss.str();
std::unique_ptr<char[]> result(new char[str.size() + 1]);
memcpy(result.get(), str.c_str(), str.size() + 1);
return result;
}
};
const json::Platform& GetTestPlatform() {
static TestPlatform* platform = new TestPlatform;
return *platform;
}
} // namespace
namespace cbor { namespace cbor {
// ============================================================================= // =============================================================================
// Detecting CBOR content // Detecting CBOR content
...@@ -692,7 +656,7 @@ TEST(JsonCborRoundtrip, EncodingDecoding) { ...@@ -692,7 +656,7 @@ TEST(JsonCborRoundtrip, EncodingDecoding) {
Status status; Status status;
std::unique_ptr<ParserHandler> encoder = NewCBOREncoder(&encoded, &status); std::unique_ptr<ParserHandler> encoder = NewCBOREncoder(&encoded, &status);
span<uint8_t> ascii_in = SpanFrom(json); span<uint8_t> ascii_in = SpanFrom(json);
json::ParseJSON(GetTestPlatform(), ascii_in, encoder.get()); json::ParseJSON(ascii_in, encoder.get());
std::vector<uint8_t> expected = { std::vector<uint8_t> expected = {
0xd8, // envelope 0xd8, // envelope
0x5a, // byte string with 32 bit length 0x5a, // byte string with 32 bit length
...@@ -736,7 +700,7 @@ TEST(JsonCborRoundtrip, EncodingDecoding) { ...@@ -736,7 +700,7 @@ TEST(JsonCborRoundtrip, EncodingDecoding) {
// And now we roundtrip, decoding the message we just encoded. // And now we roundtrip, decoding the message we just encoded.
std::string decoded; std::string decoded;
std::unique_ptr<ParserHandler> json_encoder = std::unique_ptr<ParserHandler> json_encoder =
json::NewJSONEncoder(&GetTestPlatform(), &decoded, &status); json::NewJSONEncoder(&decoded, &status);
ParseCBOR(span<uint8_t>(encoded.data(), encoded.size()), json_encoder.get()); ParseCBOR(span<uint8_t>(encoded.data(), encoded.size()), json_encoder.get());
EXPECT_EQ(Error::OK, status.error); EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ(json, decoded); EXPECT_EQ(json, decoded);
...@@ -753,10 +717,10 @@ TEST(JsonCborRoundtrip, MoreRoundtripExamples) { ...@@ -753,10 +717,10 @@ TEST(JsonCborRoundtrip, MoreRoundtripExamples) {
Status status; Status status;
std::unique_ptr<ParserHandler> encoder = NewCBOREncoder(&encoded, &status); std::unique_ptr<ParserHandler> encoder = NewCBOREncoder(&encoded, &status);
span<uint8_t> ascii_in = SpanFrom(json); span<uint8_t> ascii_in = SpanFrom(json);
json::ParseJSON(GetTestPlatform(), ascii_in, encoder.get()); json::ParseJSON(ascii_in, encoder.get());
std::string decoded; std::string decoded;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &decoded, &status); json::NewJSONEncoder(&decoded, &status);
ParseCBOR(span<uint8_t>(encoded.data(), encoded.size()), json_writer.get()); ParseCBOR(span<uint8_t>(encoded.data(), encoded.size()), json_writer.get());
EXPECT_EQ(Error::OK, status.error); EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ(json, decoded); EXPECT_EQ(json, decoded);
...@@ -788,7 +752,7 @@ TEST(JSONToCBOREncoderTest, HelloWorldBinary_WithTripToJson) { ...@@ -788,7 +752,7 @@ TEST(JSONToCBOREncoderTest, HelloWorldBinary_WithTripToJson) {
// Now drive the json writer via the CBOR decoder. // Now drive the json writer via the CBOR decoder.
std::string decoded; std::string decoded;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &decoded, &status); json::NewJSONEncoder(&decoded, &status);
ParseCBOR(SpanFrom(encoded), json_writer.get()); ParseCBOR(SpanFrom(encoded), json_writer.get());
EXPECT_EQ(Error::OK, status.error); EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ(Status::npos(), status.pos); EXPECT_EQ(Status::npos(), status.pos);
...@@ -808,7 +772,7 @@ TEST(ParseCBORTest, ParseEmptyCBORMessage) { ...@@ -808,7 +772,7 @@ TEST(ParseCBORTest, ParseEmptyCBORMessage) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(in.data(), in.size()), json_writer.get()); ParseCBOR(span<uint8_t>(in.data(), in.size()), json_writer.get());
EXPECT_EQ(Error::OK, status.error); EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ("{}", out); EXPECT_EQ("{}", out);
...@@ -832,7 +796,7 @@ TEST(ParseCBORTest, ParseCBORHelloWorld) { ...@@ -832,7 +796,7 @@ TEST(ParseCBORTest, ParseCBORHelloWorld) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::OK, status.error); EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ("{\"msg\":\"Hello, \\ud83c\\udf0e.\"}", out); EXPECT_EQ("{\"msg\":\"Hello, \\ud83c\\udf0e.\"}", out);
...@@ -857,7 +821,7 @@ TEST(ParseCBORTest, UTF8IsSupportedInKeys) { ...@@ -857,7 +821,7 @@ TEST(ParseCBORTest, UTF8IsSupportedInKeys) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::OK, status.error); EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ("{\"\\ud83c\\udf0e\":\"\\u263e\"}", out); EXPECT_EQ("{\"\\ud83c\\udf0e\":\"\\u263e\"}", out);
...@@ -868,7 +832,7 @@ TEST(ParseCBORTest, NoInputError) { ...@@ -868,7 +832,7 @@ TEST(ParseCBORTest, NoInputError) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(in.data(), in.size()), json_writer.get()); ParseCBOR(span<uint8_t>(in.data(), in.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_NO_INPUT, status.error); EXPECT_EQ(Error::CBOR_NO_INPUT, status.error);
EXPECT_EQ("", out); EXPECT_EQ("", out);
...@@ -882,7 +846,7 @@ TEST(ParseCBORTest, InvalidStartByteError) { ...@@ -882,7 +846,7 @@ TEST(ParseCBORTest, InvalidStartByteError) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(SpanFrom(json), json_writer.get()); ParseCBOR(SpanFrom(json), json_writer.get());
EXPECT_EQ(Error::CBOR_INVALID_START_BYTE, status.error); EXPECT_EQ(Error::CBOR_INVALID_START_BYTE, status.error);
EXPECT_EQ("", out); EXPECT_EQ("", out);
...@@ -898,7 +862,7 @@ TEST(ParseCBORTest, UnexpectedEofExpectedValueError) { ...@@ -898,7 +862,7 @@ TEST(ParseCBORTest, UnexpectedEofExpectedValueError) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE, status.error); EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE, status.error);
EXPECT_EQ(bytes.size(), status.pos); EXPECT_EQ(bytes.size(), status.pos);
...@@ -916,7 +880,7 @@ TEST(ParseCBORTest, UnexpectedEofInArrayError) { ...@@ -916,7 +880,7 @@ TEST(ParseCBORTest, UnexpectedEofInArrayError) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_IN_ARRAY, status.error); EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_IN_ARRAY, status.error);
EXPECT_EQ(bytes.size(), status.pos); EXPECT_EQ(bytes.size(), status.pos);
...@@ -931,7 +895,7 @@ TEST(ParseCBORTest, UnexpectedEofInMapError) { ...@@ -931,7 +895,7 @@ TEST(ParseCBORTest, UnexpectedEofInMapError) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_IN_MAP, status.error); EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_IN_MAP, status.error);
EXPECT_EQ(7u, status.pos); EXPECT_EQ(7u, status.pos);
...@@ -945,7 +909,7 @@ TEST(ParseCBORTest, TopLevelCantBeEmptyEnvelope) { ...@@ -945,7 +909,7 @@ TEST(ParseCBORTest, TopLevelCantBeEmptyEnvelope) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_MAP_START_EXPECTED, status.error); EXPECT_EQ(Error::CBOR_MAP_START_EXPECTED, status.error);
EXPECT_EQ(bytes.size(), status.pos); EXPECT_EQ(bytes.size(), status.pos);
...@@ -967,7 +931,7 @@ TEST(ParseCBORTest, MapStartExpectedAtTopLevel) { ...@@ -967,7 +931,7 @@ TEST(ParseCBORTest, MapStartExpectedAtTopLevel) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_MAP_START_EXPECTED, status.error); EXPECT_EQ(Error::CBOR_MAP_START_EXPECTED, status.error);
EXPECT_EQ(6u, status.pos); EXPECT_EQ(6u, status.pos);
...@@ -997,7 +961,7 @@ TEST(ParseCBORTest, OnlyMapsAndArraysSupportedInsideEnvelopes) { ...@@ -997,7 +961,7 @@ TEST(ParseCBORTest, OnlyMapsAndArraysSupportedInsideEnvelopes) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_MAP_OR_ARRAY_EXPECTED_IN_ENVELOPE, status.error); EXPECT_EQ(Error::CBOR_MAP_OR_ARRAY_EXPECTED_IN_ENVELOPE, status.error);
EXPECT_EQ(error_pos, status.pos); EXPECT_EQ(error_pos, status.pos);
...@@ -1014,7 +978,7 @@ TEST(ParseCBORTest, InvalidMapKeyError) { ...@@ -1014,7 +978,7 @@ TEST(ParseCBORTest, InvalidMapKeyError) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_INVALID_MAP_KEY, status.error); EXPECT_EQ(Error::CBOR_INVALID_MAP_KEY, status.error);
EXPECT_EQ(7u, status.pos); EXPECT_EQ(7u, status.pos);
...@@ -1045,7 +1009,7 @@ TEST(ParseCBORTest, StackLimitExceededError) { ...@@ -1045,7 +1009,7 @@ TEST(ParseCBORTest, StackLimitExceededError) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::OK, status.error); EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ(Status::npos(), status.pos); EXPECT_EQ(Status::npos(), status.pos);
...@@ -1056,7 +1020,7 @@ TEST(ParseCBORTest, StackLimitExceededError) { ...@@ -1056,7 +1020,7 @@ TEST(ParseCBORTest, StackLimitExceededError) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::OK, status.error); EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ(Status::npos(), status.pos); EXPECT_EQ(Status::npos(), status.pos);
...@@ -1076,7 +1040,7 @@ TEST(ParseCBORTest, StackLimitExceededError) { ...@@ -1076,7 +1040,7 @@ TEST(ParseCBORTest, StackLimitExceededError) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_STACK_LIMIT_EXCEEDED, status.error); EXPECT_EQ(Error::CBOR_STACK_LIMIT_EXCEEDED, status.error);
EXPECT_EQ(opening_segment_size * 301, status.pos); EXPECT_EQ(opening_segment_size * 301, status.pos);
...@@ -1086,7 +1050,7 @@ TEST(ParseCBORTest, StackLimitExceededError) { ...@@ -1086,7 +1050,7 @@ TEST(ParseCBORTest, StackLimitExceededError) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_STACK_LIMIT_EXCEEDED, status.error); EXPECT_EQ(Error::CBOR_STACK_LIMIT_EXCEEDED, status.error);
EXPECT_EQ(opening_segment_size * 301, status.pos); EXPECT_EQ(opening_segment_size * 301, status.pos);
...@@ -1105,7 +1069,7 @@ TEST(ParseCBORTest, UnsupportedValueError) { ...@@ -1105,7 +1069,7 @@ TEST(ParseCBORTest, UnsupportedValueError) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_UNSUPPORTED_VALUE, status.error); EXPECT_EQ(Error::CBOR_UNSUPPORTED_VALUE, status.error);
EXPECT_EQ(error_pos, status.pos); EXPECT_EQ(error_pos, status.pos);
...@@ -1128,7 +1092,7 @@ TEST(ParseCBORTest, InvalidString16Error) { ...@@ -1128,7 +1092,7 @@ TEST(ParseCBORTest, InvalidString16Error) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_INVALID_STRING16, status.error); EXPECT_EQ(Error::CBOR_INVALID_STRING16, status.error);
EXPECT_EQ(error_pos, status.pos); EXPECT_EQ(error_pos, status.pos);
...@@ -1148,7 +1112,7 @@ TEST(ParseCBORTest, InvalidString8Error) { ...@@ -1148,7 +1112,7 @@ TEST(ParseCBORTest, InvalidString8Error) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_INVALID_STRING8, status.error); EXPECT_EQ(Error::CBOR_INVALID_STRING8, status.error);
EXPECT_EQ(error_pos, status.pos); EXPECT_EQ(error_pos, status.pos);
...@@ -1170,7 +1134,7 @@ TEST(ParseCBORTest, InvalidBinaryError) { ...@@ -1170,7 +1134,7 @@ TEST(ParseCBORTest, InvalidBinaryError) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_INVALID_BINARY, status.error); EXPECT_EQ(Error::CBOR_INVALID_BINARY, status.error);
EXPECT_EQ(error_pos, status.pos); EXPECT_EQ(error_pos, status.pos);
...@@ -1191,7 +1155,7 @@ TEST(ParseCBORTest, InvalidDoubleError) { ...@@ -1191,7 +1155,7 @@ TEST(ParseCBORTest, InvalidDoubleError) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_INVALID_DOUBLE, status.error); EXPECT_EQ(Error::CBOR_INVALID_DOUBLE, status.error);
EXPECT_EQ(error_pos, status.pos); EXPECT_EQ(error_pos, status.pos);
...@@ -1212,7 +1176,7 @@ TEST(ParseCBORTest, InvalidSignedError) { ...@@ -1212,7 +1176,7 @@ TEST(ParseCBORTest, InvalidSignedError) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_INVALID_INT32, status.error); EXPECT_EQ(Error::CBOR_INVALID_INT32, status.error);
EXPECT_EQ(error_pos, status.pos); EXPECT_EQ(error_pos, status.pos);
...@@ -1235,7 +1199,7 @@ TEST(ParseCBORTest, TrailingJunk) { ...@@ -1235,7 +1199,7 @@ TEST(ParseCBORTest, TrailingJunk) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_TRAILING_JUNK, status.error); EXPECT_EQ(Error::CBOR_TRAILING_JUNK, status.error);
EXPECT_EQ(error_pos, status.pos); EXPECT_EQ(error_pos, status.pos);
...@@ -1258,7 +1222,7 @@ TEST(ParseCBORTest, EnvelopeContentsLengthMismatch) { ...@@ -1258,7 +1222,7 @@ TEST(ParseCBORTest, EnvelopeContentsLengthMismatch) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
EXPECT_EQ(Error::CBOR_ENVELOPE_CONTENTS_LENGTH_MISMATCH, status.error); EXPECT_EQ(Error::CBOR_ENVELOPE_CONTENTS_LENGTH_MISMATCH, status.error);
EXPECT_EQ(bytes.size(), status.pos); EXPECT_EQ(bytes.size(), status.pos);
...@@ -1293,7 +1257,7 @@ TYPED_TEST(AppendString8EntryToMapTest, AppendsEntrySuccessfully) { ...@@ -1293,7 +1257,7 @@ TYPED_TEST(AppendString8EntryToMapTest, AppendsEntrySuccessfully) {
EXPECT_EQ(Status::npos(), status.pos); EXPECT_EQ(Status::npos(), status.pos);
std::string out; std::string out;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(SpanFrom(msg), json_writer.get()); ParseCBOR(SpanFrom(msg), json_writer.get());
EXPECT_EQ("{\"key\":\"value\",\"foo\":\"bar\"}", out); EXPECT_EQ("{\"key\":\"value\",\"foo\":\"bar\"}", out);
EXPECT_EQ(Error::OK, status.error); EXPECT_EQ(Error::OK, status.error);
...@@ -1316,7 +1280,7 @@ TYPED_TEST(AppendString8EntryToMapTest, AppendThreeEntries) { ...@@ -1316,7 +1280,7 @@ TYPED_TEST(AppendString8EntryToMapTest, AppendThreeEntries) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status); json::NewJSONEncoder(&out, &status);
ParseCBOR(SpanFrom(msg), json_writer.get()); ParseCBOR(SpanFrom(msg), json_writer.get());
EXPECT_EQ("{\"key\":\"value\",\"key1\":\"value1\",\"key2\":\"value2\"}", out); EXPECT_EQ("{\"key\":\"value\",\"key1\":\"value1\",\"key2\":\"value2\"}", out);
EXPECT_EQ(Error::OK, status.error); EXPECT_EQ(Error::OK, status.error);
......
...@@ -2,6 +2,5 @@ ...@@ -2,6 +2,5 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// This file is V8 specific. // This file is V8 specific. It's not rolled from the upstream project.
// It is not rolled from the upstream project.
// CRDTP doesn't export symbols from V8, so it's empty. // CRDTP doesn't export symbols from V8, so it's empty.
...@@ -12,10 +12,10 @@ ...@@ -12,10 +12,10 @@
#include <stack> #include <stack>
#include "cbor.h" #include "cbor.h"
#include "json_platform.h"
namespace v8_crdtp { namespace v8_crdtp {
namespace json { namespace json {
// ============================================================================= // =============================================================================
// json::NewJSONEncoder - for encoding streaming parser events as JSON // json::NewJSONEncoder - for encoding streaming parser events as JSON
// ============================================================================= // =============================================================================
...@@ -104,8 +104,7 @@ void Base64Encode(const span<uint8_t>& in, C* out) { ...@@ -104,8 +104,7 @@ void Base64Encode(const span<uint8_t>& in, C* out) {
template <typename C> template <typename C>
class JSONEncoder : public ParserHandler { class JSONEncoder : public ParserHandler {
public: public:
JSONEncoder(const Platform* platform, C* out, Status* status) JSONEncoder(C* out, Status* status) : out_(out), status_(status) {
: platform_(platform), out_(out), status_(status) {
*status_ = Status(); *status_ = Status();
state_.emplace(Container::NONE); state_.emplace(Container::NONE);
} }
...@@ -283,14 +282,14 @@ class JSONEncoder : public ParserHandler { ...@@ -283,14 +282,14 @@ class JSONEncoder : public ParserHandler {
Emit("null"); Emit("null");
return; return;
} }
std::unique_ptr<char[]> str_value = platform_->DToStr(value); std::string str_value = json::platform::DToStr(value);
// DToStr may fail to emit a 0 before the decimal dot. E.g. this is // DToStr may fail to emit a 0 before the decimal dot. E.g. this is
// the case in base::NumberToString in Chromium (which is based on // the case in base::NumberToString in Chromium (which is based on
// dmg_fp). So, much like // dmg_fp). So, much like
// https://cs.chromium.org/chromium/src/base/json/json_writer.cc // https://cs.chromium.org/chromium/src/base/json/json_writer.cc
// we probe for this and emit the leading 0 anyway if necessary. // we probe for this and emit the leading 0 anyway if necessary.
const char* chars = str_value.get(); const char* chars = str_value.c_str();
if (chars[0] == '.') { if (chars[0] == '.') {
Emit('0'); Emit('0');
} else if (chars[0] == '-' && chars[1] == '.') { } else if (chars[0] == '-' && chars[1] == '.') {
...@@ -336,25 +335,22 @@ class JSONEncoder : public ParserHandler { ...@@ -336,25 +335,22 @@ class JSONEncoder : public ParserHandler {
out_->insert(out_->end(), str.begin(), str.end()); out_->insert(out_->end(), str.begin(), str.end());
} }
const Platform* platform_;
C* out_; C* out_;
Status* status_; Status* status_;
std::stack<State> state_; std::stack<State> state_;
}; };
} // namespace } // namespace
std::unique_ptr<ParserHandler> NewJSONEncoder(const Platform* platform, std::unique_ptr<ParserHandler> NewJSONEncoder(std::vector<uint8_t>* out,
std::vector<uint8_t>* out,
Status* status) { Status* status) {
return std::unique_ptr<ParserHandler>( return std::unique_ptr<ParserHandler>(
new JSONEncoder<std::vector<uint8_t>>(platform, out, status)); new JSONEncoder<std::vector<uint8_t>>(out, status));
} }
std::unique_ptr<ParserHandler> NewJSONEncoder(const Platform* platform, std::unique_ptr<ParserHandler> NewJSONEncoder(std::string* out,
std::string* out,
Status* status) { Status* status) {
return std::unique_ptr<ParserHandler>( return std::unique_ptr<ParserHandler>(
new JSONEncoder<std::string>(platform, out, status)); new JSONEncoder<std::string>(out, status));
} }
// ============================================================================= // =============================================================================
...@@ -387,8 +383,7 @@ const char* const kFalseString = "false"; ...@@ -387,8 +383,7 @@ const char* const kFalseString = "false";
template <typename Char> template <typename Char>
class JsonParser { class JsonParser {
public: public:
JsonParser(const Platform* platform, ParserHandler* handler) explicit JsonParser(ParserHandler* handler) : handler_(handler) {}
: platform_(platform), handler_(handler) {}
void Parse(const Char* start, size_t length) { void Parse(const Char* start, size_t length) {
start_pos_ = start; start_pos_ = start;
...@@ -412,12 +407,12 @@ class JsonParser { ...@@ -412,12 +407,12 @@ class JsonParser {
return false; return false;
buffer.push_back(static_cast<char>(chars[ii])); buffer.push_back(static_cast<char>(chars[ii]));
} }
return platform_->StrToD(buffer.c_str(), result); return platform::StrToD(buffer.c_str(), result);
} }
bool CharsToDouble(const uint8_t* chars, size_t length, double* result) { bool CharsToDouble(const uint8_t* chars, size_t length, double* result) {
std::string buffer(reinterpret_cast<const char*>(chars), length); std::string buffer(reinterpret_cast<const char*>(chars), length);
return platform_->StrToD(buffer.c_str(), result); return platform::StrToD(buffer.c_str(), result);
} }
static bool ParseConstToken(const Char* start, static bool ParseConstToken(const Char* start,
...@@ -966,22 +961,17 @@ class JsonParser { ...@@ -966,22 +961,17 @@ class JsonParser {
const Char* start_pos_ = nullptr; const Char* start_pos_ = nullptr;
bool error_ = false; bool error_ = false;
const Platform* platform_;
ParserHandler* handler_; ParserHandler* handler_;
}; };
} // namespace } // namespace
void ParseJSON(const Platform& platform, void ParseJSON(span<uint8_t> chars, ParserHandler* handler) {
span<uint8_t> chars, JsonParser<uint8_t> parser(handler);
ParserHandler* handler) {
JsonParser<uint8_t> parser(&platform, handler);
parser.Parse(chars.data(), chars.size()); parser.Parse(chars.data(), chars.size());
} }
void ParseJSON(const Platform& platform, void ParseJSON(span<uint16_t> chars, ParserHandler* handler) {
span<uint16_t> chars, JsonParser<uint16_t> parser(handler);
ParserHandler* handler) {
JsonParser<uint16_t> parser(&platform, handler);
parser.Parse(chars.data(), chars.size()); parser.Parse(chars.data(), chars.size());
} }
...@@ -989,58 +979,43 @@ void ParseJSON(const Platform& platform, ...@@ -989,58 +979,43 @@ void ParseJSON(const Platform& platform,
// json::ConvertCBORToJSON, json::ConvertJSONToCBOR - for transcoding // json::ConvertCBORToJSON, json::ConvertJSONToCBOR - for transcoding
// ============================================================================= // =============================================================================
template <typename C> template <typename C>
Status ConvertCBORToJSONTmpl(const Platform& platform, Status ConvertCBORToJSONTmpl(span<uint8_t> cbor, C* json) {
span<uint8_t> cbor,
C* json) {
Status status; Status status;
std::unique_ptr<ParserHandler> json_writer = std::unique_ptr<ParserHandler> json_writer = NewJSONEncoder(json, &status);
NewJSONEncoder(&platform, json, &status);
cbor::ParseCBOR(cbor, json_writer.get()); cbor::ParseCBOR(cbor, json_writer.get());
return status; return status;
} }
Status ConvertCBORToJSON(const Platform& platform, Status ConvertCBORToJSON(span<uint8_t> cbor, std::vector<uint8_t>* json) {
span<uint8_t> cbor, return ConvertCBORToJSONTmpl(cbor, json);
std::vector<uint8_t>* json) {
return ConvertCBORToJSONTmpl(platform, cbor, json);
} }
Status ConvertCBORToJSON(const Platform& platform, Status ConvertCBORToJSON(span<uint8_t> cbor, std::string* json) {
span<uint8_t> cbor, return ConvertCBORToJSONTmpl(cbor, json);
std::string* json) {
return ConvertCBORToJSONTmpl(platform, cbor, json);
} }
template <typename T, typename C> template <typename T, typename C>
Status ConvertJSONToCBORTmpl(const Platform& platform, span<T> json, C* cbor) { Status ConvertJSONToCBORTmpl(span<T> json, C* cbor) {
Status status; Status status;
std::unique_ptr<ParserHandler> encoder = cbor::NewCBOREncoder(cbor, &status); std::unique_ptr<ParserHandler> encoder = cbor::NewCBOREncoder(cbor, &status);
ParseJSON(platform, json, encoder.get()); ParseJSON(json, encoder.get());
return status; return status;
} }
Status ConvertJSONToCBOR(const Platform& platform, Status ConvertJSONToCBOR(span<uint8_t> json, std::string* cbor) {
span<uint8_t> json, return ConvertJSONToCBORTmpl(json, cbor);
std::string* cbor) {
return ConvertJSONToCBORTmpl(platform, json, cbor);
} }
Status ConvertJSONToCBOR(const Platform& platform, Status ConvertJSONToCBOR(span<uint16_t> json, std::string* cbor) {
span<uint16_t> json, return ConvertJSONToCBORTmpl(json, cbor);
std::string* cbor) {
return ConvertJSONToCBORTmpl(platform, json, cbor);
} }
Status ConvertJSONToCBOR(const Platform& platform, Status ConvertJSONToCBOR(span<uint8_t> json, std::vector<uint8_t>* cbor) {
span<uint8_t> json, return ConvertJSONToCBORTmpl(json, cbor);
std::vector<uint8_t>* cbor) {
return ConvertJSONToCBORTmpl(platform, json, cbor);
} }
Status ConvertJSONToCBOR(const Platform& platform, Status ConvertJSONToCBOR(span<uint16_t> json, std::vector<uint8_t>* cbor) {
span<uint16_t> json, return ConvertJSONToCBORTmpl(json, cbor);
std::vector<uint8_t>* cbor) {
return ConvertJSONToCBORTmpl(platform, json, cbor);
} }
} // namespace json } // namespace json
} // namespace v8_crdtp } // namespace v8_crdtp
...@@ -6,9 +6,7 @@ ...@@ -6,9 +6,7 @@
#define V8_CRDTP_JSON_H_ #define V8_CRDTP_JSON_H_
#include <memory> #include <memory>
#include "export.h" #include "export.h"
#include "json_platform.h"
#include "parser_handler.h" #include "parser_handler.h"
namespace v8_crdtp { namespace v8_crdtp {
...@@ -23,45 +21,34 @@ namespace json { ...@@ -23,45 +21,34 @@ namespace json {
// Except for calling the HandleError routine at any time, the client // Except for calling the HandleError routine at any time, the client
// code must call the Handle* methods in an order in which they'd occur // code must call the Handle* methods in an order in which they'd occur
// in valid JSON; otherwise we may crash (the code uses assert). // in valid JSON; otherwise we may crash (the code uses assert).
std::unique_ptr<ParserHandler> NewJSONEncoder(const Platform* platform, std::unique_ptr<ParserHandler> NewJSONEncoder(std::vector<uint8_t>* out,
std::vector<uint8_t>* out,
Status* status);
std::unique_ptr<ParserHandler> NewJSONEncoder(const Platform* platform,
std::string* out,
Status* status); Status* status);
std::unique_ptr<ParserHandler> NewJSONEncoder(std::string* out, Status* status);
// ============================================================================= // =============================================================================
// json::ParseJSON - for receiving streaming parser events for JSON // json::ParseJSON - for receiving streaming parser events for JSON
// ============================================================================= // =============================================================================
void ParseJSON(const Platform& platform, void ParseJSON(span<uint8_t> chars, ParserHandler* handler);
span<uint8_t> chars,
ParserHandler* handler); void ParseJSON(span<uint16_t> chars, ParserHandler* handler);
void ParseJSON(const Platform& platform,
span<uint16_t> chars,
ParserHandler* handler);
// ============================================================================= // =============================================================================
// json::ConvertCBORToJSON, json::ConvertJSONToCBOR - for transcoding // json::ConvertCBORToJSON, json::ConvertJSONToCBOR - for transcoding
// ============================================================================= // =============================================================================
Status ConvertCBORToJSON(const Platform& platform,
span<uint8_t> cbor, Status ConvertCBORToJSON(span<uint8_t> cbor, std::string* json);
std::string* json);
Status ConvertCBORToJSON(const Platform& platform, Status ConvertCBORToJSON(span<uint8_t> cbor, std::vector<uint8_t>* json);
span<uint8_t> cbor,
std::vector<uint8_t>* json); Status ConvertJSONToCBOR(span<uint8_t> json, std::vector<uint8_t>* cbor);
Status ConvertJSONToCBOR(const Platform& platform,
span<uint8_t> json, Status ConvertJSONToCBOR(span<uint16_t> json, std::vector<uint8_t>* cbor);
std::vector<uint8_t>* cbor);
Status ConvertJSONToCBOR(const Platform& platform, Status ConvertJSONToCBOR(span<uint8_t> json, std::string* cbor);
span<uint16_t> json,
std::vector<uint8_t>* cbor); Status ConvertJSONToCBOR(span<uint16_t> json, std::string* cbor);
Status ConvertJSONToCBOR(const Platform& platform,
span<uint8_t> json,
std::string* cbor);
Status ConvertJSONToCBOR(const Platform& platform,
span<uint16_t> json,
std::string* cbor);
} // namespace json } // namespace json
} // namespace v8_crdtp } // namespace v8_crdtp
......
...@@ -5,23 +5,21 @@ ...@@ -5,23 +5,21 @@
#ifndef V8_CRDTP_JSON_PLATFORM_H_ #ifndef V8_CRDTP_JSON_PLATFORM_H_
#define V8_CRDTP_JSON_PLATFORM_H_ #define V8_CRDTP_JSON_PLATFORM_H_
#include <memory> #include <string>
#include "export.h"
namespace v8_crdtp { namespace v8_crdtp {
namespace json { namespace json {
// Client code must provide an instance. Implementation should delegate // These routines are implemented in json_platform.cc, or in a
// to whatever is appropriate. // platform-dependent (code-base dependent) custom replacement.
class Platform { // E.g., json_platform_chromium.cc, json_platform_v8.cc.
public: namespace platform {
virtual ~Platform() = default; // Parses |str| into |result|. Returns false iff there are
// Parses |str| into |result|. Returns false iff there are // leftover characters or parsing errors.
// leftover characters or parsing errors. bool StrToD(const char* str, double* result);
virtual bool StrToD(const char* str, double* result) const = 0;
// Prints |value| in a format suitable for JSON. // Prints |value| in a format suitable for JSON.
virtual std::unique_ptr<char[]> DToStr(double value) const = 0; std::string DToStr(double value);
}; } // namespace platform
} // namespace json } // namespace json
} // namespace v8_crdtp } // namespace v8_crdtp
......
// Copyright 2019 The V8 Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file is V8 specific. It's not rolled from the upstream project.
#include "json_platform.h"
#include <cmath>
#include "../../../src/numbers/conversions.h"
#include "../../../src/utils/vector.h"
namespace v8_crdtp {
namespace json {
namespace platform {
// Parses |str| into |result|. Returns false iff there are
// leftover characters or parsing errors.
bool StrToD(const char* str, double* result) {
*result = v8::internal::StringToDouble(str, v8::internal::NO_FLAGS);
return std::isfinite(*result);
}
// Prints |value| in a format suitable for JSON.
std::string DToStr(double value) {
v8::internal::ScopedVector<char> buffer(
v8::internal::kDoubleToCStringMinBufferSize);
const char* str = v8::internal::DoubleToCString(value, buffer);
return (str == nullptr) ? "" : std::string(str);
}
} // namespace platform
} // namespace json
} // namespace v8_crdtp
...@@ -14,47 +14,14 @@ ...@@ -14,47 +14,14 @@
#include <sstream> #include <sstream>
#include <string> #include <string>
#include "cbor.h"
#include "parser_handler.h"
#include "span.h"
#include "status.h"
#include "test_platform.h" #include "test_platform.h"
namespace v8_crdtp { namespace v8_crdtp {
namespace {
class TestPlatform : public json::Platform {
bool StrToD(const char* str, double* result) const override {
// This is not thread-safe
// (see https://en.cppreference.com/w/cpp/locale/setlocale)
// but good enough for a unittest.
const char* saved_locale = std::setlocale(LC_NUMERIC, nullptr);
char* end;
*result = std::strtod(str, &end);
std::setlocale(LC_NUMERIC, saved_locale);
if (errno == ERANGE) {
// errno must be reset, e.g. see the example here:
// https://en.cppreference.com/w/cpp/string/byte/strtof
errno = 0;
return false;
}
return end == str + strlen(str);
}
std::unique_ptr<char[]> DToStr(double value) const override {
std::stringstream ss;
ss.imbue(std::locale("C"));
ss << value;
std::string str = ss.str();
std::unique_ptr<char[]> result(new char[str.size() + 1]);
memcpy(result.get(), str.c_str(), str.size() + 1);
return result;
}
};
const json::Platform& GetTestPlatform() {
static TestPlatform* platform = new TestPlatform;
return *platform;
}
} // namespace
namespace json { namespace json {
// ============================================================================= // =============================================================================
// json::NewJSONEncoder - for encoding streaming parser events as JSON // json::NewJSONEncoder - for encoding streaming parser events as JSON
// ============================================================================= // =============================================================================
...@@ -66,8 +33,7 @@ void WriteUTF8AsUTF16(ParserHandler* writer, const std::string& utf8) { ...@@ -66,8 +33,7 @@ void WriteUTF8AsUTF16(ParserHandler* writer, const std::string& utf8) {
TEST(JsonEncoder, OverlongEncodings) { TEST(JsonEncoder, OverlongEncodings) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> writer = std::unique_ptr<ParserHandler> writer = NewJSONEncoder(&out, &status);
NewJSONEncoder(&GetTestPlatform(), &out, &status);
// We encode 0x7f, which is the DEL ascii character, as a 4 byte UTF8 // We encode 0x7f, which is the DEL ascii character, as a 4 byte UTF8
// sequence. This is called an overlong encoding, because only 1 byte // sequence. This is called an overlong encoding, because only 1 byte
...@@ -85,8 +51,7 @@ TEST(JsonEncoder, OverlongEncodings) { ...@@ -85,8 +51,7 @@ TEST(JsonEncoder, OverlongEncodings) {
TEST(JsonEncoder, IncompleteUtf8Sequence) { TEST(JsonEncoder, IncompleteUtf8Sequence) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> writer = std::unique_ptr<ParserHandler> writer = NewJSONEncoder(&out, &status);
NewJSONEncoder(&GetTestPlatform(), &out, &status);
writer->HandleArrayBegin(); // This emits [, which starts an array. writer->HandleArrayBegin(); // This emits [, which starts an array.
...@@ -111,8 +76,7 @@ TEST(JsonEncoder, IncompleteUtf8Sequence) { ...@@ -111,8 +76,7 @@ TEST(JsonEncoder, IncompleteUtf8Sequence) {
TEST(JsonStdStringWriterTest, HelloWorld) { TEST(JsonStdStringWriterTest, HelloWorld) {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> writer = std::unique_ptr<ParserHandler> writer = NewJSONEncoder(&out, &status);
NewJSONEncoder(&GetTestPlatform(), &out, &status);
writer->HandleMapBegin(); writer->HandleMapBegin();
WriteUTF8AsUTF16(writer.get(), "msg1"); WriteUTF8AsUTF16(writer.get(), "msg1");
WriteUTF8AsUTF16(writer.get(), "Hello, 🌎."); WriteUTF8AsUTF16(writer.get(), "Hello, 🌎.");
...@@ -155,8 +119,7 @@ TEST(JsonStdStringWriterTest, RepresentingNonFiniteValuesAsNull) { ...@@ -155,8 +119,7 @@ TEST(JsonStdStringWriterTest, RepresentingNonFiniteValuesAsNull) {
// So in practice it's mapped to null. // So in practice it's mapped to null.
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> writer = std::unique_ptr<ParserHandler> writer = NewJSONEncoder(&out, &status);
NewJSONEncoder(&GetTestPlatform(), &out, &status);
writer->HandleMapBegin(); writer->HandleMapBegin();
writer->HandleString8(SpanFrom("Infinity")); writer->HandleString8(SpanFrom("Infinity"));
writer->HandleDouble(std::numeric_limits<double>::infinity()); writer->HandleDouble(std::numeric_limits<double>::infinity());
...@@ -176,8 +139,7 @@ TEST(JsonStdStringWriterTest, BinaryEncodedAsJsonString) { ...@@ -176,8 +139,7 @@ TEST(JsonStdStringWriterTest, BinaryEncodedAsJsonString) {
{ {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> writer = std::unique_ptr<ParserHandler> writer = NewJSONEncoder(&out, &status);
NewJSONEncoder(&GetTestPlatform(), &out, &status);
writer->HandleBinary(SpanFrom(std::vector<uint8_t>({'M', 'a', 'n'}))); writer->HandleBinary(SpanFrom(std::vector<uint8_t>({'M', 'a', 'n'})));
EXPECT_TRUE(status.ok()); EXPECT_TRUE(status.ok());
EXPECT_EQ("\"TWFu\"", out); EXPECT_EQ("\"TWFu\"", out);
...@@ -185,8 +147,7 @@ TEST(JsonStdStringWriterTest, BinaryEncodedAsJsonString) { ...@@ -185,8 +147,7 @@ TEST(JsonStdStringWriterTest, BinaryEncodedAsJsonString) {
{ {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> writer = std::unique_ptr<ParserHandler> writer = NewJSONEncoder(&out, &status);
NewJSONEncoder(&GetTestPlatform(), &out, &status);
writer->HandleBinary(SpanFrom(std::vector<uint8_t>({'M', 'a'}))); writer->HandleBinary(SpanFrom(std::vector<uint8_t>({'M', 'a'})));
EXPECT_TRUE(status.ok()); EXPECT_TRUE(status.ok());
EXPECT_EQ("\"TWE=\"", out); EXPECT_EQ("\"TWE=\"", out);
...@@ -194,8 +155,7 @@ TEST(JsonStdStringWriterTest, BinaryEncodedAsJsonString) { ...@@ -194,8 +155,7 @@ TEST(JsonStdStringWriterTest, BinaryEncodedAsJsonString) {
{ {
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> writer = std::unique_ptr<ParserHandler> writer = NewJSONEncoder(&out, &status);
NewJSONEncoder(&GetTestPlatform(), &out, &status);
writer->HandleBinary(SpanFrom(std::vector<uint8_t>({'M'}))); writer->HandleBinary(SpanFrom(std::vector<uint8_t>({'M'})));
EXPECT_TRUE(status.ok()); EXPECT_TRUE(status.ok());
EXPECT_EQ("\"TQ==\"", out); EXPECT_EQ("\"TQ==\"", out);
...@@ -203,8 +163,7 @@ TEST(JsonStdStringWriterTest, BinaryEncodedAsJsonString) { ...@@ -203,8 +163,7 @@ TEST(JsonStdStringWriterTest, BinaryEncodedAsJsonString) {
{ // "Hello, world.", verified with base64decode.org. { // "Hello, world.", verified with base64decode.org.
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> writer = std::unique_ptr<ParserHandler> writer = NewJSONEncoder(&out, &status);
NewJSONEncoder(&GetTestPlatform(), &out, &status);
writer->HandleBinary(SpanFrom(std::vector<uint8_t>( writer->HandleBinary(SpanFrom(std::vector<uint8_t>(
{'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.'}))); {'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.'})));
EXPECT_TRUE(status.ok()); EXPECT_TRUE(status.ok());
...@@ -217,8 +176,7 @@ TEST(JsonStdStringWriterTest, HandlesErrors) { ...@@ -217,8 +176,7 @@ TEST(JsonStdStringWriterTest, HandlesErrors) {
// status and clears the output. // status and clears the output.
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> writer = std::unique_ptr<ParserHandler> writer = NewJSONEncoder(&out, &status);
NewJSONEncoder(&GetTestPlatform(), &out, &status);
writer->HandleMapBegin(); writer->HandleMapBegin();
WriteUTF8AsUTF16(writer.get(), "msg1"); WriteUTF8AsUTF16(writer.get(), "msg1");
writer->HandleError(Status{Error::JSON_PARSER_VALUE_EXPECTED, 42}); writer->HandleError(Status{Error::JSON_PARSER_VALUE_EXPECTED, 42});
...@@ -227,36 +185,11 @@ TEST(JsonStdStringWriterTest, HandlesErrors) { ...@@ -227,36 +185,11 @@ TEST(JsonStdStringWriterTest, HandlesErrors) {
EXPECT_EQ("", out); EXPECT_EQ("", out);
} }
// We'd use Gmock but unfortunately it only handles copyable return types. TEST(JsonStdStringWriterTest, DoubleToString_LeadingZero) {
class MockPlatform : public Platform { // In JSON, .1 must be rendered as 0.1, and -.7 must be rendered as -0.7.
public:
// Not implemented.
bool StrToD(const char* str, double* result) const override { return false; }
// A map with pre-registered responses for DToSTr.
std::map<double, std::string> dtostr_responses_;
std::unique_ptr<char[]> DToStr(double value) const override {
auto it = dtostr_responses_.find(value);
CHECK(it != dtostr_responses_.end());
const std::string& str = it->second;
std::unique_ptr<char[]> response(new char[str.size() + 1]);
memcpy(response.get(), str.c_str(), str.size() + 1);
return response;
}
};
TEST(JsonStdStringWriterTest, DoubleToString) {
// This "broken" platform responds without the leading 0 before the
// decimal dot, so it'd be invalid JSON.
MockPlatform platform;
platform.dtostr_responses_[.1] = ".1";
platform.dtostr_responses_[-.7] = "-.7";
std::string out; std::string out;
Status status; Status status;
std::unique_ptr<ParserHandler> writer = std::unique_ptr<ParserHandler> writer = NewJSONEncoder(&out, &status);
NewJSONEncoder(&platform, &out, &status);
writer->HandleArrayBegin(); writer->HandleArrayBegin();
writer->HandleDouble(.1); writer->HandleDouble(.1);
writer->HandleDouble(-.7); writer->HandleDouble(-.7);
...@@ -320,7 +253,7 @@ class JsonParserTest : public ::testing::Test { ...@@ -320,7 +253,7 @@ class JsonParserTest : public ::testing::Test {
TEST_F(JsonParserTest, SimpleDictionary) { TEST_F(JsonParserTest, SimpleDictionary) {
std::string json = "{\"foo\": 42}"; std::string json = "{\"foo\": 42}";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); ParseJSON(SpanFrom(json), &log_);
EXPECT_TRUE(log_.status().ok()); EXPECT_TRUE(log_.status().ok());
EXPECT_EQ( EXPECT_EQ(
"map begin\n" "map begin\n"
...@@ -336,7 +269,7 @@ TEST_F(JsonParserTest, UsAsciiDelCornerCase) { ...@@ -336,7 +269,7 @@ TEST_F(JsonParserTest, UsAsciiDelCornerCase) {
// character in https://tools.ietf.org/html/rfc7159#section-7, so // character in https://tools.ietf.org/html/rfc7159#section-7, so
// it can be placed directly into the JSON string, without JSON escaping. // it can be placed directly into the JSON string, without JSON escaping.
std::string json = "{\"foo\": \"a\x7f\"}"; std::string json = "{\"foo\": \"a\x7f\"}";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); ParseJSON(SpanFrom(json), &log_);
EXPECT_TRUE(log_.status().ok()); EXPECT_TRUE(log_.status().ok());
EXPECT_EQ( EXPECT_EQ(
"map begin\n" "map begin\n"
...@@ -355,7 +288,7 @@ TEST_F(JsonParserTest, UsAsciiDelCornerCase) { ...@@ -355,7 +288,7 @@ TEST_F(JsonParserTest, UsAsciiDelCornerCase) {
TEST_F(JsonParserTest, Whitespace) { TEST_F(JsonParserTest, Whitespace) {
std::string json = "\n {\n\"msg\"\n: \v\"Hello, world.\"\t\r}\t"; std::string json = "\n {\n\"msg\"\n: \v\"Hello, world.\"\t\r}\t";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); ParseJSON(SpanFrom(json), &log_);
EXPECT_TRUE(log_.status().ok()); EXPECT_TRUE(log_.status().ok());
EXPECT_EQ( EXPECT_EQ(
"map begin\n" "map begin\n"
...@@ -367,7 +300,7 @@ TEST_F(JsonParserTest, Whitespace) { ...@@ -367,7 +300,7 @@ TEST_F(JsonParserTest, Whitespace) {
TEST_F(JsonParserTest, NestedDictionary) { TEST_F(JsonParserTest, NestedDictionary) {
std::string json = "{\"foo\": {\"bar\": {\"baz\": 1}, \"bar2\": 2}}"; std::string json = "{\"foo\": {\"bar\": {\"baz\": 1}, \"bar2\": 2}}";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); ParseJSON(SpanFrom(json), &log_);
EXPECT_TRUE(log_.status().ok()); EXPECT_TRUE(log_.status().ok());
EXPECT_EQ( EXPECT_EQ(
"map begin\n" "map begin\n"
...@@ -387,7 +320,7 @@ TEST_F(JsonParserTest, NestedDictionary) { ...@@ -387,7 +320,7 @@ TEST_F(JsonParserTest, NestedDictionary) {
TEST_F(JsonParserTest, Doubles) { TEST_F(JsonParserTest, Doubles) {
std::string json = "{\"foo\": 3.1415, \"bar\": 31415e-4}"; std::string json = "{\"foo\": 3.1415, \"bar\": 31415e-4}";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); ParseJSON(SpanFrom(json), &log_);
EXPECT_TRUE(log_.status().ok()); EXPECT_TRUE(log_.status().ok());
EXPECT_EQ( EXPECT_EQ(
"map begin\n" "map begin\n"
...@@ -402,7 +335,7 @@ TEST_F(JsonParserTest, Doubles) { ...@@ -402,7 +335,7 @@ TEST_F(JsonParserTest, Doubles) {
TEST_F(JsonParserTest, Unicode) { TEST_F(JsonParserTest, Unicode) {
// Globe character. 0xF0 0x9F 0x8C 0x8E in utf8, 0xD83C 0xDF0E in utf16. // Globe character. 0xF0 0x9F 0x8C 0x8E in utf8, 0xD83C 0xDF0E in utf16.
std::string json = "{\"msg\": \"Hello, \\uD83C\\uDF0E.\"}"; std::string json = "{\"msg\": \"Hello, \\uD83C\\uDF0E.\"}";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); ParseJSON(SpanFrom(json), &log_);
EXPECT_TRUE(log_.status().ok()); EXPECT_TRUE(log_.status().ok());
EXPECT_EQ( EXPECT_EQ(
"map begin\n" "map begin\n"
...@@ -420,7 +353,7 @@ TEST_F(JsonParserTest, Unicode_ParseUtf16) { ...@@ -420,7 +353,7 @@ TEST_F(JsonParserTest, Unicode_ParseUtf16) {
// Either way they arrive as utf8 (after decoding in log_.str()). // Either way they arrive as utf8 (after decoding in log_.str()).
std::vector<uint16_t> json = std::vector<uint16_t> json =
UTF8ToUTF16(SpanFrom("{\"space\": \"🌎 \\uD83C\\uDF19.\"}")); UTF8ToUTF16(SpanFrom("{\"space\": \"🌎 \\uD83C\\uDF19.\"}"));
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); ParseJSON(SpanFrom(json), &log_);
EXPECT_TRUE(log_.status().ok()); EXPECT_TRUE(log_.status().ok());
EXPECT_EQ( EXPECT_EQ(
"map begin\n" "map begin\n"
...@@ -446,7 +379,7 @@ TEST_F(JsonParserTest, Unicode_ParseUtf8) { ...@@ -446,7 +379,7 @@ TEST_F(JsonParserTest, Unicode_ParseUtf8) {
"\"3 byte\":\"\"," "\"3 byte\":\"\","
"\"4 byte\":\"🌎\"" "\"4 byte\":\"🌎\""
"}"; "}";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); ParseJSON(SpanFrom(json), &log_);
EXPECT_TRUE(log_.status().ok()); EXPECT_TRUE(log_.status().ok());
EXPECT_EQ( EXPECT_EQ(
"map begin\n" "map begin\n"
...@@ -467,7 +400,7 @@ TEST_F(JsonParserTest, UnprocessedInputRemainsError) { ...@@ -467,7 +400,7 @@ TEST_F(JsonParserTest, UnprocessedInputRemainsError) {
std::string json = "{\"foo\": 3.1415} junk"; std::string json = "{\"foo\": 3.1415} junk";
size_t junk_idx = json.find("junk"); size_t junk_idx = json.find("junk");
EXPECT_NE(junk_idx, std::string::npos); EXPECT_NE(junk_idx, std::string::npos);
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); ParseJSON(SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_UNPROCESSED_INPUT_REMAINS, log_.status().error); EXPECT_EQ(Error::JSON_PARSER_UNPROCESSED_INPUT_REMAINS, log_.status().error);
EXPECT_EQ(junk_idx, log_.status().pos); EXPECT_EQ(junk_idx, log_.status().pos);
EXPECT_EQ("", log_.str()); EXPECT_EQ("", log_.str());
...@@ -487,7 +420,7 @@ TEST_F(JsonParserTest, StackLimitExceededError_BelowLimit) { ...@@ -487,7 +420,7 @@ TEST_F(JsonParserTest, StackLimitExceededError_BelowLimit) {
// kStackLimit is 300 (see json_parser.cc). First let's // kStackLimit is 300 (see json_parser.cc). First let's
// try with a small nested example. // try with a small nested example.
std::string json_3 = MakeNestedJson(3); std::string json_3 = MakeNestedJson(3);
ParseJSON(GetTestPlatform(), SpanFrom(json_3), &log_); ParseJSON(SpanFrom(json_3), &log_);
EXPECT_TRUE(log_.status().ok()); EXPECT_TRUE(log_.status().ok());
EXPECT_EQ( EXPECT_EQ(
"map begin\n" "map begin\n"
...@@ -506,8 +439,7 @@ TEST_F(JsonParserTest, StackLimitExceededError_BelowLimit) { ...@@ -506,8 +439,7 @@ TEST_F(JsonParserTest, StackLimitExceededError_BelowLimit) {
TEST_F(JsonParserTest, StackLimitExceededError_AtLimit) { TEST_F(JsonParserTest, StackLimitExceededError_AtLimit) {
// Now with kStackLimit (300). // Now with kStackLimit (300).
std::string json_limit = MakeNestedJson(300); std::string json_limit = MakeNestedJson(300);
ParseJSON(GetTestPlatform(), ParseJSON(span<uint8_t>(reinterpret_cast<const uint8_t*>(json_limit.data()),
span<uint8_t>(reinterpret_cast<const uint8_t*>(json_limit.data()),
json_limit.size()), json_limit.size()),
&log_); &log_);
EXPECT_TRUE(log_.status().ok()); EXPECT_TRUE(log_.status().ok());
...@@ -516,7 +448,7 @@ TEST_F(JsonParserTest, StackLimitExceededError_AtLimit) { ...@@ -516,7 +448,7 @@ TEST_F(JsonParserTest, StackLimitExceededError_AtLimit) {
TEST_F(JsonParserTest, StackLimitExceededError_AboveLimit) { TEST_F(JsonParserTest, StackLimitExceededError_AboveLimit) {
// Now with kStackLimit + 1 (301) - it exceeds in the innermost instance. // Now with kStackLimit + 1 (301) - it exceeds in the innermost instance.
std::string exceeded = MakeNestedJson(301); std::string exceeded = MakeNestedJson(301);
ParseJSON(GetTestPlatform(), SpanFrom(exceeded), &log_); ParseJSON(SpanFrom(exceeded), &log_);
EXPECT_EQ(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, log_.status().error); EXPECT_EQ(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, log_.status().error);
EXPECT_EQ(strlen("{\"foo\":") * 301, log_.status().pos); EXPECT_EQ(strlen("{\"foo\":") * 301, log_.status().pos);
} }
...@@ -524,14 +456,14 @@ TEST_F(JsonParserTest, StackLimitExceededError_AboveLimit) { ...@@ -524,14 +456,14 @@ TEST_F(JsonParserTest, StackLimitExceededError_AboveLimit) {
TEST_F(JsonParserTest, StackLimitExceededError_WayAboveLimit) { TEST_F(JsonParserTest, StackLimitExceededError_WayAboveLimit) {
// Now way past the limit. Still, the point of exceeding is 301. // Now way past the limit. Still, the point of exceeding is 301.
std::string far_out = MakeNestedJson(320); std::string far_out = MakeNestedJson(320);
ParseJSON(GetTestPlatform(), SpanFrom(far_out), &log_); ParseJSON(SpanFrom(far_out), &log_);
EXPECT_EQ(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, log_.status().error); EXPECT_EQ(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, log_.status().error);
EXPECT_EQ(strlen("{\"foo\":") * 301, log_.status().pos); EXPECT_EQ(strlen("{\"foo\":") * 301, log_.status().pos);
} }
TEST_F(JsonParserTest, NoInputError) { TEST_F(JsonParserTest, NoInputError) {
std::string json = ""; std::string json = "";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); ParseJSON(SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_NO_INPUT, log_.status().error); EXPECT_EQ(Error::JSON_PARSER_NO_INPUT, log_.status().error);
EXPECT_EQ(0u, log_.status().pos); EXPECT_EQ(0u, log_.status().pos);
EXPECT_EQ("", log_.str()); EXPECT_EQ("", log_.str());
...@@ -539,7 +471,7 @@ TEST_F(JsonParserTest, NoInputError) { ...@@ -539,7 +471,7 @@ TEST_F(JsonParserTest, NoInputError) {
TEST_F(JsonParserTest, InvalidTokenError) { TEST_F(JsonParserTest, InvalidTokenError) {
std::string json = "|"; std::string json = "|";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); ParseJSON(SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_INVALID_TOKEN, log_.status().error); EXPECT_EQ(Error::JSON_PARSER_INVALID_TOKEN, log_.status().error);
EXPECT_EQ(0u, log_.status().pos); EXPECT_EQ(0u, log_.status().pos);
EXPECT_EQ("", log_.str()); EXPECT_EQ("", log_.str());
...@@ -548,7 +480,7 @@ TEST_F(JsonParserTest, InvalidTokenError) { ...@@ -548,7 +480,7 @@ TEST_F(JsonParserTest, InvalidTokenError) {
TEST_F(JsonParserTest, InvalidNumberError) { TEST_F(JsonParserTest, InvalidNumberError) {
// Mantissa exceeds max (the constant used here is int64_t max). // Mantissa exceeds max (the constant used here is int64_t max).
std::string json = "1E9223372036854775807"; std::string json = "1E9223372036854775807";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); ParseJSON(SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_INVALID_NUMBER, log_.status().error); EXPECT_EQ(Error::JSON_PARSER_INVALID_NUMBER, log_.status().error);
EXPECT_EQ(0u, log_.status().pos); EXPECT_EQ(0u, log_.status().pos);
EXPECT_EQ("", log_.str()); EXPECT_EQ("", log_.str());
...@@ -557,7 +489,7 @@ TEST_F(JsonParserTest, InvalidNumberError) { ...@@ -557,7 +489,7 @@ TEST_F(JsonParserTest, InvalidNumberError) {
TEST_F(JsonParserTest, InvalidStringError) { TEST_F(JsonParserTest, InvalidStringError) {
// \x22 is an unsupported escape sequence // \x22 is an unsupported escape sequence
std::string json = "\"foo\\x22\""; std::string json = "\"foo\\x22\"";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); ParseJSON(SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_INVALID_STRING, log_.status().error); EXPECT_EQ(Error::JSON_PARSER_INVALID_STRING, log_.status().error);
EXPECT_EQ(0u, log_.status().pos); EXPECT_EQ(0u, log_.status().pos);
EXPECT_EQ("", log_.str()); EXPECT_EQ("", log_.str());
...@@ -565,7 +497,7 @@ TEST_F(JsonParserTest, InvalidStringError) { ...@@ -565,7 +497,7 @@ TEST_F(JsonParserTest, InvalidStringError) {
TEST_F(JsonParserTest, UnexpectedArrayEndError) { TEST_F(JsonParserTest, UnexpectedArrayEndError) {
std::string json = "[1,2,]"; std::string json = "[1,2,]";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); ParseJSON(SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_UNEXPECTED_ARRAY_END, log_.status().error); EXPECT_EQ(Error::JSON_PARSER_UNEXPECTED_ARRAY_END, log_.status().error);
EXPECT_EQ(5u, log_.status().pos); EXPECT_EQ(5u, log_.status().pos);
EXPECT_EQ("", log_.str()); EXPECT_EQ("", log_.str());
...@@ -573,7 +505,7 @@ TEST_F(JsonParserTest, UnexpectedArrayEndError) { ...@@ -573,7 +505,7 @@ TEST_F(JsonParserTest, UnexpectedArrayEndError) {
TEST_F(JsonParserTest, CommaOrArrayEndExpectedError) { TEST_F(JsonParserTest, CommaOrArrayEndExpectedError) {
std::string json = "[1,2 2"; std::string json = "[1,2 2";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); ParseJSON(SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED, EXPECT_EQ(Error::JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED,
log_.status().error); log_.status().error);
EXPECT_EQ(5u, log_.status().pos); EXPECT_EQ(5u, log_.status().pos);
...@@ -583,7 +515,7 @@ TEST_F(JsonParserTest, CommaOrArrayEndExpectedError) { ...@@ -583,7 +515,7 @@ TEST_F(JsonParserTest, CommaOrArrayEndExpectedError) {
TEST_F(JsonParserTest, StringLiteralExpectedError) { TEST_F(JsonParserTest, StringLiteralExpectedError) {
// There's an error because the key bar, a string, is not terminated. // There's an error because the key bar, a string, is not terminated.
std::string json = "{\"foo\": 3.1415, \"bar: 31415e-4}"; std::string json = "{\"foo\": 3.1415, \"bar: 31415e-4}";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); ParseJSON(SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_STRING_LITERAL_EXPECTED, log_.status().error); EXPECT_EQ(Error::JSON_PARSER_STRING_LITERAL_EXPECTED, log_.status().error);
EXPECT_EQ(16u, log_.status().pos); EXPECT_EQ(16u, log_.status().pos);
EXPECT_EQ("", log_.str()); EXPECT_EQ("", log_.str());
...@@ -591,7 +523,7 @@ TEST_F(JsonParserTest, StringLiteralExpectedError) { ...@@ -591,7 +523,7 @@ TEST_F(JsonParserTest, StringLiteralExpectedError) {
TEST_F(JsonParserTest, ColonExpectedError) { TEST_F(JsonParserTest, ColonExpectedError) {
std::string json = "{\"foo\", 42}"; std::string json = "{\"foo\", 42}";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); ParseJSON(SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_COLON_EXPECTED, log_.status().error); EXPECT_EQ(Error::JSON_PARSER_COLON_EXPECTED, log_.status().error);
EXPECT_EQ(6u, log_.status().pos); EXPECT_EQ(6u, log_.status().pos);
EXPECT_EQ("", log_.str()); EXPECT_EQ("", log_.str());
...@@ -599,7 +531,7 @@ TEST_F(JsonParserTest, ColonExpectedError) { ...@@ -599,7 +531,7 @@ TEST_F(JsonParserTest, ColonExpectedError) {
TEST_F(JsonParserTest, UnexpectedMapEndError) { TEST_F(JsonParserTest, UnexpectedMapEndError) {
std::string json = "{\"foo\": 42, }"; std::string json = "{\"foo\": 42, }";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); ParseJSON(SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_UNEXPECTED_MAP_END, log_.status().error); EXPECT_EQ(Error::JSON_PARSER_UNEXPECTED_MAP_END, log_.status().error);
EXPECT_EQ(12u, log_.status().pos); EXPECT_EQ(12u, log_.status().pos);
EXPECT_EQ("", log_.str()); EXPECT_EQ("", log_.str());
...@@ -608,7 +540,7 @@ TEST_F(JsonParserTest, UnexpectedMapEndError) { ...@@ -608,7 +540,7 @@ TEST_F(JsonParserTest, UnexpectedMapEndError) {
TEST_F(JsonParserTest, CommaOrMapEndExpectedError) { TEST_F(JsonParserTest, CommaOrMapEndExpectedError) {
// The second separator should be a comma. // The second separator should be a comma.
std::string json = "{\"foo\": 3.1415: \"bar\": 0}"; std::string json = "{\"foo\": 3.1415: \"bar\": 0}";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); ParseJSON(SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_COMMA_OR_MAP_END_EXPECTED, log_.status().error); EXPECT_EQ(Error::JSON_PARSER_COMMA_OR_MAP_END_EXPECTED, log_.status().error);
EXPECT_EQ(14u, log_.status().pos); EXPECT_EQ(14u, log_.status().pos);
EXPECT_EQ("", log_.str()); EXPECT_EQ("", log_.str());
...@@ -616,7 +548,7 @@ TEST_F(JsonParserTest, CommaOrMapEndExpectedError) { ...@@ -616,7 +548,7 @@ TEST_F(JsonParserTest, CommaOrMapEndExpectedError) {
TEST_F(JsonParserTest, ValueExpectedError) { TEST_F(JsonParserTest, ValueExpectedError) {
std::string json = "}"; std::string json = "}";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); ParseJSON(SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_VALUE_EXPECTED, log_.status().error); EXPECT_EQ(Error::JSON_PARSER_VALUE_EXPECTED, log_.status().error);
EXPECT_EQ(0u, log_.status().pos); EXPECT_EQ(0u, log_.status().pos);
EXPECT_EQ("", log_.str()); EXPECT_EQ("", log_.str());
...@@ -633,14 +565,13 @@ TYPED_TEST(ConvertJSONToCBORTest, RoundTripValidJson) { ...@@ -633,14 +565,13 @@ TYPED_TEST(ConvertJSONToCBORTest, RoundTripValidJson) {
TypeParam json(json_in.begin(), json_in.end()); TypeParam json(json_in.begin(), json_in.end());
TypeParam cbor; TypeParam cbor;
{ {
Status status = ConvertJSONToCBOR(GetTestPlatform(), SpanFrom(json), &cbor); Status status = ConvertJSONToCBOR(SpanFrom(json), &cbor);
EXPECT_EQ(Error::OK, status.error); EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ(Status::npos(), status.pos); EXPECT_EQ(Status::npos(), status.pos);
} }
TypeParam roundtrip_json; TypeParam roundtrip_json;
{ {
Status status = Status status = ConvertCBORToJSON(SpanFrom(cbor), &roundtrip_json);
ConvertCBORToJSON(GetTestPlatform(), SpanFrom(cbor), &roundtrip_json);
EXPECT_EQ(Error::OK, status.error); EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ(Status::npos(), status.pos); EXPECT_EQ(Status::npos(), status.pos);
} }
...@@ -654,15 +585,14 @@ TYPED_TEST(ConvertJSONToCBORTest, RoundTripValidJson16) { ...@@ -654,15 +585,14 @@ TYPED_TEST(ConvertJSONToCBORTest, RoundTripValidJson16) {
'"', ':', '[', '1', ',', '2', ',', '3', ']', '}'}; '"', ':', '[', '1', ',', '2', ',', '3', ']', '}'};
TypeParam cbor; TypeParam cbor;
{ {
Status status = ConvertJSONToCBOR( Status status =
GetTestPlatform(), span<uint16_t>(json16.data(), json16.size()), &cbor); ConvertJSONToCBOR(span<uint16_t>(json16.data(), json16.size()), &cbor);
EXPECT_EQ(Error::OK, status.error); EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ(Status::npos(), status.pos); EXPECT_EQ(Status::npos(), status.pos);
} }
TypeParam roundtrip_json; TypeParam roundtrip_json;
{ {
Status status = Status status = ConvertCBORToJSON(SpanFrom(cbor), &roundtrip_json);
ConvertCBORToJSON(GetTestPlatform(), SpanFrom(cbor), &roundtrip_json);
EXPECT_EQ(Error::OK, status.error); EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ(Status::npos(), status.pos); EXPECT_EQ(Status::npos(), status.pos);
} }
......
...@@ -2,8 +2,7 @@ ...@@ -2,8 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// This file is V8 specific, to make encoding_test.cc work. // This file is V8 specific. It's not rolled from the upstream project.
// It is not rolled from the upstream project.
#ifndef V8_INSPECTOR_PROTOCOL_CRDTP_TEST_PLATFORM_H_ #ifndef V8_INSPECTOR_PROTOCOL_CRDTP_TEST_PLATFORM_H_
#define V8_INSPECTOR_PROTOCOL_CRDTP_TEST_PLATFORM_H_ #define V8_INSPECTOR_PROTOCOL_CRDTP_TEST_PLATFORM_H_
......
...@@ -2,8 +2,7 @@ ...@@ -2,8 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// This file is V8 specific, to make encoding_test.cc work. // This file is V8 specific. It's not rolled from the upstream project.
// It is not rolled from the upstream project.
#include "test_platform.h" #include "test_platform.h"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment