Skip to content

Commit 01d72f8

Browse files
committed
feat(test): Initial implementation
1 parent 023facc commit 01d72f8

17 files changed

Lines changed: 491 additions & 0 deletions

CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ project(YAVL
44
VERSION 0.1.0
55
LANGUAGES C
66
)
7+
set(YAVL_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
8+
79
include(GNUInstallDirs)
810
include(CMakePackageConfigHelpers)
11+
include(CTest)
912

1013
find_package(Doxygen OPTIONAL_COMPONENTS doxygen)
1114

@@ -142,6 +145,10 @@ foreach(header "${${PROJECT_NAME}_GEN_HEADERS}")
142145
)
143146
endforeach()
144147

148+
# Tests
149+
# =====
150+
add_subdirectory("test/")
151+
145152
# Arch PKGBUILD
146153
# =============
147154
configure_file(

test/CMakeLists.txt

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
cmake_minimum_required(VERSION 4.2)
2+
set(OLD_PROJECT_NAME "${PROJECT_NAME}")
3+
project("${OLD_PROJECT_NAME}Tests" C CXX)
4+
5+
# Collect tests
6+
file(GLOB_RECURSE "${OLD_PROJECT_NAME}_TESTS"
7+
LIST_DIRECTORIES false
8+
CONFIGURE_DEPENDS
9+
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
10+
**/*.c
11+
)
12+
13+
list(JOIN "${OLD_PROJECT_NAME}_TESTS" " " testrunner_str)
14+
create_test_sourcelist(
15+
"${OLD_PROJECT_NAME}_TEST_SRC"
16+
TestRunner.c
17+
${${OLD_PROJECT_NAME}_TESTS}
18+
)
19+
20+
# Additional libraries
21+
add_subdirectory("lib/")
22+
23+
add_executable("${OLD_PROJECT_NAME}TestRunner" TestRunner.c ${${OLD_PROJECT_NAME}_TEST_SRC})
24+
add_executable("${OLD_PROJECT_NAME}::TestRunner" ALIAS "${OLD_PROJECT_NAME}TestRunner")
25+
add_executable("${PROJECT_NAME}::Runner" ALIAS "${OLD_PROJECT_NAME}TestRunner")
26+
target_link_libraries("${OLD_PROJECT_NAME}TestRunner" PRIVATE "${OLD_PROJECT_NAME}" "${PROJECT_NAME}RefLib")
27+
target_include_directories("${OLD_PROJECT_NAME}TestRunner" PRIVATE "include/")
28+
set_target_properties("${OLD_PROJECT_NAME}TestRunner" PROPERTIES
29+
CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/test")
30+
31+
foreach(test IN LISTS "${OLD_PROJECT_NAME}_TESTS")
32+
get_filename_component(TName "${test}" NAME_WE)
33+
get_filename_component(TPath "${test}" DIRECTORY)
34+
string(REPLACE "/" "->" TNamespace "${TPath}")
35+
string(REPLACE "/" ";" TLabels "${TPath}")
36+
string(REGEX MATCH "^should(_not)?" TKind "${TName}")
37+
add_test(
38+
NAME "${TNamespace}.${TName}"
39+
COMMAND "${OLD_PROJECT_NAME}TestRunner" "${TPath}/${TName}"
40+
)
41+
if(TKind STREQUAL "should_not")
42+
set_property(
43+
TEST
44+
"${TNamespace}.${TName}"
45+
PROPERTY
46+
WILL_FAIL true
47+
)
48+
endif()
49+
set_property(
50+
TEST
51+
"${TNamespace}.${TName}"
52+
PROPERTY
53+
SKIP_RETURN_CODE 2
54+
)
55+
set_property(
56+
TEST
57+
"${TNamespace}.${TName}"
58+
PROPERTY
59+
LABELS ${TLabels}
60+
)
61+
endforeach()

test/include/TestRunner.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#include "TestRunner/prefix.h"
2+
#include "TestRunner/fun.h"
3+
#include "TestRunner/res.h"

test/include/TestRunner/fun.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// Macros
2+
#define is(S) (code = code || !(S))
3+
#define test_if(S) if((code = code || !(S)))
4+
#define countof(A) (sizeof(A)/sizeof(A[0]))

test/include/TestRunner/prefix.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#ifdef PREFIX
2+
3+
// Macro backups
4+
#pragma push_macro("vec_api")
5+
#pragma push_macro("vec_perf")
6+
7+
// Map names to numbers
8+
#define vec_api 1L
9+
#define vec_perf 2L
10+
11+
// Compare macro to macro by name
12+
#if PREFIX == vec_api
13+
#define PRIVATE_DEP_should(T,K) vec_api##K##T
14+
#elif PREFIX == vec_perf
15+
#define PRIVATE_DEP_should(T,K) vec_perf##K##T
16+
#else /* PREFIX == vec_api */
17+
#error Unhandled PREFIX case
18+
#endif /* PREFIX == vec_api */
19+
20+
// Macro restore
21+
#undef vec_perf
22+
#undef vec_api
23+
#pragma pop_macro("vec_perf")
24+
#pragma pop_macro("vec_api")
25+
26+
// Static macros
27+
#define it_should(T) int PRIVATE_DEP_should(T,_should_)(int argc,char** argv)
28+
#define it_should_not(T) int PRIVATE_DEP_should(T,_should_not_)(int argc,char** argv)
29+
#define _tostr(...) #__VA_ARGS__
30+
#define tostr(...) _tostr(__VA_ARGS__)
31+
#define todo(...) { _Pragma(_tostr(message("Unimplemented test case: " #__VA_ARGS__))) return 2; }
32+
#define it_todo(T) int PRIVATE_DEP_should(T,_should_)(int argc,char** argv) todo
33+
#undef PREFIX
34+
#endif

test/include/TestRunner/res.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#pragma once
2+
#ifndef TESTRUNNER_H
3+
#define TESTRUNNER_H
4+
// Shared resources across tests
5+
static char A[] = {1,2,3,4};
6+
static char B[] = {5,6,7,8,9,10};
7+
#endif

test/lib/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
add_subdirectory("cppvec")
2+
#add_subdirectory("bench") #TODO!

test/lib/cppvec/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
add_library("${PROJECT_NAME}RefLib" STATIC src/lib.cpp)
2+
add_library("${PROJECT_NAME}::RefLib" ALIAS "${PROJECT_NAME}RefLib")
3+
target_include_directories("${PROJECT_NAME}RefLib" PUBLIC "include/")

test/lib/cppvec/include/RefLib.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#ifdef __cplusplus
2+
#include <vector>
3+
extern "C" {
4+
#define cpp_vector(T,...) std::vector<T __VA_OPT__(,) __VA_ARGS__>
5+
#else
6+
#define cpp_vector(T,...) struct vector_##T
7+
/// Type definition
8+
cpp_vector(char);
9+
#endif
10+
#include <stddef.h>
11+
#include <stdbool.h>
12+
// C++ API maps
13+
cpp_vector(char) *const cpp_vec_new();
14+
void cpp_vec_free(cpp_vector(char) *const vec);
15+
void cpp_vec_push(cpp_vector(char) *const vec, const char data);
16+
char cpp_vec_pop(cpp_vector(char) *const vec, const char data);
17+
char* cpp_vec_ref(cpp_vector(char) *const vec, size_t idx);
18+
size_t cpp_vec_get_len(cpp_vector(char) *const vec);
19+
size_t cpp_vec_get_reservd(cpp_vector(char) *const vec);
20+
size_t cpp_vec_get_reservd_max(cpp_vector(char) *const vec);
21+
void cpp_vec_set_reservd(cpp_vector(char) *const vec, size_t new_reservd);
22+
char cpp_vec_get_el(cpp_vector(char) *const vec, size_t idx);
23+
char cpp_vec_set_el(cpp_vector(char) *const vec, size_t idx, char v);
24+
#ifdef __cplusplus
25+
}
26+
#endif

test/lib/cppvec/src/lib.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include <RefLib.h>
2+
3+
// Bindings for C++ std::vec to C.
4+
5+
extern "C" {
6+
cpp_vector(char) *const cpp_vec_new() {
7+
return new cpp_vector(char);
8+
}
9+
void cpp_vec_free(cpp_vector(char) *const vec) {
10+
delete vec;
11+
}
12+
void cpp_vec_push(cpp_vector(char) *const vec, const char data) {
13+
vec->push_back(data);
14+
}
15+
char cpp_vec_pop(cpp_vector(char) *const vec, const char data) {
16+
char last = vec->back();
17+
vec->pop_back();
18+
return last;
19+
}
20+
char* cpp_vec_ref(cpp_vector(char) *const vec, size_t idx) {
21+
return vec->data()+idx;
22+
}
23+
size_t cpp_vec_get_len(cpp_vector(char) *const vec) {
24+
return vec->size();
25+
}
26+
size_t cpp_vec_get_reservd(cpp_vector(char) *const vec) {
27+
return vec->capacity();
28+
}
29+
size_t cpp_vec_get_reservd_max(cpp_vector(char) *const vec) {
30+
return vec->max_size();
31+
}
32+
void cpp_vec_set_reservd(cpp_vector(char) *const vec, size_t new_reservd) {
33+
vec->reserve(new_reservd);
34+
}
35+
char cpp_vec_get_el(cpp_vector(char) *const vec, size_t idx) {
36+
return (*vec)[idx];
37+
}
38+
char cpp_vec_set_el(cpp_vector(char) *const vec, size_t idx, char v) {
39+
return (*vec)[idx] = v;
40+
}
41+
}

0 commit comments

Comments
 (0)