SmartAudio/package/avs/avs-sdk/files/avs-device-sdk/ADSL/test/common/MockDirectiveHandler.h

259 lines
9.4 KiB
C++

/*
* Copyright 2017-2018 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.
*/
#ifndef ALEXA_CLIENT_SDK_ADSL_TEST_COMMON_MOCKDIRECTIVEHANDLER_H_
#define ALEXA_CLIENT_SDK_ADSL_TEST_COMMON_MOCKDIRECTIVEHANDLER_H_
#include <chrono>
#include <future>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <AVSCommon/SDKInterfaces/DirectiveHandlerInterface.h>
#include <AVSCommon/AVS/NamespaceAndName.h>
namespace alexaClientSDK {
namespace adsl {
namespace test {
/**
* gmock does not fully support C++11's move only semantics. Replaces the use of unique_ptr in
* DirectiveHandlerInterface with shared_ptr so that methods using unique_ptr can be mocked.
*/
class DirectiveHandlerMockAdapter : public avsCommon::sdkInterfaces::DirectiveHandlerInterface {
public:
void preHandleDirective(
std::shared_ptr<avsCommon::avs::AVSDirective> directive,
std::unique_ptr<avsCommon::sdkInterfaces::DirectiveHandlerResultInterface> result) override;
/**
* Variant of preHandleDirective taking a shared_ptr instead of a unique_ptr.
*
* @param directive The @c AVSDirective to be (pre) handled.
* @param result The object to receive completion/failure notifications.
*/
virtual void preHandleDirective(
std::shared_ptr<avsCommon::avs::AVSDirective> directive,
std::shared_ptr<avsCommon::sdkInterfaces::DirectiveHandlerResultInterface> result) = 0;
};
/**
* MockDirectiveHandler. This mock sports the following functionality:
* - Spins up a thread when handleDirective() is invoked.
* - Triggers early termination of the handling thread when cancelDirective() is invoked.
* - Makes appropriate callbacks to DirectiveHandlerResultInterface instances passed bin by preHandle().
* - Provides functions to dynamically trigger completion and failure.
* - Provides methods to wait for the DirectiveHandlerInterface methods to be called.
*
* @note Each instance contains directive specific state, so it must only be be used to process a single directive.
*/
class MockDirectiveHandler : public DirectiveHandlerMockAdapter {
public:
/**
* Create a MockDirectiveHandler.
*
* @param config The @c avsCommon::avs::DirectiveHandlerConfiguration of the handler.
* @param handlingTimeMs The amount of time (in milliseconds) this handler takes to handle directives.
* @return A new MockDirectiveHandler.
*/
static std::shared_ptr<testing::NiceMock<MockDirectiveHandler>> create(
avsCommon::avs::DirectiveHandlerConfiguration config,
std::chrono::milliseconds handlingTimeMs = DEFAULT_HANDLING_TIME_MS);
/**
* Constructor.
*
* @param handlingTimeMs The amount of time (in milliseconds) this handler takes to handle directives.
*/
MockDirectiveHandler(
avsCommon::avs::DirectiveHandlerConfiguration config,
std::chrono::milliseconds handlingTimeMs);
/// Destructor.
~MockDirectiveHandler();
/**
* The functional part of mocking handleDirectiveImmediately().
*
* @param directive The directive to handle.
*/
void mockHandleDirectiveImmediately(std::shared_ptr<avsCommon::avs::AVSDirective> directive);
/**
* The functional part of mocking preHandleDirective().
*
* @param directive The directive to pre-handle.
* @param result The result object to
*/
void mockPreHandleDirective(
std::shared_ptr<avsCommon::avs::AVSDirective> directive,
std::shared_ptr<avsCommon::sdkInterfaces::DirectiveHandlerResultInterface> result);
/**
* The functional part of mocking handleDirective().
*
* @param messageId The MessageId of the @c AVSDirective to handle.
* @return Whether handling the directive has begun.
*/
bool mockHandleDirective(const std::string& messageId);
/**
* The functional part of mocking cancelDirective().
*
* @param directive The MessageId of the directive to cancel.
*/
void mockCancelDirective(const std::string& messageId);
/**
* The functional part of mocking onDeregistered().
*/
void mockOnDeregistered();
/**
* Method for m_doHandleDirectiveThread. Waits a specified time before reporting completion.
* If cancelDirective() is called in the mean time, wake up and exit.
*
* @param messageId The messageId to pass to the observer when reporting completion.
*/
void doHandleDirective(const std::string& messageId);
/**
* Fail preHandleDirective() by calling onDirectiveError().
*
* @param directive The directive to simulate the failure of.
* @param result An object to receive the result of the handling operation.
*/
void doPreHandlingFailed(
std::shared_ptr<avsCommon::avs::AVSDirective> directive,
std::shared_ptr<avsCommon::sdkInterfaces::DirectiveHandlerResultInterface> result);
/**
* Trigger completion of handling.
*/
void doHandlingCompleted();
/**
* Fail handleDirective() by calling onDirectiveError().
*
* @param messageId The MessageId of the directive to simulate the failure of.
*/
bool doHandlingFailed(const std::string& messageId);
void shutdown();
/**
* Block until preHandleDirective() is called.
*
* @param timeout The max amount of time to wait (in milliseconds).
* @return @c true if preHandleDirective() was called before the timeout.
*/
bool waitUntilPreHandling(std::chrono::milliseconds timeout = DEFAULT_DONE_TIMEOUT_MS);
/**
* Block until handleDirective() is called.
*
* @param timeout The max amount of time to wait (in milliseconds).
* @return @c true if handleDirective() was called before the timeout.
*/
bool waitUntilHandling(std::chrono::milliseconds timeout = DEFAULT_DONE_TIMEOUT_MS);
/**
* Block until cancelDirective() is called.
*
* @param timeout The max amount of time to wait (in milliseconds).
* @return @c true if cancelDirective() was called before the timeout.
*/
bool waitUntilCanceling(std::chrono::milliseconds timeout = DEFAULT_DONE_TIMEOUT_MS);
/**
* Block until completed() result is specified.
*
* @param timeout The max amount of time to wait (in milliseconds).
* @return @c true if setCompleted() was called before the timeout.
*/
bool waitUntilCompleted(std::chrono::milliseconds timeout = DEFAULT_DONE_TIMEOUT_MS);
/// The amount of time (in milliseconds) handling a directive will take.
std::chrono::milliseconds m_handlingTimeMs;
/// Object used to specify the result of handling a directive.
std::shared_ptr<avsCommon::sdkInterfaces::DirectiveHandlerResultInterface> m_result;
/// The @c AVSDirective (if any) being handled.
std::shared_ptr<avsCommon::avs::AVSDirective> m_directive;
/// Thread to perform handleDirective() asynchronously.
std::thread m_doHandleDirectiveThread;
/// Mutex to protect m_isShuttingDown.
std::mutex m_mutex;
/// condition_variable use to wake doHandlingDirectiveThread.
std::condition_variable m_wakeNotifier;
/// Whether or not handling completed.
bool m_isCompleted;
/// Whether or not this handler is shutting down.
bool m_isShuttingDown;
/// Promise fulfilled when preHandleDirective() begins.
std::promise<void> m_preHandlingPromise;
/// Future to notify when preHandleDirective() begins.
std::future<void> m_preHandlingFuture;
/// Promise fulfilled when handleDirective() begins.
std::promise<void> m_handlingPromise;
/// Future to notify when handleDirective() begins.
std::future<void> m_handlingFuture;
/// Promise fulfilled when cancelDirective() begins.
std::promise<void> m_cancelingPromise;
/// Future to notify when cancelDirective() begins.
std::shared_future<void> m_cancelingFuture;
/// Promise fulfilled when a completed result is reported.
std::promise<void> m_completedPromise;
/// Future to notify when a completed result is reported.
std::future<void> m_completedFuture;
MOCK_METHOD1(handleDirectiveImmediately, void(std::shared_ptr<avsCommon::avs::AVSDirective>));
MOCK_METHOD2(
preHandleDirective,
void(
std::shared_ptr<avsCommon::avs::AVSDirective>,
std::shared_ptr<avsCommon::sdkInterfaces::DirectiveHandlerResultInterface>));
MOCK_METHOD1(handleDirective, bool(const std::string&));
MOCK_METHOD1(cancelDirective, void(const std::string&));
MOCK_METHOD0(onDeregistered, void());
MOCK_CONST_METHOD0(getConfiguration, avsCommon::avs::DirectiveHandlerConfiguration());
/// Default amount of time taken to handle a directive (0).
static const std::chrono::milliseconds DEFAULT_HANDLING_TIME_MS;
/// Timeout used when waiting for tests to complete (we should not reach this).
static const std::chrono::milliseconds DEFAULT_DONE_TIMEOUT_MS;
};
} // namespace test
} // namespace adsl
} // namespace alexaClientSDK
#endif // ALEXA_CLIENT_SDK_ADSL_TEST_COMMON_MOCKDIRECTIVEHANDLER_H_