Files
react-native/ReactCommon/hermes/inspector/chrome/tests/MessageTests.cpp
T
Janic Duplessis cff9590864 Implement Runtime.getHeapUsage for hermes chrome inspector (#33173)
Summary:
Reland of https://github.com/facebook/react-native/issues/32895 with fix for optional params object.

Original description:

I was looking at the hermes chrome devtools integration and noticed requests to `Runtime.getHeapUsage` which was not implemented. When implemented it will show a summary of memory usage of the javascript instance in devtools.

<img width="325" alt="image" src="https://user-images.githubusercontent.com/2677334/149637113-e1d95d26-9e26-46c2-9be6-47d22284f15f.png">

## Changelog

[General] [Added] - Implement Runtime.getHeapUsage for hermes chrome inspector

Pull Request resolved: https://github.com/facebook/react-native/pull/33173

Test Plan:
I was able to reproduce the issue that caused the initial PR to be reverted using the resume request in Flipper. Pausing JS execution then resuming it will cause it to crash before this change, and works fine after.

Before

<img width="912" alt="image" src="https://user-images.githubusercontent.com/2677334/149637073-15f4e1fa-8183-42dc-8673-d4371731415c.png">

After

<img width="1076" alt="image" src="https://user-images.githubusercontent.com/2677334/149637085-579dee8f-5efb-4658-b0a8-2400bd119924.png">

Reviewed By: jpporto

Differential Revision: D34446672

Pulled By: ShikaSD

fbshipit-source-id: 6e26b8d53cd88cddded36437c72a01822551b9d0
2022-03-01 10:09:05 -08:00

1533 lines
47 KiB
C++

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <hermes/inspector/chrome/MessageTypes.h>
#include <iostream>
#include <folly/dynamic.h>
#include <folly/json.h>
#include <gtest/gtest.h>
namespace facebook {
namespace hermes {
namespace inspector {
namespace chrome {
namespace message {
using folly::dynamic;
TEST(MessageTests, testSerializeSomeFieldsInRequest) {
debugger::SetBreakpointByUrlRequest req;
// req.id should default to 0
req.lineNumber = 2;
req.url = "http://example.com/example.js";
dynamic result = req.toDynamic();
dynamic expected = folly::parseJson(R"({
"id": 0,
"method": "Debugger.setBreakpointByUrl",
"params": {
"lineNumber": 2,
"url": "http://example.com/example.js"
}
})");
EXPECT_EQ(result, expected);
}
TEST(MessageTests, testDeserializeSomeFieldsInRequest) {
dynamic message = folly::parseJson(R"(
{
"id": 10,
"method": "Debugger.setBreakpointByUrl",
"params": {
"lineNumber": 42,
"url": "http://example.com"
}
}
)");
debugger::SetBreakpointByUrlRequest req(message);
EXPECT_EQ(req.toDynamic(), message);
EXPECT_EQ(req.id, 10);
EXPECT_EQ(req.method, "Debugger.setBreakpointByUrl");
EXPECT_EQ(req.lineNumber, 42);
EXPECT_FALSE(req.columnNumber.hasValue());
EXPECT_FALSE(req.condition.hasValue());
EXPECT_EQ(req.url, "http://example.com");
EXPECT_FALSE(req.urlRegex.hasValue());
}
TEST(MessageTests, testSerializeAllFieldsInRequest) {
debugger::SetBreakpointByUrlRequest req;
req.id = 1;
req.lineNumber = 2;
req.columnNumber = 3;
req.condition = "foo == 42";
req.url = "http://example.com/example.js";
req.urlRegex = "http://example.com/.*";
dynamic result = req.toDynamic();
dynamic expected = folly::parseJson(R"({
"id": 1,
"method": "Debugger.setBreakpointByUrl",
"params": {
"lineNumber": 2,
"columnNumber": 3,
"condition": "foo == 42",
"url": "http://example.com/example.js",
"urlRegex": "http://example.com/.*"
}
})");
EXPECT_EQ(result, expected);
}
TEST(MessageTests, testDeserializeAllFieldsInRequest) {
dynamic message = folly::parseJson(R"({
"id": 1,
"method": "Debugger.setBreakpointByUrl",
"params": {
"lineNumber": 2,
"columnNumber": 3,
"condition": "foo == 42",
"url": "http://example.com/example.js",
"urlRegex": "http://example.com/.*"
}
})");
debugger::SetBreakpointByUrlRequest req(message);
EXPECT_EQ(req.id, 1);
EXPECT_EQ(req.method, "Debugger.setBreakpointByUrl");
EXPECT_EQ(req.lineNumber, 2);
EXPECT_EQ(req.columnNumber, 3);
EXPECT_EQ(req.condition, "foo == 42");
EXPECT_EQ(req.url, "http://example.com/example.js");
EXPECT_EQ(req.urlRegex, "http://example.com/.*");
}
TEST(MessageTests, testSerializeResponse) {
debugger::Location location;
location.scriptId = "myScriptId";
location.lineNumber = 2;
location.columnNumber = 3;
debugger::SetBreakpointByUrlResponse resp;
resp.id = 1;
resp.breakpointId = "myBreakpointId";
resp.locations = {location};
dynamic result = resp.toDynamic();
dynamic expected = folly::parseJson(R"({
"id": 1,
"result": {
"breakpointId": "myBreakpointId",
"locations": [
{
"lineNumber": 2,
"columnNumber": 3,
"scriptId": "myScriptId"
}
]
}
})");
EXPECT_EQ(result, expected);
}
TEST(MessageTests, testDeserializeResponse) {
dynamic message = folly::parseJson(R"({
"id": 1,
"result": {
"breakpointId": "myBreakpointId",
"locations": [
{
"lineNumber": 2,
"columnNumber": 3,
"scriptId": "myScriptId"
}
]
}
})");
debugger::SetBreakpointByUrlResponse resp(message);
EXPECT_EQ(resp.toDynamic(), message);
EXPECT_EQ(resp.id, 1);
EXPECT_EQ(resp.breakpointId, "myBreakpointId");
EXPECT_EQ(resp.locations.size(), 1);
EXPECT_EQ(resp.locations[0].lineNumber, 2);
EXPECT_EQ(resp.locations[0].columnNumber, 3);
EXPECT_EQ(resp.locations[0].scriptId, "myScriptId");
}
TEST(MessageTests, testSerializeNotification) {
debugger::Location startLocation;
startLocation.lineNumber = 1;
startLocation.scriptId = "script1";
debugger::Location endLocation;
endLocation.lineNumber = 2;
endLocation.scriptId = "script2";
debugger::Scope scope;
scope.type = "closure";
scope.object.type = "object";
scope.object.subtype = "regexp";
scope.object.className = "RegExp";
scope.object.value = dynamic::object("foo", "bar");
scope.object.unserializableValue = "nope";
scope.object.description = "myDesc";
scope.object.objectId = "id1";
scope.name = "myScope";
scope.startLocation = startLocation;
scope.endLocation = endLocation;
debugger::CallFrame frame;
frame.callFrameId = "callFrame1";
frame.functionName = "foo1";
frame.location.scriptId = "script1";
frame.location.lineNumber = 3;
frame.location.columnNumber = 4;
frame.url = "foo.js";
frame.scopeChain = std::vector<debugger::Scope>{scope};
frame.thisObj.type = "function";
debugger::PausedNotification note;
note.callFrames = std::vector<debugger::CallFrame>{frame};
note.reason = "debugCommand";
note.data = dynamic::object("foo", "bar");
note.hitBreakpoints = std::vector<std::string>{"a", "b"};
dynamic result = note.toDynamic();
dynamic expected = folly::parseJson(R"({
"method": "Debugger.paused",
"params": {
"callFrames": [
{
"callFrameId": "callFrame1",
"functionName": "foo1",
"location": {
"scriptId": "script1",
"lineNumber": 3,
"columnNumber": 4
},
"url": "foo.js",
"scopeChain": [
{
"type": "closure",
"object": {
"type": "object",
"subtype": "regexp",
"className": "RegExp",
"value": { "foo": "bar" },
"unserializableValue": "nope",
"description": "myDesc",
"objectId": "id1"
},
"name": "myScope",
"startLocation": {
"lineNumber": 1,
"scriptId": "script1"
},
"endLocation": {
"lineNumber": 2,
"scriptId": "script2"
}
}
],
"this": { "type": "function" }
}
],
"reason": "debugCommand",
"data": {
"foo": "bar"
},
"hitBreakpoints": [ "a", "b" ]
}
})");
EXPECT_EQ(result, expected);
}
TEST(MessageTests, testDeserializeNotification) {
dynamic message = folly::parseJson(R"({
"method": "Debugger.paused",
"params": {
"callFrames": [
{
"callFrameId": "callFrame1",
"functionName": "foo1",
"location": {
"scriptId": "script1",
"lineNumber": 3,
"columnNumber": 4
},
"url": "foo.js",
"scopeChain": [
{
"type": "closure",
"object": {
"type": "object",
"subtype": "regexp",
"className": "RegExp",
"value": { "foo": "bar" },
"unserializableValue": "nope",
"description": "myDesc",
"objectId": "id1"
},
"name": "myScope",
"startLocation": {
"lineNumber": 1,
"scriptId": "script1"
},
"endLocation": {
"lineNumber": 2,
"scriptId": "script2"
}
}
],
"this": { "type": "function" }
}
],
"reason": "debugCommand",
"data": {
"foo": "bar"
},
"hitBreakpoints": [ "a", "b" ]
}
})");
debugger::PausedNotification note(message);
EXPECT_EQ(note.method, "Debugger.paused");
EXPECT_EQ(note.callFrames.size(), 1);
EXPECT_EQ(note.reason, "debugCommand");
EXPECT_EQ(note.data, static_cast<dynamic>(dynamic::object("foo", "bar")));
auto expectedHitBreakpoints = std::vector<std::string>{"a", "b"};
EXPECT_EQ(note.hitBreakpoints, expectedHitBreakpoints);
debugger::CallFrame &callFrame = note.callFrames[0];
EXPECT_EQ(callFrame.callFrameId, "callFrame1");
EXPECT_EQ(callFrame.functionName, "foo1");
EXPECT_EQ(callFrame.location.scriptId, "script1");
EXPECT_EQ(callFrame.location.lineNumber, 3);
EXPECT_EQ(callFrame.location.columnNumber, 4);
EXPECT_EQ(callFrame.url, "foo.js");
EXPECT_EQ(callFrame.scopeChain.size(), 1);
EXPECT_EQ(callFrame.thisObj.type, "function");
debugger::Scope &scope = callFrame.scopeChain[0];
EXPECT_EQ(scope.type, "closure");
EXPECT_EQ(scope.object.type, "object");
EXPECT_EQ(scope.object.subtype, "regexp");
EXPECT_EQ(scope.object.className, "RegExp");
EXPECT_EQ(
scope.object.value, static_cast<dynamic>(dynamic::object("foo", "bar")));
EXPECT_EQ(scope.object.unserializableValue, "nope");
EXPECT_EQ(scope.object.description, "myDesc");
EXPECT_EQ(scope.object.objectId, "id1");
EXPECT_EQ(scope.name, "myScope");
debugger::Location &startLocation = scope.startLocation.value();
EXPECT_EQ(startLocation.lineNumber, 1);
EXPECT_FALSE(startLocation.columnNumber.hasValue());
EXPECT_EQ(startLocation.scriptId, "script1");
debugger::Location &endLocation = scope.endLocation.value();
EXPECT_EQ(endLocation.lineNumber, 2);
EXPECT_FALSE(endLocation.columnNumber.hasValue());
EXPECT_EQ(endLocation.scriptId, "script2");
}
TEST(MessageTests, TestSerializeAsyncStackTrace) {
runtime::StackTrace stack;
stack.description = "childStack";
stack.parent = std::make_unique<runtime::StackTrace>();
stack.parent->description = "parentStack";
dynamic result = stack.toDynamic();
dynamic expected = folly::parseJson(R"({
"description": "childStack",
"callFrames": [],
"parent": {
"description": "parentStack",
"callFrames": []
}
})");
EXPECT_EQ(result, expected);
}
TEST(MessageTests, TestDeserializeAsyncStackTrace) {
dynamic message = folly::parseJson(R"({
"description": "childStack",
"callFrames": [],
"parent": {
"description": "parentStack",
"callFrames": []
}
})");
runtime::StackTrace stack(message);
EXPECT_EQ(stack.description, "childStack");
EXPECT_EQ(stack.callFrames.size(), 0);
EXPECT_EQ(stack.parent->description, "parentStack");
EXPECT_EQ(stack.parent->callFrames.size(), 0);
}
TEST(MessageTests, TestRequestFromJson) {
std::unique_ptr<Request> baseReq1 = Request::fromJsonThrowOnError(R"({
"id": 1,
"method": "Debugger.enable"
})");
auto req1 = static_cast<debugger::EnableRequest *>(baseReq1.get());
EXPECT_EQ(req1->id, 1);
EXPECT_EQ(req1->method, "Debugger.enable");
std::unique_ptr<Request> baseReq2 = Request::fromJsonThrowOnError(R"({
"id": 2,
"method": "Debugger.removeBreakpoint",
"params": {
"breakpointId": "foobar"
}
})");
auto req2 = static_cast<debugger::RemoveBreakpointRequest *>(baseReq2.get());
EXPECT_EQ(req2->id, 2);
EXPECT_EQ(req2->method, "Debugger.removeBreakpoint");
EXPECT_EQ(req2->breakpointId, "foobar");
folly::Try<std::unique_ptr<Request>> invalidReq =
Request::fromJson("invalid");
EXPECT_TRUE(invalidReq.hasException());
}
TEST(MessageTests, TestBreakpointRequestFromJSON) {
std::unique_ptr<Request> baseReq = Request::fromJsonThrowOnError(R"({
"id": 1,
"method": "Debugger.setBreakpoint",
"params": {
"location": {
"scriptId": "23",
"lineNumber": 45,
"columnNumber": 67
}
}
})");
auto req = static_cast<debugger::SetBreakpointRequest *>(baseReq.get());
EXPECT_EQ(req->location.scriptId, "23");
EXPECT_EQ(req->location.lineNumber, 45);
EXPECT_EQ(req->location.columnNumber.value(), 67);
}
struct MyHandler : public NoopRequestHandler {
void handle(const debugger::EnableRequest &req) override {
enableReq = req;
}
void handle(const debugger::RemoveBreakpointRequest &req) override {
removeReq = req;
}
debugger::EnableRequest enableReq;
debugger::RemoveBreakpointRequest removeReq;
};
TEST(MessageTests, TestRequestHandler) {
MyHandler handler;
std::unique_ptr<Request> enableReq = Request::fromJsonThrowOnError(R"({
"id": 1,
"method": "Debugger.enable"
})");
enableReq->accept(handler);
EXPECT_EQ(handler.enableReq.id, 1);
EXPECT_EQ(handler.enableReq.method, "Debugger.enable");
std::unique_ptr<Request> removeReq = Request::fromJsonThrowOnError(R"({
"id": 2,
"method": "Debugger.removeBreakpoint",
"params": {
"breakpointId": "foobar"
}
})");
removeReq->accept(handler);
EXPECT_EQ(handler.removeReq.id, 2);
EXPECT_EQ(handler.removeReq.method, "Debugger.removeBreakpoint");
EXPECT_EQ(handler.removeReq.breakpointId, "foobar");
}
TEST(MessageTests, testEnableRequest) {
std::string message = R"(
{
"id": 10,
"method": "Debugger.enable"
}
)";
// Builder does not throw
auto req = Request::fromJsonThrowOnError(message);
debugger::EnableRequest *resolvedReq =
dynamic_cast<debugger::EnableRequest *>(req.get());
// Builder returns correct type
EXPECT_FALSE(resolvedReq == nullptr);
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::EnableRequest deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics
EXPECT_EQ(resolvedReq->id, 10);
EXPECT_EQ(resolvedReq->method, "Debugger.enable");
EXPECT_EQ(resolvedReq->id, deserializedReq.id);
EXPECT_EQ(resolvedReq->method, deserializedReq.method);
}
TEST(MessageTests, testDisableRequest) {
std::string message = R"(
{
"id": 10,
"method": "Debugger.disable"
}
)";
// Builder does not throw
auto req = Request::fromJsonThrowOnError(message);
debugger::DisableRequest *resolvedReq =
dynamic_cast<debugger::DisableRequest *>(req.get());
// Builder returns correct type
EXPECT_FALSE(resolvedReq == nullptr);
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::DisableRequest deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics
EXPECT_EQ(resolvedReq->id, 10);
EXPECT_EQ(resolvedReq->method, "Debugger.disable");
EXPECT_EQ(resolvedReq->id, deserializedReq.id);
EXPECT_EQ(resolvedReq->method, deserializedReq.method);
}
TEST(MessageTests, testEvaluateOnCallFrameRequestMinimal) {
std::string message = R"(
{
"id": 10,
"method": "Debugger.evaluateOnCallFrame",
"params":{
"callFrameId" : "42",
"expression": "Foo Bar"
}
}
)";
// Builder does not throw
auto req = Request::fromJsonThrowOnError(message);
debugger::EvaluateOnCallFrameRequest *resolvedReq =
dynamic_cast<debugger::EvaluateOnCallFrameRequest *>(req.get());
// Builder returns correct type
EXPECT_FALSE(resolvedReq == nullptr);
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::EvaluateOnCallFrameRequest deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics
EXPECT_EQ(resolvedReq->id, 10);
EXPECT_EQ(resolvedReq->method, "Debugger.evaluateOnCallFrame");
EXPECT_EQ(resolvedReq->callFrameId, "42");
EXPECT_EQ(resolvedReq->expression, "Foo Bar");
EXPECT_EQ(resolvedReq->id, deserializedReq.id);
EXPECT_EQ(resolvedReq->method, deserializedReq.method);
EXPECT_EQ(resolvedReq->callFrameId, deserializedReq.callFrameId);
EXPECT_EQ(resolvedReq->expression, deserializedReq.expression);
EXPECT_FALSE(resolvedReq->objectGroup.hasValue());
EXPECT_FALSE(resolvedReq->includeCommandLineAPI.hasValue());
EXPECT_FALSE(resolvedReq->silent.hasValue());
EXPECT_FALSE(resolvedReq->returnByValue.hasValue());
EXPECT_FALSE(resolvedReq->throwOnSideEffect.hasValue());
}
TEST(MessageTests, testEvaluateOnCallFrameRequestFull) {
std::string message = R"(
{
"id": 10,
"method": "Debugger.evaluateOnCallFrame",
"params":{
"callFrameId" : "42",
"expression": "Foo Bar",
"objectGroup" : "FooBarGroup",
"includeCommandLineAPI" : false,
"silent" : true,
"returnByValue" : false,
"throwOnSideEffect" : true
}
}
)";
// Builder does not throw
auto req = Request::fromJsonThrowOnError(message);
debugger::EvaluateOnCallFrameRequest *resolvedReq =
dynamic_cast<debugger::EvaluateOnCallFrameRequest *>(req.get());
// Builder returns correct type
EXPECT_FALSE(resolvedReq == nullptr);
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::EvaluateOnCallFrameRequest deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics, resolvedReq is correct
EXPECT_EQ(resolvedReq->id, 10);
EXPECT_EQ(resolvedReq->method, "Debugger.evaluateOnCallFrame");
EXPECT_EQ(resolvedReq->callFrameId, "42");
EXPECT_EQ(resolvedReq->expression, "Foo Bar");
EXPECT_TRUE(resolvedReq->objectGroup.hasValue());
EXPECT_TRUE(resolvedReq->includeCommandLineAPI.hasValue());
EXPECT_TRUE(resolvedReq->silent.hasValue());
EXPECT_TRUE(resolvedReq->returnByValue.hasValue());
EXPECT_TRUE(resolvedReq->throwOnSideEffect.hasValue());
EXPECT_TRUE(resolvedReq->objectGroup.value() == "FooBarGroup");
EXPECT_TRUE(resolvedReq->includeCommandLineAPI.value() == false);
EXPECT_TRUE(resolvedReq->silent.value() == true);
EXPECT_TRUE(resolvedReq->returnByValue.value() == false);
EXPECT_TRUE(resolvedReq->throwOnSideEffect.value() == true);
// Specifics, resolvedReq and deserialized match
EXPECT_EQ(resolvedReq->id, deserializedReq.id);
EXPECT_EQ(resolvedReq->method, deserializedReq.method);
EXPECT_EQ(resolvedReq->callFrameId, deserializedReq.callFrameId);
EXPECT_EQ(resolvedReq->expression, deserializedReq.expression);
EXPECT_EQ(
resolvedReq->objectGroup.value(), deserializedReq.objectGroup.value());
EXPECT_EQ(
resolvedReq->includeCommandLineAPI.value(),
deserializedReq.includeCommandLineAPI.value());
EXPECT_EQ(resolvedReq->silent.value(), deserializedReq.silent.value());
EXPECT_EQ(
resolvedReq->returnByValue.value(),
deserializedReq.returnByValue.value());
EXPECT_EQ(
resolvedReq->throwOnSideEffect.value(),
deserializedReq.throwOnSideEffect.value());
}
TEST(MessageTests, testPauseRequest) {
std::string message = R"(
{
"id": 10,
"method": "Debugger.pause"
}
)";
// Builder does not throw
auto req = Request::fromJsonThrowOnError(message);
debugger::PauseRequest *resolvedReq =
dynamic_cast<debugger::PauseRequest *>(req.get());
// Builder returns correct type
EXPECT_FALSE(resolvedReq == nullptr);
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::PauseRequest deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics
EXPECT_EQ(resolvedReq->id, 10);
EXPECT_EQ(resolvedReq->method, "Debugger.pause");
EXPECT_EQ(resolvedReq->id, deserializedReq.id);
EXPECT_EQ(resolvedReq->method, deserializedReq.method);
}
TEST(MessageTests, testRemoveBreakpointRequest) {
std::string message = R"(
{
"id": 10,
"method": "Debugger.removeBreakpoint",
"params":{
"breakpointId" : "42"
}
}
)";
// Builder does not throw
auto req = Request::fromJsonThrowOnError(message);
debugger::RemoveBreakpointRequest *resolvedReq =
dynamic_cast<debugger::RemoveBreakpointRequest *>(req.get());
// Builder returns correct type
EXPECT_FALSE(resolvedReq == nullptr);
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::RemoveBreakpointRequest deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics
EXPECT_EQ(resolvedReq->id, 10);
EXPECT_EQ(resolvedReq->method, "Debugger.removeBreakpoint");
EXPECT_TRUE(resolvedReq->breakpointId == "42");
EXPECT_EQ(resolvedReq->id, deserializedReq.id);
EXPECT_EQ(resolvedReq->method, deserializedReq.method);
EXPECT_EQ(resolvedReq->breakpointId, deserializedReq.breakpointId);
}
TEST(MessageTests, testResumeRequest) {
std::string message = R"(
{
"id": 10,
"method": "Debugger.resume",
"params": {
"terminateOnResume": false
}
}
)";
// Builder does not throw
auto req = Request::fromJsonThrowOnError(message);
debugger::ResumeRequest *resolvedReq =
dynamic_cast<debugger::ResumeRequest *>(req.get());
// Builder returns correct type
EXPECT_FALSE(resolvedReq == nullptr);
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::ResumeRequest deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics
EXPECT_EQ(resolvedReq->id, 10);
EXPECT_EQ(resolvedReq->method, "Debugger.resume");
EXPECT_EQ(resolvedReq->id, deserializedReq.id);
EXPECT_EQ(resolvedReq->method, deserializedReq.method);
}
TEST(MessageTests, testSetBreakpointRequestMinimal) {
std::string message = R"(
{
"id": 10,
"method": "Debugger.setBreakpoint",
"params":{
"location" :
{
"lineNumber": 2,
"columnNumber": 3,
"scriptId": "myScriptId"
}
}
}
)";
// Builder does not throw
auto req = Request::fromJsonThrowOnError(message);
debugger::SetBreakpointRequest *resolvedReq =
dynamic_cast<debugger::SetBreakpointRequest *>(req.get());
// Builder returns correct type
EXPECT_FALSE(resolvedReq == nullptr);
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::SetBreakpointRequest deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics
debugger::Location location;
location.scriptId = "myScriptId";
location.lineNumber = 2;
location.columnNumber = 3;
EXPECT_EQ(resolvedReq->id, 10);
EXPECT_EQ(resolvedReq->method, "Debugger.setBreakpoint");
EXPECT_EQ(resolvedReq->location.scriptId, "myScriptId");
EXPECT_EQ(resolvedReq->location.lineNumber, 2);
EXPECT_EQ(resolvedReq->location.columnNumber, 3);
EXPECT_FALSE(resolvedReq->condition.hasValue());
EXPECT_EQ(resolvedReq->id, deserializedReq.id);
EXPECT_EQ(resolvedReq->method, deserializedReq.method);
EXPECT_EQ(resolvedReq->location.scriptId, deserializedReq.location.scriptId);
EXPECT_EQ(
resolvedReq->location.lineNumber, deserializedReq.location.lineNumber);
EXPECT_EQ(
resolvedReq->location.columnNumber,
deserializedReq.location.columnNumber);
}
TEST(MessageTests, testSetBreakpointRequestFull) {
std::string message = R"(
{
"id": 10,
"method": "Debugger.setBreakpoint",
"params":{
"location" :
{
"lineNumber": 2,
"columnNumber": 3,
"scriptId": "myScriptId"
},
"condition": "FooBarCondition"
}
}
)";
// Builder does not throw
auto req = Request::fromJsonThrowOnError(message);
debugger::SetBreakpointRequest *resolvedReq =
dynamic_cast<debugger::SetBreakpointRequest *>(req.get());
// Builder returns correct type
EXPECT_FALSE(resolvedReq == nullptr);
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::SetBreakpointRequest deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics
EXPECT_EQ(resolvedReq->id, 10);
EXPECT_EQ(resolvedReq->method, "Debugger.setBreakpoint");
EXPECT_EQ(resolvedReq->location.scriptId, "myScriptId");
EXPECT_EQ(resolvedReq->location.lineNumber, 2);
EXPECT_EQ(resolvedReq->location.columnNumber, 3);
EXPECT_TRUE(resolvedReq->condition.hasValue());
EXPECT_EQ(resolvedReq->condition.value(), "FooBarCondition");
EXPECT_EQ(resolvedReq->id, deserializedReq.id);
EXPECT_EQ(resolvedReq->method, deserializedReq.method);
EXPECT_EQ(resolvedReq->location.scriptId, deserializedReq.location.scriptId);
EXPECT_EQ(
resolvedReq->location.lineNumber, deserializedReq.location.lineNumber);
EXPECT_EQ(
resolvedReq->location.columnNumber,
deserializedReq.location.columnNumber);
EXPECT_EQ(resolvedReq->condition.value(), deserializedReq.condition.value());
}
TEST(MessageTests, testSetBreakpointByUrlRequestMinimal) {
std::string message = R"(
{
"id": 1,
"method": "Debugger.setBreakpointByUrl",
"params": {
"lineNumber": 2
}
}
)";
// Builder does not throw
auto req = Request::fromJsonThrowOnError(message);
debugger::SetBreakpointByUrlRequest *resolvedReq =
dynamic_cast<debugger::SetBreakpointByUrlRequest *>(req.get());
// Builder returns correct type
EXPECT_FALSE(resolvedReq == nullptr);
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::SetBreakpointByUrlRequest deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics
EXPECT_EQ(resolvedReq->id, 1);
EXPECT_EQ(resolvedReq->method, "Debugger.setBreakpointByUrl");
EXPECT_EQ(resolvedReq->lineNumber, 2);
EXPECT_FALSE(resolvedReq->condition.hasValue());
EXPECT_FALSE(resolvedReq->columnNumber.hasValue());
EXPECT_FALSE(resolvedReq->url.hasValue());
EXPECT_FALSE(resolvedReq->urlRegex.hasValue());
EXPECT_EQ(resolvedReq->id, deserializedReq.id);
EXPECT_EQ(resolvedReq->method, deserializedReq.method);
EXPECT_EQ(resolvedReq->lineNumber, deserializedReq.lineNumber);
}
TEST(MessageTests, testSetBreakpointByUrlRequestFull) {
std::string message = R"(
{
"id": 1,
"method": "Debugger.setBreakpointByUrl",
"params": {
"lineNumber": 2,
"columnNumber": 3,
"condition": "foo == 42",
"url": "http://example.com/example.js",
"urlRegex": "http://example.com/.*"
}
}
)";
// Builder does not throw
auto req = Request::fromJsonThrowOnError(message);
debugger::SetBreakpointByUrlRequest *resolvedReq =
dynamic_cast<debugger::SetBreakpointByUrlRequest *>(req.get());
// Builder returns correct type
EXPECT_FALSE(resolvedReq == nullptr);
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::SetBreakpointByUrlRequest deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics
EXPECT_EQ(resolvedReq->id, 1);
EXPECT_EQ(resolvedReq->method, "Debugger.setBreakpointByUrl");
EXPECT_EQ(resolvedReq->lineNumber, 2);
EXPECT_TRUE(resolvedReq->condition.hasValue());
EXPECT_EQ(resolvedReq->condition.value(), "foo == 42");
EXPECT_TRUE(resolvedReq->columnNumber.hasValue());
EXPECT_EQ(resolvedReq->columnNumber.value(), 3);
EXPECT_TRUE(resolvedReq->url.hasValue());
EXPECT_EQ(resolvedReq->url.value(), "http://example.com/example.js");
EXPECT_TRUE(resolvedReq->urlRegex.hasValue());
EXPECT_EQ(resolvedReq->urlRegex.value(), "http://example.com/.*");
EXPECT_EQ(resolvedReq->id, deserializedReq.id);
EXPECT_EQ(resolvedReq->method, deserializedReq.method);
EXPECT_EQ(resolvedReq->lineNumber, deserializedReq.lineNumber);
EXPECT_EQ(resolvedReq->condition.value(), deserializedReq.condition.value());
EXPECT_EQ(
resolvedReq->columnNumber.value(), deserializedReq.columnNumber.value());
EXPECT_EQ(resolvedReq->url.value(), deserializedReq.url.value());
EXPECT_EQ(resolvedReq->urlRegex.value(), deserializedReq.urlRegex.value());
}
TEST(MessageTests, testSetBreakpointsActiveRequest) {
std::string message = R"(
{
"id": 1,
"method": "Debugger.setBreakpointsActive",
"params": {
"active": true
}
}
)";
// Builder does not throw
auto req = Request::fromJsonThrowOnError(message);
debugger::SetBreakpointsActiveRequest *resolvedReq =
dynamic_cast<debugger::SetBreakpointsActiveRequest *>(req.get());
// Builder returns correct type
EXPECT_FALSE(resolvedReq == nullptr);
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::SetBreakpointsActiveRequest deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics
EXPECT_EQ(resolvedReq->id, 1);
EXPECT_EQ(resolvedReq->method, "Debugger.setBreakpointsActive");
EXPECT_EQ(resolvedReq->active, true);
EXPECT_EQ(resolvedReq->id, deserializedReq.id);
EXPECT_EQ(resolvedReq->method, deserializedReq.method);
EXPECT_EQ(resolvedReq->active, deserializedReq.active);
}
TEST(MessageTests, testSetInstrumentationBreakpointRequest) {
std::string message = R"(
{
"id": 1,
"method": "Debugger.setInstrumentationBreakpoint",
"params": {
"instrumentation": "TODO: THIS SHOUD NOT BE ACCEPTED BY ENUM"
}
}
)";
// Builder does not throw
auto req = Request::fromJsonThrowOnError(message);
debugger::SetInstrumentationBreakpointRequest *resolvedReq =
dynamic_cast<debugger::SetInstrumentationBreakpointRequest *>(req.get());
// Builder returns correct type
EXPECT_FALSE(resolvedReq == nullptr);
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::SetInstrumentationBreakpointRequest deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics
EXPECT_EQ(resolvedReq->id, 1);
EXPECT_EQ(resolvedReq->method, "Debugger.setInstrumentationBreakpoint");
EXPECT_EQ(
resolvedReq->instrumentation, "TODO: THIS SHOUD NOT BE ACCEPTED BY ENUM");
EXPECT_EQ(resolvedReq->id, deserializedReq.id);
EXPECT_EQ(resolvedReq->method, deserializedReq.method);
EXPECT_EQ(resolvedReq->instrumentation, deserializedReq.instrumentation);
}
TEST(MessageTests, testSetPauseOnExceptionsRequest) {
std::string message = R"(
{
"id": 1,
"method": "Debugger.setPauseOnExceptions",
"params": {
"state": "TODO: THIS SHOUD NOT BE ACCEPTED BY ENUM"
}
}
)";
// Builder does not throw
auto req = Request::fromJsonThrowOnError(message);
debugger::SetPauseOnExceptionsRequest *resolvedReq =
dynamic_cast<debugger::SetPauseOnExceptionsRequest *>(req.get());
// Builder returns correct type
EXPECT_FALSE(resolvedReq == nullptr);
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::SetPauseOnExceptionsRequest deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics
EXPECT_EQ(resolvedReq->id, 1);
EXPECT_EQ(resolvedReq->method, "Debugger.setPauseOnExceptions");
EXPECT_EQ(resolvedReq->state, "TODO: THIS SHOUD NOT BE ACCEPTED BY ENUM");
EXPECT_EQ(resolvedReq->id, deserializedReq.id);
EXPECT_EQ(resolvedReq->method, deserializedReq.method);
EXPECT_EQ(resolvedReq->state, deserializedReq.state);
}
TEST(MessageTests, testStepIntoRequest) {
std::string message = R"(
{
"id": 10,
"method": "Debugger.stepInto"
}
)";
// Builder does not throw
auto req = Request::fromJsonThrowOnError(message);
debugger::StepIntoRequest *resolvedReq =
dynamic_cast<debugger::StepIntoRequest *>(req.get());
// Builder returns correct type
EXPECT_FALSE(resolvedReq == nullptr);
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::StepIntoRequest deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics
EXPECT_EQ(resolvedReq->id, 10);
EXPECT_EQ(resolvedReq->method, "Debugger.stepInto");
EXPECT_EQ(resolvedReq->id, deserializedReq.id);
EXPECT_EQ(resolvedReq->method, deserializedReq.method);
}
TEST(MessageTests, testStepOutRequest) {
std::string message = R"(
{
"id": 10,
"method": "Debugger.stepOut"
}
)";
// Builder does not throw
auto req = Request::fromJsonThrowOnError(message);
debugger::StepOutRequest *resolvedReq =
dynamic_cast<debugger::StepOutRequest *>(req.get());
// Builder returns correct type
EXPECT_FALSE(resolvedReq == nullptr);
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::StepOutRequest deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics
EXPECT_EQ(resolvedReq->id, 10);
EXPECT_EQ(resolvedReq->method, "Debugger.stepOut");
EXPECT_EQ(resolvedReq->id, deserializedReq.id);
EXPECT_EQ(resolvedReq->method, deserializedReq.method);
}
TEST(MessageTests, testStepOverRequest) {
std::string message = R"(
{
"id": 10,
"method": "Debugger.stepOver"
}
)";
// Builder does not throw
auto req = Request::fromJsonThrowOnError(message);
debugger::StepOverRequest *resolvedReq =
dynamic_cast<debugger::StepOverRequest *>(req.get());
// Builder returns correct type
EXPECT_FALSE(resolvedReq == nullptr);
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::StepOverRequest deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics
EXPECT_EQ(resolvedReq->id, 10);
EXPECT_EQ(resolvedReq->method, "Debugger.stepOver");
EXPECT_EQ(resolvedReq->id, deserializedReq.id);
EXPECT_EQ(resolvedReq->method, deserializedReq.method);
}
TEST(MessageTests, testEvaluateOnCallFrameResponseMinimal) {
std::string message = R"(
{
"result":
{
"result":{
"type": "string"
}
},
"id":2
}
)";
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::EvaluateOnCallFrameResponse deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
EXPECT_FALSE(deserializedReq.result.subtype.hasValue());
EXPECT_FALSE(deserializedReq.result.value.hasValue());
EXPECT_FALSE(deserializedReq.result.unserializableValue.hasValue());
EXPECT_FALSE(deserializedReq.result.description.hasValue());
EXPECT_FALSE(deserializedReq.result.objectId.hasValue());
// Specifics
EXPECT_EQ(deserializedReq.id, 2);
EXPECT_EQ(deserializedReq.result.type, "string");
}
TEST(MessageTests, testEvaluateOnCallFrameResponseFull) {
std::string message = R"(
{
"result":
{
"result":{
"type": "string",
"subtype": "SuperString",
"value": {"foobarkey": "foobarval"},
"unserializableValue": "unserializableValueVal",
"description": "A Wonderful desc",
"objectId": "AnObjectID"
}
},
"id":2
}
)";
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::EvaluateOnCallFrameResponse deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
EXPECT_TRUE(deserializedReq.result.subtype.hasValue());
EXPECT_TRUE(deserializedReq.result.value.hasValue());
EXPECT_TRUE(deserializedReq.result.unserializableValue.hasValue());
EXPECT_TRUE(deserializedReq.result.description.hasValue());
EXPECT_TRUE(deserializedReq.result.objectId.hasValue());
EXPECT_EQ(deserializedReq.result.subtype.value(), "SuperString");
EXPECT_EQ(
deserializedReq.result.value.value(),
folly::parseJson(R"({"foobarkey": "foobarval"})"));
EXPECT_EQ(
deserializedReq.result.unserializableValue.value(),
"unserializableValueVal");
EXPECT_EQ(deserializedReq.result.description.value(), "A Wonderful desc");
EXPECT_EQ(deserializedReq.result.objectId.value(), "AnObjectID");
// Specifics
EXPECT_EQ(deserializedReq.id, 2);
EXPECT_EQ(deserializedReq.result.type, "string");
}
TEST(MessageTests, testSetBreakpointByUrlResponse) {
std::string message = R"({
"id": 1,
"result":{
"breakpointId": "myBreakpointId",
"locations": [
{
"lineNumber": 2,
"columnNumber": 3,
"scriptId": "myScriptId"
}
]
}
})";
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::SetBreakpointByUrlResponse deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics
EXPECT_EQ(deserializedReq.id, 1);
EXPECT_EQ(deserializedReq.breakpointId, "myBreakpointId");
EXPECT_EQ(deserializedReq.locations.size(), 1);
EXPECT_EQ(deserializedReq.locations[0].lineNumber, 2);
EXPECT_EQ(deserializedReq.locations[0].columnNumber, 3);
EXPECT_EQ(deserializedReq.locations[0].scriptId, "myScriptId");
}
TEST(MessageTests, testSetBreakpointResponse) {
std::string message = R"({
"id": 1,
"result":{
"breakpointId": "myBreakpointId",
"actualLocation":
{
"lineNumber": 2,
"columnNumber": 3,
"scriptId": "myScriptId"
}
}
})";
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::SetBreakpointResponse deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics
EXPECT_EQ(deserializedReq.breakpointId, "myBreakpointId");
EXPECT_EQ(deserializedReq.actualLocation.lineNumber, 2);
EXPECT_EQ(deserializedReq.actualLocation.columnNumber, 3);
EXPECT_EQ(deserializedReq.actualLocation.scriptId, "myScriptId");
EXPECT_EQ(deserializedReq.id, 1);
}
TEST(MessageTests, testSetInstrumentationBreakpointResponse) {
std::string message = R"({
"id": 1,
"result":{
"breakpointId": "myBreakpointId"
}
})";
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::SetInstrumentationBreakpointResponse deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics
EXPECT_EQ(deserializedReq.breakpointId, "myBreakpointId");
EXPECT_EQ(deserializedReq.id, 1);
}
TEST(MessageTests, testBreakpointResolvedNotification) {
std::string message = R"(
{
"method": "Debugger.breakpointResolved",
"params":{
"breakpointId" : "42",
"location":
{
"lineNumber": 2,
"columnNumber": 3,
"scriptId": "myScriptId"
}
}
}
)";
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::BreakpointResolvedNotification deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics
EXPECT_EQ(deserializedReq.method, "Debugger.breakpointResolved");
EXPECT_EQ(deserializedReq.breakpointId, "42");
EXPECT_EQ(deserializedReq.location.lineNumber, 2);
EXPECT_EQ(deserializedReq.location.columnNumber, 3);
EXPECT_EQ(deserializedReq.location.scriptId, "myScriptId");
}
TEST(MessageTests, testPauseNotificationMinimal) {
std::string message = R"(
{
"method": "Debugger.paused",
"params":{
"reason": "Some Valid Reason",
"callFrames":[
{
"callFrameId": "aCallFrameId",
"functionName": "aFunctionName",
"location":{
"lineNumber": 2,
"columnNumber": 3,
"scriptId": "myScriptId"
},
"url": "aURL",
"scopeChain": [
{
"type": "aType",
"object": {
"type": "aRemoteObjectType"
}
}
],
"this": {
"type": "aType"
}
}
]
}
}
)";
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::PausedNotification deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
EXPECT_FALSE(deserializedReq.callFrames[0].functionLocation.hasValue());
EXPECT_FALSE(deserializedReq.callFrames[0].returnValue.hasValue());
EXPECT_FALSE(deserializedReq.asyncStackTrace.hasValue());
EXPECT_FALSE(deserializedReq.hitBreakpoints.hasValue());
EXPECT_FALSE(deserializedReq.data.hasValue());
// Specifics
EXPECT_EQ(deserializedReq.method, "Debugger.paused");
EXPECT_EQ(deserializedReq.reason, "Some Valid Reason");
EXPECT_EQ(deserializedReq.callFrames[0].functionName, "aFunctionName");
EXPECT_EQ(deserializedReq.callFrames[0].callFrameId, "aCallFrameId");
EXPECT_EQ(deserializedReq.callFrames[0].url, "aURL");
EXPECT_EQ(deserializedReq.callFrames[0].location.lineNumber, 2);
EXPECT_EQ(deserializedReq.callFrames[0].location.columnNumber, 3);
EXPECT_EQ(deserializedReq.callFrames[0].location.scriptId, "myScriptId");
EXPECT_EQ(deserializedReq.callFrames[0].scopeChain[0].type, "aType");
EXPECT_EQ(
deserializedReq.callFrames[0].scopeChain[0].object.type,
"aRemoteObjectType");
EXPECT_EQ(deserializedReq.callFrames[0].thisObj.type, "aType");
}
TEST(MessageTests, testPauseNotificationFull) {
std::string message = R"(
{
"method": "Debugger.paused",
"params":{
"reason": "Some Valid Reason",
"callFrames":[
{
"functionLocation": {
"lineNumber": 2,
"columnNumber": 3,
"scriptId": "myScriptId"
},
"returnValue" : {
"type": "aRemoteObjectType",
"subtype": "subtype",
"className":"className",
"value": "value",
"unserializableValue": "unserializableValue",
"description": "description",
"objectId": "objectId"
},
"callFrameId": "aCallFrameId",
"functionName": "aFunctionName",
"location":{
"lineNumber": 2,
"columnNumber": 3,
"scriptId": "myScriptId"
},
"url": "aURL",
"scopeChain": [
{
"type": "aType",
"object": {
"type": "aRemoteObjectType"
}
}
],
"this": {
"type": "aType"
}
}
],
"data": {"dataKey": "dataVal"},
"hitBreakpoints": [
"foo","bar"
],
"asyncStackTrace":{
"description": "an asyncStackTrace Desc",
"callFrames":[
{
"functionName": "aFunctionName",
"lineNumber": 2,
"columnNumber": 3,
"scriptId": "myScriptId",
"url": "aURL"
}
]
}
}
}
)";
folly::Optional<debugger::Location> functionLocation;
folly::Optional<runtime::RemoteObject> returnValue;
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::PausedNotification deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Check optionnals
// ----------------
EXPECT_TRUE(deserializedReq.callFrames[0].functionLocation.hasValue());
EXPECT_TRUE(deserializedReq.callFrames[0].returnValue.hasValue());
EXPECT_TRUE(deserializedReq.asyncStackTrace.hasValue());
EXPECT_TRUE(deserializedReq.hitBreakpoints.hasValue());
EXPECT_TRUE(deserializedReq.data.hasValue());
EXPECT_TRUE(
deserializedReq.callFrames[0].returnValue.value().subtype.hasValue());
EXPECT_TRUE(
deserializedReq.callFrames[0].returnValue.value().className.hasValue());
EXPECT_TRUE(deserializedReq.callFrames[0]
.returnValue.value()
.unserializableValue.hasValue());
EXPECT_TRUE(
deserializedReq.callFrames[0].returnValue.value().value.hasValue());
EXPECT_TRUE(
deserializedReq.callFrames[0].returnValue.value().description.hasValue());
EXPECT_TRUE(
deserializedReq.callFrames[0].returnValue.value().objectId.hasValue());
// Check optionnals Values
// -----------------------
EXPECT_EQ(
deserializedReq.callFrames[0].functionLocation.value().lineNumber, 2);
EXPECT_EQ(
deserializedReq.callFrames[0].functionLocation.value().columnNumber, 3);
EXPECT_EQ(
deserializedReq.callFrames[0].functionLocation.value().scriptId,
"myScriptId");
EXPECT_EQ(
deserializedReq.callFrames[0].returnValue.value().type,
"aRemoteObjectType");
EXPECT_EQ(
deserializedReq.callFrames[0].returnValue.value().subtype.hasValue(),
true);
EXPECT_EQ(
deserializedReq.callFrames[0].returnValue.value().subtype.value(),
"subtype");
EXPECT_EQ(
deserializedReq.callFrames[0].returnValue.value().className.hasValue(),
true);
EXPECT_EQ(
deserializedReq.callFrames[0].returnValue.value().className.value(),
"className");
EXPECT_EQ(
deserializedReq.callFrames[0].returnValue.value().value.hasValue(), true);
EXPECT_EQ(
deserializedReq.callFrames[0].returnValue.value().value.value(), "value");
EXPECT_EQ(
deserializedReq.callFrames[0]
.returnValue.value()
.unserializableValue.hasValue(),
true);
EXPECT_EQ(
deserializedReq.callFrames[0]
.returnValue.value()
.unserializableValue.value(),
"unserializableValue");
EXPECT_EQ(
deserializedReq.callFrames[0].returnValue.value().description.hasValue(),
true);
EXPECT_EQ(
deserializedReq.callFrames[0].returnValue.value().description.value(),
"description");
EXPECT_EQ(
deserializedReq.callFrames[0].returnValue.value().objectId.hasValue(),
true);
EXPECT_EQ(
deserializedReq.callFrames[0].returnValue.value().objectId.value(),
"objectId");
EXPECT_EQ(deserializedReq.hitBreakpoints.value()[0], "foo");
EXPECT_EQ(deserializedReq.hitBreakpoints.value()[1], "bar");
EXPECT_EQ(
deserializedReq.data.value(),
folly::parseJson(R"({"dataKey": "dataVal"})"));
// Check Compulsory
// ----------------
EXPECT_EQ(deserializedReq.method, "Debugger.paused");
EXPECT_EQ(deserializedReq.reason, "Some Valid Reason");
EXPECT_EQ(deserializedReq.callFrames[0].functionName, "aFunctionName");
EXPECT_EQ(deserializedReq.callFrames[0].callFrameId, "aCallFrameId");
EXPECT_EQ(deserializedReq.callFrames[0].url, "aURL");
EXPECT_EQ(deserializedReq.callFrames[0].location.lineNumber, 2);
EXPECT_EQ(deserializedReq.callFrames[0].location.columnNumber, 3);
EXPECT_EQ(deserializedReq.callFrames[0].location.scriptId, "myScriptId");
EXPECT_EQ(deserializedReq.callFrames[0].scopeChain[0].type, "aType");
EXPECT_EQ(
deserializedReq.callFrames[0].scopeChain[0].object.type,
"aRemoteObjectType");
EXPECT_EQ(deserializedReq.callFrames[0].thisObj.type, "aType");
}
TEST(MessageTests, testResumedNotification) {
std::string message = R"(
{
"method": "Debugger.resumed"
}
)";
// Serialize and Deserialize are inverse functions
dynamic messageJSON = folly::parseJson(message);
debugger::ResumedNotification deserializedReq(messageJSON);
EXPECT_EQ(deserializedReq.toDynamic(), messageJSON);
// Specifics
EXPECT_EQ(deserializedReq.method, "Debugger.resumed");
}
} // namespace message
} // namespace chrome
} // namespace inspector
} // namespace hermes
} // namespace facebook