From 31a92b008dbdab75bca358632d7f6b888fbe7a24 Mon Sep 17 00:00:00 2001 From: Raphael Herouart Date: Mon, 7 Feb 2022 07:53:31 -0800 Subject: [PATCH] Add some tests for compliance to the Chrome DevTools Protocol Summary: Some test to make sure hermes engine follows the Chrome DevTools Protocol for all implemented Debugger Messages Changelog: [Internal] Reviewed By: ShikaSD Differential Revision: D34042008 fbshipit-source-id: 3a074e9840706ca977ff86d050e67b0dcea5c7ef --- .../inspector/chrome/tests/MessageTests.cpp | 649 +++++++++++++++++- 1 file changed, 648 insertions(+), 1 deletion(-) diff --git a/ReactCommon/hermes/inspector/chrome/tests/MessageTests.cpp b/ReactCommon/hermes/inspector/chrome/tests/MessageTests.cpp index 1bd85d669e1..51a64f533e4 100644 --- a/ReactCommon/hermes/inspector/chrome/tests/MessageTests.cpp +++ b/ReactCommon/hermes/inspector/chrome/tests/MessageTests.cpp @@ -52,6 +52,7 @@ TEST(MessageTests, testDeserializeSomeFieldsInRequest) { )"); 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); @@ -151,7 +152,7 @@ TEST(MessageTests, testDeserializeResponse) { } })"); 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); @@ -455,6 +456,652 @@ TEST(MessageTests, TestRequestHandler) { 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(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(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(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(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(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(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" + } + )"; + + // Builder does not throw + auto req = Request::fromJsonThrowOnError(message); + debugger::ResumeRequest *resolvedReq = + dynamic_cast(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(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(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(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(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(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(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(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(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(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(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); +} + } // namespace message } // namespace chrome } // namespace inspector