Index: uspace/lib/pcut/include/pcut/asserts.h
===================================================================
--- uspace/lib/pcut/include/pcut/asserts.h	(revision 134ac5d540e7a16b331b62d90010680153d6fbd6)
+++ uspace/lib/pcut/include/pcut/asserts.h	(revision 134ac5d540e7a16b331b62d90010680153d6fbd6)
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2014 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Predefined asserts.
+ *
+ * @defgroup asserts Asserts
+ * Predefined asserts you can use with PCUT.
+ * @{
+ */
+#ifndef PCUT_ASSERTS_H_GUARD
+#define PCUT_ASSERTS_H_GUARD
+
+#include <errno.h>
+
+/** @cond devel */
+
+/** Raise assertion error.
+ *
+ * This function immediately terminates current test and executes a tear-down
+ * (if registered).
+ *
+ * @param fmt Printf-like format string.
+ * @param ... Extra arguments.
+ */
+void pcut_failed_assertion_fmt(const char *fmt, ...);
+
+/** OS-agnostic string comparison.
+ *
+ * @param a First string to compare.
+ * @param b Second string to compare.
+ * @return Whether the strings are equal.
+ */
+int pcut_str_equals(const char *a, const char *b);
+
+/** OS-agnostic conversion from error code to error description.
+ *
+ * This function ensures that the description stored in @p buffer is
+ * always a nul-terminated string.
+ *
+ * @param error Error code.
+ * @param buffer Where to store the error description.
+ * @param size Size of the buffer.
+ */
+void pcut_str_error(int error, char *buffer, int size);
+
+/** @endcond */
+
+/** Raise assertion error.
+ *
+ * This macro adds current file and line and triggers immediate test
+ * abort (tear-down function of the test suite is run when available).
+ *
+ * @param fmt Printf-like format string.
+ * @param ... Extra arguments.
+ */
+#define PCUT_ASSERTION_FAILED(fmt, ...) \
+	pcut_failed_assertion_fmt(__FILE__ ":%d: " fmt, __LINE__, ##__VA_ARGS__)
+
+
+/** Generic assertion for a boolean expression.
+ *
+ * @param actual Actually obtained (computed) value we wish to test to true.
+ */
+#define PCUT_ASSERT_TRUE(actual) \
+	do { \
+		if (!(actual)) { \
+			PCUT_ASSERTION_FAILED("Expected true but got <%s>", \
+				#actual); \
+		} \
+	} while (0)
+
+/** Generic assertion for a boolean expression.
+ *
+ * @param actual Actually obtained (computed) value we wish to test to false.
+ */
+#define PCUT_ASSERT_FALSE(actual) \
+	do { \
+		if ((actual)) { \
+			PCUT_ASSERTION_FAILED("Expected false but got <%s>", \
+				#actual); \
+		} \
+	} while (0)
+
+
+/** Generic assertion for types where == is defined.
+ *
+ * @param expected Expected (correct) value.
+ * @param actual Actually obtained (computed) value we wish to test.
+ */
+#define PCUT_ASSERT_EQUALS(expected, actual) \
+		do {\
+			if (!((expected) == (actual))) { \
+				PCUT_ASSERTION_FAILED("Expected <"#expected "> but got <" #actual ">"); \
+			} \
+		} while (0)
+
+/** Asserts that given pointer is NULL.
+ *
+ * @param pointer The pointer to be tested.
+ */
+#define PCUT_ASSERT_NULL(pointer) \
+	do { \
+		void *pcut_ptr_eval = (pointer); \
+		if (pcut_ptr_eval != (NULL)) { \
+			PCUT_ASSERTION_FAILED("Expected <" #pointer "> to be NULL, " \
+				"instead it points to %p", pcut_ptr_eval); \
+		} \
+	} while (0)
+
+/** Asserts that given pointer is not NULL.
+ *
+ * Use this function when directly quoting the original pointer variable
+ * does not provide sufficient information.
+ *
+ * @param pointer The pointer to be tested.
+ * @param pointer_name Name of the pointer.
+ */
+#define PCUT_ASSERT_NOT_NULL_WITH_NAME(pointer, pointer_name) \
+	do { \
+		const void *pcut_ptr_eval = (pointer); \
+		if (pcut_ptr_eval == (NULL)) { \
+			PCUT_ASSERTION_FAILED("Pointer <" pointer_name "> ought not to be NULL"); \
+		} \
+	} while (0)
+
+/** Asserts that given pointer is not NULL.
+ *
+ * @param pointer The pointer to be tested.
+ */
+#define PCUT_ASSERT_NOT_NULL(pointer) \
+	PCUT_ASSERT_NOT_NULL_WITH_NAME(pointer, #pointer)
+
+
+/** Assertion for checking that two integers are equal.
+ *
+ * @param expected Expected (correct) value.
+ * @param actual Actually obtained (computed) value we wish to test.
+ */
+#define PCUT_ASSERT_INT_EQUALS(expected, actual) \
+	do {\
+		long pcut_expected_eval = (expected); \
+		long pcut_actual_eval = (actual); \
+		if (pcut_expected_eval != pcut_actual_eval) { \
+			PCUT_ASSERTION_FAILED("Expected <%ld> but got <%ld> (%s != %s)", \
+				pcut_expected_eval, pcut_actual_eval, \
+				#expected, #actual); \
+		} \
+	} while (0)
+
+/** Assertion for checking that two doubles are close enough.
+ *
+ * @param expected Expected (correct) value.
+ * @param actual Actually obtained (computed) value we wish to test.
+ * @param epsilon How much the actual value can differ from the expected one.
+ */
+#define PCUT_ASSERT_DOUBLE_EQUALS(expected, actual, epsilon) \
+	do {\
+		double pcut_expected_eval = (expected); \
+		double pcut_actual_eval = (actual); \
+		double pcut_epsilon_eval = (epsilon); \
+		double pcut_double_diff = pcut_expected_eval - pcut_actual_eval; \
+		if ((pcut_double_diff < -pcut_epsilon_eval) | (pcut_double_diff > pcut_epsilon_eval)) { \
+			PCUT_ASSERTION_FAILED("Expected <%lf+-%lf> but got <%lf> (%s != %s)", \
+				pcut_expected_eval, pcut_epsilon_eval, pcut_actual_eval, \
+				#expected, #actual); \
+		} \
+	} while (0)
+
+/** Assertion for checking that two strings (`const char *`) are equal.
+ *
+ * @param expected Expected (correct) value.
+ * @param actual Actually obtained (computed) value we wish to test.
+ */
+#define PCUT_ASSERT_STR_EQUALS(expected, actual) \
+	do {\
+		const char *pcut_expected_eval = (expected); \
+		const char *pcut_actual_eval = (actual); \
+		PCUT_ASSERT_NOT_NULL_WITH_NAME(pcut_expected_eval, #expected); \
+		PCUT_ASSERT_NOT_NULL_WITH_NAME(pcut_actual_eval, #actual); \
+		if (!pcut_str_equals(pcut_expected_eval, pcut_actual_eval)) { \
+			PCUT_ASSERTION_FAILED("Expected <%s> but got <%s> (%s != %s)", \
+				pcut_expected_eval, pcut_actual_eval, \
+				#expected, #actual); \
+		} \
+	} while (0)
+
+
+/** Assertion for checking that two strings (`const char *`) are equal or both NULL.
+ *
+ * @param expected Expected (correct) value.
+ * @param actual Actually obtained (computed) value we wish to test.
+ */
+#define PCUT_ASSERT_STR_EQUALS_OR_NULL(expected, actual) \
+	do {\
+		const char *pcut_expected_eval = (expected); \
+		const char *pcut_actual_eval = (actual); \
+		int pcut_both_null = (pcut_expected_eval == NULL) && (pcut_actual_eval == NULL); \
+		int pcut_some_null = (pcut_expected_eval == NULL) || (pcut_actual_eval == NULL); \
+		if (!pcut_both_null && (pcut_some_null || !pcut_str_equals(pcut_expected_eval, pcut_actual_eval))) { \
+			PCUT_ASSERTION_FAILED("Expected <%s> but got <%s> (%s != %s)", \
+				pcut_expected_eval == NULL ? "NULL" : pcut_expected_eval, \
+				pcut_actual_eval == NULL ? "NULL" : pcut_actual_eval, \
+				#expected, #actual); \
+		} \
+	} while (0)
+
+
+/** Assertion for checking errno-style variables for errors.
+ *
+ * Use this function when directly quoting the original error code does
+ * not provide sufficient information.
+ *
+ * @param expected_value Expected errno error code.
+ * @param expected_quoted Expected error code as a string.
+ * @param actual_value Actual value of the error code.
+ */
+#define PCUT_ASSERT_ERRNO_VAL_WITH_NAME(expected_value, expected_quoted, actual_value) \
+	do {\
+		int pcut_expected_eval = (expected_value); \
+		int pcut_actual_eval = (actual_value); \
+		if (pcut_expected_eval != pcut_actual_eval) { \
+			char pcut_expected_description[100]; \
+			char pcut_actual_description[100]; \
+			pcut_str_error(pcut_expected_eval, pcut_expected_description, 100); \
+			pcut_str_error(pcut_actual_eval, pcut_actual_description, 100); \
+			PCUT_ASSERTION_FAILED("Expected error %d (%s, %s) but got error %d (%s)", \
+				pcut_expected_eval, expected_quoted, \
+				pcut_expected_description, \
+				pcut_actual_eval, pcut_actual_description); \
+		} \
+	} while (0)
+
+/** Assertion for checking errno-style variables for errors.
+ *
+ * @param expected Expected errno error code.
+ * @param actual Actual value of the error code.
+ */
+#define PCUT_ASSERT_ERRNO_VAL(expected, actual) \
+	PCUT_ASSERT_ERRNO_VAL_WITH_NAME(expected, #expected, actual)
+
+/** Assertion for checking errno variable for errors.
+ *
+ * @param expected Expected errno error code.
+ */
+#define PCUT_ASSERT_ERRNO(expected) \
+	PCUT_ASSERT_ERRNO_VAL_WITH_NAME(expected, #expected, (errno))
+
+/**
+ * @}
+ */
+
+#endif
Index: uspace/lib/pcut/include/pcut/datadef.h
===================================================================
--- uspace/lib/pcut/include/pcut/datadef.h	(revision 134ac5d540e7a16b331b62d90010680153d6fbd6)
+++ uspace/lib/pcut/include/pcut/datadef.h	(revision 134ac5d540e7a16b331b62d90010680153d6fbd6)
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2012-2013 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Data types internally used by PCUT.
+ */
+#ifndef PCUT_DATADEF_H_GUARD
+#define PCUT_DATADEF_H_GUARD
+
+#include <pcut/prevs.h>
+#include <stdlib.h>
+#include <stddef.h>
+
+/** @cond devel */
+
+enum {
+	PCUT_KIND_SKIP,
+	PCUT_KIND_NESTED,
+	PCUT_KIND_SETUP,
+	PCUT_KIND_TEARDOWN,
+	PCUT_KIND_TESTSUITE,
+	PCUT_KIND_TEST
+};
+
+enum {
+	PCUT_EXTRA_TIMEOUT,
+	PCUT_EXTRA_SKIP,
+	PCUT_EXTRA_LAST
+};
+
+/** Generic wrapper for test cases, test suites etc. */
+typedef struct pcut_item pcut_item_t;
+
+/** Extra information about a test. */
+typedef struct pcut_extra pcut_extra_t;
+
+/** Test method type. */
+typedef void (*pcut_test_func_t)(void);
+
+/** Set-up or tear-down method type. */
+typedef void (*pcut_setup_func_t)(void);
+
+/** @copydoc pcut_extra_t */
+struct pcut_extra {
+	/** Discriminator for the union.
+	 *
+	 * Use PCUT_EXTRA_* to determine which field of the union is used.
+	 */
+	int type;
+	union {
+		/** Test-specific time-out in seconds. */
+		int timeout;
+	};
+};
+
+/** @copydoc pcut_item_t */
+struct pcut_item {
+	/** Link to previous item. */
+	pcut_item_t *previous;
+	/** Link to next item. */
+	pcut_item_t *next;
+
+	/** Unique id of this item. */
+	int id;
+
+	/** Discriminator for the union.
+	 *
+	 * Use PCUT_KIND_* to determine which field of the union is used.
+	 */
+	int kind;
+	union {
+		struct {
+			const char *name;
+			pcut_setup_func_t setup;
+			pcut_setup_func_t teardown;
+		} suite;
+		struct {
+			const char *name;
+			pcut_test_func_t func;
+			pcut_extra_t *extras;
+		} test;
+		/* setup is used for both set-up and tear-down */
+		struct {
+			pcut_setup_func_t func;
+		} setup;
+		struct {
+			pcut_item_t *last;
+		} nested;
+		struct {
+			int dummy;
+		} meta;
+	};
+};
+
+#ifdef PCUT_DEBUG_BUILD
+#define PCUT_DEBUG(msg, ...) \
+	printf("[PCUT]: Debug: " msg "\n", ##__VA_ARGS__)
+#else
+
+/** Debug printing.
+ *
+ * By default, this macro does nothing. Define PCUT_DEBUG_BUILD to
+ * actually print the messages to the console.
+ *
+ * @param msg Printf-like formatting message.
+ * @param ... Extra arguments for printf.
+ */
+#define PCUT_DEBUG(msg, ...) (void)0
+#endif
+
+/** @endcond */
+
+#endif
Index: uspace/lib/pcut/include/pcut/impl.h
===================================================================
--- uspace/lib/pcut/include/pcut/impl.h	(revision 01579ad1020d073a91a73278666eb1fa947e04f5)
+++ 	(revision )
@@ -1,184 +1,0 @@
-/*
- * Copyright (c) 2012-2013 Vojtech Horky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if !defined(PCUT_TEST_H_GUARD) && !defined(PCUT_INTERNAL)
-#error "You cannot include this file directly."
-#endif
-
-#ifndef PCUT_IMPL_H_GUARD
-#define PCUT_IMPL_H_GUARD
-
-#include "prevs.h"
-#include <stdlib.h>
-
-enum {
-	PCUT_KIND_SKIP,
-	PCUT_KIND_NESTED,
-	PCUT_KIND_SETUP,
-	PCUT_KIND_TEARDOWN,
-	PCUT_KIND_TESTSUITE,
-	PCUT_KIND_TEST
-};
-
-typedef struct pcut_item pcut_item_t;
-typedef void (*pcut_test_func_t)(void);
-typedef void (*pcut_setup_func_t)(void);
-
-struct pcut_item {
-	pcut_item_t *previous;
-	pcut_item_t *next;
-	int id;
-	int kind;
-	union {
-		struct {
-			const char *name;
-			pcut_setup_func_t setup;
-			pcut_setup_func_t teardown;
-		} suite;
-		struct {
-			const char *name;
-			pcut_test_func_t func;
-		} test;
-		/* setup is used for both set-up and tear-down */
-		struct {
-			pcut_setup_func_t func;
-		} setup;
-		struct {
-			pcut_item_t *last;
-		} nested;
-		struct {
-			int dummy;
-		} meta;
-	};
-};
-
-void pcut_failed_assertion(const char *message);
-void pcut_failed_assertion_fmt(const char *fmt, ...);
-int pcut_str_equals(const char *a, const char *b);
-int pcut_main(pcut_item_t *last, int argc, char *argv[]);
-
-#define PCUT_ASSERTION_FAILED(fmt, ...) \
-	pcut_failed_assertion_fmt(__FILE__ ":%d: " fmt, __LINE__, ##__VA_ARGS__)
-
-#define PCUT_JOIN_IMPL(a, b) a##b
-#define PCUT_JOIN(a, b) PCUT_JOIN_IMPL(a, b)
-
-#define PCUT_ITEM_NAME(number) \
-	PCUT_JOIN(pcut_item_, number)
-
-#define PCUT_ITEM_NAME_PREV(number) \
-	PCUT_JOIN(pcut_item_, PCUT_JOIN(PCUT_PREV_, number))
-
-#define PCUT_ADD_ITEM(number, itemkind, ...) \
-		static pcut_item_t PCUT_ITEM_NAME(number) = { \
-				.previous = &PCUT_ITEM_NAME_PREV(number), \
-				.next = NULL, \
-				.id = -1, \
-				.kind = itemkind, \
-				__VA_ARGS__ \
-		}; \
-
-#define PCUT_TEST_IMPL(testname, number) \
-		static void PCUT_JOIN(test_, testname)(void); \
-		PCUT_ADD_ITEM(number, PCUT_KIND_TEST, \
-				.test = { \
-					.name = #testname, \
-					.func = PCUT_JOIN(test_, testname) \
-				} \
-		) \
-		void PCUT_JOIN(test_, testname)(void)
-
-#define PCUT_TEST_SUITE_IMPL(suitename, number) \
-		PCUT_ADD_ITEM(number, PCUT_KIND_TESTSUITE, \
-				.suite = { \
-					.name = #suitename, \
-					.setup = NULL, \
-					.teardown = NULL \
-				} \
-		)
-
-#define PCUT_TEST_BEFORE_IMPL(number) \
-		static void PCUT_JOIN(setup_, number)(void); \
-		PCUT_ADD_ITEM(number, PCUT_KIND_SETUP, \
-				.setup.func = PCUT_JOIN(setup_, number) \
-		) \
-		void PCUT_JOIN(setup_, number)(void)
-
-#define PCUT_TEST_AFTER_IMPL(number) \
-		static void PCUT_JOIN(teardown_, number)(void); \
-		PCUT_ADD_ITEM(number, PCUT_KIND_TEARDOWN, \
-				.setup.func = PCUT_JOIN(teardown_, number) \
-		) \
-		void PCUT_JOIN(teardown_, number)(void)
-
-#define PCUT_EXPORT_IMPL(identifier, number) \
-	pcut_item_t pcut_exported_##identifier = { \
-		.previous = &PCUT_ITEM_NAME_PREV(number), \
-		.next = NULL, \
-		.kind = PCUT_KIND_SKIP \
-	}
-
-/*
- * Trick with [] and & copied from
- * http://bytes.com/topic/c/answers/553555-initializer-element-not-constant#post2159846
- * because following does not work:
- * extern int *a;
- * int *b = a;
- */
-#define PCUT_IMPORT_IMPL(identifier, number) \
-	extern pcut_item_t pcut_exported_##identifier; \
-	PCUT_ADD_ITEM(number, PCUT_KIND_NESTED, \
-		.nested.last = &pcut_exported_##identifier \
-	)
-
-#define PCUT_INIT_IMPL(first_number) \
-	static pcut_item_t PCUT_ITEM_NAME(__COUNTER__) = { \
-		.previous = NULL, \
-		.next = NULL, \
-		.id = -1, \
-		.kind = PCUT_KIND_SKIP \
-	}; \
-	PCUT_TEST_SUITE(Default);
-
-#define PCUT_MAIN_IMPL(last_number) \
-	static pcut_item_t pcut_item_last = { \
-		.previous = &PCUT_JOIN(pcut_item_, PCUT_JOIN(PCUT_PREV_, last_number)), \
-		.kind = PCUT_KIND_SKIP \
-	}; \
-	int main(int argc, char *argv[]) { \
-		return pcut_main(&pcut_item_last, argc, argv); \
-	}
-
-#ifdef PCUT_DEBUG_BUILD
-#define PCUT_DEBUG(msg, ...) \
-	printf("[PCUT]: Debug: " msg "\n", ##__VA_ARGS__)
-#else
-#define PCUT_DEBUG(msg, ...) (void)0
-#endif
-
-#endif
Index: uspace/lib/pcut/include/pcut/pcut.h
===================================================================
--- uspace/lib/pcut/include/pcut/pcut.h	(revision 134ac5d540e7a16b331b62d90010680153d6fbd6)
+++ uspace/lib/pcut/include/pcut/pcut.h	(revision 134ac5d540e7a16b331b62d90010680153d6fbd6)
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012-2014 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * PCUT: Plain-C unit-testing mini-framework.
+ */
+#ifndef PCUT_PCUT_H_GUARD
+#define PCUT_PCUT_H_GUARD
+
+#include <pcut/asserts.h>
+#include <pcut/tests.h>
+
+#endif
Index: uspace/lib/pcut/include/pcut/prevs.h
===================================================================
--- uspace/lib/pcut/include/pcut/prevs.h	(revision 01579ad1020d073a91a73278666eb1fa947e04f5)
+++ uspace/lib/pcut/include/pcut/prevs.h	(revision 134ac5d540e7a16b331b62d90010680153d6fbd6)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012-2013 Vojtech Horky
+ * Copyright (c) 2012-2014 Vojtech Horky
  * All rights reserved.
  *
@@ -27,10 +27,14 @@
  */
 
-#if !defined(PCUT_TEST_H_GUARD) && !defined(PCUT_INTERNAL)
-#error "You cannot include this file directly."
-#endif
+/**
+ * @file
+ * Counter macros internally used by PCUT.
+ */
 
 #ifndef PCUT_PREVS_H_GUARD
 #define PCUT_PREVS_H_GUARD
+
+#ifndef PCUT_DOXYGEN_IS_RUNNING
+/** @cond devel */
 
 #define PCUT_PREV_1 0
@@ -335,4 +339,8 @@
 #define PCUT_PREV_300 299
 
+/** @endcond */
+
 #endif
 
+#endif
+
Index: uspace/lib/pcut/include/pcut/test.h
===================================================================
--- uspace/lib/pcut/include/pcut/test.h	(revision 01579ad1020d073a91a73278666eb1fa947e04f5)
+++ 	(revision )
@@ -1,172 +1,0 @@
-/*
- * Copyright (c) 2012-2013 Vojtech Horky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- *
- * PCUT: Plain-C unit-testing mini-framework.
- */
-#ifndef PCUT_TEST_H_GUARD
-#define PCUT_TEST_H_GUARD
-
-#include "impl.h"
-
-/** Generic assertion for types where == is defined.
- *
- * @param expected Expected (correct) value.
- * @param actual Actually obtained (computed) value we wish to test.
- */
-#define PCUT_ASSERT_EQUALS(expected, actual) \
-		do {\
-			if (!((expected) == (actual))) { \
-				PCUT_ASSERTION_FAILED("Expected <"#expected "> but got <" #actual ">"); \
-			} \
-		} while (0)
-
-/** Asserts that given pointer is NULL.
- *
- * @param pointer The pointer to be tested.
- */
-#define PCUT_ASSERT_NULL(pointer) \
-	do { \
-		void *pcut_ptr_eval = (pointer); \
-		if (pcut_ptr_eval != (NULL)) { \
-			PCUT_ASSERTION_FAILED("Expected <" #pointer "> to be NULL, " \
-				"instead it points to %p", pcut_ptr_eval); \
-		} \
-	} while (0)
-
-/** Asserts that given pointer is not NULL.
- *
- * @param pointer The pointer to be tested.
- */
-#define PCUT_ASSERT_NOT_NULL(pointer) \
-	do { \
-		void *pcut_ptr_eval = (pointer); \
-		if (pcut_ptr_eval == (NULL)) { \
-			PCUT_ASSERTION_FAILED("Pointer <" #pointer "> ought not to be NULL"); \
-		} \
-	} while (0)
-
-
-/** Assertion for checking that two integers are equal.
- *
- * @param expected Expected (correct) value.
- * @param actual Actually obtained (computed) value we wish to test.
- */
-#define PCUT_ASSERT_INT_EQUALS(expected, actual) \
-	do {\
-		long pcut_expected_eval = (expected); \
-		long pcut_actual_eval = (actual); \
-		if (pcut_expected_eval != pcut_actual_eval) { \
-			PCUT_ASSERTION_FAILED("Expected <%ld> but got <%ld> (%s != %s)", \
-				pcut_expected_eval, pcut_actual_eval, \
-				#expected, #actual); \
-		} \
-	} while (0)
-
-/** Assertion for checking that two doubles are close enough.
- *
- * @param expected Expected (correct) value.
- * @param actual Actually obtained (computed) value we wish to test.
- * @param epsilon How much the actual value can differ from the expected one.
- */
-#define PCUT_ASSERT_DOUBLE_EQUALS(expected, actual, epsilon) \
-	do {\
-		double pcut_expected_eval = (expected); \
-		double pcut_actual_eval = (actual); \
-		double pcut_epsilon_eval = (epsilon); \
-		double pcut_double_diff = pcut_expected_eval - pcut_actual_eval; \
-		if ((pcut_double_diff < -pcut_epsilon_eval) | (pcut_double_diff > pcut_epsilon_eval)) { \
-			PCUT_ASSERTION_FAILED("Expected <%lf+-%lf> but got <%lf> (%s != %s)", \
-				pcut_expected_eval, pcut_epsilon_eval, pcut_actual_eval, \
-				#expected, #actual); \
-		} \
-	} while (0)
-
-/** Assertion for checking that two strings (`const char *`) are equal.
- *
- * @param expected Expected (correct) value.
- * @param actual Actually obtained (computed) value we wish to test.
- */
-#define PCUT_ASSERT_STR_EQUALS(expected, actual) \
-	do {\
-		const char *pcut_expected_eval = (expected); \
-		const char *pcut_actual_eval = (actual); \
-		if (!pcut_str_equals(pcut_expected_eval, pcut_actual_eval)) { \
-			PCUT_ASSERTION_FAILED("Expected <%s> but got <%s> (%s != %s)", \
-				pcut_expected_eval, pcut_actual_eval, \
-				#expected, #actual); \
-		} \
-	} while (0)
-
-
-/** Define a new test with given name.
- *
- * @param name A valid C identifier name (not quoted).
- */
-#define PCUT_TEST(name) PCUT_TEST_IMPL(name, __COUNTER__)
-
-/** Define a new test suite with given name.
- *
- * All tests following this macro belong to the new suite
- * (up to next occurence of PCUT_TEST_SUITE).
- *
- */
-#define PCUT_TEST_SUITE(name) PCUT_TEST_SUITE_IMPL(name, __COUNTER__)
-
-/** Define a set-up function for a test suite.
- *
- * There could be only a single set-up function for each suite.
- */
-#define PCUT_TEST_BEFORE \
-	PCUT_TEST_BEFORE_IMPL(__COUNTER__)
-
-/** Define a tear-down function for a test suite.
- *
- * There could be only a single tear-down function for each suite.
- */
-#define PCUT_TEST_AFTER \
-	PCUT_TEST_AFTER_IMPL(__COUNTER__)
-
-/** Export test cases from current file. */
-#define PCUT_EXPORT(identifier) \
-	PCUT_EXPORT_IMPL(identifier, __COUNTER__)
-
-/** Import test cases from a different file. */
-#define PCUT_IMPORT(identifier) \
-	PCUT_IMPORT_IMPL(identifier, __COUNTER__)
-
-/** Initialize the PCUT testing framework. */
-#define PCUT_INIT \
-	PCUT_INIT_IMPL(__COUNTER__)
-
-/** Insert code to run all the tests. */
-#define PCUT_MAIN() \
-	PCUT_MAIN_IMPL(__COUNTER__)
-
-#endif
Index: uspace/lib/pcut/include/pcut/tests.h
===================================================================
--- uspace/lib/pcut/include/pcut/tests.h	(revision 134ac5d540e7a16b331b62d90010680153d6fbd6)
+++ uspace/lib/pcut/include/pcut/tests.h	(revision 134ac5d540e7a16b331b62d90010680153d6fbd6)
@@ -0,0 +1,422 @@
+/*
+ * Copyright (c) 2014 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Tests and test suites.
+ *
+ * @defgroup tests Tests
+ * Create test suites and test cases.
+ * @{
+ */
+#ifndef PCUT_TESTS_H_GUARD
+#define PCUT_TESTS_H_GUARD
+
+#include <pcut/datadef.h>
+
+/*
+ * Trick with [] and & copied from
+ * http://bytes.com/topic/c/answers/553555-initializer-element-not-constant#post2159846
+ * because following does not work:
+ * extern int *a;
+ * int *b = a;
+ */
+
+
+#ifndef __COUNTER__
+#define PCUT_WITHOUT_COUNTER
+#endif
+
+#ifndef PCUT_WITHOUT_COUNTER
+#define PCUT_ITEM_COUNTER_INCREMENT
+#endif
+
+
+/** Default timeout for a single test (in seconds).
+ * @showinitializer
+ */
+#define PCUT_DEFAULT_TEST_TIMEOUT 3
+
+/** Item counter that is expected to be incremented by preprocessor.
+ *
+ * Used compiler must support __COUNTER__ for this to work without any
+ * extra preprocessing.
+ */
+#ifdef PCUT_WITHOUT_COUNTER
+#define PCUT_ITEM_COUNTER PCUT_you_need_to_run_pcut_preprocessor
+#else
+#define PCUT_ITEM_COUNTER __COUNTER__
+#endif
+
+
+/*
+ * Helper macros
+ * -------------
+ */
+
+/** @cond devel */
+
+/** Join the two arguments on preprocessor level (inner call). */
+#define PCUT_JOIN_IMPL(a, b) a##b
+
+/** Join the two arguments on preprocessor level. */
+#define PCUT_JOIN(a, b) PCUT_JOIN_IMPL(a, b)
+
+/** Produce identifier name for an item with given number.
+ *
+ * @param number Item number.
+ */
+#ifndef PCUT_WITHOUT_COUNTER
+#define PCUT_ITEM_NAME(number) \
+	PCUT_JOIN(pcut_item_, number)
+#else
+#define PCUT_ITEM_NAME(number) PCUT_ITEM_NAME
+#endif
+
+/** Produce identifier name for a preceding item.
+ *
+ * @param number Number of the current item.
+ */
+#ifndef PCUT_WITHOUT_COUNTER
+#define PCUT_ITEM_NAME_PREV(number) \
+	PCUT_JOIN(pcut_item_, PCUT_JOIN(PCUT_PREV_, number))
+#else
+#define PCUT_ITEM_NAME_PREV(number) PCUT_ITEM_NAME_PREV
+#endif
+
+#ifndef PCUT_WITHOUT_COUNTER
+#define PCUT_ITEM_EXTRAS_NAME(number) \
+	PCUT_JOIN(pcut_extras_, number)
+#else
+#define PCUT_ITEM_EXTRAS_NAME(number) PCUT_ITEM2_NAME
+#endif
+
+#ifndef PCUT_WITHOUT_COUNTER
+#define PCUT_ITEM_SETUP_NAME(number) \
+	PCUT_JOIN(pcut_setup_, number)
+#else
+#define PCUT_ITEM_SETUP_NAME(number) PCUT_ITEM3_NAME
+#endif
+
+
+
+/** Create a new item, append it to the list.
+ *
+ * @param number Number of this item.
+ * @param itemkind Kind of this item (PCUT_KIND_*).
+ * @param ... Other initializers of the pcut_item_t.
+ */
+#define PCUT_ADD_ITEM(number, itemkind, ...) \
+		static pcut_item_t PCUT_ITEM_NAME(number) = { \
+				.previous = &PCUT_ITEM_NAME_PREV(number), \
+				.next = NULL, \
+				.id = -1, \
+				.kind = itemkind, \
+				__VA_ARGS__ \
+		};
+
+/** @endcond */
+
+
+
+/*
+ * Test-case related macros
+ * ------------------------
+ */
+
+/** Define test time-out.
+ *
+ * Use as argument to PCUT_TEST().
+ *
+ * @param time_out Time-out value in seconds.
+ */
+#define PCUT_TEST_SET_TIMEOUT(time_out) \
+	{ .type = PCUT_EXTRA_TIMEOUT, .timeout = (time_out) }
+
+/** Skip current test.
+ *
+ * Use as argument to PCUT_TEST().
+ */
+#define PCUT_TEST_SKIP \
+	{ .type = PCUT_EXTRA_SKIP }
+
+
+/** @cond devel */
+
+/** Terminate list of extra test options. */
+#define PCUT_TEST_EXTRA_LAST { .type = PCUT_EXTRA_LAST }
+
+/** Define a new test with given name and given item number.
+ *
+ * @param testname A valid C identifier name (not quoted).
+ * @param number Number of the item describing this test.
+ * @param ... Extra test properties.
+ */
+#define PCUT_TEST_WITH_NUMBER(testname, number, ...) \
+		PCUT_ITEM_COUNTER_INCREMENT \
+		static pcut_extra_t PCUT_ITEM_EXTRAS_NAME(number)[] = { \
+				__VA_ARGS__ \
+		}; \
+		static void PCUT_JOIN(test_, testname)(void); \
+		PCUT_ADD_ITEM(number, PCUT_KIND_TEST, \
+				.test = { \
+					.name = #testname, \
+					.func = PCUT_JOIN(test_, testname), \
+					.extras = PCUT_ITEM_EXTRAS_NAME(number), \
+				} \
+		) \
+		void PCUT_JOIN(test_, testname)(void)
+
+/** @endcond */
+
+/** Define a new test with given name.
+ *
+ * @param name A valid C identifier name (not quoted).
+ * @param ... Extra test properties.
+ */
+#define PCUT_TEST(name, ...) \
+	PCUT_TEST_WITH_NUMBER(name, PCUT_ITEM_COUNTER, ##__VA_ARGS__, PCUT_TEST_EXTRA_LAST)
+
+
+
+
+
+/*
+ * Test suite related macros
+ * -------------------------
+ */
+
+/** @cond devel */
+
+/** Define and start a new test suite.
+ *
+ * @see PCUT_TEST_SUITE
+ *
+ * @param suitename Suite name (a valid C identifier).
+ * @param number Item number.
+ */
+#define PCUT_TEST_SUITE_WITH_NUMBER(suitename, number) \
+		PCUT_ITEM_COUNTER_INCREMENT \
+		PCUT_ADD_ITEM(number, PCUT_KIND_TESTSUITE, \
+				.suite = { \
+					.name = #suitename, \
+					.setup = NULL, \
+					.teardown = NULL \
+				} \
+		)
+
+/** Define a set-up function for a test suite.
+ *
+ * @see PCUT_TEST_BEFORE
+ *
+ * @param number Item number.
+ */
+#define PCUT_TEST_BEFORE_WITH_NUMBER(number) \
+		PCUT_ITEM_COUNTER_INCREMENT \
+		static void PCUT_ITEM_SETUP_NAME(number)(void); \
+		PCUT_ADD_ITEM(number, PCUT_KIND_SETUP, \
+				.setup.func = PCUT_ITEM_SETUP_NAME(number) \
+		) \
+		void PCUT_ITEM_SETUP_NAME(number)(void)
+
+/** Define a tear-down function for a test suite.
+ *
+ * @see PCUT_TEST_AFTER
+ *
+ * @param number Item number.
+ */
+#define PCUT_TEST_AFTER_WITH_NUMBER(number) \
+		PCUT_ITEM_COUNTER_INCREMENT \
+		static void PCUT_ITEM_SETUP_NAME(number)(void); \
+		PCUT_ADD_ITEM(number, PCUT_KIND_TEARDOWN, \
+				.setup.func = PCUT_ITEM_SETUP_NAME(number) \
+		) \
+		void PCUT_ITEM_SETUP_NAME(number)(void)
+
+/** @endcond */
+
+
+/** Define and start a new test suite.
+ *
+ * All tests following this macro belong to the new suite
+ * (up to next occurrence of PCUT_TEST_SUITE).
+ *
+ * This command shall be used as is without any extra code.
+ *
+ * @param name Suite name (a valid C identifier).
+ */
+#define PCUT_TEST_SUITE(name) \
+	PCUT_TEST_SUITE_WITH_NUMBER(name, PCUT_ITEM_COUNTER)
+
+/** Define a set-up function for a test suite.
+ *
+ * The code of the function immediately follows this macro.
+ *
+ * @code
+ * PCUT_TEST_SUITE(my_suite);
+ *
+ * PCUT_TEST_BEFORE {
+ *     printf("This is executed before each test in this suite.\n");
+ * }
+ * @endcode
+ *
+ * There could be only a single set-up function for each suite.
+ */
+#define PCUT_TEST_BEFORE \
+	PCUT_TEST_BEFORE_WITH_NUMBER(PCUT_ITEM_COUNTER)
+
+/** Define a tear-down function for a test suite.
+ *
+ * The code of the function immediately follows this macro.
+ *
+ * @code
+ * PCUT_TEST_SUITE(my_suite);
+ *
+ * PCUT_TEST_AFTER {
+ *     printf("This is executed after each test in this suite.\n");
+ * }
+ * @endcode
+ *
+ * There could be only a single tear-down function for each suite.
+ */
+#define PCUT_TEST_AFTER \
+	PCUT_TEST_AFTER_WITH_NUMBER(PCUT_ITEM_COUNTER)
+
+
+
+
+
+/*
+ * Import/export related macros
+ * ----------------------------
+ */
+
+/** @cond devel */
+
+/** Export test cases from current file.
+ *
+ * @see PCUT_EXPORT
+ *
+ * @param identifier Identifier of this block of tests.
+ * @param number Item number.
+ */
+#define PCUT_EXPORT_WITH_NUMBER(identifier, number) \
+	PCUT_ITEM_COUNTER_INCREMENT \
+	pcut_item_t pcut_exported_##identifier = { \
+		.previous = &PCUT_ITEM_NAME_PREV(number), \
+		.next = NULL, \
+		.kind = PCUT_KIND_SKIP \
+	}
+
+/** Import test cases from a different file.
+ *
+ * @see PCUT_EXPORT
+ *
+ * @param identifier Identifier of the tests to import.
+ * @param number Item number.
+ */
+#define PCUT_IMPORT_WITH_NUMBER(identifier, number) \
+	PCUT_ITEM_COUNTER_INCREMENT \
+	extern pcut_item_t pcut_exported_##identifier; \
+	PCUT_ADD_ITEM(number, PCUT_KIND_NESTED, \
+		.nested.last = &pcut_exported_##identifier \
+	)
+
+/** @endcond */
+
+/** Export test cases from current file.
+ *
+ * @param identifier Identifier of this block of tests.
+ */
+#define PCUT_EXPORT(identifier) \
+	PCUT_EXPORT_WITH_NUMBER(identifier, PCUT_ITEM_COUNTER)
+
+/** Import test cases from a different file.
+ *
+ * @param identifier Identifier of the tests to import.
+ * (previously exported with PCUT_EXPORT).
+ */
+#define PCUT_IMPORT(identifier) \
+	PCUT_IMPORT_WITH_NUMBER(identifier, PCUT_ITEM_COUNTER)
+
+
+
+
+
+/*
+ * PCUT initialization and invocation macros
+ * -----------------------------------------
+ */
+
+/** @cond devel */
+
+/** Initialize the PCUT testing framework with a first item.
+ *
+ * @param first_number Number of the first item.
+ */
+#define PCUT_INIT_WITH_NUMBER(first_number) \
+	PCUT_ITEM_COUNTER_INCREMENT \
+	static pcut_item_t PCUT_ITEM_NAME(first_number) = { \
+		.previous = NULL, \
+		.next = NULL, \
+		.id = -1, \
+		.kind = PCUT_KIND_SKIP \
+	}; \
+	PCUT_TEST_SUITE(Default);
+
+int pcut_main(pcut_item_t *last, int argc, char *argv[]);
+
+/** Insert code to run all the tests.
+ *
+ * @param number Item number.
+ */
+#define PCUT_MAIN_WITH_NUMBER(number) \
+	PCUT_ITEM_COUNTER_INCREMENT \
+	static pcut_item_t pcut_item_last = { \
+		.previous = &PCUT_ITEM_NAME_PREV(number), \
+		.kind = PCUT_KIND_SKIP \
+	}; \
+	int main(int argc, char *argv[]) { \
+		return pcut_main(&pcut_item_last, argc, argv); \
+	}
+
+/** @endcond */
+
+/** Initialize the PCUT testing framework. */
+#define PCUT_INIT \
+	PCUT_INIT_WITH_NUMBER(PCUT_ITEM_COUNTER)
+
+/** Insert code to run all the tests. */
+#define PCUT_MAIN() \
+	PCUT_MAIN_WITH_NUMBER(PCUT_ITEM_COUNTER)
+
+
+/**
+ * @}
+ */
+
+#endif
