mirror of
https://github.com/swaywm/sway.git
synced 2026-04-28 06:46:26 -04:00
Merge d47a9d7752 into 71f710cf0f
This commit is contained in:
commit
8ca1f50323
17 changed files with 618 additions and 5 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -7,7 +7,6 @@ install_manifest.txt
|
|||
*.o
|
||||
*.a
|
||||
bin/
|
||||
test/
|
||||
build/
|
||||
.lvimrc
|
||||
config-debug
|
||||
|
|
|
|||
|
|
@ -18,9 +18,11 @@ arch:
|
|||
- cairo
|
||||
- gdk-pixbuf2
|
||||
- wlc-git
|
||||
- cmocka
|
||||
script:
|
||||
- "cmake ."
|
||||
- "make"
|
||||
- "make check"
|
||||
|
||||
script:
|
||||
- "curl -s https://raw.githubusercontent.com/mikkeloscar/arch-travis/master/arch-travis.sh | bash"
|
||||
|
|
|
|||
66
CMake/FindCMocka.cmake
Normal file
66
CMake/FindCMocka.cmake
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
# - Try to find CMocka
|
||||
# Once done this will define
|
||||
#
|
||||
# CMOCKA_ROOT_DIR - Set this variable to the root installation of CMocka
|
||||
#
|
||||
# Read-Only variables:
|
||||
# CMOCKA_FOUND - system has CMocka
|
||||
# CMOCKA_INCLUDE_DIR - the CMocka include directory
|
||||
# CMOCKA_LIBRARIES - Link these to use CMocka
|
||||
# CMOCKA_DEFINITIONS - Compiler switches required for using CMocka
|
||||
#
|
||||
#=============================================================================
|
||||
# Copyright (c) 2011-2012 Andreas Schneider <asn@cryptomilk.org>
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
#
|
||||
|
||||
set(_CMOCKA_ROOT_HINTS
|
||||
)
|
||||
|
||||
set(_CMOCKA_ROOT_PATHS
|
||||
"$ENV{PROGRAMFILES}/cmocka"
|
||||
)
|
||||
|
||||
find_path(CMOCKA_ROOT_DIR
|
||||
NAMES
|
||||
include/cmocka.h
|
||||
HINTS
|
||||
${_CMOCKA_ROOT_HINTS}
|
||||
PATHS
|
||||
${_CMOCKA_ROOT_PATHS}
|
||||
)
|
||||
mark_as_advanced(CMOCKA_ROOT_DIR)
|
||||
|
||||
find_path(CMOCKA_INCLUDE_DIR
|
||||
NAMES
|
||||
cmocka.h
|
||||
PATHS
|
||||
${CMOCKA_ROOT_DIR}/include
|
||||
)
|
||||
|
||||
find_library(CMOCKA_LIBRARY
|
||||
NAMES
|
||||
cmocka
|
||||
PATHS
|
||||
${CMOCKA_ROOT_DIR}/lib
|
||||
)
|
||||
|
||||
if (CMOCKA_LIBRARY)
|
||||
set(CMOCKA_LIBRARIES
|
||||
${CMOCKA_LIBRARIES}
|
||||
${CMOCKA_LIBRARY}
|
||||
)
|
||||
endif (CMOCKA_LIBRARY)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(CMocka DEFAULT_MSG CMOCKA_LIBRARIES CMOCKA_INCLUDE_DIR)
|
||||
|
||||
# show the CMOCKA_INCLUDE_DIR and CMOCKA_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(CMOCKA_INCLUDE_DIR CMOCKA_LIBRARIES)
|
||||
53
CMake/Test.cmake
Normal file
53
CMake/Test.cmake
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
function(configure_test)
|
||||
set(options)
|
||||
set(oneValueArgs NAME SUBPROJECT)
|
||||
set(multiValueArgs WRAPPERS SOURCES INCLUDES LIBRARIES)
|
||||
cmake_parse_arguments(CONFIGURE_TEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
include_directories(
|
||||
${CMOCKA_INCLUDE_DIR}
|
||||
${CONFIGURE_TEST_INCLUDES}
|
||||
)
|
||||
add_definitions(${CMOCKA_DEFINITIONS})
|
||||
|
||||
set(
|
||||
CMAKE_RUNTIME_OUTPUT_DIRECTORY
|
||||
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test/${CONFIGURE_TEST_SUBPROJECT}/${CONFIGURE_TEST_NAME}
|
||||
)
|
||||
|
||||
add_executable(${CONFIGURE_TEST_NAME}_test
|
||||
${CMAKE_SOURCE_DIR}/test/util.c
|
||||
${CONFIGURE_TEST_SOURCES}
|
||||
)
|
||||
|
||||
list(APPEND CONFIGURE_TEST_WRAPPERS "malloc" "calloc" "realloc" "free")
|
||||
|
||||
if (enable-coverage)
|
||||
add_definitions(-g -O0 --coverage -fprofile-arcs -ftest-coverage)
|
||||
endif()
|
||||
|
||||
list(LENGTH CONFIGURE_TEST_WRAPPERS WRAPPED_COUNT)
|
||||
|
||||
if(NOT ${WRAPPED_COUNT} STREQUAL "0")
|
||||
set(WRAPPED "")
|
||||
|
||||
foreach(WRAPPER ${CONFIGURE_TEST_WRAPPERS})
|
||||
string(REGEX REPLACE "\\n" "" WRAPPER "${WRAPPER}")
|
||||
set(WRAPPED
|
||||
"${WRAPPED} \
|
||||
-Wl,--wrap=${WRAPPER}"
|
||||
)
|
||||
endforeach()
|
||||
|
||||
set_target_properties(${CONFIGURE_TEST_NAME}_test
|
||||
PROPERTIES
|
||||
LINK_FLAGS "${WRAPPED}"
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${CONFIGURE_TEST_NAME}_test ${CMOCKA_LIBRARIES} ${CONFIGURE_TEST_LIBRARIES})
|
||||
|
||||
if (enable-coverage)
|
||||
target_link_libraries(${CONFIGURE_TEST_NAME}_test gcov)
|
||||
endif()
|
||||
endfunction()
|
||||
|
|
@ -48,18 +48,20 @@ option(enable-gdk-pixbuf "Use Pixbuf to support more image formats" YES)
|
|||
option(enable-binding-event "Enables binding event subscription" YES)
|
||||
option(zsh-completions "Zsh shell completions" NO)
|
||||
option(default-wallpaper "Installs the default wallpaper" YES)
|
||||
option(enable-tests "Enables test suite" YES)
|
||||
option(enable-coverage "Enables test coverage" NO)
|
||||
|
||||
find_package(JsonC REQUIRED)
|
||||
find_package(PCRE REQUIRED)
|
||||
find_package(WLC REQUIRED)
|
||||
find_package(Wayland REQUIRED)
|
||||
find_package(XKBCommon REQUIRED)
|
||||
find_package(LibInput REQUIRED)
|
||||
find_package(Cairo REQUIRED)
|
||||
find_package(Pango REQUIRED)
|
||||
find_package(GdkPixbuf)
|
||||
find_package(PAM)
|
||||
|
||||
find_package(LibInput REQUIRED)
|
||||
find_package(CMocka)
|
||||
|
||||
find_package(Backtrace)
|
||||
if(Backtrace_FOUND)
|
||||
|
|
@ -71,6 +73,7 @@ endif()
|
|||
|
||||
include(FeatureSummary)
|
||||
include(Manpage)
|
||||
include(Test)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
if (enable-gdk-pixbuf)
|
||||
|
|
@ -130,6 +133,14 @@ install(
|
|||
COMPONENT data
|
||||
)
|
||||
|
||||
if(enable-tests)
|
||||
if (CMOCKA_FOUND)
|
||||
add_subdirectory(test)
|
||||
else()
|
||||
message(WARNING "Not building tests - cmocka is required.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(default-wallpaper)
|
||||
install(
|
||||
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/assets/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
## 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
|
||||
|
||||
If you already use i3, then copy your i3 config to `~/.config/sway/config` and
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ char *read_line(FILE *file) {
|
|||
return NULL;
|
||||
}
|
||||
while (1) {
|
||||
int c = getc(file);
|
||||
int c = fgetc(file);
|
||||
if (c == '\n' && lastChar == '\\'){
|
||||
--length; // Ignore last character.
|
||||
lastChar = '\0';
|
||||
|
|
@ -51,7 +51,7 @@ char *read_line_buffer(FILE *file, char *string, size_t string_len) {
|
|||
return NULL;
|
||||
}
|
||||
while (1) {
|
||||
int c = getc(file);
|
||||
int c = fgetc(file);
|
||||
if (c == EOF || c == '\n' || c == '\0') {
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
23
include/tests.h
Normal file
23
include/tests.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef __TESTS_H
|
||||
#define __TESTS_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdarg.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);
|
||||
int malloc_calls();
|
||||
int free_calls();
|
||||
int calloc_calls();
|
||||
int realloc_calls();
|
||||
int alloc_calls();
|
||||
|
||||
#endif
|
||||
22
test/CMakeLists.txt
Normal file
22
test/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
set(test_targets "")
|
||||
|
||||
add_subdirectory(common)
|
||||
|
||||
add_custom_target(check
|
||||
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/test/runner "${CMAKE_BINARY_DIR}")
|
||||
|
||||
if(enable-coverage)
|
||||
find_program(GCOV_PATH gcov)
|
||||
find_program(LCOV_PATH lcov)
|
||||
find_program(GENHTML_PATH genhtml)
|
||||
if(NOT GCOV_PATH)
|
||||
MESSAGE(FATAL_ERROR "gcov not found! Aborting...")
|
||||
endif()
|
||||
if(NOT LCOV_PATH)
|
||||
MESSAGE(FATAL_ERROR "lcov not found! Aborting...")
|
||||
endif()
|
||||
if(NOT GENHTML_PATH)
|
||||
MESSAGE(FATAL_ERROR "genhtml not found! Aborting...")
|
||||
endif()
|
||||
endif()
|
||||
2
test/common/CMakeLists.txt
Normal file
2
test/common/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
add_subdirectory(list)
|
||||
add_subdirectory(readline)
|
||||
7
test/common/list/CMakeLists.txt
Normal file
7
test/common/list/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
configure_test(
|
||||
SUBPROJECT common
|
||||
NAME list
|
||||
SOURCES
|
||||
${PROJECT_SOURCE_DIR}/common/list.c
|
||||
list.c
|
||||
)
|
||||
187
test/common/list/list.c
Normal file
187
test/common/list/list.c
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <stdlib.h>
|
||||
#include "tests.h"
|
||||
#include "list.h"
|
||||
|
||||
static void assert_list_contents(list_t *list, int contents[], size_t len) {
|
||||
assert_int_equal(list->length, (int)len);
|
||||
for (size_t i = 0; i < (size_t)list->length; ++i) {
|
||||
assert_int_equal(contents[i], *(int *)list->items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static list_t *create_test_list(int contents[], size_t len) {
|
||||
list_t *l = create_list();
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
list_add(l, &contents[i]);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
static void test_create_and_free(void **state) {
|
||||
list_t *list = create_list();
|
||||
assert_int_equal(list->length, 0);
|
||||
assert_int_equal(list->capacity, 10);
|
||||
assert_non_null(list->items);
|
||||
list_free(list);
|
||||
assert_int_equal(malloc_calls(), 2);
|
||||
assert_int_equal(free_calls(), 2);
|
||||
}
|
||||
|
||||
static void test_add(void **state) {
|
||||
list_t *list = create_list();
|
||||
|
||||
int items[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
|
||||
for (size_t i = 0; i < sizeof(items) / sizeof(int); ++i) {
|
||||
list_add(list, &items[i]);
|
||||
assert_int_equal(items[i], *(int *)list->items[i]);
|
||||
assert_int_equal(list->length, i + 1);
|
||||
}
|
||||
assert_list_contents(list, items, 15);
|
||||
assert_int_equal(list->length, 15);
|
||||
assert_int_equal(list->capacity, 20);
|
||||
assert_int_equal(realloc_calls(), 1);
|
||||
|
||||
list_free(list);
|
||||
}
|
||||
|
||||
static void test_insert(void **state) {
|
||||
list_t *list = create_list();
|
||||
int i = 1, j = 2;
|
||||
list_add(list, &i);
|
||||
list_add(list, &i);
|
||||
list_add(list, &i);
|
||||
list_insert(list, 0, &j);
|
||||
assert_int_equal(j, *(int *)list->items[0]);
|
||||
assert_int_equal(list->length, 4);
|
||||
list_free(list);
|
||||
}
|
||||
|
||||
static void test_del(void **state) {
|
||||
list_t *list = create_list();
|
||||
|
||||
int items[] = { 1, 2, 3, 4, 5 };
|
||||
int new_items[] = { 1, 2, 4, 5 };
|
||||
for (size_t i = 0; i < sizeof(items) / sizeof(int); ++i) {
|
||||
list_add(list, &items[i]);
|
||||
}
|
||||
|
||||
list_del(list, 2);
|
||||
assert_list_contents(list, new_items, 4);
|
||||
list_free(list);
|
||||
}
|
||||
|
||||
static void test_cat(void **state) {
|
||||
int items_a[] = { 1, 2, 3, 4 };
|
||||
int items_b[] = { 5, 6, 7, 8 };
|
||||
int items_final[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
|
||||
list_t *list_a = create_test_list(items_a, 4);
|
||||
list_t *list_b = create_test_list(items_b, 4);
|
||||
|
||||
list_cat(list_a, list_b);
|
||||
|
||||
assert_list_contents(list_a, items_final, 8);
|
||||
list_free(list_a);
|
||||
list_free(list_b);
|
||||
}
|
||||
|
||||
static int qsort_compare(const void *left, const void *right) {
|
||||
return **(int * const *)left - **(int * const *)right;
|
||||
}
|
||||
|
||||
static void test_qsort(void **state) {
|
||||
int items_start[] = { 1, 4, 3, 2 };
|
||||
int items_final[] = { 1, 2, 3, 4 };
|
||||
list_t *list = create_test_list(items_start, 4);
|
||||
list_qsort(list, qsort_compare);
|
||||
assert_list_contents(list, items_final, 4);
|
||||
list_free(list);
|
||||
}
|
||||
|
||||
static int find_compare(const void *a, const void *b) {
|
||||
return *(int *)a - *(int *)b;
|
||||
}
|
||||
|
||||
static void test_seq_find(void **state) {
|
||||
int items[] = { 1, 2, 3, 4 };
|
||||
int expected = 3;
|
||||
list_t *list = create_test_list(items, 4);
|
||||
int index = list_seq_find(list, find_compare, &expected);
|
||||
assert_int_equal(index, 2);
|
||||
list_free(list);
|
||||
}
|
||||
|
||||
int foreach_count = 0;
|
||||
|
||||
static void foreach(void *item) {
|
||||
foreach_count++;
|
||||
assert_int_equal(*(int *)item, foreach_count);
|
||||
}
|
||||
|
||||
static void test_foreach(void **state) {
|
||||
int items[] = { 1, 2, 3, 4 };
|
||||
list_t *list = create_test_list(items, 4);
|
||||
list_foreach(list, foreach);
|
||||
assert_int_equal(foreach_count, 4);
|
||||
list_free(list);
|
||||
}
|
||||
|
||||
struct stable_data {
|
||||
int id, value;
|
||||
};
|
||||
|
||||
static int stable_compare(const void *_a, const void *_b) {
|
||||
struct stable_data * const *a = _a;
|
||||
struct stable_data * const *b = _b;
|
||||
return (*a)->value - (*b)->value;
|
||||
}
|
||||
|
||||
static void test_stable_sort(void **state) {
|
||||
struct stable_data initial[] = {
|
||||
{ .id = 0, .value = 0 },
|
||||
{ .id = 3, .value = 2 },
|
||||
{ .id = 4, .value = 3 },
|
||||
{ .id = 1, .value = 1 },
|
||||
{ .id = 2, .value = 1 },
|
||||
{ .id = 5, .value = 4 },
|
||||
{ .id = 7, .value = 5 },
|
||||
{ .id = 6, .value = 5 },
|
||||
};
|
||||
struct stable_data expected[] = {
|
||||
{ .id = 0, .value = 0 },
|
||||
{ .id = 1, .value = 1 },
|
||||
{ .id = 2, .value = 1 },
|
||||
{ .id = 3, .value = 2 },
|
||||
{ .id = 4, .value = 3 },
|
||||
{ .id = 5, .value = 4 },
|
||||
{ .id = 7, .value = 5 },
|
||||
{ .id = 6, .value = 5 },
|
||||
};
|
||||
list_t *list = create_list();
|
||||
for (size_t i = 0; i < sizeof(initial) / sizeof(initial[0]); ++i) {
|
||||
list_add(list, &initial[i]);
|
||||
}
|
||||
list_stable_sort(list, stable_compare);
|
||||
for (size_t i = 0; i < sizeof(expected) / sizeof(expected[0]); ++i) {
|
||||
struct stable_data *item = list->items[i];
|
||||
assert_int_equal(item->value, expected[i].value);
|
||||
assert_int_equal(item->id, expected[i].id);
|
||||
}
|
||||
list_free(list);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(test_create_and_free),
|
||||
cmocka_unit_test(test_add),
|
||||
cmocka_unit_test(test_insert),
|
||||
cmocka_unit_test(test_del),
|
||||
cmocka_unit_test(test_cat),
|
||||
cmocka_unit_test(test_qsort),
|
||||
cmocka_unit_test(test_seq_find),
|
||||
cmocka_unit_test(test_foreach),
|
||||
cmocka_unit_test(test_stable_sort),
|
||||
};
|
||||
return cmocka_run_group_tests(tests, reset_mem_wrappers, NULL);
|
||||
}
|
||||
9
test/common/readline/CMakeLists.txt
Normal file
9
test/common/readline/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
configure_test(
|
||||
SUBPROJECT common
|
||||
NAME readline
|
||||
SOURCES
|
||||
${PROJECT_SOURCE_DIR}/common/readline.c
|
||||
readline.c
|
||||
WRAPPERS
|
||||
fgetc
|
||||
)
|
||||
61
test/common/readline/readline.c
Normal file
61
test/common/readline/readline.c
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "tests.h"
|
||||
#include "readline.h"
|
||||
|
||||
int __wrap_fgetc(FILE *stream) {
|
||||
return mock_type(int);
|
||||
}
|
||||
|
||||
static void prep_string(const char *str) {
|
||||
while (*str) {
|
||||
will_return(__wrap_fgetc, *str++);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_eof_line_ending(void **state) {
|
||||
prep_string("hello");
|
||||
will_return(__wrap_fgetc, EOF);
|
||||
char *line = read_line(NULL);
|
||||
assert_string_equal(line, "hello");
|
||||
free(line);
|
||||
}
|
||||
|
||||
static void test_newline(void **state) {
|
||||
prep_string("hello\n");
|
||||
char *line = read_line(NULL);
|
||||
assert_string_equal(line, "hello");
|
||||
free(line);
|
||||
}
|
||||
|
||||
static void test_continuation(void **state) {
|
||||
prep_string("hello \\\nworld");
|
||||
will_return(__wrap_fgetc, EOF);
|
||||
char *line = read_line(NULL);
|
||||
assert_string_equal(line, "hello world");
|
||||
free(line);
|
||||
}
|
||||
|
||||
static void test_expand_buffer(void **state) {
|
||||
const char *test = "This is a very very long string. "
|
||||
"This string is so long that it may in fact be greater "
|
||||
"than 128 bytes (or octets) in length, which is suitable "
|
||||
"for triggering a realloc";
|
||||
prep_string(test);
|
||||
will_return(__wrap_fgetc, EOF);
|
||||
char *line = read_line(NULL);
|
||||
assert_string_equal(line, test);
|
||||
free(line);
|
||||
assert_int_equal(realloc_calls(), 1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(test_eof_line_ending),
|
||||
cmocka_unit_test(test_newline),
|
||||
cmocka_unit_test(test_continuation),
|
||||
cmocka_unit_test(test_expand_buffer),
|
||||
};
|
||||
return cmocka_run_group_tests(tests, reset_mem_wrappers, NULL);
|
||||
}
|
||||
27
test/runner
Executable file
27
test/runner
Executable file
|
|
@ -0,0 +1,27 @@
|
|||
#!/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
|
||||
|
||||
if (( $ret == 0 ))
|
||||
then
|
||||
if grep 'enable-coverage:BOOL=YES' "$1/CMakeCache.txt" > /dev/null
|
||||
then
|
||||
echo "Generating coverage reports"
|
||||
rm -rf "$1/coverage"
|
||||
mkdir "$1/coverage"
|
||||
lcov --directory "$1" \
|
||||
--capture \
|
||||
--output-file "$1/coverage/lcov.info" > /dev/null
|
||||
lcov --remove "$1/coverage/lcov.info" 'test/*' '/usr/*' \
|
||||
--output-file "$1/coverage/lcov.info.clean" > /dev/null
|
||||
genhtml -o "$1/coverage/" "$1/coverage/lcov.info.clean"
|
||||
fi
|
||||
fi
|
||||
|
||||
exit $ret
|
||||
106
test/util.c
Normal file
106
test/util.c
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
#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_CMOCKA;
|
||||
int malloc_callcount = 0,
|
||||
free_callcount = 0,
|
||||
calloc_callcount = 0,
|
||||
realloc_callcount = 0;
|
||||
|
||||
int reset_mem_wrappers(void **state) {
|
||||
_memory_behavior = WRAPPER_INVOKE_CMOCKA;
|
||||
malloc_callcount =
|
||||
free_callcount =
|
||||
calloc_callcount =
|
||||
realloc_callcount = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void memory_behavior(enum wrapper_behavior behavior) {
|
||||
_memory_behavior = behavior;
|
||||
}
|
||||
|
||||
int malloc_calls() {
|
||||
return malloc_callcount;
|
||||
}
|
||||
|
||||
int free_calls() {
|
||||
return free_callcount;
|
||||
}
|
||||
|
||||
int calloc_calls() {
|
||||
return calloc_callcount;
|
||||
}
|
||||
|
||||
int realloc_calls() {
|
||||
return realloc_callcount;
|
||||
}
|
||||
|
||||
int alloc_calls() {
|
||||
return malloc_callcount + calloc_callcount;
|
||||
}
|
||||
|
||||
void *__wrap_malloc(size_t size) {
|
||||
++malloc_callcount;
|
||||
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) {
|
||||
++free_callcount;
|
||||
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) {
|
||||
++calloc_callcount;
|
||||
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) {
|
||||
++realloc_callcount;
|
||||
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…
Add table
Add a link
Reference in a new issue