SmartAudio/package/avs/avs-sdk/files/avs-device-sdk/Integration/test/NetworkIntegrationTests.cpp

251 lines
8.1 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.
*/
/// @file NetworkIntegrationTests.cpp
#include <chrono>
#include <fstream>
#include <stdlib.h>
#include <unistd.h>
#include <gtest/gtest.h>
#include <ACL/AVSConnectionManager.h>
#include <AVSCommon/AVS/MessageRequest.h>
#include <AVSCommon/Utils/Logger/Logger.h>
#include <ContextManager/ContextManager.h>
#include "Integration/ACLTestContext.h"
#include "Integration/ConnectionStatusObserver.h"
#include "Integration/JsonHeader.h"
#include "Integration/ObservableMessageRequest.h"
namespace alexaClientSDK {
namespace integration {
namespace test {
using namespace ::testing;
using namespace acl;
using namespace avsCommon::avs;
using namespace avsCommon::avs::attachment;
using namespace avsCommon::utils::sds;
using namespace avsCommon::sdkInterfaces;
static const std::string TAG("NetworkIntegrationTests");
#define LX(event) alexaClientSDK::avsCommon::utils::logger::LogEntry(TAG, event)
/// Amount of Delay in milliseconds to be added.
static const std::string DELAY_TIME = "1000ms";
/// Amount of Delay for causing a TIMEDOUT status in MessageRequest.
static const std::string LONG_DELAY_TIME = "40000ms";
/// The time to wait for expected message status on sending the message.
static const int TIMEOUT_FOR_SEND_IN_SECONDS = 10;
/// The time to wait for expected message status when delay is longer.
static const int LONG_TIMEOUT_FOR_SEND_IN_SECONDS = 40;
/// Path to the AlexaClientSDKConfig.json file.
std::string g_configPath;
/// The network interface specified for the delay to be added.
std::string network_interface;
/**
* Test class to stress test the ACL Library for slow network connection.
*/
class NetworkIntegrationTests : public ::testing::Test {
public:
void SetUp() override;
void TearDown() override;
/**
* This function enables the @c m_avsConnectionManager to establish a connection to AVS.
*/
void connect();
/**
* This function disables the @c m_avsConnectionManager to tear down the connection.
*/
void disconnect();
/**
* The function to send one message to AVS.
* @param jsonContent The content in json format to send in the message.
* @param expectedStatus The expected status of the message being sent to AVS.
* @param timeout The maximum time to wait for the @c expectedStatus.
* @param attachmentReader The attachment reader for the MessageRequest.
*/
void sendEvent(
const std::string& jsonContent,
MessageRequestObserverInterface::Status expectedStatus,
std::chrono::seconds timeout,
std::shared_ptr<avsCommon::avs::attachment::AttachmentReader> attachmentReader = nullptr);
/**
* The function adds delay to the network.
* @param DelayTime The delay in milliseconds to be introduced in the network.
*/
void addDelay(const std::string& delayTime);
/**
* Remove the delay in the network.
*/
void deleteDelay();
protected:
/// Context for running ACL based tests.
std::unique_ptr<ACLTestContext> m_context;
/// ConnectionStatus Observer for checking the status changes in connection.
std::shared_ptr<ConnectionStatusObserver> m_connectionStatusObserver;
/// Connection Manager for handling the communication between client and AVS.
std::shared_ptr<AVSConnectionManager> m_avsConnectionManager;
/// ContextManager object.
std::shared_ptr<contextManager::ContextManager> m_contextManager;
};
void NetworkIntegrationTests::SetUp() {
m_context = ACLTestContext::create(g_configPath);
ASSERT_TRUE(m_context);
m_avsConnectionManager = AVSConnectionManager::create(
m_context->getMessageRouter(),
false,
{m_context->getConnectionStatusObserver()},
std::unordered_set<std::shared_ptr<MessageObserverInterface>>());
ASSERT_TRUE(m_avsConnectionManager);
}
void NetworkIntegrationTests::TearDown() {
deleteDelay();
}
void NetworkIntegrationTests::connect() {
m_avsConnectionManager->enable();
m_context->waitForConnected();
}
void NetworkIntegrationTests::disconnect() {
if (m_avsConnectionManager) {
m_avsConnectionManager->disable();
m_context->waitForDisconnected();
}
}
void NetworkIntegrationTests::sendEvent(
const std::string& jsonContent,
MessageRequestObserverInterface::Status expectedStatus,
std::chrono::seconds timeout,
std::shared_ptr<avsCommon::avs::attachment::AttachmentReader> attachmentReader) {
auto messageRequest = std::make_shared<ObservableMessageRequest>(jsonContent, attachmentReader);
m_avsConnectionManager->sendMessage(messageRequest);
ASSERT_TRUE(messageRequest->waitFor(expectedStatus, timeout));
ASSERT_TRUE(messageRequest->hasSendCompleted() || messageRequest->wasExceptionReceived());
}
void NetworkIntegrationTests::addDelay(const std::string& delayTime) {
std::string str = "tc qdisc add dev " + network_interface + " root netem delay " + delayTime;
int ret = system(str.c_str());
ASSERT_TRUE(WIFEXITED(ret)) << "System call didn't terminate normally";
ASSERT_EQ(0, WEXITSTATUS(ret)) << "Child process in system call exited abnormally";
}
void NetworkIntegrationTests::deleteDelay() {
std::string str = "tc qdisc delete dev " + network_interface + " root";
int ret = system(str.c_str());
ASSERT_TRUE(WIFEXITED(ret)) << "System call didn't terminate normally";
ASSERT_EQ(0, WEXITSTATUS(ret)) << "Child process in system call exited abnormally";
}
/**
* Test if connection and disconnection can be established after delay is introduced.
*/
TEST_F(NetworkIntegrationTests, testConnectAfterSlowConnection) {
addDelay(DELAY_TIME);
connect();
disconnect();
}
/**
* Establish Connection, and introduce delay and check if @c connectionStatus remains CONNECTED.
*/
TEST_F(NetworkIntegrationTests, testConnectBeforeSlowConnection) {
connect();
addDelay(DELAY_TIME);
disconnect();
}
/**
* Establish connection, introduce delay and test if connect can be done again.
*/
TEST_F(NetworkIntegrationTests, testReConnectAfterDelay) {
connect();
addDelay(DELAY_TIME);
disconnect();
connect();
disconnect();
}
/**
* Establish connection, introduce a delay, send a message, check if the Status of MessageRequest
* is SUCCESS.
*/
TEST_F(NetworkIntegrationTests, testSendEventAfterDelayPass) {
connect();
addDelay(DELAY_TIME);
sendEvent(
SYNCHRONIZE_STATE_JSON,
MessageRequestObserverInterface::Status::SUCCESS,
std::chrono::seconds(TIMEOUT_FOR_SEND_IN_SECONDS));
disconnect();
}
/**
* Establish connection, introduce a longer delay time of greater than 30 seconds, send a message,
* the Status of MessageRequest will be TIMEDOUT.
*/
TEST_F(NetworkIntegrationTests, testSendEventAfterDelayFails) {
connect();
addDelay(LONG_DELAY_TIME);
sendEvent(
SYNCHRONIZE_STATE_JSON,
MessageRequestObserverInterface::Status::TIMEDOUT,
std::chrono::seconds(LONG_TIMEOUT_FOR_SEND_IN_SECONDS));
disconnect();
}
} // namespace test
} // namespace integration
} // namespace alexaClientSDK
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
if (getuid()) {
std::cerr << "You need to be root to run this test" << std::endl;
return 1;
}
if (argc < 3) {
std::cerr << "USAGE: " << std::string(argv[0]) << "<path_to_AlexaClientSDKConfig.json> <Network_Interface_Name>"
<< std::endl;
return 1;
} else {
alexaClientSDK::integration::test::g_configPath = std::string(argv[1]);
alexaClientSDK::integration::test::network_interface = std::string(argv[2]);
return RUN_ALL_TESTS();
}
}