test/test.h

Sun, 17 Dec 2023 14:25:34 +0100

author
Mike Becker <universe@uap-core.de>
date
Sun, 17 Dec 2023 14:25:34 +0100
changeset 797
edbb20b1438d
parent 747
efbd59642577
child 816
839fefbdedc7
permissions
-rw-r--r--

[Makefile] fix missing rules preventing dry-runs

We have to support dry-runs, because many IDEs are using
dry-runs to collect build information.

Some rules have dependencies that expect certain files or
directories to be just present. We added respective build
rules which invoke the test program. This way, the behavior
when running make normally is exactly the same, but dry-runs
are also not failing now.

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2017 Mike Becker, Olaf Wintermann All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
 
/**
 * @file: test.h
 * 
 * UCX Test Framework.
 * 
 * Usage of this test framework:
 *
 * **** IN HEADER FILE: ****
 *
 * <pre>
 * UCX_TEST(function_name);
 * UCX_TEST_SUBROUTINE(subroutine_name, paramlist); // optional
 * </pre>
 *
 * **** IN SOURCE FILE: ****
 * <pre>
 * UCX_TEST_SUBROUTINE(subroutine_name, paramlist) {
 *   // tests with UCX_TEST_ASSERT()
 * }
 * 
 * UCX_TEST(function_name) {
 *   // memory allocation and other stuff here
 *   #UCX_TEST_BEGIN
 *   // tests with UCX_TEST_ASSERT() and/or
 *   // calls with UCX_TEST_CALL_SUBROUTINE() here
 *   #UCX_TEST_END
 *   // cleanup of memory here
 * }
 * </pre>
 *
 * <b>Note:</b> if a test fails, a longjump is performed
 * back to the #UCX_TEST_BEGIN macro!
 * 
 * <b>Attention:</b> Do not call own functions within a test, that use
 * UCX_TEST_ASSERT() macros and are not defined by using UCX_TEST_SUBROUTINE().
 * 
 *
 * @author Mike Becker
 * @author Olaf Wintermann
 *
 */

#ifndef UCX_TEST_H
#define	UCX_TEST_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>

#ifdef	__cplusplus
extern "C" {
#endif

#ifndef __FUNCTION__

/**
 * Alias for the <code>__func__</code> preprocessor macro.
 * Some compilers use <code>__func__</code> and others use __FUNCTION__.
 * We use __FUNCTION__ so we define it for those compilers which use
 * <code>__func__</code>.
 */
#define __FUNCTION__ __func__
#endif

/** Type for the UcxTestSuite. */
typedef struct UcxTestSuite UcxTestSuite;

/** Pointer to a test function. */
typedef void(*UcxTest)(UcxTestSuite*,FILE*);

/** Type for the internal list of test cases. */
typedef struct UcxTestList UcxTestList;

/** Structure for the internal list of test cases. */
struct UcxTestList {
    
    /** Test case. */
    UcxTest test;
    
    /** Pointer to the next list element. */
    UcxTestList *next;
};

/**
 * A test suite containing multiple test cases.
 */
struct UcxTestSuite {
    
    /** The number of successful tests after the suite has been run. */
    unsigned int success;
    
    /** The number of failed tests after the suite has been run. */
    unsigned int failure;
    
    /**
     * Internal list of test cases.
     * Use ucx_test_register() to add tests to this list.
     */
    UcxTestList *tests;
};

/**
 * Creates a new test suite.
 * @return a new test suite
 */
UcxTestSuite* ucx_test_suite_new();

/**
 * Destroys a test suite.
 * @param suite the test suite to destroy
 */
void ucx_test_suite_free(UcxTestSuite* suite);

/**
 * Registers a test function with the specified test suite.
 * 
 * @param suite the suite, the test function shall be added to
 * @param test the test function to register
 * @return <code>EXIT_SUCCESS</code> on success or
 * <code>EXIT_FAILURE</code> on failure
 */
int ucx_test_register(UcxTestSuite* suite, UcxTest test);

/**
 * Runs a test suite and writes the test log to the specified stream.
 * @param suite the test suite to run
 * @param outstream the stream the log shall be written to
 */
void ucx_test_run(UcxTestSuite* suite, FILE* outstream);

/**
 * Macro for a #UcxTest function header.
 * 
 * Use this macro to declare and/or define a #UcxTest function.
 * 
 * @param name the name of the test function
 */
#define UCX_TEST(name) void name(UcxTestSuite* _suite_,FILE *_output_)

/**
 * Marks the begin of a test.
 * <b>Note:</b> Any UCX_TEST_ASSERT() calls must be performed <b>after</b>
 * #UCX_TEST_BEGIN.
 * 
 * @see #UCX_TEST_END
 */
#define UCX_TEST_BEGIN fwrite("Running ", 1, 8, _output_);\
        fwrite(__FUNCTION__, 1, strlen(__FUNCTION__), _output_);\
        fwrite("... ", 1, 4, _output_);\
        jmp_buf _env_; \
        if (!setjmp(_env_)) {

/**
 * Checks a test assertion.
 * If the assertion is correct, the test carries on. If the assertion is not
 * correct, the specified message (terminated by a dot and a line break) is
 * written to the test suites output stream.
 * @param condition the condition to check
 * @param message the message that shall be printed out on failure
 */
#define UCX_TEST_ASSERT(condition,message) if (!(condition)) { \
        fwrite(message".\n", 1, 2+strlen(message), _output_); \
        _suite_->failure++; \
        longjmp(_env_, 1);\
    }

/**
 * Macro for a test subroutine function header.
 * 
 * Use this to declare and/or define a subroutine that can be called by using
 * UCX_TEST_CALL_SUBROUTINE().
 * 
 * @param name the name of the subroutine
 * @param ... the parameter list
 * 
 * @see UCX_TEST_CALL_SUBROUTINE()
 */
#define UCX_TEST_SUBROUTINE(name,...) void name(UcxTestSuite* _suite_,\
        FILE *_output_, jmp_buf _env_, __VA_ARGS__)

/**
 * Macro for calling a test subroutine.
 * 
 * Subroutines declared with UCX_TEST_SUBROUTINE() can be called by using this
 * macro.
 * 
 * <b>Note:</b> You may <b>only</b> call subroutines within a #UCX_TEST_BEGIN-
 * #UCX_TEST_END-block.
 * 
 * @param name the name of the subroutine
 * @param ... the argument list
 * 
 * @see UCX_TEST_SUBROUTINE()
 */
#define UCX_TEST_CALL_SUBROUTINE(name,...) \
        name(_suite_,_output_,_env_,__VA_ARGS__);

/**
 * Marks the end of a test.
 * <b>Note:</b> Any UCX_TEST_ASSERT() calls must be performed <b>before</b>
 * #UCX_TEST_END.
 * 
 * @see #UCX_TEST_BEGIN
 */
#define UCX_TEST_END fwrite("success.\n", 1, 9, _output_); _suite_->success++;}

#ifdef	__cplusplus
}
#endif

#endif	/* UCX_TEST_H */

mercurial