avs-device-sdk/AVSGatewayManager/test/PostConnectVerifyGatewaySen...

244 lines
9.0 KiB
C++

/*
* 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 <thread>
#include <gmock/gmock.h>
#include <AVSCommon/SDKInterfaces/MockPostConnectSendMessage.h>
#include <AVSCommon/Utils/JSON/JSONUtils.h>
#include <AVS/include/AVSCommon/AVS/MessageRequest.h>
#include <AVSGatewayManager/PostConnectVerifyGatewaySender.h>
namespace alexaClientSDK {
namespace avsGatewayManager {
namespace test {
using namespace ::testing;
using namespace avsCommon::avs;
using namespace avsCommon::sdkInterfaces;
using namespace avsCommon::sdkInterfaces::test;
using namespace avsCommon::utils::json::jsonUtils;
/// String indicating the VerifyGateway event's expected namespace.
static const std::string EXPECTED_NAMESPACE = "Alexa.ApiGateway";
/// String indicating the VerifyGateway event's expected name.
static const std::string EXPECTED_NAME = "VerifyGateway";
/// String indicating the VerifyGateway event's expected payload.
static const std::string EXPECTED_PAYLOAD = "{}";
/// Number of retries used in tests.
static const int TEST_RETRY_COUNT = 3;
/**
* Test harness for @c PostConnectVerifyGatewaySender class.
*/
class PostConnectVerifyGatewaySenderTest : public Test {
public:
/// Setup the test harness for running the test.
void SetUp() override;
/// Clean up the test harness after running the test.
void TearDown() override;
protected:
/// flag that will be set when the callback method is called.
bool m_callbackCheck;
/**
* Callback that will be called when the postConnectVerifyGatewaySender receives a successful response.
*
* @param postConnectVerifyGatewaySender The @c PostConnectVerifyGatewaySender instance.
*/
void updateStateCallback(std::shared_ptr<PostConnectVerifyGatewaySender> postConnectVerifyGatewaySender);
/// The instance of the @c PostConnectVerifyGatewaySender that will be used in the tests.
std::shared_ptr<PostConnectVerifyGatewaySender> m_postConnectVerifyGatewaySender;
/// The executor thread to run @c MockPostConnectSendMessage.
std::thread m_mockPostConnectSenderThread;
/// The mock @c PostConnectSendMessage used to test.
std::shared_ptr<MockPostConnectSendMessage> m_mockPostConnectSendMessage;
};
struct EventData {
std::string namespaceString;
std::string nameString;
std::string payloadString;
};
bool parseEventJson(const std::string& eventJson, EventData* eventData) {
std::string eventString;
if (!retrieveValue(eventJson, "event", &eventString)) {
return false;
}
std::string headerString;
if (!retrieveValue(eventString, "header", &headerString)) {
return false;
}
if (!retrieveValue(headerString, "namespace", &eventData->namespaceString)) {
return false;
}
if (!retrieveValue(headerString, "name", &eventData->nameString)) {
return false;
}
if (!retrieveValue(eventString, "payload", &eventData->payloadString)) {
return false;
}
return true;
}
bool validateEvent(const std::string& eventJson) {
EventData eventData;
if (!parseEventJson(eventJson, &eventData)) {
return false;
}
if (eventData.nameString != EXPECTED_NAME || eventData.namespaceString != EXPECTED_NAMESPACE ||
eventData.payloadString != EXPECTED_PAYLOAD) {
return false;
}
return true;
}
void PostConnectVerifyGatewaySenderTest::SetUp() {
m_callbackCheck = false;
m_mockPostConnectSendMessage = std::make_shared<NiceMock<MockPostConnectSendMessage>>();
auto callback = std::bind(&PostConnectVerifyGatewaySenderTest::updateStateCallback, this, std::placeholders::_1);
m_postConnectVerifyGatewaySender = PostConnectVerifyGatewaySender::create(callback);
}
void PostConnectVerifyGatewaySenderTest::TearDown() {
if (m_mockPostConnectSenderThread.joinable()) {
m_mockPostConnectSenderThread.join();
}
}
void PostConnectVerifyGatewaySenderTest::updateStateCallback(
std::shared_ptr<PostConnectVerifyGatewaySender> postConnectVerifyGatewaySender) {
if (postConnectVerifyGatewaySender == m_postConnectVerifyGatewaySender) {
m_callbackCheck = true;
}
}
/**
* Test if the create method fails
*/
TEST_F(PostConnectVerifyGatewaySenderTest, test_creaetWithEmptyCallbackMethod) {
std::function<void(const std::shared_ptr<PostConnectVerifyGatewaySender>&)> callback;
auto instance = PostConnectVerifyGatewaySender::create(callback);
}
/**
* Test happy path where performGateway returns true when VerifyGateway event is sent and 204 response is received.
*/
TEST_F(PostConnectVerifyGatewaySenderTest, test_performGatewayWhen204IsReceived) {
auto sendMessageLambda = [this](std::shared_ptr<MessageRequest> request) {
if (m_mockPostConnectSenderThread.joinable()) {
m_mockPostConnectSenderThread.join();
}
m_mockPostConnectSenderThread = std::thread([request]() {
EXPECT_TRUE(validateEvent(request->getJsonContent()));
request->sendCompleted(MessageRequestObserverInterface::Status::SUCCESS_NO_CONTENT);
});
};
EXPECT_CALL(*m_mockPostConnectSendMessage, sendPostConnectMessage(_)).WillOnce(Invoke(sendMessageLambda));
ASSERT_TRUE(m_postConnectVerifyGatewaySender->performOperation(m_mockPostConnectSendMessage));
ASSERT_TRUE(m_callbackCheck);
}
/**
* Test if performGateway returns false when VerifyGateway event is sent and 200 response is received.
*/
TEST_F(PostConnectVerifyGatewaySenderTest, test_performGatewayWhen200IsReceived) {
auto sendMessageLambda = [this](std::shared_ptr<MessageRequest> request) {
if (m_mockPostConnectSenderThread.joinable()) {
m_mockPostConnectSenderThread.join();
}
m_mockPostConnectSenderThread = std::thread([request]() {
EXPECT_TRUE(validateEvent(request->getJsonContent()));
request->sendCompleted(MessageRequestObserverInterface::Status::SUCCESS);
});
};
EXPECT_CALL(*m_mockPostConnectSendMessage, sendPostConnectMessage(_)).WillOnce(Invoke(sendMessageLambda));
ASSERT_TRUE(m_postConnectVerifyGatewaySender->performOperation(m_mockPostConnectSendMessage));
ASSERT_FALSE(m_callbackCheck);
}
/**
* Test if performGateway returns false when VerifyGateway event is sent and 400 response is received.
*/
TEST_F(PostConnectVerifyGatewaySenderTest, test_performGatewayWhen400IsReceived) {
auto sendMessageLambda = [this](std::shared_ptr<MessageRequest> request) {
if (m_mockPostConnectSenderThread.joinable()) {
m_mockPostConnectSenderThread.join();
}
m_mockPostConnectSenderThread = std::thread([request]() {
EXPECT_TRUE(validateEvent(request->getJsonContent()));
request->sendCompleted(MessageRequestObserverInterface::Status::BAD_REQUEST);
});
};
EXPECT_CALL(*m_mockPostConnectSendMessage, sendPostConnectMessage(_)).WillOnce(Invoke(sendMessageLambda));
ASSERT_FALSE(m_postConnectVerifyGatewaySender->performOperation(m_mockPostConnectSendMessage));
ASSERT_FALSE(m_callbackCheck);
}
/**
* Test if performGateway retries sending VerifyGateway event when a 5xx response is received.
*/
TEST_F(PostConnectVerifyGatewaySenderTest, test_performGatewayRetriesWhen503IsReceived) {
std::promise<int> retryCountPromise;
auto sendMessageLambda = [this, &retryCountPromise](std::shared_ptr<MessageRequest> request) {
if (m_mockPostConnectSenderThread.joinable()) {
m_mockPostConnectSenderThread.join();
}
m_mockPostConnectSenderThread = std::thread([this, request, &retryCountPromise]() {
EXPECT_TRUE(validateEvent(request->getJsonContent()));
request->sendCompleted(MessageRequestObserverInterface::Status::SERVER_INTERNAL_ERROR_V2);
static int count = 0;
count++;
if (TEST_RETRY_COUNT == count) {
retryCountPromise.set_value(count);
std::thread localThread([this]() { m_postConnectVerifyGatewaySender->abortOperation(); });
if (localThread.joinable()) {
localThread.join();
}
}
});
};
EXPECT_CALL(*m_mockPostConnectSendMessage, sendPostConnectMessage(_)).WillRepeatedly(Invoke(sendMessageLambda));
ASSERT_FALSE(m_postConnectVerifyGatewaySender->performOperation(m_mockPostConnectSendMessage));
EXPECT_EQ(retryCountPromise.get_future().get(), TEST_RETRY_COUNT);
ASSERT_FALSE(m_callbackCheck);
}
} // namespace test
} // namespace avsGatewayManager
} // namespace alexaClientSDK