BuildRequires: pkgconfig(libprivilege-control)
BuildRequires: pkgconfig(security-server)
BuildRequires: pkgconfig(security-manager)
-BuildRequires: pkgconfig(dpl-test-efl)
BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(dbus-1)
BuildRequires: pkgconfig(dbus-glib-1)
+BuildRequires: pkgconfig(libpcrecpp)
+BuildRequires: pkgconfig(libxml-2.0)
BuildRequires: pkgconfig(libiri)
BuildRequires: pkgconfig(sqlite3)
BuildRequires: pkgconfig(cynara-admin)
# limitations under the License.
#
+INCLUDE(FindPkgConfig)
+
+PKG_CHECK_MODULES(SYS_FRAMEWORK_TEST
+ REQUIRED
+ libxml-2.0
+ libpcrecpp
+ libiri
+ )
+
+PKG_CHECK_MODULES(SYS_FRAMEWORK_TEST_OTHER
+ REQUIRED
+ glib-2.0
+ dlog
+ )
+
+ADD_DEFINITIONS(${SYS_FRAMEWORK_TEST_OTHER_CFLAGS})
+
+include(framework/config.cmake)
+
+SET(DPL_FRAMEWORK_TEST_LIBRARY "dpl-test-framework")
+
+INCLUDE_DIRECTORIES(SYSTEM
+ ${SYS_FRAMEWORK_TEST_OTHER_INCLUDE_DIRS}
+ ${DPL_FRAMEWORK_TEST_INCLUDE_DIR}
+ )
+
+ADD_LIBRARY(${DPL_FRAMEWORK_TEST_LIBRARY} ${DPL_FRAMEWORK_TEST_SOURCES})
+
+TARGET_LINK_LIBRARIES(${DPL_FRAMEWORK_TEST_LIBRARY}
+ ${SYS_FRAMEWORK_TEST_OTHER_LIBRARIES}
+ ${SYS_FRAMEWORK_TEST_LIBRARIES}
+ )
+
INSTALL(FILES ${PROJECT_SOURCE_DIR}/tests/security-tests.sh
DESTINATION bin
PERMISSIONS OWNER_READ
WORLD_EXECUTE
)
+
ADD_SUBDIRECTORY(common)
ADD_SUBDIRECTORY(libprivilege-control-tests)
ADD_SUBDIRECTORY(libsmack-tests)
#dependencies
PKG_CHECK_MODULES(COMMON_TARGET_DEP
libsmack
- dpl-test-efl
dbus-1
dbus-glib-1
sqlite3
#system and local includes
INCLUDE_DIRECTORIES(SYSTEM ${COMMON_TARGET_DEP_INCLUDE_DIRS})
-INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/tests/common)
+INCLUDE_DIRECTORIES(
+ ${PROJECT_SOURCE_DIR}/tests/framework/include
+ ${PROJECT_SOURCE_DIR}/tests/common
+ )
#output OBJECT format
ADD_LIBRARY(${COMMON_TARGET_TEST} ${COMMON_TARGET_TEST_SOURCES})
-TARGET_LINK_LIBRARIES(${COMMON_TARGET_TEST} ${COMMON_TARGET_DEP_LIBRARIES})
+TARGET_LINK_LIBRARIES(${COMMON_TARGET_TEST} ${COMMON_TARGET_DEP_LIBRARIES}
+ dpl-test-framework)
INSTALL (FILES ${PROJECT_SOURCE_DIR}/tests/common/security-tests.conf DESTINATION /etc/dbus-1/system.d)
#include <grp.h>
#include <errno.h>
#include <vector>
+#include <algorithm>
int DB::Transaction::db_result = PC_OPERATION_SUCCESS;
PKG_CHECK_MODULES(CYNARA_TARGET_DEP
REQUIRED
- dpl-test-efl
libprivilege-control
cynara-admin
cynara-client
#linker directories
TARGET_LINK_LIBRARIES(${CYNARA_TARGET_TEST}
${CYNARA_TARGET_DEP_LIBRARIES}
+ dpl-test-framework
tests-common
)
* @brief Tests for libcynara-client and libcynara-admin
*/
+#include <dpl/exception.h>
#include <tests_common.h>
#include <cynara_test_client.h>
#include <cynara_test_admin.h>
--- /dev/null
+# Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# @file config.cmake
+# @author Lukasz Marek (l.marek@samsung.com)
+# @version 1.0
+# @brief
+#
+
+SET(DPL_FRAMEWORK_TEST_SOURCES
+ ${PROJECT_SOURCE_DIR}/tests/framework/src/assert.cpp
+ ${PROJECT_SOURCE_DIR}/tests/framework/src/atomic.cpp
+ ${PROJECT_SOURCE_DIR}/tests/framework/src/binary_queue.cpp
+ ${PROJECT_SOURCE_DIR}/tests/framework/src/colors.cpp
+ ${PROJECT_SOURCE_DIR}/tests/framework/src/exception.cpp
+ ${PROJECT_SOURCE_DIR}/tests/framework/src/noncopyable.cpp
+ ${PROJECT_SOURCE_DIR}/tests/framework/src/singleton.cpp
+ ${PROJECT_SOURCE_DIR}/tests/framework/src/abstract_log_provider.cpp
+ ${PROJECT_SOURCE_DIR}/tests/framework/src/dlog_log_provider.cpp
+ ${PROJECT_SOURCE_DIR}/tests/framework/src/log.cpp
+ ${PROJECT_SOURCE_DIR}/tests/framework/src/old_style_log_provider.cpp
+ ${PROJECT_SOURCE_DIR}/tests/framework/src/test_results_collector.cpp
+ ${PROJECT_SOURCE_DIR}/tests/framework/src/test_runner_child.cpp
+ ${PROJECT_SOURCE_DIR}/tests/framework/src/test_runner.cpp
+ ${PROJECT_SOURCE_DIR}/tests/framework/src/test_runner_multiprocess.cpp
+)
+
+SET(DPL_FRAMEWORK_TEST_INCLUDE_DIR
+ ${PROJECT_SOURCE_DIR}/tests/framework/include
+)
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file abstract_input.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the header file of abstract input
+ */
+#ifndef DPL_ABSTRACT_INPUT_H
+#define DPL_ABSTRACT_INPUT_H
+
+#include <dpl/exception.h>
+#include <memory>
+
+namespace DPL {
+class BinaryQueue;
+typedef std::auto_ptr<BinaryQueue> BinaryQueueAutoPtr;
+
+class AbstractInput
+{
+ public:
+ class Exception
+ {
+ public:
+ DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
+ DECLARE_EXCEPTION_TYPE(Base, ReadFailed)
+ };
+
+ public:
+ virtual ~AbstractInput() {}
+
+ /**
+ * Read binary data from input
+ * If no data is available method returns NULL buffer.
+ * In case connection was successfuly close, method returns empty buffer
+ *
+ * @param[in] size Maximum number of bytes to read from input
+ * @return Buffer containing read bytes
+ * @throw ReadFailed
+ */
+ virtual BinaryQueueAutoPtr Read(size_t size) = 0;
+};
+} // namespace DPL
+
+#endif // DPL_ABSTRACT_INPUT_H
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file abstract_output.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the header file of abstract output
+ */
+#ifndef DPL_ABSTRACT_INPUT_OUTPUT_H
+#define DPL_ABSTRACT_INPUT_OUTPUT_H
+
+#include <dpl/abstract_input.h>
+#include <dpl/abstract_output.h>
+
+namespace DPL {
+class AbstractInputOutput :
+ public AbstractInput,
+ public AbstractOutput
+{
+ public:
+ virtual ~AbstractInputOutput() {}
+};
+} // namespace DPL
+
+#endif // DPL_ABSTRACT_INPUT_OUTPUT_H
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file abstract_output.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the header file of abstract output
+ */
+#ifndef DPL_ABSTRACT_OUTPUT_H
+#define DPL_ABSTRACT_OUTPUT_H
+
+#include <dpl/exception.h>
+#include <memory>
+
+namespace DPL {
+class BinaryQueue;
+typedef std::auto_ptr<BinaryQueue> BinaryQueueAutoPtr;
+
+class AbstractOutput
+{
+ public:
+ class Exception
+ {
+ public:
+ DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
+ DECLARE_EXCEPTION_TYPE(Base, WriteFailed)
+ };
+
+ public:
+ virtual ~AbstractOutput() {}
+
+ /**
+ * Write binary data to output
+ * If output is blocked, Write returns zero, if instance is a type of
+ * WaitableAbstractOutput one can wait for writability then
+ *
+ * @param[in] buffer Input buffer with data to be written
+ * @param[in] bufferSize Maximum number of bytes to write from buffer
+ * @return Number of bytes success successfuly written or zero if output is
+ * blocked
+ * @throw WriteFailed
+ */
+ virtual size_t Write(const BinaryQueue &buffer, size_t bufferSize) = 0;
+};
+} // namespace DPL
+
+#endif // DPL_ABSTRACT_OUTPUT_H
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file assert.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of assert
+ */
+#ifndef DPL_ASSERT_H
+#define DPL_ASSERT_H
+
+#include <dpl/noreturn.h>
+
+namespace DPL {
+// Assertion handler procedure
+// Do not call directly
+// Always use Assert macro
+DPL_NORETURN void AssertProc(const char *condition,
+ const char *file,
+ int line,
+ const char *function);
+} // namespace DPL
+
+#define Assert(Condition) do { if (!(Condition)) { DPL::AssertProc(#Condition, \
+ __FILE__, \
+ __LINE__, \
+ __FUNCTION__); \
+ } } while (0)
+
+#endif // DPL_ASSERT_H
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file atomic.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the header file of atomic
+ */
+#ifndef DPL_ATOMIC_H
+#define DPL_ATOMIC_H
+
+#pragma GCC system_header
+#include <glib.h>
+
+namespace DPL {
+class Atomic
+{
+ public:
+ typedef gint ValueType;
+
+ private:
+ volatile ValueType m_value;
+
+ public:
+ Atomic(ValueType value = static_cast<ValueType>(0));
+
+ ValueType ExchangeAndAdd(ValueType value);
+ bool CompareAndExchange(ValueType oldValue, ValueType newValue);
+ bool operator--();
+ void operator++();
+
+ operator ValueType() const;
+};
+} // namespace DPL
+
+#endif // DPL_ATOMIC_H
--- /dev/null
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file availability.h
+ * @author Jihoon Chung (jihoon.chung@samsung.com)
+ * @version 1.0
+ */
+#ifndef DPL_AVAILABILITY_H
+#define DPL_AVAILABILITY_H
+
+#define DPL_DEPRECATED __attribute__((deprecated))
+#define DPL_DEPRECATED_WITH_MESSAGE(msg) __attribute__((deprecated(msg)))
+
+#define DPL_UNUSED __attribute__((unused))
+#define DPL_UNUSED_PARAM(variable) (void)variable
+
+#endif // DPL_AVAILABILITY_H
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file binary_queue.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the header file of binary queue
+ */
+#ifndef DPL_BINARY_QUEUE_H
+#define DPL_BINARY_QUEUE_H
+
+#include <dpl/abstract_input_output.h>
+#include <dpl/exception.h>
+#include <dpl/noncopyable.h>
+#include <memory>
+#include <list>
+
+namespace DPL {
+/**
+ * Binary stream implemented as constant size bucket list
+ *
+ * @todo Add optimized implementation for FlattenConsume
+ */
+class BinaryQueue :
+ public AbstractInputOutput
+{
+ public:
+ class Exception
+ {
+ public:
+ DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
+ DECLARE_EXCEPTION_TYPE(Base, OutOfData)
+ };
+
+ typedef void (*BufferDeleter)(const void *buffer, size_t bufferSize,
+ void *userParam);
+ static void BufferDeleterFree(const void *buffer,
+ size_t bufferSize,
+ void *userParam);
+
+ class BucketVisitor
+ {
+ public:
+ /**
+ * Destructor
+ */
+ virtual ~BucketVisitor();
+
+ /**
+ * Visit bucket
+ *
+ * @return none
+ * @param[in] buffer Constant pointer to bucket data buffer
+ * @param[in] bufferSize Number of bytes in bucket
+ */
+ virtual void OnVisitBucket(const void *buffer, size_t bufferSize) = 0;
+ };
+
+ private:
+ struct Bucket :
+ private Noncopyable
+ {
+ const void *buffer;
+ const void *ptr;
+ size_t size;
+ size_t left;
+
+ BufferDeleter deleter;
+ void *param;
+
+ Bucket(const void *buffer,
+ size_t bufferSize,
+ BufferDeleter deleter,
+ void *userParam);
+ virtual ~Bucket();
+ };
+
+ typedef std::list<Bucket *> BucketList;
+ BucketList m_buckets;
+ size_t m_size;
+
+ static void DeleteBucket(Bucket *bucket);
+
+ class BucketVisitorCall
+ {
+ private:
+ BucketVisitor *m_visitor;
+
+ public:
+ BucketVisitorCall(BucketVisitor *visitor);
+ virtual ~BucketVisitorCall();
+
+ void operator()(Bucket *bucket) const;
+ };
+
+ public:
+ /**
+ * Construct empty binary queue
+ */
+ BinaryQueue();
+
+ /**
+ * Construct binary queue via bare copy of other binary queue
+ *
+ * @param[in] other Other binary queue to copy from
+ * @warning One cannot assume that bucket structure is preserved during copy
+ */
+ BinaryQueue(const BinaryQueue &other);
+
+ /**
+ * Destructor
+ */
+ virtual ~BinaryQueue();
+
+ /**
+ * Construct binary queue via bare copy of other binary queue
+ *
+ * @param[in] other Other binary queue to copy from
+ * @warning One cannot assume that bucket structure is preserved during copy
+ */
+ const BinaryQueue &operator=(const BinaryQueue &other);
+
+ /**
+ * Append copy of @a bufferSize bytes from memory pointed by @a buffer
+ * to the end of binary queue. Uses default deleter based on free.
+ *
+ * @return none
+ * @param[in] buffer Pointer to buffer to copy data from
+ * @param[in] bufferSize Number of bytes to copy
+ * @exception std::bad_alloc Cannot allocate memory to hold additional data
+ * @see BinaryQueue::BufferDeleterFree
+ */
+ void AppendCopy(const void *buffer, size_t bufferSize);
+
+ /**
+ * Append @a bufferSize bytes from memory pointed by @a buffer
+ * to the end of binary queue. Uses custom provided deleter.
+ * Responsibility for deleting provided buffer is transfered to BinaryQueue.
+ *
+ * @return none
+ * @param[in] buffer Pointer to data buffer
+ * @param[in] bufferSize Number of bytes available in buffer
+ * @param[in] deleter Pointer to deleter procedure used to free provided
+ * buffer
+ * @param[in] userParam User parameter passed to deleter routine
+ * @exception std::bad_alloc Cannot allocate memory to hold additional data
+ */
+ void AppendUnmanaged(
+ const void *buffer,
+ size_t bufferSize,
+ BufferDeleter deleter =
+ &BinaryQueue::BufferDeleterFree,
+ void *userParam = NULL);
+
+ /**
+ * Append copy of other binary queue to the end of this binary queue
+ *
+ * @return none
+ * @param[in] other Constant reference to other binary queue to copy data
+ * from
+ * @exception std::bad_alloc Cannot allocate memory to hold additional data
+ * @warning One cannot assume that bucket structure is preserved during copy
+ */
+ void AppendCopyFrom(const BinaryQueue &other);
+
+ /**
+ * Move bytes from other binary queue to the end of this binary queue.
+ * This also removes all bytes from other binary queue.
+ * This method is designed to be as fast as possible (only pointer swaps)
+ * and is suggested over making copies of binary queues.
+ * Bucket structure is preserved after operation.
+ *
+ * @return none
+ * @param[in] other Reference to other binary queue to move data from
+ * @exception std::bad_alloc Cannot allocate memory to hold additional data
+ */
+ void AppendMoveFrom(BinaryQueue &other);
+
+ /**
+ * Append copy of binary queue to the end of other binary queue
+ *
+ * @return none
+ * @param[in] other Constant reference to other binary queue to copy data to
+ * @exception std::bad_alloc Cannot allocate memory to hold additional data
+ * @warning One cannot assume that bucket structure is preserved during copy
+ */
+ void AppendCopyTo(BinaryQueue &other) const;
+
+ /**
+ * Move bytes from binary queue to the end of other binary queue.
+ * This also removes all bytes from binary queue.
+ * This method is designed to be as fast as possible (only pointer swaps)
+ * and is suggested over making copies of binary queues.
+ * Bucket structure is preserved after operation.
+ *
+ * @return none
+ * @param[in] other Reference to other binary queue to move data to
+ * @exception std::bad_alloc Cannot allocate memory to hold additional data
+ */
+ void AppendMoveTo(BinaryQueue &other);
+
+ /**
+ * Retrieve total size of all data contained in binary queue
+ *
+ * @return Number of bytes in binary queue
+ */
+ size_t Size() const;
+
+ /**
+ * Remove all data from binary queue
+ *
+ * @return none
+ */
+ void Clear();
+
+ /**
+ * Check if binary queue is empty
+ *
+ * @return true if binary queue is empty, false otherwise
+ */
+ bool Empty() const;
+
+ /**
+ * Remove @a size bytes from beginning of binary queue
+ *
+ * @return none
+ * @param[in] size Number of bytes to remove
+ * @exception BinaryQueue::Exception::OutOfData Number of bytes is larger
+ * than available bytes in binary queue
+ */
+ void Consume(size_t size);
+
+ /**
+ * Retrieve @a bufferSize bytes from beginning of binary queue and copy them
+ * to user supplied buffer
+ *
+ * @return none
+ * @param[in] buffer Pointer to user buffer to receive bytes
+ * @param[in] bufferSize Size of user buffer pointed by @a buffer
+ * @exception BinaryQueue::Exception::OutOfData Number of bytes to flatten
+ * is larger than available bytes in binary queue
+ */
+ void Flatten(void *buffer, size_t bufferSize) const;
+
+ /**
+ * Retrieve @a bufferSize bytes from beginning of binary queue, copy them
+ * to user supplied buffer, and remove from binary queue
+ *
+ * @return none
+ * @param[in] buffer Pointer to user buffer to receive bytes
+ * @param[in] bufferSize Size of user buffer pointed by @a buffer
+ * @exception BinaryQueue::Exception::OutOfData Number of bytes to flatten
+ * is larger than available bytes in binary queue
+ */
+ void FlattenConsume(void *buffer, size_t bufferSize);
+
+ /**
+ * Visit each buffer with data using visitor object
+ *
+ * @return none
+ * @param[in] visitor Pointer to bucket visitor
+ * @see BinaryQueue::BucketVisitor
+ */
+ void VisitBuckets(BucketVisitor *visitor) const;
+
+ /**
+ * IAbstractInput interface
+ */
+ virtual BinaryQueueAutoPtr Read(size_t size);
+
+ /**
+ * IAbstractOutput interface
+ */
+ virtual size_t Write(const BinaryQueue &buffer, size_t bufferSize);
+};
+
+/**
+ * Binary queue auto pointer
+ */
+typedef std::auto_ptr<BinaryQueue> BinaryQueueAutoPtr;
+} // namespace DPL
+
+#endif // DPL_BINARY_QUEUE_H
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file colors.h
+ * @author Lukasz Wrzosek (l.wrzosek@samsung.com)
+ * @version 1.0
+ * @brief Some constants with definition of colors for Console
+ * and html output
+ */
+
+#ifndef DPL_COLORS_H
+#define DPL_COLORS_H
+
+namespace DPL {
+namespace Colors {
+namespace Text {
+extern const char* BOLD_GREEN_BEGIN;
+extern const char* BOLD_GREEN_END;
+extern const char* PURPLE_BEGIN;
+extern const char* PURPLE_END;
+extern const char* RED_BEGIN;
+extern const char* RED_END;
+extern const char* GREEN_BEGIN;
+extern const char* GREEN_END;
+extern const char* CYAN_BEGIN;
+extern const char* CYAN_END;
+extern const char* BOLD_RED_BEGIN;
+extern const char* BOLD_RED_END;
+extern const char* BOLD_YELLOW_BEGIN;
+extern const char* BOLD_YELLOW_END;
+extern const char* BOLD_GOLD_BEGIN;
+extern const char* BOLD_GOLD_END;
+extern const char* BOLD_WHITE_BEGIN;
+extern const char* BOLD_WHITE_END;
+} //namespace Text
+
+namespace Html {
+extern const char* BOLD_GREEN_BEGIN;
+extern const char* BOLD_GREEN_END;
+extern const char* PURPLE_BEGIN;
+extern const char* PURPLE_END;
+extern const char* RED_BEGIN;
+extern const char* RED_END;
+extern const char* GREEN_BEGIN;
+extern const char* GREEN_END;
+extern const char* CYAN_BEGIN;
+extern const char* CYAN_END;
+extern const char* BOLD_RED_BEGIN;
+extern const char* BOLD_RED_END;
+extern const char* BOLD_YELLOW_BEGIN;
+extern const char* BOLD_YELLOW_END;
+extern const char* BOLD_GOLD_BEGIN;
+extern const char* BOLD_GOLD_END;
+extern const char* BOLD_WHITE_BEGIN;
+extern const char* BOLD_WHITE_END;
+} //namespace Html
+} //namespace Colors
+} //namespace DPL
+
+#endif /* DPL_COLORS_H */
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file exception.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief Header file for base exception
+ */
+#ifndef DPL_EXCEPTION_H
+#define DPL_EXCEPTION_H
+
+#include <string>
+#include <cstring>
+#include <cstdio>
+#include <exception>
+#include <cstdlib>
+#include <sstream>
+
+namespace DPL {
+void LogUnhandledException(const std::string &str);
+void LogUnhandledException(const std::string &str,
+ const char *filename,
+ int line,
+ const char *function);
+}
+
+namespace DPL {
+class Exception
+{
+ private:
+ static unsigned int m_exceptionCount;
+ static Exception* m_lastException;
+ static void (*m_terminateHandler)();
+
+ static void AddRef(Exception* exception)
+ {
+ if (!m_exceptionCount) {
+ m_terminateHandler = std::set_terminate(&TerminateHandler);
+ }
+
+ ++m_exceptionCount;
+ m_lastException = exception;
+ }
+
+ static void UnRef(Exception* e)
+ {
+ if (m_lastException == e) {
+ m_lastException = NULL;
+ }
+
+ --m_exceptionCount;
+
+ if (!m_exceptionCount) {
+ std::set_terminate(m_terminateHandler);
+ m_terminateHandler = NULL;
+ }
+ }
+
+ static void TerminateHandler()
+ {
+ if (m_lastException != NULL) {
+ DisplayKnownException(*m_lastException);
+ abort();
+ } else {
+ DisplayUnknownException();
+ abort();
+ }
+ }
+
+ Exception *m_reason;
+ std::string m_path;
+ std::string m_function;
+ int m_line;
+
+ protected:
+ std::string m_message;
+ std::string m_className;
+
+ public:
+ static std::string KnownExceptionToString(const Exception &e)
+ {
+ std::ostringstream message;
+ message <<
+ "\033[1;5;31m\n=== Unhandled DPL exception occurred ===\033[m\n\n";
+ message << "\033[1;33mException trace:\033[m\n\n";
+ message << e.DumpToString();
+ message << "\033[1;31m\n=== Will now abort ===\033[m\n";
+
+ return message.str();
+ }
+
+ static std::string UnknownExceptionToString()
+ {
+ std::ostringstream message;
+ message <<
+ "\033[1;5;31m\n=== Unhandled non-DPL exception occurred ===\033[m\n\n";
+ message << "\033[1;31m\n=== Will now abort ===\033[m\n";
+
+ return message.str();
+ }
+
+ static void DisplayKnownException(const Exception& e)
+ {
+ LogUnhandledException(KnownExceptionToString(e).c_str());
+ }
+
+ static void DisplayUnknownException()
+ {
+ LogUnhandledException(UnknownExceptionToString().c_str());
+ }
+
+ Exception(const Exception &other)
+ {
+ // Deep copy
+ if (other.m_reason != NULL) {
+ m_reason = new Exception(*other.m_reason);
+ } else {
+ m_reason = NULL;
+ }
+
+ m_message = other.m_message;
+ m_path = other.m_path;
+ m_function = other.m_function;
+ m_line = other.m_line;
+
+ m_className = other.m_className;
+
+ AddRef(this);
+ }
+
+ const Exception &operator =(const Exception &other)
+ {
+ if (this == &other) {
+ return *this;
+ }
+
+ // Deep copy
+ if (other.m_reason != NULL) {
+ m_reason = new Exception(*other.m_reason);
+ } else {
+ m_reason = NULL;
+ }
+
+ m_message = other.m_message;
+ m_path = other.m_path;
+ m_function = other.m_function;
+ m_line = other.m_line;
+
+ m_className = other.m_className;
+
+ AddRef(this);
+
+ return *this;
+ }
+
+ Exception(const char *path,
+ const char *function,
+ int line,
+ const std::string &message) :
+ m_reason(NULL),
+ m_path(path),
+ m_function(function),
+ m_line(line),
+ m_message(message)
+ {
+ AddRef(this);
+ }
+
+ Exception(const char *path,
+ const char *function,
+ int line,
+ const Exception &reason,
+ const std::string &message) :
+ m_reason(new Exception(reason)),
+ m_path(path),
+ m_function(function),
+ m_line(line),
+ m_message(message)
+ {
+ AddRef(this);
+ }
+
+ virtual ~Exception() throw()
+ {
+ if (m_reason != NULL) {
+ delete m_reason;
+ m_reason = NULL;
+ }
+
+ UnRef(this);
+ }
+
+ void Dump() const
+ {
+ // Show reason first
+ if (m_reason != NULL) {
+ m_reason->Dump();
+ }
+
+ // Afterward, dump exception
+ const char *file = strchr(m_path.c_str(), '/');
+
+ if (file == NULL) {
+ file = m_path.c_str();
+ } else {
+ ++file;
+ }
+
+ printf("\033[0;36m[%s:%i]\033[m %s() \033[4;35m%s\033[m: %s\033[m\n",
+ file, m_line,
+ m_function.c_str(),
+ m_className.c_str(),
+ m_message.empty() ? "<EMPTY>" : m_message.c_str());
+ }
+
+ std::string DumpToString() const
+ {
+ std::string ret;
+ if (m_reason != NULL) {
+ ret = m_reason->DumpToString();
+ }
+
+ const char *file = strchr(m_path.c_str(), '/');
+
+ if (file == NULL) {
+ file = m_path.c_str();
+ } else {
+ ++file;
+ }
+
+ char buf[1024];
+ snprintf(buf,
+ sizeof(buf),
+ "\033[0;36m[%s:%i]\033[m %s() \033[4;35m%s\033[m: %s\033[m\n",
+ file,
+ m_line,
+ m_function.c_str(),
+ m_className.c_str(),
+ m_message.empty() ? "<EMPTY>" : m_message.c_str());
+
+ buf[sizeof(buf) - 1] = '\n';
+ ret += buf;
+
+ return ret;
+ }
+
+ Exception *GetReason() const
+ {
+ return m_reason;
+ }
+
+ std::string GetPath() const
+ {
+ return m_path;
+ }
+
+ std::string GetFunction() const
+ {
+ return m_function;
+ }
+
+ int GetLine() const
+ {
+ return m_line;
+ }
+
+ std::string GetMessage() const
+ {
+ return m_message;
+ }
+
+ std::string GetClassName() const
+ {
+ return m_className;
+ }
+};
+} // namespace DPL
+
+#define Try try
+
+#define Throw(ClassName) \
+ throw ClassName(__FILE__, __FUNCTION__, __LINE__)
+
+#define ThrowMsg(ClassName, Message) \
+ do \
+ { \
+ std::ostringstream dplLoggingStream; \
+ dplLoggingStream << Message; \
+ throw ClassName(__FILE__, __FUNCTION__, __LINE__, dplLoggingStream.str()); \
+ } while (0)
+
+#define ReThrow(ClassName) \
+ throw ClassName(__FILE__, __FUNCTION__, __LINE__, _rethrown_exception)
+
+#define ReThrowMsg(ClassName, Message) \
+ throw ClassName(__FILE__, \
+ __FUNCTION__, \
+ __LINE__, \
+ _rethrown_exception, \
+ Message)
+
+#define Catch(ClassName) \
+ catch (const ClassName &_rethrown_exception)
+
+#define DECLARE_EXCEPTION_TYPE(BaseClass, Class) \
+ class Class : \
+ public BaseClass \
+ { \
+ public: \
+ Class(const char *path, \
+ const char *function, \
+ int line, \
+ const std::string & message = std::string()) : \
+ BaseClass(path, function, line, message) \
+ { \
+ BaseClass::m_className = #Class; \
+ } \
+ \
+ Class(const char *path, \
+ const char *function, \
+ int line, \
+ const DPL::Exception & reason, \
+ const std::string & message = std::string()) : \
+ BaseClass(path, function, line, reason, message) \
+ { \
+ BaseClass::m_className = #Class; \
+ } \
+ };
+
+#define UNHANDLED_EXCEPTION_HANDLER_BEGIN try
+
+#define UNHANDLED_EXCEPTION_HANDLER_END \
+ catch (const DPL::Exception &exception) \
+ { \
+ std::ostringstream msg; \
+ msg << DPL::Exception::KnownExceptionToString(exception); \
+ DPL::LogUnhandledException(msg.str(), __FILE__, __LINE__, __FUNCTION__); \
+ abort(); \
+ } \
+ catch (std::exception& e) \
+ { \
+ std::ostringstream msg; \
+ msg << e.what(); \
+ msg << "\n"; \
+ msg << DPL::Exception::UnknownExceptionToString(); \
+ DPL::LogUnhandledException(msg.str(), __FILE__, __LINE__, __FUNCTION__); \
+ abort(); \
+ } \
+ catch (...) \
+ { \
+ std::ostringstream msg; \
+ msg << DPL::Exception::UnknownExceptionToString(); \
+ DPL::LogUnhandledException(msg.str(), __FILE__, __LINE__, __FUNCTION__); \
+ abort(); \
+ }
+
+namespace DPL {
+namespace CommonException {
+/**
+ * Internal exception definitions
+ *
+ * These should normally not happen.
+ * Usually, exception trace with internal error includes
+ * important messages.
+ */
+DECLARE_EXCEPTION_TYPE(Exception, InternalError) ///< Unexpected error from
+ // underlying libraries or
+ // kernel
+}
+}
+
+#endif // DPL_EXCEPTION_H
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file abstract_log_provider.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of abstract log provider
+ */
+#ifndef DPL_ABSTRACT_LOG_PROVIDER_H
+#define DPL_ABSTRACT_LOG_PROVIDER_H
+
+namespace DPL {
+namespace Log {
+class AbstractLogProvider
+{
+ public:
+ virtual ~AbstractLogProvider() {}
+
+ virtual void Debug(const char *message,
+ const char *fileName,
+ int line,
+ const char *function) = 0;
+ virtual void Info(const char *message,
+ const char *fileName,
+ int line,
+ const char *function) = 0;
+ virtual void Warning(const char *message,
+ const char *fileName,
+ int line,
+ const char *function) = 0;
+ virtual void Error(const char *message,
+ const char *fileName,
+ int line,
+ const char *function) = 0;
+ virtual void Pedantic(const char *message,
+ const char *fileName,
+ int line,
+ const char *function) = 0;
+
+ protected:
+ static const char *LocateSourceFileName(const char *filename);
+};
+}
+} // namespace DPL
+
+#endif // DPL_ABSTRACT_LOG_PROVIDER_H
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file dlog_log_provider.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of DLOG log provider
+ */
+#ifndef DPL_DLOG_LOG_PROVIDER_H
+#define DPL_DLOG_LOG_PROVIDER_H
+
+#include <dpl/log/abstract_log_provider.h>
+#include <dpl/scoped_free.h>
+#include <string>
+
+namespace DPL {
+namespace Log {
+class DLOGLogProvider :
+ public AbstractLogProvider
+{
+ private:
+ DPL::ScopedFree<char> m_tag;
+
+ static std::string FormatMessage(const char *message,
+ const char *filename,
+ int line,
+ const char *function);
+
+ public:
+ DLOGLogProvider();
+ virtual ~DLOGLogProvider();
+
+ virtual void Debug(const char *message,
+ const char *fileName,
+ int line,
+ const char *function);
+ virtual void Info(const char *message,
+ const char *fileName,
+ int line,
+ const char *function);
+ virtual void Warning(const char *message,
+ const char *fileName,
+ int line,
+ const char *function);
+ virtual void Error(const char *message,
+ const char *fileName,
+ int line,
+ const char *function);
+ virtual void Pedantic(const char *message,
+ const char *fileName,
+ int line,
+ const char *function);
+
+ // Set global Tag according to DLOG
+ void SetTag(const char *tag);
+};
+}
+} // namespace DPL
+
+#endif // DPL_DLOG_LOG_PROVIDER_H
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file log.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of log system
+ */
+#ifndef DPL_LOG_H
+#define DPL_LOG_H
+
+#include <dpl/singleton.h>
+#include <dpl/noncopyable.h>
+#include <dpl/log/abstract_log_provider.h>
+#include <dpl/log/dlog_log_provider.h>
+#include <dpl/log/old_style_log_provider.h>
+#include <sstream>
+#include <list>
+
+namespace DPL {
+namespace Log {
+/**
+ * DPL log system
+ *
+ * To switch logs into old style, export
+ * DPL_USE_OLD_STYLE_LOGS before application start
+ */
+class LogSystem :
+ private Noncopyable
+{
+ private:
+ typedef std::list<AbstractLogProvider *> AbstractLogProviderPtrList;
+ AbstractLogProviderPtrList m_providers;
+
+ DLOGLogProvider *m_dlogProvider;
+ OldStyleLogProvider *m_oldStyleProvider;
+
+ bool m_isLoggingEnabled;
+
+ public:
+ bool IsLoggingEnabled() const;
+ LogSystem();
+ virtual ~LogSystem();
+
+ /**
+ * Log debug message
+ */
+ void Debug(const char *message,
+ const char *filename,
+ int line,
+ const char *function);
+
+ /**
+ * Log info message
+ */
+ void Info(const char *message,
+ const char *filename,
+ int line,
+ const char *function);
+
+ /**
+ * Log warning message
+ */
+ void Warning(const char *message,
+ const char *filename,
+ int line,
+ const char *function);
+
+ /**
+ * Log error message
+ */
+ void Error(const char *message,
+ const char *filename,
+ int line,
+ const char *function);
+
+ /**
+ * Log pedantic message
+ */
+ void Pedantic(const char *message,
+ const char *filename,
+ int line,
+ const char *function);
+
+ /**
+ * Set default's DLOG provider Tag
+ */
+ void SetTag(const char *tag);
+
+ /**
+ * Add abstract provider to providers list
+ *
+ * @notice Ownership is transfered to LogSystem and deleted upon exit
+ */
+ void AddProvider(AbstractLogProvider *provider);
+
+ /**
+ * Remove abstract provider from providers list
+ */
+ void RemoveProvider(AbstractLogProvider *provider);
+};
+
+/*
+ * Replacement low overhead null logging class
+ */
+class NullStream
+{
+ public:
+ NullStream() {}
+
+ template <typename T>
+ NullStream& operator<<(const T&)
+ {
+ return *this;
+ }
+};
+
+/**
+ * Log system singleton
+ */
+typedef Singleton<LogSystem> LogSystemSingleton;
+}
+} // namespace DPL
+
+//
+// Log support
+//
+//
+
+#ifdef DPL_LOGS_ENABLED
+ #define DPL_MACRO_FOR_LOGGING(message, function) \
+ do \
+ { \
+ if (DPL::Log::LogSystemSingleton::Instance().IsLoggingEnabled()) \
+ { \
+ std::ostringstream platformLog; \
+ platformLog << message; \
+ DPL::Log::LogSystemSingleton::Instance().function( \
+ platformLog.str().c_str(), \
+ __FILE__, __LINE__, __FUNCTION__); \
+ } \
+ } while (0)
+#else
+/* avoid warnings about unused variables */
+ #define DPL_MACRO_FOR_LOGGING(message, function) \
+ do { \
+ DPL::Log::NullStream ns; \
+ ns << message; \
+ } while (0)
+#endif
+
+#define LogDebug(message) DPL_MACRO_FOR_LOGGING(message, Debug)
+#define LogInfo(message) DPL_MACRO_FOR_LOGGING(message, Info)
+#define LogWarning(message) DPL_MACRO_FOR_LOGGING(message, Warning)
+#define LogError(message) DPL_MACRO_FOR_LOGGING(message, Error)
+#define LogPedantic(message) DPL_MACRO_FOR_LOGGING(message, Pedantic)
+
+#endif // DPL_LOG_H
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file old_style_log_provider.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of old style log provider
+ */
+#ifndef DPL_OLD_STYLE_LOG_PROVIDER_H
+#define DPL_OLD_STYLE_LOG_PROVIDER_H
+
+#include <dpl/log/abstract_log_provider.h>
+#include <string>
+
+namespace DPL {
+namespace Log {
+class OldStyleLogProvider :
+ public AbstractLogProvider
+{
+ private:
+ bool m_showDebug;
+ bool m_showInfo;
+ bool m_showWarning;
+ bool m_showError;
+ bool m_showPedantic;
+ bool m_printStdErr;
+
+ static std::string FormatMessage(const char *message,
+ const char *filename,
+ int line,
+ const char *function);
+
+ public:
+ OldStyleLogProvider(bool showDebug,
+ bool showInfo,
+ bool showWarning,
+ bool showError,
+ bool showPedantic);
+ OldStyleLogProvider(bool showDebug,
+ bool showInfo,
+ bool showWarning,
+ bool showError,
+ bool showPedantic,
+ bool printStdErr);
+ virtual ~OldStyleLogProvider() {}
+
+ virtual void Debug(const char *message,
+ const char *fileName,
+ int line,
+ const char *function);
+ virtual void Info(const char *message,
+ const char *fileName,
+ int line,
+ const char *function);
+ virtual void Warning(const char *message,
+ const char *fileName,
+ int line,
+ const char *function);
+ virtual void Error(const char *message,
+ const char *fileName,
+ int line,
+ const char *function);
+ virtual void Pedantic(const char *message,
+ const char *fileName,
+ int line,
+ const char *function);
+};
+}
+} // namespace DPL
+
+#endif // DPL_OLD_STYLE_LOG_PROVIDER_H
--- /dev/null
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @file secure_log.h
+ * @author Jihoon Chung(jihoon.chung@samsung.com)
+ * @version 0.1
+ * @brief
+ */
+
+#ifndef DPL_SECURE_LOG_H
+#define DPL_SECURE_LOG_H
+
+#include <dlog.h>
+
+#define COLOR_ERROR "\e[1;31m"
+#define COLOR_WARNING "\e[2;31m"
+#define COLOR_END "\e[0m"
+#define COLOR_TAG "\e[0m"
+
+// default TAG
+#undef LOG_TAG
+#define LOG_TAG "WRT_UNDEFINED"
+
+#ifdef WRT_LOG
+#undef LOG_TAG
+#define LOG_TAG "WRT"
+#undef COLOR_TAG
+#define COLOR_TAG "\e[1;32m"
+#endif
+
+#ifdef WRT_BUNDLE_LOG
+#undef LOG_TAG
+#define LOG_TAG "WRT_BUNDLE"
+#undef COLOR_TAG
+#define COLOR_TAG "\e[1;34m"
+#endif
+
+#ifdef WRT_PLUGINS_COMMON_LOG
+#undef LOG_TAG
+#define LOG_TAG "WRT_PLUGINS/COMMON"
+#undef COLOR_TAG
+#define COLOR_TAG "\e[1;36m"
+#endif
+
+#ifdef WRT_PLUGINS_WIDGET_LOG
+#undef LOG_TAG
+#define LOG_TAG "WRT_PLUGINS/WIDGET"
+#undef COLOR_TAG
+#define COLOR_TAG "\e[1;35m"
+#endif
+
+#ifdef WRT_INSTALLER_LOG
+#undef LOG_TAG
+#define LOG_TAG "WRT_INSTALLER"
+#undef COLOR_TAG
+#define COLOR_TAG "\e[1;32m"
+#endif
+
+#ifndef SECURE_SLOGD
+#define SECURE_SLOGD(fmt, arg...) SLOGD(fmt,##arg)
+#endif
+
+#ifndef SECURE_SLOGW
+#define SECURE_SLOGW(fmt, arg...) SLOGW(fmt,##arg)
+#endif
+
+#ifndef SECURE_SLOGE
+#define SECURE_SLOGE(fmt, arg...) SLOGE(fmt,##arg)
+#endif
+
+#define _D(fmt, arg ...) SECURE_SLOGD(COLOR_TAG fmt COLOR_END,##arg)
+#define _W(fmt, arg ...) SECURE_SLOGW(COLOR_WARNING fmt COLOR_END,##arg)
+#define _E(fmt, arg ...) SECURE_SLOGE(COLOR_ERROR fmt COLOR_END,##arg)
+
+#endif // DPL_SECURE_LOG_H
+
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file noncopyable
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of noncopyable
+ */
+#ifndef DPL_NONCOPYABLE_H
+#define DPL_NONCOPYABLE_H
+
+namespace DPL {
+class Noncopyable
+{
+ private:
+ Noncopyable(const Noncopyable &);
+ const Noncopyable &operator=(const Noncopyable &);
+
+ public:
+ Noncopyable();
+ virtual ~Noncopyable();
+};
+} // namespace DPL
+
+#endif // DPL_NONCOPYABLE_H
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file noreturn.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of noreturn
+ */
+#ifndef DPL_NORETURN_H
+#define DPL_NORETURN_H
+
+#define DPL_NORETURN __attribute__((__noreturn__))
+
+#endif // DPL_NORETURN_H
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*!
+ * @file scoped_fclose.h
+ * @author Piotr Marcinkiewicz (p.marcinkiew@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of scoped fclose RAII
+ */
+#ifndef DPL_SCOPED_FCLOSE_H
+#define DPL_SCOPED_FCLOSE_H
+
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <cerrno>
+#include <cstdio>
+#include <string>
+#include <dpl/log/log.h>
+#include <dpl/scoped_resource.h>
+
+namespace DPL {
+struct ScopedFClosePolicy
+{
+ typedef FILE* Type;
+ static Type NullValue()
+ {
+ return NULL;
+ }
+ static void Destroy(Type file)
+ {
+ if (file != NULL) {
+ // Try to flush first
+ if (TEMP_FAILURE_RETRY(fflush(file)) != 0) {
+ std::string errString = strerror(errno);
+ LogPedantic("Failed to fflush scoped fclose error: "
+ << errString);
+ }
+
+ // fclose cannot be retried, try to close once
+ if (fclose(file) != 0) {
+ std::string errString = strerror(errno);
+ LogPedantic("Failed scoped fclose error: " << errString);
+ }
+ }
+ }
+};
+
+class ScopedFClose : public ScopedResource<ScopedFClosePolicy>
+{
+ typedef ScopedFClosePolicy Policy;
+ typedef ScopedResource<Policy> BaseType;
+
+ public:
+ explicit ScopedFClose(FILE* argFileStream = Policy::NullValue()) :
+ BaseType(argFileStream)
+ {}
+};
+} // namespace DPL
+
+#endif // DPL_SCOPED_FCLOSE_H
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*!
+ * @file scoped_free.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of scoped free RAII
+ */
+
+#ifndef DPL_SCOPED_FREE_H
+#define DPL_SCOPED_FREE_H
+
+#include <malloc.h>
+#include <cstddef>
+
+#include <dpl/scoped_resource.h>
+
+namespace DPL {
+template<typename Class>
+struct ScopedFreePolicy
+{
+ typedef Class* Type;
+ static Type NullValue()
+ {
+ return NULL;
+ }
+ static void Destroy(Type ptr)
+ {
+ free(ptr);
+ }
+};
+
+template<typename Memory>
+class ScopedFree : public ScopedResource<ScopedFreePolicy<Memory> >
+{
+ typedef ScopedFreePolicy<Memory> Policy;
+ typedef ScopedResource<Policy> BaseType;
+
+ public:
+ explicit ScopedFree(Memory *ptr = Policy::NullValue()) : BaseType(ptr) { }
+};
+} // namespace DPL
+
+#endif // DPL_SCOPED_FREE_H
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file scoped_resource.h
+ * @author Piotr Marcinkiewicz (p.marcinkiew@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of scoped resource pattern
+ */
+#ifndef DPL_SCOPED_RESOURCE_H
+#define DPL_SCOPED_RESOURCE_H
+
+#include <dpl/noncopyable.h>
+
+namespace DPL {
+template<typename ClassPolicy>
+class ScopedResource :
+ private Noncopyable
+{
+ public:
+ typedef typename ClassPolicy::Type ValueType;
+ typedef ScopedResource<ClassPolicy> ThisType;
+
+ protected:
+ ValueType m_value;
+
+ public:
+ explicit ScopedResource(ValueType value) : m_value(value) { }
+
+ ~ScopedResource()
+ {
+ ClassPolicy::Destroy(m_value);
+ }
+
+ ValueType Get() const
+ {
+ return m_value;
+ }
+
+ void Reset(ValueType value = ClassPolicy::NullValue())
+ {
+ ClassPolicy::Destroy(m_value);
+ m_value = value;
+ }
+
+ ValueType Release()
+ {
+ ValueType value = m_value;
+ m_value = ClassPolicy::NullValue();
+ return value;
+ }
+ typedef ValueType ThisType::*UnknownBoolType;
+
+ operator UnknownBoolType() const
+ {
+ return m_value == ClassPolicy::NullValue() ?
+ 0 : //0 is valid here because it converts to false
+ &ThisType::m_value; //it converts to true
+ }
+
+ bool operator !() const
+ {
+ return m_value == ClassPolicy::NullValue();
+ }
+};
+} // namespace DPL
+
+#endif // DPL_SCOPED_RESOURCE_H
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file singleton.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of singleton
+ */
+#ifndef DPL_SINGLETON_H
+#define DPL_SINGLETON_H
+
+#include <dpl/assert.h>
+
+namespace DPL {
+template<typename Class>
+class Singleton :
+ private Class
+{
+ //
+ // Note:
+ //
+ // To remove posibility of instantiating directly Class,
+ // make Class' default constructor protected
+ //
+
+ private:
+ Singleton()
+ {}
+
+ static Singleton &InternalInstance();
+
+ public:
+ virtual ~Singleton()
+ {}
+
+ static Class &Instance();
+};
+} // namespace DPL
+
+#endif // DPL_SINGLETON_H
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file singleton_impl.h
+ * @author Lukasz Wrzosek (l.wrzosek@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of singleton
+ */
+#ifndef DPL_SINGLETON_IMPL_H
+#define DPL_SINGLETON_IMPL_H
+
+/*
+ * WARNING!
+ *
+ * If some singleton's implementation uses another singletons implementation,
+ * those templates make the second singleton a dubleton. Be warned. Try to use
+ * singleton_safe_impl.h if possible.
+ */
+
+namespace DPL {
+template<typename Class>
+Singleton<Class>& Singleton<Class>::InternalInstance()
+{
+ static Singleton<Class> instance;
+ return instance;
+}
+
+template<typename Class>
+Class &Singleton<Class>::Instance()
+{
+ Singleton<Class>& instance = Singleton<Class>::InternalInstance();
+ return instance;
+}
+} // namespace DPL
+
+#define IMPLEMENT_SINGLETON(Type) \
+ template DPL::Singleton<Type>&DPL::Singleton<Type>::InternalInstance(); \
+ template Type & DPL::Singleton<Type>::Instance(); \
+
+#endif // DPL_SINGLETON_IMPL_H
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file singleton_safe_impl.h
+ * @author Tomasz Swierczek (t.swierczek@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of singleton
+ */
+#ifndef DPL_SINGLETON_SAFE_IMPL_H
+#define DPL_SINGLETON_SAFE_IMPL_H
+
+#define IMPLEMENT_SAFE_SINGLETON(Class) \
+ namespace DPL { \
+ template<> \
+ Singleton<Class>&Singleton<Class>::InternalInstance() \
+ { \
+ static Singleton<Class> instance; \
+ return instance; \
+ } \
+ \
+ template<> \
+ Class & Singleton<Class>::Instance() \
+ { \
+ Singleton<Class>& instance = Singleton<Class>::InternalInstance(); \
+ return instance; \
+ } \
+ \
+ template Singleton<Class>&Singleton<Class>::InternalInstance(); \
+ template Class & Singleton<Class>::Instance(); \
+ } // namespace DPL
+
+#endif // DPL_SINGLETON_SAFE_IMPL_H
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file test_results_collector.h
+ * @author Lukasz Wrzosek (l.wrzosek@samsung.com)
+ * @version 1.0
+ * @brief Header file with declaration of TestResultsCollectorBase
+ */
+
+#ifndef DPL_TEST_RESULTS_COLLECTOR_H
+#define DPL_TEST_RESULTS_COLLECTOR_H
+
+#include <dpl/noncopyable.h>
+#include <vector>
+#include <list>
+#include <map>
+#include <chrono>
+#include <string>
+#include <memory>
+
+namespace DPL {
+namespace Test {
+class TestResultsCollectorBase;
+typedef std::shared_ptr<TestResultsCollectorBase>
+TestResultsCollectorBasePtr;
+
+class TestResultsCollectorBase :
+ private DPL::Noncopyable
+{
+ public:
+ typedef TestResultsCollectorBase* (*CollectorConstructorFunc)();
+ typedef std::list<std::string> TestCaseIdList;
+ struct FailStatus
+ {
+ enum Type
+ {
+ NONE,
+ FAILED,
+ IGNORED,
+ INTERNAL
+ };
+ };
+
+ virtual ~TestResultsCollectorBase() {}
+
+ virtual bool Configure()
+ {
+ return true;
+ }
+ virtual void Start() { }
+ virtual void Finish() { }
+ virtual void CollectCurrentTestGroupName(const std::string& /*groupName*/)
+ {}
+
+ virtual void CollectTestsCasesList(const TestCaseIdList& /*list*/) {}
+ virtual void CollectResult(const std::string& id,
+ const std::string& description,
+ const FailStatus::Type status = FailStatus::NONE,
+ const std::string& reason = "",
+ const bool& isPerformanceTest = false,
+ const std::chrono::system_clock::duration& performanceTime = std::chrono::microseconds::zero(),
+ const std::chrono::system_clock::duration& performanceMaxTime = std::chrono::microseconds::zero()) = 0;
+ virtual std::string CollectorSpecificHelp() const
+ {
+ return "";
+ }
+ virtual bool ParseCollectorSpecificArg (const std::string& /*arg*/)
+ {
+ return false;
+ }
+
+ static TestResultsCollectorBase* Create(const std::string& name);
+ static void RegisterCollectorConstructor(
+ const std::string& name,
+ CollectorConstructorFunc
+ constructor);
+ static std::vector<std::string> GetCollectorsNames();
+
+ private:
+ typedef std::map<std::string, CollectorConstructorFunc> ConstructorsMap;
+ static ConstructorsMap m_constructorsMap;
+};
+}
+}
+
+#endif /* DPL_TEST_RESULTS_COLLECTOR_H */
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file test_runner.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @author Lukasz Wrzosek (l.wrzosek@samsung.com)
+ * @version 1.0
+ * @brief This file is the header file of test runner
+ */
+#ifndef DPL_TEST_RUNNER_H
+#define DPL_TEST_RUNNER_H
+
+#include <dpl/singleton.h>
+#include <dpl/availability.h>
+#include <dpl/atomic.h>
+#include <dpl/test/test_results_collector.h>
+#include <sstream>
+#include <string>
+#include <vector>
+#include <chrono>
+#include <list>
+#include <set>
+#include <map>
+
+namespace DPL {
+namespace Test {
+class TestRunner
+{
+ typedef std::map<std::string, TestResultsCollectorBasePtr>
+ TestResultsCollectors;
+ TestResultsCollectors m_collectors;
+
+ std::string m_startTestId;
+ bool m_runIgnored;
+
+ public:
+ TestRunner() :
+ m_currentTestCase(NULL)
+ , m_terminate(false)
+ , m_allowChildLogs(false)
+ {}
+
+ void beginPerformanceTestTime(std::chrono::system_clock::duration maxTimeInMicroseconds);
+ void endPerformanceTestTime();
+ void getCurrentTestCasePerformanceResult(bool& isPerformanceTest,
+ std::chrono::system_clock::duration& result,
+ std::chrono::system_clock::duration& resultMax);
+ void setCurrentTestCasePerformanceResult(bool isPerformanceTest,
+ std::chrono::system_clock::duration result,
+ std::chrono::system_clock::duration resultMax);
+
+ typedef void (*TestCase)();
+
+ private:
+ struct TestCaseStruct
+ {
+ std::string name;
+ TestCase proc;
+
+ bool m_isPerformanceTest;
+ std::chrono::system_clock::time_point m_performanceTestStartTime;
+ std::chrono::system_clock::duration m_performanceTestDurationTime;
+ std::chrono::system_clock::duration m_performanceMaxTime;
+
+ bool operator <(const TestCaseStruct &other) const
+ {
+ return name < other.name;
+ }
+
+ bool operator ==(const TestCaseStruct &other) const
+ {
+ return name == other.name;
+ }
+
+ TestCaseStruct(const std::string &n, TestCase p) :
+ name(n),
+ proc(p),
+ m_isPerformanceTest(false)
+ {}
+ };
+
+ typedef std::list<TestCaseStruct> TestCaseStructList;
+ typedef std::map<std::string, TestCaseStructList> TestCaseGroupMap;
+ TestCaseGroupMap m_testGroups;
+
+ TestCaseStruct * m_currentTestCase;
+
+ typedef std::set<std::string> SelectedTestNameSet;
+ SelectedTestNameSet m_selectedTestNamesSet;
+ typedef std::set<std::string> SelectedTestGroupSet;
+ SelectedTestGroupSet m_selectedTestGroupSet;
+ std::string m_currentGroup;
+
+ DPL::Atomic m_totalAssertions;
+
+ // Terminate without any logs.
+ // Some test requires to call fork function.
+ // Child process must not produce any logs and should die quietly.
+ bool m_terminate;
+ bool m_allowChildLogs;
+
+ void Banner();
+ void InvalidArgs(const std::string& message = "Invalid arguments!");
+ void Usage();
+
+ bool filterGroupsByXmls(const std::vector<std::string> & files);
+ bool filterByXML(std::map<std::string, bool> & casesMap);
+ void normalizeXMLTag(std::string& str, const std::string& testcase);
+
+ enum Status { FAILED, IGNORED, PASS };
+
+ Status RunTestCase(const TestCaseStruct& testCase);
+
+ void setCurrentTestCase(TestCaseStruct* testCase);
+ TestCaseStruct *getCurrentTestCase();
+
+ void RunTests();
+
+ void CollectResult(const std::string& id,
+ const std::string& description,
+ const TestResultsCollectorBase::FailStatus::Type status
+ = TestResultsCollectorBase::FailStatus::NONE,
+ const std::string& reason = std::string(),
+ const bool& isPerformanceTest = false,
+ const std::chrono::system_clock::duration& performanceTime = std::chrono::microseconds::zero(),
+ const std::chrono::system_clock::duration& performanceMaxTime = std::chrono::microseconds::zero());
+
+ public:
+ class TestFailed
+ {
+ private:
+ std::string m_message;
+
+ public:
+ TestFailed()
+ {}
+
+ //! \brief Failed test message creator
+ //!
+ //! \param[in] aTest string for tested expression
+ //! \param[in] aFile source file name
+ //! \param[in] aLine source file line
+ //! \param[in] aMessage error message
+ TestFailed(const char* aTest,
+ const char* aFile,
+ int aLine,
+ const std::string &aMessage);
+
+ TestFailed(const std::string &message);
+
+ std::string GetMessage() const
+ {
+ return m_message;
+ }
+ };
+
+ class Ignored
+ {
+ private:
+ std::string m_message;
+
+ public:
+ Ignored()
+ {}
+
+ Ignored(const std::string &message) :
+ m_message(message)
+ {}
+
+ std::string GetMessage() const
+ {
+ return m_message;
+ }
+ };
+
+ void MarkAssertion();
+
+ void RegisterTest(const char *testName, TestCase proc);
+ void InitGroup(const char* name);
+
+ int ExecTestRunner(int argc, char *argv[]);
+ typedef std::vector<std::string> ArgsList;
+ int ExecTestRunner(ArgsList args);
+ bool getRunIgnored() const;
+ // The runner will terminate as soon as possible (after current test).
+ void Terminate();
+ bool GetAllowChildLogs();
+};
+
+typedef DPL::Singleton<TestRunner> TestRunnerSingleton;
+}
+} // namespace DPL
+
+#define RUNNER_TEST_GROUP_INIT(GroupName) \
+ static int Static##GroupName##Init() \
+ { \
+ DPL::Test::TestRunnerSingleton::Instance().InitGroup(#GroupName); \
+ return 0; \
+ } \
+ const int DPL_UNUSED Static##GroupName##InitVar = \
+ Static##GroupName##Init();
+
+#define RUNNER_TEST(Proc) \
+ void Proc(); \
+ static int Static##Proc##Init() \
+ { \
+ DPL::Test::TestRunnerSingleton::Instance().RegisterTest(#Proc, &Proc); \
+ return 0; \
+ } \
+ const int DPL_UNUSED Static##Proc##InitVar = Static##Proc##Init(); \
+ void Proc()
+
+//! \brief Returns base name for path
+
+#define RUNNER_ASSERT_MSG(test, message) \
+ do \
+ { \
+ DPL::Test::TestRunnerSingleton::Instance().MarkAssertion(); \
+ \
+ if (!(test)) \
+ { \
+ std::ostringstream assertMsg; \
+ assertMsg << message; \
+ throw DPL::Test::TestRunner::TestFailed(#test, \
+ __FILE__, \
+ __LINE__, \
+ assertMsg.str()); \
+ } \
+ } while (0)
+
+#define RUNNER_ASSERT(test) RUNNER_ASSERT_MSG(test, "")
+
+#define RUNNER_FAIL RUNNER_ASSERT(false)
+
+#define RUNNER_IGNORED_MSG(message) do { std::ostringstream assertMsg; \
+ assertMsg << message; \
+ throw DPL::Test::TestRunner::Ignored( \
+ assertMsg.str()); \
+} while (0)
+
+/*
+ * Use these macros to do the time measurement. The first macro will start time measurement,
+ * the second will gather the result. These macros can be used only once per test-case.
+ * The result of time measurement will be displayed only if the test will pass.
+ * Notice that these macros will work only if will be used in parent process. If these
+ * macros will be used in child process then there will be no time measure results printed.
+ * This macro in multiprocess tests has effect only if used in parent process. This macro
+ * used in child process in multiprocess test has no effect.
+ * The precision of measurement is 1 microsecond - the smallest time value that can be
+ * measured is 0.000001s.
+ * The time measure results will be printed only specific output format:
+ * - text
+ * - html
+ * - xml
+ * - csv
+ * In TAP format performance result will not be displayed.
+ */
+#define RUNNER_PERF_TEST_BEGIN(maxTime) \
+ do { \
+ DPL::Test::TestRunnerSingleton::Instance().beginPerformanceTestTime( \
+ std::chrono::microseconds{static_cast<long long int>(maxTime*1000000.0)}); \
+ } while (0)
+
+#define RUNNER_PERF_TEST_END() \
+ do { \
+ DPL::Test::TestRunnerSingleton::Instance().endPerformanceTestTime(); \
+ } while (0)
+
+#endif // DPL_TEST_RUNNER_H
--- /dev/null
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file test_runner_child.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief This file is the header file of test runner
+ */
+#ifndef DPL_TEST_RUNNER_CHILD_H
+#define DPL_TEST_RUNNER_CHILD_H
+
+#include <dpl/test/test_runner.h>
+
+namespace DPL {
+namespace Test {
+
+class PipeWrapper : DPL::Noncopyable
+{
+ public:
+ enum Usage {
+ READONLY,
+ WRITEONLY
+ };
+
+ enum Status {
+ SUCCESS,
+ TIMEOUT,
+ ERROR
+ };
+
+ PipeWrapper();
+
+ bool isReady();
+
+ void setUsage(Usage usage);
+
+ virtual ~PipeWrapper();
+
+ Status send(int code, std::string &message);
+ Status sendTime(int code,
+ std::chrono::system_clock::duration time,
+ std::chrono::system_clock::duration timeMax);
+
+ Status receive(int &code,
+ int &msgType,
+ std::string &data,
+ std::chrono::system_clock::duration &time,
+ std::chrono::system_clock::duration &timeMax,
+ time_t deadline);
+
+ void closeAll();
+
+ protected:
+
+ std::string toBinaryString(int data);
+ std::string toBinaryString(std::chrono::system_clock::duration data);
+
+ void closeHelp(int desc);
+
+ Status writeHelp(const void *buffer, int size);
+
+ Status readHelp(void *buf, int size, time_t deadline);
+
+ static const int PIPE_CLOSED = -1;
+
+ int m_pipefd[2];
+};
+
+void RunChildProc(TestRunner::TestCase procChild);
+} // namespace Test
+} // namespace DPL
+
+#define RUNNER_CHILD_TEST(Proc) \
+ void Proc(); \
+ void Proc##Child(); \
+ static int Static##Proc##Init() \
+ { \
+ DPL::Test::TestRunnerSingleton::Instance().RegisterTest(#Proc, &Proc); \
+ return 0; \
+ } \
+ const int DPL_UNUSED Static##Proc##InitVar = Static##Proc##Init(); \
+ void Proc(){ \
+ DPL::Test::RunChildProc(&Proc##Child); \
+ } \
+ void Proc##Child()
+
+#endif // DPL_TEST_RUNNER_CHILD_H
--- /dev/null
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file test_runner_multiprocess.h
+ * @author Marcin Niesluchowski (m.niesluchow@samsung.com)
+ * @version 1.0
+ * @brief This file is the header file of multiprocess test runner
+ */
+#ifndef DPL_TEST_RUNNER_MULTIPROCESS_H
+#define DPL_TEST_RUNNER_MULTIPROCESS_H
+
+#include <dpl/test/test_runner_child.h>
+
+namespace DPL {
+namespace Test {
+
+class SimplePipeWrapper :
+ public PipeWrapper
+{
+ public:
+ SimplePipeWrapper();
+
+ virtual ~SimplePipeWrapper();
+
+ Status send(std::string &message);
+ Status receive(std::string &data, bool &empty, time_t deadline);
+};
+
+void RunMultiProc(TestRunner::TestCase procMulti);
+} // namespace Test
+} // namespace DPL
+
+#define RUNNER_MULTIPROCESS_TEST(Proc) \
+ void Proc(); \
+ void Proc##Multi(); \
+ static int Static##Proc##Init() \
+ { \
+ DPL::Test::TestRunnerSingleton::Instance().RegisterTest(#Proc, &Proc); \
+ return 0; \
+ } \
+ const int DPL_UNUSED Static##Proc##InitVar = Static##Proc##Init(); \
+ void Proc(){ \
+ DPL::Test::RunMultiProc(&Proc##Multi); \
+ } \
+ void Proc##Multi()
+
+#endif // DPL_TEST_RUNNER_MULTIPROCESS_H
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file abstract_log_provider.cpp
+ * @author Pawel Sikorski (p.sikorski@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of abstract log provider
+ */
+#include <stddef.h>
+#include <dpl/log/abstract_log_provider.h>
+#include <cstring>
+
+namespace DPL {
+namespace Log {
+const char *AbstractLogProvider::LocateSourceFileName(const char *filename)
+{
+ const char *ptr = strrchr(filename, '/');
+ return ptr != NULL ? ptr + 1 : filename;
+}
+}
+}
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file assert.cpp
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of assert
+ */
+#include <stddef.h>
+#include <dpl/assert.h>
+#include <dpl/colors.h>
+#include <dpl/exception.h>
+#include <dpl/log/log.h>
+#include <cstdlib>
+
+namespace DPL {
+void AssertProc(const char *condition,
+ const char *file,
+ int line,
+ const char *function)
+{
+#define INTERNAL_LOG(message) \
+ do \
+ { \
+ std::ostringstream platformLog; \
+ platformLog << message; \
+ DPL::Log::LogSystemSingleton::Instance().Pedantic( \
+ platformLog.str().c_str(), \
+ __FILE__, __LINE__, __FUNCTION__); \
+ } \
+ while (0)
+
+ // Try to log failed assertion to log system
+ Try
+ {
+ INTERNAL_LOG(
+ "################################################################################");
+ INTERNAL_LOG(
+ "### DPL assertion failed! ###");
+ INTERNAL_LOG(
+ "################################################################################");
+ INTERNAL_LOG("### Condition: " << condition);
+ INTERNAL_LOG("### File: " << file);
+ INTERNAL_LOG("### Line: " << line);
+ INTERNAL_LOG("### Function: " << function);
+ INTERNAL_LOG(
+ "################################################################################");
+ } catch (Exception) {
+ // Just ignore possible double errors
+ }
+
+ // Fail with c-library abort
+ abort();
+}
+} // namespace DPL
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file atomic.cpp
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of atomic
+ */
+#include <stddef.h>
+#include <dpl/atomic.h>
+
+namespace DPL {
+Atomic::Atomic(ValueType value) :
+ m_value(value)
+{}
+
+Atomic::ValueType Atomic::ExchangeAndAdd(ValueType value)
+{
+ return g_atomic_int_add(const_cast<gint* >(&m_value), value);
+}
+
+bool Atomic::CompareAndExchange(ValueType oldValue, ValueType newValue)
+{
+ return g_atomic_int_compare_and_exchange(const_cast<gint* >(&m_value),
+ oldValue,
+ newValue);
+}
+
+bool Atomic::operator--()
+{
+ return g_atomic_int_dec_and_test(const_cast<gint* >(&m_value)) != TRUE;
+}
+
+void Atomic::operator++()
+{
+ g_atomic_int_inc(const_cast<gint* >(&m_value));
+}
+
+Atomic::operator ValueType() const
+{
+ return g_atomic_int_get(const_cast<gint* >(&m_value));
+}
+} // namespace DPL
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file binary_queue.cpp
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of binary queue
+ */
+#include <stddef.h>
+#include <dpl/binary_queue.h>
+#include <dpl/assert.h>
+#include <dpl/scoped_free.h>
+#include <algorithm>
+#include <malloc.h>
+#include <cstring>
+#include <new>
+
+namespace DPL {
+BinaryQueue::BinaryQueue() :
+ m_size(0)
+{}
+
+BinaryQueue::BinaryQueue(const BinaryQueue &other) :
+ m_size(0)
+{
+ AppendCopyFrom(other);
+}
+
+BinaryQueue::~BinaryQueue()
+{
+ // Remove all remainig buckets
+ Clear();
+}
+
+const BinaryQueue &BinaryQueue::operator=(const BinaryQueue &other)
+{
+ if (this != &other) {
+ Clear();
+ AppendCopyFrom(other);
+ }
+
+ return *this;
+}
+
+void BinaryQueue::AppendCopyFrom(const BinaryQueue &other)
+{
+ // To speed things up, always copy as one bucket
+ void *bufferCopy = malloc(other.m_size);
+
+ if (bufferCopy == NULL) {
+ throw std::bad_alloc();
+ }
+
+ try {
+ other.Flatten(bufferCopy, other.m_size);
+ AppendUnmanaged(bufferCopy, other.m_size, &BufferDeleterFree, NULL);
+ } catch (const std::bad_alloc &) {
+ // Free allocated memory
+ free(bufferCopy);
+ throw;
+ }
+}
+
+void BinaryQueue::AppendMoveFrom(BinaryQueue &other)
+{
+ // Copy all buckets
+ std::copy(other.m_buckets.begin(),
+ other.m_buckets.end(), std::back_inserter(m_buckets));
+ m_size += other.m_size;
+
+ // Clear other, but do not free memory
+ other.m_buckets.clear();
+ other.m_size = 0;
+}
+
+void BinaryQueue::AppendCopyTo(BinaryQueue &other) const
+{
+ other.AppendCopyFrom(*this);
+}
+
+void BinaryQueue::AppendMoveTo(BinaryQueue &other)
+{
+ other.AppendMoveFrom(*this);
+}
+
+void BinaryQueue::Clear()
+{
+ std::for_each(m_buckets.begin(), m_buckets.end(), &DeleteBucket);
+ m_buckets.clear();
+ m_size = 0;
+}
+
+void BinaryQueue::AppendCopy(const void* buffer, size_t bufferSize)
+{
+ // Create data copy with malloc/free
+ void *bufferCopy = malloc(bufferSize);
+
+ // Check if allocation succeded
+ if (bufferCopy == NULL) {
+ throw std::bad_alloc();
+ }
+
+ // Copy user data
+ memcpy(bufferCopy, buffer, bufferSize);
+
+ try {
+ // Try to append new bucket
+ AppendUnmanaged(bufferCopy, bufferSize, &BufferDeleterFree, NULL);
+ } catch (const std::bad_alloc &) {
+ // Free allocated memory
+ free(bufferCopy);
+ throw;
+ }
+}
+
+void BinaryQueue::AppendUnmanaged(const void* buffer,
+ size_t bufferSize,
+ BufferDeleter deleter,
+ void* userParam)
+{
+ // Do not attach empty buckets
+ if (bufferSize == 0) {
+ deleter(buffer, bufferSize, userParam);
+ return;
+ }
+
+ // Just add new bucket with selected deleter
+ m_buckets.push_back(new Bucket(buffer, bufferSize, deleter, userParam));
+
+ // Increase total queue size
+ m_size += bufferSize;
+}
+
+size_t BinaryQueue::Size() const
+{
+ return m_size;
+}
+
+bool BinaryQueue::Empty() const
+{
+ return m_size == 0;
+}
+
+void BinaryQueue::Consume(size_t size)
+{
+ // Check parameters
+ if (size > m_size) {
+ Throw(Exception::OutOfData);
+ }
+
+ size_t bytesLeft = size;
+
+ // Consume data and/or remove buckets
+ while (bytesLeft > 0) {
+ // Get consume size
+ size_t count = std::min(bytesLeft, m_buckets.front()->left);
+
+ m_buckets.front()->ptr =
+ static_cast<const char *>(m_buckets.front()->ptr) + count;
+ m_buckets.front()->left -= count;
+ bytesLeft -= count;
+ m_size -= count;
+
+ if (m_buckets.front()->left == 0) {
+ DeleteBucket(m_buckets.front());
+ m_buckets.pop_front();
+ }
+ }
+}
+
+void BinaryQueue::Flatten(void *buffer, size_t bufferSize) const
+{
+ // Check parameters
+ if (bufferSize == 0) {
+ return;
+ }
+
+ if (bufferSize > m_size) {
+ Throw(Exception::OutOfData);
+ }
+
+ size_t bytesLeft = bufferSize;
+ void *ptr = buffer;
+ BucketList::const_iterator bucketIterator = m_buckets.begin();
+ Assert(m_buckets.end() != bucketIterator);
+
+ // Flatten data
+ while (bytesLeft > 0) {
+ // Get consume size
+ size_t count = std::min(bytesLeft, (*bucketIterator)->left);
+
+ // Copy data to user pointer
+ memcpy(ptr, (*bucketIterator)->ptr, count);
+
+ // Update flattened bytes count
+ bytesLeft -= count;
+ ptr = static_cast<char *>(ptr) + count;
+
+ // Take next bucket
+ ++bucketIterator;
+ }
+}
+
+void BinaryQueue::FlattenConsume(void *buffer, size_t bufferSize)
+{
+ // FIXME: Optimize
+ Flatten(buffer, bufferSize);
+ Consume(bufferSize);
+}
+
+void BinaryQueue::DeleteBucket(BinaryQueue::Bucket *bucket)
+{
+ delete bucket;
+}
+
+void BinaryQueue::BufferDeleterFree(const void* data,
+ size_t dataSize,
+ void* userParam)
+{
+ (void)dataSize;
+ (void)userParam;
+
+ // Default free deleter
+ free(const_cast<void *>(data));
+}
+
+BinaryQueue::Bucket::Bucket(const void* data,
+ size_t dataSize,
+ BufferDeleter dataDeleter,
+ void* userParam) :
+ buffer(data),
+ ptr(data),
+ size(dataSize),
+ left(dataSize),
+ deleter(dataDeleter),
+ param(userParam)
+{
+ Assert(data != NULL);
+ Assert(deleter != NULL);
+}
+
+BinaryQueue::Bucket::~Bucket()
+{
+ // Invoke deleter on bucket data
+ deleter(buffer, size, param);
+}
+
+BinaryQueue::BucketVisitor::~BucketVisitor()
+{}
+
+BinaryQueue::BucketVisitorCall::BucketVisitorCall(BucketVisitor *visitor) :
+ m_visitor(visitor)
+{}
+
+BinaryQueue::BucketVisitorCall::~BucketVisitorCall()
+{}
+
+void BinaryQueue::BucketVisitorCall::operator()(Bucket *bucket) const
+{
+ m_visitor->OnVisitBucket(bucket->ptr, bucket->left);
+}
+
+void BinaryQueue::VisitBuckets(BucketVisitor *visitor) const
+{
+ Assert(visitor != NULL);
+
+ // Visit all buckets
+ std::for_each(m_buckets.begin(), m_buckets.end(), BucketVisitorCall(visitor));
+}
+
+BinaryQueueAutoPtr BinaryQueue::Read(size_t size)
+{
+ // Simulate input stream
+ size_t available = std::min(size, m_size);
+
+ ScopedFree<void> bufferCopy(malloc(available));
+
+ if (!bufferCopy) {
+ throw std::bad_alloc();
+ }
+
+ BinaryQueueAutoPtr result(new BinaryQueue());
+
+ Flatten(bufferCopy.Get(), available);
+ result->AppendUnmanaged(
+ bufferCopy.Get(), available, &BufferDeleterFree, NULL);
+ bufferCopy.Release();
+ Consume(available);
+
+ return result;
+}
+
+size_t BinaryQueue::Write(const BinaryQueue &buffer, size_t bufferSize)
+{
+ // Simulate output stream
+ AppendCopyFrom(buffer);
+ return bufferSize;
+}
+} // namespace DPL
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file colors.cpp
+ * @author Lukasz Wrzosek (l.wrzosek@samsung.com)
+ * @version 1.0
+ * @brief Some constants with definition of colors for Console
+ * and html output
+ */
+#include <stddef.h>
+#include <dpl/colors.h>
+
+namespace DPL {
+namespace Colors {
+namespace Text {
+const char* BOLD_GREEN_BEGIN = "\033[1;32m";
+const char* BOLD_GREEN_END = "\033[m";
+const char* RED_BEGIN = "\033[0;31m";
+const char* RED_END = "\033[m";
+const char* PURPLE_BEGIN = "\033[0;35m";
+const char* PURPLE_END = "\033[m";
+const char* GREEN_BEGIN = "\033[0;32m";
+const char* GREEN_END = "\033[m";
+const char* CYAN_BEGIN = "\033[0;36m";
+const char* CYAN_END = "\033[m";
+const char* BOLD_RED_BEGIN = "\033[1;31m";
+const char* BOLD_RED_END = "\033[m";
+const char* BOLD_YELLOW_BEGIN = "\033[1;33m";
+const char* BOLD_YELLOW_END = "\033[m";
+const char* BOLD_GOLD_BEGIN = "\033[0;33m";
+const char* BOLD_GOLD_END = "\033[m";
+const char* BOLD_WHITE_BEGIN = "\033[1;37m";
+const char* BOLD_WHITE_END = "\033[m";
+} //namespace Text
+
+namespace Html {
+const char* BOLD_GREEN_BEGIN = "<font color=\"green\"><b>";
+const char* BOLD_GREEN_END = "</b></font>";
+const char* PURPLE_BEGIN = "<font color=\"purple\"><b>";
+const char* PURPLE_END = "</b></font>";
+const char* RED_BEGIN = "<font color=\"red\"><b>";
+const char* RED_END = "</b></font>";
+const char* GREEN_BEGIN = "<font color=\"green\">";
+const char* GREEN_END = "</font>";
+const char* CYAN_BEGIN = "<font color=\"cyan\">";
+const char* CYAN_END = "</font>";
+const char* BOLD_RED_BEGIN = "<font color=\"red\"><b>";
+const char* BOLD_RED_END = "</b></font>";
+const char* BOLD_YELLOW_BEGIN = "<font color=\"yellow\"><b>";
+const char* BOLD_YELLOW_END = "</b></font>";
+const char* BOLD_GOLD_BEGIN = "<font color=\"gold\"><b>";
+const char* BOLD_GOLD_END = "</b></font>";
+const char* BOLD_WHITE_BEGIN = "<font color=\"white\"><b>";
+const char* BOLD_WHITE_END = "</b></font>";
+} //namespace Html
+} //namespace Colors
+} //namespace DPL
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file dlog_log_provider.cpp
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of DLOG log provider
+ */
+#include <stddef.h>
+#include <dpl/log/dlog_log_provider.h>
+#include <cstring>
+#include <sstream>
+#include <dlog.h>
+
+namespace DPL {
+namespace Log {
+std::string DLOGLogProvider::FormatMessage(const char *message,
+ const char *filename,
+ int line,
+ const char *function)
+{
+ std::ostringstream val;
+
+ val << std::string("[") <<
+ LocateSourceFileName(filename) << std::string(":") << line <<
+ std::string("] ") << function << std::string("(): ") << message;
+
+ return val.str();
+}
+
+DLOGLogProvider::DLOGLogProvider()
+{}
+
+DLOGLogProvider::~DLOGLogProvider()
+{}
+
+void DLOGLogProvider::SetTag(const char *tag)
+{
+ m_tag.Reset(strdup(tag));
+}
+
+void DLOGLogProvider::Debug(const char *message,
+ const char *filename,
+ int line,
+ const char *function)
+{
+#ifdef SECURE_LOG
+ SECURE_LOG(LOG_DEBUG, m_tag.Get(), "%s",
+ FormatMessage(message, filename, line, function).c_str());
+#else
+ LOG(LOG_DEBUG, m_tag.Get(), "%s",
+ FormatMessage(message, filename, line, function).c_str());
+#endif
+}
+
+void DLOGLogProvider::Info(const char *message,
+ const char *filename,
+ int line,
+ const char *function)
+{
+#ifdef SECURE_LOG
+ SECURE_LOG(LOG_INFO, m_tag.Get(), "%s",
+ FormatMessage(message, filename, line, function).c_str());
+#else
+ LOG(LOG_INFO, m_tag.Get(), "%s",
+ FormatMessage(message, filename, line, function).c_str());
+#endif
+}
+
+void DLOGLogProvider::Warning(const char *message,
+ const char *filename,
+ int line,
+ const char *function)
+{
+#ifdef SECURE_LOG
+ SECURE_LOG(LOG_WARN, m_tag.Get(), "%s",
+ FormatMessage(message, filename, line, function).c_str());
+#else
+ LOG(LOG_WARN, m_tag.Get(), "%s",
+ FormatMessage(message, filename, line, function).c_str());
+#endif
+}
+
+void DLOGLogProvider::Error(const char *message,
+ const char *filename,
+ int line,
+ const char *function)
+{
+#ifdef SECURE_LOG
+ SECURE_LOG(LOG_ERROR, m_tag.Get(), "%s",
+ FormatMessage(message, filename, line, function).c_str());
+#else
+ LOG(LOG_ERROR, m_tag.Get(), "%s",
+ FormatMessage(message, filename, line, function).c_str());
+#endif
+}
+
+void DLOGLogProvider::Pedantic(const char *message,
+ const char *filename,
+ int line,
+ const char *function)
+{
+#ifdef SECURE_LOG
+ SECURE_LOG(LOG_DEBUG, "DPL", "%s", FormatMessage(message,
+ filename,
+ line,
+ function).c_str());
+#else
+ LOG(LOG_DEBUG, "DPL", "%s", FormatMessage(message,
+ filename,
+ line,
+ function).c_str());
+#endif
+}
+}
+} // namespace DPL
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file exception.cpp
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation of exception system
+ */
+#include <stddef.h>
+#include <dpl/exception.h>
+#include <dpl/log/log.h>
+#include <cstdio>
+
+namespace DPL {
+Exception* Exception::m_lastException = NULL;
+unsigned int Exception::m_exceptionCount = 0;
+void (*Exception::m_terminateHandler)() = NULL;
+
+void LogUnhandledException(const std::string &str)
+{
+ // Logging to console
+ printf("%s\n", str.c_str());
+
+ // Logging to dlog
+ LogPedantic(str);
+}
+
+void LogUnhandledException(const std::string &str,
+ const char *filename,
+ int line,
+ const char *function)
+{
+ // Logging to console
+ std::ostringstream msg;
+ msg << "\033[1;5;31m\n=== [" << filename << ":" << line << "] " <<
+ function << " ===\033[m";
+ msg << str;
+ printf("%s\n", msg.str().c_str());
+
+ // Logging to dlog
+ DPL::Log::LogSystemSingleton::Instance().Error(
+ str.c_str(), filename, line, function);
+}
+} // namespace DPL
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file log.cpp
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of log system
+ */
+#include <stddef.h>
+#include <string.h>
+
+#include <dpl/log/log.h>
+#include <dpl/singleton_impl.h>
+
+IMPLEMENT_SINGLETON(DPL::Log::LogSystem)
+
+namespace DPL {
+namespace Log {
+namespace // anonymous
+{
+const char *OLD_STYLE_LOGS_ENV_NAME = "DPL_USE_OLD_STYLE_LOGS";
+const char *OLD_STYLE_PEDANTIC_LOGS_ENV_NAME =
+ "DPL_USE_OLD_STYLE_PEDANTIC_LOGS";
+const char *OLD_STYLE_LOGS_MASK_ENV_NAME = "DPL_USE_OLD_STYLE_LOGS_MASK";
+const char *DPL_LOG_OFF = "DPL_LOG_OFF";
+} // namespace anonymous
+
+bool LogSystem::IsLoggingEnabled() const
+{
+ return m_isLoggingEnabled;
+}
+
+LogSystem::LogSystem() :
+ m_dlogProvider(NULL),
+ m_oldStyleProvider(NULL),
+ m_isLoggingEnabled(!getenv(DPL_LOG_OFF))
+{
+ bool oldStyleLogs = false;
+ bool oldStyleDebugLogs = true;
+ bool oldStyleInfoLogs = true;
+ bool oldStyleWarningLogs = true;
+ bool oldStyleErrorLogs = true;
+ bool oldStylePedanticLogs = false;
+
+ // Check environment settings about pedantic logs
+ const char *value = getenv(OLD_STYLE_LOGS_ENV_NAME);
+
+ if (value != NULL && !strcmp(value, "1")) {
+ oldStyleLogs = true;
+ }
+
+ value = getenv(OLD_STYLE_PEDANTIC_LOGS_ENV_NAME);
+
+ if (value != NULL && !strcmp(value, "1")) {
+ oldStylePedanticLogs = true;
+ }
+
+ value = getenv(OLD_STYLE_LOGS_MASK_ENV_NAME);
+
+ if (value != NULL) {
+ size_t len = strlen(value);
+
+ if (len >= 1) {
+ if (value[0] == '0') {
+ oldStyleDebugLogs = false;
+ } else if (value[0] == '1') {
+ oldStyleDebugLogs = true;
+ }
+ }
+
+ if (len >= 2) {
+ if (value[1] == '0') {
+ oldStyleInfoLogs = false;
+ } else if (value[1] == '1') {
+ oldStyleInfoLogs = true;
+ }
+ }
+
+ if (len >= 3) {
+ if (value[2] == '0') {
+ oldStyleWarningLogs = false;
+ } else if (value[2] == '1') {
+ oldStyleWarningLogs = true;
+ }
+ }
+
+ if (len >= 4) {
+ if (value[3] == '0') {
+ oldStyleErrorLogs = false;
+ } else if (value[3] == '1') {
+ oldStyleErrorLogs = true;
+ }
+ }
+ }
+
+ // Setup default DLOG and old style logging
+ if (oldStyleLogs) {
+ // Old style
+ m_oldStyleProvider = new OldStyleLogProvider(oldStyleDebugLogs,
+ oldStyleInfoLogs,
+ oldStyleWarningLogs,
+ oldStyleErrorLogs,
+ oldStylePedanticLogs);
+ AddProvider(m_oldStyleProvider);
+ } else {
+ // DLOG
+ m_dlogProvider = new DLOGLogProvider();
+ AddProvider(m_dlogProvider);
+ }
+}
+
+LogSystem::~LogSystem()
+{
+ // Delete all providers
+ for (AbstractLogProviderPtrList::iterator iterator = m_providers.begin();
+ iterator != m_providers.end();
+ ++iterator)
+ {
+ delete *iterator;
+ }
+
+ m_providers.clear();
+
+ // And even default providers
+ m_dlogProvider = NULL;
+ m_oldStyleProvider = NULL;
+}
+
+void LogSystem::SetTag(const char* tag)
+{
+ if (m_dlogProvider != NULL) {
+ m_dlogProvider->SetTag(tag);
+ }
+}
+
+void LogSystem::AddProvider(AbstractLogProvider *provider)
+{
+ m_providers.push_back(provider);
+}
+
+void LogSystem::RemoveProvider(AbstractLogProvider *provider)
+{
+ m_providers.remove(provider);
+}
+
+void LogSystem::Debug(const char *message,
+ const char *filename,
+ int line,
+ const char *function)
+{
+ for (AbstractLogProviderPtrList::iterator iterator = m_providers.begin();
+ iterator != m_providers.end();
+ ++iterator)
+ {
+ (*iterator)->Debug(message, filename, line, function);
+ }
+}
+
+void LogSystem::Info(const char *message,
+ const char *filename,
+ int line,
+ const char *function)
+{
+ for (AbstractLogProviderPtrList::iterator iterator = m_providers.begin();
+ iterator != m_providers.end();
+ ++iterator)
+ {
+ (*iterator)->Info(message, filename, line, function);
+ }
+}
+
+void LogSystem::Warning(const char *message,
+ const char *filename,
+ int line,
+ const char *function)
+{
+ for (AbstractLogProviderPtrList::iterator iterator = m_providers.begin();
+ iterator != m_providers.end();
+ ++iterator)
+ {
+ (*iterator)->Warning(message, filename, line, function);
+ }
+}
+
+void LogSystem::Error(const char *message,
+ const char *filename,
+ int line,
+ const char *function)
+{
+ for (AbstractLogProviderPtrList::iterator iterator = m_providers.begin();
+ iterator != m_providers.end();
+ ++iterator)
+ {
+ (*iterator)->Error(message, filename, line, function);
+ }
+}
+
+void LogSystem::Pedantic(const char *message,
+ const char *filename,
+ int line,
+ const char *function)
+{
+ for (AbstractLogProviderPtrList::iterator iterator = m_providers.begin();
+ iterator != m_providers.end();
+ ++iterator)
+ {
+ (*iterator)->Pedantic(message, filename, line, function);
+ }
+}
+}
+} // namespace DPL
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file noncopyable.cpp
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of noncopyable
+ */
+#include <stddef.h>
+#include <dpl/noncopyable.h>
+
+namespace DPL {
+Noncopyable::Noncopyable()
+{}
+
+Noncopyable::~Noncopyable()
+{}
+} // namespace DPL
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file old_style_log_provider.cpp
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of old style log provider
+ */
+#include <stddef.h>
+#include <dpl/log/old_style_log_provider.h>
+#include <dpl/colors.h>
+#include <cstdio>
+#include <cstring>
+#include <sstream>
+#include <sys/time.h>
+#include <unistd.h>
+
+namespace DPL {
+namespace Log {
+namespace // anonymous
+{
+using namespace DPL::Colors::Text;
+const char *DEBUG_BEGIN = GREEN_BEGIN;
+const char *DEBUG_END = GREEN_END;
+const char *INFO_BEGIN = CYAN_BEGIN;
+const char *INFO_END = CYAN_END;
+const char *ERROR_BEGIN = RED_BEGIN;
+const char *ERROR_END = RED_END;
+const char *WARNING_BEGIN = BOLD_GOLD_BEGIN;
+const char *WARNING_END = BOLD_GOLD_END;
+const char *PEDANTIC_BEGIN = PURPLE_BEGIN;
+const char *PEDANTIC_END = PURPLE_END;
+
+std::string GetFormattedTime()
+{
+ timeval tv;
+ tm localNowTime;
+
+ gettimeofday(&tv, NULL);
+ localtime_r(&tv.tv_sec, &localNowTime);
+
+ char format[64];
+ snprintf(format,
+ sizeof(format),
+ "%02i:%02i:%02i.%03i",
+ localNowTime.tm_hour,
+ localNowTime.tm_min,
+ localNowTime.tm_sec,
+ static_cast<int>(tv.tv_usec / 1000));
+ return format;
+}
+} // namespace anonymous
+
+std::string OldStyleLogProvider::FormatMessage(const char *message,
+ const char *filename,
+ int line,
+ const char *function)
+{
+ std::ostringstream val;
+
+ val << std::string("[") << GetFormattedTime() << std::string("] [") <<
+ static_cast<unsigned long>(pthread_self()) << "/" <<
+ static_cast<int>(getpid()) << std::string("] [") <<
+ LocateSourceFileName(filename) << std::string(":") << line <<
+ std::string("] ") << function << std::string("(): ") << message;
+
+ return val.str();
+}
+
+OldStyleLogProvider::OldStyleLogProvider(bool showDebug,
+ bool showInfo,
+ bool showWarning,
+ bool showError,
+ bool showPedantic) :
+ m_showDebug(showDebug),
+ m_showInfo(showInfo),
+ m_showWarning(showWarning),
+ m_showError(showError),
+ m_showPedantic(showPedantic),
+ m_printStdErr(false)
+{}
+
+OldStyleLogProvider::OldStyleLogProvider(bool showDebug,
+ bool showInfo,
+ bool showWarning,
+ bool showError,
+ bool showPedantic,
+ bool printStdErr) :
+ m_showDebug(showDebug),
+ m_showInfo(showInfo),
+ m_showWarning(showWarning),
+ m_showError(showError),
+ m_showPedantic(showPedantic),
+ m_printStdErr(printStdErr)
+{}
+
+void OldStyleLogProvider::Debug(const char *message,
+ const char *filename,
+ int line,
+ const char *function)
+{
+ if (m_showDebug) {
+ if (m_printStdErr) {
+ fprintf(stderr, "%s%s%s\n", DEBUG_BEGIN,
+ FormatMessage(message, filename, line,
+ function).c_str(), DEBUG_END);
+ } else {
+ fprintf(stdout, "%s%s%s\n", DEBUG_BEGIN,
+ FormatMessage(message, filename, line,
+ function).c_str(), DEBUG_END);
+ }
+ }
+}
+
+void OldStyleLogProvider::Info(const char *message,
+ const char *filename,
+ int line,
+ const char *function)
+{
+ if (m_showInfo) {
+ if (m_printStdErr) {
+ fprintf(stderr, "%s%s%s\n", INFO_BEGIN,
+ FormatMessage(message, filename, line,
+ function).c_str(), INFO_END);
+ } else {
+ fprintf(stdout, "%s%s%s\n", INFO_BEGIN,
+ FormatMessage(message, filename, line,
+ function).c_str(), INFO_END);
+ }
+ }
+}
+
+void OldStyleLogProvider::Warning(const char *message,
+ const char *filename,
+ int line,
+ const char *function)
+{
+ if (m_showWarning) {
+ if (m_printStdErr) {
+ fprintf(stderr, "%s%s%s\n", WARNING_BEGIN,
+ FormatMessage(message, filename, line,
+ function).c_str(), WARNING_END);
+ } else {
+ fprintf(stdout, "%s%s%s\n", WARNING_BEGIN,
+ FormatMessage(message, filename, line,
+ function).c_str(), WARNING_END);
+ }
+ }
+}
+
+void OldStyleLogProvider::Error(const char *message,
+ const char *filename,
+ int line,
+ const char *function)
+{
+ if (m_showError) {
+ if (m_printStdErr) {
+ fprintf(stderr, "%s%s%s\n", ERROR_BEGIN,
+ FormatMessage(message, filename, line,
+ function).c_str(), ERROR_END);
+ } else {
+ fprintf(stdout, "%s%s%s\n", ERROR_BEGIN,
+ FormatMessage(message, filename, line,
+ function).c_str(), ERROR_END);
+ }
+ }
+}
+
+void OldStyleLogProvider::Pedantic(const char *message,
+ const char *filename,
+ int line,
+ const char *function)
+{
+ if (m_showPedantic) {
+ if (m_printStdErr) {
+ fprintf(stderr, "%s%s%s\n", PEDANTIC_BEGIN,
+ FormatMessage(message, filename, line,
+ function).c_str(), PEDANTIC_END);
+ } else {
+ fprintf(stdout, "%s%s%s\n", PEDANTIC_BEGIN,
+ FormatMessage(message, filename, line,
+ function).c_str(), PEDANTIC_END);
+ }
+ }
+}
+}
+} // namespace DPL
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file singleton.cpp
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of singleton
+ */
+#include <stddef.h>
+#include <dpl/singleton.h>
+
+//
+// Note:
+//
+// The file here is left blank to enable precompilation
+// of templates in corresponding header file.
+// Do not remove this file.
+//
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file test_results_collector.h
+ * @author Lukasz Wrzosek (l.wrzosek@samsung.com)
+ * @version 1.0
+ * @brief Implementation file some concrete TestResulstsCollector
+ */
+#include <cstddef>
+#include <dpl/test/test_results_collector.h>
+#include <dpl/availability.h>
+#include <dpl/colors.h>
+#include <dpl/assert.h>
+#include <dpl/scoped_fclose.h>
+#include <dpl/exception.h>
+
+#include <string>
+#include <string.h>
+#include <errno.h>
+#include <cstdio>
+#include <fstream>
+#include <sstream>
+#include <cstdlib>
+
+#define GREEN_RESULT_OK "[%s%s%s]\n", BOLD_GREEN_BEGIN, " OK ", \
+ BOLD_GREEN_END
+#define GREEN_RESULT_OK_TIME "[%s%s%s] [elapsed: %0.3fms]\n", BOLD_GREEN_BEGIN, \
+ " OK ", BOLD_GREEN_END
+#define GREEN_RESULT_OK_TIME_MAX(elapsed, max) \
+ "[%s%s%s] %s[elapsed: %0.3fms, expected < %0.3fms]%s\n", BOLD_GREEN_BEGIN, \
+ " OK ", BOLD_GREEN_END, BOLD_GREEN_BEGIN, elapsed, max, BOLD_GREEN_END
+#define GREEN_RESULT_OK_TIME_TOO_LONG(elapsed, max) \
+ "[%s%s%s] %s[elapsed: %0.3fms, expected < %0.3fms]%s\n", BOLD_GREEN_BEGIN, \
+ " OK ", BOLD_GREEN_END, BOLD_RED_BEGIN, elapsed, max, BOLD_RED_END
+
+namespace { /* anonymous namespace */
+// Get duration as a fraction of millisecond (max precision is 1 microsecond)
+double get_milliseconds (const std::chrono::system_clock::duration& performanceTime)
+{
+ return (static_cast<double>(std::chrono::duration_cast<std::chrono::microseconds>
+ (performanceTime).count()))/1000.0;
+}
+} /* anonymous namespace */
+
+namespace DPL {
+namespace Test {
+namespace {
+const char *DEFAULT_HTML_FILE_NAME = "index.html";
+const char *DEFAULT_TAP_FILE_NAME = "results.tap";
+const char *DEFAULT_XML_FILE_NAME = "results.xml";
+
+bool ParseCollectorFileArg(const std::string &arg, std::string &filename)
+{
+ const std::string argname = "--file=";
+ if (arg.find(argname) == 0 ) {
+ filename = arg.substr(argname.size());
+ return true;
+ }
+ return false;
+}
+
+class Statistic
+{
+ public:
+ Statistic() :
+ m_failed(0),
+ m_ignored(0),
+ m_passed(0),
+ m_count(0)
+ {}
+
+ void AddTest(TestResultsCollectorBase::FailStatus::Type type)
+ {
+ ++m_count;
+ switch (type) {
+ case TestResultsCollectorBase::FailStatus::INTERNAL:
+ case TestResultsCollectorBase::FailStatus::FAILED: ++m_failed;
+ break;
+ case TestResultsCollectorBase::FailStatus::IGNORED: ++m_ignored;
+ break;
+ case TestResultsCollectorBase::FailStatus::NONE: ++m_passed;
+ break;
+ default:
+ Assert(false && "Bad FailStatus");
+ }
+ }
+
+ std::size_t GetTotal() const
+ {
+ return m_count;
+ }
+ std::size_t GetPassed() const
+ {
+ return m_passed;
+ }
+ std::size_t GetSuccesed() const
+ {
+ return m_passed;
+ }
+ std::size_t GetFailed() const
+ {
+ return m_failed;
+ }
+ std::size_t GetIgnored() const
+ {
+ return m_ignored;
+ }
+ float GetPassedOrIgnoredPercend() const
+ {
+ float passIgnoredPercent =
+ 100.0f * (static_cast<float>(m_passed)
+ + static_cast<float>(m_ignored))
+ / static_cast<float>(m_count);
+ return passIgnoredPercent;
+ }
+
+ private:
+ std::size_t m_failed;
+ std::size_t m_ignored;
+ std::size_t m_passed;
+ std::size_t m_count;
+};
+
+class ConsoleCollector :
+ public TestResultsCollectorBase
+{
+ public:
+ static TestResultsCollectorBase* Constructor();
+
+ private:
+ ConsoleCollector() {}
+
+ virtual void CollectCurrentTestGroupName(const std::string& name)
+ {
+ printf("Starting group %s\n", name.c_str());
+ m_currentGroup = name;
+ }
+
+ virtual void Finish()
+ {
+ using namespace DPL::Colors::Text;
+
+ // Show result
+ for (auto &group : m_groupsStats) {
+ PrintStats(group.first, group.second);
+ }
+ PrintStats("All tests together", m_stats);
+ }
+
+ virtual void CollectResult(const std::string& id,
+ const std::string& /*description*/,
+ const FailStatus::Type status = FailStatus::NONE,
+ const std::string& reason = "",
+ const bool& isPerformanceTest = true,
+ const std::chrono::system_clock::duration& performanceTime = std::chrono::microseconds::zero(),
+ const std::chrono::system_clock::duration& performanceMaxTime = std::chrono::microseconds::zero())
+ {
+ using namespace DPL::Colors::Text;
+ std::string tmp = "'" + id + "' ...";
+
+ printf("Running test case %-60s", tmp.c_str());
+ switch (status) {
+ case TestResultsCollectorBase::FailStatus::NONE:
+ if (isPerformanceTest) {
+ if (performanceMaxTime <= std::chrono::microseconds::zero()) {
+ printf(GREEN_RESULT_OK_TIME,
+ get_milliseconds(performanceTime));
+ break;
+ }
+ else {
+ if (performanceTime > performanceMaxTime)
+ printf(GREEN_RESULT_OK_TIME_TOO_LONG(
+ get_milliseconds(performanceTime),
+ get_milliseconds(performanceMaxTime)));
+ else
+ printf(GREEN_RESULT_OK_TIME_MAX(
+ get_milliseconds(performanceTime),
+ get_milliseconds(performanceMaxTime)));
+ break;
+ }
+ }
+ printf(GREEN_RESULT_OK);
+ break;
+ case TestResultsCollectorBase::FailStatus::FAILED:
+ PrintfErrorMessage(" FAILED ", reason, true);
+ break;
+ case TestResultsCollectorBase::FailStatus::IGNORED:
+ PrintfIgnoredMessage("Ignored ", reason, true);
+ break;
+ case TestResultsCollectorBase::FailStatus::INTERNAL:
+ PrintfErrorMessage("INTERNAL", reason, true);
+ break;
+ default:
+ Assert(false && "Bad status");
+ }
+ m_stats.AddTest(status);
+ m_groupsStats[m_currentGroup].AddTest(status);
+ }
+
+ void PrintfErrorMessage(const char* type,
+ const std::string& message,
+ bool verbosity)
+ {
+ using namespace DPL::Colors::Text;
+ if (verbosity) {
+ printf("[%s%s%s] %s%s%s\n",
+ BOLD_RED_BEGIN,
+ type,
+ BOLD_RED_END,
+ BOLD_YELLOW_BEGIN,
+ message.c_str(),
+ BOLD_YELLOW_END);
+ } else {
+ printf("[%s%s%s]\n",
+ BOLD_RED_BEGIN,
+ type,
+ BOLD_RED_END);
+ }
+ }
+
+ void PrintfIgnoredMessage(const char* type,
+ const std::string& message,
+ bool verbosity)
+ {
+ using namespace DPL::Colors::Text;
+ if (verbosity) {
+ printf("[%s%s%s] %s%s%s\n",
+ CYAN_BEGIN,
+ type,
+ CYAN_END,
+ BOLD_GOLD_BEGIN,
+ message.c_str(),
+ BOLD_GOLD_END);
+ } else {
+ printf("[%s%s%s]\n",
+ CYAN_BEGIN,
+ type,
+ CYAN_END);
+ }
+ }
+
+ void PrintStats(const std::string& title, const Statistic& stats)
+ {
+ using namespace DPL::Colors::Text;
+ printf("\n%sResults [%s]: %s\n", BOLD_GREEN_BEGIN,
+ title.c_str(), BOLD_GREEN_END);
+ printf("%s%s%3zu%s\n",
+ CYAN_BEGIN,
+ "Total tests: ",
+ stats.GetTotal(),
+ CYAN_END);
+ printf(" %s%s%3zu%s\n",
+ CYAN_BEGIN,
+ "Succeeded: ",
+ stats.GetPassed(),
+ CYAN_END);
+ printf(" %s%s%3zu%s\n",
+ CYAN_BEGIN,
+ "Failed: ",
+ stats.GetFailed(),
+ CYAN_END);
+ printf(" %s%s%3zu%s\n",
+ CYAN_BEGIN,
+ "Ignored: ",
+ stats.GetIgnored(),
+ CYAN_END);
+ }
+
+ Statistic m_stats;
+ std::map<std::string, Statistic> m_groupsStats;
+ std::string m_currentGroup;
+};
+
+TestResultsCollectorBase* ConsoleCollector::Constructor()
+{
+ return new ConsoleCollector();
+}
+
+class HtmlCollector :
+ public TestResultsCollectorBase
+{
+ public:
+ static TestResultsCollectorBase* Constructor();
+
+ private:
+ HtmlCollector() : m_filename(DEFAULT_HTML_FILE_NAME) {}
+
+ virtual void CollectCurrentTestGroupName(const std::string& name)
+ {
+ fprintf(m_fp.Get(), "<b>Starting group %s", name.c_str());
+ m_currentGroup = name;
+ }
+
+ virtual bool Configure()
+ {
+ m_fp.Reset(fopen(m_filename.c_str(), "w"));
+ if (!m_fp) {
+ LogPedantic("Could not open file " << m_filename << " for writing");
+ return false;
+ }
+ return true;
+ }
+ virtual std::string CollectorSpecificHelp() const
+ {
+ return "--file=<filename> - name of file for output\n"
+ " default - index.html\n";
+ }
+
+ virtual void Start()
+ {
+ Assert(!!m_fp && "File handle must not be null");
+ fprintf(m_fp.Get(),
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0"
+ "Transitional//EN\" "
+ "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\""
+ ">\n");
+ fprintf(m_fp.Get(),
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\" "
+ "lang=\"en\" dir=\"ltr\">\n");
+ fprintf(m_fp.Get(), "<body style=\"background-color: black;\">\n");
+ fprintf(m_fp.Get(), "<pre>\n");
+ fprintf(m_fp.Get(), "<font color=\"white\">\n");
+ }
+
+ virtual void Finish()
+ {
+ using namespace DPL::Colors::Html;
+ // Show result
+ for (auto &group : m_groupsStats) {
+ PrintStats(group.first, group.second);
+ }
+ PrintStats("All tests together", m_stats);
+ fprintf(m_fp.Get(), "</font>\n");
+ fprintf(m_fp.Get(), "</pre>\n");
+ fprintf(m_fp.Get(), "</body>\n");
+ fprintf(m_fp.Get(), "</html>\n");
+ }
+
+ virtual bool ParseCollectorSpecificArg(const std::string& arg)
+ {
+ return ParseCollectorFileArg(arg, m_filename);
+ }
+
+ virtual void CollectResult(const std::string& id,
+ const std::string& /*description*/,
+ const FailStatus::Type status = FailStatus::NONE,
+ const std::string& reason = "",
+ const bool& isPerformanceTest = false,
+ const std::chrono::system_clock::duration& performanceTime = std::chrono::microseconds::zero(),
+ const std::chrono::system_clock::duration& performanceMaxTime = std::chrono::microseconds::zero())
+ {
+ using namespace DPL::Colors::Html;
+ std::string tmp = "'" + id + "' ...";
+
+ fprintf(m_fp.Get(), "Running test case %-100s", tmp.c_str());
+ switch (status) {
+ case TestResultsCollectorBase::FailStatus::NONE:
+ if (isPerformanceTest) {
+ if (performanceMaxTime <= std::chrono::microseconds::zero()) {
+ fprintf(m_fp.Get(), GREEN_RESULT_OK_TIME,
+ get_milliseconds(performanceTime));
+ break;
+ } else {
+ if (performanceTime > performanceMaxTime)
+ fprintf(m_fp.Get(), GREEN_RESULT_OK_TIME_TOO_LONG(
+ get_milliseconds(performanceTime),
+ get_milliseconds(performanceMaxTime)));
+ else
+ fprintf(m_fp.Get(), GREEN_RESULT_OK_TIME_MAX(
+ get_milliseconds(performanceTime),
+ get_milliseconds(performanceMaxTime)));
+ break;
+ }
+ }
+ fprintf(m_fp.Get(), GREEN_RESULT_OK);
+ break;
+ case TestResultsCollectorBase::FailStatus::FAILED:
+ PrintfErrorMessage(" FAILED ", reason, true);
+ break;
+ case TestResultsCollectorBase::FailStatus::IGNORED:
+ PrintfIgnoredMessage("Ignored ", reason, true);
+ break;
+ case TestResultsCollectorBase::FailStatus::INTERNAL:
+ PrintfErrorMessage("INTERNAL", reason, true);
+ break;
+ default:
+ Assert(false && "Bad status");
+ }
+ m_groupsStats[m_currentGroup].AddTest(status);
+ m_stats.AddTest(status);
+ }
+
+ void PrintfErrorMessage(const char* type,
+ const std::string& message,
+ bool verbosity)
+ {
+ using namespace DPL::Colors::Html;
+ if (verbosity) {
+ fprintf(m_fp.Get(),
+ "[%s%s%s] %s%s%s\n",
+ BOLD_RED_BEGIN,
+ type,
+ BOLD_RED_END,
+ BOLD_YELLOW_BEGIN,
+ message.c_str(),
+ BOLD_YELLOW_END);
+ } else {
+ fprintf(m_fp.Get(),
+ "[%s%s%s]\n",
+ BOLD_RED_BEGIN,
+ type,
+ BOLD_RED_END);
+ }
+ }
+
+ void PrintfIgnoredMessage(const char* type,
+ const std::string& message,
+ bool verbosity)
+ {
+ using namespace DPL::Colors::Html;
+
+ if (verbosity) {
+ fprintf(m_fp.Get(),
+ "[%s%s%s] %s%s%s\n",
+ CYAN_BEGIN,
+ type,
+ CYAN_END,
+ BOLD_GOLD_BEGIN,
+ message.c_str(),
+ BOLD_GOLD_END);
+ } else {
+ fprintf(m_fp.Get(),
+ "[%s%s%s]\n",
+ CYAN_BEGIN,
+ type,
+ CYAN_END);
+ }
+ }
+
+ void PrintStats(const std::string& name, const Statistic& stats)
+ {
+ using namespace DPL::Colors::Html;
+ fprintf(
+ m_fp.Get(), "\n%sResults [%s]:%s\n", BOLD_GREEN_BEGIN,
+ name.c_str(), BOLD_GREEN_END);
+ fprintf(
+ m_fp.Get(), "%s%s%3zu%s\n", CYAN_BEGIN,
+ "Total tests: ", stats.GetTotal(), CYAN_END);
+ fprintf(
+ m_fp.Get(), " %s%s%3zu%s\n", CYAN_BEGIN,
+ "Succeeded: ", stats.GetPassed(), CYAN_END);
+ fprintf(
+ m_fp.Get(), " %s%s%3zu%s\n", CYAN_BEGIN,
+ "Failed: ", stats.GetFailed(), CYAN_END);
+ fprintf(
+ m_fp.Get(), " %s%s%3zu%s\n", CYAN_BEGIN,
+ "Ignored: ", stats.GetIgnored(), CYAN_END);
+ }
+
+ std::string m_filename;
+ ScopedFClose m_fp;
+ Statistic m_stats;
+ std::string m_currentGroup;
+ std::map<std::string, Statistic> m_groupsStats;
+};
+
+TestResultsCollectorBase* HtmlCollector::Constructor()
+{
+ return new HtmlCollector();
+}
+
+class XmlCollector :
+ public TestResultsCollectorBase
+{
+ public:
+ static TestResultsCollectorBase* Constructor();
+
+ private:
+ XmlCollector() : m_filename(DEFAULT_XML_FILE_NAME) {}
+
+ virtual void CollectCurrentTestGroupName(const std::string& name)
+ {
+ std::size_t pos = GetCurrentGroupPosition();
+ if (std::string::npos != pos) {
+ GroupFinish(pos);
+ FlushOutput();
+ m_stats = Statistic();
+ }
+
+ pos = m_outputBuffer.find("</testsuites>");
+ if (std::string::npos == pos) {
+ ThrowMsg(DPL::Exception, "Could not find test suites closing tag");
+ }
+ GroupStart(pos, name);
+ }
+
+ void GroupStart(const std::size_t pos, const std::string& name)
+ {
+ std::stringstream groupHeader;
+ groupHeader << "\n\t<testsuite";
+ groupHeader << " name=\"" << EscapeSpecialCharacters(name) << "\"";
+ groupHeader << R"( tests="1")"; // include SegFault
+ groupHeader << R"( failures="1")"; // include SegFault
+ groupHeader << R"( skipped="0")";
+ groupHeader << ">";
+
+ groupHeader << "\n\t\t<testcase name=\"unknown\" status=\"FAILED\">";
+ groupHeader <<
+ "\n\t\t\t<failure type=\"FAILED\" message=\"segmentation fault\"/>";
+ groupHeader << "\n\t\t</testcase>";
+
+ groupHeader << "\n\t</testsuite>";
+
+ m_outputBuffer.insert(pos - 1, groupHeader.str());
+ }
+
+ virtual bool Configure()
+ {
+ m_fp.Reset(fopen(m_filename.c_str(), "w"));
+ if (!m_fp) {
+ LogPedantic("Could not open file " << m_filename << " for writing");
+ return false;
+ }
+ return true;
+ }
+
+ virtual std::string CollectorSpecificHelp() const
+ {
+ return "--file=<filename> - name of file for output\n"
+ " default - results.xml\n";
+ }
+
+ virtual void Start()
+ {
+ Assert(!!m_fp && "File handle must not be null");
+ m_outputBuffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
+ m_outputBuffer.append("<testsuites>\n</testsuites>");
+ FlushOutput();
+ }
+
+ virtual void Finish()
+ {
+ std::size_t pos = GetCurrentGroupPosition();
+ if (std::string::npos != pos) {
+ GroupFinish(pos);
+ FlushOutput();
+ }
+ }
+
+ virtual bool ParseCollectorSpecificArg(const std::string& arg)
+ {
+ return ParseCollectorFileArg(arg, m_filename);
+ }
+
+ virtual void CollectResult(const std::string& id,
+ const std::string& /*description*/,
+ const FailStatus::Type status = FailStatus::NONE,
+ const std::string& reason = "",
+ const bool& isPerformanceTest = false,
+ const std::chrono::system_clock::duration& performanceTime = std::chrono::microseconds::zero(),
+ const std::chrono::system_clock::duration& performanceMaxTime = std::chrono::microseconds::zero())
+ {
+ m_resultBuffer.erase();
+ m_resultBuffer.append("\t\t<testcase name=\"");
+ m_resultBuffer.append(EscapeSpecialCharacters(id));
+ m_resultBuffer.append("\"");
+ switch (status) {
+ case TestResultsCollectorBase::FailStatus::NONE:
+ if (isPerformanceTest) {
+ if (performanceMaxTime <= std::chrono::microseconds::zero()) {
+ m_resultBuffer.append(" status=\"OK\" time=\"");
+ std::ostringstream ostr;
+ ostr << performanceTime.count();
+ m_resultBuffer.append(ostr.str());
+ m_resultBuffer.append("\"/>\n");
+ break;
+ } else {
+ m_resultBuffer.append(" status=\"OK\" time=\"");
+ std::ostringstream ostr;
+ ostr << performanceTime.count();
+ m_resultBuffer.append(ostr.str());
+ m_resultBuffer.append("\" time_expected=\"");
+ ostr.str("");
+ ostr << performanceMaxTime.count();
+ m_resultBuffer.append(ostr.str());
+ m_resultBuffer.append("\"/>\n");
+ break;
+ }
+ }
+ m_resultBuffer.append(" status=\"OK\"/>\n");
+ break;
+ case TestResultsCollectorBase::FailStatus::FAILED:
+ m_resultBuffer.append(" status=\"FAILED\">\n");
+ PrintfErrorMessage("FAILED", EscapeSpecialCharacters(reason), true);
+ m_resultBuffer.append("\t\t</testcase>\n");
+ break;
+ case TestResultsCollectorBase::FailStatus::IGNORED:
+ m_resultBuffer.append(" status=\"Ignored\">\n");
+ PrintfIgnoredMessage("Ignored", EscapeSpecialCharacters(
+ reason), true);
+ m_resultBuffer.append("\t\t</testcase>\n");
+ break;
+ case TestResultsCollectorBase::FailStatus::INTERNAL:
+ m_resultBuffer.append(" status=\"FAILED\">\n");
+ PrintfErrorMessage("INTERNAL", EscapeSpecialCharacters(
+ reason), true);
+ m_resultBuffer.append("\t\t</testcase>");
+ break;
+ default:
+ Assert(false && "Bad status");
+ }
+ std::size_t group_pos = GetCurrentGroupPosition();
+ if (std::string::npos == group_pos) {
+ ThrowMsg(DPL::Exception, "No current group set");
+ }
+
+ std::size_t last_case_pos = m_outputBuffer.find(
+ "<testcase name=\"unknown\"",
+ group_pos);
+ if (std::string::npos == last_case_pos) {
+ ThrowMsg(DPL::Exception, "Could not find SegFault test case");
+ }
+ m_outputBuffer.insert(last_case_pos - 2, m_resultBuffer);
+
+ m_stats.AddTest(status);
+
+ UpdateGroupHeader(group_pos,
+ m_stats.GetTotal() + 1, // include SegFault
+ m_stats.GetFailed() + 1, // include SegFault
+ m_stats.GetIgnored());
+ FlushOutput();
+ }
+
+ std::size_t GetCurrentGroupPosition() const
+ {
+ return m_outputBuffer.rfind("<testsuite ");
+ }
+
+ void UpdateGroupHeader(const std::size_t groupPosition,
+ const unsigned int tests,
+ const unsigned int failures,
+ const unsigned int skipped)
+ {
+ UpdateElementAttribute(groupPosition, "tests", UIntToString(tests));
+ UpdateElementAttribute(groupPosition, "failures", UIntToString(failures));
+ UpdateElementAttribute(groupPosition, "skipped", UIntToString(skipped));
+ }
+
+ void UpdateElementAttribute(const std::size_t elementPosition,
+ const std::string& name,
+ const std::string& value)
+ {
+ std::string pattern = name + "=\"";
+
+ std::size_t start = m_outputBuffer.find(pattern, elementPosition);
+ if (std::string::npos == start) {
+ ThrowMsg(DPL::Exception,
+ "Could not find attribute " << name << " beginning");
+ }
+
+ std::size_t end = m_outputBuffer.find("\"", start + pattern.length());
+ if (std::string::npos == end) {
+ ThrowMsg(DPL::Exception,
+ "Could not find attribute " << name << " end");
+ }
+
+ m_outputBuffer.replace(start + pattern.length(),
+ end - start - pattern.length(),
+ value);
+ }
+
+ std::string UIntToString(const unsigned int value)
+ {
+ std::stringstream result;
+ result << value;
+ return result.str();
+ }
+
+ void GroupFinish(const std::size_t groupPosition)
+ {
+ std::size_t segFaultStart =
+ m_outputBuffer.find("<testcase name=\"unknown\"", groupPosition);
+ if (std::string::npos == segFaultStart) {
+ ThrowMsg(DPL::Exception,
+ "Could not find SegFault test case start position");
+ }
+ segFaultStart -= 2; // to erase tabs
+
+ std::string closeTag = "</testcase>";
+ std::size_t segFaultEnd = m_outputBuffer.find(closeTag, segFaultStart);
+ if (std::string::npos == segFaultEnd) {
+ ThrowMsg(DPL::Exception,
+ "Could not find SegFault test case end position");
+ }
+ segFaultEnd += closeTag.length() + 1; // to erase new line
+
+ m_outputBuffer.erase(segFaultStart, segFaultEnd - segFaultStart);
+
+ UpdateGroupHeader(groupPosition,
+ m_stats.GetTotal(),
+ m_stats.GetFailed(),
+ m_stats.GetIgnored());
+ }
+
+ void FlushOutput()
+ {
+ int fd = fileno(m_fp.Get());
+ if (-1 == fd) {
+ const char* errStr = strerror(errno);
+ ThrowMsg(DPL::Exception, errStr);
+ }
+
+ if (-1 == TEMP_FAILURE_RETRY(ftruncate(fd, 0L))) {
+ const char* errStr = strerror(errno);
+ ThrowMsg(DPL::Exception, errStr);
+ }
+
+ if (-1 == TEMP_FAILURE_RETRY(fseek(m_fp.Get(), 0L, SEEK_SET))) {
+ const char* errStr = strerror(errno);
+ ThrowMsg(DPL::Exception, errStr);
+ }
+
+ if (m_outputBuffer.size() !=
+ fwrite(m_outputBuffer.c_str(), 1, m_outputBuffer.size(),
+ m_fp.Get()))
+ {
+ const char* errStr = strerror(errno);
+ ThrowMsg(DPL::Exception, errStr);
+ }
+
+ if (-1 == TEMP_FAILURE_RETRY(fflush(m_fp.Get()))) {
+ const char* errStr = strerror(errno);
+ ThrowMsg(DPL::Exception, errStr);
+ }
+ }
+
+ void PrintfErrorMessage(const char* type,
+ const std::string& message,
+ bool verbosity)
+ {
+ if (verbosity) {
+ m_resultBuffer.append("\t\t\t<failure type=\"");
+ m_resultBuffer.append(EscapeSpecialCharacters(type));
+ m_resultBuffer.append("\" message=\"");
+ m_resultBuffer.append(EscapeSpecialCharacters(message));
+ m_resultBuffer.append("\"/>\n");
+ } else {
+ m_resultBuffer.append("\t\t\t<failure type=\"");
+ m_resultBuffer.append(EscapeSpecialCharacters(type));
+ m_resultBuffer.append("\"/>\n");
+ }
+ }
+
+ void PrintfIgnoredMessage(const char* type,
+ const std::string& message,
+ bool verbosity)
+ {
+ if (verbosity) {
+ m_resultBuffer.append("\t\t\t<skipped type=\"");
+ m_resultBuffer.append(EscapeSpecialCharacters(type));
+ m_resultBuffer.append("\" message=\"");
+ m_resultBuffer.append(EscapeSpecialCharacters(message));
+ m_resultBuffer.append("\"/>\n");
+ } else {
+ m_resultBuffer.append("\t\t\t<skipped type=\"");
+ m_resultBuffer.append(EscapeSpecialCharacters(type));
+ m_resultBuffer.append("\"/>\n");
+ }
+ }
+
+ std::string EscapeSpecialCharacters(std::string s)
+ {
+ for (unsigned int i = 0; i < s.size();) {
+ switch (s[i]) {
+ case '"':
+ s.erase(i, 1);
+ s.insert(i, """);
+ i += 6;
+ break;
+
+ case '&':
+ s.erase(i, 1);
+ s.insert(i, "&");
+ i += 5;
+ break;
+
+ case '<':
+ s.erase(i, 1);
+ s.insert(i, "<");
+ i += 4;
+ break;
+
+ case '>':
+ s.erase(i, 1);
+ s.insert(i, ">");
+ i += 4;
+ break;
+
+ case '\'':
+ s.erase(i, 1);
+ s.insert(i, "'");
+ i += 5;
+ break;
+ default:
+ ++i;
+ break;
+ }
+ }
+ return s;
+ }
+
+ std::string m_filename;
+ ScopedFClose m_fp;
+ Statistic m_stats;
+ std::string m_outputBuffer;
+ std::string m_resultBuffer;
+};
+
+TestResultsCollectorBase* XmlCollector::Constructor()
+{
+ return new XmlCollector();
+}
+
+class CSVCollector :
+ public TestResultsCollectorBase
+{
+ public:
+ static TestResultsCollectorBase* Constructor();
+
+ private:
+ CSVCollector() {}
+
+ virtual void Start()
+ {
+ printf("GROUP;ID;RESULT;REASON;ELAPSED [s];EXPECTED [s]\n");
+ }
+
+ virtual void CollectCurrentTestGroupName(const std::string& name)
+ {
+ m_currentGroup = name;
+ }
+
+ virtual void CollectResult(const std::string& id,
+ const std::string& /*description*/,
+ const FailStatus::Type status = FailStatus::NONE,
+ const std::string& reason = "",
+ const bool& isPerformanceTest = false,
+ const std::chrono::system_clock::duration& performanceTime = std::chrono::microseconds::zero(),
+ const std::chrono::system_clock::duration& performanceMaxTime = std::chrono::microseconds::zero())
+ {
+ std::string statusMsg = "";
+ switch (status) {
+ case TestResultsCollectorBase::FailStatus::NONE:
+ statusMsg = "OK";
+ if (isPerformanceTest) {
+ statusMsg.append(";;");
+ std::ostringstream ostr;
+ ostr << performanceTime.count();
+ statusMsg.append(ostr.str());
+ if (performanceMaxTime <= std::chrono::microseconds::zero()) {
+ statusMsg.append(";");
+ ostr.str("");
+ ostr << performanceMaxTime.count();
+ statusMsg.append(ostr.str());
+ }
+ }
+ break;
+ case TestResultsCollectorBase::FailStatus::FAILED: statusMsg = "FAILED";
+ break;
+ case TestResultsCollectorBase::FailStatus::IGNORED: statusMsg =
+ "IGNORED";
+ break;
+ case TestResultsCollectorBase::FailStatus::INTERNAL: statusMsg =
+ "FAILED";
+ break;
+ default:
+ Assert(false && "Bad status");
+ }
+ printf("%s;%s;%s;%s\n",
+ m_currentGroup.c_str(),
+ id.c_str(),
+ statusMsg.c_str(),
+ reason.c_str());
+ }
+
+ std::string m_currentGroup;
+};
+
+TestResultsCollectorBase* CSVCollector::Constructor()
+{
+ return new CSVCollector();
+}
+}
+
+class TAPCollector :
+ public TestResultsCollectorBase
+{
+ public:
+ static TestResultsCollectorBase* Constructor();
+
+ private:
+ TAPCollector() : m_filename(DEFAULT_TAP_FILE_NAME) {}
+
+ virtual bool Configure()
+ {
+ m_output.open(m_filename.c_str(), std::ios_base::trunc);
+ if (m_output.fail()) {
+ LogError("Can't open output file: " << m_filename);
+ return false;
+ }
+ return true;
+ }
+ virtual std::string CollectorSpecificHelp() const
+ {
+ std::string retVal = "--file=<filename> - name of file for output\n"
+ " default - ";
+ retVal += DEFAULT_TAP_FILE_NAME;
+ retVal += "\n";
+ return retVal;
+ }
+
+ virtual void Start()
+ {
+ Assert(m_output.good() && "Output file must be opened.");
+ m_output << "TAP version 13" << std::endl;
+ m_testIndex = 0;
+ }
+
+ virtual void Finish()
+ {
+ m_output << "1.." << m_testIndex << std::endl;
+ m_output << m_collectedData.rdbuf();
+ m_output.close();
+ }
+
+ virtual bool ParseCollectorSpecificArg(const std::string& arg)
+ {
+ return ParseCollectorFileArg(arg, m_filename);
+ }
+
+ virtual void CollectResult(const std::string& id,
+ const std::string& description,
+ const FailStatus::Type status = FailStatus::NONE,
+ const std::string& reason = "",
+ const bool& isPerformanceTest = false,
+ const std::chrono::system_clock::duration& performanceTime = std::chrono::microseconds::zero(),
+ const std::chrono::system_clock::duration& performanceMaxTime = std::chrono::microseconds::zero())
+ {
+ /* Remove unused variable warning */
+ DPL_UNUSED_PARAM(isPerformanceTest);
+ DPL_UNUSED_PARAM(performanceTime);
+ DPL_UNUSED_PARAM(performanceMaxTime);
+
+ m_testIndex++;
+ switch (status) {
+ case TestResultsCollectorBase::FailStatus::NONE:
+ LogBasicTAP(true, id, description);
+ endTAPLine();
+ break;
+ case TestResultsCollectorBase::FailStatus::FAILED:
+ LogBasicTAP(false, id, description);
+ endTAPLine();
+ break;
+ case TestResultsCollectorBase::FailStatus::IGNORED:
+ LogBasicTAP(true, id, description);
+ m_collectedData << " # skip " << reason;
+ endTAPLine();
+ break;
+ case TestResultsCollectorBase::FailStatus::INTERNAL:
+ LogBasicTAP(true, id, description);
+ endTAPLine();
+ m_collectedData << " ---" << std::endl;
+ m_collectedData << " message: " << reason << std::endl;
+ m_collectedData << " severity: Internal" << std::endl;
+ m_collectedData << " ..." << std::endl;
+ break;
+ default:
+ Assert(false && "Bad status");
+ }
+ }
+
+ void LogBasicTAP(bool isOK, const std::string& id,
+ const std::string& description)
+ {
+ if (!isOK) {
+ m_collectedData << "not ";
+ }
+ m_collectedData << "ok " << m_testIndex << " [" <<
+ id << "] " << description;
+ }
+
+ void endTAPLine()
+ {
+ m_collectedData << std::endl;
+ }
+
+ std::string m_filename;
+ std::stringstream m_collectedData;
+ std::ofstream m_output;
+ int m_testIndex;
+};
+
+TestResultsCollectorBase* TAPCollector::Constructor()
+{
+ return new TAPCollector();
+}
+
+void TestResultsCollectorBase::RegisterCollectorConstructor(
+ const std::string& name,
+ TestResultsCollectorBase::CollectorConstructorFunc func)
+{
+ Assert(m_constructorsMap.find(name) == m_constructorsMap.end());
+ m_constructorsMap[name] = func;
+}
+
+TestResultsCollectorBase* TestResultsCollectorBase::Create(
+ const std::string& name)
+{
+ ConstructorsMap::iterator found = m_constructorsMap.find(name);
+ if (found != m_constructorsMap.end()) {
+ return found->second();
+ } else {
+ return NULL;
+ }
+}
+
+std::vector<std::string> TestResultsCollectorBase::GetCollectorsNames()
+{
+ std::vector<std::string> list;
+ for (auto &constructor : m_constructorsMap)
+ {
+ list.push_back(constructor.first);
+ }
+ return list;
+}
+
+TestResultsCollectorBase::ConstructorsMap TestResultsCollectorBase::
+ m_constructorsMap;
+
+namespace {
+static int RegisterCollectorConstructors();
+static const int RegisterHelperVariable = RegisterCollectorConstructors();
+int RegisterCollectorConstructors()
+{
+ (void)RegisterHelperVariable;
+
+ TestResultsCollectorBase::RegisterCollectorConstructor(
+ "text",
+ &ConsoleCollector::Constructor);
+ TestResultsCollectorBase::RegisterCollectorConstructor(
+ "html",
+ &HtmlCollector::Constructor);
+ TestResultsCollectorBase::RegisterCollectorConstructor(
+ "csv",
+ &CSVCollector::Constructor);
+ TestResultsCollectorBase::RegisterCollectorConstructor(
+ "tap",
+ &TAPCollector::Constructor);
+ TestResultsCollectorBase::RegisterCollectorConstructor(
+ "xml",
+ &XmlCollector::Constructor);
+
+ return 0;
+}
+}
+}
+}
+#undef GREEN_RESULT_OK
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file test_runner.cpp
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @author Lukasz Wrzosek (l.wrzosek@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of test runner
+ */
+#include <stddef.h>
+#include <dpl/test/test_runner.h>
+#include <dpl/test/test_results_collector.h>
+#include <dpl/exception.h>
+#include <dpl/scoped_free.h>
+#include <dpl/log/log.h>
+#include <dpl/colors.h>
+#include <pcrecpp.h>
+#include <algorithm>
+#include <cstdio>
+#include <memory.h>
+#include <libgen.h>
+#include <cstring>
+#include <cstdlib>
+
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+#include <dpl/singleton_impl.h>
+IMPLEMENT_SINGLETON(DPL::Test::TestRunner)
+
+namespace {
+
+std::string getXMLNode(xmlNodePtr node)
+{
+ std::string ret;
+ xmlChar * value = xmlNodeGetContent(node);
+ ret = std::string(reinterpret_cast<char*>(value));
+ xmlFree(value);
+ return ret;
+}
+
+}
+
+
+namespace DPL {
+namespace Test {
+namespace // anonymous
+{
+std::string BaseName(std::string aPath)
+{
+ ScopedFree<char> path(strdup(aPath.c_str()));
+ if (NULL == path.Get()) {
+ throw std::bad_alloc();
+ }
+ char* baseName = basename(path.Get());
+ std::string retValue = baseName;
+ return retValue;
+}
+} // namespace anonymous
+
+//! \brief Failed test message creator
+//!
+//! \param[in] aTest string for tested expression
+//! \param[in] aFile source file name
+//! \param[in] aLine source file line
+//! \param[in] aMessage error message
+TestRunner::TestFailed::TestFailed(const char* aTest,
+ const char* aFile,
+ int aLine,
+ const std::string &aMessage)
+{
+ std::ostringstream assertMsg;
+ assertMsg << "[" << BaseName(aFile) << ":" << aLine
+ << "] Assertion failed ("
+ << aTest << ") " << aMessage;
+ m_message = assertMsg.str();
+}
+
+TestRunner::TestFailed::TestFailed(const std::string &message)
+{
+ m_message = message;
+}
+
+void TestRunner::RegisterTest(const char *testName, TestCase proc)
+{
+ m_testGroups[m_currentGroup].push_back(TestCaseStruct(testName, proc));
+}
+
+void TestRunner::InitGroup(const char* name)
+{
+ m_currentGroup = name;
+}
+
+void TestRunner::normalizeXMLTag(std::string& str, const std::string& testcase)
+{
+ //Add testcase if missing
+ std::string::size_type pos = str.find(testcase);
+ if(pos != 0)
+ {
+ str = testcase + "_" + str;
+ }
+
+ //dpl test runner cannot have '-' character in name so it have to be replaced
+ // for TCT case to make comparision works
+ std::replace(str.begin(), str.end(), '-', '_');
+}
+
+bool TestRunner::filterGroupsByXmls(const std::vector<std::string> & files)
+{
+ DECLARE_EXCEPTION_TYPE(DPL::Exception, XMLError)
+
+ const std::string idPath = "/test_definition/suite/set/testcase/@id";
+
+ bool success = true;
+ std::map<std::string, bool> casesMap;
+
+ std::string testsuite;
+ if(!m_testGroups.empty())
+ {
+ for(TestCaseGroupMap::const_iterator cit = m_testGroups.begin(); cit != m_testGroups.end(); ++cit)
+ {
+ if(!cit->second.empty())
+ {
+ for(TestCaseStructList::const_iterator cj = cit->second.begin(); cj != cit->second.end(); ++cj)
+ {
+ std::string name = cj->name;
+ std::string::size_type st = name.find('_');
+ if(st != std::string::npos)
+ {
+ name = name.substr(0, st);
+ testsuite = name;
+ break;
+ }
+ }
+ if(!testsuite.empty()) break;
+ }
+ }
+ }
+
+ xmlInitParser();
+ LIBXML_TEST_VERSION
+ xmlXPathInit();
+
+ Try
+ {
+ for (const std::string &file : files)
+ {
+ xmlDocPtr doc;
+ xmlXPathContextPtr xpathCtx;
+
+ doc = xmlReadFile(file.c_str(), NULL, 0);
+ if (doc == NULL) {
+ ThrowMsg(XMLError, "File Problem");
+ } else {
+ //context
+ xpathCtx = xmlXPathNewContext(doc);
+ if (xpathCtx == NULL) {
+ ThrowMsg(XMLError,
+ "Error: unable to create new XPath context\n");
+ }
+ xpathCtx->node = xmlDocGetRootElement(doc);
+ }
+
+ std::string result;
+ xmlXPathObjectPtr xpathObject;
+ //get requested node's values
+ xpathObject = xmlXPathEvalExpression(BAD_CAST idPath.c_str(), xpathCtx);
+ if (xpathObject == NULL)
+ {
+ ThrowMsg(XMLError, "XPath evaluation failure: " << idPath);
+ }
+ xmlNodeSetPtr nodes = xpathObject->nodesetval;
+ unsigned size = (nodes) ? nodes->nodeNr : 0;
+ LogDebug("Found " << size << " nodes matching xpath");
+ for(unsigned i = 0; i < size; ++i)
+ {
+ LogPedantic("Type: " << nodes->nodeTab[i]->type);
+ if (nodes->nodeTab[i]->type == XML_ATTRIBUTE_NODE) {
+ xmlNodePtr curNode = nodes->nodeTab[i];
+ result = getXMLNode(curNode);
+ LogPedantic("Result: " << result);
+ normalizeXMLTag(result, testsuite);
+ casesMap.insert(make_pair(result, false));
+ }
+ }
+ //Cleanup of XPath data
+ xmlXPathFreeObject(xpathObject);
+ xmlXPathFreeContext(xpathCtx);
+ xmlFreeDoc(doc);
+ }
+ }
+ Catch(XMLError)
+ {
+ LogError("Libxml error: " << _rethrown_exception.DumpToString());
+ success = false;
+ }
+ xmlCleanupParser();
+
+ if(!filterByXML(casesMap))
+ {
+ success = false;
+ }
+
+ return success;
+}
+
+bool TestRunner::filterByXML(std::map<std::string, bool> & casesMap)
+{
+ for (auto &group : m_testGroups) {
+ TestCaseStructList newList;
+ for (auto &tc : group.second)
+ {
+ if (casesMap.find(tc.name) != casesMap.end()) {
+ casesMap[tc.name] = true;
+ newList.push_back(tc);
+ }
+ }
+ group.second = newList;
+ }
+ for (auto &cs : casesMap)
+ {
+ if(cs.second == false)
+ {
+ LogError("Cannot find testcase from XML file: " << cs.first);
+ return false;
+ }
+ }
+ return true;
+}
+
+TestRunner::Status TestRunner::RunTestCase(const TestCaseStruct& testCase)
+{
+ setCurrentTestCase(&(const_cast<TestCaseStruct &>(testCase)));
+ try {
+ testCase.proc();
+ } catch (const TestFailed &e) {
+ // Simple test failure
+ CollectResult(testCase.name,
+ "",
+ TestResultsCollectorBase::FailStatus::FAILED,
+ e.GetMessage());
+
+ setCurrentTestCase(NULL);
+ return FAILED;
+ } catch (const Ignored &e) {
+ if (m_runIgnored) {
+ // Simple test have to be implemented
+ CollectResult(testCase.name,
+ "",
+ TestResultsCollectorBase::FailStatus::IGNORED,
+ e.GetMessage());
+ }
+
+ setCurrentTestCase(NULL);
+ return IGNORED;
+ } catch (const DPL::Exception &e) {
+ // DPL exception failure
+ CollectResult(testCase.name,
+ "",
+ TestResultsCollectorBase::FailStatus::INTERNAL,
+ "DPL exception:" + e.GetMessage());
+
+ setCurrentTestCase(NULL);
+ return FAILED;
+ } catch (const std::exception &) {
+ // std exception failure
+ CollectResult(testCase.name,
+ "",
+ TestResultsCollectorBase::FailStatus::INTERNAL,
+ "std exception");
+
+ setCurrentTestCase(NULL);
+ return FAILED;
+ } catch (...) {
+ // Unknown exception failure
+ CollectResult(testCase.name,
+ "",
+ TestResultsCollectorBase::FailStatus::INTERNAL,
+ "unknown exception");
+
+ setCurrentTestCase(NULL);
+ return FAILED;
+ }
+
+ CollectResult(testCase.name,
+ "",
+ TestResultsCollectorBase::FailStatus::NONE,
+ "",
+ testCase.m_isPerformanceTest,
+ testCase.m_performanceTestDurationTime,
+ testCase.m_performanceMaxTime);
+ setCurrentTestCase(NULL);
+
+ // Everything OK
+ return PASS;
+}
+
+void TestRunner::RunTests()
+{
+ using namespace DPL::Colors::Text;
+
+ Banner();
+ for (auto &collector : m_collectors) {
+ collector.second->Start();
+ }
+
+ unsigned count = 0;
+ for (auto &group : m_testGroups) {
+ count += group.second.size();
+ }
+ fprintf(stderr, "%sFound %d testcases...%s\n", GREEN_BEGIN, count, GREEN_END);
+ fprintf(stderr, "%s%s%s\n", GREEN_BEGIN, "Running tests...", GREEN_END);
+ for (auto &group : m_testGroups) {
+ TestCaseStructList list = group.second;
+ if (!list.empty()) {
+ for (auto &collector : m_collectors) {
+ collector.second->CollectCurrentTestGroupName(group.first);
+ }
+ list.sort();
+
+ for (TestCaseStructList::const_iterator iterator = list.begin();
+ iterator != list.end();
+ ++iterator)
+ {
+ TestCaseStruct test = *iterator;
+ if (m_startTestId == test.name) {
+ m_startTestId = "";
+ }
+
+ if (m_startTestId.empty()) {
+ RunTestCase(test);
+ }
+ if (m_terminate == true) {
+ // Terminate quietly without any logs
+ return;
+ }
+ }
+ }
+ }
+
+ std::for_each(m_collectors.begin(),
+ m_collectors.end(),
+ [] (const TestResultsCollectors::value_type & collector)
+ {
+ collector.second->Finish();
+ });
+
+ // Finished
+ fprintf(stderr, "%s%s%s\n\n", GREEN_BEGIN, "Finished", GREEN_END);
+}
+
+TestRunner::TestCaseStruct *TestRunner::getCurrentTestCase()
+{
+ return m_currentTestCase;
+}
+
+void TestRunner::setCurrentTestCase(TestCaseStruct* testCase)
+{
+ m_currentTestCase = testCase;
+}
+
+void TestRunner::beginPerformanceTestTime(std::chrono::system_clock::duration maxTimeInMicroseconds)
+{
+ TestCaseStruct* testCase = getCurrentTestCase();
+ if (!testCase)
+ return;
+
+ testCase->m_isPerformanceTest = true;
+ testCase->m_performanceMaxTime = maxTimeInMicroseconds;
+ testCase->m_performanceTestStartTime = std::chrono::system_clock::now();
+
+ // Set result to 0 microseconds. Display 0ms result when end macro is missing.
+ testCase->m_performanceTestDurationTime = std::chrono::microseconds::zero();
+}
+
+void TestRunner::endPerformanceTestTime()
+{
+ TestCaseStruct* testCase = getCurrentTestCase();
+ if (!testCase)
+ return;
+
+ testCase->m_performanceTestDurationTime = std::chrono::system_clock::now() -
+ testCase->m_performanceTestStartTime;
+}
+
+void TestRunner::getCurrentTestCasePerformanceResult(bool& isPerformanceTest,
+ std::chrono::system_clock::duration& result,
+ std::chrono::system_clock::duration& resultMax)
+{
+ TestCaseStruct* testCase = getCurrentTestCase();
+ if (!testCase || !(testCase->m_isPerformanceTest)){
+ isPerformanceTest = false;
+ return;
+ }
+
+ isPerformanceTest = testCase->m_isPerformanceTest;
+ result = testCase->m_performanceTestDurationTime;
+ resultMax = testCase->m_performanceMaxTime;
+}
+
+void TestRunner::setCurrentTestCasePerformanceResult(bool isPerformanceTest,
+ std::chrono::system_clock::duration result,
+ std::chrono::system_clock::duration resultMax)
+{
+ TestCaseStruct* testCase = getCurrentTestCase();
+ if (!testCase)
+ return;
+
+ testCase->m_isPerformanceTest = isPerformanceTest;
+ testCase->m_performanceTestDurationTime = result;
+ testCase->m_performanceMaxTime = resultMax;
+}
+
+
+void TestRunner::CollectResult(
+ const std::string& id,
+ const std::string& description,
+ const TestResultsCollectorBase::FailStatus::Type status,
+ const std::string& reason,
+ const bool& isPerformanceTest,
+ const std::chrono::system_clock::duration& performanceTestDurationTime,
+ const std::chrono::system_clock::duration& performanceMaxTime)
+{
+ std::for_each(m_collectors.begin(),
+ m_collectors.end(),
+ [&](const TestResultsCollectors::value_type & collector)
+ {
+ collector.second->CollectResult(id,
+ description,
+ status,
+ reason,
+ isPerformanceTest,
+ performanceTestDurationTime,
+ performanceMaxTime);
+ });
+}
+
+void TestRunner::Banner()
+{
+ using namespace DPL::Colors::Text;
+ fprintf(stderr,
+ "%s%s%s\n",
+ BOLD_GREEN_BEGIN,
+ "DPL tests runner",
+ BOLD_GREEN_END);
+ fprintf(stderr,
+ "%s%s%s%s\n\n",
+ GREEN_BEGIN,
+ "Build: ",
+ __TIMESTAMP__,
+ GREEN_END);
+}
+
+void TestRunner::InvalidArgs(const std::string& message)
+{
+ using namespace DPL::Colors::Text;
+ fprintf(stderr,
+ "%s%s%s\n",
+ BOLD_RED_BEGIN,
+ message.c_str(),
+ BOLD_RED_END);
+}
+
+void TestRunner::Usage()
+{
+ fprintf(stderr, "Usage: runner [options]\n\n");
+ fprintf(stderr, "Output type:\n");
+ fprintf(stderr, " --output=<output type> --output=<output type> ...\n");
+ fprintf(stderr, "\n possible output types:\n");
+ for (std::string &type : TestResultsCollectorBase::GetCollectorsNames()) {
+ fprintf(stderr, " --output=%s\n", type.c_str());
+ }
+ fprintf(stderr, "\n example:\n");
+ fprintf(stderr,
+ " test-binary --output=text --output=xml --file=output.xml\n\n");
+ fprintf(stderr, "Other parameters:\n");
+ fprintf(stderr,
+ " --regexp='regexp'\t Only selected tests"
+ " which names match regexp run\n\n");
+ fprintf(stderr, " --start=<test id>\tStart from concrete test id");
+ fprintf(stderr, " --group=<group name>\t Run tests only from one group\n");
+ fprintf(stderr, " --runignored\t Run also ignored tests\n");
+ fprintf(stderr, " --list\t Show a list of Test IDs\n");
+ fprintf(stderr, " --listgroups\t Show a list of Test Group names \n");
+ fprintf(stderr, " --only-from-xml=<xml file>\t Run only testcases specified in XML file \n"
+ " XML name is taken from attribute id=\"part1_part2\" as whole.\n"
+ " If part1 is not found (no _) then it is implicitily "
+ "set according to suite part1 from binary tests\n");
+ fprintf(
+ stderr,
+ " --listingroup=<group name>\t Show a list of Test IDS in one group\n");
+ fprintf(stderr, " --allowchildlogs\t Allow to print logs from child process on screen.\n");
+ fprintf(stderr, " When active child process will be able to print logs on stdout and stderr.\n");
+ fprintf(stderr, " Both descriptors will be closed after test.\n");
+ fprintf(stderr, " --help\t This help\n\n");
+ std::for_each(m_collectors.begin(),
+ m_collectors.end(),
+ [] (const TestResultsCollectors::value_type & collector)
+ {
+ fprintf(stderr,
+ "Output %s has specific args:\n",
+ collector.first.c_str());
+ fprintf(stderr,
+ "%s\n",
+ collector.second->
+ CollectorSpecificHelp().c_str());
+ });
+ fprintf(stderr, "For bug reporting, please write to:\n");
+ fprintf(stderr, "<p.dobrowolsk@samsung.com>\n");
+}
+
+int TestRunner::ExecTestRunner(int argc, char *argv[])
+{
+ std::vector<std::string> args;
+ for (int i = 0; i < argc; ++i) {
+ args.push_back(argv[i]);
+ }
+ return ExecTestRunner(args);
+}
+
+void TestRunner::MarkAssertion()
+{
+ ++m_totalAssertions;
+}
+
+int TestRunner::ExecTestRunner(ArgsList args)
+{
+ m_runIgnored = false;
+ // Parse command line
+ if (args.size() == 1) {
+ InvalidArgs();
+ Usage();
+ return -1;
+ }
+
+ args.erase(args.begin());
+
+ bool showHelp = false;
+ bool justList = false;
+ std::vector<std::string> xmlFiles;
+
+ TestResultsCollectorBasePtr currentCollector;
+
+ // Parse each argument
+ for(std::string &arg : args)
+ {
+ const std::string regexp = "--regexp=";
+ const std::string output = "--output=";
+ const std::string groupId = "--group=";
+ const std::string runIgnored = "--runignored";
+ const std::string listCmd = "--list";
+ const std::string startCmd = "--start=";
+ const std::string listGroupsCmd = "--listgroups";
+ const std::string listInGroup = "--listingroup=";
+ const std::string allowChildLogs = "--allowchildlogs";
+ const std::string onlyFromXML = "--only-from-xml=";
+
+ if (currentCollector) {
+ if (currentCollector->ParseCollectorSpecificArg(arg)) {
+ continue;
+ }
+ }
+
+ if (arg.find(startCmd) == 0) {
+ arg.erase(0, startCmd.length());
+ for (auto &group : m_testGroups) {
+ for (auto &tc : group.second) {
+ if (tc.name == arg) {
+ m_startTestId = arg;
+ break;
+ }
+ }
+ if (!m_startTestId.empty()) {
+ break;
+ }
+ }
+ if (!m_startTestId.empty()) {
+ continue;
+ }
+ InvalidArgs();
+ fprintf(stderr, "Start test id has not been found\n");
+ Usage();
+ return 0;
+ } else if (arg.find(groupId) == 0) {
+ arg.erase(0, groupId.length());
+ TestCaseGroupMap::iterator found = m_testGroups.find(arg);
+ if (found != m_testGroups.end()) {
+ std::string name = found->first;
+ TestCaseStructList newList = found->second;
+ m_testGroups.clear();
+ m_testGroups[name] = newList;
+ } else {
+ fprintf(stderr, "Group %s not found\n", arg.c_str());
+ InvalidArgs();
+ Usage();
+ return -1;
+ }
+ } else if (arg == runIgnored) {
+ m_runIgnored = true;
+ } else if (arg == listCmd) {
+ justList = true;
+ } else if (arg == listGroupsCmd) {
+ for (auto &group : m_testGroups) {
+ printf("GR:%s\n", group.first.c_str());
+ }
+ return 0;
+ } else if (arg.find(listInGroup) == 0) {
+ arg.erase(0, listInGroup.length());
+ for (auto &test : m_testGroups[arg]) {
+ printf("ID:%s\n", test.name.c_str());
+ }
+ return 0;
+ } else if (arg.find(allowChildLogs) == 0) {
+ arg.erase(0, allowChildLogs.length());
+ m_allowChildLogs = true;
+ } else if (arg == "--help") {
+ showHelp = true;
+ } else if (arg.find(output) == 0) {
+ arg.erase(0, output.length());
+ if (m_collectors.find(arg) != m_collectors.end()) {
+ InvalidArgs(
+ "Multiple outputs of the same type are not supported!");
+ Usage();
+ return -1;
+ }
+ currentCollector.reset(TestResultsCollectorBase::Create(arg));
+ if (!currentCollector) {
+ InvalidArgs("Unsupported output type!");
+ Usage();
+ return -1;
+ }
+ m_collectors[arg] = currentCollector;
+ } else if (arg.find(regexp) == 0) {
+ arg.erase(0, regexp.length());
+ if (arg.length() == 0) {
+ InvalidArgs();
+ Usage();
+ return -1;
+ }
+
+ if (arg[0] == '\'' && arg[arg.length() - 1] == '\'') {
+ arg.erase(0);
+ arg.erase(arg.length() - 1);
+ }
+
+ if (arg.length() == 0) {
+ InvalidArgs();
+ Usage();
+ return -1;
+ }
+
+ pcrecpp::RE re(arg.c_str());
+ for (auto &group : m_testGroups) {
+ TestCaseStructList newList;
+ for (auto &tc : group.second)
+ {
+ if (re.PartialMatch(tc.name)) {
+ newList.push_back(tc);
+ }
+ }
+ group.second = newList;
+ }
+ } else if(arg.find(onlyFromXML) == 0) {
+ arg.erase(0, onlyFromXML.length());
+ if (arg.length() == 0) {
+ InvalidArgs();
+ Usage();
+ return -1;
+ }
+
+ if (arg[0] == '\'' && arg[arg.length() - 1] == '\'') {
+ arg.erase(0);
+ arg.erase(arg.length() - 1);
+ }
+
+ if (arg.length() == 0) {
+ InvalidArgs();
+ Usage();
+ return -1;
+ }
+
+ xmlFiles.push_back(arg);
+ } else {
+ InvalidArgs();
+ Usage();
+ return -1;
+ }
+ }
+
+ if(!xmlFiles.empty())
+ {
+ if(!filterGroupsByXmls(xmlFiles))
+ {
+ fprintf(stderr, "XML file is not correct\n");
+ return 0;
+ }
+ }
+
+ if(justList)
+ {
+ for (auto &group : m_testGroups) {
+ for (auto &tc : group.second) {
+ printf("ID:%s:%s\n", group.first.c_str(), tc.name.c_str());
+ }
+ }
+ return 0;
+ }
+
+ currentCollector.reset();
+
+ // Show help
+ if (showHelp) {
+ Usage();
+ return 0;
+ }
+
+ if (m_collectors.empty()) {
+ TestResultsCollectorBasePtr collector(
+ TestResultsCollectorBase::Create("text"));
+ m_collectors["text"] = collector;
+ }
+
+ for (auto &collector : m_collectors) {
+ if (!collector.second->Configure()) {
+ fprintf(stderr, "Could not configure selected output");
+ return 0;
+ }
+ }
+
+ // Run tests
+ RunTests();
+
+ return 0;
+}
+
+bool TestRunner::getRunIgnored() const
+{
+ return m_runIgnored;
+}
+
+void TestRunner::Terminate()
+{
+ m_terminate = true;
+}
+
+bool TestRunner::GetAllowChildLogs()
+{
+ return m_allowChildLogs;
+}
+
+}
+} // namespace DPL
--- /dev/null
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file test_runner_child.cpp
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of test runner
+ */
+#include <stddef.h>
+#include <dpl/test/test_runner.h>
+#include <dpl/test/test_runner_child.h>
+#include <dpl/test/test_results_collector.h>
+#include <dpl/binary_queue.h>
+#include <dpl/exception.h>
+#include <dpl/scoped_free.h>
+#include <dpl/colors.h>
+#include <pcrecpp.h>
+#include <algorithm>
+#include <cstdio>
+#include <memory.h>
+#include <libgen.h>
+#include <cstring>
+#include <cstdlib>
+#include <ctime>
+#include <unistd.h>
+#include <poll.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+
+namespace {
+const int CHILD_TEST_FAIL = 0;
+const int CHILD_TEST_PASS = 1;
+const int CHILD_TEST_IGNORED = 2;
+
+const int MSG_TYPE_MESSAGE = 0; // sizeof(Message) + Message
+const int MSG_TYPE_PERF_TIME = 1; // perfTime + maxTime
+
+int closeOutput() {
+ int devnull;
+ int retcode = -1;
+ if (-1 == (devnull = TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY))))
+ return -1;
+
+ // replace stdout with /dev/null
+ if (-1 == TEMP_FAILURE_RETRY(dup2(devnull, STDOUT_FILENO)))
+ goto end;
+
+ // replace stderr with /dev/null
+ if (-1 == TEMP_FAILURE_RETRY(dup2(devnull, STDERR_FILENO)))
+ goto end;
+
+ retcode = 0;
+
+end:
+ close(devnull);
+ return retcode;
+}
+
+} // namespace anonymous
+
+namespace DPL {
+namespace Test {
+
+PipeWrapper::PipeWrapper()
+{
+ if (-1 == pipe(m_pipefd)) {
+ m_pipefd[0] = PIPE_CLOSED;
+ m_pipefd[1] = PIPE_CLOSED;
+ }
+}
+
+PipeWrapper::~PipeWrapper()
+{
+ closeHelp(0);
+ closeHelp(1);
+}
+
+bool PipeWrapper::isReady()
+{
+ return m_pipefd[0] != PIPE_CLOSED || m_pipefd[1] != PIPE_CLOSED;
+}
+
+void PipeWrapper::setUsage(Usage usage)
+{
+ if (usage == READONLY) {
+ closeHelp(1);
+ }
+ if (usage == WRITEONLY) {
+ closeHelp(0);
+ }
+}
+
+PipeWrapper::Status PipeWrapper::send(int code, std::string &message)
+{
+ if (m_pipefd[1] == PIPE_CLOSED) {
+ return ERROR;
+ }
+
+ std::ostringstream output;
+ output << toBinaryString(code);
+ output << toBinaryString(MSG_TYPE_MESSAGE);
+ output << toBinaryString(static_cast<int>(message.size()));
+ output << message;
+
+ std::string binary = output.str();
+ int size = binary.size();
+
+ if ((writeHelp(&size,
+ sizeof(int)) == ERROR) ||
+ (writeHelp(binary.c_str(), size) == ERROR))
+ {
+ return ERROR;
+ }
+ return SUCCESS;
+}
+
+PipeWrapper::Status PipeWrapper::sendTime(int code,
+ std::chrono::system_clock::duration time,
+ std::chrono::system_clock::duration timeMax)
+{
+ if (m_pipefd[1] == PIPE_CLOSED) {
+ return ERROR;
+ }
+
+ std::ostringstream output;
+ output << toBinaryString(code);
+ output << toBinaryString(MSG_TYPE_PERF_TIME);
+ output << toBinaryString(time);
+ output << toBinaryString(timeMax);
+
+ std::string binary = output.str();
+ int size = binary.size();
+
+ if ((writeHelp(&size,
+ sizeof(int)) == ERROR) ||
+ (writeHelp(binary.c_str(), size) == ERROR))
+ {
+ return ERROR;
+ }
+ return SUCCESS;
+}
+
+PipeWrapper::Status PipeWrapper::receive(int &code,
+ int &msgType,
+ std::string &data,
+ std::chrono::system_clock::duration &time,
+ std::chrono::system_clock::duration &timeMax,
+ time_t deadline)
+{
+ if (m_pipefd[0] == PIPE_CLOSED) {
+ return ERROR;
+ }
+
+ int size;
+ Status ret;
+
+ if ((ret = readHelp(&size, sizeof(int), deadline)) != SUCCESS) {
+ return ret;
+ }
+
+ std::vector<char> buffer;
+ buffer.resize(size);
+
+ if ((ret = readHelp(&buffer[0], size, deadline)) != SUCCESS) {
+ return ret;
+ }
+
+ try {
+ DPL::BinaryQueue queue;
+ queue.AppendCopy(&buffer[0], size);
+
+ queue.FlattenConsume(&code, sizeof(int));
+ queue.FlattenConsume(&msgType, sizeof(int));
+
+ switch (msgType) {
+ case MSG_TYPE_MESSAGE:
+ queue.FlattenConsume(&size, sizeof(int));
+
+ buffer.resize(size);
+
+ queue.FlattenConsume(&buffer[0], size);
+ data.assign(buffer.begin(), buffer.end());
+ break;
+ case MSG_TYPE_PERF_TIME:
+ queue.FlattenConsume(&time, sizeof(std::chrono::system_clock::duration));
+ queue.FlattenConsume(&timeMax, sizeof(std::chrono::system_clock::duration));
+ break;
+ default:
+ return ERROR;
+ }
+ } catch (DPL::BinaryQueue::Exception::Base &e) {
+ return ERROR;
+ }
+ return SUCCESS;
+}
+
+void PipeWrapper::closeAll()
+{
+ closeHelp(0);
+ closeHelp(1);
+}
+
+std::string PipeWrapper::toBinaryString(int data)
+{
+ char buffer[sizeof(int)];
+ memcpy(buffer, &data, sizeof(int));
+ return std::string(buffer, buffer + sizeof(int));
+}
+
+std::string PipeWrapper::toBinaryString(std::chrono::system_clock::duration data)
+{
+ char buffer[sizeof(std::chrono::system_clock::duration)];
+ memcpy(buffer, &data, sizeof(std::chrono::system_clock::duration));
+ return std::string(buffer, buffer + sizeof(std::chrono::system_clock::duration));
+}
+
+void PipeWrapper::closeHelp(int desc)
+{
+ if (m_pipefd[desc] != PIPE_CLOSED) {
+ TEMP_FAILURE_RETRY(close(m_pipefd[desc]));
+ m_pipefd[desc] = PIPE_CLOSED;
+ }
+}
+
+PipeWrapper::Status PipeWrapper::writeHelp(const void *buffer, int size)
+{
+ int ready = 0;
+ const char *p = static_cast<const char *>(buffer);
+ while (ready != size) {
+ int ret = write(m_pipefd[1], &p[ready], size - ready);
+
+ if (ret == -1 && (errno == EAGAIN || errno == EINTR)) {
+ continue;
+ }
+
+ if (ret == -1) {
+ closeHelp(1);
+ return ERROR;
+ }
+
+ ready += ret;
+ }
+ return SUCCESS;
+}
+
+PipeWrapper::Status PipeWrapper::readHelp(void *buf, int size, time_t deadline)
+{
+ int ready = 0;
+ char *buffer = static_cast<char*>(buf);
+ while (ready != size) {
+ time_t wait = deadline - time(0);
+ wait = wait < 1 ? 1 : wait;
+ pollfd fds = { m_pipefd[0], POLLIN, 0 };
+
+ int pollReturn = poll(&fds, 1, wait * 1000);
+
+ if (pollReturn == 0) {
+ return TIMEOUT; // Timeout
+ }
+
+ if (pollReturn < -1) {
+ return ERROR;
+ }
+
+ int ret = read(m_pipefd[0], &buffer[ready], size - ready);
+
+ if (ret == -1 && (errno == EAGAIN || errno == EINTR)) {
+ continue;
+ }
+
+ if (ret == -1 || ret == 0) {
+ closeHelp(0);
+ return ERROR;
+ }
+
+ ready += ret;
+ }
+ return SUCCESS;
+}
+
+void RunChildProc(TestRunner::TestCase procChild)
+{
+ PipeWrapper pipe;
+ if (!pipe.isReady()) {
+ throw TestRunner::TestFailed("Pipe creation failed");
+ }
+
+ pid_t pid = fork();
+
+ if (pid == -1) {
+ throw TestRunner::TestFailed("Child creation failed");
+ }
+
+ if (pid != 0) {
+ // parent code
+ pipe.setUsage(PipeWrapper::READONLY);
+
+ int code;
+ int msgType;
+ std::chrono::system_clock::duration time_m;
+ std::chrono::system_clock::duration timeMax_m;
+ std::string message;
+
+ int pipeReturn = pipe.receive(code, msgType, message, time_m, timeMax_m, time(0) + 10);
+
+ if (pipeReturn != PipeWrapper::SUCCESS) { // Timeout or reading error
+ pipe.closeAll();
+ kill(pid, SIGKILL);
+ }
+
+ int status;
+ waitpid(pid, &status, 0);
+
+ if (pipeReturn == PipeWrapper::TIMEOUT) {
+ throw TestRunner::TestFailed("Timeout");
+ }
+
+ if (pipeReturn == PipeWrapper::ERROR) {
+ throw TestRunner::TestFailed("Reading pipe error");
+ }
+
+ if (code == CHILD_TEST_PASS && msgType == MSG_TYPE_PERF_TIME) {
+ DPL::Test::TestRunnerSingleton::Instance().setCurrentTestCasePerformanceResult(true,
+ time_m,
+ timeMax_m);
+ }
+
+ if (code == CHILD_TEST_FAIL) {
+ throw TestRunner::TestFailed(message);
+ } else if (code == CHILD_TEST_IGNORED) {
+ throw TestRunner::Ignored(message);
+ }
+ } else {
+ // child code
+
+ // End Runner after current test
+ TestRunnerSingleton::Instance().Terminate();
+
+ int code = CHILD_TEST_PASS;
+ std::string msg;
+ bool isPerformanceTest;
+ std::chrono::system_clock::duration time_m;
+ std::chrono::system_clock::duration timeMax_m;
+
+ bool allowLogs = TestRunnerSingleton::Instance().GetAllowChildLogs();
+
+ close(STDIN_FILENO);
+ if (!allowLogs) {
+ closeOutput(); // if fails nothing we can do
+ }
+
+ pipe.setUsage(PipeWrapper::WRITEONLY);
+
+ try {
+ procChild();
+ } catch (const DPL::Test::TestRunner::TestFailed &e) {
+ msg = e.GetMessage();
+ code = CHILD_TEST_FAIL;
+ } catch (const DPL::Test::TestRunner::Ignored &e) {
+ msg = e.GetMessage();
+ code = CHILD_TEST_IGNORED;
+ } catch (...) { // catch all exception generated by "user" code
+ msg = "unhandled exeception";
+ code = CHILD_TEST_FAIL;
+ }
+
+ if (allowLogs) {
+ closeOutput();
+ }
+
+ DPL::Test::TestRunnerSingleton::Instance().getCurrentTestCasePerformanceResult(isPerformanceTest,
+ time_m,
+ timeMax_m);
+
+ if (code == CHILD_TEST_PASS && isPerformanceTest){
+ pipe.sendTime(code,
+ time_m,
+ timeMax_m);
+ } else {
+ pipe.send(code, msg);
+ }
+ }
+}
+} // namespace Test
+} // namespace DPL
--- /dev/null
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file test_runner_multiprocess.cpp
+ * @author Marcin Niesluchowski (m.niesluchow@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of multiprocess test runner
+ */
+
+#include <sys/file.h>
+#include <dpl/exception.h>
+#include <dpl/test/test_runner.h>
+#include <dpl/test/test_runner_child.h>
+#include <dpl/test/test_runner_multiprocess.h>
+#include <poll.h>
+#include <limits.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+namespace {
+
+const int MULTI_TEST_ERROR = -1;
+const int MULTI_TEST_PASS = 0;
+const int MULTI_TEST_FAILED = 1;
+const int MULTI_TEST_IGNORED = 2;
+const int MULTI_TEST_INTERNAL = 3;
+
+}
+
+namespace DPL {
+namespace Test {
+
+SimplePipeWrapper::SimplePipeWrapper()
+: PipeWrapper()
+{
+
+}
+
+SimplePipeWrapper::~SimplePipeWrapper()
+{
+
+}
+
+PipeWrapper::Status SimplePipeWrapper::send(std::string &message)
+{
+ if (m_pipefd[1] == PIPE_CLOSED) {
+ return ERROR;
+ }
+
+ if (message.size() > PIPE_BUF-1) {
+ return ERROR;
+ }
+
+ char buffer[PIPE_BUF] = { 0 };
+
+
+ for(unsigned int i = 0; i < message.size(); ++i) {
+ buffer[i] = message[i];
+ }
+
+ return writeHelp(buffer, PIPE_BUF);
+}
+
+PipeWrapper::Status SimplePipeWrapper::receive(std::string &data, bool &empty, time_t deadline)
+{
+ if (m_pipefd[0] == PIPE_CLOSED) {
+ return ERROR;
+ }
+
+ empty = false;
+
+ data.resize(PIPE_BUF);
+
+ char buffer[PIPE_BUF] = { 0 };
+
+ int ready = 0;
+ while (ready != PIPE_BUF) {
+ time_t wait = deadline - time(0);
+ wait = wait < 1 ? 1 : wait;
+ pollfd fds = { m_pipefd[0], POLLIN, 0 };
+
+ int pollReturn = poll(&fds, 1, wait * 1000);
+
+ if (pollReturn == 0) {
+ return TIMEOUT; // Timeout
+ }
+
+ if (pollReturn < -1) {
+ return ERROR;
+ }
+ int ret = read(m_pipefd[0], &buffer[ready], PIPE_BUF - ready);
+ if (ret == -1 && (errno == EAGAIN || errno == EINTR)) {
+ continue;
+ }
+
+ if (ret == -1) {
+ closeHelp(0);
+ return ERROR;
+ }
+ if (ret == 0) {
+ empty = true;
+ break;
+ }
+
+ ready += ret;
+ }
+
+
+ for(unsigned int i = 0; i < PIPE_BUF; ++i){
+ if(buffer[i] == 0) {
+ data.resize(i);
+ return SUCCESS;
+ }
+ data[i] = buffer[i];
+ }
+
+ return ERROR;
+}
+
+void RunMultiProc(TestRunner::TestCase procMulti)
+{
+ SimplePipeWrapper pipe;
+ int code = MULTI_TEST_PASS;
+ std::string msg = "";
+ int pipeReturn;
+
+ int waitStatus;
+
+ pid_t top_pid = getpid();
+
+ if (!pipe.isReady()) {
+ throw TestRunner::TestFailed("Pipe creation failed");
+ }
+ // pipe
+
+ try {
+ procMulti();
+ } catch (const TestRunner::TestFailed &e) {
+ code = MULTI_TEST_FAILED;
+ msg = e.GetMessage();
+ } catch (const TestRunner::Ignored &e) {
+ code = MULTI_TEST_IGNORED;
+ msg = e.GetMessage();
+ } catch (const DPL::Exception &e) {
+ code = MULTI_TEST_INTERNAL;
+ msg = "DPL exception:" + e.GetMessage();
+ } catch (const std::exception &) {
+ code = MULTI_TEST_INTERNAL;
+ msg = "std exception";
+ } catch (...) {
+ // Unknown exception failure
+ code = MULTI_TEST_INTERNAL;
+ msg = "unknown exception";
+ }
+
+ while (true) {
+ pid_t child_pid = wait(&waitStatus);
+ if (child_pid == -1) {
+ if (errno == ECHILD) {
+ if (top_pid == getpid()) {
+ std::string recMsg="";
+
+ pipe.setUsage(PipeWrapper::READONLY);
+
+ bool empty=false;
+ while(true) {
+ pipeReturn = pipe.receive(recMsg, empty, time(0) + 10);
+
+ if (empty) {
+ break;
+ }
+ if (pipeReturn == PipeWrapper::ERROR) {
+ pipe.closeAll();
+ throw TestRunner::TestFailed("Reading pipe error");
+ } else if (pipeReturn == PipeWrapper::TIMEOUT) {
+ pipe.closeAll();
+ throw TestRunner::TestFailed("Timeout error");
+ }
+ msg = msg + "\n" + recMsg;
+ }
+ pipe.closeAll();
+
+ switch(code) {
+ case MULTI_TEST_PASS:
+ return;
+ case MULTI_TEST_FAILED:
+ throw TestRunner::TestFailed(msg);
+ case MULTI_TEST_IGNORED:
+ throw TestRunner::Ignored(msg);
+ case MULTI_TEST_INTERNAL:
+ throw TestRunner::TestFailed(msg);
+ default:
+ throw TestRunner::TestFailed(msg);
+ }
+ } else {
+ pipe.setUsage(PipeWrapper::WRITEONLY);
+
+ pipeReturn = pipe.send(msg);
+
+ if (pipeReturn == PipeWrapper::ERROR) {
+ pipe.closeAll();
+ code = MULTI_TEST_ERROR;
+ }
+
+ exit(code);
+ }
+ }
+ } else if (WIFEXITED(waitStatus)) {
+ if ((signed char)WEXITSTATUS(waitStatus) == MULTI_TEST_FAILED) {
+ switch (code) {
+ case MULTI_TEST_PASS:
+ code = MULTI_TEST_FAILED;
+ break;
+ case MULTI_TEST_FAILED:
+ break;
+ case MULTI_TEST_IGNORED:
+ code = MULTI_TEST_FAILED;
+ break;
+ case MULTI_TEST_INTERNAL:
+ break;
+ default:
+ break;
+ }
+ } else if ((signed char)WEXITSTATUS(waitStatus) == MULTI_TEST_IGNORED) {
+ switch (code) {
+ case MULTI_TEST_PASS:
+ code = MULTI_TEST_IGNORED;
+ break;
+ case MULTI_TEST_FAILED:
+ break;
+ case MULTI_TEST_IGNORED:
+ break;
+ case MULTI_TEST_INTERNAL:
+ break;
+ default:
+ break;
+ }
+ } else if ((signed char)WEXITSTATUS(waitStatus) == MULTI_TEST_INTERNAL) {
+ switch (code) {
+ case MULTI_TEST_PASS:
+ code = MULTI_TEST_INTERNAL;
+ break;
+ case MULTI_TEST_FAILED:
+ code = MULTI_TEST_INTERNAL;
+ break;
+ case MULTI_TEST_IGNORED:
+ code = MULTI_TEST_INTERNAL;
+ break;
+ case MULTI_TEST_INTERNAL:
+ break;
+ default:
+ break;
+ }
+ } else if ((signed char)WEXITSTATUS(waitStatus) != MULTI_TEST_PASS) {
+ code = MULTI_TEST_ERROR;
+ msg = "PROCESS BAD CODE RETURN";
+ }
+ }
+ }
+}
+} // namespace Test
+} // namespace DPL
PKG_CHECK_MODULES(LPC_TARGET_DEP
libsmack
libprivilege-control
- dpl-test-efl
sqlite3
libtzplatform-config
REQUIRED
#linker directories
TARGET_LINK_LIBRARIES(${LPC_TARGET_TEST}
${LPC_TARGET_DEP_LIBRARIES}
+ dpl-test-framework
tests-common
-lcrypt
)
#dependencies
PKG_CHECK_MODULES(TARGET_DEP
libsmack
- dpl-test-efl
REQUIRED
)
#linker directories
TARGET_LINK_LIBRARIES(${TARGET_TEST}
${TARGET_DEP_LIBRARIES}
+ dpl-test-framework
tests-common
)
libprivilege-control
security-manager
libtzplatform-config
- sqlite3
- dpl-test-efl)
+ sqlite3)
SET(TARGET_SEC_MGR_TESTS "security-manager-tests")
TARGET_LINK_LIBRARIES(${TARGET_SEC_MGR_TESTS}
${SEC_MGR_TESTS_DEP_LIBRARIES}
- tests-common)
+ dpl-test-framework
+ tests-common
+ )
INSTALL(TARGETS ${TARGET_SEC_MGR_TESTS} DESTINATION /usr/bin)
libsmack
libprivilege-control
security-server
- dpl-test-efl
dlog
dbus-1
dbus-glib-1
TARGET_LINK_LIBRARIES(${TARGET_SEC_SRV_CLIENT_SMACK_TESTS}
${SEC_SRV_TESTS_DEP_LIBRARIES}
- tests-common)
+ dpl-test-framework
+ tests-common
+ )
TARGET_LINK_LIBRARIES(${TARGET_SEC_SRV_TC_SERVER_TESTS}
${TARGET_SEC_SRV_COMMON}
${SEC_SRV_TESTS_DEP_LIBRARIES}
- tests-common)
+ dpl-test-framework
+ tests-common
+ )
TARGET_LINK_LIBRARIES(${TARGET_SEC_SRV_PWD_TESTS}
${TARGET_SEC_SRV_COMMON}
${SEC_SRV_TESTS_DEP_LIBRARIES}
- tests-common)
+ dpl-test-framework
+ tests-common
+ )
TARGET_LINK_LIBRARIES(${TARGET_SEC_SRV_PRIVILEGE_TESTS}
${SEC_SRV_TESTS_DEP_LIBRARIES}
- tests-common)
+ dpl-test-framework
+ tests-common
+ )
TARGET_LINK_LIBRARIES(${TARGET_SEC_SRV_STRESS_TESTS}
${SEC_SRV_TESTS_DEP_LIBRARIES}
- tests-common)
+ dpl-test-framework
+ tests-common
+ )
TARGET_LINK_LIBRARIES(${TARGET_SEC_SRV_MT_TESTS}
${SEC_SRV_TESTS_DEP_LIBRARIES}
- tests-common)
+ dpl-test-framework
+ tests-common
+ )
TARGET_LINK_LIBRARIES(${TARGET_SEC_SRV_DBUS_TESTS}
${SEC_SRV_TESTS_DEP_LIBRARIES}
- tests-common)
+ dpl-test-framework
+ tests-common
+ )
TARGET_LINK_LIBRARIES(${TARGET_SEC_SRV_MEASURER}
${TARGET_SEC_SRV_COMMON}
${SEC_SRV_TESTS_DEP_LIBRARIES}
- tests-common)
+ dpl-test-framework
+ tests-common
+ )
# Installation
*/
#include <dpl/log/log.h>
-#include <dpl/serialization.h>
#include <dpl/singleton.h>
#include <dpl/singleton_safe_impl.h>
#include <dpl/test/test_runner.h>