resp.c

Basic RESP handling library in C
git clone git://git.finwo.net/lib/resp.c
Log | Files | Refs | LICENSE

test.h (5359B)


      1 /// assert.h
      2 /// ========
      3 ///
      4 /// Single-file unit-testing library for C
      5 ///
      6 /// Features
      7 /// --------
      8 ///
      9 /// - Single header file, no other library dependencies
     10 /// - Simple ANSI C. The library should work with virtually every C(++) compiler on
     11 ///   virtually any playform
     12 /// - Reporting of assertion failures, including the expression and location of the
     13 ///   failure
     14 /// - Stops test on first failed assertion
     15 /// - ANSI color output for maximum visibility
     16 /// - Easily embeddable in applications for runtime tests or separate testing
     17 ///   applications
     18 ///
     19 /// Todo
     20 /// ----
     21 ///
     22 /// - Disable assertions on definition, to allow production build without source modifications
     23 ///
     24 /// Example Usage
     25 /// -------------
     26 ///
     27 /// ```C
     28 /// #include "finwo/assert.h"
     29 /// #include "mylib.h"
     30 ///
     31 /// void test_sheep() {
     32 ///   ASSERT("Sheep are cool", are_sheep_cool());
     33 ///   ASSERT_EQUALS(4, sheep.legs);
     34 /// }
     35 ///
     36 /// void test_cheese() {
     37 ///   ASSERT("Cheese is tangy", cheese.tanginess > 0);
     38 ///   ASSERT_STRING_EQUALS("Wensleydale", cheese.name);
     39 /// }
     40 ///
     41 /// int main() {
     42 ///   RUN(test_sheep);
     43 ///   RUN(test_cheese);
     44 ///   return TEST_REPORT();
     45 /// }
     46 /// ```
     47 ///
     48 /// To run the tests, compile the tests as a binary and run it.
     49 
     50 #ifndef __TINYTEST_INCLUDED_H__
     51 #define __TINYTEST_INCLUDED_H__
     52 
     53 #include <stdio.h>
     54 #include <stdlib.h>
     55 #include <string.h>
     56 
     57 ///
     58 /// API
     59 /// ---
     60 ///
     61 
     62 ///
     63 /// ### Macros
     64 ///
     65 
     66 
     67 /// <details>
     68 ///   <summary>ASSERT(msg, expression)</summary>
     69 ///
     70 ///   Perform an assertion
     71 ///<C
     72 #define ASSERT(msg, expression) if (!tap_assert(__FILE__, __LINE__, (msg), (#expression), (expression) ? 1 : 0)) return
     73 ///>
     74 /// </details>
     75 
     76 
     77 /// <details>
     78 ///   <summary>ASSERT_EQUALS(expected, actual)</summary>
     79 ///
     80 ///   Perform an equal assertion
     81 ///<C
     82 /* Convenient assertion methods */
     83 /* TODO: Generate readable error messages for assert_equals or assert_str_equals */
     84 #define ASSERT_EQUALS(expected, actual) ASSERT((#actual), (expected) == (actual))
     85 ///>
     86 /// </details>
     87 
     88 /// <details>
     89 ///   <summary>ASSERT_STRING_EQUALS(expected, actual)</summary>
     90 ///
     91 ///   Perform an equal string assertion
     92 ///<C
     93 #define ASSERT_STRING_EQUALS(expected, actual) ASSERT((#actual), strcmp((expected),(actual)) == 0)
     94 ///>
     95 /// </details>
     96 
     97 /// <details>
     98 ///   <summary>RUN(fn)</summary>
     99 ///
    100 ///   Run a test suite/function containing assertions
    101 ///<C
    102 #define RUN(test_function) tap_execute((#test_function), (test_function))
    103 ///>
    104 /// </details>
    105 
    106 /// <details>
    107 ///   <summary>TEST_REPORT()</summary>
    108 ///
    109 ///   Report on the tests that have been run
    110 ///<C
    111 #define TEST_REPORT() tap_report()
    112 ///>
    113 /// </details>
    114 
    115 ///
    116 /// Extras
    117 /// ------
    118 ///
    119 /// ### Disable color
    120 ///
    121 /// If you want to disable color during the assertions, because you want to
    122 /// interpret the output for example (it is "tap" format after all), you can
    123 /// define `NO_COLOR` during compilation to disable color output.
    124 ///
    125 /// ```sh
    126 /// cc -D NO_COLOR source.c -o test
    127 /// ```
    128 ///
    129 /// ### Silent assertions
    130 ///
    131 /// You can also fully disable output for assertions by defining the
    132 /// `ASSERT_SILENT` macro. This will fully disable the printf performed after
    133 /// the assertion is performed.
    134 ///
    135 /// ```sh
    136 /// cc -D ASSERT_SILENT source.c -o test
    137 /// ```
    138 ///
    139 /// ### Silent reporting
    140 ///
    141 /// If you do not want the report to be displayed at the end, you can define the
    142 /// `REPORT_SILENT` macro. This will disable the printf during reporting and
    143 /// only keep the return code.
    144 ///
    145 /// ```sh
    146 /// cc -D REPORT_SILENT source.c -o test
    147 /// ```
    148 ///
    149 
    150 #ifdef NO_COLOR
    151 #define TAP_COLOR_CODE  ""
    152 #define TAP_COLOR_RED   ""
    153 #define TAP_COLOR_GREEN ""
    154 #define TAP_COLOR_RESET ""
    155 #else
    156 #define TAP_COLOR_CODE  "\x1B"
    157 #define TAP_COLOR_RED   "[1;31m"
    158 #define TAP_COLOR_GREEN "[1;32m"
    159 #define TAP_COLOR_RESET "[0m"
    160 #endif
    161 
    162 int tap_asserts = 0;
    163 int tap_passes = 0;
    164 int tap_fails = 0;
    165 const char *tap_current_name = NULL;
    166 
    167 void tap_execute(const char* name, void (*test_function)()) {
    168   tap_current_name = name;
    169   printf("# %s\n", name);
    170   test_function();
    171 }
    172 
    173 int tap_assert(const char* file, int line, const char* msg, const char* expression, int pass) {
    174   tap_asserts++;
    175 
    176   if (pass) {
    177     tap_passes++;
    178 #ifndef ASSERT_SILENT
    179     printf("%s%sok%s%s %d - %s\n",
    180       TAP_COLOR_CODE, TAP_COLOR_GREEN,
    181       TAP_COLOR_CODE, TAP_COLOR_RESET,
    182       tap_asserts,
    183       msg
    184     );
    185 #endif
    186   } else {
    187     tap_fails++;
    188 #ifndef ASSERT_SILENT
    189     printf(
    190       "%s%snot ok%s%s %d - %s\n"
    191       "  On %s:%d, in test %s()\n"
    192       "    %s\n"
    193       ,
    194       TAP_COLOR_CODE, TAP_COLOR_RED,
    195       TAP_COLOR_CODE, TAP_COLOR_RESET,
    196       tap_asserts, msg,
    197       file, line, tap_current_name,
    198       expression
    199     );
    200   }
    201 #endif
    202   return pass;
    203 }
    204 
    205 int tap_report(void) {
    206 #ifndef REPORT_SILENT
    207   printf(
    208     "1..%d\n"
    209     "# tests %d\n"
    210     "# pass  %d\n"
    211     "# fail  %d\n",
    212     tap_asserts,
    213     tap_asserts,
    214     tap_passes,
    215     tap_fails
    216   );
    217 #endif
    218   return tap_fails ? 2 : 0;
    219 }
    220 
    221 #endif // __TINYTEST_INCLUDED_H__
    222 
    223 ///
    224 /// Credits
    225 /// -------
    226 ///
    227 /// This library was heavily based on the [tinytest][tinytest] library by
    228 /// [Joe Walnes][joewalnes]. A license reference to his library could not be
    229 /// found, which is why this reference is in this file. Should I be contacted
    230 /// about licensing issues, I'll investigate further.
    231 ///
    232 /// [joewalnes]: https://github.com/joewalnes
    233 /// [tinytest]: https://github.com/joewalnes/tinytest