UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2017 Mike Becker, Olaf Wintermann All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file: test.h 31 * 32 * UCX Test Framework. 33 * 34 * Usage of this test framework: 35 * 36 * **** IN HEADER FILE: **** 37 * 38 * <pre> 39 * UCX_TEST(function_name); 40 * UCX_TEST_SUBROUTINE(subroutine_name, paramlist); // optional 41 * </pre> 42 * 43 * **** IN SOURCE FILE: **** 44 * <pre> 45 * UCX_TEST_SUBROUTINE(subroutine_name, paramlist) { 46 * // tests with UCX_TEST_ASSERT() 47 * } 48 * 49 * UCX_TEST(function_name) { 50 * // memory allocation and other stuff here 51 * #UCX_TEST_BEGIN 52 * // tests with UCX_TEST_ASSERT() and/or 53 * // calls with UCX_TEST_CALL_SUBROUTINE() here 54 * #UCX_TEST_END 55 * // cleanup of memory here 56 * } 57 * </pre> 58 * 59 * <b>Note:</b> if a test fails, a longjump is performed 60 * back to the #UCX_TEST_BEGIN macro! 61 * 62 * <b>Attention:</b> Do not call own functions within a test, that use 63 * UCX_TEST_ASSERT() macros and are not defined by using UCX_TEST_SUBROUTINE(). 64 * 65 * 66 * @author Mike Becker 67 * @author Olaf Wintermann 68 * 69 */ 70 71 #ifndef UCX_TEST_H 72 #define UCX_TEST_H 73 74 #include <stdio.h> 75 #include <stdlib.h> 76 #include <string.h> 77 #include <setjmp.h> 78 79 #ifdef __cplusplus 80 extern "C" { 81 #endif 82 83 #ifndef __FUNCTION__ 84 85 /** 86 * Alias for the <code>__func__</code> preprocessor macro. 87 * Some compilers use <code>__func__</code> and others use __FUNCTION__. 88 * We use __FUNCTION__ so we define it for those compilers which use 89 * <code>__func__</code>. 90 */ 91 #define __FUNCTION__ __func__ 92 #endif 93 94 /** Type for the UcxTestSuite. */ 95 typedef struct UcxTestSuite UcxTestSuite; 96 97 /** Pointer to a test function. */ 98 typedef void(*UcxTest)(UcxTestSuite*,FILE*); 99 100 /** Type for the internal list of test cases. */ 101 typedef struct UcxTestList UcxTestList; 102 103 /** Structure for the internal list of test cases. */ 104 struct UcxTestList { 105 106 /** Test case. */ 107 UcxTest test; 108 109 /** Pointer to the next list element. */ 110 UcxTestList *next; 111 }; 112 113 /** 114 * A test suite containing multiple test cases. 115 */ 116 struct UcxTestSuite { 117 118 /** The number of successful tests after the suite has been run. */ 119 unsigned int success; 120 121 /** The number of failed tests after the suite has been run. */ 122 unsigned int failure; 123 124 /** 125 * Internal list of test cases. 126 * Use ucx_test_register() to add tests to this list. 127 */ 128 UcxTestList *tests; 129 }; 130 131 /** 132 * Creates a new test suite. 133 * @return a new test suite 134 */ 135 UcxTestSuite* ucx_test_suite_new(); 136 137 /** 138 * Destroys a test suite. 139 * @param suite the test suite to destroy 140 */ 141 void ucx_test_suite_free(UcxTestSuite* suite); 142 143 /** 144 * Registers a test function with the specified test suite. 145 * 146 * @param suite the suite, the test function shall be added to 147 * @param test the test function to register 148 * @return <code>EXIT_SUCCESS</code> on success or 149 * <code>EXIT_FAILURE</code> on failure 150 */ 151 int ucx_test_register(UcxTestSuite* suite, UcxTest test); 152 153 /** 154 * Runs a test suite and writes the test log to the specified stream. 155 * @param suite the test suite to run 156 * @param outstream the stream the log shall be written to 157 */ 158 void ucx_test_run(UcxTestSuite* suite, FILE* outstream); 159 160 /** 161 * Macro for a #UcxTest function header. 162 * 163 * Use this macro to declare and/or define a #UcxTest function. 164 * 165 * @param name the name of the test function 166 */ 167 #define UCX_TEST(name) void name(UcxTestSuite* _suite_,FILE *_output_) 168 169 /** 170 * Marks the begin of a test. 171 * <b>Note:</b> Any UCX_TEST_ASSERT() calls must be performed <b>after</b> 172 * #UCX_TEST_BEGIN. 173 * 174 * @see #UCX_TEST_END 175 */ 176 #define UCX_TEST_BEGIN fwrite("Running ", 1, 8, _output_);\ 177 fwrite(__FUNCTION__, 1, strlen(__FUNCTION__), _output_);\ 178 fwrite("... ", 1, 4, _output_);\ 179 jmp_buf _env_; \ 180 if (!setjmp(_env_)) { 181 182 /** 183 * Checks a test assertion. 184 * If the assertion is correct, the test carries on. If the assertion is not 185 * correct, the specified message (terminated by a dot and a line break) is 186 * written to the test suites output stream. 187 * @param condition the condition to check 188 * @param message the message that shall be printed out on failure 189 */ 190 #define UCX_TEST_ASSERT(condition,message) if (!(condition)) { \ 191 fwrite(".\n"message, 1, 2+strlen(message), _output_); \ 192 _suite_->failure++; \ 193 longjmp(_env_, 1);\ 194 } 195 196 /** 197 * Macro for a test subroutine function header. 198 * 199 * Use this to declare and/or define a subroutine that can be called by using 200 * UCX_TEST_CALL_SUBROUTINE(). 201 * 202 * @param name the name of the subroutine 203 * @param ... the parameter list 204 * 205 * @see UCX_TEST_CALL_SUBROUTINE() 206 */ 207 #define UCX_TEST_SUBROUTINE(name,...) void name(UcxTestSuite* _suite_,\ 208 FILE *_output_, jmp_buf _env_, __VA_ARGS__) 209 210 /** 211 * Macro for calling a test subroutine. 212 * 213 * Subroutines declared with UCX_TEST_SUBROUTINE() can be called by using this 214 * macro. 215 * 216 * <b>Note:</b> You may <b>only</b> call subroutines within a #UCX_TEST_BEGIN- 217 * #UCX_TEST_END-block. 218 * 219 * @param name the name of the subroutine 220 * @param ... the argument list 221 * 222 * @see UCX_TEST_SUBROUTINE() 223 */ 224 #define UCX_TEST_CALL_SUBROUTINE(name,...) \ 225 name(_suite_,_output_,_env_,__VA_ARGS__); 226 227 /** 228 * Marks the end of a test. 229 * <b>Note:</b> Any UCX_TEST_ASSERT() calls must be performed <b>before</b> 230 * #UCX_TEST_END. 231 * 232 * @see #UCX_TEST_BEGIN 233 */ 234 #define UCX_TEST_END fwrite("success.\n", 1, 9, _output_); _suite_->success++;} 235 236 #ifdef __cplusplus 237 } 238 #endif 239 240 #endif /* UCX_TEST_H */ 241 242