/* * AttachmentManagerTest.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. */ #include #include #include #include #include #include #include "AVSCommon/AttachmentManager.h" namespace alexaClientSDK { namespace avsCommon { /// Time out to wait for an attachment. static const std::chrono::milliseconds TIME_OUT_IN_MILLISECONDS(50); /// The content ID of an attachment. static const std::string CONTENT_ID_TEST0 = "contentId_test0"; /// The content ID of an attachment. static const std::string CONTENT_ID_TEST1 = "contentId_test1"; using namespace ::testing; /** * Test fixture class that tests the @c AttachmentManager */ class AttachmentManagerTest: public ::testing::Test { protected: void SetUp() override { m_attachmentManager = std::make_shared(); } /// The attachment manager used for testing. std::shared_ptr m_attachmentManager; /// The condition variable to ensure certain orders of reader and writer. std::condition_variable m_cv; /// Mutex to protect shared data. std::mutex m_mutex; }; /// Test if the attachment manager has been successfully created. TEST_F(AttachmentManagerTest, attachmentManagerCreation) { ASSERT_TRUE(m_attachmentManager); } /// Test if the attachment reader has timed out. TEST_F(AttachmentManagerTest, createAttachmentReaderTimeOut) { auto attachmentReader = m_attachmentManager->createAttachmentReader(CONTENT_ID_TEST0); auto status = attachmentReader.wait_for(TIME_OUT_IN_MILLISECONDS); ASSERT_EQ(status, std::future_status::timeout); } /// Test getting attachment through attachment reader synchronously. TEST_F(AttachmentManagerTest, createAttachmentReaderSynchrously) { std::shared_ptr attachment = std::make_shared(); m_attachmentManager->createAttachment(CONTENT_ID_TEST0, attachment); auto attachmentReader = m_attachmentManager->createAttachmentReader(CONTENT_ID_TEST0); ASSERT_TRUE(attachmentReader.get()); } /// Test getting attachment through attachment reader asynchronously. TEST_F(AttachmentManagerTest, gettingAttachmentAsynchrouslyWithWriterArrivesFirst) { auto createAttachment = [this]() { std::shared_ptr attachment = std::make_shared(); m_attachmentManager->createAttachment(CONTENT_ID_TEST0, attachment); }; std::thread writeThread(createAttachment); auto attachmentReader = m_attachmentManager->createAttachmentReader(CONTENT_ID_TEST0); ASSERT_TRUE(attachmentReader.get()); if (writeThread.joinable()) { writeThread.join(); } } /// Test getting attachment through attachment reader asynchronously, with reader trying to read first. TEST_F(AttachmentManagerTest, gettingAttachmentAsynchrouslyWithReaderArrivesFirst) { bool readerIsReady = false; auto createAttachment = [this, &readerIsReady]() { std::shared_ptr attachment = std::make_shared(); std::unique_lock lock(m_mutex); m_cv.wait(lock, [&readerIsReady]() { return readerIsReady; }); m_attachmentManager->createAttachment(CONTENT_ID_TEST0, attachment); }; auto readAttachment = [this, &readerIsReady]() { std::unique_lock lock(m_mutex); auto attachmentReader = m_attachmentManager->createAttachmentReader(CONTENT_ID_TEST0); readerIsReady = true; lock.unlock(); m_cv.notify_one(); ASSERT_TRUE(attachmentReader.get()); }; // Start the read thread before the write thread. std::thread readThread(readAttachment); std::thread writeThread(createAttachment); if (readThread.joinable()) { readThread.join(); } if (writeThread.joinable()) { writeThread.join(); } } /// Test release the expired attachment upon the creation of another attachment. TEST_F(AttachmentManagerTest, releaseExpiredAttachmentOnAttachmentCreation) { m_attachmentManager = std::make_shared(std::chrono::minutes(0)); m_attachmentManager->createAttachment(CONTENT_ID_TEST0, std::make_shared()); m_attachmentManager->createAttachment(CONTENT_ID_TEST1, std::make_shared()); auto attachmentReader = m_attachmentManager->createAttachmentReader(CONTENT_ID_TEST0); auto status = attachmentReader.wait_for(TIME_OUT_IN_MILLISECONDS); ASSERT_EQ(status, std::future_status::timeout); attachmentReader = m_attachmentManager->createAttachmentReader(CONTENT_ID_TEST1); status = attachmentReader.wait_for(TIME_OUT_IN_MILLISECONDS); ASSERT_EQ(status, std::future_status::timeout); } /// Test releasing attachment through attachment manager without any error. TEST_F(AttachmentManagerTest, releaseAttachment) { m_attachmentManager->createAttachment(CONTENT_ID_TEST0, std::make_shared()); m_attachmentManager->releaseAttachment(CONTENT_ID_TEST0); // Try to release the attachment that is not created; m_attachmentManager->releaseAttachment(CONTENT_ID_TEST1); } /// Test reading attachments after attachment has been released. TEST_F(AttachmentManagerTest, readAttachmentAfterReleasing) { m_attachmentManager->createAttachment(CONTENT_ID_TEST0, std::make_shared()); m_attachmentManager->createAttachment(CONTENT_ID_TEST1, std::make_shared()); m_attachmentManager->releaseAttachment(CONTENT_ID_TEST0); m_attachmentManager->releaseAttachment(CONTENT_ID_TEST1); auto attachmentReader = m_attachmentManager->createAttachmentReader(CONTENT_ID_TEST0); auto status = attachmentReader.wait_for(TIME_OUT_IN_MILLISECONDS); ASSERT_EQ(status, std::future_status::timeout); attachmentReader = m_attachmentManager->createAttachmentReader(CONTENT_ID_TEST1); status = attachmentReader.wait_for(TIME_OUT_IN_MILLISECONDS); ASSERT_EQ(status, std::future_status::timeout); } } // namespace avsCommon } // namespace alexaClientSDK