avs-device-sdk/CapabilityAgents/Alexa/test/AlexaInterfaceMessageSender...

816 lines
29 KiB
C++

/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
#include <chrono>
#include <memory>
#include <thread>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <rapidjson/document.h>
#include <rapidjson/error/en.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <AVSCommon/AVS/AVSDirective.h>
#include <AVSCommon/SDKInterfaces/MockContextManager.h>
#include <AVSCommon/SDKInterfaces/MockExceptionEncounteredSender.h>
#include <AVSCommon/SDKInterfaces/MockMessageSender.h>
#include <AVSCommon/Utils/Timing/TimePoint.h>
#include "Alexa/AlexaInterfaceMessageSender.h"
namespace alexaClientSDK {
namespace capabilityAgents {
namespace alexa {
namespace test {
using namespace ::testing;
using namespace avsCommon::avs;
using namespace avsCommon::sdkInterfaces;
using namespace avsCommon::sdkInterfaces::test;
using namespace avsCommon::utils;
using namespace avsCommon::utils::timing;
using namespace rapidjson;
/// Amount of time for the test to wait for event to be sent.
static const std::chrono::seconds MY_WAIT_TIMEOUT(2);
/// Name for PowerController.
static const std::string NAME_POWER_CONTROLLER("PowerController");
/// Namespace for PowerController.
static const std::string NAMESPACE_POWER_CONTROLLER("Alexa.PowerController");
/// Name for TurnOn directive to PowerController.
static const std::string NAME_TURN_ON("TurnOn");
/// Name for powerState.
static const std::string POWER_STATE("powerState");
/// Value for powerState ON.
static const std::string POWER_STATE_ON("\"ON\"");
/// Event key.
static const std::string EVENT("event");
/// Header key.
static const std::string HEADER("header");
/// Message Id key.
static const std::string MESSAGE_ID("messageId");
/// Message Id for testing.
static const std::string MESSAGE_ID_TEST("MessageId_Test");
/// Correlation token Key.
static const std::string CORRELATION_TOKEN("correlationToken");
/// Correlation token for testing.
static const std::string CORRELATION_TOKEN_TEST("CorrelationToken_Test");
/// Event correlation token Key.
static const std::string EVENT_CORRELATION_TOKEN("eventCorrelationToken");
/// Event correlation token for testing.
static const std::string EVENT_CORRELATION_TOKEN_TEST("EventCorrelationToken_Test");
/// Payload key
static const std::string PAYLOAD_VERSION("version");
/// A speech recognizer payload for testing
static const std::string PAYLOAD_VERSION_TEST("3");
/// Payload key
static const std::string TIME_OF_SAMPLE("timeOfSample");
/// A speech recognizer payload for testing
static const std::string TIME_OF_SAMPLE_TEST("2017-02-03T16:20:50.523Z");
/// Payload key
static const std::string ENDPOINT_ID("endpointId");
/// A speech recognizer payload for testing
static const std::string ENDPOINT_ID_TEST("EndpointId_Test");
/// Payload key
static const std::string ERROR_ENDPOINT_UNREACHABLE("ENDPOINT_UNREACHABLE");
/// A speech recognizer payload for testing
static const std::string ERROR_ENDPOINT_UNREACHABLE_MESSAGE("Endpoint unreachable message");
/// Payload key
static const std::string PAYLOAD("payload");
/// A speech recognizer payload for testing
static const std::string PAYLOAD_TEST("payload_Test");
// clang-format off
/// A StateReport context for testing.
static const std::string STATE_REPORT_CONTEXT =
"\"context\":{"
"\"properties\":["
"{"
"\"namespace\":\"Alexa.PowerController\","
"\"name\":\"powerState\","
"\"value\":\"ON\","
"\"timeOfSample\":\""+TIME_OF_SAMPLE_TEST+"\","
"\"uncertaintyInMilliseconds\": 0"
"}"
"]"
"}";
/// A StateReport event with context for testing.
static const std::string STATE_REPORT_EVENT_JSON_STRING =
"{"
"\"event\":{"
"\"header\":{"
"\"namespace\":\"Alexa\","
"\"name\":\"StateReport\","
"\"messageId\":\""+MESSAGE_ID_TEST+"\","
"\"correlationToken\":\""+CORRELATION_TOKEN_TEST+"\","
"\"eventCorrelationToken\":\""+EVENT_CORRELATION_TOKEN_TEST+"\","
"\"payloadVersion\":\""+PAYLOAD_VERSION_TEST+"\""
"},"
"\"endpoint\":{"
"\"endpointId\":\""+ENDPOINT_ID_TEST+"\""
"},"
"\"payload\":{}"
"},"
+STATE_REPORT_CONTEXT+
"}";
/// A StateReport event for testing.
static const std::string STATE_REPORT_EVENT_NO_CONTEXT_JSON_STRING =
"{"
"\"event\":{"
"\"header\":{"
"\"namespace\":\"Alexa\","
"\"name\":\"StateReport\","
"\"messageId\":\""+MESSAGE_ID_TEST+"\","
"\"correlationToken\":\""+CORRELATION_TOKEN_TEST+"\","
"\"eventCorrelationToken\":\""+EVENT_CORRELATION_TOKEN_TEST+"\","
"\"payloadVersion\":\""+PAYLOAD_VERSION_TEST+"\""
"},"
"\"endpoint\":{"
"\"endpointId\":\""+ENDPOINT_ID_TEST+"\""
"},"
"\"payload\":{}"
"}"
"}";
/// Sample response from MockContextManager.
static const std::string TURNON_PROPERTIES_STRING =
"\"properties\":["
"{"
"\"namespace\":\"Alexa.PowerController\","
"\"name\":\"powerState\","
"\"value\":\"ON\","
"\"timeOfSample\":\""+TIME_OF_SAMPLE_TEST+"\","
"\"uncertaintyInMilliseconds\": 0"
"}"
"]";
/// Sample response from MockContextManager.
static const std::string TURNON_CONTEXT_STRING =
"\"context\":{"
+TURNON_PROPERTIES_STRING+
"}";
/// Sample response from PowerControllerCapabilityAgent.
static const std::string TURNON_RESPONSE_EVENT_STRING =
"\"event\":{"
"\"header\":{"
"\"namespace\":\"Alexa\","
"\"name\":\"Response\","
"\"messageId\":\""+MESSAGE_ID_TEST+"\","
"\"correlationToken\":\""+CORRELATION_TOKEN_TEST+"\","
"\"eventCorrelationToken\":\""+EVENT_CORRELATION_TOKEN_TEST+"\","
"\"payloadVersion\":\""+PAYLOAD_VERSION_TEST+"\""
"},"
"\"endpoint\":{"
"\"endpointId\":\""+ENDPOINT_ID_TEST+"\""
"},"
"\"payload\":{}"
"}";
/// Complete event response with context.
static const std::string TURNON_RESPONSE_EVENT_WITH_CONTEXT_STRING =
"{"
+TURNON_RESPONSE_EVENT_STRING+","
+TURNON_CONTEXT_STRING+
"}";
/// Complete event response without context.
static const std::string TURNON_RESPONSE_EVENT_WITHOUT_CONTEXT_STRING =
"{"
+TURNON_RESPONSE_EVENT_STRING+
"}";
/// Sample error response
static const std::string ERROR_RESPONSE_EVENT_STRING =
"{"
"\"event\":{"
"\"header\":{"
"\"namespace\":\"Alexa\","
"\"name\":\"ErrorResponse\","
"\"messageId\":\""+MESSAGE_ID_TEST+"\","
"\"correlationToken\":\""+CORRELATION_TOKEN_TEST+"\","
"\"eventCorrelationToken\":\""+EVENT_CORRELATION_TOKEN_TEST+"\","
"\"payloadVersion\":\""+PAYLOAD_VERSION_TEST+"\""
"},"
"\"endpoint\":{"
"\"endpointId\":\""+ENDPOINT_ID_TEST+"\""
"},"
"\"payload\":{"
"\"type\":\""+ERROR_ENDPOINT_UNREACHABLE+"\","
"\"message\":\""+ERROR_ENDPOINT_UNREACHABLE_MESSAGE+"\""
"}"
"}"
"}";
/// Sample deferred response
static const std::string DEFERRED_RESPONSE_EVENT_STRING =
"{"
"\"event\":{"
"\"header\":{"
"\"namespace\":\"Alexa\","
"\"name\":\"DeferredResponse\","
"\"messageId\":\""+MESSAGE_ID_TEST+"\","
"\"correlationToken\":\""+CORRELATION_TOKEN_TEST+"\","
"\"eventCorrelationToken\":\""+EVENT_CORRELATION_TOKEN_TEST+"\","
"\"payloadVersion\":\""+PAYLOAD_VERSION_TEST+"\""
"},"
"\"payload\":{"
"\"estimatedDeferralInSeconds\":7"
"}"
"}"
"}";
/// Sample response from PowerControllerCapabilityAgent.
static const std::string TURNON_CHANGE_REPORT_WITH_CHANGE_EVENT_STRING =
"{"
"\"context\":{"
"\"properties\":[]"
"},"
"\"event\":{"
"\"header\":{"
"\"namespace\":\"Alexa\","
"\"name\":\"ChangeReport\","
"\"messageId\":\""+MESSAGE_ID_TEST+"\","
"\"eventCorrelationToken\":\""+EVENT_CORRELATION_TOKEN_TEST+"\","
"\"payloadVersion\":\""+PAYLOAD_VERSION_TEST+"\""
"},"
"\"endpoint\":{"
"\"endpointId\":\""+ENDPOINT_ID_TEST+"\""
"},"
"\"payload\":{"
"\"change\":{"
"\"cause\":{"
"\"type\":\"ALEXA_INTERACTION\""
"},"
+TURNON_PROPERTIES_STRING+
"}"
"}"
"}"
"}";
// clang-format on
/// Test harness for @c AlexaInterfaceMessageSender class.
class AlexaInterfaceMessageSenderTest : public ::testing::Test {
public:
/// Set up/tear down the test harness for running a test.
void SetUp() override;
void TearDown() override;
public:
/**
* Build a test AVSMessageEndpoint object.
*
* @return the test object
*/
AVSMessageEndpoint buildTestEndpoint(void);
/**
* Build a test CapabilityTag object.
*
* @return the test object
*/
CapabilityTag buildTestTag(void);
/**
* Build a test CapabilityTag object.
*
* @return the test object
*/
CapabilityState buildTestState(void);
/**
* Helper function to create an AlexaInterfaceMessageSender and set the expects for it.
*
* @return pointer to the new AlexaInterfaceMessageSender
*/
std::shared_ptr<AlexaInterfaceMessageSender> createMessageSender(void);
/**
* Helper function to remove the messageId.
*
* @param document The document from which to remove the messageId.
* @param messageId The messageId that was removed (if successful).
* @return bool Indicates whether removing the messageId was successful.
*/
bool removeMessageId(Document* document, std::string* messageId);
/**
* Helper function to remove the eventCorrelationToken.
*
* @param document The document from which to remove the eventCorrelationToken.
* @param eventCorrelationToken The eventCorrelationToken that was removed (if successful).
* @return bool Indicates whether removing the eventCorrelationToken was successful.
*/
bool removeEventCorrelationToken(Document* document, std::string* eventCorrelationToken);
/**
* Setup mocks for sending an event that expects the event to be sent on the happy path.
*
* @param sender the AlexaInterfaceMessageSender to use
* @param jsonEventString the expected event as a JSON string
* @param sendStatus the send status result to be returned
* @param triggerOperation the function to call to start the sending process
* @return true on success, false on failure
*/
bool expectEventSent(
const std::shared_ptr<AlexaInterfaceMessageSender>& sender,
const std::string& jsonEventString,
MessageRequestObserverInterface::Status sendStatus,
std::function<void()> triggerOperation);
/**
* Setup mocks for sending an event, even if the context is invalid.
*
* @param jsonEventString the expected event as a JSON string
* @param sendStatus the send status result to be returned
* @param triggerOperation the function to call to start the sending process
* @return true on success, false on failure
*/
bool expectEventSentOnInvalidContext(
const std::shared_ptr<AlexaInterfaceMessageSender>& sender,
const std::string& jsonEventString,
MessageRequestObserverInterface::Status sendStatus,
std::function<void()> triggerOperation);
/**
* Setup mocks for sending an event that does not require context at all.
*
* @param jsonEventString the expected event as a JSON string
* @param sendStatus the send status result to be returned
* @param triggerOperation the function to call to start the sending process
* @return true on success, false on failure
*/
bool expectEventSentWithoutContext(
const std::shared_ptr<AlexaInterfaceMessageSender>& sender,
const std::string& jsonEventString,
MessageRequestObserverInterface::Status sendStatus,
std::function<void()> triggerOperation);
/**
* Setup mocks for an event that should not be sent if context is invalid.
*
* @param jsonEventString the expected event as a JSON string
* @param sendStatus the send status result to be returned
* @param triggerOperation the function to call to start the sending process
* @return true on success, false on failure
*/
bool expectEventNotSentOnInvalidContext(
const std::shared_ptr<AlexaInterfaceMessageSender>& sender,
const std::string& jsonEventString,
MessageRequestObserverInterface::Status sendStatus,
std::function<void()> triggerOperation);
/**
* Check to see that an event JSON matches the expected result after removing fields that are always different.
*
* @param jsonEventString the event JSON string to check
* @param testEventString the event JSON string to test against
* @return true on success, false on failure
*/
bool checkEventJson(std::string jsonEventString, std::string testEventString);
protected:
/// Context manager mock.
std::shared_ptr<avsCommon::sdkInterfaces::test::MockContextManager> m_mockContextManager;
/// Message sender mock to track messages being sent.
std::shared_ptr<MockMessageSender> m_messageSender;
/// Test @c AVSContext object.
AVSContext m_context;
};
void AlexaInterfaceMessageSenderTest::SetUp() {
m_mockContextManager = std::make_shared<StrictMock<avsCommon::sdkInterfaces::test::MockContextManager>>();
m_messageSender = std::make_shared<StrictMock<MockMessageSender>>();
m_context.addState(buildTestTag(), buildTestState());
}
void AlexaInterfaceMessageSenderTest::TearDown() {
m_messageSender.reset();
m_mockContextManager.reset();
}
AVSMessageEndpoint AlexaInterfaceMessageSenderTest::buildTestEndpoint(void) {
return AVSMessageEndpoint(ENDPOINT_ID_TEST);
}
CapabilityTag AlexaInterfaceMessageSenderTest::buildTestTag(void) {
return CapabilityTag(NAMESPACE_POWER_CONTROLLER, POWER_STATE, ENDPOINT_ID_TEST);
}
CapabilityState AlexaInterfaceMessageSenderTest::buildTestState(void) {
TimePoint timePoint;
timePoint.setTime_ISO_8601(TIME_OF_SAMPLE_TEST);
return CapabilityState(POWER_STATE_ON, timePoint, 0);
}
bool AlexaInterfaceMessageSenderTest::removeMessageId(Document* document, std::string* messageId) {
if (!document || !messageId) {
return false;
}
auto it = document->FindMember(EVENT.c_str());
if (it == document->MemberEnd()) return false;
it = it->value.FindMember(HEADER.c_str());
if (it == document->MemberEnd()) return false;
auto& eventHeader = it->value;
it = it->value.FindMember(MESSAGE_ID.c_str());
if (it == document->MemberEnd()) return false;
*messageId = it->value.GetString();
eventHeader.RemoveMember(it);
return true;
}
bool AlexaInterfaceMessageSenderTest::removeEventCorrelationToken(
Document* document,
std::string* eventCorrelationToken) {
if (!document || !eventCorrelationToken) {
return false;
}
auto it = document->FindMember(EVENT.c_str());
if (it == document->MemberEnd()) return false;
it = it->value.FindMember(HEADER.c_str());
if (it == document->MemberEnd()) return false;
auto& eventHeader = it->value;
it = it->value.FindMember(EVENT_CORRELATION_TOKEN.c_str());
if (it == document->MemberEnd()) return false;
*eventCorrelationToken = it->value.GetString();
eventHeader.RemoveMember(it);
return true;
}
std::shared_ptr<AlexaInterfaceMessageSender> AlexaInterfaceMessageSenderTest::createMessageSender(void) {
EXPECT_CALL(*m_mockContextManager, addContextManagerObserver(_)).Times(1);
auto sender = AlexaInterfaceMessageSender::create(m_mockContextManager, m_messageSender);
EXPECT_THAT(sender, NotNull());
return sender;
}
bool AlexaInterfaceMessageSenderTest::expectEventSent(
const std::shared_ptr<AlexaInterfaceMessageSender>& sender,
const std::string& jsonEventString,
MessageRequestObserverInterface::Status sendStatus,
std::function<void()> triggerOperation) {
std::promise<bool> eventPromise;
std::promise<bool> contextPromise;
// Expect getContext() and reply with onContextAvailable()
EXPECT_CALL(*m_mockContextManager, getContext(_, _, _)).WillOnce(InvokeWithoutArgs([this, sender, &contextPromise] {
const ContextRequestToken token = 1;
sender->onContextAvailable(ENDPOINT_ID_TEST, m_context, token);
contextPromise.set_value(true);
return token;
}));
// Expect sendMessage() and reply with sendCompleted()
EXPECT_CALL(*m_messageSender, sendMessage(_))
.Times(1)
.WillOnce(Invoke([this, sendStatus, &jsonEventString, &eventPromise](std::shared_ptr<MessageRequest> request) {
if (checkEventJson(request->getJsonContent(), jsonEventString)) {
request->sendCompleted(sendStatus);
eventPromise.set_value(true);
} else {
// Unexpected event
eventPromise.set_value(false);
}
}));
triggerOperation();
EXPECT_TRUE(contextPromise.get_future().wait_for(MY_WAIT_TIMEOUT) == std::future_status::ready);
auto sendFuture = eventPromise.get_future();
bool isSendFutureReady = false;
isSendFutureReady = sendFuture.wait_for(MY_WAIT_TIMEOUT) == std::future_status::ready;
// Workaround GTEST issue where expectations can hold a reference to a shared_ptr even after we wait for the future.
EXPECT_TRUE(Mock::VerifyAndClearExpectations(m_messageSender.get()));
EXPECT_TRUE(Mock::VerifyAndClearExpectations(m_mockContextManager.get()));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
if (!isSendFutureReady) {
return false;
}
return sendFuture.get();
}
bool AlexaInterfaceMessageSenderTest::expectEventSentOnInvalidContext(
const std::shared_ptr<AlexaInterfaceMessageSender>& sender,
const std::string& jsonEventString,
MessageRequestObserverInterface::Status sendStatus,
std::function<void()> triggerOperation) {
std::promise<bool> eventPromise;
std::promise<bool> contextPromise;
// Expect getContext() and reply with onContextFailure()
EXPECT_CALL(*m_mockContextManager, getContext(_, _, _)).WillOnce(InvokeWithoutArgs([sender, &contextPromise] {
const ContextRequestToken token = 1;
sender->onContextFailure(ContextRequestError::STATE_PROVIDER_TIMEDOUT, token);
contextPromise.set_value(false);
return token;
}));
// Expect sendMessage() and reply with sendCompleted()
EXPECT_CALL(*m_messageSender, sendMessage(_))
.Times(1)
.WillOnce(Invoke([this, sendStatus, &jsonEventString, &eventPromise](std::shared_ptr<MessageRequest> request) {
if (checkEventJson(request->getJsonContent(), jsonEventString)) {
request->sendCompleted(sendStatus);
eventPromise.set_value(true);
} else {
// Unexpected event
eventPromise.set_value(false);
}
}));
triggerOperation();
EXPECT_TRUE(contextPromise.get_future().wait_for(MY_WAIT_TIMEOUT) == std::future_status::ready);
auto sendFuture = eventPromise.get_future();
bool isSendFutureReady = false;
isSendFutureReady = sendFuture.wait_for(MY_WAIT_TIMEOUT) == std::future_status::ready;
// Workaround GTEST issue where expectations can hold a reference to a shared_ptr even after we wait for the future.
EXPECT_TRUE(Mock::VerifyAndClearExpectations(m_messageSender.get()));
EXPECT_TRUE(Mock::VerifyAndClearExpectations(m_mockContextManager.get()));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
if (!isSendFutureReady) {
return false;
}
return sendFuture.get();
}
bool AlexaInterfaceMessageSenderTest::expectEventSentWithoutContext(
const std::shared_ptr<AlexaInterfaceMessageSender>& sender,
const std::string& jsonEventString,
MessageRequestObserverInterface::Status sendStatus,
std::function<void()> triggerOperation) {
std::promise<bool> eventPromise;
std::promise<bool> contextPromise;
// Expect sendMessage() and reply with sendCompleted()
EXPECT_CALL(*m_messageSender, sendMessage(_))
.Times(1)
.WillOnce(Invoke([this, sendStatus, &jsonEventString, &eventPromise](std::shared_ptr<MessageRequest> request) {
if (checkEventJson(request->getJsonContent(), jsonEventString)) {
request->sendCompleted(sendStatus);
eventPromise.set_value(true);
} else {
// Unexpected event
eventPromise.set_value(false);
}
}));
triggerOperation();
auto sendFuture = eventPromise.get_future();
bool isSendFutureReady = false;
isSendFutureReady = sendFuture.wait_for(MY_WAIT_TIMEOUT) == std::future_status::ready;
// Workaround GTEST issue where expectations can hold a reference to a shared_ptr even after we wait for the future.
EXPECT_TRUE(Mock::VerifyAndClearExpectations(m_messageSender.get()));
EXPECT_TRUE(Mock::VerifyAndClearExpectations(m_mockContextManager.get()));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
if (!isSendFutureReady) {
return false;
}
return sendFuture.get();
}
bool AlexaInterfaceMessageSenderTest::expectEventNotSentOnInvalidContext(
const std::shared_ptr<AlexaInterfaceMessageSender>& sender,
const std::string& jsonEventString,
MessageRequestObserverInterface::Status sendStatus,
std::function<void()> triggerOperation) {
std::promise<bool> eventPromise;
std::promise<bool> contextPromise;
// Expect getContext() and reply with onContextFailure()
EXPECT_CALL(*m_mockContextManager, getContext(_, _, _)).WillOnce(InvokeWithoutArgs([sender, &contextPromise] {
const ContextRequestToken token = 1;
sender->onContextFailure(ContextRequestError::STATE_PROVIDER_TIMEDOUT, token);
contextPromise.set_value(false);
return token;
}));
triggerOperation();
EXPECT_TRUE(contextPromise.get_future().wait_for(MY_WAIT_TIMEOUT) == std::future_status::ready);
auto sendFuture = eventPromise.get_future();
bool isSendFutureReady = false;
isSendFutureReady = sendFuture.wait_for(MY_WAIT_TIMEOUT) == std::future_status::ready;
// Workaround GTEST issue where expectations can hold a reference to a shared_ptr even after we wait for the future.
EXPECT_TRUE(Mock::VerifyAndClearExpectations(m_messageSender.get()));
EXPECT_TRUE(Mock::VerifyAndClearExpectations(m_mockContextManager.get()));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
if (!isSendFutureReady) {
return false;
}
return sendFuture.get();
}
bool AlexaInterfaceMessageSenderTest::checkEventJson(std::string jsonEventString, std::string testEventString) {
Document expected, actual;
expected.Parse(testEventString);
actual.Parse(jsonEventString);
// messageId and eventCorrelationToken are randomly generated. Remove before comparing the Event strings.
std::string value;
EXPECT_TRUE(removeMessageId(&expected, &value));
EXPECT_TRUE(removeMessageId(&actual, &value));
EXPECT_TRUE(removeEventCorrelationToken(&expected, &value));
EXPECT_TRUE(removeEventCorrelationToken(&actual, &value));
EXPECT_EQ(expected, actual) << "Expected: " << testEventString << "\nValue: " << jsonEventString;
return true;
}
TEST_F(AlexaInterfaceMessageSenderTest, test_givenInvalidParameters_create_shouldFail) {
auto handler = AlexaInterfaceMessageSender::create(nullptr, m_messageSender);
EXPECT_THAT(handler, IsNull());
handler = AlexaInterfaceMessageSender::create(m_mockContextManager, nullptr);
EXPECT_THAT(handler, IsNull());
}
TEST_F(AlexaInterfaceMessageSenderTest, test_sendReportState_shouldSucceedAndSend) {
auto sender = createMessageSender();
bool result = false;
bool directiveResponseEventSent = expectEventSent(
sender,
STATE_REPORT_EVENT_JSON_STRING,
MessageRequestObserverInterface::Status::SUCCESS,
[this, sender, &result]() {
result = sender->sendStateReportEvent("", CORRELATION_TOKEN_TEST, buildTestEndpoint());
});
ASSERT_TRUE(result);
ASSERT_TRUE(directiveResponseEventSent);
}
TEST_F(AlexaInterfaceMessageSenderTest, test_sendReportState_missingContext_shouldSucceedAndSend) {
auto sender = createMessageSender();
bool result = false;
bool directiveResponseEventSent = expectEventSentOnInvalidContext(
sender,
STATE_REPORT_EVENT_NO_CONTEXT_JSON_STRING,
MessageRequestObserverInterface::Status::SUCCESS,
[this, sender, &result]() {
result = sender->sendStateReportEvent("", CORRELATION_TOKEN_TEST, buildTestEndpoint());
});
ASSERT_TRUE(result);
ASSERT_TRUE(directiveResponseEventSent);
}
TEST_F(AlexaInterfaceMessageSenderTest, test_sendResponse_shouldSend) {
auto sender = createMessageSender();
bool result = false;
bool directiveResponseEventSent = expectEventSent(
sender,
TURNON_RESPONSE_EVENT_WITH_CONTEXT_STRING,
MessageRequestObserverInterface::Status::SUCCESS,
[this, sender, &result]() {
result = sender->sendResponseEvent("", CORRELATION_TOKEN_TEST, buildTestEndpoint());
});
ASSERT_TRUE(result);
ASSERT_TRUE(directiveResponseEventSent);
}
TEST_F(AlexaInterfaceMessageSenderTest, test_sendResponse_noContext_shouldSend) {
auto sender = createMessageSender();
bool result = false;
bool directiveResponseEventSent = expectEventSentOnInvalidContext(
sender,
TURNON_RESPONSE_EVENT_WITHOUT_CONTEXT_STRING,
MessageRequestObserverInterface::Status::SUCCESS,
[this, sender, &result]() {
result = sender->sendResponseEvent("", CORRELATION_TOKEN_TEST, buildTestEndpoint());
});
ASSERT_TRUE(result);
ASSERT_TRUE(directiveResponseEventSent);
}
TEST_F(AlexaInterfaceMessageSenderTest, test_sendErrorResponse_shouldSend) {
auto sender = createMessageSender();
bool result = false;
bool directiveResponseEventSent = expectEventSentWithoutContext(
sender,
ERROR_RESPONSE_EVENT_STRING,
MessageRequestObserverInterface::Status::SUCCESS,
[this, sender, &result]() {
result = sender->sendErrorResponseEvent(
"",
CORRELATION_TOKEN_TEST,
buildTestEndpoint(),
AlexaInterfaceMessageSenderInterface::ErrorResponseType::ENDPOINT_UNREACHABLE,
ERROR_ENDPOINT_UNREACHABLE_MESSAGE);
});
ASSERT_TRUE(result);
ASSERT_TRUE(directiveResponseEventSent);
}
TEST_F(AlexaInterfaceMessageSenderTest, test_sendDeferredResponse_shouldSend) {
auto sender = createMessageSender();
bool result = false;
bool directiveResponseEventSent = expectEventSentWithoutContext(
sender, DEFERRED_RESPONSE_EVENT_STRING, MessageRequestObserverInterface::Status::SUCCESS, [sender, &result]() {
result = sender->sendDeferredResponseEvent("", CORRELATION_TOKEN_TEST, 7);
});
ASSERT_TRUE(result);
ASSERT_TRUE(directiveResponseEventSent);
}
TEST_F(AlexaInterfaceMessageSenderTest, test_sendResponse_withChange_shouldSend) {
auto sender = createMessageSender();
bool directiveResponseEventSent = expectEventSent(
sender,
TURNON_CHANGE_REPORT_WITH_CHANGE_EVENT_STRING,
MessageRequestObserverInterface::Status::SUCCESS,
[this, sender]() {
sender->onStateChanged(buildTestTag(), buildTestState(), AlexaStateChangeCauseType::ALEXA_INTERACTION);
});
ASSERT_TRUE(directiveResponseEventSent);
}
TEST_F(AlexaInterfaceMessageSenderTest, test_sendResponse_withChange_withoutContext_shouldNotSend) {
auto sender = createMessageSender();
bool directiveResponseEventSent = expectEventNotSentOnInvalidContext(
sender, "", MessageRequestObserverInterface::Status::SUCCESS, [this, sender]() {
sender->onStateChanged(buildTestTag(), buildTestState(), AlexaStateChangeCauseType::ALEXA_INTERACTION);
});
ASSERT_FALSE(directiveResponseEventSent);
}
} // namespace test
} // namespace alexa
} // namespace capabilityAgents
} // namespace alexaClientSDK