[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/+/1913424
Reviewed-by: Yang Guo <yangguo@chromium.org>
Commit-Queue: Johannes Henkel <johannes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65219}
This commit is contained in:
Johannes Henkel 2019-11-22 15:00:49 -08:00 committed by Commit Bot
parent bd9efe1fd1
commit ce3ce2f66d
16 changed files with 220 additions and 401 deletions

View File

@ -143,8 +143,6 @@ v8_source_set("inspector") {
"v8-heap-profiler-agent-impl.h",
"v8-inspector-impl.cc",
"v8-inspector-impl.h",
"v8-inspector-protocol-encoding.cc",
"v8-inspector-protocol-encoding.h",
"v8-inspector-session-impl.cc",
"v8-inspector-session-impl.h",
"v8-profiler-agent-impl.cc",

View File

@ -1,53 +0,0 @@
// 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

View File

@ -1,24 +0,0 @@
// 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_

View File

@ -4,6 +4,8 @@
#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/macros.h"
#include "src/inspector/injected-script.h"
@ -17,7 +19,6 @@
#include "src/inspector/v8-debugger.h"
#include "src/inspector/v8-heap-profiler-agent-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-runtime-agent-impl.h"
#include "src/inspector/v8-schema-agent-impl.h"
@ -26,14 +27,16 @@ namespace v8_inspector {
namespace {
using v8_crdtp::span;
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) {
return msg.is8Bit() && msg.length() >= 2 && msg.characters8()[0] == 0xd8 &&
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()
? ConvertJSONToCBOR(
span<uint8_t>(state.characters8(), state.length()), cbor)
@ -168,7 +171,7 @@ std::unique_ptr<StringBuffer> V8InspectorSessionImpl::serializeForFrontend(
return std::unique_ptr<StringBuffer>(
new BinaryStringBuffer(std::move(cbor)));
std::vector<uint8_t> json;
IPEStatus status = ConvertCBORToJSON(SpanFrom(cbor), &json);
Status status = ConvertCBORToJSON(SpanFrom(cbor), &json);
DCHECK(status.ok());
USE(status);
String16 string16(reinterpret_cast<const char*>(json.data()), json.size());

View File

@ -4,6 +4,12 @@
import("../../gni/v8.gni")
config("crdtp_config") {
visibility = [ "../../src/inspector:*" ]
configs = [ "../../:internal_config" ]
include_dirs = [ "../../include" ]
}
v8_source_set("crdtp") {
sources = [
"crdtp/cbor.cc",
@ -12,37 +18,59 @@ v8_source_set("crdtp") {
"crdtp/glue.h",
"crdtp/json.cc",
"crdtp/json.h",
"crdtp/json_platform.h",
"crdtp/parser_handler.h",
"crdtp/span.h",
"crdtp/status.cc",
"crdtp/status.h",
]
configs = [ "../../:internal_config" ]
configs = [ ":crdtp_config" ]
deps = [
":crdtp_platform",
]
}
# crdtp_test is part of the unittests, defined in
# test/unittests/BUILD.gn.
# A small adapter library which only :crdtp may depend on.
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") {
testonly = true
sources = [
"crdtp/cbor_test.cc",
"crdtp/glue_test.cc",
"crdtp/json_test.cc",
"crdtp/span_test.cc",
"crdtp/status_test.cc",
"crdtp/test_platform.cc",
"crdtp/test_platform.h",
]
configs = [
"../..:external_config",
"../..:internal_config_base",
]
configs = [ ":crdtp_config" ]
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",
"../..:v8_libbase",
"../../src/inspector:inspector_string_conversions",
"//testing/gmock",
"//testing/gtest",
]
testonly = true
}

View File

@ -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).
We're working on enabling standalone builds for parts of this package for
testing and development.
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
To build and run the tests of the crdtp library, see
[CRDTP - Chrome DevTools Protocol](crdtp/README.md).

View File

@ -2,7 +2,7 @@ Name: inspector protocol
Short Name: inspector_protocol
URL: https://chromium.googlesource.com/deps/inspector_protocol/
Version: 0
Revision: 4c2a3acaea9f2e7958081dd361f81e20e9eff5e7
Revision: 7a44a37f66b58358dd8ab85ccde1998fafa95e53
License: BSD
License File: LICENSE
Security Critical: no

View File

@ -22,42 +22,6 @@
using testing::ElementsAreArray;
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 {
// =============================================================================
// Detecting CBOR content
@ -692,7 +656,7 @@ TEST(JsonCborRoundtrip, EncodingDecoding) {
Status status;
std::unique_ptr<ParserHandler> encoder = NewCBOREncoder(&encoded, &status);
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 = {
0xd8, // envelope
0x5a, // byte string with 32 bit length
@ -736,7 +700,7 @@ TEST(JsonCborRoundtrip, EncodingDecoding) {
// And now we roundtrip, decoding the message we just encoded.
std::string decoded;
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());
EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ(json, decoded);
@ -753,10 +717,10 @@ TEST(JsonCborRoundtrip, MoreRoundtripExamples) {
Status status;
std::unique_ptr<ParserHandler> encoder = NewCBOREncoder(&encoded, &status);
span<uint8_t> ascii_in = SpanFrom(json);
json::ParseJSON(GetTestPlatform(), ascii_in, encoder.get());
json::ParseJSON(ascii_in, encoder.get());
std::string decoded;
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());
EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ(json, decoded);
@ -788,7 +752,7 @@ TEST(JSONToCBOREncoderTest, HelloWorldBinary_WithTripToJson) {
// Now drive the json writer via the CBOR decoder.
std::string decoded;
std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &decoded, &status);
json::NewJSONEncoder(&decoded, &status);
ParseCBOR(SpanFrom(encoded), json_writer.get());
EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ(Status::npos(), status.pos);
@ -808,7 +772,7 @@ TEST(ParseCBORTest, ParseEmptyCBORMessage) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ("{}", out);
@ -832,7 +796,7 @@ TEST(ParseCBORTest, ParseCBORHelloWorld) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ("{\"msg\":\"Hello, \\ud83c\\udf0e.\"}", out);
@ -857,7 +821,7 @@ TEST(ParseCBORTest, UTF8IsSupportedInKeys) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ("{\"\\ud83c\\udf0e\":\"\\u263e\"}", out);
@ -868,7 +832,7 @@ TEST(ParseCBORTest, NoInputError) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::CBOR_NO_INPUT, status.error);
EXPECT_EQ("", out);
@ -882,7 +846,7 @@ TEST(ParseCBORTest, InvalidStartByteError) {
std::string out;
Status status;
std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status);
json::NewJSONEncoder(&out, &status);
ParseCBOR(SpanFrom(json), json_writer.get());
EXPECT_EQ(Error::CBOR_INVALID_START_BYTE, status.error);
EXPECT_EQ("", out);
@ -898,7 +862,7 @@ TEST(ParseCBORTest, UnexpectedEofExpectedValueError) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE, status.error);
EXPECT_EQ(bytes.size(), status.pos);
@ -916,7 +880,7 @@ TEST(ParseCBORTest, UnexpectedEofInArrayError) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_IN_ARRAY, status.error);
EXPECT_EQ(bytes.size(), status.pos);
@ -931,7 +895,7 @@ TEST(ParseCBORTest, UnexpectedEofInMapError) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_IN_MAP, status.error);
EXPECT_EQ(7u, status.pos);
@ -945,7 +909,7 @@ TEST(ParseCBORTest, TopLevelCantBeEmptyEnvelope) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::CBOR_MAP_START_EXPECTED, status.error);
EXPECT_EQ(bytes.size(), status.pos);
@ -967,7 +931,7 @@ TEST(ParseCBORTest, MapStartExpectedAtTopLevel) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::CBOR_MAP_START_EXPECTED, status.error);
EXPECT_EQ(6u, status.pos);
@ -997,7 +961,7 @@ TEST(ParseCBORTest, OnlyMapsAndArraysSupportedInsideEnvelopes) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::CBOR_MAP_OR_ARRAY_EXPECTED_IN_ENVELOPE, status.error);
EXPECT_EQ(error_pos, status.pos);
@ -1014,7 +978,7 @@ TEST(ParseCBORTest, InvalidMapKeyError) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::CBOR_INVALID_MAP_KEY, status.error);
EXPECT_EQ(7u, status.pos);
@ -1045,7 +1009,7 @@ TEST(ParseCBORTest, StackLimitExceededError) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ(Status::npos(), status.pos);
@ -1056,7 +1020,7 @@ TEST(ParseCBORTest, StackLimitExceededError) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ(Status::npos(), status.pos);
@ -1076,7 +1040,7 @@ TEST(ParseCBORTest, StackLimitExceededError) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::CBOR_STACK_LIMIT_EXCEEDED, status.error);
EXPECT_EQ(opening_segment_size * 301, status.pos);
@ -1086,7 +1050,7 @@ TEST(ParseCBORTest, StackLimitExceededError) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::CBOR_STACK_LIMIT_EXCEEDED, status.error);
EXPECT_EQ(opening_segment_size * 301, status.pos);
@ -1105,7 +1069,7 @@ TEST(ParseCBORTest, UnsupportedValueError) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::CBOR_UNSUPPORTED_VALUE, status.error);
EXPECT_EQ(error_pos, status.pos);
@ -1128,7 +1092,7 @@ TEST(ParseCBORTest, InvalidString16Error) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::CBOR_INVALID_STRING16, status.error);
EXPECT_EQ(error_pos, status.pos);
@ -1148,7 +1112,7 @@ TEST(ParseCBORTest, InvalidString8Error) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::CBOR_INVALID_STRING8, status.error);
EXPECT_EQ(error_pos, status.pos);
@ -1170,7 +1134,7 @@ TEST(ParseCBORTest, InvalidBinaryError) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::CBOR_INVALID_BINARY, status.error);
EXPECT_EQ(error_pos, status.pos);
@ -1191,7 +1155,7 @@ TEST(ParseCBORTest, InvalidDoubleError) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::CBOR_INVALID_DOUBLE, status.error);
EXPECT_EQ(error_pos, status.pos);
@ -1212,7 +1176,7 @@ TEST(ParseCBORTest, InvalidSignedError) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::CBOR_INVALID_INT32, status.error);
EXPECT_EQ(error_pos, status.pos);
@ -1235,7 +1199,7 @@ TEST(ParseCBORTest, TrailingJunk) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::CBOR_TRAILING_JUNK, status.error);
EXPECT_EQ(error_pos, status.pos);
@ -1258,7 +1222,7 @@ TEST(ParseCBORTest, EnvelopeContentsLengthMismatch) {
std::string out;
Status status;
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());
EXPECT_EQ(Error::CBOR_ENVELOPE_CONTENTS_LENGTH_MISMATCH, status.error);
EXPECT_EQ(bytes.size(), status.pos);
@ -1293,7 +1257,7 @@ TYPED_TEST(AppendString8EntryToMapTest, AppendsEntrySuccessfully) {
EXPECT_EQ(Status::npos(), status.pos);
std::string out;
std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status);
json::NewJSONEncoder(&out, &status);
ParseCBOR(SpanFrom(msg), json_writer.get());
EXPECT_EQ("{\"key\":\"value\",\"foo\":\"bar\"}", out);
EXPECT_EQ(Error::OK, status.error);
@ -1316,7 +1280,7 @@ TYPED_TEST(AppendString8EntryToMapTest, AppendThreeEntries) {
std::string out;
Status status;
std::unique_ptr<ParserHandler> json_writer =
json::NewJSONEncoder(&GetTestPlatform(), &out, &status);
json::NewJSONEncoder(&out, &status);
ParseCBOR(SpanFrom(msg), json_writer.get());
EXPECT_EQ("{\"key\":\"value\",\"key1\":\"value1\",\"key2\":\"value2\"}", out);
EXPECT_EQ(Error::OK, status.error);

View File

@ -2,6 +2,5 @@
// 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 is not rolled from the upstream project.
// This file is V8 specific. It's not rolled from the upstream project.
// CRDTP doesn't export symbols from V8, so it's empty.

View File

@ -12,10 +12,10 @@
#include <stack>
#include "cbor.h"
#include "json_platform.h"
namespace v8_crdtp {
namespace json {
// =============================================================================
// json::NewJSONEncoder - for encoding streaming parser events as JSON
// =============================================================================
@ -104,8 +104,7 @@ void Base64Encode(const span<uint8_t>& in, C* out) {
template <typename C>
class JSONEncoder : public ParserHandler {
public:
JSONEncoder(const Platform* platform, C* out, Status* status)
: platform_(platform), out_(out), status_(status) {
JSONEncoder(C* out, Status* status) : out_(out), status_(status) {
*status_ = Status();
state_.emplace(Container::NONE);
}
@ -283,14 +282,14 @@ class JSONEncoder : public ParserHandler {
Emit("null");
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
// the case in base::NumberToString in Chromium (which is based on
// dmg_fp). So, much like
// https://cs.chromium.org/chromium/src/base/json/json_writer.cc
// 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] == '.') {
Emit('0');
} else if (chars[0] == '-' && chars[1] == '.') {
@ -336,25 +335,22 @@ class JSONEncoder : public ParserHandler {
out_->insert(out_->end(), str.begin(), str.end());
}
const Platform* platform_;
C* out_;
Status* status_;
std::stack<State> state_;
};
} // namespace
std::unique_ptr<ParserHandler> NewJSONEncoder(const Platform* platform,
std::vector<uint8_t>* out,
std::unique_ptr<ParserHandler> NewJSONEncoder(std::vector<uint8_t>* out,
Status* status) {
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::string* out,
std::unique_ptr<ParserHandler> NewJSONEncoder(std::string* out,
Status* status) {
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";
template <typename Char>
class JsonParser {
public:
JsonParser(const Platform* platform, ParserHandler* handler)
: platform_(platform), handler_(handler) {}
explicit JsonParser(ParserHandler* handler) : handler_(handler) {}
void Parse(const Char* start, size_t length) {
start_pos_ = start;
@ -412,12 +407,12 @@ class JsonParser {
return false;
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) {
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,
@ -966,22 +961,17 @@ class JsonParser {
const Char* start_pos_ = nullptr;
bool error_ = false;
const Platform* platform_;
ParserHandler* handler_;
};
} // namespace
void ParseJSON(const Platform& platform,
span<uint8_t> chars,
ParserHandler* handler) {
JsonParser<uint8_t> parser(&platform, handler);
void ParseJSON(span<uint8_t> chars, ParserHandler* handler) {
JsonParser<uint8_t> parser(handler);
parser.Parse(chars.data(), chars.size());
}
void ParseJSON(const Platform& platform,
span<uint16_t> chars,
ParserHandler* handler) {
JsonParser<uint16_t> parser(&platform, handler);
void ParseJSON(span<uint16_t> chars, ParserHandler* handler) {
JsonParser<uint16_t> parser(handler);
parser.Parse(chars.data(), chars.size());
}
@ -989,58 +979,43 @@ void ParseJSON(const Platform& platform,
// json::ConvertCBORToJSON, json::ConvertJSONToCBOR - for transcoding
// =============================================================================
template <typename C>
Status ConvertCBORToJSONTmpl(const Platform& platform,
span<uint8_t> cbor,
C* json) {
Status ConvertCBORToJSONTmpl(span<uint8_t> cbor, C* json) {
Status status;
std::unique_ptr<ParserHandler> json_writer =
NewJSONEncoder(&platform, json, &status);
std::unique_ptr<ParserHandler> json_writer = NewJSONEncoder(json, &status);
cbor::ParseCBOR(cbor, json_writer.get());
return status;
}
Status ConvertCBORToJSON(const Platform& platform,
span<uint8_t> cbor,
std::vector<uint8_t>* json) {
return ConvertCBORToJSONTmpl(platform, cbor, json);
Status ConvertCBORToJSON(span<uint8_t> cbor, std::vector<uint8_t>* json) {
return ConvertCBORToJSONTmpl(cbor, json);
}
Status ConvertCBORToJSON(const Platform& platform,
span<uint8_t> cbor,
std::string* json) {
return ConvertCBORToJSONTmpl(platform, cbor, json);
Status ConvertCBORToJSON(span<uint8_t> cbor, std::string* json) {
return ConvertCBORToJSONTmpl(cbor, json);
}
template <typename T, typename C>
Status ConvertJSONToCBORTmpl(const Platform& platform, span<T> json, C* cbor) {
Status ConvertJSONToCBORTmpl(span<T> json, C* cbor) {
Status status;
std::unique_ptr<ParserHandler> encoder = cbor::NewCBOREncoder(cbor, &status);
ParseJSON(platform, json, encoder.get());
ParseJSON(json, encoder.get());
return status;
}
Status ConvertJSONToCBOR(const Platform& platform,
span<uint8_t> json,
std::string* cbor) {
return ConvertJSONToCBORTmpl(platform, json, cbor);
Status ConvertJSONToCBOR(span<uint8_t> json, std::string* cbor) {
return ConvertJSONToCBORTmpl(json, cbor);
}
Status ConvertJSONToCBOR(const Platform& platform,
span<uint16_t> json,
std::string* cbor) {
return ConvertJSONToCBORTmpl(platform, json, cbor);
Status ConvertJSONToCBOR(span<uint16_t> json, std::string* cbor) {
return ConvertJSONToCBORTmpl(json, cbor);
}
Status ConvertJSONToCBOR(const Platform& platform,
span<uint8_t> json,
std::vector<uint8_t>* cbor) {
return ConvertJSONToCBORTmpl(platform, json, cbor);
Status ConvertJSONToCBOR(span<uint8_t> json, std::vector<uint8_t>* cbor) {
return ConvertJSONToCBORTmpl(json, cbor);
}
Status ConvertJSONToCBOR(const Platform& platform,
span<uint16_t> json,
std::vector<uint8_t>* cbor) {
return ConvertJSONToCBORTmpl(platform, json, cbor);
Status ConvertJSONToCBOR(span<uint16_t> json, std::vector<uint8_t>* cbor) {
return ConvertJSONToCBORTmpl(json, cbor);
}
} // namespace json
} // namespace v8_crdtp

View File

@ -6,9 +6,7 @@
#define V8_CRDTP_JSON_H_
#include <memory>
#include "export.h"
#include "json_platform.h"
#include "parser_handler.h"
namespace v8_crdtp {
@ -23,45 +21,34 @@ namespace json {
// 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
// in valid JSON; otherwise we may crash (the code uses assert).
std::unique_ptr<ParserHandler> NewJSONEncoder(const Platform* platform,
std::vector<uint8_t>* out,
Status* status);
std::unique_ptr<ParserHandler> NewJSONEncoder(const Platform* platform,
std::string* out,
std::unique_ptr<ParserHandler> NewJSONEncoder(std::vector<uint8_t>* out,
Status* status);
std::unique_ptr<ParserHandler> NewJSONEncoder(std::string* out, Status* status);
// =============================================================================
// json::ParseJSON - for receiving streaming parser events for JSON
// =============================================================================
void ParseJSON(const Platform& platform,
span<uint8_t> chars,
ParserHandler* handler);
void ParseJSON(const Platform& platform,
span<uint16_t> chars,
ParserHandler* handler);
void ParseJSON(span<uint8_t> chars, ParserHandler* handler);
void ParseJSON(span<uint16_t> chars, ParserHandler* handler);
// =============================================================================
// json::ConvertCBORToJSON, json::ConvertJSONToCBOR - for transcoding
// =============================================================================
Status ConvertCBORToJSON(const Platform& platform,
span<uint8_t> cbor,
std::string* json);
Status ConvertCBORToJSON(const Platform& platform,
span<uint8_t> cbor,
std::vector<uint8_t>* json);
Status ConvertJSONToCBOR(const Platform& platform,
span<uint8_t> json,
std::vector<uint8_t>* cbor);
Status ConvertJSONToCBOR(const Platform& platform,
span<uint16_t> json,
std::vector<uint8_t>* 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);
Status ConvertCBORToJSON(span<uint8_t> cbor, std::string* json);
Status ConvertCBORToJSON(span<uint8_t> cbor, std::vector<uint8_t>* json);
Status ConvertJSONToCBOR(span<uint8_t> json, std::vector<uint8_t>* cbor);
Status ConvertJSONToCBOR(span<uint16_t> json, std::vector<uint8_t>* cbor);
Status ConvertJSONToCBOR(span<uint8_t> json, std::string* cbor);
Status ConvertJSONToCBOR(span<uint16_t> json, std::string* cbor);
} // namespace json
} // namespace v8_crdtp

View File

@ -5,23 +5,21 @@
#ifndef V8_CRDTP_JSON_PLATFORM_H_
#define V8_CRDTP_JSON_PLATFORM_H_
#include <memory>
#include "export.h"
#include <string>
namespace v8_crdtp {
namespace json {
// Client code must provide an instance. Implementation should delegate
// to whatever is appropriate.
class Platform {
public:
virtual ~Platform() = default;
// Parses |str| into |result|. Returns false iff there are
// leftover characters or parsing errors.
virtual bool StrToD(const char* str, double* result) const = 0;
// These routines are implemented in json_platform.cc, or in a
// platform-dependent (code-base dependent) custom replacement.
// E.g., json_platform_chromium.cc, json_platform_v8.cc.
namespace platform {
// Parses |str| into |result|. Returns false iff there are
// leftover characters or parsing errors.
bool StrToD(const char* str, double* result);
// Prints |value| in a format suitable for JSON.
virtual std::unique_ptr<char[]> DToStr(double value) const = 0;
};
// Prints |value| in a format suitable for JSON.
std::string DToStr(double value);
} // namespace platform
} // namespace json
} // namespace v8_crdtp

View File

@ -0,0 +1,32 @@
// 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

View File

@ -14,47 +14,14 @@
#include <sstream>
#include <string>
#include "cbor.h"
#include "parser_handler.h"
#include "span.h"
#include "status.h"
#include "test_platform.h"
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 {
// =============================================================================
// json::NewJSONEncoder - for encoding streaming parser events as JSON
// =============================================================================
@ -66,8 +33,7 @@ void WriteUTF8AsUTF16(ParserHandler* writer, const std::string& utf8) {
TEST(JsonEncoder, OverlongEncodings) {
std::string out;
Status status;
std::unique_ptr<ParserHandler> writer =
NewJSONEncoder(&GetTestPlatform(), &out, &status);
std::unique_ptr<ParserHandler> writer = NewJSONEncoder(&out, &status);
// 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
@ -85,8 +51,7 @@ TEST(JsonEncoder, OverlongEncodings) {
TEST(JsonEncoder, IncompleteUtf8Sequence) {
std::string out;
Status status;
std::unique_ptr<ParserHandler> writer =
NewJSONEncoder(&GetTestPlatform(), &out, &status);
std::unique_ptr<ParserHandler> writer = NewJSONEncoder(&out, &status);
writer->HandleArrayBegin(); // This emits [, which starts an array.
@ -111,8 +76,7 @@ TEST(JsonEncoder, IncompleteUtf8Sequence) {
TEST(JsonStdStringWriterTest, HelloWorld) {
std::string out;
Status status;
std::unique_ptr<ParserHandler> writer =
NewJSONEncoder(&GetTestPlatform(), &out, &status);
std::unique_ptr<ParserHandler> writer = NewJSONEncoder(&out, &status);
writer->HandleMapBegin();
WriteUTF8AsUTF16(writer.get(), "msg1");
WriteUTF8AsUTF16(writer.get(), "Hello, 🌎.");
@ -155,8 +119,7 @@ TEST(JsonStdStringWriterTest, RepresentingNonFiniteValuesAsNull) {
// So in practice it's mapped to null.
std::string out;
Status status;
std::unique_ptr<ParserHandler> writer =
NewJSONEncoder(&GetTestPlatform(), &out, &status);
std::unique_ptr<ParserHandler> writer = NewJSONEncoder(&out, &status);
writer->HandleMapBegin();
writer->HandleString8(SpanFrom("Infinity"));
writer->HandleDouble(std::numeric_limits<double>::infinity());
@ -176,8 +139,7 @@ TEST(JsonStdStringWriterTest, BinaryEncodedAsJsonString) {
{
std::string out;
Status status;
std::unique_ptr<ParserHandler> writer =
NewJSONEncoder(&GetTestPlatform(), &out, &status);
std::unique_ptr<ParserHandler> writer = NewJSONEncoder(&out, &status);
writer->HandleBinary(SpanFrom(std::vector<uint8_t>({'M', 'a', 'n'})));
EXPECT_TRUE(status.ok());
EXPECT_EQ("\"TWFu\"", out);
@ -185,8 +147,7 @@ TEST(JsonStdStringWriterTest, BinaryEncodedAsJsonString) {
{
std::string out;
Status status;
std::unique_ptr<ParserHandler> writer =
NewJSONEncoder(&GetTestPlatform(), &out, &status);
std::unique_ptr<ParserHandler> writer = NewJSONEncoder(&out, &status);
writer->HandleBinary(SpanFrom(std::vector<uint8_t>({'M', 'a'})));
EXPECT_TRUE(status.ok());
EXPECT_EQ("\"TWE=\"", out);
@ -194,8 +155,7 @@ TEST(JsonStdStringWriterTest, BinaryEncodedAsJsonString) {
{
std::string out;
Status status;
std::unique_ptr<ParserHandler> writer =
NewJSONEncoder(&GetTestPlatform(), &out, &status);
std::unique_ptr<ParserHandler> writer = NewJSONEncoder(&out, &status);
writer->HandleBinary(SpanFrom(std::vector<uint8_t>({'M'})));
EXPECT_TRUE(status.ok());
EXPECT_EQ("\"TQ==\"", out);
@ -203,8 +163,7 @@ TEST(JsonStdStringWriterTest, BinaryEncodedAsJsonString) {
{ // "Hello, world.", verified with base64decode.org.
std::string out;
Status status;
std::unique_ptr<ParserHandler> writer =
NewJSONEncoder(&GetTestPlatform(), &out, &status);
std::unique_ptr<ParserHandler> writer = NewJSONEncoder(&out, &status);
writer->HandleBinary(SpanFrom(std::vector<uint8_t>(
{'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.'})));
EXPECT_TRUE(status.ok());
@ -217,8 +176,7 @@ TEST(JsonStdStringWriterTest, HandlesErrors) {
// status and clears the output.
std::string out;
Status status;
std::unique_ptr<ParserHandler> writer =
NewJSONEncoder(&GetTestPlatform(), &out, &status);
std::unique_ptr<ParserHandler> writer = NewJSONEncoder(&out, &status);
writer->HandleMapBegin();
WriteUTF8AsUTF16(writer.get(), "msg1");
writer->HandleError(Status{Error::JSON_PARSER_VALUE_EXPECTED, 42});
@ -227,36 +185,11 @@ TEST(JsonStdStringWriterTest, HandlesErrors) {
EXPECT_EQ("", out);
}
// We'd use Gmock but unfortunately it only handles copyable return types.
class MockPlatform : public Platform {
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";
TEST(JsonStdStringWriterTest, DoubleToString_LeadingZero) {
// In JSON, .1 must be rendered as 0.1, and -.7 must be rendered as -0.7.
std::string out;
Status status;
std::unique_ptr<ParserHandler> writer =
NewJSONEncoder(&platform, &out, &status);
std::unique_ptr<ParserHandler> writer = NewJSONEncoder(&out, &status);
writer->HandleArrayBegin();
writer->HandleDouble(.1);
writer->HandleDouble(-.7);
@ -320,7 +253,7 @@ class JsonParserTest : public ::testing::Test {
TEST_F(JsonParserTest, SimpleDictionary) {
std::string json = "{\"foo\": 42}";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
ParseJSON(SpanFrom(json), &log_);
EXPECT_TRUE(log_.status().ok());
EXPECT_EQ(
"map begin\n"
@ -336,7 +269,7 @@ TEST_F(JsonParserTest, UsAsciiDelCornerCase) {
// character in https://tools.ietf.org/html/rfc7159#section-7, so
// it can be placed directly into the JSON string, without JSON escaping.
std::string json = "{\"foo\": \"a\x7f\"}";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
ParseJSON(SpanFrom(json), &log_);
EXPECT_TRUE(log_.status().ok());
EXPECT_EQ(
"map begin\n"
@ -355,7 +288,7 @@ TEST_F(JsonParserTest, UsAsciiDelCornerCase) {
TEST_F(JsonParserTest, Whitespace) {
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_EQ(
"map begin\n"
@ -367,7 +300,7 @@ TEST_F(JsonParserTest, Whitespace) {
TEST_F(JsonParserTest, NestedDictionary) {
std::string json = "{\"foo\": {\"bar\": {\"baz\": 1}, \"bar2\": 2}}";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
ParseJSON(SpanFrom(json), &log_);
EXPECT_TRUE(log_.status().ok());
EXPECT_EQ(
"map begin\n"
@ -387,7 +320,7 @@ TEST_F(JsonParserTest, NestedDictionary) {
TEST_F(JsonParserTest, Doubles) {
std::string json = "{\"foo\": 3.1415, \"bar\": 31415e-4}";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
ParseJSON(SpanFrom(json), &log_);
EXPECT_TRUE(log_.status().ok());
EXPECT_EQ(
"map begin\n"
@ -402,7 +335,7 @@ TEST_F(JsonParserTest, Doubles) {
TEST_F(JsonParserTest, Unicode) {
// Globe character. 0xF0 0x9F 0x8C 0x8E in utf8, 0xD83C 0xDF0E in utf16.
std::string json = "{\"msg\": \"Hello, \\uD83C\\uDF0E.\"}";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
ParseJSON(SpanFrom(json), &log_);
EXPECT_TRUE(log_.status().ok());
EXPECT_EQ(
"map begin\n"
@ -420,7 +353,7 @@ TEST_F(JsonParserTest, Unicode_ParseUtf16) {
// Either way they arrive as utf8 (after decoding in log_.str()).
std::vector<uint16_t> json =
UTF8ToUTF16(SpanFrom("{\"space\": \"🌎 \\uD83C\\uDF19.\"}"));
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
ParseJSON(SpanFrom(json), &log_);
EXPECT_TRUE(log_.status().ok());
EXPECT_EQ(
"map begin\n"
@ -446,7 +379,7 @@ TEST_F(JsonParserTest, Unicode_ParseUtf8) {
"\"3 byte\":\"\","
"\"4 byte\":\"🌎\""
"}";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
ParseJSON(SpanFrom(json), &log_);
EXPECT_TRUE(log_.status().ok());
EXPECT_EQ(
"map begin\n"
@ -467,7 +400,7 @@ TEST_F(JsonParserTest, UnprocessedInputRemainsError) {
std::string json = "{\"foo\": 3.1415} junk";
size_t junk_idx = json.find("junk");
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(junk_idx, log_.status().pos);
EXPECT_EQ("", log_.str());
@ -487,7 +420,7 @@ TEST_F(JsonParserTest, StackLimitExceededError_BelowLimit) {
// kStackLimit is 300 (see json_parser.cc). First let's
// try with a small nested example.
std::string json_3 = MakeNestedJson(3);
ParseJSON(GetTestPlatform(), SpanFrom(json_3), &log_);
ParseJSON(SpanFrom(json_3), &log_);
EXPECT_TRUE(log_.status().ok());
EXPECT_EQ(
"map begin\n"
@ -506,8 +439,7 @@ TEST_F(JsonParserTest, StackLimitExceededError_BelowLimit) {
TEST_F(JsonParserTest, StackLimitExceededError_AtLimit) {
// Now with kStackLimit (300).
std::string json_limit = MakeNestedJson(300);
ParseJSON(GetTestPlatform(),
span<uint8_t>(reinterpret_cast<const uint8_t*>(json_limit.data()),
ParseJSON(span<uint8_t>(reinterpret_cast<const uint8_t*>(json_limit.data()),
json_limit.size()),
&log_);
EXPECT_TRUE(log_.status().ok());
@ -516,7 +448,7 @@ TEST_F(JsonParserTest, StackLimitExceededError_AtLimit) {
TEST_F(JsonParserTest, StackLimitExceededError_AboveLimit) {
// Now with kStackLimit + 1 (301) - it exceeds in the innermost instance.
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(strlen("{\"foo\":") * 301, log_.status().pos);
}
@ -524,14 +456,14 @@ TEST_F(JsonParserTest, StackLimitExceededError_AboveLimit) {
TEST_F(JsonParserTest, StackLimitExceededError_WayAboveLimit) {
// Now way past the limit. Still, the point of exceeding is 301.
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(strlen("{\"foo\":") * 301, log_.status().pos);
}
TEST_F(JsonParserTest, NoInputError) {
std::string json = "";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
ParseJSON(SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_NO_INPUT, log_.status().error);
EXPECT_EQ(0u, log_.status().pos);
EXPECT_EQ("", log_.str());
@ -539,7 +471,7 @@ TEST_F(JsonParserTest, NoInputError) {
TEST_F(JsonParserTest, InvalidTokenError) {
std::string json = "|";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
ParseJSON(SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_INVALID_TOKEN, log_.status().error);
EXPECT_EQ(0u, log_.status().pos);
EXPECT_EQ("", log_.str());
@ -548,7 +480,7 @@ TEST_F(JsonParserTest, InvalidTokenError) {
TEST_F(JsonParserTest, InvalidNumberError) {
// Mantissa exceeds max (the constant used here is int64_t max).
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(0u, log_.status().pos);
EXPECT_EQ("", log_.str());
@ -557,7 +489,7 @@ TEST_F(JsonParserTest, InvalidNumberError) {
TEST_F(JsonParserTest, InvalidStringError) {
// \x22 is an unsupported escape sequence
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(0u, log_.status().pos);
EXPECT_EQ("", log_.str());
@ -565,7 +497,7 @@ TEST_F(JsonParserTest, InvalidStringError) {
TEST_F(JsonParserTest, UnexpectedArrayEndError) {
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(5u, log_.status().pos);
EXPECT_EQ("", log_.str());
@ -573,7 +505,7 @@ TEST_F(JsonParserTest, UnexpectedArrayEndError) {
TEST_F(JsonParserTest, CommaOrArrayEndExpectedError) {
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,
log_.status().error);
EXPECT_EQ(5u, log_.status().pos);
@ -583,7 +515,7 @@ TEST_F(JsonParserTest, CommaOrArrayEndExpectedError) {
TEST_F(JsonParserTest, StringLiteralExpectedError) {
// There's an error because the key bar, a string, is not terminated.
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(16u, log_.status().pos);
EXPECT_EQ("", log_.str());
@ -591,7 +523,7 @@ TEST_F(JsonParserTest, StringLiteralExpectedError) {
TEST_F(JsonParserTest, ColonExpectedError) {
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(6u, log_.status().pos);
EXPECT_EQ("", log_.str());
@ -599,7 +531,7 @@ TEST_F(JsonParserTest, ColonExpectedError) {
TEST_F(JsonParserTest, UnexpectedMapEndError) {
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(12u, log_.status().pos);
EXPECT_EQ("", log_.str());
@ -608,7 +540,7 @@ TEST_F(JsonParserTest, UnexpectedMapEndError) {
TEST_F(JsonParserTest, CommaOrMapEndExpectedError) {
// The second separator should be a comma.
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(14u, log_.status().pos);
EXPECT_EQ("", log_.str());
@ -616,7 +548,7 @@ TEST_F(JsonParserTest, CommaOrMapEndExpectedError) {
TEST_F(JsonParserTest, ValueExpectedError) {
std::string json = "}";
ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
ParseJSON(SpanFrom(json), &log_);
EXPECT_EQ(Error::JSON_PARSER_VALUE_EXPECTED, log_.status().error);
EXPECT_EQ(0u, log_.status().pos);
EXPECT_EQ("", log_.str());
@ -633,14 +565,13 @@ TYPED_TEST(ConvertJSONToCBORTest, RoundTripValidJson) {
TypeParam json(json_in.begin(), json_in.end());
TypeParam cbor;
{
Status status = ConvertJSONToCBOR(GetTestPlatform(), SpanFrom(json), &cbor);
Status status = ConvertJSONToCBOR(SpanFrom(json), &cbor);
EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ(Status::npos(), status.pos);
}
TypeParam roundtrip_json;
{
Status status =
ConvertCBORToJSON(GetTestPlatform(), SpanFrom(cbor), &roundtrip_json);
Status status = ConvertCBORToJSON(SpanFrom(cbor), &roundtrip_json);
EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ(Status::npos(), status.pos);
}
@ -654,15 +585,14 @@ TYPED_TEST(ConvertJSONToCBORTest, RoundTripValidJson16) {
'"', ':', '[', '1', ',', '2', ',', '3', ']', '}'};
TypeParam cbor;
{
Status status = ConvertJSONToCBOR(
GetTestPlatform(), span<uint16_t>(json16.data(), json16.size()), &cbor);
Status status =
ConvertJSONToCBOR(span<uint16_t>(json16.data(), json16.size()), &cbor);
EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ(Status::npos(), status.pos);
}
TypeParam roundtrip_json;
{
Status status =
ConvertCBORToJSON(GetTestPlatform(), SpanFrom(cbor), &roundtrip_json);
Status status = ConvertCBORToJSON(SpanFrom(cbor), &roundtrip_json);
EXPECT_EQ(Error::OK, status.error);
EXPECT_EQ(Status::npos(), status.pos);
}

View File

@ -2,8 +2,7 @@
// 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, to make encoding_test.cc work.
// It is not rolled from the upstream project.
// This file is V8 specific. It's not rolled from the upstream project.
#ifndef V8_INSPECTOR_PROTOCOL_CRDTP_TEST_PLATFORM_H_
#define V8_INSPECTOR_PROTOCOL_CRDTP_TEST_PLATFORM_H_

View File

@ -2,8 +2,7 @@
// 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, to make encoding_test.cc work.
// It is not rolled from the upstream project.
// This file is V8 specific. It's not rolled from the upstream project.
#include "test_platform.h"