sheredom / utest.h

🧪 single header unit testing framework for C and C++

Home Page:https://www.duskborn.com/utest_h/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

musl libc support

bl4ckb0ne opened this issue · comments

I'm using Alpine linux, a linux distribution based on musl libc instead of glibc, and i'm encountering a couple of compilation issues

First this issue about the time.h header that is not included

In file included from /home/simon/dev/utest.h/test/main.c:26:
/home/simon/dev/utest.h/test/../utest.h: In function ‘utest_ns’:
/home/simon/dev/utest.h/test/../utest.h:200:19: error: storage size of ‘ts’ isn’t known
  200 |   struct timespec ts;
      |                   ^~
/home/simon/dev/utest.h/test/../utest.h:204:9: error: unknown type name ‘clockid_t’
  204 |   const clockid_t cid = CLOCK_REALTIME;
      |         ^~~~~~~~~
/home/simon/dev/utest.h/test/../utest.h:204:25: error: ‘CLOCK_REALTIME’ undeclared (first use in this function)
  204 |   const clockid_t cid = CLOCK_REALTIME;
      |                         ^~~~~~~~~~~~~~
/home/simon/dev/utest.h/test/../utest.h:204:25: note: each undeclared identifier is reported only once for each function it appears in
/home/simon/dev/utest.h/test/../utest.h:208:11: error: ‘SYS_clock_gettime’ undeclared (first use in this function)
  208 |   syscall(SYS_clock_gettime, cid, &ts);
      |           ^~~~~~~~~~~~~~~~~
/home/simon/dev/utest.h/test/../utest.h:200:19: error: unused variable ‘ts’ [-Werror=unused-variable]
  200 |   struct timespec ts;
      |                   ^~
/home/simon/dev/utest.h/test/../utest.h:215:1: error: control reaches end of non-void function [-Werror=return-type]
  215 | }
      | ^

Which is easily fixed by this patch

diff --git a/utest.h b/utest.h
index 7f2bcaa..5ade166 100644
--- a/utest.h
+++ b/utest.h
@@ -101,6 +101,10 @@ typedef uint64_t utest_uint64_t;
 #include <sys/syscall.h>
 #include <unistd.h>
 #endif
+#else /* non glibc platforms */
+#include <time.h>
+#include <sys/syscall.h>
+#include <unistd.h>
 #endif

 #elif defined(__APPLE__)

But then the real trouble begins

[ 50%] Linking CXX executable utest_test_wpo
/usr/bin/ld: cannot find -lgcc_

This caused by the fact that the project is using the gnu standard instead of the regular one. Changing it causes another wave of compilation issues, mostly due to comments and other non-standard things that gnu89 has.

[  6%] Building C object CMakeFiles/utest_test_wpo.dir/main.c.o
/home/simon/dev/utest.h/test/main.c:1:1: error: C++ style comments are not allowed in ISO C90
    1 | // This is free and unencumbered software released into the public domain.
      | ^
/home/simon/dev/utest.h/test/main.c:1:1: note: (this will be reported only once per input file)
In file included from /home/simon/dev/utest.h/test/main.c:26:
/home/simon/dev/utest.h/test/../utest.h:160:22: error: unknown type name ‘inline’
  160 | #define UTEST_INLINE inline
      |                      ^~~~~~
