avs-device-sdk/CapabilityAgents/ToggleController/test/ToggleControllerCapabilityA...

652 lines
26 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 <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 "ToggleController/ToggleControllerAttributeBuilder.h"
#include "ToggleController/ToggleControllerCapabilityAgent.h"
#include <AVSCommon/AVS/Attachment/MockAttachmentManager.h>
#include <AVSCommon/SDKInterfaces/MockContextManager.h>
#include <AVSCommon/SDKInterfaces/MockDirectiveHandlerResult.h>
#include <AVSCommon/SDKInterfaces/MockExceptionEncounteredSender.h>
#include <AVSCommon/SDKInterfaces/MockAlexaInterfaceMessageSender.h>
#include <AVSCommon/SDKInterfaces/ToggleController/ToggleControllerAttributes.h>
#include <AVSCommon/SDKInterfaces/ToggleController/ToggleControllerInterface.h>
#include <AVSCommon/Utils/Memory/Memory.h>
#include <AVSCommon/Utils/Timing/TimePoint.h>
#include <AVSCommon/Utils/WaitEvent.h>
namespace alexaClientSDK {
namespace capabilityAgents {
namespace toggleController {
namespace test {
using namespace avsCommon::avs;
using namespace avsCommon::avs::attachment::test;
using namespace avsCommon::sdkInterfaces;
using namespace avsCommon::sdkInterfaces::toggleController;
using namespace avsCommon::sdkInterfaces::test;
using namespace avsCommon::utils::memory;
using namespace rapidjson;
using namespace ::testing;
// For readability.
using EndpointIdentifier = endpoints::EndpointIdentifier;
/// Timeout when waiting for futures to be set.
static std::chrono::milliseconds TIMEOUT(1000);
/// The namespace for capability agent.
static const std::string NAMESPACE{"Alexa.ToggleController"};
/// The supported version
static const std::string INTERFACE_VERSION{"3"};
/// The name for TurnOn directive
static const std::string NAME_TURNON{"TurnOn"};
/// The name for TurnOff directive
static const std::string NAME_TURNOFF{"TurnOff"};
/// The name for toggleState property
static const std::string TOGGLESTATE_PROPERTY_NAME{"toggleState"};
/// An unknown directive signature.
static const std::string UNKNOWN_DIRECTIVE{"Unknown"};
/// The test EndpointId
static const EndpointIdentifier TEST_ENDPOINT_ID("testEndpointId");
/// The test instance
static const EndpointIdentifier TEST_INSTANCE("testInstance");
/// Event key.
static const std::string EVENT("event");
/// Header key.
static const std::string HEADER("header");
/// MessageId key.
static const std::string MESSAGE_ID("messageId");
/// MessageId for testing.
static const std::string MESSAGE_ID_TEST("MessageId_Test");
/// Dialog request Id key.
static const std::string DIALOG_REQUEST_ID("dialogRequestId");
/// DialogRequestId for testing.
static const std::string DIALOG_REQUEST_ID_TEST("DialogRequestId_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 for testing.
static const std::string EVENT_CORRELATION_TOKEN_TEST("EventCorrelationToken_Test");
/// Time of sample key
static const std::string TIME_OF_SAMPLE("timeOfSample");
/// Time of sample used for testing
static const std::string TIME_OF_SAMPLE_TEST("2017-02-03T16:20:50.523Z");
class MockToggleControllerInterface : public ToggleControllerInterface {
public:
using SetToggleStateResult = std::pair<AlexaResponseType, std::string>;
using GetToggleStateResult = std::pair<AlexaResponseType, avsCommon::utils::Optional<ToggleState>>;
MOCK_METHOD2(setToggleState, SetToggleStateResult(const bool state, const AlexaStateChangeCauseType cause));
MOCK_METHOD0(getToggleState, GetToggleStateResult());
MOCK_METHOD1(addObserver, bool(std::shared_ptr<ToggleControllerObserverInterface>));
MOCK_METHOD1(removeObserver, void(const std::shared_ptr<ToggleControllerObserverInterface>&));
};
class ToggleControllerCapabilityAgentTest : public ::testing::Test {
public:
/// SetUp before each test case.
void SetUp() override;
/// Constructor.
ToggleControllerCapabilityAgentTest() {
}
/// build toggleControllerAttributes
avsCommon::utils::Optional<avsCommon::sdkInterfaces::toggleController::ToggleControllerAttributes>
buildToggleControllerAttribute(const avsCommon::avs::CapabilityResources& capabilityResources) {
auto toggleControllerAttributeBuilder =
capabilityAgents::toggleController::ToggleControllerAttributeBuilder::create();
toggleControllerAttributeBuilder->withCapabilityResources(capabilityResources);
return toggleControllerAttributeBuilder->build();
}
protected:
/**
* Function to create ToggleControllerCapabilityAgent based on the reportable flags
* and sets required ContextManager and ToggleController mocks.
*/
std::shared_ptr<ToggleControllerCapabilityAgent> createCapabilityAgentAndSetExpects(
const avsCommon::sdkInterfaces::toggleController::ToggleControllerAttributes& toggleControllerAttributes,
bool proactivelyReported,
bool retrievable,
bool nonControllable);
/// The test @c ToggleState as ON
ToggleControllerInterface::ToggleState TEST_POWER_STATE_ON;
/// The test @c ToggleState as OFF
ToggleControllerInterface::ToggleState TEST_POWER_STATE_OFF;
/// A mock @c ToggleContollerInterface object.
std::shared_ptr<StrictMock<MockToggleControllerInterface>> m_mockToggleController;
/// A mock @c ToggleContollerObserverInterface object.
std::shared_ptr<ToggleControllerObserverInterface> m_observer;
// a context manager
std::shared_ptr<StrictMock<MockContextManager>> m_mockContextManager;
/// Response sender mock to track events being sent.
std::shared_ptr<MockAlexaInterfaceMessageSender> m_mockResponseSender;
// A strict mock that allows the test to strictly monitor the exceptions being sent.
std::shared_ptr<StrictMock<MockExceptionEncounteredSender>> m_mockExceptionSender;
/// A strict mock that allows the test to strictly monitor the handling of directives.
std::unique_ptr<StrictMock<MockDirectiveHandlerResult>> m_mockDirectiveHandlerResult;
};
void ToggleControllerCapabilityAgentTest::SetUp() {
m_mockExceptionSender = std::make_shared<StrictMock<MockExceptionEncounteredSender>>();
m_mockDirectiveHandlerResult = make_unique<StrictMock<MockDirectiveHandlerResult>>();
m_mockToggleController = std::make_shared<StrictMock<MockToggleControllerInterface>>();
m_mockContextManager = std::make_shared<testing::StrictMock<MockContextManager>>();
m_mockResponseSender = std::make_shared<MockAlexaInterfaceMessageSender>();
auto timePoint = avsCommon::utils::timing::TimePoint();
timePoint.setTime_ISO_8601(TIME_OF_SAMPLE_TEST);
TEST_POWER_STATE_ON = ToggleControllerInterface::ToggleState{true, timePoint, std::chrono::milliseconds(0)};
TEST_POWER_STATE_OFF = ToggleControllerInterface::ToggleState{false, timePoint, std::chrono::milliseconds(0)};
}
std::shared_ptr<ToggleControllerCapabilityAgent> ToggleControllerCapabilityAgentTest::
createCapabilityAgentAndSetExpects(
const avsCommon::sdkInterfaces::toggleController::ToggleControllerAttributes& toggleControllerAttributes,
bool proactivelyReported,
bool retrievable,
bool nonControllable) {
// ContextManager Mocks
if (retrievable) {
// Expects a non-null CA reference during create.
EXPECT_CALL(*m_mockContextManager, addStateProvider(_, ::testing::NotNull()));
// Expects a null when CA is shutdown.
EXPECT_CALL(*m_mockContextManager, removeStateProvider(_));
}
if (proactivelyReported) {
// addObserver Called during the initialization.
EXPECT_CALL(*m_mockToggleController, addObserver(_))
.WillOnce(WithArg<0>(Invoke([this](std::shared_ptr<ToggleControllerObserverInterface> observer) {
m_observer = observer;
return true;
})));
// removeObserver is called during the shutdown
EXPECT_CALL(*m_mockToggleController, removeObserver(_))
.WillOnce(WithArg<0>(
Invoke([this](std::shared_ptr<ToggleControllerObserverInterface> observer) { m_observer = nullptr; })));
}
auto toggleControllerCapabilityAgent = ToggleControllerCapabilityAgent::create(
TEST_ENDPOINT_ID,
TEST_INSTANCE,
toggleControllerAttributes,
m_mockToggleController,
m_mockContextManager,
m_mockResponseSender,
m_mockExceptionSender,
proactivelyReported,
retrievable,
nonControllable);
return toggleControllerCapabilityAgent;
}
/**
* Utility function to build the @c AVSDirective for test.
*
* @param directiveName The name of the test directive to build.
*
* @return The created AVSDirective object or @c nullptr if build failed.
*/
static std::shared_ptr<AVSDirective> buildAVSDirective(std::string directiveName) {
// Create Directive.
auto attachmentManager = std::make_shared<StrictMock<MockAttachmentManager>>();
auto avsMessageHeader = std::make_shared<AVSMessageHeader>(
NAMESPACE,
directiveName,
MESSAGE_ID_TEST,
DIALOG_REQUEST_ID_TEST,
CORRELATION_TOKEN_TEST,
EVENT_CORRELATION_TOKEN_TEST,
INTERFACE_VERSION,
TEST_INSTANCE);
auto avsMessageEndpoint = AVSMessageEndpoint(TEST_ENDPOINT_ID);
return AVSDirective::create("", avsMessageHeader, "", attachmentManager, "", avsMessageEndpoint);
}
/// Test that create() returns a nullptr if called with invalid arguments.
TEST_F(ToggleControllerCapabilityAgentTest, test_givenInvalidParameters_create_shouldFail) {
CapabilityResources emptyResource;
auto emptyToggleControllerAttribute = buildToggleControllerAttribute(emptyResource);
CapabilityResources resource;
ASSERT_TRUE(resource.addFriendlyNameWithText("light", "en-US"));
auto toggleControllerAttributes = buildToggleControllerAttribute(resource);
ASSERT_TRUE(toggleControllerAttributes.hasValue());
EXPECT_THAT(
ToggleControllerCapabilityAgent::create(
"", "", emptyToggleControllerAttribute.value(), nullptr, nullptr, nullptr, nullptr, true, true),
IsNull());
EXPECT_THAT(
ToggleControllerCapabilityAgent::create(
"",
TEST_INSTANCE,
toggleControllerAttributes.value(),
m_mockToggleController,
m_mockContextManager,
m_mockResponseSender,
m_mockExceptionSender,
true,
true),
IsNull());
EXPECT_THAT(
ToggleControllerCapabilityAgent::create(
TEST_ENDPOINT_ID,
"",
toggleControllerAttributes.value(),
m_mockToggleController,
m_mockContextManager,
m_mockResponseSender,
m_mockExceptionSender,
true,
true),
IsNull());
EXPECT_THAT(
ToggleControllerCapabilityAgent::create(
TEST_ENDPOINT_ID,
TEST_INSTANCE,
emptyToggleControllerAttribute.value(),
m_mockToggleController,
m_mockContextManager,
m_mockResponseSender,
m_mockExceptionSender,
true,
true),
IsNull());
EXPECT_THAT(
ToggleControllerCapabilityAgent::create(
TEST_ENDPOINT_ID,
TEST_INSTANCE,
toggleControllerAttributes.value(),
nullptr,
m_mockContextManager,
m_mockResponseSender,
m_mockExceptionSender,
true,
true),
IsNull());
EXPECT_THAT(
ToggleControllerCapabilityAgent::create(
TEST_ENDPOINT_ID,
TEST_INSTANCE,
toggleControllerAttributes.value(),
m_mockToggleController,
nullptr,
m_mockResponseSender,
m_mockExceptionSender,
true,
true),
IsNull());
EXPECT_THAT(
ToggleControllerCapabilityAgent::create(
TEST_ENDPOINT_ID,
TEST_INSTANCE,
toggleControllerAttributes.value(),
m_mockToggleController,
m_mockContextManager,
nullptr,
m_mockExceptionSender,
true,
true),
IsNull());
EXPECT_THAT(
ToggleControllerCapabilityAgent::create(
TEST_ENDPOINT_ID,
TEST_INSTANCE,
toggleControllerAttributes.value(),
m_mockToggleController,
m_mockContextManager,
m_mockResponseSender,
nullptr,
true,
true),
IsNull());
}
/**
* Test successful handling of TurnOn directive.
*/
TEST_F(ToggleControllerCapabilityAgentTest, test_turnOnDirective_successCase) {
avsCommon::utils::WaitEvent waitEvent;
CapabilityResources resource;
ASSERT_TRUE(resource.addFriendlyNameWithText("light", "en-US"));
auto toggleControllerAttributes = buildToggleControllerAttribute(resource);
ASSERT_TRUE(toggleControllerAttributes.hasValue());
EXPECT_CALL(*m_mockDirectiveHandlerResult, setCompleted()).WillOnce(InvokeWithoutArgs([&waitEvent]() {
waitEvent.wakeUp();
}));
EXPECT_CALL(*m_mockToggleController, setToggleState(true, _))
.WillOnce(WithArg<1>(
Invoke([](AlexaStateChangeCauseType cause) { return std::make_pair(AlexaResponseType::SUCCESS, ""); })));
EXPECT_CALL(*m_mockResponseSender, sendResponseEvent(_, _, _, _));
auto toggleControllerCapabilityAgent =
createCapabilityAgentAndSetExpects(toggleControllerAttributes.value(), false, true, false);
ASSERT_THAT(toggleControllerCapabilityAgent, NotNull());
// Simulate directive
toggleControllerCapabilityAgent->CapabilityAgent::preHandleDirective(
buildAVSDirective(NAME_TURNON), std::move(m_mockDirectiveHandlerResult));
toggleControllerCapabilityAgent->CapabilityAgent::handleDirective(MESSAGE_ID_TEST);
EXPECT_TRUE(waitEvent.wait(TIMEOUT));
toggleControllerCapabilityAgent->shutdown();
}
/**
* Test error path of TurnOn directive.
*/
TEST_F(ToggleControllerCapabilityAgentTest, test_turnOnDirective_errorCase) {
avsCommon::utils::WaitEvent waitEvent;
CapabilityResources resource;
ASSERT_TRUE(resource.addFriendlyNameWithText("light", "en-US"));
auto toggleControllerAttributes = buildToggleControllerAttribute(resource);
ASSERT_TRUE(toggleControllerAttributes.hasValue());
EXPECT_CALL(*m_mockDirectiveHandlerResult, setCompleted()).WillOnce(InvokeWithoutArgs([&waitEvent]() {
waitEvent.wakeUp();
}));
EXPECT_CALL(*m_mockToggleController, setToggleState(true, _))
.WillOnce(WithArg<1>(Invoke([](AlexaStateChangeCauseType cause) {
return std::make_pair(AlexaResponseType::ENDPOINT_UNREACHABLE, "TestEndpointNotReachable");
})));
EXPECT_CALL(*m_mockResponseSender, sendErrorResponseEvent(_, _, _, _, _));
auto toggleControllerCapabilityAgent =
createCapabilityAgentAndSetExpects(toggleControllerAttributes.value(), true, true, false);
ASSERT_THAT(toggleControllerCapabilityAgent, NotNull());
// Simulate directive
toggleControllerCapabilityAgent->CapabilityAgent::preHandleDirective(
buildAVSDirective(NAME_TURNON), std::move(m_mockDirectiveHandlerResult));
toggleControllerCapabilityAgent->CapabilityAgent::handleDirective(MESSAGE_ID_TEST);
EXPECT_TRUE(waitEvent.wait(TIMEOUT));
toggleControllerCapabilityAgent->shutdown();
}
/**
* Test successful handling of TurnOff directive.
*/
TEST_F(ToggleControllerCapabilityAgentTest, test_turnOffDirective_successCase) {
avsCommon::utils::WaitEvent waitEvent;
CapabilityResources resource;
ASSERT_TRUE(resource.addFriendlyNameWithText("light", "en-US"));
auto toggleControllerAttributes = buildToggleControllerAttribute(resource);
ASSERT_TRUE(toggleControllerAttributes.hasValue());
EXPECT_CALL(*m_mockDirectiveHandlerResult, setCompleted()).WillOnce(InvokeWithoutArgs([&waitEvent]() {
waitEvent.wakeUp();
}));
EXPECT_CALL(*m_mockToggleController, setToggleState(false, _))
.WillOnce(WithArg<1>(
Invoke([](AlexaStateChangeCauseType cause) { return std::make_pair(AlexaResponseType::SUCCESS, ""); })));
EXPECT_CALL(*m_mockResponseSender, sendResponseEvent(_, _, _, _));
auto toggleControllerCapabilityAgent =
createCapabilityAgentAndSetExpects(toggleControllerAttributes.value(), false, true, false);
ASSERT_THAT(toggleControllerCapabilityAgent, NotNull());
// Simulate directive
toggleControllerCapabilityAgent->CapabilityAgent::preHandleDirective(
buildAVSDirective(NAME_TURNOFF), std::move(m_mockDirectiveHandlerResult));
toggleControllerCapabilityAgent->CapabilityAgent::handleDirective(MESSAGE_ID_TEST);
EXPECT_TRUE(waitEvent.wait(TIMEOUT));
toggleControllerCapabilityAgent->shutdown();
}
/**
* Test error path of TurnOff directive.
*/
TEST_F(ToggleControllerCapabilityAgentTest, test_turnOffDirective_errorCase) {
avsCommon::utils::WaitEvent waitEvent;
CapabilityResources resource;
ASSERT_TRUE(resource.addFriendlyNameWithText("light", "en-US"));
auto toggleControllerAttributes = buildToggleControllerAttribute(resource);
ASSERT_TRUE(toggleControllerAttributes.hasValue());
EXPECT_CALL(*m_mockDirectiveHandlerResult, setCompleted()).WillOnce(InvokeWithoutArgs([&waitEvent]() {
waitEvent.wakeUp();
}));
EXPECT_CALL(*m_mockToggleController, setToggleState(false, _))
.WillOnce(WithArg<1>(Invoke([](AlexaStateChangeCauseType cause) {
return std::make_pair(AlexaResponseType::ENDPOINT_UNREACHABLE, "TestEndpointNotReachable");
})));
EXPECT_CALL(*m_mockResponseSender, sendErrorResponseEvent(_, _, _, _, _));
auto toggleControllerCapabilityAgent =
createCapabilityAgentAndSetExpects(toggleControllerAttributes.value(), true, true, false);
ASSERT_THAT(toggleControllerCapabilityAgent, NotNull());
// Simulate directive
toggleControllerCapabilityAgent->CapabilityAgent::preHandleDirective(
buildAVSDirective(NAME_TURNOFF), std::move(m_mockDirectiveHandlerResult));
toggleControllerCapabilityAgent->CapabilityAgent::handleDirective(MESSAGE_ID_TEST);
EXPECT_TRUE(waitEvent.wait(TIMEOUT));
toggleControllerCapabilityAgent->shutdown();
}
/**
* Test triggering of reportStateChange and subsequent call to the
* ContextManager to build the context.
*/
TEST_F(ToggleControllerCapabilityAgentTest, test_reportStateChange_successCase) {
avsCommon::utils::WaitEvent waitEvent;
CapabilityResources resource;
ASSERT_TRUE(resource.addFriendlyNameWithText("light", "en-US"));
auto toggleControllerAttributes = buildToggleControllerAttribute(resource);
ASSERT_TRUE(toggleControllerAttributes.hasValue());
auto toggleControllerCapabilityAgent =
createCapabilityAgentAndSetExpects(toggleControllerAttributes.value(), true, true, false);
ASSERT_THAT(toggleControllerCapabilityAgent, NotNull());
EXPECT_CALL(*m_mockToggleController, setToggleState(true, _))
.WillOnce(WithArg<1>(Invoke([this](AlexaStateChangeCauseType cause) {
m_observer->onToggleStateChanged(TEST_POWER_STATE_ON, cause);
return std::make_pair(AlexaResponseType::SUCCESS, "");
})));
EXPECT_CALL(*m_mockContextManager, reportStateChange(_, _, _))
.WillOnce(InvokeWithoutArgs([toggleControllerCapabilityAgent] {
const unsigned int stateRequestToken = 1;
toggleControllerCapabilityAgent->provideState(
CapabilityTag(NAMESPACE, TOGGLESTATE_PROPERTY_NAME, TEST_ENDPOINT_ID, TEST_INSTANCE),
stateRequestToken);
}));
EXPECT_CALL(*m_mockToggleController, getToggleState())
.WillOnce(InvokeWithoutArgs([this]() -> MockToggleControllerInterface::GetToggleStateResult {
return std::make_pair(
AlexaResponseType::SUCCESS,
avsCommon::utils::Optional<ToggleControllerInterface::ToggleState>(TEST_POWER_STATE_ON));
}));
EXPECT_CALL(*m_mockContextManager, provideStateResponse(_, _, _)).WillOnce(InvokeWithoutArgs([&waitEvent]() {
waitEvent.wakeUp();
}));
m_mockToggleController->setToggleState(true, AlexaStateChangeCauseType::APP_INTERACTION);
EXPECT_TRUE(waitEvent.wait(TIMEOUT));
toggleControllerCapabilityAgent->shutdown();
}
/**
* Test triggering of reportStateChange and subsequent failure to get the getToggleState and
* call to the ContextManager to report the failure.
*/
TEST_F(ToggleControllerCapabilityAgentTest, test_reportStateChange_errorCase) {
avsCommon::utils::WaitEvent waitEvent;
CapabilityResources resource;
ASSERT_TRUE(resource.addFriendlyNameWithText("light", "en-US"));
auto toggleControllerAttributes = buildToggleControllerAttribute(resource);
ASSERT_TRUE(toggleControllerAttributes.hasValue());
auto toggleControllerCapabilityAgent =
createCapabilityAgentAndSetExpects(toggleControllerAttributes.value(), true, true, false);
ASSERT_THAT(toggleControllerCapabilityAgent, NotNull());
EXPECT_CALL(*m_mockToggleController, setToggleState(true, _))
.WillOnce(WithArg<1>(Invoke([this](AlexaStateChangeCauseType cause) {
m_observer->onToggleStateChanged(TEST_POWER_STATE_ON, cause);
return std::make_pair(AlexaResponseType::SUCCESS, "");
})));
EXPECT_CALL(*m_mockContextManager, reportStateChange(_, _, _))
.WillOnce(InvokeWithoutArgs([toggleControllerCapabilityAgent] {
const unsigned int stateRequestToken = 1;
toggleControllerCapabilityAgent->provideState(
CapabilityTag(NAMESPACE, TOGGLESTATE_PROPERTY_NAME, TEST_ENDPOINT_ID, TEST_INSTANCE),
stateRequestToken);
}));
EXPECT_CALL(*m_mockToggleController, getToggleState())
.WillOnce(InvokeWithoutArgs([]() -> MockToggleControllerInterface::GetToggleStateResult {
return std::make_pair(
AlexaResponseType::ENDPOINT_UNREACHABLE,
avsCommon::utils::Optional<ToggleControllerInterface::ToggleState>());
}));
EXPECT_CALL(*m_mockContextManager, provideStateUnavailableResponse(_, _, _))
.WillOnce(InvokeWithoutArgs([&waitEvent]() { waitEvent.wakeUp(); }));
m_mockToggleController->setToggleState(true, AlexaStateChangeCauseType::APP_INTERACTION);
EXPECT_TRUE(waitEvent.wait(TIMEOUT));
toggleControllerCapabilityAgent->shutdown();
}
/**
* Tests unknown Directive with both proactively reported and retrievable set.
* Expect that the sendExceptionEncountered and setFailed will be called.
*/
TEST_F(ToggleControllerCapabilityAgentTest, test_unknownDirectiveWithProactivelyReportedAndRetrievableTrue) {
avsCommon::utils::WaitEvent waitEvent;
EXPECT_CALL(*m_mockExceptionSender, sendExceptionEncountered(_, _, _));
EXPECT_CALL(*m_mockDirectiveHandlerResult, setFailed(_)).WillOnce(InvokeWithoutArgs([&waitEvent]() {
waitEvent.wakeUp();
}));
CapabilityResources resource;
ASSERT_TRUE(resource.addFriendlyNameWithText("light", "en-US"));
auto toggleControllerAttributes = buildToggleControllerAttribute(resource);
ASSERT_TRUE(toggleControllerAttributes.hasValue());
auto toggleControllerCapabilityAgent =
createCapabilityAgentAndSetExpects(toggleControllerAttributes.value(), true, true, false);
ASSERT_THAT(toggleControllerCapabilityAgent, NotNull());
toggleControllerCapabilityAgent->CapabilityAgent::preHandleDirective(
buildAVSDirective(UNKNOWN_DIRECTIVE), std::move(m_mockDirectiveHandlerResult));
toggleControllerCapabilityAgent->CapabilityAgent::handleDirective(MESSAGE_ID_TEST);
EXPECT_TRUE(waitEvent.wait(TIMEOUT));
toggleControllerCapabilityAgent->shutdown();
}
/**
* Tests unknown Directive with both proactively reported and retrievable as false.
* Expect that the sendExceptionEncountered and setFailed will be called.
*/
TEST_F(ToggleControllerCapabilityAgentTest, test_unknownDirectiveWithProactivelyReportedAndRetrievableFalse) {
avsCommon::utils::WaitEvent waitEvent;
EXPECT_CALL(*m_mockExceptionSender, sendExceptionEncountered(_, _, _));
EXPECT_CALL(*m_mockDirectiveHandlerResult, setFailed(_)).WillOnce(InvokeWithoutArgs([&waitEvent]() {
waitEvent.wakeUp();
}));
CapabilityResources resource;
ASSERT_TRUE(resource.addFriendlyNameWithText("light", "en-US"));
auto toggleControllerAttributes = buildToggleControllerAttribute(resource);
ASSERT_TRUE(toggleControllerAttributes.hasValue());
auto toggleControllerCapabilityAgent =
createCapabilityAgentAndSetExpects(toggleControllerAttributes.value(), false, false, false);
toggleControllerCapabilityAgent->CapabilityAgent::preHandleDirective(
buildAVSDirective(UNKNOWN_DIRECTIVE), std::move(m_mockDirectiveHandlerResult));
toggleControllerCapabilityAgent->CapabilityAgent::handleDirective(MESSAGE_ID_TEST);
EXPECT_TRUE(waitEvent.wait(TIMEOUT));
toggleControllerCapabilityAgent->shutdown();
}
} // namespace test
} // namespace toggleController
} // namespace capabilityAgents
} // namespace alexaClientSDK