changeset 31:57fb1b70b990

build: Enhance coverage and valgrind targets. By directly collecting the test executable names. Also increase coverage in src/base/str
author Lewin Bormann <lbo@spheniscida.de>
date Tue, 20 Aug 2019 19:47:46 +0200
parents 656efbd10859
children 53ae0f7d8aa1
files CMakeLists.txt coverage.sh src/CMakeLists.txt src/base/CMakeLists.txt src/base/str.c src/base/str.h src/base/str_test.c valgrind.sh
diffstat 8 files changed, 95 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Tue Aug 20 19:23:28 2019 +0200
+++ b/CMakeLists.txt	Tue Aug 20 19:47:46 2019 +0200
@@ -12,6 +12,14 @@
 ADD_COMPILE_OPTIONS(-g -O0)
 endif ()
 
+SET_PROPERTY(GLOBAL PROPERTY YALL_TESTS "")
+FUNCTION(YADD_TEST test_executable_name)
+    GET_PROPERTY(OLD_LIST GLOBAL PROPERTY YALL_TESTS)
+    SET_PROPERTY(GLOBAL PROPERTY YALL_TESTS "${OLD_LIST} ${CMAKE_CURRENT_BINARY_DIR}/${test_executable_name}")
+    ADD_TEST(NAME "${test_executable_name}_ctest" COMMAND "./${test_executable_name}")
+ENDFUNCTION(YADD_TEST)
+
+
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
 
@@ -29,7 +37,14 @@
     ADD_CUSTOM_TARGET(doxygen ALL COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} VERBATIM)
 endif ()
 
+GET_PROPERTY(ALL_TEST_EXECUTABLES GLOBAL PROPERTY YALL_TESTS)
 ADD_CUSTOM_TARGET(coverage
-    COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/coverage.sh ${YALL_TESTS}
+    COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/coverage.sh ${ALL_TEST_EXECUTABLES}
     WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
 )
