summaryrefslogtreecommitdiff
path: root/src/components/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/utils')
-rw-r--r--src/components/utils/CMakeLists.txt90
-rw-r--r--src/components/utils/include/utils/back_trace.h6
-rw-r--r--src/components/utils/include/utils/bitstream.h2
-rw-r--r--src/components/utils/include/utils/file_system.h9
-rw-r--r--src/components/utils/include/utils/gen_hash.h50
-rw-r--r--src/components/utils/include/utils/helpers.h119
-rw-r--r--src/components/utils/include/utils/log_message_loop_thread.h1
-rw-r--r--src/components/utils/include/utils/resource_usage.h13
-rw-r--r--src/components/utils/include/utils/signals.h72
-rw-r--r--src/components/utils/include/utils/singleton.h2
-rw-r--r--src/components/utils/include/utils/stl_utils.h27
-rw-r--r--src/components/utils/include/utils/system.h5
-rw-r--r--src/components/utils/include/utils/threads/pulse_thread_delegate.h4
-rw-r--r--src/components/utils/include/utils/threads/thread_validator.h11
-rw-r--r--src/components/utils/src/appenders_loader.cc2
-rw-r--r--src/components/utils/src/back_trace.cc4
-rw-r--r--src/components/utils/src/bitstream.cc2
-rw-r--r--src/components/utils/src/conditional_variable_posix.cc23
-rw-r--r--src/components/utils/src/date_time.cc81
-rw-r--r--src/components/utils/src/file_system.cc17
-rw-r--r--src/components/utils/src/gen_hash.cc53
-rw-r--r--src/components/utils/src/lock_posix.cc57
-rw-r--r--src/components/utils/src/logger_status.cc2
-rw-r--r--src/components/utils/src/resource_usage.cc6
-rw-r--r--src/components/utils/src/rwlock_posix.cc30
-rw-r--r--src/components/utils/src/signals_linux.cc83
-rw-r--r--src/components/utils/src/system.cc21
-rw-r--r--src/components/utils/src/threads/posix_thread.cc299
-rw-r--r--src/components/utils/src/threads/pulse_thread_delegate.cc4
-rw-r--r--src/components/utils/src/threads/thread_delegate.cc6
-rw-r--r--src/components/utils/src/threads/thread_validator.cc15
-rw-r--r--src/components/utils/test/CMakeLists.txt75
-rw-r--r--src/components/utils/test/async_runner_test.cc140
-rw-r--r--src/components/utils/test/auto_trace_test.cc101
-rw-r--r--src/components/utils/test/back_trace_test.cc53
-rw-r--r--src/components/utils/test/bitstream_test.cc230
-rw-r--r--src/components/utils/test/conditional_variable_test.cc132
-rw-r--r--src/components/utils/test/data_accessor_test.cc140
-rw-r--r--src/components/utils/test/date_time_test.cc318
-rw-r--r--src/components/utils/test/file_system_test.cc1166
-rw-r--r--src/components/utils/test/lock_posix_test.cc123
-rw-r--r--src/components/utils/test/log4cxx.properties11
-rw-r--r--src/components/utils/test/log_message_loop_thread_test.cc96
-rw-r--r--src/components/utils/test/message_queue_test.cc169
-rw-r--r--src/components/utils/test/messagemeter_test.cc2
-rw-r--r--src/components/utils/test/posix_thread_test.cc312
-rw-r--r--src/components/utils/test/resource_usage_test.cc100
-rw-r--r--src/components/utils/test/rwlock_posix_test.cc143
-rw-r--r--src/components/utils/test/signals_linux_test.cc55
-rw-r--r--src/components/utils/test/singleton_test.cc189
-rw-r--r--src/components/utils/test/stl_utils_test.cc106
-rw-r--r--src/components/utils/test/system_test.cc125
-rwxr-xr-xsrc/components/utils/test/testscript.sh5
-rw-r--r--src/components/utils/test/thread_validator_test.cc53
-rw-r--r--src/components/utils/test/timer_thread_test.cc158
55 files changed, 4659 insertions, 459 deletions
diff --git a/src/components/utils/CMakeLists.txt b/src/components/utils/CMakeLists.txt
index bbb74dc1e1..3ebabe9043 100644
--- a/src/components/utils/CMakeLists.txt
+++ b/src/components/utils/CMakeLists.txt
@@ -1,56 +1,96 @@
-set(UtilsIncludeDir ${CMAKE_SOURCE_DIR}/src/components/utils/include)
+# 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.
+
+
+set(UTILS_INCLUDE_DIR ${COMPONENTS_DIR}/utils/include)
+set(UTILS_SRC_DIR ${COMPONENTS_DIR}/utils/src)
include_directories (
- ./include
- ../config_profile/include
- ../media_manager/include/
- ../protocol_handler/include/
+ ${UTILS_INCLUDE_DIR}
+ ${COMPONENTS_DIR}/config_profile/include
+ ${COMPONENTS_DIR}/media_manager/include
+ ${COMPONENTS_DIR}/protocol_handler/include
${LOG4CXX_INCLUDE_DIRECTORY}
)
set (SOURCES
- ./src/bitstream.cc
- ./src/conditional_variable_posix.cc
- ./src/file_system.cc
- ./src/threads/posix_thread.cc
- ./src/threads/thread_manager.cc
- ./src/threads/thread_validator.cc
- ./src/lock_posix.cc
- ./src/rwlock_posix.cc
- ./src/date_time.cc
- ./src/signals_linux.cc
- ./src/system.cc
- ./src/resource_usage.cc
- ./src/appenders_loader.cc
+ ${UTILS_SRC_DIR}/bitstream.cc
+ ${UTILS_SRC_DIR}/conditional_variable_posix.cc
+ ${UTILS_SRC_DIR}/file_system.cc
+ ${UTILS_SRC_DIR}/threads/posix_thread.cc
+ ${UTILS_SRC_DIR}/threads/thread_delegate.cc
+ ${UTILS_SRC_DIR}/threads/thread_validator.cc
+ ${UTILS_SRC_DIR}/threads/async_runner.cc
+ ${UTILS_SRC_DIR}/lock_posix.cc
+ ${UTILS_SRC_DIR}/rwlock_posix.cc
+ ${UTILS_SRC_DIR}/date_time.cc
+ ${UTILS_SRC_DIR}/signals_linux.cc
+ ${UTILS_SRC_DIR}/system.cc
+ ${UTILS_SRC_DIR}/resource_usage.cc
+ ${UTILS_SRC_DIR}/appenders_loader.cc
+ ${UTILS_SRC_DIR}/gen_hash.cc
)
if(ENABLE_LOG)
list(APPEND SOURCES
- ./src/push_log.cc
- ./src/log_message_loop_thread.cc
- ./src/logger_status.cc
+ ${UTILS_SRC_DIR}/push_log.cc
+ ${UTILS_SRC_DIR}/log_message_loop_thread.cc
+ ${UTILS_SRC_DIR}/logger_status.cc
+ ${UTILS_SRC_DIR}/auto_trace.cc
+ ${UTILS_SRC_DIR}/logger.cc
)
endif()
if (BUILD_BACKTRACE_SUPPORT)
list(APPEND SOURCES
- ./src/back_trace.cc
+ ${UTILS_SRC_DIR}/back_trace.cc
)
endif()
if (CMAKE_SYSTEM_NAME STREQUAL "QNX")
list(APPEND SOURCES
- ./src/threads/pulse_thread_delegate.cc
+ ${UTILS_SRC_DIR}/threads/pulse_thread_delegate.cc
)
endif()
add_library("Utils" SHARED ${SOURCES})
+if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+ list(APPEND LIBRARIES dl)
+endif()
+
+
if(ENABLE_LOG)
list(APPEND LIBRARIES log4cxx -L${LOG4CXX_LIBS_DIRECTORY})
list(APPEND LIBRARIES apr-1 -L${APR_LIBS_DIRECTORY})
list(APPEND LIBRARIES aprutil-1 -L${APR_UTIL_LIBS_DIRECTORY})
- target_link_libraries("Utils" ${LIBRARIES})
ADD_DEPENDENCIES(Utils install-3rd_party_logger)
endif()
@@ -58,6 +98,8 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
target_link_libraries("Utils" pthread ${RTLIB})
endif()
+target_link_libraries("Utils" ${LIBRARIES})
+
if(BUILD_TESTS)
add_subdirectory(test)
endif()
diff --git a/src/components/utils/include/utils/back_trace.h b/src/components/utils/include/utils/back_trace.h
index 7f8912faf9..f2410e36bc 100644
--- a/src/components/utils/include/utils/back_trace.h
+++ b/src/components/utils/include/utils/back_trace.h
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (c) 2013, Ford Motor Company
* All rights reserved.
*
@@ -61,10 +61,10 @@ class Backtrace {
// Captured symbols in order from topmost stack frame to last captured
std::vector<std::string> CallStack() const;
- threads::Thread::Id ThreadId() const;
+ threads::PlatformThreadHandle ThreadId() const;
private:
- threads::Thread::Id thread_id_;
+ threads::PlatformThreadHandle thread_id_;
std::vector<void*> backtrace_;
};
diff --git a/src/components/utils/include/utils/bitstream.h b/src/components/utils/include/utils/bitstream.h
index cba15abd8b..9bf41d187f 100644
--- a/src/components/utils/include/utils/bitstream.h
+++ b/src/components/utils/include/utils/bitstream.h
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (c) 2013, Ford Motor Company
* All rights reserved.
*
diff --git a/src/components/utils/include/utils/file_system.h b/src/components/utils/include/utils/file_system.h
index d68ec484f9..7b69527606 100644
--- a/src/components/utils/include/utils/file_system.h
+++ b/src/components/utils/include/utils/file_system.h
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (c) 2013, Ford Motor Company
* All rights reserved.
*
@@ -234,6 +234,13 @@ const std::string ConvertPathForURL(const std::string& path);
*/
bool CreateFile(const std::string& path);
+/**
+ * @brief Get modification time of file
+ * @param path Path to file
+ * @return Modification time in nanoseconds
+ */
+uint64_t GetFileModificationTime(const std::string& path);
+
void remove_directory_content(const std::string& directory_name);
} // namespace file_system
diff --git a/src/components/utils/include/utils/gen_hash.h b/src/components/utils/include/utils/gen_hash.h
new file mode 100644
index 0000000000..e4102d36db
--- /dev/null
+++ b/src/components/utils/include/utils/gen_hash.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#ifndef SRC_COMPONENTS_UTILS_INCLUDE_UTILS_GEN_HASH_H_
+#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_GEN_HASH_H_
+
+#include <string>
+
+namespace utils {
+
+/**
+ * @brief generate random alphanumeric string of specified length
+ * @param size length of random string
+ * @return random string
+ */
+
+const std::string gen_hash(size_t size);
+
+} // namespace utils
+
+#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_GEN_HASH_H_
diff --git a/src/components/utils/include/utils/helpers.h b/src/components/utils/include/utils/helpers.h
new file mode 100644
index 0000000000..e616dd56c1
--- /dev/null
+++ b/src/components/utils/include/utils/helpers.h
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+#ifndef SRC_COMPONENTS_UTILS_INCLUDE_UTILS_HELPERS_H
+#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_HELPERS_H
+
+/**
+ * These helpers allows to simplify compare strategy between some objects.
+ * Suppose user has some enum with value E with some numbers of possible values
+ * enum E {V1, V2, V3, V5};
+ * So we want to know if some user-input value is belong to one of the enum's subset.
+ * Usually user has to do next routine
+ *
+ * E input_value = V3;
+ * if (input_value == V1 || input_value == V2 || input_value == V3) {
+ * do_some_stuff_here;
+ * }
+ *
+ * How it suppose to be with these helpers methods:
+ *
+ * E input_value = V3;
+ * if (Compare<E, EQ, ONE>(input_value, V1, V2, V3)) {
+ * do_some_stuff;
+ * }
+ *
+ * Also User is able to easily change compare startegy by using some set of
+ * predefined startegies.
+ */
+namespace helpers {
+
+ template<typename T>
+ bool EQ (T what, T to) {
+ return what == to;
+ }
+
+ template<typename T>
+ bool NEQ (T what, T to) {
+ return !EQ<T>(what, to);
+ }
+
+ template<class U = bool>
+ bool ALL (U what, U to) {
+ return what && to;
+ }
+
+ template<class U = bool>
+ bool ONE (U what, U to) {
+ return what || to;
+ }
+
+ template <typename T,
+ bool (*CompareType)(T ,T),
+ bool (*CmpStrategy)(bool ,bool)>
+ bool Compare (T what, T to) {
+ return CompareType(what, to);
+ }
+
+ template <typename T,
+ bool (*CompareType)(T ,T),
+ bool (*CmpStrategy)(bool, bool)>
+ bool Compare(T what, T to, T to1) {
+ return CmpStrategy(Compare<T, CompareType, CmpStrategy>(what, to),
+ Compare<T, CompareType, CmpStrategy>(what, to1));
+ }
+
+ template <typename T,
+ bool (*CompareType)(T ,T),
+ bool (*CmpStrategy)(bool, bool)>
+ bool Compare(T what, T to, T to1, T to2) {
+ return CmpStrategy(Compare<T, CompareType, CmpStrategy>(what, to, to1),
+ Compare<T, CompareType, CmpStrategy>(what, to2));
+ }
+
+ template <typename T,
+ bool (*CompareType)(T ,T),
+ bool (*CmpStrategy)(bool, bool)>
+ bool Compare(T what, T to, T to1, T to2, T to3) {
+ return CmpStrategy(Compare<T, CompareType, CmpStrategy>(what, to, to1, to2),
+ Compare<T, CompareType, CmpStrategy>(what, to3));
+ }
+
+ template <typename T,
+ bool (*CompareType)(T ,T),
+ bool (*CmpStrategy)(bool, bool)>
+ bool Compare(T what, T to, T to1, T to2, T to3, T to4) {
+ return CmpStrategy(Compare<T, CompareType, CmpStrategy>(what, to, to1, to2, to3),
+ Compare<T, CompareType, CmpStrategy>(what, to4));
+ }
+}
+
+#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_HELPERS_H
diff --git a/src/components/utils/include/utils/log_message_loop_thread.h b/src/components/utils/include/utils/log_message_loop_thread.h
index b23a246e13..87b6c7e531 100644
--- a/src/components/utils/include/utils/log_message_loop_thread.h
+++ b/src/components/utils/include/utils/log_message_loop_thread.h
@@ -37,6 +37,7 @@
#include <queue>
#include <log4cxx/logger.h>
+#include "utils/macro.h"
#include "utils/threads/message_loop_thread.h"
#include "utils/singleton.h"
diff --git a/src/components/utils/include/utils/resource_usage.h b/src/components/utils/include/utils/resource_usage.h
index a8fa4aa7d9..ff90b2c22f 100644
--- a/src/components/utils/include/utils/resource_usage.h
+++ b/src/components/utils/include/utils/resource_usage.h
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (c) 2014, Ford Motor Company
* All rights reserved.
*
@@ -38,6 +38,7 @@
#include <sys/procfs.h>
#endif
+#include "utils/macro.h"
#include <string>
#include <iostream>
@@ -120,6 +121,16 @@ class Resources {
private:
+#ifdef BUILD_TESTS
+ friend class ResourceUsagePrivateTest;
+ FRIEND_TEST(ResourceUsagePrivateTest, ReadStatFileTest);
+ FRIEND_TEST(ResourceUsagePrivateTest, GetProcInfoTest);
+ FRIEND_TEST(ResourceUsagePrivateTest, GetMemInfoTest);
+ FRIEND_TEST(ResourceUsagePrivateTest, GetStatPathTest_FileExists);
+ FRIEND_TEST(ResourceUsagePrivateTest, GetStatPathTest_ReadFile);
+ FRIEND_TEST(ResourceUsagePrivateTest, GetProcPathTest);
+#endif
+
/*
* @brief reads /proc/PID/stat file on linux
* do not work on QNX ( return false, output wan't be changed )
diff --git a/src/components/utils/include/utils/signals.h b/src/components/utils/include/utils/signals.h
index 28e8afd9d6..6c91836309 100644
--- a/src/components/utils/include/utils/signals.h
+++ b/src/components/utils/include/utils/signals.h
@@ -1,41 +1,49 @@
/*
-* 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.
-*/
+ * 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.
+ */
#ifndef SRC_COMPONENTS_UTILS_INCLUDE_UTILS_SIGNALS_H_
#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_SIGNALS_H_
+#ifdef __QNXNTO__
+typedef void (*sighandler_t) (int);
+#else
+#include <signal.h>
+#endif
+
namespace utils {
-bool SubscribeToTerminateSignal(void (*func)(int32_t p));
-bool ResetSubscribeToTerminateSignal();
+
+bool SubscribeToTerminateSignal(sighandler_t func);
+bool SubscribeToFaultSignal(sighandler_t func);
+
} // namespace utils
#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_SIGNALS_H_
diff --git a/src/components/utils/include/utils/singleton.h b/src/components/utils/include/utils/singleton.h
index d7b625e0a1..41face4f2f 100644
--- a/src/components/utils/include/utils/singleton.h
+++ b/src/components/utils/include/utils/singleton.h
@@ -28,7 +28,7 @@
* 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.
-*/
+ */
#ifndef SRC_COMPONENTS_UTILS_INCLUDE_UTILS_SINGLETON_H_
#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_SINGLETON_H_
diff --git a/src/components/utils/include/utils/stl_utils.h b/src/components/utils/include/utils/stl_utils.h
index f525c6429f..70fbadbd5e 100644
--- a/src/components/utils/include/utils/stl_utils.h
+++ b/src/components/utils/include/utils/stl_utils.h
@@ -1,5 +1,5 @@
-/**
- * Copyright (c) 2013, Ford Motor Company
+/*
+ * Copyright (c) 2015, Ford Motor Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -44,14 +44,15 @@ template<class T>
class StlCollectionDeleter {
public:
typedef T Collection;
- StlCollectionDeleter(T* collection): collection_(collection) {
+ StlCollectionDeleter(T* collection)
+ : collection_(collection) {
DCHECK(collection_);
}
~StlCollectionDeleter() {
- for (typename Collection::iterator i = collection_->begin(),
- end = collection_->end();
- i != end; ++i) {
+ for (typename Collection::iterator i = collection_->begin(), end =
+ collection_->end(); i != end; ++i) {
delete *i;
+ *i = NULL;
}
}
private:
@@ -62,20 +63,22 @@ template<class T>
class StlMapDeleter {
public:
typedef T Collection;
- StlMapDeleter(T* collection): collection_(collection) {
+ StlMapDeleter(T* collection)
+ : collection_(collection) {
DCHECK(collection_);
}
~StlMapDeleter() {
- for (typename Collection::iterator i = collection_->begin(),
- end = collection_->end();
- i != end; ++i) {
+ for (typename Collection::iterator i = collection_->begin(), end =
+ collection_->end(); i != end; ++i) {
delete i->second;
+ i->second = NULL;
}
+
}
private:
Collection* collection_;
};
-} // namespace utils
+} // namespace utils
-#endif /* SRC_COMPONENTS_UTILS_INCLUDE_UTILS_STL_UTILS_H_ */
+#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_STL_UTILS_H_
diff --git a/src/components/utils/include/utils/system.h b/src/components/utils/include/utils/system.h
index 16bdc03673..3b34d78526 100644
--- a/src/components/utils/include/utils/system.h
+++ b/src/components/utils/include/utils/system.h
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (c) 2014, Ford Motor Company
* All rights reserved.
*
@@ -76,6 +76,9 @@ class System {
*/
bool Execute(bool wait);
+ std::string command() const;
+ std::vector<std::string> argv() const;
+
private:
/**
* Command for executing
diff --git a/src/components/utils/include/utils/threads/pulse_thread_delegate.h b/src/components/utils/include/utils/threads/pulse_thread_delegate.h
index bb109bde94..207b64caaf 100644
--- a/src/components/utils/include/utils/threads/pulse_thread_delegate.h
+++ b/src/components/utils/include/utils/threads/pulse_thread_delegate.h
@@ -57,7 +57,7 @@ class PulseThreadDelegate : public ThreadDelegate {
*/
PulseThreadDelegate();
virtual void threadMain();
- virtual bool exitThreadMain();
+ virtual void exitThreadMain();
protected:
/**
@@ -86,7 +86,7 @@ class PulseThreadDelegate : public ThreadDelegate {
private:
enum {PULSE_CODE = _PULSE_CODE_MINAVAIL + 1};
- bool run_;
+ volatile bool run_;
int chid_;
int coid_;
};
diff --git a/src/components/utils/include/utils/threads/thread_validator.h b/src/components/utils/include/utils/threads/thread_validator.h
index def1994b76..dc2d138e2e 100644
--- a/src/components/utils/include/utils/threads/thread_validator.h
+++ b/src/components/utils/include/utils/threads/thread_validator.h
@@ -1,5 +1,5 @@
-/**
- * Copyright (c) 2013, Ford Motor Company
+/*
+ * Copyright (c) 2014, Ford Motor Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -67,8 +67,9 @@ class SingleThreadSimpleValidator {
// This method should be called in every public method
// of classes being checked for absence of concurrent access
void AssertRunningOnCreationThread() const;
+ PlatformThreadHandle creation_thread_id() const;
private:
- const Thread::Id creation_thread_id_;
+ const PlatformThreadHandle creation_thread_id_;
};
@@ -91,13 +92,13 @@ class SingleThreadValidator {
// Must be called prior to transferring object being validated to
// another thread or when passing it back
- void PassToThread(Thread::Id thread_id) const;
+ void PassToThread(PlatformThreadHandle thread_id) const;
// This method should be called in every public method
// of classes being checked for absence of unintended concurrent
// access
void AssertRunningOnValidThread() const;
private:
- mutable Thread::Id owning_thread_id_;
+ mutable PlatformThreadHandle owning_thread_id_;
};
} // namespace threads
diff --git a/src/components/utils/src/appenders_loader.cc b/src/components/utils/src/appenders_loader.cc
index cbbd039060..9741bd1b8d 100644
--- a/src/components/utils/src/appenders_loader.cc
+++ b/src/components/utils/src/appenders_loader.cc
@@ -39,7 +39,7 @@ namespace utils {
AppendersLoader appenders_loader;
AppendersLoader::AppendersLoader() {
- handle_ = dlopen("libappenders.so", RTLD_LAZY | RTLD_NODELETE);
+ handle_ = dlopen("libappenders.so", RTLD_LAZY);
}
AppendersLoader::~AppendersLoader() {
diff --git a/src/components/utils/src/back_trace.cc b/src/components/utils/src/back_trace.cc
index 23b1b4d1e9..f49c60b467 100644
--- a/src/components/utils/src/back_trace.cc
+++ b/src/components/utils/src/back_trace.cc
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (c) 2013, Ford Motor Company
* All rights reserved.
*
@@ -89,7 +89,7 @@ vector<string> Backtrace::CallStack() const {
return callstack;
}
-Thread::Id Backtrace::ThreadId() const {
+threads::PlatformThreadHandle Backtrace::ThreadId() const {
return thread_id_;
}
diff --git a/src/components/utils/src/bitstream.cc b/src/components/utils/src/bitstream.cc
index c616b1ae4a..ae353b44c6 100644
--- a/src/components/utils/src/bitstream.cc
+++ b/src/components/utils/src/bitstream.cc
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (c) 2013, Ford Motor Company
* All rights reserved.
*
diff --git a/src/components/utils/src/conditional_variable_posix.cc b/src/components/utils/src/conditional_variable_posix.cc
index a89f8cab65..2928cac9db 100644
--- a/src/components/utils/src/conditional_variable_posix.cc
+++ b/src/components/utils/src/conditional_variable_posix.cc
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (c) 2013, Ford Motor Company
* All rights reserved.
*
@@ -83,14 +83,29 @@ void ConditionalVariable::Broadcast() {
}
-void ConditionalVariable::Wait(AutoLock& auto_lock) {
+bool ConditionalVariable::Wait(Lock& lock) {
+ lock.AssertTakenAndMarkFree();
+ int32_t wait_status = pthread_cond_wait(&cond_var_,
+ &lock.mutex_);
+ lock.AssertFreeAndMarkTaken();
+ if (wait_status != 0) {
+ LOG4CXX_ERROR(logger_, "Failed to wait for conditional variable");
+ return false;
+ }
+ return true;
+}
+
+bool ConditionalVariable::Wait(AutoLock& auto_lock) {
Lock& lock = auto_lock.GetLock();
lock.AssertTakenAndMarkFree();
int32_t wait_status = pthread_cond_wait(&cond_var_,
&lock.mutex_);
lock.AssertFreeAndMarkTaken();
- if (wait_status != 0)
+ if (wait_status != 0) {
LOG4CXX_ERROR(logger_, "Failed to wait for conditional variable");
+ return false;
+ }
+ return true;
}
ConditionalVariable::WaitStatus ConditionalVariable::WaitFor(
@@ -104,7 +119,6 @@ ConditionalVariable::WaitStatus ConditionalVariable::WaitFor(
(milliseconds % kMillisecondsPerSecond) * kNanosecondsPerMillisecond;
wait_interval.tv_sec += wait_interval.tv_nsec / kNanosecondsPerSecond;
wait_interval.tv_nsec %= kNanosecondsPerSecond;
-
Lock& lock = auto_lock.GetLock();
lock.AssertTakenAndMarkFree();
int32_t timedwait_status = pthread_cond_timedwait(&cond_var_,
@@ -129,7 +143,6 @@ ConditionalVariable::WaitStatus ConditionalVariable::WaitFor(
LOG4CXX_ERROR(logger_, "Failed to timewait for conditional variable timedwait_status: " << timedwait_status);
}
}
-
return wait_status;
}
diff --git a/src/components/utils/src/date_time.cc b/src/components/utils/src/date_time.cc
index f190951647..42a199e0fb 100644
--- a/src/components/utils/src/date_time.cc
+++ b/src/components/utils/src/date_time.cc
@@ -1,49 +1,50 @@
/*
-* 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.
-*/
+ * 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 <sys/time.h>
#include <stdint.h>
#include "utils/date_time.h"
+
namespace date_time {
-TimevalStruct DateTime::getCurrentTime() {
- TimevalStruct currentTime;
- timezone timeZone;
+ TimevalStruct DateTime::getCurrentTime() {
+ TimevalStruct currentTime;
+ timezone timeZone;
- gettimeofday(&currentTime, &timeZone);
+ gettimeofday(&currentTime, &timeZone);
- return currentTime;
-}
+ return currentTime;
+ }
int64_t date_time::DateTime::getSecs(const TimevalStruct &time) {
return static_cast<int64_t>(time.tv_sec);
@@ -100,3 +101,11 @@ TimeCompare date_time::DateTime::compareTime(const TimevalStruct &time1, const T
}
} // namespace date_time
+
+bool operator<(const TimevalStruct& time1, const TimevalStruct& time2) {
+ return date_time::DateTime::Less(time1, time2);
+}
+
+bool operator==(const TimevalStruct& time1, const TimevalStruct& time2) {
+ return date_time::DateTime::Equal(time1, time2);
+}
diff --git a/src/components/utils/src/file_system.cc b/src/components/utils/src/file_system.cc
index 64e021a6f1..69efcad863 100644
--- a/src/components/utils/src/file_system.cc
+++ b/src/components/utils/src/file_system.cc
@@ -325,10 +325,12 @@ std::vector<std::string> file_system::ListFiles(
}
closedir(directory);
+
+ }
+
#ifdef __QNXNTO__
- delete[] direntbuffer;
+ delete[] direntbuffer;
#endif
- }
return listFiles;
}
@@ -410,3 +412,14 @@ bool file_system::CreateFile(const std::string& path) {
return true;
}
}
+
+
+uint64_t file_system::GetFileModificationTime(const std::string& path) {
+ struct stat info;
+ stat(path.c_str(), &info);
+#ifndef __QNXNTO__
+ return static_cast<uint64_t>(info.st_mtim.tv_nsec);
+#else
+ return static_cast<uint64_t>(info.st_mtime);
+#endif
+}
diff --git a/src/components/utils/src/gen_hash.cc b/src/components/utils/src/gen_hash.cc
new file mode 100644
index 0000000000..6ac5c217c3
--- /dev/null
+++ b/src/components/utils/src/gen_hash.cc
@@ -0,0 +1,53 @@
+/*
+ * 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 "utils/gen_hash.h"
+
+#include <cstdlib>
+
+namespace utils {
+
+const std::string gen_hash(size_t size) {
+ static const char symbols[] = "0123456789"
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ static const size_t capacity = sizeof(symbols) - 1;
+
+ std::string hash(size, '\0');
+ for (std::string::iterator i = hash.begin(); i != hash.end(); ++i) {
+ int index = std::rand() % capacity;
+ *i = symbols[index];
+ }
+ return hash;
+}
+
+} // namespace utils
diff --git a/src/components/utils/src/lock_posix.cc b/src/components/utils/src/lock_posix.cc
index f75b7ee9ea..d2837708fa 100644
--- a/src/components/utils/src/lock_posix.cc
+++ b/src/components/utils/src/lock_posix.cc
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (c) 2013, Ford Motor Company
* All rights reserved.
*
@@ -34,6 +34,8 @@
#include <errno.h>
#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
#include "utils/logger.h"
@@ -43,11 +45,11 @@ CREATE_LOGGERPTR_GLOBAL(logger_, "Utils")
Lock::Lock()
#ifndef NDEBUG
- : lock_taken_(0),
- is_mutex_recursive_(false)
+ : lock_taken_(0),
+ is_mutex_recursive_(false)
#endif // NDEBUG
{
- int32_t status = pthread_mutex_init(&mutex_, NULL);
+ const int32_t status = pthread_mutex_init(&mutex_, NULL);
if (status != 0) {
LOG4CXX_ERROR(logger_, "Failed to initialize mutex");
}
@@ -55,8 +57,8 @@ Lock::Lock()
Lock::Lock(bool is_mutex_recursive)
#ifndef NDEBUG
- : lock_taken_(0),
- is_mutex_recursive_(is_mutex_recursive)
+ : lock_taken_(0),
+ is_mutex_recursive_(is_mutex_recursive)
#endif // NDEBUG
{
int32_t status;
@@ -67,6 +69,7 @@ Lock::Lock(bool is_mutex_recursive)
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
status = pthread_mutex_init(&mutex_, &attr);
+ pthread_mutexattr_destroy(&attr);
} else {
status = pthread_mutex_init(&mutex_, NULL);
}
@@ -79,54 +82,41 @@ Lock::Lock(bool is_mutex_recursive)
Lock::~Lock() {
#ifndef NDEBUG
if (lock_taken_ > 0) {
- LOG4CXX_ERROR(logger_, "Destroying non-released mutex");
+ LOG4CXX_ERROR(logger_, "Destroying non-released mutex " << &mutex_);
}
#endif
int32_t status = pthread_mutex_destroy(&mutex_);
if (status != 0) {
- LOG4CXX_ERROR(logger_, "Failed to destroy mutex");
+ LOG4CXX_ERROR(logger_, "Failed to destroy mutex " << &mutex_ << ": " << strerror(status));
}
}
void Lock::Acquire() {
- int32_t status = pthread_mutex_lock(&mutex_);
+ const int32_t status = pthread_mutex_lock(&mutex_);
if (status != 0) {
- LOG4CXX_ERROR(logger_, "Failed to acquire mutex");
+ LOG4CXX_ERROR(logger_, "Failed to acquire mutex " << &mutex_ << ": " << strerror(status));
+ } else {
+ AssertFreeAndMarkTaken();
}
- AssertFreeAndMarkTaken();
}
void Lock::Release() {
AssertTakenAndMarkFree();
- int32_t status = pthread_mutex_unlock(&mutex_);
+ const int32_t status = pthread_mutex_unlock(&mutex_);
if (status != 0) {
- LOG4CXX_ERROR(logger_, "Failed to unlock mutex");
+ LOG4CXX_ERROR(logger_, "Failed to unlock mutex" << &mutex_ << ": " << strerror(status));
}
}
bool Lock::Try() {
- bool ackquired = false;
-#ifndef NDEBUG
- if ((lock_taken_ > 0) && !is_mutex_recursive_) {
- LOG4CXX_ERROR(logger_, "Trying to lock already taken not recurcive mutex");
- }
-#endif
- switch(pthread_mutex_trylock(&mutex_)) {
- case 0: {
- ackquired = true;
+ const int32_t status = pthread_mutex_trylock(&mutex_);
+ if (status == 0) {
#ifndef NDEBUG
- lock_taken_++;
+ lock_taken_++;
#endif
- } break;
- case EBUSY: {
- ackquired = false;
- } break;
- default: {
- ackquired = false;
- LOG4CXX_ERROR(logger_, "Failed to try lock the mutex");
- }
+ return true;
}
- return ackquired;
+ return false;
}
#ifndef NDEBUG
@@ -146,5 +136,4 @@ void Lock::AssertTakenAndMarkFree() {
}
#endif
-
-} // namespace sync_primitives
+} // namespace sync_primitives
diff --git a/src/components/utils/src/logger_status.cc b/src/components/utils/src/logger_status.cc
index be341b9add..ea9dfa3f22 100644
--- a/src/components/utils/src/logger_status.cc
+++ b/src/components/utils/src/logger_status.cc
@@ -34,6 +34,6 @@
namespace logger {
-LoggerStatus logger_status = LoggerThreadNotCreated;
+volatile LoggerStatus logger_status = LoggerThreadNotCreated;
} // namespace logger
diff --git a/src/components/utils/src/resource_usage.cc b/src/components/utils/src/resource_usage.cc
index aaa9c1b4a7..62c8d25b82 100644
--- a/src/components/utils/src/resource_usage.cc
+++ b/src/components/utils/src/resource_usage.cc
@@ -124,6 +124,8 @@ bool Resources::GetProcInfo(Resources::PidStats& output) {
if (0 >= fd) {
LOG4CXX_ERROR(logger_, "Failed open process proc file : " << GetProcPath() <<
"; error no : " << strerror( errno ) );
+
+ close(fd);
return false;
}
devctl(fd, DCMD_PROC_INFO, &output, sizeof(output), 0);
@@ -148,14 +150,14 @@ bool Resources::GetMemInfo(Resources::MemInfo &output) {
std::string as_path = GetStatPath();
struct stat st;
struct _dir* proc_dir = 0;
- struct dirent* proc_entry = 0;
if (0 == (proc_dir = opendir(proc))) {
LOG4CXX_ERROR(logger_, "Unable to access to " << proc);
result = false;
return result;
}
- if (0 == (proc_entry = readdir(proc_dir))) {
+ if (0 == readdir(proc_dir)) {
LOG4CXX_ERROR(logger_, "Unable to read : " << proc_dir);
+ closedir(proc_dir);
result = false;
return result;
}
diff --git a/src/components/utils/src/rwlock_posix.cc b/src/components/utils/src/rwlock_posix.cc
index 7cc850b25b..08edb8cb0c 100644
--- a/src/components/utils/src/rwlock_posix.cc
+++ b/src/components/utils/src/rwlock_posix.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
@@ -49,22 +49,44 @@ RWLock::~RWLock() {
}
}
-void RWLock::AcquireForReading() {
+bool RWLock::AcquireForReading() {
if (pthread_rwlock_rdlock(&rwlock_) != 0) {
LOG4CXX_ERROR(logger_, "Failed to acquire rwlock for reading");
+ return false;
}
+ return true;
}
-void RWLock::AcquireForWriting() {
+bool RWLock::TryAcquireForReading() {
+ if (pthread_rwlock_tryrdlock(&rwlock_) != 0) {
+ LOG4CXX_ERROR(logger_, "Failed to acquire rwlock for reading");
+ return false;
+ }
+ return true;
+}
+
+bool RWLock::AcquireForWriting() {
if (pthread_rwlock_wrlock(&rwlock_) != 0) {
LOG4CXX_ERROR(logger_, "Failed to acquire rwlock for writing");
+ return false;
+ }
+ return true;
+}
+
+bool RWLock::TryAcquireForWriting() {
+ if (pthread_rwlock_trywrlock(&rwlock_) != 0) {
+ LOG4CXX_ERROR(logger_, "Failed to acquire rwlock for writing");
+ return false;
}
+ return true;
}
-void RWLock::Release() {
+bool RWLock::Release() {
if (pthread_rwlock_unlock(&rwlock_) != 0) {
LOG4CXX_ERROR(logger_, "Failed to release rwlock");
+ return false;
}
+ return true;
}
} // namespace sync_primitives
diff --git a/src/components/utils/src/signals_linux.cc b/src/components/utils/src/signals_linux.cc
index 3ded6a5877..2e598d1b0f 100644
--- a/src/components/utils/src/signals_linux.cc
+++ b/src/components/utils/src/signals_linux.cc
@@ -1,54 +1,63 @@
/*
-* 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.
-*/
+ * 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 <csignal>
#include <cstdlib>
#include <stdint.h>
+#include "utils/signals.h"
+
namespace utils {
-bool SubscribeToTerminateSignal(void (*func)(int32_t p)) {
+bool SubscribeToTerminateSignal(sighandler_t func) {
struct sigaction act;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
- return (sigaction(SIGINT, &act, NULL) == 0)
- && (sigaction(SIGTERM, &act, NULL) == 0);
+ bool sigint_subscribed = (sigaction(SIGINT, &act, NULL) == 0);
+ bool sigterm_subscribed = (sigaction(SIGTERM, &act, NULL) == 0);
+
+ return sigint_subscribed && sigterm_subscribed;
}
-bool ResetSubscribeToTerminateSignal() {
- void (*prev_func)(int32_t p);
- prev_func = signal(SIGINT, SIG_DFL);
- return (SIG_ERR != prev_func);
+bool SubscribeToFaultSignal(sighandler_t func) {
+ struct sigaction act;
+ act.sa_handler = func;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_RESETHAND; // we only want to catch SIGSEGV once to flush logger queue
+
+ bool sigsegv_subscribed = (sigaction(SIGSEGV, &act, NULL) == 0);
+
+ return sigsegv_subscribed;
}
} // namespace utils
diff --git a/src/components/utils/src/system.cc b/src/components/utils/src/system.cc
index ee90315db0..70659419a7 100644
--- a/src/components/utils/src/system.cc
+++ b/src/components/utils/src/system.cc
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (c) 2014, Ford Motor Company
* All rights reserved.
*
@@ -42,6 +42,7 @@
#include <algorithm>
#include <functional>
#include <cstring>
+#include <iostream>
#include "utils/logger.h"
#include "utils/system.h"
@@ -66,15 +67,23 @@ System::System(const std::string& file, const std::string& command)
argv_.push_back(command);
}
-bool System::Execute() {
- return Execute(false);
-}
-
System& System::Add(const std::string& arg) {
argv_.push_back(arg);
return *this;
}
+std::string System::command() const {
+ return command_;
+}
+
+std::vector<std::string> System::argv() const {
+ return argv_;
+}
+
+bool System::Execute() {
+ return Execute(false);
+}
+
#ifdef __QNX__
bool System::Execute(bool wait) {
@@ -89,7 +98,7 @@ bool System::Execute(bool wait) {
if (ret == -1) {
LOG4CXX_ERROR(logger_, "Can't execute command: " << command_
- << " Errno is: " << std::strerror(errno));
+ << " Errno is: " << std::strerror(errno));
return false;
}
diff --git a/src/components/utils/src/threads/posix_thread.cc b/src/components/utils/src/threads/posix_thread.cc
index 3f7e006eca..82dd8c59b3 100644
--- a/src/components/utils/src/threads/posix_thread.cc
+++ b/src/components/utils/src/threads/posix_thread.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
@@ -31,125 +31,168 @@
*/
#include <errno.h>
-
#include <limits.h>
#include <stddef.h>
#include <signal.h>
-#include "utils/atomic.h"
+#ifdef BUILD_TESTS
+// Temporary fix for UnitTest until APPLINK-9987 is resolved
+#include <unistd.h>
+#endif
+
#include "utils/threads/thread.h"
-#include "utils/threads/thread_manager.h"
-#include "utils/logger.h"
#include "pthread.h"
-
+#include "utils/atomic.h"
+#include "utils/threads/thread_delegate.h"
+#include "utils/logger.h"
#ifndef __QNXNTO__
- const int EOK = 0;
+const int EOK = 0;
#endif
#if defined(OS_POSIX)
- const size_t THREAD_NAME_SIZE = 15;
+const size_t THREAD_NAME_SIZE = 15;
#endif
namespace threads {
CREATE_LOGGERPTR_GLOBAL(logger_, "Utils")
-namespace {
-
-static void* threadFunc(void* arg) {
- LOG4CXX_INFO(logger_, "Thread #" << pthread_self() << " started successfully");
- threads::Thread* thread = static_cast<threads::Thread*>(arg);
- threads::ThreadDelegate* delegate = thread->delegate();
- delegate->threadMain();
- thread->set_running(false);
- MessageQueue<ThreadManager::ThreadDesc>& threads = ::threads::ThreadManager::instance()->threads_to_terminate;
- if (!threads.IsShuttingDown()) {
- LOG4CXX_INFO(logger_, "Pushing thread #" << pthread_self() << " to join queue");
- ThreadManager::ThreadDesc desc = { pthread_self(), delegate };
- threads.push(desc);
- }
- LOG4CXX_INFO(logger_, "Thread #" << pthread_self() << " exited successfully");
- return NULL;
-}
+size_t Thread::kMinStackSize = PTHREAD_STACK_MIN; /* Ubuntu : 16384 ; QNX : 256; */
+void Thread::cleanup(void* arg) {
+ LOG4CXX_AUTO_TRACE(logger_);
+ Thread* thread = reinterpret_cast<Thread*>(arg);
+ sync_primitives::AutoLock auto_lock(thread->state_lock_);
+ thread->isThreadRunning_ = false;
+ thread->state_cond_.Broadcast();
}
-size_t Thread::kMinStackSize = PTHREAD_STACK_MIN; /* Ubuntu : 16384 ; QNX : 256; */
+void* Thread::threadFunc(void* arg) {
+ // 0 - state_lock unlocked
+ // stopped = 0
+ // running = 0
+ // finalized = 0
+ // 4 - state_lock unlocked
+ // stopped = 1
+ // running = 1
+ // finalized = 0
+ // 5 - state_lock unlocked
+ // stopped = 1
+ // running = 1
+ // finalized = 1
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+ LOG4CXX_DEBUG(logger_,
+ "Thread #" << pthread_self() << " started successfully");
+
+ threads::Thread* thread = reinterpret_cast<Thread*>(arg);
+ DCHECK(thread);
+
+ pthread_cleanup_push(&cleanup, thread);
+
+ thread->state_lock_.Acquire();
+ thread->state_cond_.Broadcast();
+
+ while (!thread->finalized_) {
+ LOG4CXX_DEBUG(logger_, "Thread #" << pthread_self() << " iteration");
+ thread->run_cond_.Wait(thread->state_lock_);
+ LOG4CXX_DEBUG(
+ logger_,
+ "Thread #" << pthread_self() << " execute. " << "stopped_ = " << thread->stopped_ << "; finalized_ = " << thread->finalized_);
+ if (!thread->stopped_ && !thread->finalized_) {
+ thread->isThreadRunning_ = true;
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+ pthread_testcancel();
+
+ thread->state_lock_.Release();
+ thread->delegate_->threadMain();
+ thread->state_lock_.Acquire();
+
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+ thread->isThreadRunning_ = false;
+ }
+ thread->state_cond_.Broadcast();
+ LOG4CXX_DEBUG(logger_,
+ "Thread #" << pthread_self() << " finished iteration");
+ }
-/*
-void ThreadBase::set_name(const std::string name) {
- std::string trimname = name.erase(15);
- if(pthread_setname_np(thread_handle_, trimname.c_str()) != EOK) {
- LOG4CXX_WARN(logger_, "Couldn't set pthread name \""
- << trimname
- << "\", error code "
- << pthread_result
- << " ("
- << strerror(pthread_result)
- << ")");
- }
+ thread->state_lock_.Release();
+ pthread_cleanup_pop(1);
+
+ LOG4CXX_DEBUG(logger_,
+ "Thread #" << pthread_self() << " exited successfully");
+ return NULL;
}
-*/
-
-void Thread::SetNameForId(const Id& thread_id, const std::string& name) {
- std::string nm = name;
- std::string& trimname = nm.size() > 15 ? nm.erase(15) : nm;
- const int rc = pthread_setname_np(thread_id.id_, trimname.c_str());
- if(rc == EOK) {
- LOG4CXX_WARN(logger_, "Couldn't set pthread name \""
- << trimname
- << "\", error code "
- << rc
- << " ("
- << strerror(rc)
- << ")");
+
+void Thread::SetNameForId(const PlatformThreadHandle& thread_id,
+ std::string name) {
+ if (name.size() > THREAD_NAME_SIZE)
+ name.erase(THREAD_NAME_SIZE);
+ const int rc = pthread_setname_np(thread_id, name.c_str());
+ if (rc != EOK) {
+ LOG4CXX_WARN(
+ logger_,
+ "Couldn't set pthread name \"" << name << "\", error code " << rc << " (" << strerror(rc) << ")");
}
}
Thread::Thread(const char* name, ThreadDelegate* delegate)
- : name_(name ? name : "undefined"),
- delegate_(delegate),
- thread_handle_(0),
- thread_options_(),
- isThreadRunning_(0) {
-}
-
-ThreadDelegate* Thread::delegate() const {
- return delegate_;
+ : name_(name ? name : "undefined"),
+ delegate_(delegate),
+ handle_(0),
+ thread_options_(),
+ isThreadRunning_(0),
+ stopped_(false),
+ finalized_(false),
+ thread_created_(false) {
}
bool Thread::start() {
- return startWithOptions(thread_options_);
+ return start(thread_options_);
}
-Thread::Id Thread::CurrentId() {
- return Id(pthread_self());
+PlatformThreadHandle Thread::CurrentId() {
+ return pthread_self();
}
-bool Thread::startWithOptions(const ThreadOptions& options) {
- LOG4CXX_TRACE_ENTER(logger_);
+bool Thread::start(const ThreadOptions& options) {
+ LOG4CXX_AUTO_TRACE(logger_);
+
+ sync_primitives::AutoLock auto_lock(state_lock_);
+ // 1 - state_lock locked
+ // stopped = 0
+ // running = 0
+
if (!delegate_) {
- NOTREACHED();
- LOG4CXX_ERROR(logger_, "NULL delegate");
- LOG4CXX_TRACE_EXIT(logger_);
+ LOG4CXX_ERROR(logger_,
+ "Cannot start thread " << name_ << ": delegate is NULL");
+ // 0 - state_lock unlocked
return false;
}
+ if (isThreadRunning_) {
+ LOG4CXX_TRACE(
+ logger_,
+ "EXIT thread "<< name_ << " #" << handle_ << " is already running");
+ return true;
+ }
+
thread_options_ = options;
pthread_attr_t attributes;
int pthread_result = pthread_attr_init(&attributes);
if (pthread_result != EOK) {
- LOG4CXX_WARN(logger_,"Couldn't init pthread attributes. Error code = "
- << pthread_result << "(\"" << strerror(pthread_result) << "\")");
+ LOG4CXX_WARN(
+ logger_,
+ "Couldn't init pthread attributes. Error code = " << pthread_result << " (\"" << strerror(pthread_result) << "\")");
}
if (!thread_options_.is_joinable()) {
pthread_result = pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);
if (pthread_result != EOK) {
- LOG4CXX_WARN(logger_,"Couldn't set detach state attribute.. Error code = "
- << pthread_result << "(\"" << strerror(pthread_result) << "\")");
+ LOG4CXX_WARN(
+ logger_,
+ "Couldn't set detach state attribute. Error code = " << pthread_result << " (\"" << strerror(pthread_result) << "\")");
thread_options_.is_joinable(false);
}
}
@@ -158,72 +201,94 @@ bool Thread::startWithOptions(const ThreadOptions& options) {
if (stack_size >= Thread::kMinStackSize) {
pthread_result = pthread_attr_setstacksize(&attributes, stack_size);
if (pthread_result != EOK) {
- LOG4CXX_WARN(logger_,"Couldn't set stacksize = " << stack_size <<
- ". Error code = " << pthread_result << "(\""
- << strerror(pthread_result) << "\")");
+ LOG4CXX_WARN(
+ logger_,
+ "Couldn't set stacksize = " << stack_size << ". Error code = " << pthread_result << " (\"" << strerror(pthread_result) << "\")");
}
}
+ else {
+ ThreadOptions thread_options_temp(Thread::kMinStackSize, thread_options_.is_joinable());
+ thread_options_ = thread_options_temp;
+ }
- pthread_result = pthread_create(&thread_handle_, &attributes, threadFunc, this);
- isThreadRunning_ = (pthread_result == EOK);
- if (!isThreadRunning_) {
- LOG4CXX_WARN(logger_, "Couldn't create thread. Error code = "
- << pthread_result << "(\"" << strerror(pthread_result) << "\")");
- } else {
- LOG4CXX_INFO(logger_,"Created thread: " << name_);
- SetNameForId(Id(thread_handle_), name_);
+ if (!thread_created_) {
+ // state_lock 1
+ pthread_result = pthread_create(&handle_, &attributes, threadFunc, this);
+ if (pthread_result == EOK) {
+ LOG4CXX_DEBUG(logger_, "Created thread: " << name_);
+ SetNameForId(handle_, name_);
+ // state_lock 0
+ // possible concurrencies: stop and threadFunc
+ state_cond_.Wait(auto_lock);
+ thread_created_ = true;
+ } else {
+ LOG4CXX_ERROR(
+ logger_,
+ "Couldn't create thread " << name_ << ". Error code = " << pthread_result << " (\"" << strerror(pthread_result) << "\")");
+ }
}
- LOG4CXX_TRACE_EXIT(logger_);
- return isThreadRunning_;
+ stopped_ = false;
+ run_cond_.NotifyOne();
+ LOG4CXX_DEBUG(
+ logger_,
+ "Thread " << name_ << " #" << handle_ << " started. pthread_result = " << pthread_result);
+ pthread_attr_destroy(&attributes);
+ return pthread_result == EOK;
}
void Thread::stop() {
- LOG4CXX_TRACE_ENTER(logger_);
+ LOG4CXX_AUTO_TRACE(logger_);
+ sync_primitives::AutoLock auto_lock(state_lock_);
- if (!atomic_post_clr(&isThreadRunning_))
- {
- return;
- }
+#ifdef BUILD_TESTS
+ // Temporary fix for UnitTest until APPLINK-9987 is resolved
+ usleep(100000);
+#endif
- if (delegate_ && !delegate_->exitThreadMain()) {
- if (thread_handle_ != pthread_self()) {
- LOG4CXX_WARN(logger_, "Cancelling thread #" << thread_handle_);
- const int pthread_result = pthread_cancel(thread_handle_);
- if (pthread_result != EOK) {
- LOG4CXX_WARN(logger_,
- "Couldn't cancel thread (#" << thread_handle_ << " \"" << name_ <<
- "\") from thread #" << pthread_self() << ". Error code = "
- << pthread_result << " (\"" << strerror(pthread_result) << "\")");
- }
- } else {
- LOG4CXX_ERROR(logger_,
- "Couldn't cancel the same thread (#" << thread_handle_
- << "\"" << name_ << "\")");
- }
+ stopped_ = true;
+
+ LOG4CXX_DEBUG(logger_, "Stopping thread #" << handle_
+
+ << " \"" << name_ << " \"");
+
+ if (delegate_ && isThreadRunning_) {
+ delegate_->exitThreadMain();
}
- LOG4CXX_TRACE_EXIT(logger_);
+ LOG4CXX_DEBUG(logger_,
+ "Stopped thread #" << handle_ << " \"" << name_ << " \"");
}
-bool Thread::Id::operator==(const Thread::Id& other) const {
- return pthread_equal(id_, other.id_) != 0;
-}
+void Thread::join() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ DCHECK(!pthread_equal(pthread_self(), handle_));
-std::ostream& operator<<(std::ostream& os, const Thread::Id& thread_id) {
- char name[32];
- if(pthread_getname_np(thread_id.Handle(), name, 32) == 0) {
- os << name;
+ stop();
+
+ sync_primitives::AutoLock auto_lock(state_lock_);
+ run_cond_.NotifyOne();
+ if (isThreadRunning_) {
+ if (!pthread_equal(pthread_self(), handle_)) {
+ state_cond_.Wait(auto_lock);
+ }
}
- return os;
+}
+
+Thread::~Thread() {
+ finalized_ = true;
+ stopped_ = true;
+ join();
+ pthread_join(handle_, NULL);
}
Thread* CreateThread(const char* name, ThreadDelegate* delegate) {
- return new Thread(name, delegate);
+ Thread* thread = new Thread(name, delegate);
+ delegate->set_thread(thread);
+ return thread;
}
void DeleteThread(Thread* thread) {
delete thread;
}
-
} // namespace threads
diff --git a/src/components/utils/src/threads/pulse_thread_delegate.cc b/src/components/utils/src/threads/pulse_thread_delegate.cc
index 8c580bea83..68db5dcbea 100644
--- a/src/components/utils/src/threads/pulse_thread_delegate.cc
+++ b/src/components/utils/src/threads/pulse_thread_delegate.cc
@@ -91,7 +91,7 @@ void PulseThreadDelegate::threadMain() {
Finalize();
}
-bool PulseThreadDelegate::exitThreadMain() {
+void PulseThreadDelegate::exitThreadMain() {
run_ = false;
LOG4CXX_TRACE(logger_, "Disconnecting from QNX channel " << chid_);
@@ -109,8 +109,6 @@ bool PulseThreadDelegate::exitThreadMain() {
else {
LOG4CXX_WARN(logger_, "Failed to destroy QNX channel " << chid_);
}
-
- return true;
}
} // namespace threads
diff --git a/src/components/utils/src/threads/thread_delegate.cc b/src/components/utils/src/threads/thread_delegate.cc
index 13271166ff..1436ea3377 100644
--- a/src/components/utils/src/threads/thread_delegate.cc
+++ b/src/components/utils/src/threads/thread_delegate.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
@@ -40,7 +40,7 @@
namespace threads {
ThreadDelegate::~ThreadDelegate() {
- if(thread_) {
+ if (thread_) {
thread_->set_delegate(NULL);
}
}
@@ -60,4 +60,4 @@ void ThreadDelegate::set_thread(Thread *thread) {
thread_ = thread;
}
-}
+} // namespace threads
diff --git a/src/components/utils/src/threads/thread_validator.cc b/src/components/utils/src/threads/thread_validator.cc
index 5e9c88a7c9..99b812c456 100644
--- a/src/components/utils/src/threads/thread_validator.cc
+++ b/src/components/utils/src/threads/thread_validator.cc
@@ -1,5 +1,5 @@
-/**
- * Copyright (c) 2013, Ford Motor Company
+/*
+ * Copyright (c) 2014, Ford Motor Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -46,7 +46,7 @@ SingleThreadSimpleValidator::~SingleThreadSimpleValidator() {
}
void SingleThreadSimpleValidator::AssertRunningOnCreationThread() const {
- Thread::Id current_id = Thread::CurrentId();
+ PlatformThreadHandle current_id = Thread::CurrentId();
if (creation_thread_id_ != current_id) {
LOG4CXX_ERROR(logger_, "Single-threaded object created at thread "
<< creation_thread_id_
@@ -60,6 +60,11 @@ void SingleThreadSimpleValidator::AssertRunningOnCreationThread() const {
}
}
+PlatformThreadHandle SingleThreadSimpleValidator::creation_thread_id() const
+{
+ return creation_thread_id_;
+}
+
SingleThreadValidator::SingleThreadValidator()
: owning_thread_id_(Thread::CurrentId()){
@@ -68,12 +73,12 @@ SingleThreadValidator::SingleThreadValidator()
SingleThreadValidator::~SingleThreadValidator() {
}
-void SingleThreadValidator::PassToThread(Thread::Id thread_id) const {
+void SingleThreadValidator::PassToThread(PlatformThreadHandle thread_id) const {
owning_thread_id_ = thread_id;
}
void SingleThreadValidator::AssertRunningOnValidThread() const {
- Thread::Id current_id = Thread::CurrentId();
+ PlatformThreadHandle current_id = Thread::CurrentId();
if (owning_thread_id_ != current_id) {
LOG4CXX_ERROR(logger_, "Single-threaded object owned by thread "
<< owning_thread_id_
diff --git a/src/components/utils/test/CMakeLists.txt b/src/components/utils/test/CMakeLists.txt
index a9ed5acdac..377b7dba7b 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 0000000000..38606c15ac
--- /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 0000000000..71e0f4376f
--- /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 0000000000..12d5df81fc
--- /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 0000000000..07a80bde07
--- /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 0000000000..a898732ffc
--- /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 0000000000..105ec8517f
--- /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 ddcf679a16..b437bdc17e 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 abf09735ba..54a662c511 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 0000000000..9b0d9533bc
--- /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 0000000000..0ba34d0ad3
--- /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 0000000000..789bf62f45
--- /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 0000000000..fbae7a9e5e
--- /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 45375e4ed6..6c13ab345e 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 0000000000..d597f036d0
--- /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 0000000000..c10bbea865
--- /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 0000000000..779b57ff32
--- /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 0000000000..263f240ec8
--- /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 0000000000..8a9e6b31e1
--- /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 0000000000..62c6d9404b
--- /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 0000000000..42307998b4
--- /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 0000000000..c42d8e78b0
--- /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 0000000000..16d9d12874
--- /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 0000000000..be25e03b7b
--- /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
+