diff options
Diffstat (limited to 'src/components/utils/test')
24 files changed, 3885 insertions, 117 deletions
diff --git a/src/components/utils/test/CMakeLists.txt b/src/components/utils/test/CMakeLists.txt index a9ed5acda..377b7dba7 100644 --- a/src/components/utils/test/CMakeLists.txt +++ b/src/components/utils/test/CMakeLists.txt @@ -1,17 +1,80 @@ +# Copyright (c) 2015, Ford Motor Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following +# disclaimer in the documentation and/or other materials provided with the +# distribution. +# +# Neither the name of the Ford Motor Company nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +if(BUILD_TESTS) + include_directories ( ${CMAKE_SOURCE_DIR}/src/3rd_party-static/gmock-1.7.0/include - ${CMAKE_SOURCE_DIR}/src/3rd_party-static/gmock-1.7.0/gtest/include) + ${CMAKE_SOURCE_DIR}/src/3rd_party-static/gmock-1.7.0/gtest/include + ${COMPONENTS_DIR}/include/utils + ) set(testSources main.cc + messagemeter_test.cc file_system_test.cc - date_time_test.cc) + date_time_test.cc + system_test.cc + signals_linux_test.cc + thread_validator_test.cc + conditional_variable_test.cc + message_queue_test.cc + resource_usage_test.cc + bitstream_test.cc + data_accessor_test.cc + lock_posix_test.cc + singleton_test.cc + #posix_thread_test.cc + stl_utils_test.cc + timer_thread_test.cc + rwlock_posix_test.cc + async_runner_test.cc +) + +if (ENABLE_LOG) + list(APPEND testSources auto_trace_test.cc) + list(APPEND testSources log_message_loop_thread_test.cc) +endif() + +if (BUILD_BACKTRACE_SUPPORT) + list(APPEND testSources back_trace_test.cc) +endif() set(testLibraries gmock - gtest - Utils) + Utils +) + +file(COPY testscript.sh DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +file(COPY log4cxx.properties DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) -add_executable(utils_test ${testSources}) -target_link_libraries(utils_test ${testLibraries}) +create_test("utils_test" "${testSources}" "${testLibraries}") +endif() diff --git a/src/components/utils/test/async_runner_test.cc b/src/components/utils/test/async_runner_test.cc new file mode 100644 index 000000000..38606c15a --- /dev/null +++ b/src/components/utils/test/async_runner_test.cc @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdlib.h> +#include <ctime> +#include "lock.h" +#include "threads/async_runner.h" +#include "utils/conditional_variable.h" + +#include "gtest/gtest.h" + +namespace test { +namespace components { +namespace utils { + +using namespace sync_primitives; +using namespace threads; + +namespace { +uint32_t check_value = 0; +} + +// ThreadDelegate successor +class TestThreadDelegate : public ThreadDelegate { + public: + void threadMain() { + ++check_value; + } +}; + +class AsyncRunnerTest : public ::testing::Test { + public: + AsyncRunnerTest() + : kDelegatesNum_(1), + asr_pt_(NULL) { + CreateAsyncRunner(); + CreateThreadsArray(); + } + + ~AsyncRunnerTest() { + DeleteAsyncRunner(); + DeleteThreadsArray(); + } + + protected: + Lock test_lock_; + uint32_t kDelegatesNum_; + ConditionalVariable cond_var_; + TestThreadDelegate **delegates_; + AsyncRunner *asr_pt_; + + void CreateThreadsArray() { + srand(std::time(NULL)); + kDelegatesNum_ = (rand() % 20 + 1); + delegates_ = new TestThreadDelegate*[kDelegatesNum_]; + } + + void DeleteThreadsArray() { + delete[] delegates_; + } + + void CreateAsyncRunner() { + asr_pt_ = new AsyncRunner("test"); + } + void DeleteAsyncRunner() { + delete asr_pt_; + } +}; + +TEST_F(AsyncRunnerTest, ASyncRunManyDelegates_ExpectSuccessfulAllDelegatesRun) { + AutoLock lock(test_lock_); + // Clear global value before test + check_value = 0; + // Create Delegates and run + for (unsigned int i = 0; i < kDelegatesNum_; ++i) { + delegates_[i] = new TestThreadDelegate(); + asr_pt_->AsyncRun(delegates_[i]); + } + // Wait for 2 secs. Give this time to delegates to be run + cond_var_.WaitFor(lock, 2000); + // Expect all delegates run successfully + EXPECT_EQ(kDelegatesNum_, check_value); +} + +TEST_F(AsyncRunnerTest, RunManyDelegatesAndStop_ExpectSuccessfulDelegatesStop) { + AutoLock lock(test_lock_); + // Clear global value before test + check_value = 0; + // Create Delegates + for (unsigned int i = 0; i < kDelegatesNum_; ++i) { + delegates_[i] = new TestThreadDelegate(); + } + // Wait for 2 secs + cond_var_.WaitFor(lock, 2000); + // Run created delegates + for (unsigned int i = 0; i < kDelegatesNum_; ++i) { + if (kDelegatesNum_ > 1) { + if (i == kDelegatesNum_ / 2) { + asr_pt_->Stop(); + } + } + asr_pt_->AsyncRun(delegates_[i]); + } + // Expect 3 delegates run successlully. The other stopped. + EXPECT_EQ(kDelegatesNum_ / 2, check_value); +} + +} // namespace utils +} // namespace components +} // namespace test + diff --git a/src/components/utils/test/auto_trace_test.cc b/src/components/utils/test/auto_trace_test.cc new file mode 100644 index 000000000..71e0f4376 --- /dev/null +++ b/src/components/utils/test/auto_trace_test.cc @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gtest/gtest.h" +#include "utils/auto_trace.h" +#include "logger.h" +#include <fstream> + +namespace test { +namespace components { +namespace utils { + +using namespace ::logger; + +CREATE_LOGGERPTR_GLOBAL(logger_, "AutoTraceTestLog"); + +void Preconditions() { + //delete file with previous logs + const char* file_name = "AutoTraceTestLogFile.log"; + std::remove(file_name); +} + +void InitLogger() { + INIT_LOGGER("log4cxx.properties"); +} + +void CreateDeleteAutoTrace(const std::string & testlog) { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_DEBUG(logger_, testlog); +} + +bool CheckTraceInFile(const std::string & testlog) { + + bool isLogFound = false; + std::string line; + + std::ifstream file_log("AutoTraceTestLogFile.log"); + + if (file_log.is_open()) { + while (getline(file_log, line)) { + std::size_t found = line.find(testlog); + std::size_t founddebug = line.find("DEBUG"); + if ((found != std::string::npos) && (founddebug != std::string::npos)) { + isLogFound = true; + break; + } + } + file_log.close(); + } else { + std::cout << "file cannot be opened \n"; + } + return isLogFound; +} + +void DeinitLogger() { + DEINIT_LOGGER(); +} + +TEST(AutoTraceTest, Basic) { + const std::string testlog = + "Test trace is working!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"; + Preconditions(); + InitLogger(); + CreateDeleteAutoTrace(testlog); + DeinitLogger(); + + ASSERT_TRUE(CheckTraceInFile(testlog)); +} + +} // namespace utils +} // namespace components +} // namespace test diff --git a/src/components/utils/test/back_trace_test.cc b/src/components/utils/test/back_trace_test.cc new file mode 100644 index 000000000..12d5df81f --- /dev/null +++ b/src/components/utils/test/back_trace_test.cc @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gtest/gtest.h" +#include "utils/back_trace.h" + +namespace test { +namespace components { +namespace utils { + +using namespace ::utils; + +TEST(BackTraceTest, CallStackShouldNotBeEmpty) { + + //arrange + Backtrace newtrace = Backtrace(); + std::vector < std::string > symbols = newtrace.CallStack(); + //assert + ASSERT_FALSE(symbols.empty()); +} + +} // namespace utils +} // namespace components +} // namespace test diff --git a/src/components/utils/test/bitstream_test.cc b/src/components/utils/test/bitstream_test.cc new file mode 100644 index 000000000..07a80bde0 --- /dev/null +++ b/src/components/utils/test/bitstream_test.cc @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <unistd.h> +#include "gtest/gtest.h" +#include "utils/macro.h" +#include "utils/bitstream.h" + +namespace test { +namespace components { +namespace utils { + +using ::utils::BitStream; + +TEST(BitstreamTest, CreateBitstream_WithDataWithDatasize_BitStreamIsGood) { + + //arrange + uint8_t data = 10; + size_t bits = 2; + BitStream bs(&data, bits); + + //assert + EXPECT_TRUE(bs.IsGood()); +} + +TEST(BitstreamTest, ExtractBitstreamInUint8_ExtractAllData_BitStreamIsGoodDataExtractedCorrectly) { + + //arrange + uint8_t data = 10; + size_t bits = 2; + BitStream bs(&data, bits); + + uint8_t extract_data = 0; + Extract(&bs, &extract_data); + + //assert + EXPECT_TRUE(bs.IsGood()); + + EXPECT_EQ(data, extract_data); +} + +TEST(BitstreamTest, ExtractBitstreamInUint8_WithDataWithZeroSize_BitStreamIsBad) { + + //arrange + uint8_t data = 10; + size_t bits = 0; + BitStream bs(&data, bits); + + uint8_t extract_data = 0; + Extract(&bs, &extract_data); + + //assert + EXPECT_TRUE(bs.IsBad()); +} + +TEST(BitstreamTest, ExtractBitstreamInUint32_WithDatasizeEq4_BitStreamIsGoodDataExtractedCorrectly) { + + //arrange + uint8_t data = 10; + size_t bits = 4; + BitStream bs(&data, bits); + + uint32_t extract_data = 0; + Extract(&bs, &extract_data); + + //assert + EXPECT_TRUE(bs.IsGood()); + +} + +TEST(BitstreamTest, ExtractBitstreamInUint32_DatasizeLess4_BitStreamIsBad) { + + //arrange + uint8_t data = 10; + size_t bits = 3; + BitStream bs(&data, bits); + + uint32_t extract_data = 0; + Extract(&bs, &extract_data); + + //assert + EXPECT_TRUE(bs.IsBad()); + +} + +TEST(BitstreamTest, ExtractFullBitstream_WithDataWithDatasize_BitStreamIsGood) { + + //arrange + uint8_t data = 10; + size_t bits = 8; + BitStream bs(&data, bits); + + uint8_t extract_data = 0; + + Extract(&bs, &extract_data, bits); + + //assert + EXPECT_TRUE(bs.IsGood()); + + EXPECT_EQ(data, extract_data); +} + +TEST(BitstreamTest, ExtractBitstreamInString_WithDataWithDatasize_BitStreamIsGood) { + + //arrange + uint8_t data = 10; + size_t bits = 2; + BitStream bs(&data, bits); + + std::string strdata = ""; + size_t length = strdata.length(); + + Extract(&bs, &strdata, length); + + //assert + EXPECT_TRUE(bs.IsGood()); +} + +TEST(BitstreamTest, CreateBitstream_NoDataZeroDatasize_BitStreamIsGood) { + + //arrange + uint8_t *data = NULL; + size_t bits = 0; + BitStream bs(data, bits); + + //assert + EXPECT_TRUE(bs.IsGood()); +} + +TEST(BitstreamTest, CreateBitstream_NoDataWithUpperboundDataSize_BitStreamIsGood) { + + //arrange + uint8_t *data = NULL; + size_t bits = 65535; + BitStream bs(data, bits); + + //assert + EXPECT_TRUE(bs.IsGood()); +} + +TEST(BitstreamTest, CreateBitstream_WithUpperboundDataWithLessDataSize_BitStreamIsGood) { + + //arrange + uint8_t data = 255; + size_t bits = sizeof(char); + BitStream bs(&data, bits); + + //assert + EXPECT_TRUE(bs.IsGood()); +} + +TEST(BitstreamTest, ExtractBitstream_WithUpperboundDataWithLessDataSize_BitStreamIsGood) { + + //arrange + uint8_t data = 255; + size_t bits = sizeof(char); + BitStream bs(&data, bits); + + uint8_t extract_data = 0; + Extract(&bs, &extract_data, bits); + + //assert + EXPECT_TRUE(bs.IsGood()); +} + +TEST(BitstreamTest, ExtractBitstream_WithUpperboundDataWithZeroDataSize_BitStreamIsGood) { + + //arrange + uint8_t data = 255; + size_t bits = 0; + BitStream bs(&data, bits); + + uint8_t extract_data = 0; + Extract(&bs, &extract_data, bits); + + //assert + EXPECT_TRUE(bs.IsGood()); +} + +TEST(BitstreamTest, ExtractBitstream_WithDataMarkedBad_ExpectIsBad) { + + //arrange + uint8_t data = 255; + size_t bits = sizeof(int); + BitStream bs(&data, bits); + //assert + EXPECT_TRUE(bs.IsGood()); + //act + bs.MarkBad(); + + //assert + EXPECT_TRUE(bs.IsBad()); + //act + Extract(&bs, &data, bits); + //arrange + EXPECT_TRUE(bs.IsBad()); +} + +} // namespace utils +} // namespace components +} // namespace test diff --git a/src/components/utils/test/conditional_variable_test.cc b/src/components/utils/test/conditional_variable_test.cc new file mode 100644 index 000000000..a898732ff --- /dev/null +++ b/src/components/utils/test/conditional_variable_test.cc @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <pthread.h> +#include <iostream> + +#include "lock.h" +#include "macro.h" + +#include "gtest/gtest.h" +#include "utils/conditional_variable.h" + +namespace test { +namespace components { +namespace utils { + +class ConditionalVariableTest : public ::testing::Test { + public: + ConditionalVariableTest() + : test_value_("initialized"), + counter_(0) { + } + void check_counter(); + void task_one(); + + static void* check_counter_helper(void *context) { + (reinterpret_cast<ConditionalVariableTest *>(context))->check_counter(); + return NULL; + } + + static void* task_one_helper(void *context) { + (reinterpret_cast<ConditionalVariableTest *>(context))->task_one(); + return NULL; + } + protected: + std::string test_value_; + sync_primitives::ConditionalVariable cond_var_; + sync_primitives::Lock test_mutex_; + unsigned counter_; +}; + +// Defines threads behaviour which depends on counter value +void ConditionalVariableTest::check_counter() { + sync_primitives::AutoLock test_lock(test_mutex_); + if (counter_ <= 1) { + counter_++; + cond_var_.Wait(test_mutex_); // Mutex unlock & Thread sleeps until Notification + } + else if(counter_ == 2) { // Checking for equal 2 in this specific case. Because we were waiting for 2 threads to be finished + cond_var_.Broadcast(); // Notify All threads waiting on conditional variable + } +} + +// Tasks for threads to begin with +void ConditionalVariableTest::task_one() { + sync_primitives::AutoLock test_lock(test_mutex_); + test_value_ = "changed by thread 1"; + cond_var_.NotifyOne(); // Notify At least one thread waiting on conditional variable + test_value_ = "changed again by thread 1"; +} + +TEST_F(ConditionalVariableTest, CheckNotifyOne_OneThreadNotified_ExpectSuccessful) { + pthread_t thread1; + sync_primitives::AutoLock test_lock(test_mutex_); + test_value_ = "changed by main thread"; + const bool thread_created = pthread_create(&thread1, + NULL, + &ConditionalVariableTest::task_one_helper, + this); + ASSERT_FALSE(thread_created) << "thread1 is not created!"; + test_value_ = "changed twice by main thread"; + cond_var_.WaitFor(test_lock, 2000); + std::string last_value("changed again by thread 1"); + EXPECT_EQ(last_value, test_value_); +} + +TEST_F(ConditionalVariableTest, CheckBroadcast_AllThreadsNotified_ExpectSuccessful) { + pthread_t thread1; + pthread_t thread2; + bool thread_created = pthread_create(&thread1, + NULL, + &ConditionalVariableTest::check_counter_helper, + this); + ASSERT_FALSE(thread_created) << "thread1 is not created!"; + thread_created = pthread_create(&thread2, + NULL, + &ConditionalVariableTest::check_counter_helper, + this); + ASSERT_FALSE(thread_created) << "thread2 is not created!"; + check_counter(); + EXPECT_EQ(2u, counter_); +} + +TEST_F(ConditionalVariableTest, CheckWaitForWithTimeout1sec_ThreadBlockedForTimeout_ExpectSuccessfulWakeUp) { + sync_primitives::AutoLock test_lock(test_mutex_); + sync_primitives::ConditionalVariable::WaitStatus wait_st = cond_var_.WaitFor(test_lock, 1000); + EXPECT_EQ(sync_primitives::ConditionalVariable::kTimeout, wait_st); +} + +} // namespace utils +} // namespace components +} // namespace test + diff --git a/src/components/utils/test/data_accessor_test.cc b/src/components/utils/test/data_accessor_test.cc new file mode 100644 index 000000000..105ec8517 --- /dev/null +++ b/src/components/utils/test/data_accessor_test.cc @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gtest/gtest.h" +#include "utils/data_accessor.h" +#include "utils/lock.h" + +namespace test { +namespace components { +namespace utils { + +TEST(DataAccessorTest, CreateDataAccessor) { + + //arrange + int test_value = 10; + sync_primitives::Lock testSet_lock_; + DataAccessor<int> testdata(test_value, testSet_lock_); + int data_from_testdata = testdata.GetData(); + + //assert + EXPECT_EQ(test_value, data_from_testdata); +} + +TEST(DataAccessorTest, CreateDataAccessor_MutexIsLocked_CannotLockItAgain) { + + //arrange + int test_value = 10; + sync_primitives::Lock testSet_lock_; + DataAccessor<int> testdata(test_value, testSet_lock_); + + //assert + EXPECT_FALSE(testSet_lock_.Try()); +} + +TEST(DataAccessorTest, CopyDataAccessor_GetDataFromDataAccessors) { + + //arrange + int test_value = 10; + sync_primitives::Lock testSet_lock_; + DataAccessor<int> testdata(test_value, testSet_lock_); + DataAccessor<int> testdata_copy(testdata); + + int data_from_testdata = testdata.GetData(); + int data_from_testdata_copy = testdata_copy.GetData(); + + //assert + EXPECT_EQ(data_from_testdata, data_from_testdata_copy); + + EXPECT_FALSE(testSet_lock_.Try()); +} + +TEST(DataAccessorTest,ChangedDataInDataAccessor_ChangeData_DataInDataAccessorIsChanged) { + + //arrange + int test_value = 10; + sync_primitives::Lock testSet_lock_; + DataAccessor<int> testdata(test_value, testSet_lock_); + test_value = 0; + + int data_from_testdata_after_change = testdata.GetData(); + + //assert + EXPECT_EQ(test_value, data_from_testdata_after_change); +} + +TEST(DataAccessorTest, DeleteDataAccessor_CreatedOneDeleteOneThread_MutexIsUnlocked) { + + //arrange + int test_value = 10; + sync_primitives::Lock testSet_lock_; + { + DataAccessor<int> testdata(test_value, testSet_lock_); + + //assert + EXPECT_FALSE(testSet_lock_.Try()); + } + //assert + + EXPECT_TRUE(testSet_lock_.Try()); + + testSet_lock_.Release(); + +} + +TEST(DataAccessorTest, DeleteDataAccessor_CreatedThreadAndCopyDeleteBothThreads_MutexIsUnlocked) { + + //arrange + int test_value = 10; + sync_primitives::Lock testSet_lock_; + { + DataAccessor<int> testdata(test_value, testSet_lock_); + { + DataAccessor<int> testdata_copy(testdata); + + //assert + EXPECT_FALSE(testSet_lock_.Try()); + } + //assert + EXPECT_FALSE(testSet_lock_.Try()); + + } + + //assert + EXPECT_TRUE(testSet_lock_.Try()); + testSet_lock_.Release(); + +} + +} // namespace utils +} // namespace components +} // namespace test diff --git a/src/components/utils/test/date_time_test.cc b/src/components/utils/test/date_time_test.cc index ddcf679a1..b437bdc17 100644 --- a/src/components/utils/test/date_time_test.cc +++ b/src/components/utils/test/date_time_test.cc @@ -1,126 +1,326 @@ /* -* Copyright (c) 2014, Ford Motor Company -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following -* disclaimer in the documentation and/or other materials provided with the -* distribution. -* -* Neither the name of the Ford Motor Company nor the names of its contributors -* may be used to endorse or promote products derived from this software -* without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -*/ - -#include <unistd.h> + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ #include "gtest/gtest.h" -#include "gmock/gmock.h" - #include "utils/date_time.h" -namespace test { -namespace components { -namespace utils { +namespace test { +namespace components { +namespace utils { +using namespace date_time; TEST(DateTimeTest, GetCurrentTime) { + + //arrange const TimevalStruct time1 = date_time::DateTime::getCurrentTime(); + + //assert ASSERT_NE(0, time1.tv_sec); ASSERT_GE(time1.tv_usec, 0); + //act const TimevalStruct time2 = date_time::DateTime::getCurrentTime(); + + //assert ASSERT_NE(0, time2.tv_sec); ASSERT_GE(time2.tv_usec, 0); - ASSERT_GE(time2.tv_sec, time1.tv_sec); + ASSERT_GE(time2.tv_sec, time1.tv_sec); +} + +TEST(DateTimeTest, GetSecs) { + //arrange + TimevalStruct time; + time.tv_sec = 1; + time.tv_usec = 2 * date_time::DateTime::MICROSECONDS_IN_MILLISECONDS; + + //assert + ASSERT_EQ(1, date_time::DateTime::getSecs(time)); } TEST(DateTimeTest, GetmSecs) { + //arrange TimevalStruct time; - time.tv_sec = 1; + time.tv_sec = 1; time.tv_usec = 2 * date_time::DateTime::MICROSECONDS_IN_MILLISECONDS; - ASSERT_EQ(time.tv_sec * date_time::DateTime::MILLISECONDS_IN_SECOND + - time.tv_usec / date_time::DateTime::MICROSECONDS_IN_MILLISECONDS, - date_time::DateTime::getmSecs(time)); + int64_t expect_value = time.tv_sec + * date_time::DateTime::MILLISECONDS_IN_SECOND + + time.tv_usec / date_time::DateTime::MICROSECONDS_IN_MILLISECONDS; + //assert + ASSERT_EQ(expect_value, date_time::DateTime::getmSecs(time)); } TEST(DateTimeTest, GetuSecs) { + //arrange TimevalStruct time; - time.tv_sec = 3; + time.tv_sec = 3; time.tv_usec = 4; - ASSERT_EQ(time.tv_sec * date_time::DateTime::MILLISECONDS_IN_SECOND * - date_time::DateTime::MICROSECONDS_IN_MILLISECONDS + time.tv_usec, - date_time::DateTime::getuSecs(time)); + int64_t expect_value = time.tv_sec + * date_time::DateTime::MILLISECONDS_IN_SECOND + * date_time::DateTime::MICROSECONDS_IN_MILLISECONDS + time.tv_usec; + //assert + ASSERT_EQ(expect_value, date_time::DateTime::getuSecs(time)); } TEST(DateTimeTest, GetuSecsmSecs) { + //arrange TimevalStruct time; - time.tv_sec = 5; + time.tv_sec = 5; time.tv_usec = 6; - ASSERT_EQ( date_time::DateTime::getmSecs(time), - date_time::DateTime::getuSecs(time) / date_time::DateTime::MICROSECONDS_IN_MILLISECONDS); + int64_t expect_value = date_time::DateTime::getuSecs(time) + / date_time::DateTime::MICROSECONDS_IN_MILLISECONDS; + + //assert + ASSERT_EQ(expect_value, date_time::DateTime::getmSecs(time)); } TEST(DateTimeTest, CalculateTimeSpan) { + //arrange const TimevalStruct time = date_time::DateTime::getCurrentTime(); const uint32_t sleep_time_mSec = 10; usleep(sleep_time_mSec * date_time::DateTime::MICROSECONDS_IN_MILLISECONDS); - ASSERT_GE(date_time::DateTime::calculateTimeSpan(time), - sleep_time_mSec); + //assert + ASSERT_GE(date_time::DateTime::calculateTimeSpan(time), sleep_time_mSec); } TEST(DateTimeTest, CalculateTimeDiff) { + + //arrange TimevalStruct time1; - time1.tv_sec = 1; + time1.tv_sec = 1; time1.tv_usec = 2 * date_time::DateTime::MICROSECONDS_IN_MILLISECONDS; TimevalStruct time2; - time2.tv_sec = 3; + time2.tv_sec = 3; time2.tv_usec = 4 * date_time::DateTime::MICROSECONDS_IN_MILLISECONDS; //time2 to time1 TimevalStruct diff1; - diff1.tv_sec = time2.tv_sec - time1.tv_sec; + diff1.tv_sec = time2.tv_sec - time1.tv_sec; diff1.tv_usec = time2.tv_usec - time1.tv_usec; const int64_t mSecDiff = static_cast<int64_t>(diff1.tv_sec) * 1000 + diff1.tv_usec / 1000; - ASSERT_EQ(mSecDiff, - date_time::DateTime::calculateTimeDiff(time2, time1)); + //assert + ASSERT_EQ(mSecDiff, date_time::DateTime::calculateTimeDiff(time2, time1)); //time1 to time2 TimevalStruct diff2; - diff2.tv_sec = time1.tv_sec - time2.tv_sec; + diff2.tv_sec = time1.tv_sec - time2.tv_sec; diff2.tv_usec = time1.tv_usec - time2.tv_usec; const int64_t mSecDiff2 = -(static_cast<int64_t>(diff2.tv_sec) * 1000 + diff2.tv_usec / 1000); - ASSERT_EQ(mSecDiff2, - date_time::DateTime::calculateTimeDiff(time1, time2)); + //assert + ASSERT_EQ(mSecDiff2, date_time::DateTime::calculateTimeDiff(time1, time2)); +} + +TEST(DateTimeTest, CalculateEqualTimeDiff) { + TimevalStruct time1; + time1.tv_sec = 1; + time1.tv_usec = 2 * date_time::DateTime::MICROSECONDS_IN_MILLISECONDS; + + TimevalStruct time2; + time2.tv_sec = 1; + time2.tv_usec = 2 * date_time::DateTime::MICROSECONDS_IN_MILLISECONDS; + + ASSERT_EQ(0, date_time::DateTime::calculateTimeDiff(time2, time1)); + ASSERT_EQ(0, date_time::DateTime::calculateTimeDiff(time1, time2)); +} + +TEST(DateTimeTest, compareTime) { + + //arrange + TimevalStruct time1; + time1.tv_sec = 1; + time1.tv_usec = 2 * date_time::DateTime::MICROSECONDS_IN_MILLISECONDS; + + TimevalStruct time2; + time2.tv_sec = 2; + time2.tv_usec = 4 * date_time::DateTime::MICROSECONDS_IN_MILLISECONDS; + + //assert + ASSERT_EQ(LESS, date_time::DateTime::compareTime(time1, time2)); + ASSERT_EQ(GREATER, date_time::DateTime::compareTime(time2, time1)); + ASSERT_NE(EQUAL, date_time::DateTime::compareTime(time2, time1)); + + //act + TimevalStruct time3 = date_time::DateTime::Sub(time2, time1); + + //assert + ASSERT_EQ(EQUAL, date_time::DateTime::compareTime(time1, time3)); +} + +//TODO(VVeremjova) APPLINK-11051 Missing convertation microseconds in seconds + +TEST(DateTimeTest, DISABLED_GetSecs_UsecConvertedInSec) { + //arrange + TimevalStruct time1; + time1.tv_sec = 0; + time1.tv_usec = date_time::DateTime::MICROSECONDS_IN_SECOND; + + //assert + ASSERT_EQ(1, date_time::DateTime::getSecs(time1)); +} + +TEST(DateTimeTest, DISABLED_compareTime_UsecConvertedInSec) { + //arrange + TimevalStruct time1; + time1.tv_sec = 1; + time1.tv_usec = 0; + + TimevalStruct time2; + time2.tv_sec = 0; + time2.tv_usec = date_time::DateTime::MICROSECONDS_IN_SECOND; + + //assert + ASSERT_EQ(1, date_time::DateTime::getSecs(time1)); + ASSERT_EQ(1, date_time::DateTime::getSecs(time2)); + ASSERT_EQ(EQUAL, date_time::DateTime::compareTime(time1, time2)); +} + +TEST(DateTimeTest, DISABLED_compareEqualTime_UsecConvertedInSec) { + //arrange + TimevalStruct time1; + time1.tv_sec = 1; + time1.tv_usec = 0; + + TimevalStruct time2; + time2.tv_sec = 0; + time2.tv_usec = date_time::DateTime::MICROSECONDS_IN_SECOND; + + //assert + ASSERT_TRUE(date_time::DateTime::Equal(time1, time2)); +} + +TEST(DateTimeTest, DISABLED_compareLessTime_UsecConvertedInSec) { + //arrange + TimevalStruct time1; + time1.tv_sec = 1; + time1.tv_usec = 0; + + TimevalStruct time2; + time2.tv_sec = 0; + time2.tv_usec = 2 * date_time::DateTime::MICROSECONDS_IN_SECOND; + + //assert + ASSERT_TRUE(date_time::DateTime::Less(time1, time2)); +} + +TEST(DateTimeTest, DISABLED_compareGreaterTime_UsecConvertedInSec) { + //arrange + TimevalStruct time1; + time1.tv_sec = 1; + time1.tv_usec = 0; + + TimevalStruct time2; + time2.tv_sec = 0; + time2.tv_usec = 2 * date_time::DateTime::MICROSECONDS_IN_SECOND; + + //assert + ASSERT_TRUE(date_time::DateTime::Greater(time2, time1)); +} + +TEST(DateTimeTest, DISABLED_CalculateTimeSub_UsecConvertedInSec) { + //arrange + TimevalStruct time1; + time1.tv_sec = 1; + time1.tv_usec = 0; + + TimevalStruct time2; + time2.tv_sec = 0; + time2.tv_usec = 2 * date_time::DateTime::MICROSECONDS_IN_SECOND; + + TimevalStruct time3 = date_time::DateTime::Sub(time2, time1); + + //assert + ASSERT_EQ(EQUAL, date_time::DateTime::compareTime(time1, time3)); +} + +TEST(DateTimeTest, DISABLED_CalculateTimeDiff_UsecConvertedInSec) { + //arrange + TimevalStruct time1; + time1.tv_sec = 2; + time1.tv_usec = 5 * date_time::DateTime::MICROSECONDS_IN_SECOND; + + TimevalStruct time2; + time2.tv_sec = 3; + time2.tv_usec = 1 * date_time::DateTime::MICROSECONDS_IN_SECOND; + + //assert + ASSERT_EQ(3000, date_time::DateTime::calculateTimeDiff(time2, time1)); + ASSERT_EQ(3000, date_time::DateTime::calculateTimeDiff(time1, time2)); +} + +TEST(DateTimeTest, DISABLED_CalculateEqualTimeDiff_UsecConvertedInSec) { + //arrange + TimevalStruct time1; + time1.tv_sec = 2; + time1.tv_usec = 2 * date_time::DateTime::MICROSECONDS_IN_SECOND; + + TimevalStruct time2; + time2.tv_sec = 3; + time2.tv_usec = 1 * date_time::DateTime::MICROSECONDS_IN_SECOND; + + //assert + ASSERT_EQ(0, date_time::DateTime::calculateTimeDiff(time2, time1)); + ASSERT_EQ(0, date_time::DateTime::calculateTimeDiff(time1, time2)); +} + +TEST(DateTimeTest, DISABLED_CalculateEqualTimeSub_UsecConvertedInSec) { + //arrange + TimevalStruct time1; + time1.tv_sec = 3; + time1.tv_usec = 0; + + TimevalStruct time2; + time2.tv_sec = 2; + time2.tv_usec = 1 * date_time::DateTime::MICROSECONDS_IN_SECOND; + + TimevalStruct time3 = date_time::DateTime::Sub(time2, time1); + TimevalStruct time4 = date_time::DateTime::Sub(time1, time2); + + TimevalStruct time_expected; + time_expected.tv_sec = 0; + + //assert + ASSERT_EQ(EQUAL, date_time::DateTime::compareTime(time_expected, time3)); + ASSERT_EQ(EQUAL, date_time::DateTime::compareTime(time_expected, time4)); } } // namespace utils diff --git a/src/components/utils/test/file_system_test.cc b/src/components/utils/test/file_system_test.cc index abf09735b..54a662c51 100644 --- a/src/components/utils/test/file_system_test.cc +++ b/src/components/utils/test/file_system_test.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Ford Motor Company + * Copyright (c) 2015, Ford Motor Company * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,82 +30,1146 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "gmock/gmock.h" +#include <algorithm> +#include <fstream> +#include "gtest/gtest.h" #include "utils/file_system.h" -namespace test { -namespace components { -namespace utils { +namespace test { +namespace components { +namespace utils { -TEST(FileSystemTest, CommonFileSystemTest) { - // Directory creation - ASSERT_FALSE(file_system::DirectoryExists("./Test directory")); +using namespace file_system; - file_system::CreateDirectory("./Test directory"); +TEST(FileSystemTest, CreateDeleteDirectory) { - ASSERT_TRUE(file_system::DirectoryExists("./Test directory")); + ASSERT_FALSE(DirectoryExists("./Test directory")); + // Directory creation + CreateDirectory("./Test directory"); - ASSERT_TRUE(file_system::IsDirectory("./Test directory")); + EXPECT_TRUE(DirectoryExists("./Test directory")); + EXPECT_TRUE(IsDirectory("./Test directory")); + // Directory removing + EXPECT_TRUE(RemoveDirectory("./Test directory", false)); + EXPECT_FALSE(DirectoryExists("./Test directory")); +} + +TEST(FileSystemTest, CreateDirectoryTwice) { + ASSERT_FALSE(DirectoryExists("./Test directory")); + // Directory creation + CreateDirectory("./Test directory"); + + EXPECT_TRUE(DirectoryExists("./Test directory")); + EXPECT_TRUE(IsDirectory("./Test directory")); + + // Create directory second time + CreateDirectory("./Test directory"); + EXPECT_TRUE(DirectoryExists("./Test directory")); + + // Directory removing + EXPECT_TRUE(RemoveDirectory("./Test directory", false)); + //try delete directory again + EXPECT_FALSE(RemoveDirectory("./Test directory", false)); + EXPECT_FALSE(DirectoryExists("./Test directory")); +} + +TEST(FileSystemTest,DeleteDirectoryRecursively) { + ASSERT_FALSE(DirectoryExists("./Test directory")); + // Create directories + CreateDirectory("./Test directory"); + CreateDirectory("./Test directory/Test directory 2"); + + // Create file inside directory + EXPECT_TRUE(CreateFile("./Test directory/test file")); + + EXPECT_FALSE(RemoveDirectory("./Test directory", false)); + EXPECT_TRUE(DirectoryExists("./Test directory")); + EXPECT_TRUE(IsDirectory("./Test directory")); + + EXPECT_TRUE(RemoveDirectory("./Test directory", true)); + EXPECT_FALSE(DirectoryExists("./Test directory")); +} + +TEST(FileSystemTest, CreateDirectoryRecursivelyDeleteRecursively) { + ASSERT_FALSE(DirectoryExists("./Test directory")); + // Create directories recursively + CreateDirectoryRecursively( + "./Test directory/Test directory 2/Test directory 3"); + + EXPECT_TRUE(DirectoryExists("./Test directory")); + EXPECT_TRUE(IsDirectory("./Test directory")); + + EXPECT_TRUE(DirectoryExists("./Test directory/Test directory 2")); + EXPECT_TRUE(IsDirectory("./Test directory/Test directory 2")); + + EXPECT_TRUE( + DirectoryExists("./Test directory/Test directory 2/Test directory 3")); + EXPECT_TRUE( + IsDirectory("./Test directory/Test directory 2/Test directory 3")); + + // Delete recursively + EXPECT_TRUE(RemoveDirectory("./Test directory", true)); + EXPECT_FALSE(DirectoryExists("./Test directory")); + EXPECT_FALSE(DirectoryExists("./Test directory/Test directory 2")); + EXPECT_FALSE( + DirectoryExists("./Test directory/Test directory 2/Test directory 3")); +} + +TEST(FileSystemTest, TwiceCreateDirectoryRecursivelyDeleteRecursivelyOnce) { + ASSERT_FALSE(DirectoryExists("./Test directory")); + // Create directories recursively + EXPECT_TRUE( + CreateDirectoryRecursively( + "./Test directory/Test directory 2/Test directory 3")); + + // Check that all directories are created + EXPECT_TRUE(DirectoryExists("./Test directory")); + EXPECT_TRUE(IsDirectory("./Test directory")); + + EXPECT_TRUE(DirectoryExists("./Test directory/Test directory 2")); + EXPECT_TRUE(IsDirectory("./Test directory/Test directory 2")); + + EXPECT_TRUE( + DirectoryExists("./Test directory/Test directory 2/Test directory 3")); + EXPECT_TRUE( + IsDirectory("./Test directory/Test directory 2/Test directory 3")); + + // Create directories recursively second time + EXPECT_TRUE( + CreateDirectoryRecursively( + "./Test directory/Test directory 2/Test directory 3")); + + EXPECT_TRUE(DirectoryExists("./Test directory")); + + EXPECT_TRUE(DirectoryExists("./Test directory/Test directory 2")); + + EXPECT_TRUE( + DirectoryExists("./Test directory/Test directory 2/Test directory 3")); + + // Delete recursively + EXPECT_TRUE(RemoveDirectory("./Test directory", true)); + EXPECT_FALSE(DirectoryExists("./Test directory")); + // Delete recursively again is impossible + EXPECT_FALSE(RemoveDirectory("./Test directory", true)); + + EXPECT_FALSE(DirectoryExists("./Test directory")); + EXPECT_FALSE(DirectoryExists("./Test directory/Test directory 2")); + EXPECT_FALSE( + DirectoryExists("./Test directory/Test directory 2/Test directory 3")); +} + +TEST(FileSystemTest, CreateDeleteFile) { + ASSERT_FALSE(FileExists("./test file")); // File creation - ASSERT_FALSE(file_system::FileExists("./Test directory/test file")); + EXPECT_TRUE(CreateFile("./test file")); + EXPECT_FALSE(IsDirectory("./test file")); - std::vector<unsigned char> data; - data.push_back('t'); - data.push_back('e'); - data.push_back('s'); - data.push_back('t'); + // Delete file + EXPECT_TRUE(DeleteFile("./test file")); + //try delete file again + EXPECT_FALSE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, CheckIsDirectory) { + ASSERT_FALSE(DirectoryExists("./Test directory")); + // Create directory and check that IsDirectory=true + CreateDirectory("./Test directory"); + EXPECT_TRUE(IsDirectory("./Test directory")); + + // Delete directory and check, that IsDirectory=false + EXPECT_TRUE(RemoveDirectory("./Test directory", false)); + EXPECT_FALSE(DirectoryExists("./Test directory")); + EXPECT_FALSE(IsDirectory("./Test directory")); + + // Create file and check that IsDirectory=false + ASSERT_FALSE(FileExists("./test file")); + EXPECT_TRUE(CreateFile("./test file")); + EXPECT_FALSE(IsDirectory("./test file")); + + // Delete file and check that IsDirectory=false + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); + EXPECT_FALSE(IsDirectory("./test file")); +} - ASSERT_TRUE(file_system::Write("./Test directory/test file", data)); +TEST(FileSystemTest, CreateFileTwice) { + ASSERT_FALSE(FileExists("./test file")); - ASSERT_TRUE(file_system::FileExists("./Test directory/test file")); + // Create file first time + EXPECT_TRUE(CreateFile("./test file")); + EXPECT_TRUE(FileExists("./test file")); - ASSERT_FALSE(file_system::IsDirectory("./Test directory/test file")); + // Create file second time + EXPECT_TRUE(CreateFile("./test file")); + EXPECT_TRUE(FileExists("./test file")); + + // Delete file + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, CreateOpenCloseFileStream) { + ASSERT_FALSE(FileExists("./test file")); + + // Create and open file + std::ofstream* test_file = Open("./test file"); + EXPECT_TRUE(test_file->is_open()); + Close(test_file); + EXPECT_FALSE(test_file->is_open()); + delete test_file; + + EXPECT_TRUE(FileExists("./test file")); + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, CreateAndOpenFileStreamTwice) { + ASSERT_FALSE(FileExists("./test file")); + + // Create and open file + std::ofstream* test_file = Open("./test file"); + EXPECT_TRUE(test_file->is_open()); + Close(test_file); + EXPECT_FALSE(test_file->is_open()); + delete test_file; + + EXPECT_TRUE(FileExists("./test file")); + + // Create file second time + EXPECT_TRUE(CreateFile("./test file")); + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, OpenFileWriteInFileStream) { + ASSERT_FALSE(FileExists("./test file")); + + // Create and open file + std::ofstream* test_file = Open("./test file"); + EXPECT_TRUE(test_file->is_open()); + + // Write data in file + uint32_t data_size = 4; + uint8_t* data = new uint8_t[data_size]; + for (uint i = 0; i < data_size; ++i) { + data[i] = i; + } + EXPECT_TRUE(Write(test_file, data, data_size)); + Close(test_file); + EXPECT_FALSE(test_file->is_open()); + delete test_file; // Read data from file - std::vector<unsigned char> result; + std::vector < uint8_t > result; + EXPECT_TRUE(ReadBinaryFile("./test file", result)); + EXPECT_FALSE(result.empty()); + +// Check data + for (uint i = 0; i < data_size; ++i) { + EXPECT_EQ(data[i], result[i]); + } + delete data; - ASSERT_TRUE(file_system::ReadBinaryFile("./Test directory/test file", - result)); - ASSERT_FALSE(result.empty()); + // Delete file + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} - // list files - ASSERT_TRUE(file_system::Write("./Test directory/test file 2", data)); +TEST(FileSystemTest, CannotWriteInClosedFileStream) { + ASSERT_FALSE(FileExists("./test file")); - std::vector<std::string> list; - list = file_system::ListFiles("./Test directory"); + // Create and open file + std::ofstream* test_file = Open("./test file"); + EXPECT_TRUE(test_file->is_open()); + Close(test_file); + EXPECT_FALSE(test_file->is_open()); - ASSERT_FALSE(list.empty()); - std::sort(list.begin(), list.end()); - ASSERT_EQ("test file", list[0]); - ASSERT_EQ("test file 2", list[1]); + // Write data in file + uint32_t data_size = 4; + uint8_t* data = new uint8_t[data_size]; + for (uint i = 0; i < data_size; ++i) { + data[i] = i; + } + EXPECT_TRUE(Write(test_file, data, data_size)); + + delete data; + delete test_file; + + // Read data from file + std::vector < uint8_t > result; + EXPECT_TRUE(ReadBinaryFile("./test file", result)); + EXPECT_TRUE(result.empty()); // Delete file - ASSERT_TRUE(file_system::FileExists("./Test directory/test file 2")); - ASSERT_TRUE(file_system::DeleteFile("./Test directory/test file 2")); - ASSERT_FALSE(file_system::FileExists("./Test directory/test file 2")); + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, CreateWriteInFileStream_CreateFileAgain_FileRewritten) { + ASSERT_FALSE(FileExists("./test file")); + + // Create and open file + std::ofstream* test_file = Open("./test file"); + EXPECT_TRUE(test_file->is_open()); - // Delete empty directory - file_system::CreateDirectory("./Test directory/Empty directory"); + // Write data in file + uint32_t data_size = 4; + uint8_t* data = new uint8_t[data_size]; + for (uint i = 0; i < data_size; ++i) { + data[i] = i; + } + EXPECT_TRUE(Write(test_file, data, data_size)); - ASSERT_TRUE(file_system::DirectoryExists( - "./Test directory/Empty directory")); - ASSERT_TRUE(file_system::RemoveDirectory( - "./Test directory/Empty directory", false)); - ASSERT_FALSE(file_system::DirectoryExists( - "./Test directory/Empty directory")); + Close(test_file); + delete test_file; - ASSERT_FALSE(file_system::RemoveDirectory("./Test directory", false)); - ASSERT_TRUE(file_system::DirectoryExists("./Test directory")); + std::vector < uint8_t > result; + EXPECT_TRUE(ReadBinaryFile("./test file", result)); + EXPECT_FALSE(result.empty()); - // Delete directory recursively - file_system::CreateDirectory("./Test directory/Test directory 2"); - ASSERT_TRUE(file_system::Write( - "./Test directory/Test directory 2/test file 2", data)); - ASSERT_TRUE(file_system::RemoveDirectory("./Test directory", true)); + delete data; + EXPECT_TRUE(CreateFile("./test file")); - ASSERT_FALSE(file_system::DirectoryExists("./Test directory")); + // Now file is empty + EXPECT_TRUE(ReadBinaryFile("./test file", result)); + EXPECT_TRUE(result.empty()); + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); } + +TEST(FileSystemTest, CreateFileStream_WriteInFile_FileStreamNotClosed) { + ASSERT_FALSE(FileExists("./test file")); + + // Create and open file + std::ofstream* test_file = Open("./test file"); + EXPECT_TRUE(test_file->is_open()); + + // Write data in file + uint32_t data_size = 4; + std::vector < uint8_t > data; + for (uint i = 0; i < data_size; ++i) { + data.push_back(i); + } + // Write data in file + EXPECT_TRUE(Write("./test file", data)); + EXPECT_TRUE(test_file->is_open()); + + // Close filestream + Close(test_file); + delete test_file; + + std::vector < uint8_t > result; + EXPECT_TRUE(ReadBinaryFile("./test file", result)); + EXPECT_FALSE(result.empty()); + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, CreateFileStream_WriteInFileWriteInFileStream_FileIncludeLastData) { + ASSERT_FALSE(FileExists("./test file")); + + // Create and open file + std::ofstream* test_file = Open("./test file"); + EXPECT_TRUE(test_file->is_open()); + + // Write data in file + uint32_t data_size = 4; + std::vector < uint8_t > data; + for (uint i = 0; i < data_size; ++i) { + data.push_back(i); + } + // Write data in file + EXPECT_TRUE(Write("./test file", data)); + + EXPECT_TRUE(test_file->is_open()); + + // Write in filestream + uint8_t* data_2 = new uint8_t[data_size]; + for (uint i = 0; i < data_size; ++i) { + data_2[i] = i + data_size; + } + EXPECT_TRUE(Write(test_file, data_2, data_size)); + // Close filestream + Close(test_file); + + delete test_file; + std::vector < uint8_t > result; + EXPECT_TRUE(ReadBinaryFile("./test file", result)); + EXPECT_FALSE(result.empty()); + + // Check data + EXPECT_EQ(result.size(), data_size); + for (uint i = 0; i < data_size; ++i) { + EXPECT_NE(data[i], result[i]); + EXPECT_EQ(data_2[i], result[i]); + } + + delete data_2; + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, WriteInFilestreamTwice_FileRewritten) { + ASSERT_FALSE(FileExists("./test file")); + + // Create and open file + std::ofstream* test_file = Open("./test file"); + EXPECT_TRUE(test_file->is_open()); + + // Open file second time + std::ofstream* test_file_2 = Open("./test file"); + EXPECT_TRUE(test_file_2->is_open()); + + uint32_t data_size = 4; + uint8_t* data = new uint8_t[data_size]; + for (uint i = 0; i < data_size; ++i) { + data[i] = i; + } + uint8_t* data_2 = new uint8_t[data_size]; + for (uint i = 0; i < data_size; ++i) { + data_2[i] = i + 4; + } + + // Write data in file + EXPECT_TRUE(Write(test_file, data, data_size)); + + EXPECT_TRUE(Write(test_file_2, data_2, data_size)); + + Close(test_file); + Close(test_file_2); + + EXPECT_FALSE(test_file->is_open()); + EXPECT_FALSE(test_file_2->is_open()); + + delete test_file; + delete test_file_2; + // Check file + std::vector < uint8_t > result; + EXPECT_TRUE(ReadBinaryFile("./test file", result)); + EXPECT_FALSE(result.empty()); + // Check data + for (uint i = 0; i < data_size; ++i) { + EXPECT_NE(data[i], result[i]); + EXPECT_EQ(data_2[i], result[i]); + } + + delete data; + delete data_2; + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, WriteInFilestreamConsequentially_FileRewritten) { + ASSERT_FALSE(FileExists("./test file")); + + // Create and open file + std::ofstream* test_file = Open("./test file"); + EXPECT_TRUE(test_file->is_open()); + + uint32_t data_size = 4; + uint8_t* data = new uint8_t[data_size]; + for (uint i = 0; i < data_size; ++i) { + data[i] = i; + } + + // Write data in file + EXPECT_TRUE(Write(test_file, data, data_size)); + + Close(test_file); + EXPECT_FALSE(test_file->is_open()); + + // Open file second time + std::ofstream* test_file_2 = Open("./test file"); + EXPECT_TRUE(test_file_2->is_open()); + + // Write second time + uint8_t* data_2 = new uint8_t[data_size]; + for (uint i = 0; i < data_size; ++i) { + data_2[i] = i + 4; + } + EXPECT_TRUE(Write(test_file_2, data_2, data_size)); + + Close(test_file_2); + EXPECT_FALSE(test_file_2->is_open()); + + delete test_file; + delete test_file_2; + // Check file + std::vector < uint8_t > result; + EXPECT_TRUE(ReadBinaryFile("./test file", result)); + EXPECT_FALSE(result.empty()); + + // Check data + EXPECT_EQ(result.size(), data_size); + for (uint i = 0; i < data_size; ++i) { + EXPECT_NE(data[i], result[i]); + EXPECT_EQ(data_2[i], result[i]); + } + + delete data; + delete data_2; + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, CreateFileTwiceWriteInFileTwice) { + ASSERT_FALSE(FileExists("./test file")); + + // Create and open file + EXPECT_TRUE(CreateFile("./test file")); + EXPECT_TRUE(FileExists("./test file")); + + uint32_t data_size = 4; + std::vector < uint8_t > data; + for (uint i = 0; i < data_size; ++i) { + data.push_back(i); + } + + // Write data in file + EXPECT_TRUE(Write("./test file", data)); + // Create file second time + EXPECT_TRUE(CreateFile("./test file")); + EXPECT_TRUE(CreateFile("./test file")); + + std::vector < uint8_t > data_2; + for (uint i = 0; i < data_size; ++i) { + data_2.push_back(i + data_size); + } + + // Write data in file + EXPECT_TRUE(Write("./test file", data_2)); + + // Check file + std::vector < uint8_t > result; + EXPECT_TRUE(ReadBinaryFile("./test file", result)); + EXPECT_FALSE(result.empty()); + + EXPECT_EQ(data_2, result); + EXPECT_EQ(result.size(), data_size); + // Check data + for (uint i = 0; i < data_size; ++i) { + EXPECT_NE(data[i], result[i]); + EXPECT_EQ(data_2[i], result[i]); + } + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, WriteInFileTwiceFileRewritten) { + ASSERT_FALSE(FileExists("./test file")); + + // Create and open file + EXPECT_TRUE(CreateFile("./test file")); + EXPECT_TRUE(FileExists("./test file")); + + // Write data in file + uint32_t data_size = 4; + std::vector < uint8_t > data; + for (uint i = 0; i < data_size; ++i) { + data.push_back(i); + } + EXPECT_TRUE(Write("./test file", data)); + + // Write data to file again + std::vector < uint8_t > data_2; + for (uint i = 0; i < data_size; ++i) { + data_2.push_back(i + data_size); + } + EXPECT_TRUE(Write("./test file", data_2)); + + // Check file + std::vector < uint8_t > result; + EXPECT_TRUE(ReadBinaryFile("./test file", result)); + EXPECT_FALSE(result.empty()); + + // Check data + EXPECT_EQ(data_size, result.size()); + for (uint i = 0; i < data_size; ++i) { + EXPECT_NE(data[i], result[i]); + EXPECT_EQ(data_2[i], result[i]); + } + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, WriteDataInTheEndOfFile) { + ASSERT_FALSE(FileExists("./test file")); + + EXPECT_TRUE(CreateFile("./test file")); + EXPECT_TRUE(FileExists("./test file")); + + int32_t data_size = 4; + std::vector < uint8_t > data; + for (int i = 0; i < data_size; ++i) { + data.push_back(i); + } + + // Write data in file + EXPECT_TRUE(Write("./test file", data)); + + // Write in file second time + std::vector < uint8_t > data_2; + for (int i = 0; i < data_size; ++i) { + data_2.push_back(i + data_size); + } + + // Write data in file + EXPECT_TRUE(Write("./test file", data_2, std::ios_base::app)); + + // Check file + std::vector < uint8_t > result; + EXPECT_TRUE(ReadBinaryFile("./test file", result)); + EXPECT_FALSE(result.empty()); + + std::vector < uint8_t > data_check; + for (int i = 0; i < 2 * data_size; ++i) { + data_check.push_back(i); + } + + // Check data + EXPECT_EQ(data_check.size(), result.size()); + for (int i = 0; i < 2 * data_size; ++i) { + EXPECT_EQ(data_check[i], result[i]); + } + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, WriteInFileStream_WriteInFileInTheEndOfFile_FileIncludeBothData) { + ASSERT_FALSE(FileExists("./test file")); + + // Create and open file + std::ofstream* test_file = Open("./test file"); + EXPECT_TRUE(test_file->is_open()); + + // Write data in file + uint32_t data_size = 4; + std::vector < uint8_t > data; + for (uint i = 0; i < data_size; ++i) { + data.push_back(i); + } + // Write data in file + EXPECT_TRUE(Write("./test file", data)); + EXPECT_TRUE(test_file->is_open()); + + // Close filestream + Close(test_file); + + delete test_file; + // Write in file second time + std::vector < uint8_t > data_2; + for (uint i = 0; i < data_size; ++i) { + data_2.push_back(i + data_size); + } + + // Write data in file + EXPECT_TRUE(Write("./test file", data_2, std::ios_base::app)); + + // Check file + std::vector < uint8_t > result; + EXPECT_TRUE(ReadBinaryFile("./test file", result)); + EXPECT_FALSE(result.empty()); + + std::vector < uint8_t > data_check; + for (uint i = 0; i < 2 * data_size; ++i) { + data_check.push_back(i); + } + + // Check data + EXPECT_EQ(data_check.size(), result.size()); + for (uint i = 0; i < 2 * data_size; ++i) { + EXPECT_EQ(data_check[i], result[i]); + } + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, OpenFileStreamForRead_WriteInFileStream) { + ASSERT_FALSE(FileExists("./test file")); + // File creation + EXPECT_TRUE(CreateFile("./test file")); + std::ofstream* test_file = Open("./test file", std::ios_base::in); + EXPECT_TRUE(test_file->is_open()); + + // Write data in file + uint32_t data_size = 4; + uint8_t* data = new uint8_t[data_size]; + for (uint i = 0; i < data_size; ++i) { + data[i] = i; + } + + EXPECT_TRUE(Write(test_file, data, data_size)); + + Close(test_file); + EXPECT_FALSE(test_file->is_open()); + + // Read data from file + std::vector < uint8_t > result; + EXPECT_TRUE(ReadBinaryFile("./test file", result)); + EXPECT_FALSE(result.empty()); + + // Check data + for (uint i = 0; i < data_size; ++i) { + EXPECT_EQ(data[i], result[i]); + } + + delete data; + delete test_file; + + EXPECT_TRUE(FileExists("./test file")); + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, WriteFileNotExists) { + ASSERT_FALSE(FileExists("./test file")); + + unsigned char tmp[] = { 't', 'e', 's', 't' }; + std::vector<unsigned char> data(tmp, tmp + 4); + EXPECT_TRUE(Write("./test file", data)); + // File now exists + ASSERT_TRUE(FileExists("./test file")); + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, WriteFileReadFile) { + ASSERT_FALSE(FileExists("./test file")); + EXPECT_TRUE(CreateFile("./test file")); + + unsigned char tmp[] = { 't', 'e', 's', 't' }; + std::vector<unsigned char> data(tmp, tmp + 4); + EXPECT_TRUE(Write("./test file", data)); + + // Read data from file + std::string result; + std::string check = "test"; + EXPECT_TRUE(ReadFile("./test file", result)); + EXPECT_NE(0, result.size()); + EXPECT_EQ(check, result); + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, WriteBinaryDataReadBinaryFile) { + ASSERT_FALSE(FileExists("./test file")); + EXPECT_TRUE(CreateFile("./test file")); + + uint8_t tmp[] = { 1, 2, 3, 4}; + std::vector<uint8_t> data(tmp, tmp + 4); + EXPECT_TRUE(WriteBinaryFile("./test file", data)); + + // Read data from file + std::vector < uint8_t > result; + EXPECT_TRUE(ReadBinaryFile("./test file", result)); + EXPECT_FALSE(result.empty()); + EXPECT_EQ(data, result); + + EXPECT_TRUE(DeleteFile("./test file")); +} + +TEST(FileSystemTest, WriteBinaryDataTwice_FileRewritten) { + ASSERT_FALSE(FileExists("./test file")); + + EXPECT_TRUE(CreateFile("./test file")); + EXPECT_TRUE(FileExists("./test file")); + + int32_t data_size = 4; + std::vector < uint8_t > data; + for (int i = 0; i < data_size; ++i) { + data.push_back(i); + } + // Write data in file + EXPECT_TRUE(WriteBinaryFile("./test file", data)); + + // Write in file second time + std::vector < uint8_t > data_2; + for (int i = 0; i < data_size; ++i) { + data_2.push_back(i + data_size); + } + + // Write data in file + EXPECT_TRUE(WriteBinaryFile("./test file", data_2)); + + // Check file + std::vector < uint8_t > result; + EXPECT_TRUE(ReadBinaryFile("./test file", result)); + EXPECT_FALSE(result.empty()); + + // Check data + EXPECT_EQ(data_2.size(), result.size()); + for (int i = 0; i < data_size; ++i) { + EXPECT_EQ(data_2[i], result[i]); + } + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, WriteBinaryDataFileNotExists) { + ASSERT_FALSE(FileExists("./test file")); + + int32_t data_size = 4; + std::vector < uint8_t > data; + for (int i = 0; i < data_size; ++i) { + data.push_back(i); + } + + EXPECT_TRUE(WriteBinaryFile("./test file", data)); + ASSERT_TRUE(FileExists("./test file")); + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, WriteDataAsBinaryData) { + ASSERT_FALSE(FileExists("./test file")); + + unsigned char tmp[] = { 't', 'e', 's', 't' }; + std::vector<unsigned char> data(tmp, tmp + 4); + EXPECT_TRUE(WriteBinaryFile("./test file", data)); + ASSERT_TRUE(FileExists("./test file")); + + // Check file + std::vector < uint8_t > result; + EXPECT_TRUE(ReadBinaryFile("./test file", result)); + EXPECT_FALSE(result.empty()); + + EXPECT_EQ(data.size(), result.size()); + + for (uint i = 0; i < result.size(); ++i) { + EXPECT_EQ(data[i], result[i]); + } + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, WriteEmptyData) { + ASSERT_FALSE(FileExists("./test file")); + + std::vector<unsigned char> data; + EXPECT_TRUE(Write("./test file", data)); + ASSERT_TRUE(FileExists("./test file")); + + // Check file + std::vector < uint8_t > result; + EXPECT_TRUE(ReadBinaryFile("./test file", result)); + EXPECT_TRUE(result.empty()); + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, WriteEmptyDataAsBinaryData) { + ASSERT_FALSE(FileExists("./test file")); + + // Write empty data + std::vector<unsigned char> data; + EXPECT_TRUE(WriteBinaryFile("./test file", data)); + ASSERT_TRUE(FileExists("./test file")); + + // Check file + std::vector < uint8_t > result; + EXPECT_TRUE(ReadBinaryFile("./test file", result)); + EXPECT_TRUE(result.empty()); + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, WriteBinaryData_WriteDataInTheEndOfFile) { + ASSERT_FALSE(FileExists("./test file")); + + // Write binary file + unsigned char tmp[] = { 't', 'e', 's', 't' }; + std::vector<unsigned char> data(tmp, tmp + 4); + EXPECT_TRUE(WriteBinaryFile("./test file", data)); + ASSERT_TRUE(FileExists("./test file")); + + // Write in file second time + int32_t data_size = 4; + std::vector < uint8_t > data_2; + for (int i = 0; i < data_size; ++i) { + data_2.push_back(i); + } + + // Write data in file + EXPECT_TRUE(Write("./test file", data_2, std::ios_base::app)); + + // Check file + std::vector < uint8_t > result; + EXPECT_TRUE(ReadBinaryFile("./test file", result)); + EXPECT_FALSE(result.empty()); + + // Prepare data for check + data.insert(data.end(), data_2.begin(), data_2.end()); + + // Compare data + EXPECT_EQ(data.size(), result.size()); + for (uint i = 0; i < result.size(); ++i) { + EXPECT_EQ(data[i], result[i]); + } + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, CreateFile_WriteDataWithFlagOpenForReading) { + ASSERT_FALSE(FileExists("./test file")); + EXPECT_TRUE(CreateFile("./test file")); + // Write data in file + int32_t data_size = 4; + std::vector < uint8_t > data; + for (int i = 0; i < data_size; ++i) { + data.push_back(i); + } + EXPECT_TRUE(Write("./test file", data, std::ios_base::in)); + EXPECT_TRUE(FileExists("./test file")); + + // Check file + std::vector < uint8_t > result; + EXPECT_TRUE(ReadBinaryFile("./test file", result)); + EXPECT_FALSE(result.empty()); + + // Compare data + EXPECT_EQ(data.size(), result.size()); + for (uint i = 0; i < result.size(); ++i) { + EXPECT_EQ(data[i], result[i]); + } + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, FileDoesNotCreated_WriteFileWithFlagOpenForReadingIsImpossible) { + ASSERT_FALSE(FileExists("./test file")); + + // Write data in file is impossible + int32_t data_size = 4; + std::vector < uint8_t > data; + for (int i = 0; i < data_size; ++i) { + data.push_back(i); + } + EXPECT_FALSE(Write("./test file", data, std::ios_base::in)); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, WriteFileGetSize) { + ASSERT_FALSE(FileExists("./test file")); + EXPECT_TRUE(CreateFile("./test file")); + EXPECT_EQ(0, FileSize("./test file")); + + unsigned char tmp[] = { 't', 'e', 's', 't' }; + std::vector<unsigned char> data(tmp, tmp + 4); + EXPECT_TRUE(Write("./test file", data)); + + EXPECT_NE(0, FileSize("./test file")); + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, CreateFileCheckDefaultAccess) { + // File creation + ASSERT_FALSE(FileExists("./test file")); + EXPECT_TRUE(CreateFile("./test file")); + + // Check accesses + EXPECT_TRUE(IsAccessible("./test file", R_OK)); + EXPECT_TRUE(IsAccessible("./test file", W_OK)); + EXPECT_TRUE(IsReadingAllowed("./test file")); + EXPECT_TRUE(IsWritingAllowed("./test file")); + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); +} + +TEST(FileSystemTest, GetFileModificationTime) { + ASSERT_FALSE(FileExists("./test file")); + + EXPECT_TRUE(CreateFile("./test file")); + + uint64_t modif_time = GetFileModificationTime("./test file"); + EXPECT_LE(0, modif_time); + + std::vector < uint8_t > data(1, 1); + EXPECT_TRUE(WriteBinaryFile("./test file", data)); + + EXPECT_LE(0, GetFileModificationTime("./test file")); + EXPECT_LE(modif_time, GetFileModificationTime("./test file")); + + EXPECT_TRUE(DeleteFile("./test file")); + EXPECT_FALSE(FileExists("./test file")); + +} + +TEST(FileSystemTest, ListFiles) { + ASSERT_FALSE(DirectoryExists("./Test directory")); + CreateDirectory("./Test directory"); + + std::vector < std::string > list; + list = ListFiles("./Test directory"); + EXPECT_TRUE(list.empty()); + + EXPECT_TRUE(CreateFile("./Test directory/test file")); + EXPECT_TRUE(CreateFile("./Test directory/test file 2")); + + list = ListFiles("./Test directory"); + EXPECT_FALSE(list.empty()); + + std::sort(list.begin(), list.end()); + EXPECT_EQ("test file", list[0]); + EXPECT_EQ("test file 2", list[1]); + + EXPECT_TRUE(RemoveDirectory("./Test directory", true)); + EXPECT_FALSE(DirectoryExists("./Test directory")); + + EXPECT_FALSE(FileExists("./Test directory/test file")); + EXPECT_FALSE(FileExists("./Test directory/test file 2")); +} + +TEST(FileSystemTest, ListFilesIncludeSubdirectory) { + ASSERT_FALSE(DirectoryExists("./Test directory")); + CreateDirectoryRecursively("./Test directory/Test directory 2/"); + + std::vector < std::string > list; + list = ListFiles("./Test directory"); + EXPECT_FALSE(list.empty()); + EXPECT_EQ(1, list.size()); + EXPECT_EQ("Test directory 2", list[0]); + + EXPECT_TRUE(RemoveDirectory("./Test directory", true)); + EXPECT_FALSE(DirectoryExists("./Test directory")); +} + +TEST(FileSystemTest, ListFilesDoesNotIncludeFilesInSubdirectory) { + ASSERT_FALSE(DirectoryExists("./Test directory")); + CreateDirectoryRecursively("./Test directory/Test directory 2/"); + + std::vector < std::string > list; + list = ListFiles("./Test directory"); + EXPECT_FALSE(list.empty()); + + EXPECT_TRUE(CreateFile("./Test directory/Test directory 2/test file")); + EXPECT_TRUE(CreateFile("./Test directory/Test directory 2/test file 2")); + + list = ListFiles("./Test directory"); + EXPECT_FALSE(list.empty()); + + std::sort(list.begin(), list.end()); + EXPECT_EQ("Test directory 2", list[0]); + EXPECT_EQ(1, list.size()); + + EXPECT_TRUE(RemoveDirectory("./Test directory", true)); + EXPECT_FALSE(DirectoryExists("./Test directory")); +} + +TEST(FileSystemTest, GetAvailableDiskSpace) { + + // Get available disk space before directory with file creaction and after + uint64_t available_space = GetAvailableDiskSpace("."); + EXPECT_NE(0, available_space); + ASSERT_FALSE(DirectoryExists("./Test directory")); + CreateDirectory("./Test directory"); + + unsigned char tmp[] = { 't', 'e', 's', 't' }; + std::vector<unsigned char> data(tmp, tmp + 4); + EXPECT_TRUE(Write("./Test directory/test file", data)); + + EXPECT_GE(available_space, GetAvailableDiskSpace(".")); + EXPECT_TRUE(RemoveDirectory("./Test directory")); + EXPECT_FALSE(DirectoryExists("./Test directory")); +} + +TEST(FileSystemTest, ConvertPathForURL) { + std::string path = "./Test directory"; + EXPECT_NE(path, ConvertPathForURL(path)); + std::string path_brackets = "./Test_directory_with(brackets)"; + EXPECT_NE(path_brackets, ConvertPathForURL(path)); + std::string another_path = "./Test_directory/new_directory_without_spaces"; + EXPECT_EQ(another_path, ConvertPathForURL(another_path)); +} + +TEST(FileSystemTest, DirectorySize) { + ASSERT_FALSE(DirectoryExists("./Test directory")); + CreateDirectory("./Test directory"); + EXPECT_TRUE(DirectoryExists("./Test directory")); + // Get size of empty directory + EXPECT_EQ(0, DirectorySize("./Test directory")); + EXPECT_TRUE(CreateFile("./Test directory/test file")); + + // Get size of nonempty directory with empty file + EXPECT_EQ(0, DirectorySize("./Test directory")); + + unsigned char tmp[] = { 't', 'e', 's', 't' }; + std::vector<unsigned char> data(tmp, tmp + 4); + + EXPECT_TRUE(Write("./Test directory/test file", data)); + // Get size of nonempty directory with nonempty file + EXPECT_NE(0, DirectorySize("./Test directory")); + + EXPECT_TRUE(DeleteFile("./Test directory/test file")); + EXPECT_EQ(0, DirectorySize("./Test directory")); + EXPECT_TRUE(RemoveDirectory("./Test directory")); + EXPECT_FALSE(DirectoryExists("./Test directory")); +} + +TEST(FileSystemTest, DeleteAllContentInDirectory) { + ASSERT_FALSE(DirectoryExists("./Test directory")); + CreateDirectory("./Test directory"); + + // Create files in directory + EXPECT_TRUE(CreateFile("./Test directory/test file")); + EXPECT_TRUE(CreateFile("./Test directory/test file 2")); + + EXPECT_TRUE(FileExists("./Test directory/test file")); + EXPECT_TRUE(FileExists("./Test directory/test file 2")); + + EXPECT_TRUE(DirectoryExists("./Test directory")); + + // Create subdirectories + CreateDirectoryRecursively( + "./Test directory/Test directory 2/Test directory 3"); + + EXPECT_TRUE(DirectoryExists("./Test directory/Test directory 2")); + EXPECT_TRUE( + DirectoryExists("./Test directory/Test directory 2/Test directory 3")); + + remove_directory_content("./Test directory"); + + // Directory does not include files and subdirectories + EXPECT_FALSE(FileExists("./Test directory/test file")); + EXPECT_FALSE(FileExists("./Test directory/test file 2")); + + EXPECT_FALSE( + DirectoryExists("./Test directory/Test directory 2/Test directory 3")); + EXPECT_FALSE(DirectoryExists("./Test directory/Test directory 2")); + + std::vector < std::string > list; + list = ListFiles("./Test directory"); + EXPECT_TRUE(list.empty()); + + EXPECT_TRUE(DirectoryExists("./Test directory")); + + EXPECT_TRUE(RemoveDirectory("./Test directory", true)); + EXPECT_FALSE(DirectoryExists("./Test directory")); +} + } // namespace utils } // namespace components } // namespace test diff --git a/src/components/utils/test/lock_posix_test.cc b/src/components/utils/test/lock_posix_test.cc new file mode 100644 index 000000000..9b0d9533b --- /dev/null +++ b/src/components/utils/test/lock_posix_test.cc @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gtest/gtest.h" +#include "utils/lock.h" + +namespace test { +namespace components { +namespace utils { + +using sync_primitives::Lock; + +TEST(LockPosixTest, DefaultCtorTest_ExpectNonRecursiveMutexCreated) { + // Create Lock object + Lock test_mutex; + // Lock mutex + test_mutex.Acquire(); + // Check if created mutex is non-recursive + EXPECT_FALSE(test_mutex.Try()); + // Release mutex before destroy + test_mutex.Release(); +} + +TEST(LockPosixTest, CtorTestWithFalseArgument_ExpectNonRecursiveMutexCreated) { + // Create Lock object + Lock test_mutex(false); + // Lock mutex + test_mutex.Acquire(); + // Check if created mutex is non-recursive + EXPECT_FALSE(test_mutex.Try()); + // Release mutex before destroy + test_mutex.Release(); +} + +TEST(LockPosixTest, CtorTestWithTrueArgument_ExpectRecursiveMutexCreated) { + // Create Lock object + Lock test_mutex(true); + // Lock mutex + test_mutex.Acquire(); + // Check if created mutex is recursive + EXPECT_TRUE(test_mutex.Try()); + // Release mutex before destroy + test_mutex.Release(); + test_mutex.Release(); +} + +TEST(LockPosixTest, AcquireMutex_ExpectMutexLocked) { + // Create Lock object (non-recursive mutex) + Lock test_mutex; + // Lock mutex + test_mutex.Acquire(); + // Try to lock it again. If locked expect false + EXPECT_FALSE(test_mutex.Try()); + test_mutex.Release(); +} + +TEST(LockPosixTest, ReleaseMutex_ExpectMutexReleased) { + // Create Lock object (non-recursive mutex) + Lock test_mutex; + // Lock mutex + test_mutex.Acquire(); + // Release mutex + test_mutex.Release(); + // Try to lock it again. If released expect true + EXPECT_TRUE(test_mutex.Try()); + test_mutex.Release(); +} + +TEST(LockPosixTest, TryLockNonRecursiveMutex_ExpectMutexNotLockedTwice) { + // Create Lock object (non-recursive mutex) + Lock test_mutex; + // Lock mutex + test_mutex.Try(); + // Try to lock it again. If locked expect false + EXPECT_FALSE(test_mutex.Try()); + test_mutex.Release(); +} + +TEST(LockPosixTest, TryLockRecursiveMutex_ExpectMutexLockedTwice) { + // Create Lock object (recursive mutex) + Lock test_mutex(true); + // Lock mutex + test_mutex.Try(); + // Try to lock it again. Expect true and internal counter increase + EXPECT_TRUE(test_mutex.Try()); + // Release mutex twice as was locked twice. + // Every Release() will decrement internal counter + test_mutex.Release(); + test_mutex.Release(); +} + +} // namespace utils +} // namespace components +} // namespace test diff --git a/src/components/utils/test/log4cxx.properties b/src/components/utils/test/log4cxx.properties new file mode 100644 index 000000000..0ba34d0ad --- /dev/null +++ b/src/components/utils/test/log4cxx.properties @@ -0,0 +1,11 @@ +log4j.appender.AutoTraceTestLogFile=org.apache.log4j.FileAppender +log4j.appender.AutoTraceTestLogFile.File=AutoTraceTestLogFile.log +log4j.appender.AutoTraceTestLogFile.append=true +log4j.appender.AutoTraceTestLogFile.DatePattern='.' yyyy-MM-dd HH-mm +log4j.appender.AutoTraceTestLogFile.ImmediateFlush=true +log4j.appender.AutoTraceTestLogFile.layout=org.apache.log4j.PatternLayout +log4j.appender.AutoTraceTestLogFile.layout.ConversionPattern=%-5p [%d{dd MMM yyyy HH:mm:ss,SSS}][%c] %F:%L %M: %m%n + + +# All SmartDeviceLinkCore logs +log4j.rootLogger=ALL, AutoTraceTestLogFile
\ No newline at end of file diff --git a/src/components/utils/test/log_message_loop_thread_test.cc b/src/components/utils/test/log_message_loop_thread_test.cc new file mode 100644 index 000000000..789bf62f4 --- /dev/null +++ b/src/components/utils/test/log_message_loop_thread_test.cc @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "utils/log_message_loop_thread.h" +#include "utils/logger_status.h" + +namespace test { +namespace components { +namespace utils { + +using namespace ::logger; +using ::testing::_; + +TEST(LogMessageLoopThread,CreateLogMessageSingleton) { + //if logger_status is LoggerThreadNotCreated or LoggerThreadCreated, + // creation of singleton will be impossible + logger::logger_status = CreatingLoggerThread; + + LogMessageLoopThread *instance_1 = LogMessageLoopThread::instance(); + LogMessageLoopThread *instance_2 = LogMessageLoopThread::instance(); + + //assert + EXPECT_EQ(instance_1, instance_2); + + LogMessageLoopThread::destroy(); + + EXPECT_FALSE(LogMessageLoopThread::exists()); + logger::logger_status = LoggerThreadNotCreated; +} + +TEST(LogMessageLoopThread, DestroyLogMessage_loggerStatusDeletingLogger) { + logger::logger_status = CreatingLoggerThread; + LogMessageLoopThread::instance(); + + //assert + EXPECT_EQ(CreatingLoggerThread, logger::logger_status); + + //act + LogMessageLoopThread::destroy(); + + //assert + EXPECT_EQ(DeletingLoggerThread, logger::logger_status); + + logger::logger_status = LoggerThreadNotCreated; +} + +class MockLogMessageTest : public LogMessageHandler { + public: + MOCK_CONST_METHOD1(Handle, void(const LogMessage message)); +}; + +TEST(LogMessageLoopThread, HandleNeverCalled) { + logger::logger_status = CreatingLoggerThread; + + MockLogMessageTest mmock; + EXPECT_CALL(mmock,Handle(_)).Times(0); + LogMessageLoopThread::instance(); + + LogMessageLoopThread::destroy(); + logger::logger_status = LoggerThreadNotCreated; +} + +} // namespace utils +} // namespace components +} // namespace test diff --git a/src/components/utils/test/message_queue_test.cc b/src/components/utils/test/message_queue_test.cc new file mode 100644 index 000000000..fbae7a9e5 --- /dev/null +++ b/src/components/utils/test/message_queue_test.cc @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <unistd.h> +#include "gtest/gtest.h" +#include "utils/message_queue.h" + +namespace test { +namespace components { +namespace utils { + +using ::utils::MessageQueue; + +class MessageQueueTest : public testing::Test { + public: + MessageQueueTest() + : test_val_1("Hello,"), + test_val_2("Beautiful "), + test_val_3("World!"), + test_line(""), + check_value(false) { + } + void add_one_element_to_queue(); + void extract_from_queue(); + void add_three_elements_to_queue(); + void ShutDownQueue(); + + static void* add_one_element_to_queue_helper(void *context); + static void* extract_from_queue_helper(void *context); + static void* add_three_elements_to_queue_helper(void *context); + static void* ShutDownQueue_helper(void *context); + + protected: + MessageQueue<std::string> test_queue; + std::string test_val_1; + std::string test_val_2; + std::string test_val_3; + std::string test_line; + bool check_value; +}; + +// Thread function - adds 1 element1 to the queue +void MessageQueueTest::add_one_element_to_queue() { + test_queue.push(test_val_1); + pthread_exit(NULL); +} + +// Thread function - removes 1 element from beginning of queue +void MessageQueueTest::extract_from_queue() { + test_queue.wait(); + test_line = test_queue.pop(); + pthread_exit(NULL); +} + +// Thread function - adds 3 elements to the queue +void MessageQueueTest::add_three_elements_to_queue() { + test_queue.push(test_val_1); + test_queue.push(test_val_2); + test_queue.push(test_val_3); + pthread_exit(NULL); +} + +// Thread function - adds 3 elements to the queue +void MessageQueueTest::ShutDownQueue() { + check_value = true; + test_queue.Shutdown(); + pthread_exit(NULL); +} + +void* MessageQueueTest::add_one_element_to_queue_helper(void *context) { + (reinterpret_cast<MessageQueueTest *>(context))->add_one_element_to_queue(); + return NULL; +} +void* MessageQueueTest::extract_from_queue_helper(void *context) { + (reinterpret_cast<MessageQueueTest *>(context))->extract_from_queue(); + return NULL; +} +void* MessageQueueTest::add_three_elements_to_queue_helper(void *context) { + (reinterpret_cast<MessageQueueTest *>(context))->add_three_elements_to_queue(); + return NULL; +} +void* MessageQueueTest::ShutDownQueue_helper(void *context) { + (reinterpret_cast<MessageQueueTest *>(context))->ShutDownQueue(); + return NULL; +} + +TEST_F(MessageQueueTest, DefaultCtorTest_ExpectEmptyQueueCreated) { + bool test_value = true; + // Check if the queue is empty + ASSERT_EQ(test_value, test_queue.empty()); +} + +TEST_F(MessageQueueTest, MessageQueuePushThreeElementsTest_ExpectThreeElementsAdded) { + pthread_t thread1; + pthread_create(&thread1, NULL, &MessageQueueTest::add_three_elements_to_queue_helper, this); + pthread_join(thread1, NULL); + // check if 3 elements were added successfully + ASSERT_EQ(3u, test_queue.size()); +} + +TEST_F(MessageQueueTest, NotEmptyMessageQueueResetTest_ExpectEmptyQueue) { + // Adding some elements to queue + test_queue.push(test_val_1); + test_queue.push(test_val_2); + test_queue.push(test_val_3); + // Resetting queue + test_queue.Reset(); + // Check if queue is empty + ASSERT_TRUE(test_queue.empty()); + // Check the size of queue after reset + ASSERT_EQ(0u, test_queue.size()); +} + +TEST_F(MessageQueueTest, MessageQueuePopOneElementTest_ExpectOneElementRemovedFromQueue) { + pthread_t thread1; + pthread_t thread2; + // Creating threads with thread function mentioned above + pthread_create(&thread1, NULL, &MessageQueueTest::add_one_element_to_queue_helper, this); + pthread_create(&thread2, NULL, &MessageQueueTest::extract_from_queue_helper, this); + // Primary thread waits until thread 2 to be finished + pthread_join(thread2, NULL); + // Check if first element was removed successfully + ASSERT_EQ(test_val_1, test_line); + // Check the size of queue after 1 element was removed + ASSERT_EQ(0u, test_queue.size()); +} + +TEST_F(MessageQueueTest, MessageQueueShutdownTest_ExpectMessageQueueWillBeShutDown) { + pthread_t thread1; + // Creating thread with thread function mentioned above + pthread_create(&thread1, NULL, &MessageQueueTest::ShutDownQueue_helper, this); + // Primary thread sleeps until thread1 will make queue shutdown + test_queue.wait(); + check_value = true; + ASSERT_TRUE(check_value); +} + +} // namespace utils +} // namespace components +} // namespace test diff --git a/src/components/utils/test/messagemeter_test.cc b/src/components/utils/test/messagemeter_test.cc index 45375e4ed..6c13ab345 100644 --- a/src/components/utils/test/messagemeter_test.cc +++ b/src/components/utils/test/messagemeter_test.cc @@ -79,7 +79,7 @@ class MessageMeterTest: public ::testing::TestWithParam<TimePair> { void TearDown() OVERRIDE { } ::utils::MessageMeter<int> meter; - TimevalStruct time_range {0, 0}; + TimevalStruct time_range = {0, 0}; int64_t time_range_msecs; int usecs; int id1, id2, id3; diff --git a/src/components/utils/test/posix_thread_test.cc b/src/components/utils/test/posix_thread_test.cc new file mode 100644 index 000000000..d597f036d --- /dev/null +++ b/src/components/utils/test/posix_thread_test.cc @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gtest/gtest.h" +#include "utils/lock.h" +#include "threads/thread.h" + +namespace test { +namespace components { +namespace utils { + +using namespace sync_primitives; +using namespace threads; + +// TODO(AByzhynar): Change this to use Gtest class to create all variables for every TEST_F +// TODO(AByzhynar): Add multithreading tests + +namespace { +const uint32_t MAX_SIZE = 20; +const size_t MyStackSize = 32768; +const char *threadName("test thread"); +const std::string test_thread_name("THREAD"); +sync_primitives::ConditionalVariable cond_var_; +sync_primitives::Lock test_mutex_; +}; + +// ThreadDelegate successor +class TestThreadDelegate : public threads::ThreadDelegate { + public: + TestThreadDelegate() + : check_value_(false) { + } + void threadMain() { + AutoLock test_lock(test_mutex_); + check_value_ = true; + cond_var_.NotifyOne(); + } + + bool check_value() const { + return check_value_; + } + private: + bool check_value_; +}; + +TEST(PosixThreadTest, CreateThread_ExpectThreadCreated) { + // Arrange + threads::Thread *thread = NULL; + TestThreadDelegate *threadDelegate = new TestThreadDelegate(); + // Create thread + ASSERT_NO_THROW(thread = CreateThread(threadName, threadDelegate)); + EXPECT_TRUE(thread != NULL); + EXPECT_EQ(thread, threadDelegate->thread()); + EXPECT_EQ(thread->delegate(), threadDelegate); + DeleteThread(thread); + delete threadDelegate; + // Check Delegate Dtor worked successfully + EXPECT_EQ(NULL, thread->delegate()); +} + +TEST(PosixThreadTest, CheckCreatedThreadName_ExpectCorrectName) { + // Arrange + threads::Thread *thread = NULL; + threads::ThreadDelegate *threadDelegate = new TestThreadDelegate(); + // Create thread + ASSERT_NO_THROW(thread = CreateThread(threadName, threadDelegate)); + // Check thread was created with correct name + EXPECT_EQ(threadName, thread->name()); + DeleteThread(thread); + delete threadDelegate; + EXPECT_EQ(NULL, thread->delegate()); +} + +TEST(PosixThreadTest, CheckCreatedThreadNameChangeToLongName_ExpectThreadNameReduced) { + // Arrange + threads::Thread *thread = NULL; + TestThreadDelegate *threadDelegate = new TestThreadDelegate(); + AutoLock test_lock(test_mutex_); + // Create thread + ASSERT_NO_THROW(thread = CreateThread(threadName, threadDelegate)); + thread->start(threads::ThreadOptions(threads::Thread::kMinStackSize)); + // Rename started thread. Name will be cut to 15 symbols + '\0' + // This is the limit in current POSIX thread implementation + thread->SetNameForId(thread->thread_handle(), + std::string("new thread with changed name")); + // Name must be large enough to keep 16 symbols. Read previous comment + char name[MAX_SIZE]; + int result = pthread_getname_np(thread->thread_handle(), name, sizeof(name)); + if (!result) + EXPECT_EQ(std::string("new thread with"), std::string(name)); + cond_var_.WaitFor(test_lock, 10000); + EXPECT_TRUE(threadDelegate->check_value()); + DeleteThread(thread); + delete threadDelegate; + EXPECT_EQ(NULL, thread->delegate()); +} + +TEST(PosixThreadTest, StartCreatedThreadWithOptionsJoinableAndMyStackSize_ExpectMyStackSizeStackAndJoinableThreadStarted) { + // Arrange + threads::Thread *thread = NULL; + TestThreadDelegate *threadDelegate = new TestThreadDelegate(); + AutoLock test_lock(test_mutex_); + // Create thread + ASSERT_NO_THROW(thread = CreateThread(threadName, threadDelegate)); + // Start thread with following options (Stack size = 32768 & thread is joinable) + thread->start(threads::ThreadOptions(MyStackSize)); + // Check thread is joinable + EXPECT_TRUE(thread->is_joinable()); + // Check thread stack size is 32768 + EXPECT_EQ(MyStackSize, thread->stack_size()); + cond_var_.WaitFor(test_lock, 10000); + EXPECT_TRUE(threadDelegate->check_value()); + DeleteThread(thread); + delete threadDelegate; + EXPECT_EQ(NULL, thread->delegate()); +} + +TEST(PosixThreadTest, StartCreatedThreadWithDefaultOptions_ExpectZeroStackAndJoinableThreadStarted) { + // Arrange + threads::Thread *thread = NULL; + TestThreadDelegate *threadDelegate = new TestThreadDelegate(); + AutoLock test_lock(test_mutex_); + // Create thread + ASSERT_NO_THROW(thread = CreateThread(threadName, threadDelegate)); + // Start thread with default options (Stack size = 0 & thread is joinable) + thread->start(threads::ThreadOptions()); + // Check thread is joinable + EXPECT_TRUE(thread->is_joinable()); + // Check thread stack size is minimum value. Stack can not be 0 + EXPECT_EQ(Thread::kMinStackSize, thread->stack_size()); + cond_var_.WaitFor(test_lock, 10000); + EXPECT_TRUE(threadDelegate->check_value()); + DeleteThread(thread); + delete threadDelegate; + EXPECT_EQ(NULL, thread->delegate()); +} + +TEST(PosixThreadTest, StartThreadWithZeroStackAndDetached_ExpectMinimumStackAndDetachedThreadStarted) { + // Arrange + threads::Thread *thread = NULL; + TestThreadDelegate *threadDelegate = new TestThreadDelegate(); + AutoLock test_lock(test_mutex_); + // Create thread + ASSERT_NO_THROW(thread = CreateThread(threadName, threadDelegate)); + // Start thread with default options (Stack size = 0 & thread is detached) + thread->start(threads::ThreadOptions(0, false)); + // Check thread is detached + EXPECT_FALSE(thread->is_joinable()); + // Check thread stack size is 0 + EXPECT_EQ(Thread::kMinStackSize, thread->stack_size()); + cond_var_.WaitFor(test_lock, 10000); + EXPECT_TRUE(threadDelegate->check_value()); + DeleteThread(thread); + delete threadDelegate; + EXPECT_EQ(NULL, thread->delegate()); +} + +TEST(PosixThreadTest, DISABLED_CheckCreatedThreadNameChangeToEmpty_ExpectThreadNameChangedToEmpty) { + // Arrange + threads::Thread *thread = NULL; + TestThreadDelegate *threadDelegate = new TestThreadDelegate(); + AutoLock test_lock(test_mutex_); + // Create thread + ASSERT_NO_THROW(thread = CreateThread(threadName, threadDelegate)); + thread->start(threads::ThreadOptions(threads::Thread::kMinStackSize)); + // Rename started thread. Name will be cut to 15 symbols + '\0' + // This is the limit in current POSIX thread implementation + thread->SetNameForId(thread->thread_handle(), std::string("")); + // Name must be large enough to keep 16 symbols. Read previous comment + char name[MAX_SIZE]; + int result = pthread_getname_np(thread->thread_handle(), name, sizeof(name)); + if (!result) { + EXPECT_EQ(std::string(""), std::string(name)); + } + cond_var_.WaitFor(test_lock, 10000); + EXPECT_TRUE(threadDelegate->check_value()); + DeleteThread(thread); + delete threadDelegate; + EXPECT_EQ(NULL, thread->delegate()); +} + +TEST(PosixThreadTest, CheckCreatedThreadNameChangeToShortName_ExpectThreadNameChangedToShort) { + // Arrange + threads::Thread *thread = NULL; + TestThreadDelegate *threadDelegate = new TestThreadDelegate(); + AutoLock test_lock(test_mutex_); + // Create thread + ASSERT_NO_THROW(thread = CreateThread(threadName, threadDelegate)); + // Start created thread + thread->start(threads::ThreadOptions(threads::Thread::kMinStackSize)); + // Rename started thread. Name will be cut to 15 symbols + '\0' + // This is the limit in current POSIX thread implementation + thread->SetNameForId(thread->thread_handle(), test_thread_name); + // Name must be large enough to keep 16 symbols. Read previous comment + char name[MAX_SIZE]; + int result = pthread_getname_np(thread->thread_handle(), name, sizeof(name)); + if (!result) { + EXPECT_EQ(test_thread_name, std::string(name)); + } + cond_var_.WaitFor(test_lock, 10000); + EXPECT_TRUE(threadDelegate->check_value()); + DeleteThread(thread); + delete threadDelegate; + EXPECT_EQ(NULL, thread->delegate()); +} + +TEST(PosixThreadTest, StartThread_ExpectThreadStarted) { + // Arrange + threads::Thread *thread = NULL; + TestThreadDelegate *threadDelegate = new TestThreadDelegate(); + AutoLock test_lock(test_mutex_); + // Create thread + ASSERT_NO_THROW(thread = CreateThread(threadName, threadDelegate)); + // Start created thread + EXPECT_TRUE(thread->start(threads::ThreadOptions(threads::Thread::kMinStackSize))); + cond_var_.WaitFor(test_lock, 10000); + EXPECT_TRUE(threadDelegate->check_value()); + DeleteThread(thread); + delete threadDelegate; + EXPECT_EQ(NULL, thread->delegate()); +} + +TEST(PosixThreadTest, StartOneThreadTwice_ExpectTheSameThreadStartedTwice) { + // Arrange + PlatformThreadHandle thread1_id; + PlatformThreadHandle thread2_id; + threads::Thread *thread = NULL; + TestThreadDelegate *threadDelegate = new TestThreadDelegate(); + AutoLock test_lock(test_mutex_); + // Create thread + ASSERT_NO_THROW(thread = CreateThread(threadName, threadDelegate)); + // Start created thread + EXPECT_TRUE(thread->start(threads::ThreadOptions(threads::Thread::kMinStackSize))); + thread1_id = thread->CurrentId(); + thread->stop(); + // Try to start thread again + EXPECT_TRUE(thread->start(threads::ThreadOptions(threads::Thread::kMinStackSize))); + thread2_id = thread->CurrentId(); + EXPECT_EQ(thread1_id, thread2_id); + cond_var_.WaitFor(test_lock, 10000); + EXPECT_TRUE(threadDelegate->check_value()); + DeleteThread(thread); + delete threadDelegate; + EXPECT_EQ(NULL, thread->delegate()); +} + +TEST(PosixThreadTest, StartOneThreadAgainAfterRename_ExpectRenamedThreadStarted) { + // Arrange + PlatformThreadHandle thread1_id; + PlatformThreadHandle thread2_id; + threads::Thread *thread = NULL; + TestThreadDelegate *threadDelegate = new TestThreadDelegate(); + AutoLock test_lock(test_mutex_); + // Create thread + ASSERT_NO_THROW(thread = CreateThread(threadName, threadDelegate)); + // Start created thread + EXPECT_TRUE(thread->start(threads::ThreadOptions(threads::Thread::kMinStackSize))); + thread1_id = thread->CurrentId(); + // Rename started thread. Name will be cut to 15 symbols + '\0' + // This is the limit in current POSIX thread implementation + thread->SetNameForId(thread->thread_handle(), test_thread_name); + // Name must be large enough to keep 16 symbols. Read previous comment + char name[MAX_SIZE]; + int result = pthread_getname_np(thread->thread_handle(), name, sizeof(name)); + if (!result) + EXPECT_EQ(test_thread_name, std::string(name)); + // Stop thread + thread->stop(); + EXPECT_TRUE(thread->start(threads::ThreadOptions(threads::Thread::kMinStackSize))); + thread2_id = thread->CurrentId(); + // Expect the same thread started with the the same name + EXPECT_EQ(test_thread_name, std::string(name)); + EXPECT_EQ(thread1_id, thread2_id); + cond_var_.WaitFor(test_lock, 10000); + EXPECT_TRUE(threadDelegate->check_value()); + DeleteThread(thread); + delete threadDelegate; + EXPECT_EQ(NULL, thread->delegate()); +} + +} // namespace utils +} // namespace components +} // namespace test diff --git a/src/components/utils/test/resource_usage_test.cc b/src/components/utils/test/resource_usage_test.cc new file mode 100644 index 000000000..c10bbea86 --- /dev/null +++ b/src/components/utils/test/resource_usage_test.cc @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2014, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <unistd.h> +#include "gtest/gtest.h" +#include "utils/macro.h" + +#include "utils/resource_usage.h" +#include "utils/file_system.h" + +namespace utils { + +class ResourceUsagePrivateTest : public ::testing::Test { + protected: + Resources res; +}; + +TEST_F(ResourceUsagePrivateTest, ReadStatFileTest) { + std::string proc_buf; + EXPECT_TRUE(res.ReadStatFile(proc_buf)); +} + +TEST_F(ResourceUsagePrivateTest, GetProcInfoTest) { + Resources::PidStats pid_stat; + EXPECT_TRUE(res.GetProcInfo(pid_stat)); +} + +TEST_F(ResourceUsagePrivateTest, GetMemInfoTest) { + Resources::MemInfo mem_info; + EXPECT_TRUE(res.GetMemInfo(mem_info)); +} + +TEST_F(ResourceUsagePrivateTest, GetStatPathTest_FileExists) { + //arrange + std::string filename = res.GetStatPath(); + //assert + EXPECT_TRUE(file_system::FileExists(filename)); +} + +TEST_F(ResourceUsagePrivateTest, GetStatPathTest_ReadFile) { + //arrange + std::string filename = res.GetStatPath(); + std::string output; + //assert + EXPECT_TRUE(file_system::ReadFile(filename, output)); + +} +TEST_F(ResourceUsagePrivateTest, GetProcPathTest) { + ///arrange + std::string fd = res.GetProcPath(); + std::string filename = res.GetStatPath(); + //assert + EXPECT_EQ(filename, fd + "/stat"); +} +} + +namespace test { +namespace components { +namespace utils { +using namespace ::utils; + +TEST(ResourceUsageTest, SuccesfulGrabResources) { + ResourseUsage* resources = Resources::getCurrentResourseUsage(); + EXPECT_TRUE(resources != NULL); + delete resources; + +} + +} // namespace utils +} // namespace components +} // namespace test diff --git a/src/components/utils/test/rwlock_posix_test.cc b/src/components/utils/test/rwlock_posix_test.cc new file mode 100644 index 000000000..779b57ff3 --- /dev/null +++ b/src/components/utils/test/rwlock_posix_test.cc @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gtest/gtest.h" +#include "utils/rwlock.h" + +namespace test { +namespace components { +namespace utils { + +using sync_primitives::RWLock; + +class RWlockTest : public ::testing::Test { + public: + void ThreadsDispatcher(void* (*func)(void*)) { + for (uint8_t i = 0; i < kNum_threads_; ++i) { + bool thread_created = (pthread_create(&thread[i], NULL, func, this) == 0); + ASSERT_TRUE(thread_created); + } + for (uint8_t i = 0; i < kNum_threads_; ++i) { + pthread_join(thread[i], NULL); + } + } + + void ReadLock() { + EXPECT_TRUE(test_rwlock.AcquireForReading()); + EXPECT_TRUE(test_rwlock.Release()); + } + + void ExpectReadLockFail() { + bool temp = test_rwlock.TryAcquireForReading(); + EXPECT_FALSE(temp); + if (temp) { + test_rwlock.Release(); + } + } + + void ExpectWriteLockFail() { + bool temp = test_rwlock.TryAcquireForWriting(); + EXPECT_FALSE(temp); + if (temp) { + test_rwlock.Release(); + } + } + + static void* ReadLock_helper(void *context) { + RWlockTest *temp = reinterpret_cast<RWlockTest *>(context); + temp->ReadLock(); + return NULL; + } + + static void* TryReadLock_helper(void *context) { + RWlockTest *temp = reinterpret_cast<RWlockTest *>(context); + temp->ExpectReadLockFail(); + return NULL; + } + + static void* TryWriteLock_helper(void *context) { + RWlockTest *temp = reinterpret_cast<RWlockTest *>(context); + temp->ExpectWriteLockFail(); + return NULL; + } + + protected: + RWLock test_rwlock; + enum { kNum_threads_ = 5 }; + pthread_t thread[kNum_threads_]; +}; + +TEST_F(RWlockTest, AcquireForReading_ExpectAccessForReading) { + // Lock rw lock for reading + EXPECT_TRUE(test_rwlock.AcquireForReading()); + // Try to lock rw lock for reading again + EXPECT_TRUE(test_rwlock.AcquireForReading()); + // Creating kNumThreads threads, starting them with callback function, waits until all of them finished + ThreadsDispatcher(&RWlockTest::ReadLock_helper); + // Releasing RW locks + EXPECT_TRUE(test_rwlock.Release()); + EXPECT_TRUE(test_rwlock.Release()); +} + +TEST_F(RWlockTest, AcquireForReading_ExpectNoAccessForWriting) { + // Lock rw lock for reading + EXPECT_TRUE(test_rwlock.AcquireForReading()); + // Try to lock rw lock for writing + EXPECT_FALSE(test_rwlock.TryAcquireForWriting()); + // Creating kNumThreads threads, starting them with callback function, waits until all of them finished + ThreadsDispatcher(&RWlockTest::TryWriteLock_helper); + EXPECT_TRUE(test_rwlock.Release()); +} + +TEST_F(RWlockTest, AcquireForWriting_ExpectNoAccessForReading) { + // Lock rw lock for writing + EXPECT_TRUE(test_rwlock.AcquireForWriting()); + // Try to lock rw lock for reading + EXPECT_FALSE(test_rwlock.TryAcquireForReading()); + // Creating kNumThreads threads, starting them with callback function, waits until all of them finished + ThreadsDispatcher(&RWlockTest::TryReadLock_helper); + EXPECT_TRUE(test_rwlock.Release()); +} + +TEST_F(RWlockTest, AcquireForWriting_ExpectNoMoreAccessForWriting) { + // Lock rw lock for writing + EXPECT_TRUE(test_rwlock.AcquireForWriting()); + // Try to lock rw lock for reading + EXPECT_FALSE(test_rwlock.TryAcquireForWriting()); + // Creating kNumThreads threads, starting them with callback function, waits until all of them finished + ThreadsDispatcher(&RWlockTest::TryWriteLock_helper); + EXPECT_TRUE(test_rwlock.Release()); +} + +} // namespace utils +} // namespace components +} // namespace test diff --git a/src/components/utils/test/signals_linux_test.cc b/src/components/utils/test/signals_linux_test.cc new file mode 100644 index 000000000..263f240ec --- /dev/null +++ b/src/components/utils/test/signals_linux_test.cc @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <unistd.h> +#include <assert.h> +#include "gtest/gtest.h" +#include "utils/signals.h" + +namespace test { +namespace components { +namespace utils { + +void handler(int sig) { +} + +TEST(SignalsLinuxTest, SubscribeToTerminateSignal_Positive) { + ASSERT_TRUE(::utils::SubscribeToTerminateSignal(handler)); +} + +TEST(SignalsLinuxTest, SubscribeToFaultSignal_Positive) { + ASSERT_TRUE(::utils::SubscribeToFaultSignal(handler)); +} + +} // namespace utils +} // namespace components +} // namespace test diff --git a/src/components/utils/test/singleton_test.cc b/src/components/utils/test/singleton_test.cc new file mode 100644 index 000000000..8a9e6b31e --- /dev/null +++ b/src/components/utils/test/singleton_test.cc @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gtest/gtest.h" +#include "utils/singleton.h" +#include <pthread.h> + +namespace test { +namespace components { +namespace utils { + +using ::utils::Singleton; + +class SingletonTest : public ::utils::Singleton<SingletonTest> { + public: + + void SetValue(int value) { + test_value = value; + } + int GetValue() { + return test_value; + } + + FRIEND_BASE_SINGLETON_CLASS (SingletonTest); + private: + int test_value; +}; + +TEST(SingletonTest, CreateAndDestroySingleton) { + //assert + ASSERT_EQ(SingletonTest::instance(), SingletonTest::instance()); + ASSERT_EQ(0, SingletonTest::instance()->GetValue()); + ASSERT_TRUE(SingletonTest::exists()); + SingletonTest::instance()->SetValue(5); + ASSERT_EQ(5, SingletonTest::instance()->GetValue()); + + //act + SingletonTest::destroy(); + + //assert + ASSERT_FALSE(SingletonTest::exists()); +} + +TEST(SingletonTest, DestroySingletonTwice) { + //assert + ASSERT_EQ(0, SingletonTest::instance()->GetValue()); + ASSERT_TRUE(SingletonTest::exists()); + + //act + SingletonTest::destroy(); + //assert + ASSERT_FALSE(SingletonTest::exists()); + + //act + SingletonTest::destroy(); + //assert + ASSERT_FALSE(SingletonTest::exists()); +} + +TEST(SingletonTest, DeleteSingletonCreateAnother) { + //arrange + SingletonTest::instance()->SetValue(10); + //assert + ASSERT_TRUE(SingletonTest::exists()); + ASSERT_EQ(10, SingletonTest::instance()->GetValue()); + //act + SingletonTest::destroy(); + //assert + ASSERT_FALSE(SingletonTest::exists()); + + //act + SingletonTest::instance(); + + //assert + ASSERT_EQ(0, SingletonTest::instance()->GetValue()); + ASSERT_TRUE(SingletonTest::exists()); + SingletonTest::destroy(); +} + +void* func_pthread1(void*) { + SingletonTest* singleton_in_other_thread = SingletonTest::instance(); + pthread_exit(singleton_in_other_thread); + return NULL; +} + +void* func_pthread2(void * value) { + SingletonTest * instance = reinterpret_cast<SingletonTest *>(value); + instance->destroy(); + pthread_exit (NULL); + return NULL; +} + +TEST(SingletonTest, CreateSingletonInDifferentThreads) { + //arrange + SingletonTest::instance(); + ASSERT_TRUE(SingletonTest::exists()); + + pthread_t thread1; + pthread_create(&thread1, NULL, func_pthread1, NULL); + + void *instance2; + pthread_join(thread1, &instance2); + SingletonTest * instance_2 = reinterpret_cast<SingletonTest *>(instance2); + + //assert + ASSERT_EQ(SingletonTest::instance(), instance_2); + + //act + SingletonTest::destroy(); + //assert + ASSERT_FALSE(SingletonTest::exists()); +} + +TEST(SingletonTest, CreateDeleteSingletonInDifferentThreads) { + //arrange + pthread_t thread1; + pthread_create(&thread1, NULL, func_pthread1, NULL); + + pthread_t thread2; + pthread_create(&thread2, NULL, func_pthread1, NULL); + + void *instance1; + pthread_join(thread1, &instance1); + SingletonTest * instance_1 = reinterpret_cast<SingletonTest *>(instance1); + + void *instance2; + pthread_join(thread2, &instance2); + SingletonTest * instance_2 = reinterpret_cast<SingletonTest *>(instance2); + + //assert + ASSERT_TRUE(instance_1->exists()); + ASSERT_TRUE(instance_2->exists()); + + ASSERT_EQ(instance_1, instance_2); + + //act + SingletonTest::destroy(); + + //assert + ASSERT_FALSE(instance_1->exists()); + ASSERT_FALSE(instance_2->exists()); +} + +TEST(SingletonTest, DeleteSingletonInDifferentThread) { + //arrange + SingletonTest::instance(); + ASSERT_TRUE(SingletonTest::exists()); + + pthread_t thread1; + pthread_create(&thread1, NULL, func_pthread2, SingletonTest::instance()); + + pthread_join(thread1, NULL); + + //assert + ASSERT_FALSE(SingletonTest::exists()); +} + +} // namespace utils +} // namespace components +} // namespace test diff --git a/src/components/utils/test/stl_utils_test.cc b/src/components/utils/test/stl_utils_test.cc new file mode 100644 index 000000000..62c6d9404 --- /dev/null +++ b/src/components/utils/test/stl_utils_test.cc @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gtest/gtest.h" +#include "utils/stl_utils.h" + +namespace test { +namespace components { +namespace utils { + +using ::utils::StlCollectionDeleter; +using ::utils::StlMapDeleter; + +class TestObject { + public: + ~TestObject() { + } +}; + +typedef std::map<int, TestObject*> TestMap; +typedef std::vector<TestObject*> TestVector; + +TEST(StlDeleter, DestructMapWithOneElement) { + TestMap test_map; + test_map[1] = new TestObject(); + + EXPECT_EQ(1, test_map.size()); + { + StlMapDeleter<TestMap> test_list_deleter_(&test_map); + } + EXPECT_EQ(1, test_map.size()); + EXPECT_EQ(NULL, test_map[1]); +} + +TEST(StlDeleter, DestructMapWithSeveralElements) { + TestMap test_map; + test_map[1] = new TestObject(); + test_map[2] = new TestObject(); + + EXPECT_EQ(2, test_map.size()); + { + StlMapDeleter<TestMap> test_list_deleter_(&test_map); + } + EXPECT_EQ(2, test_map.size()); + EXPECT_EQ(NULL, test_map[1]); + EXPECT_EQ(NULL, test_map[2]); +} + +TEST(StlDeleter, DestructVectorWithOneElement) { + TestVector test_vector; + test_vector.push_back(new TestObject()); + + EXPECT_EQ(1, test_vector.size()); + { + StlCollectionDeleter<TestVector> test_list_deleter_(&test_vector); + } + EXPECT_EQ(1, test_vector.size()); + EXPECT_EQ(NULL, test_vector[0]); +} + +TEST(StlDeleter, DestructVectorWithSeveralElements) { + TestVector test_vector; + test_vector.push_back(new TestObject()); + test_vector.push_back(new TestObject()); + + EXPECT_EQ(2, test_vector.size()); + { + StlCollectionDeleter<TestVector> test_list_deleter_(&test_vector); + } + EXPECT_EQ(2, test_vector.size()); + EXPECT_EQ(NULL, test_vector[0]); + EXPECT_EQ(NULL, test_vector[1]); +} + +} // namespace utils +} // namespace components +} // namespace test diff --git a/src/components/utils/test/system_test.cc b/src/components/utils/test/system_test.cc new file mode 100644 index 000000000..42307998b --- /dev/null +++ b/src/components/utils/test/system_test.cc @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2014, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gmock/gmock.h" +#include "utils/system.h" + +namespace test { +namespace components { +namespace utils { + +using namespace ::utils; + +TEST(SystemTest, Constructor_WithCommandName_ExpectArgsStored) { + // Command creation without any arguments + const std::string test_command("ls"); + System object(test_command); + + // Check if the object was created with correct command + ASSERT_EQ(object.command(), test_command); + int vec_size = object.argv().size(); + ASSERT_EQ(vec_size, 1); +} + +TEST(SystemTest, Constructor_WithFileNameCommandName_ExpectArgsStored) { + // Command creation with 1 argument + const std::string test_command("ls"); + const std::string test_list_args("-la"); + System object(test_command, test_list_args); + + // Check if the object was created with correct command + ASSERT_EQ(object.command(), test_command); + + // Check if actual number of arguments arec correct + int vec_size = object.argv().size(); + ASSERT_EQ(vec_size, 1); // Correct number of arguments is 1 + +} + +TEST(SystemTest, AddTwoArgsToCommand_ExpectTwoArgsAdded) { + const std::string test_command("echo"); + const char* args[] = {"-e", "\b"}; + System object(test_command); + + // Adding arguments + object.Add(args[0]); + object.Add(args[1]); + + // Check if actual number of arguments equal args stored in object + int vec_size = object.argv().size(); + ASSERT_EQ(vec_size, 3); // Correct number of arguments is 3 +} + +TEST(SystemTest, AddTwoArgsToCommand_CheckOrder_ExpectOrderCorrect) { + const std::string test_command("echo"); + const char* args[] = {"-e", "\b"}; + System object(test_command); + + // Adding arguments + object.Add(args[0]); + object.Add(args[1]); + + // Check if the object was appended by correct arguments in correct order + EXPECT_STREQ(object.argv()[1].c_str(), args[0]); + EXPECT_STREQ(object.argv()[2].c_str(), args[1]); +} + + + +TEST(SystemTest, SynchronousInvokeWithExistingCommand_ExpectSuccessfull) { + const std::string test_command("./testscript.sh"); + System object(test_command); + + // Check if Execute() method is working properly with synchronous command invoke + ASSERT_TRUE(object.Execute(true)); +} + +TEST(SystemTest, SynchronousInvokeWithEmptyCommand_IncorrectCommand_ExpectFailed) { + const std::string test_command(""); // any incorrect command + System object(test_command); + + // Check if Execute() method will fail with not correct command (synchronous command invoke) + ASSERT_FALSE(object.Execute(true)); +} + +TEST(SystemTest, ASynchronousInvokeEmptyCommand_InvokeSuccessfull) { + const std::string test_command(""); // Possible to put here any command (existing or incorrect) + const std::string test_list_args("anything"); // as command will never be executed from child process + System object(test_command, test_list_args); // as parrent process does not wait for child process to be finished + + // Check if Execute() method is working properly with asynchronous command invoke + ASSERT_TRUE(object.Execute()); +} + +} // namespace utils +} // namespace components +} // namespace test diff --git a/src/components/utils/test/testscript.sh b/src/components/utils/test/testscript.sh new file mode 100755 index 000000000..c42d8e78b --- /dev/null +++ b/src/components/utils/test/testscript.sh @@ -0,0 +1,5 @@ +#!/bin/sh +echo "Hello, Ford " + + + diff --git a/src/components/utils/test/thread_validator_test.cc b/src/components/utils/test/thread_validator_test.cc new file mode 100644 index 000000000..16d9d1287 --- /dev/null +++ b/src/components/utils/test/thread_validator_test.cc @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <unistd.h> + +#include "gtest/gtest.h" + +#include "utils/threads/thread_validator.h" + +namespace test { +namespace components { +namespace utils { + +using namespace ::threads; + +TEST(ThreadValidatorTest, CompareID_CurrentThreadAndPthread_AreEqual) { + SingleThreadSimpleValidator object; + ASSERT_EQ(object.creation_thread_id(), pthread_self()); + +} + +} // namespace utils +} // namespace components +} // namespace test diff --git a/src/components/utils/test/timer_thread_test.cc b/src/components/utils/test/timer_thread_test.cc new file mode 100644 index 000000000..be25e03b7 --- /dev/null +++ b/src/components/utils/test/timer_thread_test.cc @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2015, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <pthread.h> +#include <iostream> + +#include "lock.h" +#include "macro.h" + +#include "gtest/gtest.h" +#include "utils/conditional_variable.h" +#include "utils/timer_thread.h" + +namespace test { +namespace components { +namespace utils { + +using namespace timer; +using namespace sync_primitives; + +class TimerThreadTest : public ::testing::Test { + public: + TimerThreadTest() + : check_val(0), + val1(3), + val2(4), + wait_val(3000) { + } + + void function() { + AutoLock alock(lock_); + ++check_val; + condvar_.NotifyOne(); + } + + protected: + uint32_t check_val; + Lock lock_; + ConditionalVariable condvar_; + const uint32_t val1; + const uint32_t val2; + const uint32_t wait_val; +}; + +TEST_F(TimerThreadTest, StartTimerThreadWithTimeoutOneSec_ExpectSuccessfullInvokeCallbackFuncOnTimeout) { + // Create Timer with TimerDeleagate + TimerThread<TimerThreadTest> timer("Test", this, &TimerThreadTest::function, + false); + AutoLock alock(lock_); + EXPECT_EQ(0, check_val); + // Start timer with 1 second timeout + timer.start(1); + condvar_.WaitFor(alock, wait_val); + EXPECT_EQ(1, check_val); +} + +TEST_F(TimerThreadTest, StartTimerThreadWithTimeoutOneSecInLoop_ExpectSuccessfullInvokeCallbackFuncOnEveryTimeout) { + // Create Timer with TimerLooperDeleagate + TimerThread<TimerThreadTest> timer("Test", this, &TimerThreadTest::function, + true); + AutoLock alock(lock_); + EXPECT_EQ(0, check_val); + // Start timer with 1 second timeout + timer.start(1); + while (check_val < val2) { + condvar_.WaitFor(alock, wait_val); + } + // Check callback function was called 4 times + EXPECT_EQ(val2, check_val); +} + +TEST_F(TimerThreadTest, StopStartedTimerThreadWithTimeoutOneSecInLoop_ExpectSuccessfullStop) { + // Create Timer with TimerLooperDeleagate + TimerThread<TimerThreadTest> timer("Test", this, &TimerThreadTest::function, + true); + AutoLock alock(lock_); + EXPECT_EQ(0, check_val); + // Start timer with 1 second timeout + timer.start(1); + // Stop timer on 3rd second + while (check_val < val2) { + if (check_val == val1) { + timer.stop(); + break; + } + condvar_.WaitFor(alock, wait_val); + } + EXPECT_EQ(val1, check_val); +} + +TEST_F(TimerThreadTest, ChangeTimeoutForStartedTimerThreadWithTimeoutOneSecInLoop_ExpectSuccessfullStop) { + // Create Timer with TimerLooperDeleagate + TimerThread<TimerThreadTest> timer("Test", this, &TimerThreadTest::function, + true); + AutoLock alock(lock_); + EXPECT_EQ(0, check_val); + // Start timer with 1 second timeout + timer.start(1); + // Change timer timeout on 3rd second + while (check_val < val2) { + if (check_val == val1) { + timer.updateTimeOut(2); + } + condvar_.WaitFor(alock, wait_val); + } + EXPECT_EQ(val2, check_val); +} + +TEST_F(TimerThreadTest, CheckStartedTimerIsRunning_ExpectTrue) { + // Create Timer with TimerLooperDeleagate + TimerThread<TimerThreadTest> timer("Test", this, &TimerThreadTest::function, + true); + AutoLock alock(lock_); + EXPECT_EQ(0, check_val); + // Start timer with 1 second timeout + timer.start(1); + // Change timer timeout on 3rd second + while (check_val < val1) { + condvar_.WaitFor(alock, wait_val); + // Check start is running + EXPECT_TRUE(timer.isRunning()); + } + EXPECT_EQ(val1, check_val); +} + +} // namespace utils +} // namespace components +} // namespace test + |