mirror of
https://github.com/swaywm/sway.git
synced 2024-11-25 09:21:28 +00:00
Add memory test utilities
This commit is contained in:
parent
698ba55860
commit
e563bec64d
|
@ -5,8 +5,6 @@ function(configure_test)
|
||||||
set(oneValueArgs NAME SUBPROJECT)
|
set(oneValueArgs NAME SUBPROJECT)
|
||||||
set(multiValueArgs WRAPPERS SOURCES INCLUDES LIBRARIES)
|
set(multiValueArgs WRAPPERS SOURCES INCLUDES LIBRARIES)
|
||||||
cmake_parse_arguments(CONFIGURE_TEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
cmake_parse_arguments(CONFIGURE_TEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||||
message("${CONFIGURE_TEST_SOURCES}")
|
|
||||||
message("${CONFIGURE_TEST_WRAPPERS}")
|
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${CMOCKA_INCLUDE_DIR}
|
${CMOCKA_INCLUDE_DIR}
|
||||||
|
@ -19,7 +17,12 @@ function(configure_test)
|
||||||
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test/${CONFIGURE_TEST_SUBPROJECT}/${CONFIGURE_TEST_NAME}
|
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test/${CONFIGURE_TEST_SUBPROJECT}/${CONFIGURE_TEST_NAME}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(${CONFIGURE_TEST_NAME}_test ${CONFIGURE_TEST_SOURCES})
|
add_executable(${CONFIGURE_TEST_NAME}_test
|
||||||
|
${CMAKE_SOURCE_DIR}/test/util.c
|
||||||
|
${CONFIGURE_TEST_SOURCES}
|
||||||
|
)
|
||||||
|
|
||||||
|
list(APPEND CONFIGURE_TEST_WRAPPERS "malloc" "calloc" "realloc" "free")
|
||||||
|
|
||||||
list(LENGTH CONFIGURE_TEST_WRAPPERS WRAPPED_COUNT)
|
list(LENGTH CONFIGURE_TEST_WRAPPERS WRAPPED_COUNT)
|
||||||
|
|
||||||
|
@ -32,7 +35,6 @@ function(configure_test)
|
||||||
"${WRAPPED} \
|
"${WRAPPED} \
|
||||||
-Wl,--wrap=${WRAPPER}"
|
-Wl,--wrap=${WRAPPER}"
|
||||||
)
|
)
|
||||||
message("${WRAPPER}, ${WRAPPED}")
|
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
set_target_properties(${CONFIGURE_TEST_NAME}_test
|
set_target_properties(${CONFIGURE_TEST_NAME}_test
|
||||||
|
@ -42,4 +44,6 @@ function(configure_test)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(${CONFIGURE_TEST_NAME}_test ${CMOCKA_LIBRARIES} ${CONFIGURE_TEST_LIBRARIES})
|
target_link_libraries(${CONFIGURE_TEST_NAME}_test ${CMOCKA_LIBRARIES} ${CONFIGURE_TEST_LIBRARIES})
|
||||||
|
|
||||||
|
set(test_targets ${test_targets} ${CONFIGURE_TEST_NAME}_test PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
|
@ -24,6 +24,39 @@ branch. Instead, when you start working on a feature, do this:
|
||||||
4. git push -u origin add-so-and-so-feature
|
4. git push -u origin add-so-and-so-feature
|
||||||
5. Make pull request from your feature branch
|
5. Make pull request from your feature branch
|
||||||
|
|
||||||
|
## Writing Tests
|
||||||
|
|
||||||
|
Tests are driven by [CMocka](https://cmocka.org/). When testing a given
|
||||||
|
function, we can "mock" out the functions it relies on to program their behavior
|
||||||
|
explicitly and test the function in isolation. The directory layout of `test/`
|
||||||
|
is identical to the global directory layout, but each C file in the parent tree
|
||||||
|
has its own directory in the test tree, with its own CMakeLists.txt that wires
|
||||||
|
things up. To add a test, make the appropriate directory in `test/` and add a
|
||||||
|
CMakeLists.txt that looks something like this made-up example:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
configure_test(
|
||||||
|
SUBPROJECT swaymsg
|
||||||
|
NAME main
|
||||||
|
SOURCES
|
||||||
|
${PROJECT_SOURCE_DIR}/swaymsg/main.c
|
||||||
|
swaymsg.c
|
||||||
|
WRAPPERS
|
||||||
|
ipc_open_socket
|
||||||
|
LIBRARIES
|
||||||
|
${WLC_LIBRARIES}
|
||||||
|
INCLUDES
|
||||||
|
${WLC_INCLUDES}
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
This defines a test suite in the swaymsg subproject that tests main. This file
|
||||||
|
would live at `test/swaymsg/main/CMakeLists.txt`. It specifies that it requires
|
||||||
|
`swaymsg/main.c` and `test/swaymsg/main/swaymsg.c`, the former being the actual
|
||||||
|
swaymsg source and the latter being the test suite. It mocks ipc_open_socket and
|
||||||
|
links against openssl. See the cmocka documentation or read existing tests to
|
||||||
|
learn more about how mocks work.
|
||||||
|
|
||||||
## Coding Style
|
## Coding Style
|
||||||
|
|
||||||
Sway is written in C. The style guidelines is [kernel
|
Sway is written in C. The style guidelines is [kernel
|
||||||
|
|
|
@ -69,6 +69,11 @@ On systems without logind, you need to suid the sway binary:
|
||||||
|
|
||||||
sudo chmod a+s /usr/local/bin/sway
|
sudo chmod a+s /usr/local/bin/sway
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
Run `make && make check` from the build directory to run tests. The exit code
|
||||||
|
will be the number of failed tests (0 for success).
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
If you already use i3, then copy your i3 config to `~/.config/sway/config` and
|
If you already use i3, then copy your i3 config to `~/.config/sway/config` and
|
||||||
|
|
|
@ -6,4 +6,13 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <cmocka.h>
|
#include <cmocka.h>
|
||||||
|
|
||||||
|
enum wrapper_behavior {
|
||||||
|
WRAPPER_INVOKE_REAL,
|
||||||
|
WRAPPER_INVOKE_CMOCKA,
|
||||||
|
WRAPPER_DO_ASSERTIONS,
|
||||||
|
};
|
||||||
|
|
||||||
|
int reset_mem_wrappers(void **state);
|
||||||
|
void memory_behavior(enum wrapper_behavior behavior);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1 +1,7 @@
|
||||||
|
set(test_targets "")
|
||||||
|
|
||||||
add_subdirectory(common)
|
add_subdirectory(common)
|
||||||
|
|
||||||
|
add_custom_target(check
|
||||||
|
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
|
||||||
|
COMMAND ${CMAKE_SOURCE_DIR}/test/runner)
|
||||||
|
|
|
@ -5,15 +5,16 @@
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
|
||||||
static void test_test(void **state) {
|
static void test_create_list(void **state) {
|
||||||
|
memory_behavior(WRAPPER_INVOKE_CMOCKA);
|
||||||
list_t *list = create_list();
|
list_t *list = create_list();
|
||||||
free(list);
|
assert_int_equal(list->length, 0);
|
||||||
assert_true(true);
|
list_free(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main(int argc, char **argv) {
|
||||||
const struct CMUnitTest tests[] = {
|
const struct CMUnitTest tests[] = {
|
||||||
cmocka_unit_test(test_test),
|
cmocka_unit_test(test_create_list),
|
||||||
};
|
};
|
||||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
return cmocka_run_group_tests(tests, reset_mem_wrappers, NULL);
|
||||||
}
|
}
|
||||||
|
|
11
test/runner
Executable file
11
test/runner
Executable file
|
@ -0,0 +1,11 @@
|
||||||
|
#!/usr/bin/bash
|
||||||
|
tests=$(find . -type f -name "*_test")
|
||||||
|
ret=0
|
||||||
|
for test in $tests
|
||||||
|
do
|
||||||
|
printf 'Running %s\n' $(basename $test)
|
||||||
|
$test
|
||||||
|
ret+=$?
|
||||||
|
done
|
||||||
|
|
||||||
|
exit $ret
|
74
test/util.c
Normal file
74
test/util.c
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "tests.h"
|
||||||
|
|
||||||
|
void *__real_malloc(size_t size);
|
||||||
|
void __real_free(void *ptr);
|
||||||
|
void *__real_calloc(size_t nmemb, size_t size);
|
||||||
|
void *__real_realloc(void *ptr, size_t size);
|
||||||
|
|
||||||
|
enum wrapper_behavior _memory_behavior = WRAPPER_INVOKE_REAL;
|
||||||
|
|
||||||
|
int reset_mem_wrappers(void **state) {
|
||||||
|
_memory_behavior = WRAPPER_INVOKE_REAL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void memory_behavior(enum wrapper_behavior behavior) {
|
||||||
|
_memory_behavior = behavior;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *__wrap_malloc(size_t size) {
|
||||||
|
switch (_memory_behavior) {
|
||||||
|
case WRAPPER_INVOKE_CMOCKA:
|
||||||
|
return test_malloc(size);
|
||||||
|
case WRAPPER_DO_ASSERTIONS:
|
||||||
|
check_expected(size);
|
||||||
|
return mock_type(void *);
|
||||||
|
case WRAPPER_INVOKE_REAL:
|
||||||
|
default:
|
||||||
|
return __real_malloc(size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __wrap_free(void *ptr) {
|
||||||
|
switch (_memory_behavior) {
|
||||||
|
case WRAPPER_INVOKE_CMOCKA:
|
||||||
|
test_free(ptr);
|
||||||
|
break;
|
||||||
|
case WRAPPER_DO_ASSERTIONS:
|
||||||
|
check_expected_ptr(ptr);
|
||||||
|
break;
|
||||||
|
case WRAPPER_INVOKE_REAL:
|
||||||
|
default:
|
||||||
|
__real_free(ptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *__wrap_calloc(size_t nmemb, size_t size) {
|
||||||
|
switch (_memory_behavior) {
|
||||||
|
case WRAPPER_INVOKE_CMOCKA:
|
||||||
|
return test_calloc(nmemb, size);
|
||||||
|
case WRAPPER_DO_ASSERTIONS:
|
||||||
|
check_expected(nmemb);
|
||||||
|
check_expected(size);
|
||||||
|
return mock_type(void *);
|
||||||
|
case WRAPPER_INVOKE_REAL:
|
||||||
|
default:
|
||||||
|
return __real_calloc(nmemb, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *__wrap_realloc(void *ptr, size_t size) {
|
||||||
|
switch (_memory_behavior) {
|
||||||
|
case WRAPPER_INVOKE_CMOCKA:
|
||||||
|
return test_realloc(ptr, size);
|
||||||
|
case WRAPPER_DO_ASSERTIONS:
|
||||||
|
check_expected_ptr(ptr);
|
||||||
|
check_expected(size);
|
||||||
|
return mock_type(void *);
|
||||||
|
case WRAPPER_INVOKE_REAL:
|
||||||
|
default:
|
||||||
|
return __real_realloc(ptr, size);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue