2017-02-10 23:39:10 +00:00
|
|
|
/*
|
|
|
|
* AlexaCommunicationsLibraryTest.cpp
|
|
|
|
*
|
|
|
|
* Copyright 2016-2017 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.
|
|
|
|
*/
|
|
|
|
|
2017-03-10 00:01:46 +00:00
|
|
|
/// @file AlexaCommunicationsLibraryTest.cpp
|
|
|
|
|
2017-05-05 17:31:58 +00:00
|
|
|
#include <future>
|
|
|
|
#include <fstream>
|
|
|
|
#include <chrono>
|
|
|
|
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
|
|
|
#include <ACL/AVSConnectionManager.h>
|
|
|
|
#include <ACL/Transport/HTTP2MessageRouter.h>
|
|
|
|
#include <AuthDelegate/AuthDelegate.h>
|
2017-05-26 23:06:14 +00:00
|
|
|
#include <AVSCommon/AVS/Attachment/AttachmentManager.h>
|
|
|
|
#include <AVSCommon/AVS/Attachment/InProcessAttachment.h>
|
|
|
|
#include <AVSCommon/Utils/SDS/InProcessSDS.h>
|
2017-05-05 17:31:58 +00:00
|
|
|
#include <AVSUtils/Initialization/AlexaClientSDKInit.h>
|
|
|
|
#include <AVSUtils/Logger/LogEntry.h>
|
|
|
|
#include <AVSUtils/Logging/Logger.h>
|
|
|
|
|
2017-02-10 23:39:10 +00:00
|
|
|
#include "Integration/AuthObserver.h"
|
|
|
|
#include "Integration/ClientMessageHandler.h"
|
|
|
|
#include "Integration/ConnectionStatusObserver.h"
|
|
|
|
#include "Integration/ObservableMessageRequest.h"
|
|
|
|
|
|
|
|
namespace alexaClientSDK {
|
|
|
|
namespace integration {
|
2017-06-09 23:23:31 +00:00
|
|
|
namespace test {
|
2017-02-10 23:39:10 +00:00
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
using namespace acl;
|
|
|
|
using namespace authDelegate;
|
|
|
|
using namespace avsCommon::avs;
|
|
|
|
using namespace avsCommon::avs::attachment;
|
|
|
|
using namespace avsCommon::utils::sds;
|
|
|
|
using namespace avsUtils::initialization;
|
2017-02-10 23:39:10 +00:00
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
/// This is a basic synchronize JSON message which may be used to initiate a connection with AVS.
|
2017-02-10 23:39:10 +00:00
|
|
|
static const std::string SYNCHRONIZE_STATE_JSON =
|
|
|
|
"{"
|
|
|
|
"\"context\":[{"
|
|
|
|
"\"header\":{"
|
|
|
|
"\"name\":\"SpeechState\","
|
|
|
|
"\"namespace\":\"SpeechSynthesizer\""
|
|
|
|
"},"
|
|
|
|
"\"payload\":{"
|
|
|
|
"\"playerActivity\":\"FINISHED\","
|
|
|
|
"\"offsetInMilliseconds\":0,"
|
|
|
|
"\"token\":\"\""
|
|
|
|
"}"
|
|
|
|
"}],"
|
|
|
|
"\"event\":{"
|
|
|
|
"\"header\":{"
|
|
|
|
"\"messageId\":\"00000000-0000-0000-0000-000000000000\","
|
|
|
|
"\"name\":\"SynchronizeState\","
|
|
|
|
"\"namespace\":\"System\""
|
|
|
|
"},"
|
|
|
|
"\"payload\":{"
|
|
|
|
"}"
|
|
|
|
"}"
|
|
|
|
"}";
|
|
|
|
|
|
|
|
/// This is a partial JSON string that should not be parseable.
|
|
|
|
static const std::string BAD_SYNCHRONIZE_STATE_JSON = "{";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This string specifies a Recognize event using the specified profile.
|
|
|
|
*
|
2017-05-26 23:06:14 +00:00
|
|
|
* CLOSE_TALK performs end-of-speech detection on the client, so a stop-capture directive will not be received from AVS.
|
|
|
|
* NEAR_FIELD performs end-of-speech detection in AVS, so a stop-capture directive will be received from AVS.
|
2017-02-10 23:39:10 +00:00
|
|
|
*/
|
|
|
|
#define RECOGNIZE_EVENT_JSON(PROFILE) \
|
|
|
|
"{" \
|
|
|
|
"\"event\":{" \
|
|
|
|
"\"payload\":{" \
|
|
|
|
"\"format\":\"AUDIO_L16_RATE_16000_CHANNELS_1\"," \
|
|
|
|
"\"profile\":\"" #PROFILE "\"" \
|
|
|
|
"}," \
|
|
|
|
"\"header\":{" \
|
|
|
|
"\"dialogRequestId\":\"dialogRequestId123\"," \
|
|
|
|
"\"messageId\":\"messageId123\"," \
|
|
|
|
"\"name\":\"Recognize\"," \
|
|
|
|
"\"namespace\":\"SpeechRecognizer\"" \
|
|
|
|
"}" \
|
|
|
|
"}," \
|
|
|
|
"\"context\":[{" \
|
|
|
|
"\"payload\":{" \
|
|
|
|
"\"activeAlerts\":[]," \
|
|
|
|
"\"allAlerts\":[]" \
|
|
|
|
"}," \
|
|
|
|
"\"header\":{" \
|
|
|
|
"\"name\":\"AlertsState\"," \
|
|
|
|
"\"namespace\":\"Alerts\"" \
|
|
|
|
"}" \
|
|
|
|
"}," \
|
|
|
|
"{" \
|
|
|
|
"\"payload\":{" \
|
|
|
|
"\"playerActivity\":\"IDLE\"," \
|
|
|
|
"\"offsetInMilliseconds\":0," \
|
|
|
|
"\"token\":\"\"" \
|
|
|
|
"}," \
|
|
|
|
"\"header\":{" \
|
|
|
|
"\"name\":\"PlaybackState\"," \
|
|
|
|
"\"namespace\":\"AudioPlayer\"" \
|
|
|
|
"}" \
|
|
|
|
"}," \
|
|
|
|
"{" \
|
|
|
|
"\"payload\":{" \
|
|
|
|
"\"muted\":false," \
|
|
|
|
"\"volume\":0" \
|
|
|
|
"}," \
|
|
|
|
"\"header\":{" \
|
|
|
|
"\"name\":\"VolumeState\"," \
|
|
|
|
"\"namespace\":\"Speaker\"" \
|
|
|
|
"}" \
|
|
|
|
"}," \
|
|
|
|
"{" \
|
|
|
|
"\"payload\":{" \
|
|
|
|
"\"playerActivity\":\"FINISHED\"," \
|
|
|
|
"\"offsetInMilliseconds\":0," \
|
|
|
|
"\"token\":\"\"" \
|
|
|
|
"}," \
|
|
|
|
"\"header\":{" \
|
|
|
|
"\"name\":\"SpeechState\"," \
|
|
|
|
"\"namespace\":\"SpeechSynthesizer\"" \
|
|
|
|
"}" \
|
|
|
|
"}]" \
|
|
|
|
"}"
|
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
/// This string specifies a Recognize event using the CLOSE_TALK profile.
|
2017-02-10 23:39:10 +00:00
|
|
|
static const std::string CT_RECOGNIZE_EVENT_JSON = RECOGNIZE_EVENT_JSON(CLOSE_TALK);
|
2017-05-26 23:06:14 +00:00
|
|
|
/// This string specifies a Recognize event using the NEAR_FIELD profile.
|
2017-02-10 23:39:10 +00:00
|
|
|
static const std::string NF_RECOGNIZE_EVENT_JSON = RECOGNIZE_EVENT_JSON(NEAR_FIELD);
|
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
/// This string specifies an ExpectSpeechTimedOut event.
|
2017-02-10 23:39:10 +00:00
|
|
|
static const std::string EXPECT_SPEECH_TIMED_OUT_EVENT_JSON =
|
|
|
|
"{"
|
|
|
|
"\"event\": {"
|
|
|
|
"\"header\": {"
|
|
|
|
"\"namespace\": \"SpeechRecognizer\","
|
|
|
|
"\"name\": \"ExpectSpeechTimedOut\","
|
|
|
|
"\"messageId\": \"messageId123\","
|
|
|
|
"},"
|
|
|
|
"\"payload\": {"
|
|
|
|
"}"
|
|
|
|
"}"
|
|
|
|
"}";
|
|
|
|
|
|
|
|
/// This is a 16 bit 16 kHz little endian linear PCM audio file containing a recognized message for AVS
|
2017-05-26 23:06:14 +00:00
|
|
|
static const std::string RECOGNIZE_AUDIO_FILE_NAME = "recognize_test.wav";
|
2017-02-10 23:39:10 +00:00
|
|
|
/// This is a 16 bit 16 kHz little endian linear PCM audio file containing several seconds of silence
|
2017-05-26 23:06:14 +00:00
|
|
|
static const std::string SILENCE_AUDIO_FILE_NAME = "silence_test.wav";
|
2017-02-10 23:39:10 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The value of MAX_THREADS is determined by the maximum number of streams we can have active at once which is defined
|
|
|
|
* in HTTP2Connection.cpp as a constant MAX_STREAMS=10. Streams include events, the downchannel and ping.
|
|
|
|
* Since we establish a downchannel when we connect, we can only have (MAX_STREAMS - 1) events sent at once.
|
|
|
|
* Therefore, the value of MAX_THREADS = MAX_STREAMS -1.
|
|
|
|
*/
|
2017-05-26 23:06:14 +00:00
|
|
|
static const int MAX_CONCURRENT_STREAMS = 9;
|
2017-02-10 23:39:10 +00:00
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
std::string g_configPath;
|
|
|
|
std::string g_inputPath;
|
2017-02-10 23:39:10 +00:00
|
|
|
|
|
|
|
class AlexaCommunicationsLibraryTest : public ::testing::Test {
|
2017-05-26 23:06:14 +00:00
|
|
|
public:
|
|
|
|
void SetUp() override {
|
|
|
|
std::ifstream infile(g_configPath);
|
2017-05-05 17:31:58 +00:00
|
|
|
ASSERT_TRUE(infile.good());
|
|
|
|
ASSERT_TRUE(AlexaClientSDKInit::initialize({&infile}));
|
2017-05-26 23:06:14 +00:00
|
|
|
|
2017-02-10 23:39:10 +00:00
|
|
|
m_authObserver = std::make_shared<AuthObserver>();
|
2017-05-05 17:31:58 +00:00
|
|
|
ASSERT_TRUE(m_authDelegate = AuthDelegate::create());
|
2017-02-10 23:39:10 +00:00
|
|
|
m_authDelegate->setAuthObserver(m_authObserver);
|
2017-05-26 23:06:14 +00:00
|
|
|
|
|
|
|
m_attachmentManager = std::make_shared<AttachmentManager>(AttachmentManager::AttachmentType::IN_PROCESS);
|
|
|
|
|
2017-02-10 23:39:10 +00:00
|
|
|
m_connectionStatusObserver = std::make_shared<ConnectionStatusObserver>();
|
2017-05-26 23:06:14 +00:00
|
|
|
m_clientMessageHandler = std::make_shared<ClientMessageHandler>(m_attachmentManager);
|
|
|
|
m_messageRouter = std::make_shared<HTTP2MessageRouter>(m_authDelegate, m_attachmentManager);
|
|
|
|
|
|
|
|
bool isEnabled = false;
|
2017-02-10 23:39:10 +00:00
|
|
|
m_avsConnectionManager = AVSConnectionManager::create(
|
|
|
|
m_messageRouter,
|
2017-05-26 23:06:14 +00:00
|
|
|
isEnabled,
|
2017-02-10 23:39:10 +00:00
|
|
|
m_connectionStatusObserver,
|
|
|
|
m_clientMessageHandler);
|
|
|
|
connect();
|
|
|
|
}
|
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
void TearDown() override {
|
2017-02-10 23:39:10 +00:00
|
|
|
disconnect();
|
|
|
|
AlexaClientSDKInit::uninitialize();
|
|
|
|
}
|
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
void connect() {
|
|
|
|
ASSERT_TRUE(m_authObserver->waitFor(AuthObserver::State::REFRESHED)) << "Retrieving the auth token timed out.";
|
2017-02-10 23:39:10 +00:00
|
|
|
m_avsConnectionManager->enable();
|
2017-06-09 23:23:31 +00:00
|
|
|
ASSERT_TRUE(m_connectionStatusObserver->waitFor(
|
|
|
|
ConnectionStatusObserverInterface::Status::CONNECTED)) << "Connecting timed out.";
|
2017-02-10 23:39:10 +00:00
|
|
|
}
|
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
void disconnect() {
|
|
|
|
m_avsConnectionManager->disable();
|
2017-06-09 23:23:31 +00:00
|
|
|
ASSERT_TRUE(m_connectionStatusObserver->waitFor(
|
|
|
|
ConnectionStatusObserverInterface::Status::DISCONNECTED)) << "Disconnecting timed out.";
|
2017-02-10 23:39:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2017-05-26 23:06:14 +00:00
|
|
|
* Function to send an Event to AVS.
|
2017-02-10 23:39:10 +00:00
|
|
|
*/
|
2017-05-26 23:06:14 +00:00
|
|
|
void sendEvent(
|
2017-05-18 05:02:48 +00:00
|
|
|
const std::string & jsonContent,
|
2017-05-26 23:06:14 +00:00
|
|
|
MessageRequest::Status expectedStatus,
|
|
|
|
std::chrono::seconds timeout,
|
|
|
|
std::shared_ptr<avsCommon::avs::attachment::AttachmentReader> attachmentReader = nullptr) {
|
2017-05-18 05:02:48 +00:00
|
|
|
auto messageRequest = std::make_shared<ObservableMessageRequest>(jsonContent, attachmentReader);
|
2017-05-26 23:06:14 +00:00
|
|
|
|
2017-05-18 05:02:48 +00:00
|
|
|
m_avsConnectionManager->sendMessage(messageRequest);
|
2017-02-10 23:39:10 +00:00
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
ASSERT_TRUE(messageRequest->waitFor(expectedStatus, timeout));
|
2017-02-10 23:39:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-05-26 23:06:14 +00:00
|
|
|
* Function to create an attachmentReader given a filename.
|
2017-02-10 23:39:10 +00:00
|
|
|
*/
|
2017-05-26 23:06:14 +00:00
|
|
|
std::shared_ptr<InProcessAttachmentReader> createAttachmentReader(const std::string & fileName) {
|
|
|
|
// 1MB is large enough for our test audio samples.
|
2017-05-18 05:02:48 +00:00
|
|
|
const int mbBytes = 1024 * 1024;
|
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
// create an SDS with 1MB size, so we can write the entire audio file into it.
|
|
|
|
auto sdsBufferSize = InProcessSDS::calculateBufferSize(mbBytes);
|
|
|
|
auto sdsBuffer = std::make_shared<InProcessSDSTraits::Buffer>(sdsBufferSize);
|
|
|
|
std::shared_ptr<InProcessSDS> sds = InProcessSDS::create(sdsBuffer);
|
2017-05-18 05:02:48 +00:00
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
// open the file.
|
|
|
|
auto is = std::make_shared<std::ifstream>(fileName, std::ios::binary);
|
|
|
|
EXPECT_TRUE(is->is_open());
|
2017-05-18 05:02:48 +00:00
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
// read the data from the file into the SDS, via the local buffer.
|
|
|
|
std::vector<char> localBuffer(mbBytes);
|
2017-05-18 05:02:48 +00:00
|
|
|
auto attachmentWriter = InProcessAttachmentWriter::create(sds);
|
|
|
|
while (*is) {
|
2017-05-26 23:06:14 +00:00
|
|
|
// data -> local buffer
|
2017-05-18 05:02:48 +00:00
|
|
|
is->read(localBuffer.data(), mbBytes);
|
2017-05-26 23:06:14 +00:00
|
|
|
size_t numBytesRead = static_cast<size_t>(is->gcount());
|
|
|
|
|
|
|
|
// local buffer -> sds
|
2017-05-18 05:02:48 +00:00
|
|
|
AttachmentWriter::WriteStatus writeStatus = AttachmentWriter::WriteStatus::OK;
|
|
|
|
attachmentWriter->write(localBuffer.data(), numBytesRead, &writeStatus);
|
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
// confirm the SDS write operation went ok
|
2017-05-18 05:02:48 +00:00
|
|
|
bool writeStatusOk = (AttachmentWriter::WriteStatus::OK == writeStatus ||
|
2017-05-26 23:06:14 +00:00
|
|
|
AttachmentWriter::WriteStatus::CLOSED == writeStatus);
|
|
|
|
EXPECT_TRUE(writeStatusOk);
|
2017-05-18 05:02:48 +00:00
|
|
|
}
|
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
// closing the writer indicates to readers of the SDS that there is no more data that will be written.
|
2017-05-18 05:02:48 +00:00
|
|
|
attachmentWriter->close();
|
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
// create and return the reader.
|
2017-05-18 05:02:48 +00:00
|
|
|
std::shared_ptr<InProcessAttachmentReader> attachmentReader =
|
|
|
|
InProcessAttachmentReader::create(AttachmentReader::Policy::NON_BLOCKING, sds);
|
2017-05-26 23:06:14 +00:00
|
|
|
EXPECT_NE(attachmentReader, nullptr);
|
2017-05-18 05:02:48 +00:00
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
return attachmentReader;
|
2017-02-10 23:39:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-05-26 23:06:14 +00:00
|
|
|
* This function sends an Event to AVS, deciding to include an audio attachment based upon a random factor.
|
2017-02-10 23:39:10 +00:00
|
|
|
*/
|
2017-05-26 23:06:14 +00:00
|
|
|
void sendRandomEvent() {
|
|
|
|
std::shared_ptr<InProcessAttachmentReader> attachmentReader;
|
|
|
|
std::string eventJson = SYNCHRONIZE_STATE_JSON;
|
|
|
|
|
|
|
|
if (rand() % 2) {
|
|
|
|
eventJson = CT_RECOGNIZE_EVENT_JSON;
|
|
|
|
attachmentReader = createAttachmentReader(g_inputPath + "/" + RECOGNIZE_AUDIO_FILE_NAME);
|
2017-02-10 23:39:10 +00:00
|
|
|
}
|
2017-05-26 23:06:14 +00:00
|
|
|
|
|
|
|
sendEvent(eventJson, MessageRequest::Status::SUCCESS, std::chrono::seconds(40), attachmentReader);
|
2017-02-10 23:39:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::shared_ptr<AuthObserver> m_authObserver;
|
|
|
|
std::shared_ptr<AuthDelegate> m_authDelegate;
|
|
|
|
std::shared_ptr<ConnectionStatusObserver> m_connectionStatusObserver;
|
|
|
|
std::shared_ptr<ClientMessageHandler> m_clientMessageHandler;
|
2017-05-26 23:06:14 +00:00
|
|
|
std::shared_ptr<AttachmentManager> m_attachmentManager;
|
2017-02-10 23:39:10 +00:00
|
|
|
std::shared_ptr<MessageRouter> m_messageRouter;
|
|
|
|
std::shared_ptr<AVSConnectionManager> m_avsConnectionManager;
|
|
|
|
};
|
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
/// Test connecting and disconnecting from AVS.
|
|
|
|
TEST_F(AlexaCommunicationsLibraryTest, testConnectAndDisconnect) {
|
2017-02-10 23:39:10 +00:00
|
|
|
/*
|
2017-05-26 23:06:14 +00:00
|
|
|
* Connect is called in SetUp and disconnect is called in TearDown. This function requires no additional logic.
|
2017-02-10 23:39:10 +00:00
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-05-26 23:06:14 +00:00
|
|
|
* Test sending an Event to AVS.
|
2017-02-10 23:39:10 +00:00
|
|
|
*
|
2017-05-26 23:06:14 +00:00
|
|
|
* This test sends a SynchronizeState Event, which does not require an attachment, or receive a Directive in response.
|
2017-02-10 23:39:10 +00:00
|
|
|
*
|
|
|
|
* @see https://developer.amazon.com/public/solutions/alexa/alexa-voice-service/reference/system#synchronizestate
|
|
|
|
*/
|
2017-05-26 23:06:14 +00:00
|
|
|
TEST_F(AlexaCommunicationsLibraryTest, testSendEvent) {
|
|
|
|
sendEvent(SYNCHRONIZE_STATE_JSON, MessageRequest::Status::SUCCESS, std::chrono::seconds(10));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function that tests the behavior of the ACL when an improperly formatted message is sent, expecting the server
|
|
|
|
* to return an internal error.
|
|
|
|
*/
|
|
|
|
TEST_F(AlexaCommunicationsLibraryTest, testSendInvalidEvent) {
|
|
|
|
sendEvent(BAD_SYNCHRONIZE_STATE_JSON, MessageRequest::Status::SERVER_INTERNAL_ERROR, std::chrono::seconds(10));
|
2017-02-10 23:39:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test ability to send an event with attachments to Alexa Voice Service.
|
|
|
|
*
|
|
|
|
* This test sends a RecognizeAudio event, which requires an attachment of the audio stream. In this case,
|
|
|
|
* we send a pre-recorded audio file which asks Alexa to "tell me a joke".
|
|
|
|
*
|
|
|
|
* @see https://developer.amazon.com/public/solutions/alexa/alexa-voice-service/reference/speechrecognizer#recognize
|
|
|
|
*/
|
2017-05-26 23:06:14 +00:00
|
|
|
TEST_F(AlexaCommunicationsLibraryTest, testSendEventWithAttachment) {
|
|
|
|
auto attachmentReader = createAttachmentReader(g_inputPath + "/" + RECOGNIZE_AUDIO_FILE_NAME);
|
|
|
|
sendEvent(CT_RECOGNIZE_EVENT_JSON, MessageRequest::Status::SUCCESS, std::chrono::seconds(10),
|
|
|
|
attachmentReader);
|
2017-02-10 23:39:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-05-26 23:06:14 +00:00
|
|
|
* Test sending an Event and receiving a Directive in response.
|
|
|
|
*
|
|
|
|
* This test sends a Recognize event, which includes an audio attachment. In this case, the audio file sent to AVS
|
|
|
|
* asks Alexa to "tell me a joke". The Speak Directive we expect in response will be the joke.
|
|
|
|
*
|
|
|
|
* @see https://developer.amazon.com/public/solutions/alexa/alexa-voice-service/reference/audioplayer#states
|
2017-02-10 23:39:10 +00:00
|
|
|
*/
|
2017-05-26 23:06:14 +00:00
|
|
|
TEST_F(AlexaCommunicationsLibraryTest, testSendEventAndReceiveDirective) {
|
|
|
|
auto attachmentReader = createAttachmentReader(g_inputPath + "/" + RECOGNIZE_AUDIO_FILE_NAME);
|
|
|
|
sendEvent(CT_RECOGNIZE_EVENT_JSON, MessageRequest::Status::SUCCESS, std::chrono::seconds(10),
|
|
|
|
attachmentReader);
|
2017-02-10 23:39:10 +00:00
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
// We expect to receive Directives in response to the recognize Event. Wait for the first one.
|
|
|
|
ASSERT_TRUE(m_clientMessageHandler->waitForNext(std::chrono::seconds(20)));
|
2017-02-10 23:39:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-05-26 23:06:14 +00:00
|
|
|
* Test sending multiple Events in succession and verify that AVS responds to each of them.
|
2017-02-10 23:39:10 +00:00
|
|
|
*/
|
2017-05-26 23:06:14 +00:00
|
|
|
TEST_F(AlexaCommunicationsLibraryTest, testSendEventsSerially) {
|
2017-02-10 23:39:10 +00:00
|
|
|
const int NUMBER_OF_SUCCESSIVE_SENDS = 10;
|
|
|
|
for (int i = 0; i < NUMBER_OF_SUCCESSIVE_SENDS; ++i) {
|
2017-05-26 23:06:14 +00:00
|
|
|
auto attachmentReader = createAttachmentReader(g_inputPath + "/" + RECOGNIZE_AUDIO_FILE_NAME);
|
|
|
|
sendEvent(CT_RECOGNIZE_EVENT_JSON, MessageRequest::Status::SUCCESS, std::chrono::seconds(10), attachmentReader);
|
2017-02-10 23:39:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-05-26 23:06:14 +00:00
|
|
|
* Test sending multiple Events concurrently and verify that AVS responds to each of them.
|
2017-02-10 23:39:10 +00:00
|
|
|
*/
|
2017-05-26 23:06:14 +00:00
|
|
|
TEST_F(AlexaCommunicationsLibraryTest, testSendEventsConcurrently) {
|
|
|
|
std::vector<std::future<void>> futures;
|
2017-02-10 23:39:10 +00:00
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
for(int i = 0; i < MAX_CONCURRENT_STREAMS; ++i){
|
|
|
|
auto future = std::async(std::launch::async, [this](){ sendRandomEvent(); });
|
|
|
|
futures.push_back(std::move(future));
|
2017-02-10 23:39:10 +00:00
|
|
|
}
|
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
for (auto & future : futures) {
|
2017-02-10 23:39:10 +00:00
|
|
|
auto status = future.wait_for(std::chrono::seconds(20));
|
|
|
|
ASSERT_EQ(status, std::future_status::ready);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-05-26 23:06:14 +00:00
|
|
|
* Test receiving an AVS Directive on the DownChannel.
|
2017-02-10 23:39:10 +00:00
|
|
|
*
|
2017-05-26 23:06:14 +00:00
|
|
|
* DownChannel Directives are unsolicited - they may be pushed to the client by AVS at any time.
|
|
|
|
* This test exercises this functionality by sending a RecognizeAudio Event with silence for the attached audio.
|
|
|
|
* By using the NEAR_FIELD audio profile, we expect AVS to detect the end of speech and send a StopCapture Directive.
|
2017-02-10 23:39:10 +00:00
|
|
|
*
|
2017-05-26 23:06:14 +00:00
|
|
|
* @see https://developer.amazon.com/public/solutions/alexa/alexa-voice-service/reference/speechrecognizer#profiles
|
2017-02-10 23:39:10 +00:00
|
|
|
*/
|
2017-05-26 23:06:14 +00:00
|
|
|
TEST_F(AlexaCommunicationsLibraryTest, testReceiveDirectiveOnDownchannel) {
|
|
|
|
auto attachmentReader = createAttachmentReader(g_inputPath + "/" + SILENCE_AUDIO_FILE_NAME);
|
|
|
|
sendEvent(NF_RECOGNIZE_EVENT_JSON, MessageRequest::Status::SUCCESS, std::chrono::seconds(10), attachmentReader);
|
2017-02-10 23:39:10 +00:00
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
// Wait for the StopCapture Directive to be received.
|
2017-02-10 23:39:10 +00:00
|
|
|
ASSERT_TRUE(m_clientMessageHandler->waitForNext(std::chrono::seconds(20)));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-05-26 23:06:14 +00:00
|
|
|
* Test that a connection to AVS persists between sending Events.
|
2017-02-10 23:39:10 +00:00
|
|
|
*/
|
2017-05-26 23:06:14 +00:00
|
|
|
TEST_F(AlexaCommunicationsLibraryTest, testPersistentConnection) {
|
|
|
|
auto attachmentReader = createAttachmentReader(g_inputPath + "/" + RECOGNIZE_AUDIO_FILE_NAME);
|
|
|
|
sendEvent(CT_RECOGNIZE_EVENT_JSON, MessageRequest::Status::SUCCESS, std::chrono::seconds(10),
|
|
|
|
attachmentReader);
|
2017-06-09 23:23:31 +00:00
|
|
|
ASSERT_FALSE(m_connectionStatusObserver->waitFor(
|
|
|
|
ConnectionStatusObserverInterface::Status::DISCONNECTED, std::chrono::seconds(20)))
|
2017-05-26 23:06:14 +00:00
|
|
|
<< "Connection changed after a response was received";
|
|
|
|
sendEvent(CT_RECOGNIZE_EVENT_JSON, MessageRequest::Status::SUCCESS, std::chrono::seconds(10),
|
|
|
|
attachmentReader);
|
2017-02-10 23:39:10 +00:00
|
|
|
}
|
|
|
|
|
2017-06-09 23:23:31 +00:00
|
|
|
} // namespace test
|
2017-02-10 23:39:10 +00:00
|
|
|
} // namespace integration
|
|
|
|
} // namespace alexaClientSDK
|
|
|
|
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
|
|
if (argc < 3) {
|
|
|
|
std::cerr << "USAGE: AlexaCommunicationsLibraryTest <path_to_auth_delgate_config> <path_to_inputs_folder>"
|
|
|
|
<< std::endl;
|
2017-03-10 00:01:46 +00:00
|
|
|
return 1;
|
2017-02-10 23:39:10 +00:00
|
|
|
} else {
|
2017-06-09 23:23:31 +00:00
|
|
|
alexaClientSDK::integration::test::g_configPath = std::string(argv[1]);
|
|
|
|
alexaClientSDK::integration::test::g_inputPath = std::string(argv[2]);
|
2017-02-10 23:39:10 +00:00
|
|
|
return RUN_ALL_TESTS();
|
|
|
|
}
|
|
|
|
}
|