From e40d52c55013cf7368b46a7d05342d70ca8904ec Mon Sep 17 00:00:00 2001 From: Joakim Soderberg Date: Wed, 27 Feb 2013 18:54:26 +0100 Subject: [PATCH] Consolidated the CMake project. - Moved everything to one CMakeLists.txt - Added support for the json_process test suites (instead of just the API tests). - Changed to use the modified json_process version that does away with the environment variables (originally written by DanielT). - Had to exclude "test_memory_funcs" on MSVC, since void pointer arithmetics are not allowed as it is done in secure_malloc and secure_free. - Had to add a check for "ssize_t". This is not available on Windows and maybe on some other platforms (used in test_pack.c) - Result from running ctest (The failure seems unrelated to CMake, it's just that the expected result is in a different order): 99% tests passed, 1 tests failed out of 121 Total Test time (real) = 1.31 sec The following tests FAILED: 24 - valid__complex-array (Failed) --- CMakeLists.txt | 116 ++++++++++++++++- config.h.cmake | 6 + src/CMakeLists.txt | 23 ---- test/bin/json_process.c | 227 ++++++++++++++++++++++----------- test/suites/api/CMakeLists.txt | 31 ----- test/suites/api/test_pack.c | 6 + 6 files changed, 273 insertions(+), 136 deletions(-) delete mode 100644 src/CMakeLists.txt delete mode 100644 test/suites/api/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 07aab7c..1a85933 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,11 @@ project (jansson C) # Options OPTION (BUILD_SHARED_LIBS "Build shared libraries." OFF) +# Set some nicer output dirs. +SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) +SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) +SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) + # This is how I thought it should go # set (JANSSON_VERSION "2.3.1") # set (JANSSON_SOVERSION 2) @@ -56,6 +61,10 @@ include (CheckFunctionKeywords) include (CheckIncludeFiles) include (CheckTypeSize) +# Turn off Microsofts "security" warnings. +if (MSVC) + add_definitions( "/W3 /D_CRT_SECURE_NO_WARNINGS /wd4005 /wd4996 /nologo" ) +endif() # Check for the int-type includes check_include_files (sys/types.h HAVE_SYS_TYPES_H) @@ -86,9 +95,17 @@ else () message (FATAL_ERROR "Could not detect a valid 32 bit integer type") endif () -# Check if we have int32_t, if not then we will use long (in config.h.cmake) -check_type_size (int32_t INT32_T) - +# Check for ssize_t and SSIZE_T existance. +check_type_size(ssize_t SSIZE_T) +check_type_size(SSIZE_T UPPERCASE_SSIZE_T) +if(NOT HAVE_SSIZE_T) + if(HAVE_UPPERCASE_SSIZE_T) + set(JSON_SSIZE SSIZE_T) + else() + set(JSON_SSIZE int) + endif() +endif() +set(CMAKE_EXTRA_INCLUDE_FILES "") # Check for all the variants of strtoll check_function_exists (strtoll HAVE_STRTOLL) @@ -207,7 +224,31 @@ add_definitions (-DHAVE_CONFIG_H) include_directories (${CMAKE_CURRENT_BINARY_DIR}/include) include_directories (${CMAKE_CURRENT_BINARY_DIR}/private_include) -add_subdirectory (src) +# Add the lib sources. +file (GLOB C_FILES src/*.c) + +if (BUILD_SHARED_LIBS) + + add_library (jansson SHARED ${C_FILES} jansson.def) + + set_target_properties (jansson PROPERTIES + VERSION ${JANSSON_VERSION} + SOVERSION ${JANSSON_SOVERSION}) + +else () + + add_library (jansson ${C_FILES}) + +endif () + +# LIBRARY for linux +# RUNTIME for windows (when building shared) +install (TARGETS jansson + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin +) + install (FILES ${CMAKE_CURRENT_BINARY_DIR}/include/jansson_config.h DESTINATION include) install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/jansson.h DESTINATION include) @@ -263,14 +304,75 @@ if (BUILD_TESTS) ENABLE_TESTING() if (TEST_WITH_VALGRIND) + # TODO: Add FindValgrind.cmake instead of having a hardcoded path. + # enable valgrind - set (CMAKE_MEMORYCHECK_COMMAND /usr/bin/valgrind) - set (CMAKE_MEMORYCHECK_COMMAND_OPTIONS "--leak-check=full --show-reachable=yes --track-origins=yes -q") + set(CMAKE_MEMORYCHECK_COMMAND /usr/bin/valgrind) + set(CMAKE_MEMORYCHECK_COMMAND_OPTIONS "--leak-check=full --show-reachable=yes --track-origins=yes -q") set(MEMCHECK_COMMAND "${CMAKE_MEMORYCHECK_COMMAND} ${CMAKE_MEMORYCHECK_COMMAND_OPTIONS}") separate_arguments(MEMCHECK_COMMAND) endif () - add_subdirectory (test/suites/api) + # + # Test suites. + # + if (CMAKE_COMPILER_IS_GNUCC) + add_definitions(-Wall -Wextra -Wdeclaration-after-statement -Werror) + endif() + + set(api_tests + test_array + test_copy + test_dump + test_dump_callback + test_equal + test_load + test_loadb + test_number + test_object + test_pack + test_simple + test_unpack) + + # Doing arithmetic on void pointers is not allowed by Microsofts compiler + # such as secure_malloc and secure_free is doing, so exclude it for now. + if (NOT MSVC) + list(APPEND api_tests test_memory_funcs) + endif() + + # Helper macro for building and linking a test program. + macro(build_testprog name dir) + add_executable(${name} EXCLUDE_FROM_ALL ${dir}/${name}.c) + add_dependencies(${name} jansson) + target_link_libraries(${name} jansson) + endmacro(build_testprog) + + # Create executables and tests/valgrind tests for API tests. + foreach (test ${api_tests}) + build_testprog(${test} ${PROJECT_SOURCE_DIR}/test/suites/api) + add_test(${test} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${test}) + + if (TEST_WITH_VALGRIND) + add_test(memcheck_${test} ${MEMCHECK_COMMAND} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${test}) + endif() + endforeach() + + # Test harness for the suites tests. + build_testprog(json_process ${PROJECT_SOURCE_DIR}/test/bin) + + set(SUITES encoding-flags valid invalid invalid-unicode) + foreach (SUITE ${SUITES}) + file(GLOB TESTDIRS ${jansson_SOURCE_DIR}/test/suites/${SUITE}/*) + foreach (TESTDIR ${TESTDIRS}) + if (IS_DIRECTORY ${TESTDIR}) + get_filename_component(TNAME ${TESTDIR} NAME) + add_test(${SUITE}__${TNAME} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/json_process ${TESTDIR}) + endif() + endforeach() + endforeach () + + add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} + DEPENDS ${api_tests} json_process) endif () diff --git a/config.h.cmake b/config.h.cmake index 6f854ec..8347d8b 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -30,6 +30,12 @@ # define int32_t @JSON_INT32@ #endif +#cmakedefine HAVE_SSIZE_T 1 + +#ifndef HAVE_SSIZE_T +# define ssize_t @JSON_SSIZE@ +#endif + #ifndef HAVE_SNPRINTF # define snprintf @JSON_SNPRINTF@ #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index 8ac6bce..0000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -file (GLOB C_FILES *.c) - -if (BUILD_SHARED_LIBS) - - add_library (jansson SHARED ${C_FILES} jansson.def) - - set_target_properties (jansson PROPERTIES - VERSION ${JANSSON_VERSION} - SOVERSION ${JANSSON_SOVERSION}) - -else () - - add_library (jansson ${C_FILES}) - -endif () - -# LIBRARY for linux -# RUNTIME for windows (when building shared) -install (TARGETS jansson - ARCHIVE DESTINATION lib - LIBRARY DESTINATION lib - RUNTIME DESTINATION bin -) diff --git a/test/bin/json_process.c b/test/bin/json_process.c index 637dfd5..72c4833 100644 --- a/test/bin/json_process.c +++ b/test/bin/json_process.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2012 Petri Lehtinen + * Copyright (c) 2009-2013 Petri Lehtinen * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -15,33 +15,31 @@ #include #include -#if HAVE_LOCALE_H +#ifdef HAVE_LOCALE_H #include -#endif + #endif #if _WIN32 #include /* for _setmode() */ #include /* for _O_BINARY */ + +static const char dir_sep = '\\'; +#else +static const char dir_sep = '/'; #endif + +struct config { + int indent; + int compact; + int preserve_order; + int ensure_ascii; + int sort_keys; + int strip; +} conf; + #define l_isspace(c) ((c) == ' ' || (c) == '\n' || (c) == '\r' || (c) == '\t') -static int getenv_int(const char *name) -{ - char *value, *end; - long result; - - value = getenv(name); - if(!value) - return 0; - - result = strtol(value, &end, 10); - if(*end != '\0') - return 0; - - return (int)result; -} - /* Return a pointer to the first non-whitespace character of str. Modifies str so that all trailing whitespace characters are replaced by '\0'. */ @@ -49,102 +47,181 @@ static const char *strip(char *str) { size_t length; char *result = str; - while(*result && l_isspace(*result)) + while (*result && l_isspace(*result)) result++; length = strlen(result); - if(length == 0) + if (length == 0) return result; - while(l_isspace(result[length - 1])) + while (l_isspace(result[length - 1])) result[--length] = '\0'; return result; } + +static char *loadfile(FILE *file) +{ + long fsize, ret; + char *buf; + + fseek(file, 0, SEEK_END); + fsize = ftell(file); + fseek(file, 0, SEEK_SET); + + buf = malloc(fsize+1); + ret = fread(buf, 1, fsize, file); + if (ret != fsize) + exit(1); + buf[fsize] = '\0'; + + return buf; +} + + +static void read_conf(FILE *conffile) +{ + char *buffer, *line, *val; + + buffer = loadfile(conffile); + line = strtok(buffer, "\r\n"); + while (line) { + val = strchr(line, '='); + if (!val) { + printf("invalid configuration line\n"); + break; + } + *val++ = '\0'; + + if (!strcmp(line, "JSON_INDENT")) + conf.indent = atoi(val); + if (!strcmp(line, "JSON_COMPACT")) + conf.compact = atoi(val); + if (!strcmp(line, "JSON_ENSURE_ASCII")) + conf.ensure_ascii = atoi(val); + if (!strcmp(line, "JSON_PRESERVE_ORDER")) + conf.preserve_order = atoi(val); + if (!strcmp(line, "JSON_SORT_KEYS")) + conf.sort_keys = atoi(val); + if (!strcmp(line, "STRIP")) + conf.strip = atoi(val); + + line = strtok(NULL, "\r\n"); + } + + free(buffer); +} + + +static int cmpfile(const char *str, const char *path, const char *fname) +{ + char filename[1024], *buffer; + int ret; + FILE *file; + + sprintf(filename, "%s%c%s", path, dir_sep, fname); + file = fopen(filename, "rb"); + if (!file) { + if (conf.strip) + strcat(filename, ".strip"); + else + strcat(filename, ".normal"); + file = fopen(filename, "rb"); + } + if (!file) { + printf("Error: test result file could not be opened.\n"); + exit(1); + } + + buffer = loadfile(file); + if (strcmp(buffer, str) != 0) + ret = 1; + else + ret = 0; + free(buffer); + fclose(file); + + return ret; +} + + int main(int argc, char *argv[]) { - int indent = 0; + int ret; size_t flags = 0; - + char filename[1024], errstr[1024]; + char *buffer; + FILE *infile, *conffile; json_t *json; json_error_t error; -#if HAVE_SETLOCALE + #ifdef HAVE_SETLOCALE setlocale(LC_ALL, ""); -#endif + #endif - if(argc != 1) { - fprintf(stderr, "usage: %s\n", argv[0]); + if (argc != 2) { + fprintf(stderr, "usage: %s test_dir\n", argv[0]); + return 2; + } + + sprintf(filename, "%s%cinput", argv[1], dir_sep); + if (!(infile = fopen(filename, "rb"))) { + fprintf(stderr, "Could not open \"%s\"\n", filename); + return 2; + } + + sprintf(filename, "%s%cenv", argv[1], dir_sep); + conffile = fopen(filename, "rb"); + if (conffile) { + read_conf(conffile); + fclose(conffile); + } + + if (conf.indent < 0 || conf.indent > 255) { + fprintf(stderr, "invalid value for JSON_INDENT: %d\n", conf.indent); return 2; } -#ifdef _WIN32 - /* On Windows, set stdout and stderr to binary mode to avoid - outputting DOS line terminators */ - _setmode(_fileno(stdout), _O_BINARY); - _setmode(_fileno(stderr), _O_BINARY); -#endif + if (conf.indent) + flags |= JSON_INDENT(conf.indent); - indent = getenv_int("JSON_INDENT"); - if(indent < 0 || indent > 255) { - fprintf(stderr, "invalid value for JSON_INDENT: %d\n", indent); - return 2; - } - - if(indent > 0) - flags |= JSON_INDENT(indent); - - if(getenv_int("JSON_COMPACT") > 0) + if (conf.compact) flags |= JSON_COMPACT; - if(getenv_int("JSON_ENSURE_ASCII")) + if (conf.ensure_ascii) flags |= JSON_ENSURE_ASCII; - if(getenv_int("JSON_PRESERVE_ORDER")) + if (conf.preserve_order) flags |= JSON_PRESERVE_ORDER; - if(getenv_int("JSON_SORT_KEYS")) + if (conf.sort_keys) flags |= JSON_SORT_KEYS; - if(getenv_int("STRIP")) { + if (conf.strip) { /* Load to memory, strip leading and trailing whitespace */ - size_t size = 0, used = 0; - char *buffer = NULL; - - while(1) { - size_t count; - - size = (size == 0 ? 128 : size * 2); - buffer = realloc(buffer, size); - if(!buffer) { - fprintf(stderr, "Unable to allocate %d bytes\n", (int)size); - return 1; - } - - count = fread(buffer + used, 1, size - used, stdin); - if(count < size - used) { - buffer[used + count] = '\0'; - break; - } - used += count; - } - + buffer = loadfile(infile); json = json_loads(strip(buffer), 0, &error); free(buffer); } else - json = json_loadf(stdin, 0, &error); + json = json_loadf(infile, 0, &error); - if(!json) { - fprintf(stderr, "%d %d %d\n%s\n", + fclose(infile); + + if (!json) { + sprintf(errstr, "%d %d %d\n%s\n", error.line, error.column, error.position, error.text); - return 1; + + ret = cmpfile(errstr, argv[1], "error"); + return ret; } - json_dumpf(json, stdout, flags); + buffer = json_dumps(json, flags); + ret = cmpfile(buffer, argv[1], "output"); + free(buffer); json_decref(json); - return 0; + return ret; } diff --git a/test/suites/api/CMakeLists.txt b/test/suites/api/CMakeLists.txt deleted file mode 100644 index a94d59e..0000000 --- a/test/suites/api/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -set (tests - test_array - test_copy - test_dump - test_dump_callback - test_equal - test_load - test_loadb - test_memory_funcs - test_number - test_object - test_pack - test_simple - test_unpack) - -foreach (test ${tests}) - add_executable (${test} ${test}.c) - target_link_libraries (${test} jansson) -endforeach() - -# batch plain tests -foreach (test ${tests}) - add_test (${test} ${CMAKE_CURRENT_BINARY_DIR}/${test}) -endforeach() - -# batch valgrind tests -if (TEST_WITH_VALGRIND) - foreach (test ${tests}) - add_test (memcheck_${test} ${MEMCHECK_COMMAND} ${CMAKE_CURRENT_BINARY_DIR}/${test}) - endforeach() -endif () diff --git a/test/suites/api/test_pack.c b/test/suites/api/test_pack.c index c7e7251..44aa8aa 100644 --- a/test/suites/api/test_pack.c +++ b/test/suites/api/test_pack.c @@ -6,6 +6,12 @@ * it under the terms of the MIT license. See LICENSE for details. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + #include #include #include