+ADD_CUSTOM_TARGET(valgrind
+    COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/valgrind.sh ${ALL_TEST_EXECUTABLES}
+    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+MESSAGE("${ALL_TEST_EXECUTABLES}")
--- a/coverage.sh	Tue Aug 20 19:23:28 2019 +0200
+++ b/coverage.sh	Tue Aug 20 19:47:46 2019 +0200
@@ -1,5 +1,6 @@
 #!/bin/bash
 
+# Expects a list of test executables as arguments.
 # Run this from the build directory using `make coverage`.
 
 set -e
@@ -7,11 +8,12 @@
 KCOV="kcov"
 KCOV_ARGS="--exclude-pattern=/usr/src,/usr/include,/usr/lib,_test.c"
 
-TESTS=`find . -name \*_test -executable -and -not -type l`
-TESTS_BASENAME=`find . -name \*_test -and -executable -and -not -type l -exec /bin/basename {} \;`
+TESTS=$@
+TESTS_BASENAME=`basename -a $TESTS`
 
 for BINARY in $TESTS; do
     $KCOV $KCOV_ARGS . $BINARY
 done
 
 $KCOV --merge --report $KCOV_ARGS . $TESTS_BASENAME
+xdg-open kcov-merged/index.html
--- a/src/CMakeLists.txt	Tue Aug 20 19:23:28 2019 +0200
+++ b/src/CMakeLists.txt	Tue Aug 20 19:47:46 2019 +0200
@@ -14,4 +14,4 @@
 # Atom test.
 ADD_EXECUTABLE(atom_test atom_test.c)
 TARGET_LINK_LIBRARIES(atom_test core gcov)
-ADD_TEST(NAME atom_test_t COMMAND ./atom_test)
+YADD_TEST(atom_test)
--- a/src/base/CMakeLists.txt	Tue Aug 20 19:23:28 2019 +0200
+++ b/src/base/CMakeLists.txt	Tue Aug 20 19:47:46 2019 +0200
@@ -11,9 +11,9 @@
 # str test.
 ADD_EXECUTABLE(str_test str_test.c)
 TARGET_LINK_LIBRARIES(str_test base gcov)
-ADD_TEST(NAME str_test_t COMMAND ./str_test)
+YADD_TEST(str_test)
 
 # vec test.
 ADD_EXECUTABLE(vec_test vec_test.c)
 TARGET_LINK_LIBRARIES(vec_test base gcov)
-ADD_TEST(NAME vec_test_t COMMAND ./vec_test)
+YADD_TEST(vec_test)
--- a/src/base/str.c	Tue Aug 20 19:23:28 2019 +0200
+++ b/src/base/str.c	Tue Aug 20 19:47:46 2019 +0200
@@ -14,12 +14,11 @@
 
 void ystr_set_owned(ystr_t *s, char *src) {
     if (src == NULL) {
-        memset(s, 0, sizeof(ystr_t));
+        ystr_destroy(s);
         return;
     }
     // Free previous memory.
-    if (!ystr_is_inline(s))
-        ystr_destroy(s);
+    ystr_destroy(s);
     size_t len = strlen(src) + 1;
     s->inner.big.len = len;
     s->inner.big.cap = len;
@@ -29,9 +28,7 @@
 
 void ystr_set(ystr_t *s, const char *src) {
     if (src == NULL) {
-        if (!ystr_is_inline(s))
-            ystr_destroy(s);
-        memset(s, 0, sizeof(ystr_t));
+        ystr_destroy(s);
         return;
     }
     ystr_set_n(s, src, strlen(src));
@@ -171,7 +168,7 @@
     if (written >= YSTR_BUILD_BUF_SIZE) {
         char *buf2 = calloc(written + 1, sizeof(char));
         va_start(args, fmt);
-        vsnprintf(buf, written + 1, fmt, args);
+        vsnprintf(buf2, written + 1, fmt, args);
         va_end(args);
 
         ystr_t fmtd;
--- a/src/base/str.h	Tue Aug 20 19:23:28 2019 +0200
+++ b/src/base/str.h	Tue Aug 20 19:47:46 2019 +0200
@@ -108,7 +108,8 @@
 void ystr_resize(ystr_t *s, size_t new);
 
 /**
- * @brief Append a C string to string, with possible formatting directives.
+ * @brief Append a C string to string, with possible formatting directives like
+ * printf.
  */
 void ystr_build(ystr_t *s, const char *fmt, ...);
 
--- a/src/base/str_test.c	Tue Aug 20 19:23:28 2019 +0200
+++ b/src/base/str_test.c	Tue Aug 20 19:47:46 2019 +0200
@@ -18,7 +18,7 @@
     assert(5 == ystr_len(&str));
 
     ystr_set(&str2, "short, too");
-    assert(str.inner.big.size == 0); // is inline.
+    assert(str2.inner.big.size == 0);  // is inline.
 
     ystr_destroy(&str);
     ystr_destroy(&str2);
@@ -28,9 +28,18 @@
 void test_str_set_owned() {
     ystr_t str;
     ystr_init(&str, NULL);
-    char *s = strdup("Hello");
+
+    char* s = strdup("Hello");
     ystr_set_owned(&str, s);
     assert(s == ystr_str(&str));
+
+    ystr_set_owned(&str, NULL);
+    assert(0 == ystr_cmp_str(&str, ""));
+
+    ystr_set(&str, "a very long string that is not inlined");
+    char* owned = strdup("short but external");
+    ystr_set_owned(&str, owned);
+
     ystr_destroy(&str);
 }
 
@@ -39,6 +48,9 @@
     ystr_init(&str, "ab");
     ystr_init(&str2, "ab");
     assert(0 == ystr_cmp(&str, &str2));
+
+    ystr_set_n(&str, NULL, 0);
+    assert(0 == ystr_cmp_str(&str, ""));
 }
 
 void test_str_at() {
@@ -68,24 +80,53 @@
     ystr_init(&s2, "abcdefghijklmnop");
     ystr_init(&s3, "0123");
 
+    ystr_append(&s1, &s3);
+    assert(0 == ystr_cmp_str(&s1, "xyz0123"));
+
     ystr_append(&s1, &s2);
-    assert(0 == ystr_cmp_str(&s1, "xyzabcdefghijklmnop"));
+    assert(0 == ystr_cmp_str(&s1, "xyz0123abcdefghijklmnop"));
 
     ystr_append(&s1, &s3);
-    assert(0 == ystr_cmp_str(&s1, "xyzabcdefghijklmnop0123"));
+    assert(0 == ystr_cmp_str(&s1, "xyz0123abcdefghijklmnop0123"));
 
     ystr_append(&s1, &s3);
-    assert(0 == ystr_cmp_str(&s1, "xyzabcdefghijklmnop01230123"));
+    assert(0 == ystr_cmp_str(&s1, "xyz0123abcdefghijklmnop01230123"));
 
-    ystr_set(&s1, "xyz");
-    ystr_build(&s1, " hello %s %d", "world", 13);
-    assert(0 == ystr_cmp_str(&s1, "xyz hello world 13"));
+    ystr_set(&s1, NULL);
+    assert(0 == ystr_cmp_str(&s1, ""));
 
     ystr_destroy(&s1);
     ystr_destroy(&s2);
     ystr_destroy(&s3);
 }
 
+void test_str_build() {
+    ystr_t s1;
+    ystr_init(&s1, "xyz");
+
+    ystr_build(&s1, " hello %s %d", "world", 13);
+    assert(0 == ystr_cmp_str(&s1, "xyz hello world 13"));
+
+    ystr_set(&s1, "initial string.");
+
+    // Generated with `base64 -w0 /dev/urandom | head -c 130`
+    const char* long_string =
+        "qBf7NDxInwVb5kqYTtF3B7gxl5VXBtAcy7uFZQjAtcP08YqB2IqK45rKxGZltcaxnV"
+        "adUH"
+        "hvHDVy/nVt4THu605d7R2icW917w1OZ9ZhRvD02ixP+FvRospdFokx4aav3f";
+    ystr_build(&s1, " Hello. Now we try a long string: %s\n", long_string);
+
+    const char* wants =
+        "initial string. Hello. Now we try a long string: "
+        "qBf7NDxInwVb5kqYTtF3B7gxl5VXBtAcy7uFZQjAtcP08YqB2IqK45rKxGZltcaxnVadUH"
+        "hvHDVy/nVt4THu605d7R2icW917w1OZ9ZhRvD02ixP+FvRospdFokx4aav3f\n";
+    puts(wants);
+    puts(ystr_str(&s1));
+    assert(0 == ystr_cmp_str(&s1, wants));
+
+    ystr_destroy(&s1);
+}
+
 void test_string_split() {
     ystr_t str;
     yvec_t parts;
@@ -123,13 +164,15 @@
     ystr_destroy(&s);
 }
 
-int main(int argc, char **argv) {
+int main(int argc, char** argv) {
+    // Use `make valgrind` to check that all memory is freed by str_test.
     test_inline_string();
     test_str_set_owned();
     test_str_set();
     test_str_at();
     test_str_cmp();
     test_str_append();
+    test_str_build();
     test_string_split();
     test_string_resize();
     return 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/valgrind.sh	Tue Aug 20 19:47:46 2019 +0200
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+# Expects a list of test executables as arguments.
+# Run this using `make valgrind` from the build directory.
+
+VALGRIND=valgrind
+VALGRIND_ARGS="--leak-check=full --track-origins=yes"
+
+TESTS=$@
+
+for BINARY in $TESTS; do
+    echo "Running valgrind on ${BINARY}"
+    $VALGRIND $VALGRIND_ARGS $BINARY
+done