diff --git a/src/test/unit/CMakeLists.txt b/src/test/unit/CMakeLists.txt new file mode 100755 index 0000000..443b9aa --- /dev/null +++ b/src/test/unit/CMakeLists.txt @@ -0,0 +1,16 @@ +CMAKE_MINIMUM_REQUIRED (VERSION 2.6) +SET(CMAKE_VERBOSE_MAKEFILE ON) + +set(CMAKE_LEGACY_CYGWIN_WIN32 0) # Remove when CMake >= 2.8.4 is required + +PROJECT("runtest") + +SET(CMAKE_C_FLAGS " -std=c99 -O3 -Wall -Wextra -Wimplicit -L../../libs/") + +INCLUDE_DIRECTORIES ( "/usr/include" ) +ADD_EXECUTABLE(runtests main.c utils.c panic.c) +#TARGET_LINK_LIBRARIES(runtests kern ) +TARGET_LINK_LIBRARIES(runtests cunit dl ) + +ADD_CUSTOM_TARGET(test "./runtests" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" VERBATIM) +ADD_SUBDIRECTORY(suites) diff --git a/src/test/unit/clean.sh b/src/test/unit/clean.sh new file mode 100755 index 0000000..fd0b741 --- /dev/null +++ b/src/test/unit/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +rm -rf CMakeFiles +rm -rf suites/CMakeFiles +rm -f cmake_install.cmake CMakeCache.txt Makefile +rm -f suites/cmake_install.cmake suites/CMakeCache.txt suites/Makefile +rm -f suites/*.dll suites/*.so runtests.exe runtests diff --git a/src/test/unit/credist.txt b/src/test/unit/credist.txt new file mode 100755 index 0000000..a928e20 --- /dev/null +++ b/src/test/unit/credist.txt @@ -0,0 +1,2 @@ +All this test env is taken from article at http://habrahabr.ru/post/123344/#habracut +Thanx to autor (a_dobkin)! diff --git a/src/test/unit/main.c b/src/test/unit/main.c new file mode 100755 index 0000000..81f30f3 --- /dev/null +++ b/src/test/unit/main.c @@ -0,0 +1,154 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" + +int modules_alphasort(const char **a, const char **b) { + return strcoll(*a, *b); +} + +void (*runSuite)( void); + +/* Функция поиска динамических модулей */ +size_t searchModulesInDir( char ***m_list, char *dir ) { + DIR *modules_dir = NULL; + struct dirent *ent = NULL; + size_t count = 0; + char **modules_list = NULL; + char *error = NULL; + void *mem_module = NULL; + void *module_handle = NULL; + unsigned int allocated_mem = 0; + + errno = 0; + + if( !dir ) { + return -1; + } + + modules_dir = opendir( dir ); + + if( !modules_dir ) { + fprintf( stderr, "%s: %s\n", dir, strerror(errno)); + return -1; + } + + while( ( ent = readdir( modules_dir ) ) ) { + if( strncmp( ent->d_name, ".", 1 ) == 0 || + ( (strstr( ent->d_name, ".so" ) == NULL) && (strstr( ent->d_name, ".dll" ) == NULL) ) + ) { + continue; + } + + size_t mem_len = ( strlen( ent->d_name ) + strlen( dir ) ) * sizeof( char ) + 2; + char *module_path = malloc( mem_len ); + memset(module_path, 0, mem_len); + + if( !module_path ) { + fprintf( stderr, "%s\n", strerror(errno) ); + return -1; + } + + strncat( module_path, dir, strlen( dir ) * sizeof( char ) ); + strncat( module_path, "/", 1 ); + strncat( module_path, ent->d_name, strlen( ent->d_name ) * sizeof( char ) ); + + module_handle = dlopen ( module_path, RTLD_LAZY ); + + if( !module_handle ) { + fprintf( stderr, "Could not load module: '%s'\n", dlerror()); + free( module_path ); + continue; + } + + dlerror(); + runSuite= dlsym( module_handle, "runSuite" ); + error = dlerror(); + if( error ) { + fprintf( stderr, "Could not load module: %s\n", error); + dlclose( module_handle ); + free( module_path ); + continue; + } + + mem_module = realloc( modules_list, allocated_mem + strlen(module_path)); + allocated_mem += strlen(module_path); + + if( !mem_module ) { + fprintf( stderr, "%s\n", strerror(errno)); + free( module_path ); + dlclose( module_handle ); + return -1; + } + + modules_list = mem_module; + modules_list[ count ] = module_path; + count++; + dlclose( module_handle ); + } + + closedir( modules_dir ); + qsort(modules_list, count, sizeof(char *), (int (*)(const void *, const void *))modules_alphasort); + *m_list = modules_list; + + return count; +} + +int main() { + char *modules_dir = NULL; + char *env_modules_dir = NULL; + struct stat dir_info; + size_t modules_total = 0; + char **modules = NULL; + size_t i = 0; + void *module_handle = NULL; + + env_modules_dir = getenv( "TEST_SUITES_DIR" ); + modules_dir = ( env_modules_dir ) ? env_modules_dir : "./suites"; + + if( stat( modules_dir, &dir_info ) < 0 ) { + fprintf( stderr, "%s: %s\n", modules_dir, strerror(errno)); + return 1; + } + + if( !S_ISDIR( dir_info.st_mode ) ) { + fprintf( stderr, "'%s' is not a directory\n", modules_dir); + return 1; + } + + if( access( modules_dir, R_OK | X_OK ) != 0 ) { + fprintf( stderr, "Directory '%s' is not accessible\n", modules_dir ); + return 1; + } + + modules_total = searchModulesInDir( &modules, modules_dir); + if(modules_total <= 0) { + fprintf( stderr, "No test suites\n"); + return 0; + } + + CUnitInitialize(); + + for( i = 0; i < modules_total; i++ ) { + module_handle = dlopen ( modules[i], RTLD_LAZY ); + if( !module_handle ) { + fprintf( stderr, "Module '%s'\n", dlerror()); + continue; + } + + runSuite = dlsym( module_handle, "runSuite" ); + runSuite(); + } + + CU_basic_set_mode(CU_BRM_VERBOSE); + CU_basic_run_tests(); + CUnitUInitialize(); + return CU_get_error(); +} diff --git a/src/test/unit/panic.c b/src/test/unit/panic.c new file mode 100755 index 0000000..a3485c3 --- /dev/null +++ b/src/test/unit/panic.c @@ -0,0 +1,18 @@ + +#include +#include +#include + + + +void pod_panic(const char *fmt, ...) +{ + + printf("Panic: "); + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + + exit(33); +} + diff --git a/src/test/unit/prepare.sh b/src/test/unit/prepare.sh new file mode 100755 index 0000000..26b01a2 --- /dev/null +++ b/src/test/unit/prepare.sh @@ -0,0 +1,2 @@ +#!/bin/sh +cmake . diff --git a/src/test/unit/suites/CMakeLists.txt b/src/test/unit/suites/CMakeLists.txt new file mode 100755 index 0000000..971741a --- /dev/null +++ b/src/test/unit/suites/CMakeLists.txt @@ -0,0 +1,24 @@ +MACRO(ADD_MODULE file) + ADD_LIBRARY( ${file} MODULE ${file}.c ../utils.c ../panic.c ) +# TARGET_LINK_LIBRARIES( ${file} cunit kern phantom win ) + TARGET_LINK_LIBRARIES( ${file} cunit ) + SET_TARGET_PROPERTIES( ${file} PROPERTIES + PREFIX "" + LIBRARY_OUTPUT_DIRECTORY "." + ) +ENDMACRO(ADD_MODULE file) + +FILE(GLOB C_FILES RELATIVE "${CMAKE_SOURCE_DIR}/suites" "${CMAKE_SOURCE_DIR}/suites/*.c") + +INCLUDE_DIRECTORIES ( "${CMAKE_SOURCE_DIR}" ) +INCLUDE_DIRECTORIES ( "../../../include" "../../../include/ia32" ) + + +SET(CMAKE_C_FLAGS " -std=c99 -O3 -Wall -Wextra -Wimplicit -I ../../openpod -L../../libs/") + + +FOREACH ( module ${C_FILES} ) + STRING( REGEX REPLACE ".c$" "" module "${module}" ) + MESSAGE(STATUS "Found test suite: ${module}") + ADD_MODULE(${module}) +ENDFOREACH ( module ${MODULES} ) diff --git a/src/test/unit/suites/suite_skeleton.c b/src/test/unit/suites/suite_skeleton.c new file mode 100755 index 0000000..e4632e3 --- /dev/null +++ b/src/test/unit/suites/suite_skeleton.c @@ -0,0 +1,30 @@ +#if 1 +#include +#include +#include + +#include "utils.h" + +TEST_FUNCT(foo) { + //printf("test case 1\n"); + /* Фейковый код */ + CU_ASSERT_EQUAL(0, 0); +} +TEST_FUNCT(foo2) { + //printf("test case 2\n"); + /* Фейковый код */ + CU_ASSERT_EQUAL(1, 1); +} + +void runSuite(void) { + /* Код тест-сьюта */ + + //printf("test suite\n"); + + CU_pSuite suite = CUnitCreateSuite("Suite1"); + if (suite) { + ADD_SUITE_TEST(suite, foo) + ADD_SUITE_TEST(suite, foo2) + } +} +#endif diff --git a/src/test/unit/test.sh b/src/test/unit/test.sh new file mode 100755 index 0000000..3812a2f --- /dev/null +++ b/src/test/unit/test.sh @@ -0,0 +1,3 @@ +#!/bin/sh +make +./runtests diff --git a/src/test/unit/utils.c b/src/test/unit/utils.c new file mode 100755 index 0000000..c50966c --- /dev/null +++ b/src/test/unit/utils.c @@ -0,0 +1,53 @@ +#include +#include +#include +#include +#include + +#include "utils.h" + +void CUnitUInitialize(void) +{ + CU_cleanup_registry(); +} + +void CUnitInitialize(void) +{ + if (CU_initialize_registry() != CUE_SUCCESS) { + //fprintf(stderr, "Failed to initialize the CUnit registry: %d\n", CU_get_error()); + printf( "Failed to initialize the CUnit registry: %d\n", CU_get_error() ); + exit(1); + } +} + +static int initSuite(void) { + return 0; +} + +static int cleanSuite(void) { + return 0; +} + +CU_pSuite CUnitCreateSuite(const char* title) +{ + CU_pSuite suite = NULL; + suite = CU_add_suite(title, initSuite, cleanSuite); + if (suite == NULL) { + CU_cleanup_registry(); + return NULL; + } + + return suite; +} + +/* +//void test_fail(int rc); // Call from any test to return to test runner and signal failure +//void test_fail_msg(int rc, const char *msg); // Call from any test to return to test runner and signal failure + +int hal_mutex_init( void *a, const char *b ) { (void) a; (void) b; } +int hal_mutex_lock( void *a ) { (void) a; } +int hal_mutex_unlock( void *a ) { (void) a; } +int hal_mutex_is_locked( void *a ) { (void) a; return 1; } + +int debug_max_level_error = 10; +*/ diff --git a/src/test/unit/utils.h b/src/test/unit/utils.h new file mode 100755 index 0000000..20656ca --- /dev/null +++ b/src/test/unit/utils.h @@ -0,0 +1,48 @@ +#ifndef __UTILS_H__ +#define __UTILS_H__ + +#include +#include +#include + +#define TEST_FUNCT(name) \ + static void test_##name() + +#define ADD_SUITE_TEST(suite, name) \ + if ((NULL == CU_add_test(suite, #name, (CU_TestFunc)test_##name))) {\ + CU_cleanup_registry();\ + return;\ + }\ + +CU_pSuite CUnitCreateSuite(const char* title); +void CUnitInitialize(void); +void CUnitUInitialize(void); + + +//#include + +//void test_fail(int rc); // Call from any test to return to test runner and signal failure +//void test_fail_msg(int rc, const char *msg); // Call from any test to return to test runner and signal failure + +//#define test_check_true(expr) if( !expr ) test_fail_msg( -1, #expr " is not true at " __XSTRING( __LINE__ ) ); +//#define test_check_false(expr) if( expr ) test_fail_msg( -1, #expr " is not false at " __XSTRING( __LINE__ ) ); + +//#define test_check_eq(expr, val) if( expr != val ) test_fail_msg( -1, #expr " != " #val " at " __XSTRING( __LINE__ ) ); +//#define test_check_ne(expr, val) if( expr == val ) test_fail_msg( -1, #expr " == " #val " at " __XSTRING( __LINE__ ) ); +//#define test_check_gt(expr, val) if( expr <= val ) test_fail_msg( -1, #expr " <= " #val " at " __XSTRING( __LINE__ ) ); +//#define test_check_ge(expr, val) if( expr < val ) test_fail_msg( -1, #expr " < " #val " at " __XSTRING( __LINE__ ) ); + +#define test_check_true(expr) CU_ASSERT_TRUE(expr) +#define test_check_false(expr) CU_ASSERT_FALSE(expr) + +#define test_check_eq(expr, val) CU_ASSERT_EQUAL(expr, val) +#define test_check_ne(expr, val) CU_ASSERT_NOT_EQUAL(expr, val) + + +#define test_check_gt(expr, val) if( expr <= val ) CU_FAIL( #expr " <= " #val ); +#define test_check_ge(expr, val) if( expr < val ) CU_FAIL( #expr " < " #val ); + +#define SHOW_FLOW0( lev, msg ) printf( msg "\n" ) +#define SHOW_INFO0( lev, msg ) printf( msg "\n" ) + +#endif