/home/simon/dev/utest.h/test/../utest.h:195:8: note: in expansion of macro ‘UTEST_INLINE’
  195 | static UTEST_INLINE utest_int64_t utest_ns(void) {
      |        ^~~~~~~~~~~~
/home/simon/dev/utest.h/test/../utest.h:195:35: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘utest_ns’
  195 | static UTEST_INLINE utest_int64_t utest_ns(void) {
      |                                   ^~~~~~~~
/home/simon/dev/utest.h/test/../utest.h:798:21: error: expected ‘;’ before ‘int’
  798 | static UTEST_INLINE int utest_strncmp(const char *a, const char *b, size_t n) {
      |                     ^~~
/home/simon/dev/utest.h/test/../utest.h:160:22: error: unknown type name ‘inline’
  160 | #define UTEST_INLINE inline
      |                      ^~~~~~
/home/simon/dev/utest.h/test/../utest.h:813:8: note: in expansion of macro ‘UTEST_INLINE’
  813 | static UTEST_INLINE FILE *utest_fopen(const char *filename, const char *mode) {
      |        ^~~~~~~~~~~~
/home/simon/dev/utest.h/test/../utest.h:813:26: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘*’ token
  813 | static UTEST_INLINE FILE *utest_fopen(const char *filename, const char *mode) {
      |                          ^
/home/simon/dev/utest.h/test/../utest.h: In function ‘utest_main’:
/home/simon/dev/utest.h/test/../utest.h:870:28: error: implicit declaration of function ‘utest_fopen’ [-Werror=implicit-function-declaration]
  870 |       utest_state.output = utest_fopen(argv[index] + strlen(output_str), "w+");
      |                            ^~~~~~~~~~~
/home/simon/dev/utest.h/test/../utest.h:870:26: error: assignment to ‘FILE *’ from ‘int’ makes pointer from integer without a cast [-Werror=int-conversion]
  870 |       utest_state.output = utest_fopen(argv[index] + strlen(output_str), "w+");
      |                          ^
/home/simon/dev/utest.h/test/../utest.h:917:10: error: implicit declaration of function ‘utest_ns’; did you mean ‘utest_main’? [-Werror=implicit-function-declaration]
  917 |     ns = utest_ns();
      |          ^~~~~~~~
      |          utest_main
In file included from /home/simon/dev/utest.h/test/main.c:27:
/home/simon/dev/utest.h/test/process.h: At top level:
/home/simon/dev/utest.h/test/process.h:156:3: error: C++ style comments are not allowed in ISO C90
  156 |   // stdout and stderr are the same FILE.
      |   ^
/home/simon/dev/utest.h/test/process.h:156:3: note: (this will be reported only once per input file)
/home/simon/dev/utest.h/test/process.h: In function ‘process_create’:
/home/simon/dev/utest.h/test/process.h:346:57: error: missing terminating ' character [-Werror]
  346 |                       environment,         // use parent's environment
      |                                                         ^
/home/simon/dev/utest.h/test/process.h:347:57: error: missing terminating ' character [-Werror]
  347 |                       NULL,                // use parent's current directory
      |                                                         ^
/home/simon/dev/utest.h/test/process.h:359:12: error: missing terminating ' character [-Werror]
  359 |   // We don't need the handle of the primary thread in the called process.
      |            ^
/home/simon/dev/utest.h/test/process.h:430:31: error: implicit declaration of function ‘fdopen’; did you mean ‘fopen’? [-Werror=implicit-function-declaration]
  430 |     out_process->stdin_file = fdopen(stdinfd[1], "wb");
      |                               ^~~~~~
      |                               fopen
/home/simon/dev/utest.h/test/process.h:430:29: error: assignment to ‘FILE *’ from ‘int’ makes pointer from integer without a cast [-Werror=int-conversion]
  430 |     out_process->stdin_file = fdopen(stdinfd[1], "wb");
      |                             ^
/home/simon/dev/utest.h/test/process.h:435:30: error: assignment to ‘FILE *’ from ‘int’ makes pointer from integer without a cast [-Werror=int-conversion]
  435 |     out_process->stdout_file = fdopen(stdoutfd[0], "rb");
      |                              ^
/home/simon/dev/utest.h/test/process.h:444:32: error: assignment to ‘FILE *’ from ‘int’ makes pointer from integer without a cast [-Werror=int-conversion]
  444 |       out_process->stderr_file = fdopen(stderrfd[0], "rb");
      |                                ^
cc1: all warnings being treated as errors

I can take care of this, but I'd like to discuss about a strategy first. Would it be ok to bump the minimal required standard to c99?

I need to support c89 because of old MSVC unfortunately.

If you leave it with me I will try and get it to work with c89 barebones (not sure how much work it'll entail though tbh!)

I solved the inline issue easily by defining it to nothing if the feature is not detected. For the commentaries I think a good search and replace trick could do it, I dont know exactly how many are there since -Werror fails on the first one. For the rest I think _POSIX_C_SOURCE is missing but I don't know exactly where to place it.

Tell me if you want me to test it on my side, I'd be happy to help.

So I'm curious now - in #37 I've added explicit testing for C99 and C11, and both are working like expected, so what again is your issue?

Can you try #37 now that I've updated it please? This seems to work locally for me with strict c99/c11 support, and so should work with MUSL.

Still some issues, I think there's a _POSIX_C_SOURCE define missing somewhere.

In file included from /home/simon/sources/utest.h/test/main.c:26:
/home/simon/sources/utest.h/test/../utest.h: In function ‘utest_ns’:
/home/simon/sources/utest.h/test/../utest.h:202:19: error: storage size of ‘ts’ isn’t known
  202 |   struct timespec ts;
      |                   ^~
/home/simon/sources/utest.h/test/../utest.h:206:9: error: unknown type name ‘clockid_t’
  206 |   const clockid_t cid = CLOCK_REALTIME;
      |         ^~~~~~~~~
/home/simon/sources/utest.h/test/../utest.h:206:25: error: ‘CLOCK_REALTIME’ undeclared (first use in this function)
  206 |   const clockid_t cid = CLOCK_REALTIME;
      |                         ^~~~~~~~~~~~~~
/home/simon/sources/utest.h/test/../utest.h:206:25: note: each undeclared identifier is reported only once for each function it appears in
/home/simon/sources/utest.h/test/../utest.h:210:11: error: ‘SYS_clock_gettime’ undeclared (first use in this function)
  210 |   syscall(SYS_clock_gettime, cid, &ts);
      |           ^~~~~~~~~~~~~~~~~
/home/simon/sources/utest.h/test/../utest.h:202:19: error: unused variable ‘ts’ [-Werror=unused-variable]
  202 |   struct timespec ts;
      |                   ^~
/home/simon/sources/utest.h/test/../utest.h:217:1: error: control reaches end of non-void function [-Werror=return-type]
  217 | }
      | ^

I fixed it on my side, here's the patch

diff --git a/utest.h b/utest.h
index 6b0f869..1970bca 100644
--- a/utest.h
+++ b/utest.h
@@ -101,6 +101,9 @@ typedef uint64_t utest_uint64_t;
 #include <sys/syscall.h>
 #include <unistd.h>
 #endif
+#else // Other libc implementations
+#include <time.h>
+#define UTEST_USE_CLOCKGETTIME
 #endif

 #elif defined(__APPLE__)

utest_test and utest_test_wpo both ran with the same issue

[==========] 849 test cases ran.
[  PASSED  ] 848 tests.
[  FAILED  ] 1 tests, listed below:
[  FAILED  ] utest_cmdline.filter_with_list

I also encounter a compilation error on my test case using gcc 9.3, but it works fine with clang on the same system

./tests/buffer.c: In function 'utest_run_buffer_alloc_header_free':
../tests/utest.h:372:38: error: format '%p' expects argument of type 'void *', but argument 3 has type 'int *' [-Werror=format=]
  372 |                                    : "%p", default                             \
      |                                      ^~~~
  373 |                                    : "undef")),                                \
  374 |                (val))
      |                ~~~~~
      |                |
      |                int *
../tests/utest.h:258:33: note: in definition of macro 'UTEST_PRINTF'
  258 |     fprintf(utest_state.output, __VA_ARGS__);                                  \
      |                                 ^~~~~~~~~~~
../tests/utest.h:544:7: note: in expansion of macro 'utest_type_printer'
  544 |       utest_type_printer(xEval);                                               \
      |       ^~~~~~~~~~~~~~~~~~
../tests/utest.h:583:25: note: in expansion of macro 'UTEST_ASSERT'
  583 | #define ASSERT_NE(x, y) UTEST_ASSERT(x, y, !=)
      |                         ^~~~~~~~~~~~
../tests/buffer.c:7:2: note: in expansion of macro 'ASSERT_NE'
    7 |  ASSERT_NE(buf, NULL);
      |  ^~~~~~~~~

I've applied your patch to #37 - hopefully it passes CI.