2017-05-26 23:06:14 +00:00
|
|
|
/*
|
|
|
|
* HTTP2StreamTest.cpp
|
|
|
|
*
|
|
|
|
* Copyright 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/// @file HTTP2StreamTest.cpp
|
|
|
|
|
|
|
|
#include <memory>
|
|
|
|
#include <random>
|
|
|
|
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
|
|
|
#include <curl/curl.h>
|
|
|
|
#include <ACL/Transport/HTTP2Stream.h>
|
2017-08-08 00:04:43 +00:00
|
|
|
#include <AVSCommon/AVS/Initialization/AlexaClientSDKInit.h>
|
|
|
|
#include <AVSCommon/Utils/SDS/InProcessSDS.h>
|
|
|
|
#include <AVSCommon/AVS/Attachment/InProcessAttachmentReader.h>
|
2017-05-26 23:06:14 +00:00
|
|
|
#include "TestableConsumer.h"
|
|
|
|
#include "MockMessageRequest.h"
|
|
|
|
#include "Common/Common.h"
|
|
|
|
|
|
|
|
namespace alexaClientSDK {
|
|
|
|
namespace acl {
|
2017-06-09 23:23:31 +00:00
|
|
|
namespace test {
|
2017-05-26 23:06:14 +00:00
|
|
|
|
2017-08-08 00:04:43 +00:00
|
|
|
using namespace ::testing;
|
|
|
|
using namespace avsCommon::avs;
|
|
|
|
using namespace avsCommon::avs::attachment;
|
|
|
|
using namespace avsCommon::utils::sds;
|
|
|
|
using namespace alexaClientSDK::avsCommon::avs::initialization;
|
|
|
|
|
2017-05-26 23:06:14 +00:00
|
|
|
/// A test url with which to initialize our test stream object.
|
|
|
|
static const std::string LIBCURL_TEST_URL = "http://example.com";
|
|
|
|
/// A test auth string with which to initialize our test stream object.
|
|
|
|
static const std::string LIBCURL_TEST_AUTH_STRING = "test_auth_string";
|
2017-08-08 00:04:43 +00:00
|
|
|
/// The length of the string we will test for the exception message.
|
2017-05-26 23:06:14 +00:00
|
|
|
static const int TEST_EXCEPTION_STRING_LENGTH = 200;
|
|
|
|
/// The number of iterations the multi-write test will perform.
|
|
|
|
static const int TEST_EXCEPTION_PARTITIONS = 7;
|
2017-08-08 00:04:43 +00:00
|
|
|
/// Number of bytes per word in the SDS circular buffer.
|
|
|
|
static const size_t SDS_WORDSIZE = 1;
|
|
|
|
/// Maximum number of readers to support in the SDS circular buffer.
|
|
|
|
static const size_t SDS_MAXREADERS = 1;
|
|
|
|
/// Number of words to hold in the SDS circular buffer.
|
|
|
|
static const size_t SDS_WORDS = 300;
|
|
|
|
/// Number of strings to read/write for the test
|
|
|
|
static const size_t NUMBER_OF_STRINGS = 1;
|
2017-05-26 23:06:14 +00:00
|
|
|
/**
|
|
|
|
* Our GTest class.
|
|
|
|
*/
|
|
|
|
class HTTP2StreamTest : public ::testing::Test {
|
|
|
|
public:
|
2017-08-08 00:04:43 +00:00
|
|
|
void SetUp() override;
|
2017-05-26 23:06:14 +00:00
|
|
|
|
2017-08-08 00:04:43 +00:00
|
|
|
void TearDown() override;
|
2017-05-26 23:06:14 +00:00
|
|
|
|
2017-08-08 00:04:43 +00:00
|
|
|
/// A message request to initiate @c m_readTestableStream with
|
|
|
|
std::shared_ptr<MessageRequest> m_MessageRequest;
|
2017-05-26 23:06:14 +00:00
|
|
|
/// A mock message request object.
|
|
|
|
std::shared_ptr<MockMessageRequest> m_mockMessageRequest;
|
|
|
|
/// An object that is required for constructing a stream.
|
|
|
|
TestableConsumer m_testableConsumer;
|
|
|
|
/// The actual stream we will be testing.
|
|
|
|
std::shared_ptr<HTTP2Stream> m_testableStream;
|
2017-08-08 00:04:43 +00:00
|
|
|
/// The stream to test @c readCallback function
|
|
|
|
std::shared_ptr<HTTP2Stream> m_readTestableStream;
|
|
|
|
/// The attachment manager for the stream
|
|
|
|
std::shared_ptr<AttachmentManager> m_attachmentManager;
|
|
|
|
/// A Writer to write data to SDS buffer.
|
|
|
|
std::unique_ptr<avsCommon::utils::sds::InProcessSDS::Writer> m_writer;
|
|
|
|
/// The attachment reader for message request of @c m_readTestableStream
|
|
|
|
std::unique_ptr<InProcessAttachmentReader> m_attachmentReader;
|
|
|
|
/// A char pointer to data buffer to read or write from callbacks
|
|
|
|
char* m_dataBegin;
|
|
|
|
/// A string to which @c m_dataBegin is pointing to
|
|
|
|
std::string m_testString;
|
2017-05-26 23:06:14 +00:00
|
|
|
};
|
|
|
|
|
2017-08-08 00:04:43 +00:00
|
|
|
void HTTP2StreamTest::SetUp() {
|
|
|
|
AlexaClientSDKInit::initialize(std::vector<std::istream*>());
|
|
|
|
|
|
|
|
m_testString = createRandomAlphabetString(TEST_EXCEPTION_STRING_LENGTH);
|
|
|
|
m_dataBegin = const_cast<char*>(m_testString.c_str());
|
|
|
|
|
|
|
|
/// Create a SDS buffer and using a @c Writer, write a string into the buffer
|
|
|
|
size_t bufferSize = InProcessSDS::calculateBufferSize(SDS_WORDS, SDS_WORDSIZE, SDS_MAXREADERS);
|
|
|
|
auto buffer = std::make_shared<avsCommon::utils::sds::InProcessSDS::Buffer>(bufferSize);
|
|
|
|
std::shared_ptr<InProcessSDS> stream = InProcessSDS::create(buffer, SDS_WORDSIZE, SDS_MAXREADERS);
|
|
|
|
ASSERT_NE(stream, nullptr);
|
|
|
|
|
|
|
|
m_writer = stream->createWriter(InProcessSDS::Writer::Policy::NONBLOCKABLE);
|
|
|
|
ASSERT_NE(m_writer, nullptr);
|
|
|
|
ASSERT_EQ(TEST_EXCEPTION_STRING_LENGTH, m_writer->write(m_dataBegin, TEST_EXCEPTION_STRING_LENGTH));
|
|
|
|
|
|
|
|
/// Create an attachment Reader for @c m_MessageRequest
|
|
|
|
m_attachmentReader = InProcessAttachmentReader::create(AttachmentReader::Policy::NON_BLOCKING, stream);
|
|
|
|
m_MessageRequest = std::make_shared<MessageRequest>("", std::move(m_attachmentReader));
|
|
|
|
ASSERT_NE(m_MessageRequest, nullptr);
|
|
|
|
|
|
|
|
m_mockMessageRequest = std::make_shared<MockMessageRequest>();
|
|
|
|
ASSERT_NE(m_mockMessageRequest, nullptr);
|
|
|
|
m_attachmentManager = std::make_shared<AttachmentManager>(AttachmentManager::AttachmentType::IN_PROCESS);
|
|
|
|
|
|
|
|
m_testableStream = std::make_shared<HTTP2Stream>(&m_testableConsumer, m_attachmentManager);
|
|
|
|
ASSERT_NE(m_testableStream, nullptr);
|
|
|
|
ASSERT_TRUE(m_testableStream->initPost(LIBCURL_TEST_URL, LIBCURL_TEST_AUTH_STRING, m_mockMessageRequest));
|
|
|
|
|
|
|
|
m_readTestableStream = std::make_shared<HTTP2Stream>(&m_testableConsumer, m_attachmentManager);
|
|
|
|
ASSERT_NE(m_readTestableStream, nullptr);
|
|
|
|
ASSERT_TRUE(m_readTestableStream->initPost(LIBCURL_TEST_URL, LIBCURL_TEST_AUTH_STRING, m_MessageRequest));
|
|
|
|
}
|
|
|
|
|
|
|
|
void HTTP2StreamTest::TearDown() {
|
|
|
|
AlexaClientSDKInit::uninitialize();
|
|
|
|
}
|
2017-05-26 23:06:14 +00:00
|
|
|
/**
|
|
|
|
* Let's simulate that AVSConnectionManager->send() has been invoked, and the messageRequest object is
|
|
|
|
* waiting to be notified on the response from AVS. We will invoke the stream writeCallbacks directly to
|
|
|
|
* simulate exception data returning from AVS, and verify that the stream passes the correct data back to
|
|
|
|
* the request object.
|
|
|
|
*/
|
|
|
|
TEST_F(HTTP2StreamTest, testExceptionReceivedSingleWrite) {
|
2017-08-08 00:04:43 +00:00
|
|
|
HTTP2Stream::writeCallback(m_dataBegin, TEST_EXCEPTION_STRING_LENGTH, NUMBER_OF_STRINGS, m_testableStream.get());
|
2017-05-26 23:06:14 +00:00
|
|
|
|
2017-08-08 00:04:43 +00:00
|
|
|
EXPECT_CALL(*m_mockMessageRequest, onExceptionReceived(_)).Times(1);
|
|
|
|
EXPECT_CALL(*m_mockMessageRequest, onSendCompleted(_)).Times(1);
|
2017-05-26 23:06:14 +00:00
|
|
|
// This simulates stream cleanup, which flushes out the parsed exception message.
|
|
|
|
m_testableStream->notifyRequestObserver();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The same test as above, but now with multiple writes (simulating either a small buffer from libcurl, or a very
|
|
|
|
* long exception message).
|
|
|
|
*/
|
|
|
|
TEST_F(HTTP2StreamTest, testExceptionReceivedMultiWrite) {
|
|
|
|
int writeQuantum = TEST_EXCEPTION_STRING_LENGTH;
|
|
|
|
if (TEST_EXCEPTION_PARTITIONS > 0) {
|
|
|
|
writeQuantum = TEST_EXCEPTION_STRING_LENGTH / TEST_EXCEPTION_PARTITIONS;
|
|
|
|
}
|
|
|
|
int numberBytesWritten = 0;
|
|
|
|
|
2017-08-08 00:04:43 +00:00
|
|
|
char* currBuffPosition = m_dataBegin;
|
2017-05-26 23:06:14 +00:00
|
|
|
while (numberBytesWritten < TEST_EXCEPTION_STRING_LENGTH) {
|
|
|
|
|
2017-08-08 00:04:43 +00:00
|
|
|
int bytesRemaining = TEST_EXCEPTION_STRING_LENGTH - numberBytesWritten;
|
2017-05-26 23:06:14 +00:00
|
|
|
int bytesToWrite = bytesRemaining < writeQuantum ? bytesRemaining : writeQuantum;
|
|
|
|
|
2017-08-08 00:04:43 +00:00
|
|
|
HTTP2Stream::writeCallback(currBuffPosition, bytesToWrite, NUMBER_OF_STRINGS, m_testableStream.get());
|
2017-05-26 23:06:14 +00:00
|
|
|
currBuffPosition += bytesToWrite;
|
|
|
|
numberBytesWritten += bytesToWrite;
|
|
|
|
}
|
|
|
|
|
2017-08-08 00:04:43 +00:00
|
|
|
EXPECT_CALL(*m_mockMessageRequest, onExceptionReceived(_)).Times(1);
|
|
|
|
EXPECT_CALL(*m_mockMessageRequest, onSendCompleted(_)).Times(1);
|
2017-05-26 23:06:14 +00:00
|
|
|
|
|
|
|
// This simulates stream cleanup, which flushes out the parsed exception message.
|
|
|
|
m_testableStream->notifyRequestObserver();
|
|
|
|
}
|
|
|
|
|
2017-08-08 00:04:43 +00:00
|
|
|
TEST_F(HTTP2StreamTest, testHeaderCallback) {
|
|
|
|
// Check if the length returned is as expected
|
|
|
|
int headerLength = TEST_EXCEPTION_STRING_LENGTH * NUMBER_OF_STRINGS;
|
|
|
|
int returnHeaderLength = HTTP2Stream::headerCallback(
|
|
|
|
m_dataBegin, TEST_EXCEPTION_STRING_LENGTH, NUMBER_OF_STRINGS, m_testableStream.get());
|
|
|
|
ASSERT_EQ(headerLength, returnHeaderLength);
|
|
|
|
// Call the function with NULL HTTP2Stream and check if it fails
|
|
|
|
returnHeaderLength = HTTP2Stream::headerCallback(
|
|
|
|
m_dataBegin, TEST_EXCEPTION_STRING_LENGTH, NUMBER_OF_STRINGS, nullptr);
|
|
|
|
ASSERT_EQ(0, returnHeaderLength);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(HTTP2StreamTest, testReadCallBack) {
|
|
|
|
//Check if the bytesRead are equal to length of data written in SDS buffer
|
|
|
|
int bytesRead = HTTP2Stream::readCallback(
|
|
|
|
m_dataBegin, TEST_EXCEPTION_STRING_LENGTH, NUMBER_OF_STRINGS, m_readTestableStream.get());
|
|
|
|
ASSERT_EQ(TEST_EXCEPTION_STRING_LENGTH, bytesRead);
|
|
|
|
// Call the function with NULL HTTP2Stream and check if it fails
|
|
|
|
bytesRead = HTTP2Stream::readCallback(m_dataBegin, TEST_EXCEPTION_STRING_LENGTH, NUMBER_OF_STRINGS, nullptr);
|
|
|
|
ASSERT_EQ(0, bytesRead);
|
|
|
|
}
|
2017-06-09 23:23:31 +00:00
|
|
|
} // namespace test
|
2017-05-26 23:06:14 +00:00
|
|
|
} // namespace acl
|
|
|
|
} // namespace alexaClientSDK
|
|
|
|
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
|
|
return RUN_ALL_TESTS();
|
|
|
|
}
|