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

443 lines
19 KiB
C++
Raw Normal View History

Version 1.17.0 alexa-client-sdk Changes in this update: **Enhancements** - Added support for [captions for TTS](https://developer.amazon.com/docs/avs-device-sdk/features.html#captions). This enhancement allows you to print onscreen captions for Alexa voice responses. - Added support for [SpeechSynthesizer Interface 1.3](https://developer.amazon.com/docs/alexa-voice-service/speechsynthesizer.html). This interface supports the new `captions` parameter. - Added support for [AudioPlayer Interface 1.3](https://developer.amazon.com/docs/alexa-voice-service/audioplayer.html). This interface supports the new `captions` parameter. - Added support for [Interaction Model 1.2](https://developer.amazon.com/docs/alexa-voice-service/interactionmodel-interface.html). - Added support for [System 2.0](https://developer.amazon.com/en-US/docs/alexa/alexa-voice-service/system.html). - Added support for Alarm Volume Ramp. This feature lets you to fade in alarms for a more pleasant experience. You enable alarm volume ramp in the sample app through the settings menu. - Added support for using certified senders for URI path extensions. This change allows you to specify the URI path extension when sending messages with [`CertifiedSender::sendJSONMessage`](https://alexa.github.io/avs-device-sdk/classalexa_client_s_d_k_1_1certified_sender_1_1_certified_sender.html#a4c0706d79717b226ba77d1a9c3280fe6). - Added new [`Metrics`](https://alexa.github.io/avs-device-sdk/classalexa_client_s_d_k_1_1avs_common_1_1utils_1_1_metrics.html) interfaces and helper classes. These additions help you create and consume [`Metrics`](https://alexa.github.io/avs-device-sdk/classalexa_client_s_d_k_1_1avs_common_1_1utils_1_1_metrics.html) events. - **Interfaces** - `MetricRecorderInterface`, `MetricSinkInterface`. - **Helper Classes** - `DataPointStringBuilder`, `DataPointCounterBuilder`, `DataPointDurationBuilder`, `MetricEventBuilder`. - Added support for the following AVS [endpoint](../avs-device-sdk/endpoints.html) controller capabilities: - [Alexa.ModeController](https://developer.amazon.com/docs/alexa-voice-service/alexa-modecontroller.html) - [Alexa.RangeController](https://developer.amazon.com/docs/alexa-voice-service/alexa-rangecontroller.html) - [Alexa.PowerController](https://developer.amazon.com/docs/alexa-voice-service/alexa-powercontroller.html) - [Alexa.ToggleController](https://developer.amazon.com/docs/alexa-voice-service/alexa-togglecontroller.html) - Added `PowerResourceManagerInterface`. This interface allows the SDK to control power resource levels for components such as the `AudioInputProcessor` and `SpeechSynthesizer`. - Added `AlexaInterfaceCapabilityAgent`. This Capability Agent handles common directives and endpoint controller capabilities support by [`Alexa.AlexaInterface`](../alexa-voice-service/alexa.html). - Added `AlexaInterfaceMessageSenderInterface`. This interface is required to send common events defined by the `Alexa.AlexaInterface` interface. - Added `BufferingComplete` to [`MediaPlayerObserverInterface`](https://alexa.github.io/avs-device-sdk/classalexa_client_s_d_k_1_1avs_common_1_1utils_1_1media_player_1_1_media_player_observer_interface.html). This method helps improve performance in poor networking conditions by making sure `MediaPlayer` pre-buffers correctly. - Added `SendDTMF` to `CallManagerInterface`. This method allows you to send DTMF tones during calls. **New build options** - CAPTIONS - **ADDED** [`CAPTIONS`](https://developer.amazon.com/docs/avs-device-sdk/cmake-parameters.html#captions) - **ADDED** [`LIBWEBVTT_LIB_PATH`](https://developer.amazon.com/docs/avs-device-sdk/cmake-parameters.html#captions) - **ADDED** [`LIBWEBVTT_INCLUDE_DIR`](https://developer.amazon.com/docs//avs-device-sdk/cmake-parameters.html#captions) - METRICS - **ADDED** [`METRICS`](https://developer.amazon.com/docs//avs-device-sdk/cmake-parameters.html#metrics) - ENDPONTS - **ADDED** [`ENABLE_ALL_ENDPOINT_CONTROLLERS`](https://developer.amazon.com/docs/avs-device-sdk/cmake-parameters.html#endpoints) - **ADDED** [`ENABLE_POWER_CONTROLLER`](https://developer.amazon.com/docs/avs-device-sdk/cmake-parameters.html#endpoints) - **ADDED** [`ENABLE_TOGGLE_CONTROLLER`](https://developer.amazon.com/docs/avs-device-sdk/cmake-parameters.html#endpoints) - **ADDED** [`ENABLE_RANGE_CONTROLLER`](https://developer.amazon.com/docs/avs-device-sdk/cmake-parameters.html#endpoints) - **ADDED** [`ENABLE_MODE_CONTROLLER`](https://developer.amazon.com/docs/avs-device-sdk/cmake-parameters.html#endpoints) **New dependencies** - To use captions, you must install a [new dependency](https://developer.amazon.com/docs/avs-device-sdk/dependencies) – the [libwebvtt parsing library](https://github.com/alexa/webvtt). Webvtt is a C/C++ library for interpreting and authoring conformant WebVTT content. WebVTT is a caption and subtitle format designed for use with HTML5 audio and video elements. **Bug fixes** - Fixed [`MimeResponseSink::onReceiveNonMimeData`](https://alexa.github.io/avs-device-sdk/classalexa_client_s_d_k_1_1acl_1_1_mime_response_sink.html) [data issue](https://github.com/alexa/avs-device-sdk/issues/1519) that returned invalid data. - Fixed [data type issue](https://github.com/alexa/avs-device-sdk/issues/1519) that incorrectly used `finalResponseCode` instead of [`FinalResponseCodeId`](https://github.com/alexa/avs-device-sdk/blob/master/AVSCommon/Utils/src/LibcurlUtils/LibCurlHttpContentFetcher.cpp#L370). - Fixed [`UrlContentToAttachmentConverter`](https://alexa.github.io/avs-device-sdk/classalexa_client_s_d_k_1_1playlist_parser_1_1_url_content_to_attachment_converter.html) issue that used the incorrect range parameter. - Fixed `FinallyGuard` [linking issue](https://github.com/alexa/avs-device-sdk/issues/1517) that caused problems compiling the SDK on iOS. - Fixed a [Bluetooth Capability Agent](https://alexa.github.io/avs-device-sdk/classalexa_client_s_d_k_1_1capability_agents_1_1bluetooth_1_1_bluetooth.html) bug that prevented devices from initializing. **Known Issues** * The WebVTT dependency required for `captions` isn't supported for Windows/Android. * Music playback history isn't displayed in the Alexa app for certain account and device types. * When using Gnu Compiler Collection 8+ (GCC 8+), `-Wclass-memaccess` triggers warnings. You can ignore these, they don't cause the build to fail. * Android error `libDefaultClient.so not found` might occur. Resolve this by upgrading to ADB version 1.0.40. * If a device loses a network connection, the lost connection status isn't returned via local TTS. * ACL encounters issues if it receives audio attachments but doesn't consume them. * `SpeechSynthesizerState` uses `GAINING_FOCUS` and `LOSING_FOCUS` as a workaround for handling intermediate states. * Media steamed through Bluetooth might abruptly stop. To restart playback, resume the media in the source application or toggle next/previous. * If a connected Bluetooth device is inactive, the Alexa app might indicates that audio is playing. * The Bluetooth agent assumes that the Bluetooth adapter is always connected to a power source. Disconnecting from a power source during operation isn't yet supported. * When using some products, interrupted Bluetooth playback might not resume if other content is locally streamed. * `make integration` isn't available for Android. To run Android integration tests, manually upload the test binary and input file and run ADB. * Alexa might truncate the beginning of speech when responding to text-to-speech (TTS) user events. This only impacts Raspberry Pi devices running Android Things with HDMI output audio. * A reminder TTS message doesn't play if the sample app restarts and loses a network connection. Instead, the default alarm tone plays twice. * `ServerDisconnectIntegratonTest` tests are disabled until they are updated to reflect new service behavior. * Bluetooth initialization must complete before connecting devices, otherwise devices are ignored. * The `DirectiveSequencerTest.test_handleBlockingThenImmediatelyThenNonBockingOnSameDialogId` test fails intermittently. * On some devices, Alexa gets stuck in a permanent listening state. Pressing `t` and `h` in the Sample App doesn't exit the listening state. * Exiting the settings menu doesn't provide a message to indicate that you're back in the main menu.
2019-12-10 21:02:09 +00:00
/*
* Copyright 2019 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 <future>
#include <memory>
#include <gmock/gmock.h>
#include <Alexa/AlexaInterfaceCapabilityAgent.h>
#include <Alexa/AlexaInterfaceMessageSenderInternalInterface.h>
#include <AVSCommon/AVS/AVSDirective.h>
#include <AVSCommon/AVS/NamespaceAndName.h>
#include <AVSCommon/SDKInterfaces/AlexaEventProcessedObserverInterface.h>
#include <AVSCommon/SDKInterfaces/MockAlexaInterfaceMessageSender.h>
#include <AVSCommon/SDKInterfaces/MockDirectiveHandlerResult.h>
#include <AVSCommon/SDKInterfaces/MockExceptionEncounteredSender.h>
#include <AVSCommon/Utils/Memory/Memory.h>
namespace alexaClientSDK {
namespace capabilityAgents {
namespace alexa {
namespace test {
using namespace avsCommon::avs;
using namespace avsCommon::sdkInterfaces::test;
using namespace avsCommon::utils::memory;
using namespace ::testing;
/// The namespace for this capability agent.
static const std::string NAMESPACE = "Alexa";
/// The Alexa.EventProcessed directive name.
static const std::string EVENT_PROCESSED_DIRECTIVE_NAME = "EventProcessed";
/// The Alexa.ReportState directive name.
static const std::string REPORT_STATE_DIRECTIVE_NAME = "ReportState";
/// The @c EventProcessed directive signature.
static const NamespaceAndName EVENT_PROCESSED{NAMESPACE, EVENT_PROCESSED_DIRECTIVE_NAME};
/// The @c ReportState directive signature.
static const NamespaceAndName REPORT_STATE{NAMESPACE, REPORT_STATE_DIRECTIVE_NAME};
/// The @c test messageId.
static const std::string TEST_ENDPOINT_ID = "test-endpoint";
/// The @c test messageId.
static const std::string TEST_MESSAGE_ID = "abcdefg";
/// The @c test EventCorrelationToken.
static const std::string TEST_EVENTCORRELATION_TOKEN = "abcdefg";
// clang-format off
/// A sample Directive JSON string for the purposes of creating an AVSDirective object.
static const std::string VALID_EVENT_PROCESSED_DIRECTIVE =
"{"
"\"directive\":{"
"\"header\":{"
"\"namespace\":\""+NAMESPACE+"\","
"\"name\":\""+EVENT_PROCESSED.name+"\","
"\"messageId\":\""+TEST_MESSAGE_ID+"\","
"\"eventCorrelationToken\":\""+TEST_EVENTCORRELATION_TOKEN+"\""
"},"
"\"payload\":{}"
"}"
"}";
/// A directive with an incorrect name.
static const std::string UNKNOWN_DIRECTIVE =
"{"
"\"directive\":{"
"\"header\":{"
"\"namespace\":\""+NAMESPACE+"\","
"\"name\":\"UnknownDirective\","
"\"messageId\":\""+TEST_MESSAGE_ID+"\","
"\"eventCorrelationToken\":\""+TEST_EVENTCORRELATION_TOKEN+"\""
"},"
"\"payload\":{}"
"}"
"}";
/// An invalid @c EventProcessed Directive with no eventCorrelationToken
static const std::string EVENT_PROCESSED_WITH_NO_EVENT_CORRELATION_TOKEN =
"{"
"\"directive\":{"
"\"header\":{"
"\"namespace\":\""+NAMESPACE+"\","
"\"name\":\""+EVENT_PROCESSED.name+"\","
"\"messageId\":\""+TEST_MESSAGE_ID+"\""
"},"
"\"payload\":{}"
"}"
"}";
/// A sample Directive JSON string for the purposes of creating an AVSDirective object.
static const std::string VALID_ALEXA_REPORTSTATE_DIRECTIVE =
"{"
"\"directive\":{"
"\"header\":{"
"\"namespace\":\""+NAMESPACE+"\","
"\"name\":\""+REPORT_STATE.name+"\","
"\"messageId\":\""+TEST_MESSAGE_ID+"\","
"\"correlationToken\":\""+TEST_EVENTCORRELATION_TOKEN+"\""
"},"
"\"endpoint\":{"
"\"endpointId\":\""+TEST_ENDPOINT_ID+"\""
"},"
"\"payload\":{}"
"}"
"}";
/// A sample Directive JSON string for the purposes of creating an AVSDirective object.
static const std::string INVALID_ALEXA_REPORTSTATE_DIRECTIVE_NO_ENDPOINT =
"{"
"\"directive\":{"
"\"header\":{"
"\"namespace\":\""+NAMESPACE+"\","
"\"name\":\""+REPORT_STATE.name+"\","
"\"messageId\":\""+TEST_MESSAGE_ID+"\","
"\"correlationToken\":\""+TEST_EVENTCORRELATION_TOKEN+"\""
"},"
"\"payload\":{}"
"}"
"}";
// clang-format on
/// Timeout when waiting for future to be set.
static std::chrono::milliseconds TIMEOUT(1000);
/// A test @c EventProcessedObserver.
class TestEventProcessedObserver : public avsCommon::sdkInterfaces::AlexaEventProcessedObserverInterface {
public:
bool waitForEventProcessed(const std::string& eventConrrelationToken) {
std::unique_lock<std::mutex> lock{m_mutex};
auto predicate = [this, eventConrrelationToken] { return m_eventCorrelationToken == eventConrrelationToken; };
return m_wakeTrigger.wait_for(lock, TIMEOUT, predicate);
}
void onAlexaEventProcessedReceived(const std::string& eventCorrelationToken) {
std::lock_guard<std::mutex> lock{m_mutex};
m_eventCorrelationToken = eventCorrelationToken;
m_wakeTrigger.notify_one();
}
private:
std::mutex m_mutex;
std::condition_variable m_wakeTrigger;
std::string m_eventCorrelationToken;
};
/// A mock @c MockAlexaInterfaceMessageSenderInternal
class MockAlexaInterfaceMessageSenderInternal : public AlexaInterfaceMessageSenderInternalInterface {
public:
MOCK_METHOD3(
sendStateReportEvent,
bool(
const std::string& instance,
const std::string& correlationToken,
const avsCommon::avs::AVSMessageEndpoint& endpoint));
MOCK_METHOD4(
sendResponseEvent,
bool(
const std::string& instance,
const std::string& correlationToken,
const avsCommon::avs::AVSMessageEndpoint& endpoint,
const std::string& jsonPayload));
MOCK_METHOD5(
sendErrorResponseEvent,
bool(
const std::string& instance,
const std::string& correlationToken,
const avsCommon::avs::AVSMessageEndpoint& endpoint,
const ErrorResponseType errorType,
const std::string& errorMessage));
MOCK_METHOD3(
sendDeferredResponseEvent,
bool(const std::string& instance, const std::string& correlationToken, const int estimatedDeferralInSeconds));
MOCK_METHOD1(
alexaResponseTypeToErrorType,
ErrorResponseType(const avsCommon::avs::AlexaResponseType& responseType));
};
/**
* Test harness for @c EventProcessedHandler class.
*/
class AlexaInterfaceCapabilityAgentTest : public Test {
public:
/// Setup the test harness for running a test.
void SetUp() override;
/// Clean up the test harness for running a test.
void TearDown() override;
/// Function to set the promise and wake @ m_wakeSetCompleteFuture.
void wakeOnSetCompleted();
/**
* Constructor.
*/
AlexaInterfaceCapabilityAgentTest() :
m_wakeSetCompletedPromise{},
m_wakeSetCompletedFuture{m_wakeSetCompletedPromise.get_future()} {
}
protected:
/// Promise to synchronize directive handling through setCompleted.
std::promise<void> m_wakeSetCompletedPromise;
/// Future to synchronize directive handling through setCompleted.
std::future<void> m_wakeSetCompletedFuture;
/// A strict mock that allows the test to strictly monitor the handling of directives.
std::unique_ptr<StrictMock<MockDirectiveHandlerResult>> m_mockDirectiveHandlerResult;
/// Device info object to pass to the CA.
std::shared_ptr<avsCommon::utils::DeviceInfo> m_deviceInfo;
/// A strict mock that allows the test to strictly monitor the exceptions being sent.
std::shared_ptr<StrictMock<MockExceptionEncounteredSender>> m_mockExceptionSender;
/// A mock that allows the test to monitor calls to @c MockAlexaInterfaceMessageSenderInternal.
std::shared_ptr<MockAlexaInterfaceMessageSenderInternal> m_mockAlexaMessageSender;
/// A pointer to an instance of @c AlexaInterfaceCapabilityAgent that will be instantiated per test.
std::shared_ptr<AlexaInterfaceCapabilityAgent> m_alexaInterfaceCapabilityAgent;
};
void AlexaInterfaceCapabilityAgentTest::SetUp() {
m_deviceInfo = avsCommon::utils::DeviceInfo::create(
"testClientId", "testProductId", "testSerialNumber", "testManufacturer", "testDescription");
m_mockExceptionSender = std::make_shared<StrictMock<MockExceptionEncounteredSender>>();
m_mockDirectiveHandlerResult = make_unique<StrictMock<MockDirectiveHandlerResult>>();
m_mockAlexaMessageSender = std::make_shared<MockAlexaInterfaceMessageSenderInternal>();
m_alexaInterfaceCapabilityAgent = AlexaInterfaceCapabilityAgent::create(
*m_deviceInfo, TEST_ENDPOINT_ID, m_mockExceptionSender, m_mockAlexaMessageSender);
ASSERT_NE(m_alexaInterfaceCapabilityAgent, nullptr);
}
void AlexaInterfaceCapabilityAgentTest::TearDown() {
}
void AlexaInterfaceCapabilityAgentTest::wakeOnSetCompleted() {
m_wakeSetCompletedPromise.set_value();
}
/**
* Tests if create method returns null with null @c ExceptionSender and null @c ReportStateHandler.
*/
TEST_F(AlexaInterfaceCapabilityAgentTest, createWithInvalidParameters) {
auto alexaInterfaceCA =
AlexaInterfaceCapabilityAgent::create(*m_deviceInfo, TEST_ENDPOINT_ID, nullptr, m_mockAlexaMessageSender);
ASSERT_EQ(alexaInterfaceCA, nullptr);
alexaInterfaceCA =
AlexaInterfaceCapabilityAgent::create(*m_deviceInfo, TEST_ENDPOINT_ID, m_mockExceptionSender, nullptr);
ASSERT_EQ(alexaInterfaceCA, nullptr);
}
/**
* Tests if Alexa.EventProcessed and Alexa.ReportState are present on the default endpoint config.
*/
TEST_F(AlexaInterfaceCapabilityAgentTest, testDefaultEndpoint) {
auto endpointId = m_deviceInfo->getDefaultEndpointId();
auto alexaInterfaceCA = AlexaInterfaceCapabilityAgent::create(
*m_deviceInfo, endpointId, m_mockExceptionSender, m_mockAlexaMessageSender);
ASSERT_NE(alexaInterfaceCA, nullptr);
auto configuration = alexaInterfaceCA->getConfiguration();
EXPECT_NE(configuration.find(EVENT_PROCESSED), configuration.end());
EXPECT_NE(configuration.find({NAMESPACE, REPORT_STATE_DIRECTIVE_NAME, endpointId}), configuration.end());
}
/**
* Tests if Alexa.ReportState is present and Alexa.EventProcessed is NOT present on a non-default endpoint config.
*/
TEST_F(AlexaInterfaceCapabilityAgentTest, testNonDefaultEndpoint) {
auto endpointId = TEST_ENDPOINT_ID;
auto alexaInterfaceCA = AlexaInterfaceCapabilityAgent::create(
*m_deviceInfo, endpointId, m_mockExceptionSender, m_mockAlexaMessageSender);
ASSERT_NE(alexaInterfaceCA, nullptr);
auto configuration = alexaInterfaceCA->getConfiguration();
EXPECT_EQ(configuration.find(EVENT_PROCESSED), configuration.end());
EXPECT_NE(configuration.find({NAMESPACE, REPORT_STATE_DIRECTIVE_NAME, endpointId}), configuration.end());
}
/**
* Tests if sendExceptionEncountered and setFailed are called for invalid directives.
*/
TEST_F(AlexaInterfaceCapabilityAgentTest, testValidUnknownDirective) {
auto directivePair = AVSDirective::create(UNKNOWN_DIRECTIVE, nullptr, "");
std::shared_ptr<AVSDirective> directive = std::move(directivePair.first);
ASSERT_THAT(directive, NotNull());
EXPECT_CALL(*m_mockExceptionSender, sendExceptionEncountered(_, Eq(ExceptionErrorType::UNSUPPORTED_OPERATION), _));
EXPECT_CALL(*m_mockDirectiveHandlerResult, setFailed(_))
.WillOnce(InvokeWithoutArgs(this, &AlexaInterfaceCapabilityAgentTest::wakeOnSetCompleted));
EXPECT_CALL(*m_mockAlexaMessageSender, sendStateReportEvent(_, _, _)).Times(Exactly(0));
m_alexaInterfaceCapabilityAgent->CapabilityAgent::preHandleDirective(
directive, std::move(m_mockDirectiveHandlerResult));
m_alexaInterfaceCapabilityAgent->CapabilityAgent::handleDirective(directive->getMessageId());
EXPECT_EQ(m_wakeSetCompletedFuture.wait_for(TIMEOUT), std::future_status::ready);
}
/**
* Tests if sendExceptionEncountered and setFailed are called when eventCorrelationToken is not in the EventProcessed
* directive.
*/
TEST_F(AlexaInterfaceCapabilityAgentTest, testInvalidEventProcessedDirective) {
auto directivePair = AVSDirective::create(EVENT_PROCESSED_WITH_NO_EVENT_CORRELATION_TOKEN, nullptr, "");
std::shared_ptr<AVSDirective> directive = std::move(directivePair.first);
ASSERT_THAT(directive, NotNull());
EXPECT_CALL(
*m_mockExceptionSender,
sendExceptionEncountered(_, Eq(ExceptionErrorType::UNEXPECTED_INFORMATION_RECEIVED), _));
EXPECT_CALL(*m_mockDirectiveHandlerResult, setFailed(_))
.WillOnce(InvokeWithoutArgs(this, &AlexaInterfaceCapabilityAgentTest::wakeOnSetCompleted));
EXPECT_CALL(*m_mockAlexaMessageSender, sendStateReportEvent(_, _, _)).Times(Exactly(0));
m_alexaInterfaceCapabilityAgent->CapabilityAgent::preHandleDirective(
directive, std::move(m_mockDirectiveHandlerResult));
m_alexaInterfaceCapabilityAgent->CapabilityAgent::handleDirective(directive->getMessageId());
EXPECT_EQ(m_wakeSetCompletedFuture.wait_for(TIMEOUT), std::future_status::ready);
}
/**
* Tests if setHandlingCompleted is called and if the observers are notified when a valid EventProcessed directive is
* received.
*/
TEST_F(AlexaInterfaceCapabilityAgentTest, testValidEventProcessedDirective) {
auto directivePair = AVSDirective::create(VALID_EVENT_PROCESSED_DIRECTIVE, nullptr, "");
std::shared_ptr<AVSDirective> directive = std::move(directivePair.first);
ASSERT_THAT(directive, NotNull());
EXPECT_CALL(*m_mockExceptionSender, sendExceptionEncountered(_, _, _)).Times(Exactly(0));
EXPECT_CALL(*m_mockDirectiveHandlerResult, setCompleted())
.WillOnce(InvokeWithoutArgs(this, &AlexaInterfaceCapabilityAgentTest::wakeOnSetCompleted));
EXPECT_CALL(*m_mockAlexaMessageSender, sendStateReportEvent(_, _, _)).Times(Exactly(0));
auto testObserver = std::make_shared<TestEventProcessedObserver>();
m_alexaInterfaceCapabilityAgent->addEventProcessedObserver(testObserver);
m_alexaInterfaceCapabilityAgent->CapabilityAgent::preHandleDirective(
directive, std::move(m_mockDirectiveHandlerResult));
m_alexaInterfaceCapabilityAgent->CapabilityAgent::handleDirective(directive->getMessageId());
EXPECT_EQ(m_wakeSetCompletedFuture.wait_for(TIMEOUT), std::future_status::ready);
ASSERT_TRUE(testObserver->waitForEventProcessed(TEST_EVENTCORRELATION_TOKEN));
}
/**
* Tests if @c sendStateReportEvent() and setHandlingCompleted are called for a valid ReportState directive.
*/
TEST_F(AlexaInterfaceCapabilityAgentTest, testValidReportStateDirective) {
auto directivePair = AVSDirective::create(VALID_ALEXA_REPORTSTATE_DIRECTIVE, nullptr, "");
std::shared_ptr<AVSDirective> directive = std::move(directivePair.first);
ASSERT_THAT(directive, NotNull());
EXPECT_CALL(*m_mockExceptionSender, sendExceptionEncountered(_, _, _)).Times(Exactly(0));
EXPECT_CALL(*m_mockAlexaMessageSender, sendErrorResponseEvent(_, _, _, _, _)).Times(Exactly(0));
EXPECT_CALL(*m_mockDirectiveHandlerResult, setCompleted())
.WillOnce(InvokeWithoutArgs(this, &AlexaInterfaceCapabilityAgentTest::wakeOnSetCompleted));
EXPECT_CALL(*m_mockAlexaMessageSender, sendStateReportEvent(_, _, _))
.Times(Exactly(1))
.WillOnce(Invoke([](const std::string& instance,
const std::string& correlationToken,
const avsCommon::avs::AVSMessageEndpoint& endpoint) {
EXPECT_EQ(correlationToken, TEST_EVENTCORRELATION_TOKEN);
EXPECT_EQ(endpoint.endpointId, TEST_ENDPOINT_ID);
return true;
}));
auto testObserver = std::make_shared<TestEventProcessedObserver>();
m_alexaInterfaceCapabilityAgent->addEventProcessedObserver(testObserver);
m_alexaInterfaceCapabilityAgent->CapabilityAgent::preHandleDirective(
directive, std::move(m_mockDirectiveHandlerResult));
m_alexaInterfaceCapabilityAgent->CapabilityAgent::handleDirective(directive->getMessageId());
EXPECT_EQ(m_wakeSetCompletedFuture.wait_for(TIMEOUT), std::future_status::ready);
}
/**
* Tests if @c sendErrorResponse() and setHandlingCompleted are called for ReportState failure.
*/
TEST_F(AlexaInterfaceCapabilityAgentTest, testValidReportStateDirectiveReportStateFailure) {
auto directivePair = AVSDirective::create(VALID_ALEXA_REPORTSTATE_DIRECTIVE, nullptr, "");
std::shared_ptr<AVSDirective> directive = std::move(directivePair.first);
ASSERT_THAT(directive, NotNull());
EXPECT_CALL(
*m_mockAlexaMessageSender,
sendErrorResponseEvent(
_, _, _, Eq(AlexaInterfaceMessageSenderInternalInterface::ErrorResponseType::INTERNAL_ERROR), _));
EXPECT_CALL(*m_mockDirectiveHandlerResult, setCompleted())
.WillOnce(InvokeWithoutArgs(this, &AlexaInterfaceCapabilityAgentTest::wakeOnSetCompleted));
EXPECT_CALL(*m_mockAlexaMessageSender, sendStateReportEvent(_, _, _)).WillOnce(Return(false));
m_alexaInterfaceCapabilityAgent->CapabilityAgent::preHandleDirective(
directive, std::move(m_mockDirectiveHandlerResult));
m_alexaInterfaceCapabilityAgent->CapabilityAgent::handleDirective(directive->getMessageId());
EXPECT_EQ(m_wakeSetCompletedFuture.wait_for(TIMEOUT), std::future_status::ready);
}
/**
* Tests if @c sendErrorResponse() and setHandlingCompleted is called for a ReportState directive without an endpoint.
*/
TEST_F(AlexaInterfaceCapabilityAgentTest, testInvalidReportStateDirectiveNoEndpoint) {
auto directivePair = AVSDirective::create(INVALID_ALEXA_REPORTSTATE_DIRECTIVE_NO_ENDPOINT, nullptr, "");
std::shared_ptr<AVSDirective> directive = std::move(directivePair.first);
ASSERT_THAT(directive, NotNull());
EXPECT_CALL(
*m_mockAlexaMessageSender,
sendErrorResponseEvent(
_, _, _, Eq(AlexaInterfaceMessageSenderInternalInterface::ErrorResponseType::INVALID_DIRECTIVE), _));
EXPECT_CALL(*m_mockDirectiveHandlerResult, setCompleted())
.WillOnce(InvokeWithoutArgs(this, &AlexaInterfaceCapabilityAgentTest::wakeOnSetCompleted));
m_alexaInterfaceCapabilityAgent->CapabilityAgent::preHandleDirective(
directive, std::move(m_mockDirectiveHandlerResult));
m_alexaInterfaceCapabilityAgent->CapabilityAgent::handleDirective(directive->getMessageId());
EXPECT_EQ(m_wakeSetCompletedFuture.wait_for(TIMEOUT), std::future_status::ready);
}
} // namespace test
} // namespace alexa
} // namespace capabilityAgents
} // namespace alexaClientSDK