Compare commits
2 Commits
537d1ca908
...
629435626e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
629435626e | ||
|
|
8b1e56a25d |
@ -35,10 +35,10 @@ steps:
|
|||||||
- name: Run tests
|
- name: Run tests
|
||||||
image: registry.riba-interactive.de/alpine-build:1
|
image: registry.riba-interactive.de/alpine-build:1
|
||||||
commands:
|
commands:
|
||||||
- cmake -S. -Bbuild
|
- cmake -S. -Bcmake-build-ci -DCMAKE_BUILD_TYPE=Debug -DENABLE_TEST_COVERAGE=on
|
||||||
- cd build
|
- cd cmake-build-ci
|
||||||
- cmake --build .
|
- cmake --build .
|
||||||
- ctest
|
- ctest -T Test -T Coverage
|
||||||
|
|
||||||
trigger:
|
trigger:
|
||||||
branch:
|
branch:
|
||||||
|
|||||||
@ -13,9 +13,14 @@ set(CMAKE_C_STANDARD 17)
|
|||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
|
option(ENABLE_TEST_COVERAGE "Enable test coverage" OFF)
|
||||||
|
|
||||||
if (CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
if (CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
||||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
if (ENABLE_TEST_COVERAGE)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -fprofile-arcs -ftest-coverage")
|
||||||
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
add_subdirectory(app)
|
add_subdirectory(app)
|
||||||
@ -24,5 +29,9 @@ add_subdirectory(library/log)
|
|||||||
|
|
||||||
if ((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR MODERN_CMAKE_BUILD_TESTING)
|
if ((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR MODERN_CMAKE_BUILD_TESTING)
|
||||||
AND BUILD_TESTING)
|
AND BUILD_TESTING)
|
||||||
|
configure_file(
|
||||||
|
${CMAKE_SOURCE_DIR}/CTestCustom.cmake
|
||||||
|
${CMAKE_BINARY_DIR}/CTestCustom.cmake COPYONLY
|
||||||
|
)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif ()
|
endif ()
|
||||||
|
|||||||
1
CTestCustom.cmake
Normal file
1
CTestCustom.cmake
Normal file
@ -0,0 +1 @@
|
|||||||
|
set(CTEST_CUSTOM_COVERAGE_EXCLUDE tests/)
|
||||||
@ -1 +1,13 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.21 FATAL_ERROR)
|
||||||
|
|
||||||
|
include("project-meta-info.in")
|
||||||
|
|
||||||
|
project(waitui-tests
|
||||||
|
VERSION ${project_version}
|
||||||
|
DESCRIPTION ${project_description}
|
||||||
|
HOMEPAGE_URL ${project_homepage}
|
||||||
|
LANGUAGES C)
|
||||||
|
|
||||||
|
#option(ENABLE_TEST_COVERAGE "Enable test coverage" ON)
|
||||||
|
|
||||||
add_subdirectory(library/list)
|
add_subdirectory(library/list)
|
||||||
164
tests/bdd-for-c-ext.h
Normal file
164
tests/bdd-for-c-ext.h
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
//
|
||||||
|
// Created by Rick Barenthin on 09.02.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef WAITUI_BDD_FOR_C_EXT_H
|
||||||
|
#define WAITUI_BDD_FOR_C_EXT_H
|
||||||
|
|
||||||
|
#include "bdd-for-c.h"
|
||||||
|
|
||||||
|
#define __BDD_EXT_1ST_PARAM_FMT__ "'%s'"
|
||||||
|
#define __BDD_EXT_OTHER_PARAM_FMT__ ", '%s'"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the format based on the count passed.
|
||||||
|
* @param num The number of format string parameters
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static inline char *__bdd_ext_build_format__(int num) {
|
||||||
|
size_t length = (sizeof(__BDD_EXT_1ST_PARAM_FMT__) - 1) +
|
||||||
|
(num - 1) * (sizeof(__BDD_EXT_OTHER_PARAM_FMT__) - 1) + 1;
|
||||||
|
char *fmt = calloc(length, sizeof(*fmt));
|
||||||
|
if (!fmt) {
|
||||||
|
perror("calloc(__bdd_ext_build_format__)");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < num; i++) {
|
||||||
|
if (i != 0) {
|
||||||
|
strcat(fmt, __BDD_EXT_OTHER_PARAM_FMT__);
|
||||||
|
} else {
|
||||||
|
strcat(fmt, __BDD_EXT_1ST_PARAM_FMT__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a format string from a test description and format parameters.
|
||||||
|
*
|
||||||
|
* @param description The description of the test case
|
||||||
|
* @param num The number of format string parameters
|
||||||
|
* @param ... The format string parameters a comma
|
||||||
|
* separated arguments
|
||||||
|
* @return The created format string
|
||||||
|
*/
|
||||||
|
static inline char *__bdd_ext_format_string_params__(const char *description,
|
||||||
|
int num, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_list copy;
|
||||||
|
|
||||||
|
int length = 1;
|
||||||
|
int written = 0;
|
||||||
|
char *fmt_string = NULL;
|
||||||
|
char *fmt = __bdd_ext_build_format__(num);
|
||||||
|
|
||||||
|
va_start(args, num);
|
||||||
|
va_copy(copy, args);
|
||||||
|
length += snprintf(NULL, 0, "%s [", description);
|
||||||
|
length += vsnprintf(NULL, 0, fmt, copy);
|
||||||
|
length += snprintf(NULL, 0, "]");
|
||||||
|
fmt_string = calloc(length, sizeof(*fmt_string));
|
||||||
|
if (!fmt_string) {
|
||||||
|
perror("calloc(__bdd_ext_format_string_params__)");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
va_end(copy);
|
||||||
|
written += snprintf(fmt_string, length, "%s [", description);
|
||||||
|
written += vsnprintf(fmt_string + written, length - written, fmt, args);
|
||||||
|
written += snprintf(fmt_string + written, length - written, "]");
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
free(fmt);
|
||||||
|
|
||||||
|
return fmt_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an array of `#test_param` structs.
|
||||||
|
*
|
||||||
|
* @note This macro must be used for passing test parameters to `for_it()`.
|
||||||
|
* @example: test_params({"input", "expected"}, {"input1", "expected1"})
|
||||||
|
*/
|
||||||
|
#define test_params(...) \
|
||||||
|
{ __VA_ARGS__ }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define arguments for a format string as one macro argument.
|
||||||
|
*
|
||||||
|
* @note This macro must be used for passing test parameters to `for_it()`.
|
||||||
|
* @example: format_args(STR_FMT(&string), STR_FMT(&string1));
|
||||||
|
*/
|
||||||
|
#define format_args(...) __VA_ARGS__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define arguments for a format string as one macro argument.
|
||||||
|
*
|
||||||
|
* The first argument must be the number of format string parameters.
|
||||||
|
*
|
||||||
|
* @example: params_format(1, "%s", "%d");
|
||||||
|
*/
|
||||||
|
#define params_format(...) __VA_ARGS__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a parametrized test case.
|
||||||
|
*
|
||||||
|
* Each test parameter results in an isolated test case which is
|
||||||
|
* executed independently and has its own output showing the test
|
||||||
|
* description followed by the given test parameters.
|
||||||
|
*
|
||||||
|
* @note: The given test parameters can be accessed by `#test_param`.
|
||||||
|
* @note: You must call `for_it_end()` after the test code to free
|
||||||
|
* allocated memory.
|
||||||
|
*
|
||||||
|
* @example: for_it("returns 1 and sets claim on existing claim",
|
||||||
|
* params_format(2, "%s", "%d"),
|
||||||
|
* format_args(test_param.input, test_param.expected),
|
||||||
|
* { char *input; int expected; },
|
||||||
|
* test_params(
|
||||||
|
* {"test input 1", 0},
|
||||||
|
* {"test input 2", 1},
|
||||||
|
* {"test input 4", 2},
|
||||||
|
* {"test input 5", 3}
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
*
|
||||||
|
* @param description: The description of the test
|
||||||
|
* @param params_format: A format string for printing the parameters
|
||||||
|
* of a test. Use `params_format()` macro for
|
||||||
|
* format creation.
|
||||||
|
* @param format_args: The arguments for the parameter format. Use
|
||||||
|
* `format_args()` macro for arguments creation.
|
||||||
|
* @param param_struct_body: The struct to be created holding the test
|
||||||
|
* parameters.
|
||||||
|
* @param params: The test parameters to be used
|
||||||
|
*/
|
||||||
|
#define for_it(description, params_format, format_args, param_struct_body, \
|
||||||
|
params) \
|
||||||
|
do { \
|
||||||
|
struct __bdd_ext_test_param__ param_struct_body \
|
||||||
|
__bdd_ext_test_params__[] = params; \
|
||||||
|
int __bdd_ext_input_size__ = sizeof(__bdd_ext_test_params__) / \
|
||||||
|
sizeof(__bdd_ext_test_params__[0]); \
|
||||||
|
for (int __bdd_ext_i__ = 0; __bdd_ext_i__ < __bdd_ext_input_size__; \
|
||||||
|
__bdd_ext_i__++) { \
|
||||||
|
struct __bdd_ext_test_param__ test_param = \
|
||||||
|
__bdd_ext_test_params__[__bdd_ext_i__]; \
|
||||||
|
char *__bdd_ext_param_format_string__ = \
|
||||||
|
__bdd_ext_format_string_params__(description, \
|
||||||
|
params_format); \
|
||||||
|
it(__bdd_ext_param_format_string__, format_args) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* End a parametrized test and free all resources allocated in #for_it.
|
||||||
|
*/
|
||||||
|
#define for_it_end() \
|
||||||
|
} \
|
||||||
|
free(__bdd_ext_param_format_string__); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
#endif//WAITUI_BDD_FOR_C_EXT_H
|
||||||
@ -664,7 +664,7 @@ for(\
|
|||||||
|
|
||||||
#define __BDD_CHECK_ONE__(condition) __BDD_CHECK__(condition, #condition)
|
#define __BDD_CHECK_ONE__(condition) __BDD_CHECK__(condition, #condition)
|
||||||
|
|
||||||
#define check(...) __BDD_MACRO__(__BDD_CHECK_, __VA_ARGS__)
|
#define check(...) do { __BDD_MACRO__(__BDD_CHECK_, __VA_ARGS__) } while (0)
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|||||||
@ -7,5 +7,9 @@ target_sources(waitui-test_list
|
|||||||
|
|
||||||
target_link_libraries(waitui-test_list PRIVATE list)
|
target_link_libraries(waitui-test_list PRIVATE list)
|
||||||
|
|
||||||
add_test(waitui-test_list waitui-test_list)
|
add_test(NAME waitui-test_list COMMAND waitui-test_list)
|
||||||
set_tests_properties(waitui-test_list PROPERTIES ENVIRONMENT "BDD_USE_TAP=1")
|
|
||||||
|
#if(ENABLE_TEST_COVERAGE)
|
||||||
|
# target_compile_options(list PUBLIC -O0 -g -fprofile-arcs -ftest-coverage)
|
||||||
|
# target_link_options(list PUBLIC -fprofile-arcs -ftest-coverage)
|
||||||
|
#endif()
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include "waitui/list.h"
|
#include "waitui/list.h"
|
||||||
|
|
||||||
#include "../../bdd-for-c.h"
|
#include "../../bdd-for-c-ext.h"
|
||||||
|
|
||||||
typedef struct value {
|
typedef struct value {
|
||||||
int count;
|
int count;
|
||||||
@ -31,54 +31,49 @@ CREATE_LIST_TYPE(INTERFACE, value)
|
|||||||
CREATE_LIST_TYPE(IMPLEMENTATION, value)
|
CREATE_LIST_TYPE(IMPLEMENTATION, value)
|
||||||
|
|
||||||
spec("list") {
|
spec("list") {
|
||||||
context("use as a stack") {
|
context("use as a normal list") {
|
||||||
static value_list *stack = NULL;
|
static value_list *list = NULL;
|
||||||
|
|
||||||
before() { stack = value_list_new(); }
|
before_each() {
|
||||||
|
list = value_list_new();
|
||||||
after() { value_list_destroy(&stack); }
|
check(list != NULL, "list should not be NULL");
|
||||||
|
|
||||||
it("should have a stack") {
|
|
||||||
check(stack != NULL, "stack should not be NULL");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
it("should allow to push a value onto the stack") {
|
after_each() {
|
||||||
value *value1 = value_new(1);
|
value_list_destroy(&list);
|
||||||
check(value1 != NULL, "value1 should not be NULL");
|
check(list == NULL, "list should be NULL");
|
||||||
check(value_list_push(stack, value1) == true,
|
|
||||||
"value1 should be added to the stack");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
it("should allow to push a second value onto the stack") {
|
describe("value_list_push()") {
|
||||||
value *value2 = value_new(2);
|
for_it(
|
||||||
check(value2 != NULL, "value2 should not be NULL");
|
"should push values onto the end list and it should be there",
|
||||||
check(value_list_push(stack, value2) == true,
|
params_format(2, "start: %d", "elements: %d"),
|
||||||
"value1 should be added to the stack");
|
format_args(test_param.start, test_param.count),
|
||||||
|
{
|
||||||
|
int start;
|
||||||
|
int count;
|
||||||
|
},
|
||||||
|
test_params(
|
||||||
|
{0, 0},
|
||||||
|
{0, 1},
|
||||||
|
{1, 1},
|
||||||
|
{4, 20},
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
for (int i = test_param.start; i < test_param.start + test_param.count; ++i) {
|
||||||
|
check(value_list_push(list, value_new(i)) == 1);
|
||||||
|
value *value = value_list_peek(list);
|
||||||
|
check(value->i == i, "value should be %d but is %d", i, value->i);
|
||||||
}
|
}
|
||||||
|
|
||||||
it("should return the last added element on pop") {
|
for (int i = test_param.start + test_param.count - 1; i >= test_param.start; --i) {
|
||||||
value *test = value_list_pop(stack);
|
value *value = value_list_pop(list);
|
||||||
check(test != NULL, "value_list_pop should not return NULL");
|
check(value != NULL, "value should not be NULL");
|
||||||
check(test->i == 2, "test should be 2");
|
check(value->i == i, "value should be %d but is %d", i, value->i);
|
||||||
value_destroy(&test);
|
value_destroy(&value);
|
||||||
}
|
}
|
||||||
|
|
||||||
it("should be able to peek the top element") {
|
|
||||||
value *test = value_list_peek(stack);
|
|
||||||
check(test != NULL, "value_list_peek should not return NULL");
|
|
||||||
check(test->i == 1, "test should be 1");
|
|
||||||
}
|
}
|
||||||
|
for_it_end();
|
||||||
it("should return the first added element on pop") {
|
|
||||||
value *test = value_list_pop(stack);
|
|
||||||
check(test != NULL, "value_list_pop should not return NULL");
|
|
||||||
check(test->i == 1, "test should be 1");
|
|
||||||
value_destroy(&test);
|
|
||||||
}
|
|
||||||
|
|
||||||
it("should return NULL if peek with an empty stack") {
|
|
||||||
value *test = value_list_peek(stack);
|
|
||||||
check(test == NULL, "value_list_peek should return NULL");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
3
tests/project-meta-info.in
Normal file
3
tests/project-meta-info.in
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
set(project_version 0.0.1)
|
||||||
|
set(project_description "waitui language system tests")
|
||||||
|
set(project_homepage "http://example.com")
|
||||||
Loading…
Reference in New Issue
Block a user