├── .gitattributes ├── .github ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── discussion.md │ ├── feature_request.md │ └── question.md ├── PULL_REQUEST_TEMPLATE.md ├── assets │ └── example_output.png └── workflows │ └── codeql-analysis.yml ├── .gitignore ├── CMakeLists.txt ├── LICENSE.md ├── README.md ├── build.sh ├── doc └── asserts.md └── eztest ├── eztest.h └── runner.c /.gitattributes: -------------------------------------------------------------------------------- 1 | # Forces header files to be classified as C rathern than C++ 2 | eztest/*.h linguist-language=C 3 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * Unwelcome sexual attention or advances 26 | * Trolling, insulting/derogatory comments, and personal or political attacks 27 | * Public or private harassment 28 | * Publishing others' private information, such as a physical or electronic 29 | address, without explicit permission 30 | * Other conduct which could reasonably be considered inappropriate in a 31 | professional setting 32 | 33 | ## Our Responsibilities 34 | 35 | Project maintainers are responsible for clarifying the standards of acceptable 36 | behavior and are expected to take appropriate and fair corrective action in 37 | response to any instances of unacceptable behavior. 38 | 39 | Project maintainers have the right and responsibility to remove, edit, or 40 | reject comments, commits, code, wiki edits, issues, and other contributions 41 | that are not aligned to this Code of Conduct, or to ban temporarily or 42 | permanently any contributor for other behaviors that they deem inappropriate, 43 | threatening, offensive, or harmful. 44 | 45 | ## Scope 46 | 47 | This Code of Conduct applies both within project spaces and in public spaces 48 | when an individual is representing the project or its community. Examples of 49 | representing a project or community include using an official project e-mail 50 | address, posting via an official social media account, or acting as an appointed 51 | representative at an online or offline event. Representation of a project may be 52 | further defined and clarified by project maintainers. 53 | 54 | ## Enforcement 55 | 56 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 57 | reported by contacting the project team using the Security Advisories section on Github. All 58 | complaints will be reviewed and investigated and will result in a response that 59 | is deemed necessary and appropriate to the circumstances. The project team is 60 | obligated to maintain confidentiality with regard to the reporter of an incident. 61 | Further details of specific enforcement policies may be posted separately. 62 | 63 | Project maintainers who do not follow or enforce the Code of Conduct in good 64 | faith may face temporary or permanent repercussions as determined by other 65 | members of the project's leadership. 66 | 67 | ## Attribution 68 | 69 | This Code of Conduct is based on the Contributor Covenant, version 1.4, 70 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 71 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to EzTest 2 | :balloon: Thank you for your interest in contributing to EzTest! :balloon: 3 | 4 | We welcome all contributions and hope you will do your best to follow the given guidelines in order to smooth the development process. 5 | 6 | ## How to contribute 7 | 8 | ### Report a bug | Suggest bug fix 9 | 10 | Please create an issue marked with the bug label. When writing the issue please attempt to follow the issue template for bugs. 11 | 12 | ##### Know of a fix? 13 | 14 | If you have a fix for the bug please create a pull requests. Make sure to fully describe the issue along with how your solution fixes the problem. 15 | 16 | ### New feature 17 | 18 | Suggest a new feature by creating an issue marked with the new feature label. 19 | 20 | ##### Developing a feature 21 | 22 | If you have developed a new feature please make sure you have followed the style guides by doing a self review. 23 | All new features should be developed in response to an issue. A common process would then be to create an issue marked with the 24 | new feature or enhancement label, develop the feature and then create a pull-request. 25 | 26 | ## Development guidelines 27 | 28 | #### Git commit messages 29 | 30 | Each git commit should be accompanied by a message giving a clear indication of what has been changed. 31 | If the commit is in response to an issue, make sure to reference the issue in the commit message. 32 | 33 | 34 | #### Code 35 | 36 | - Indentation and brackets follow [Allman style](https://en.wikipedia.org/wiki/Indentation_style#Allman_style) 37 | - Indentation should be 4 spaces 38 | - Code documentation should follow "JavaDoc style" 39 | Example: 40 | ``` 41 | /** 42 | * 43 | * @param 44 | * @see 45 | * @return 46 | */ 47 | ``` 48 | 49 | #### Integration 50 | 51 | To smooth integration, it is recommended that you develop on a branch specific for your feature. Once you have completed the feature please create a pull-request to get the code reviewed and merged. 52 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Use parameter.. 16 | 2. Call method.. 17 | etc. 18 | 19 | **Expected behavior** 20 | A clear and concise description of what you expected to happen. 21 | 22 | **Screenshots** 23 | If applicable, add screenshots to help explain your problem. 24 | 25 | **Additional context** 26 | Add any other context about the problem here. 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/discussion.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Discussion 3 | about: 'Open a dialog into any project related subjects. ' 4 | title: "[DISCUSSION]" 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[FEATURE REQUEST]" 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: Questions & help 4 | title: "[QUESTION]" 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | # [TITLE] 11 | Add further details and code to help us better understand your question. 12 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. 4 | 5 | Fixes # (issue) 6 | 7 | ## Type of change 8 | 9 | - [ ] Bug fix (non-breaking change which fixes an issue) 10 | - [ ] New feature (non-breaking change which adds functionality) 11 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 12 | 13 | # How Has This Been Tested? 14 | 15 | Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration 16 | 17 | # Checklist: 18 | 19 | - [ ] I have performed a self-review of my own code 20 | - [ ] I have commented my code, particularly in hard-to-understand areas 21 | - [ ] My changes generate no new warnings 22 | - [ ] I have added tests that prove my fix is effective or that my feature works 23 | -------------------------------------------------------------------------------- /.github/assets/example_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/havardt/EzTest/9ebdcf3db330c8a6d2f3b1d06fae2ce5d42de773/.github/assets/example_output.png -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ master ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ master ] 20 | schedule: 21 | - cron: '19 17 * * 4' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'cpp' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://git.io/codeql-language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v3 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v2 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 52 | 53 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 54 | # If this step fails, then you should remove it and run the build manually (see below) 55 | - name: Autobuild 56 | uses: github/codeql-action/autobuild@v2 57 | 58 | # ℹ️ Command-line programs to run using the OS shell. 59 | # 📚 https://git.io/JvXDl 60 | 61 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 62 | # and modify them (or add more) to build your code if your project 63 | # uses a compiled language 64 | 65 | #- run: | 66 | # make bootstrap 67 | # make release 68 | 69 | - name: Perform CodeQL Analysis 70 | uses: github/codeql-action/analyze@v2 71 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.obj 3 | *.exe 4 | *.out 5 | out/ 6 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | 3 | project (eztest) 4 | 5 | set (CMAKE_C_STANDARD 11) 6 | 7 | set (eztest_VERSION_MAJOR 3) 8 | set (eztest_VERSION_MINOR 0) 9 | set (eztest_VERSION_PATCH 0) 10 | 11 | if (CMAKE_COMPILER_IS_GNUCC) 12 | set(CMAKE_C_FLAGS "-Wall") 13 | set(CMAKE_C_FLAGS_DEBUG "-g") 14 | set(CMAKE_C_FLAGS_RELEASE "-O3") 15 | endif() 16 | 17 | add_executable(eztest eztest/runner.c eztest/eztest.h) 18 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 havardt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

EzTest

2 | 3 |
4 | 5 | [![Release](https://img.shields.io/github/v/release/havardt/eztest?label=Release)](https://github.com/havardt/EzTest/releases) 6 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 7 | 8 |
9 | 10 |

An easy to use unit testing framework written in, and created for, the C language.

11 | 12 |
13 | 14 |
15 | 16 | 17 | 18 | ## Table of contents 19 | * [Introduction](#introduction) 20 | * [Getting started](#getting-started) 21 | * [Asserts](#asserts) 22 | * [Runner](#runner) 23 | * [How to contribute](#contribute) 24 | * [License info](#license) 25 | 26 | ## Introduction 27 | 28 | 29 | ###### A simple test 30 | 31 | ```C 32 | TEST(Math, AddingTwoOnTwoShouldEqualFour) 33 | { 34 | const int expected = 4; 35 | const int actual = math_add(2, 2); 36 | 37 | ASSERT_ARE_EQUAL(expected, actual); // or ASSERT_EQ(expected, actual); using the shorthand. 38 | } 39 | ``` 40 | The [asserts](#asserts) are created using the power of the C11 macro ```_Generic```. As seen in the above example, this means that the user doesn't have to provide any prefix or suffix to represent the data type. 41 | 42 | ###### A full test (Setup and Teardown) 43 | EzTest also provides the option of setup and teardown functions. The setup function is a function that runs before every test within a test suite. The teardown function has similar behaviour, but runs after the test. A test utilizing setup and teardown functions is defined by using the ```TEST_FULL(suite, name)``` macro. A setup and teardown function *must* also be defined for the test suite when using the full test macro. This is done with the ```SETUP(suite)``` and ```TEARDOWN(suite)``` macros. 44 | 45 | ```C 46 | 47 | SETUP(Math) 48 | { 49 | // Code to run before every test in the Math suite. 50 | } 51 | 52 | TEST_FULL(Math, AddingTwoOnTwoShouldEqualFour) 53 | { 54 | // Test code placed here. 55 | } 56 | 57 | TEARDOWN(Math) 58 | { 59 | // This code runs after every test in the Math suite. 60 | } 61 | 62 | ``` 63 | 64 | See the next section for information on how to get started with EzTest. 65 | 66 | ## Getting started 67 | EzTest was created to make unit testing quick and easy in C. The fastest way to get started with EzTest is by using the [template](https://github.com/havardt/EzTest-Template). The template provides a default project layout for C projects using EzTest. After getting the template or creating your own project structure, you are ready to start. 68 | 69 | #### 1. Write tests using the test macros 70 | Before having access to the test macros you need to include the eztest header file: ```#include "eztest.h"```. 71 | There are two macros for creating tests: ```TEST(suite, test)``` and ```TEST_FULL(suite, test)```. 72 | The first is for simple unit tests while the second is for tests with a setup and teardown function. Both of these macros take the same arguments. 73 | 74 | ###### Argument 1: Suite 75 | This is the name of the test suite that the test will be associated with. The name must follow the rules for variable names in C and must be unique through out your tests. The suite name can be used to group multiple tests providing a better overview for the tester. 76 | 77 | ###### Argument 2: Test 78 | This is the name of the test. The name must follow the rules for variable names in C and must be unique within the test suite. 79 | 80 | Example usage of both ```TEST(suite, test)``` and ```TEST_FULL(suite, test)``` can be found in the [usage section](#usage). 81 | 82 | 83 | #### 2. Build/ Compile 84 | 85 | ###### Option I: CMake/Template 86 | The perhaps simplest way to build your tests is to use CMake. If you are using CMake and/or the template, then follow the build instructions given [here](https://github.com/havardt/EzTest-Template#hammer_and_wrench-build). 87 | 88 | ###### Option II: Manual build 89 | To build the EzTest runner, compile using a C11 compatible C compiler by providing the ```runner.c``` source file along with your test files. 90 | Example compile: ```$ gcc -o ezrunner runner.c ``` 91 | 92 | 93 | #### 3. Run 94 | Run the executable to run your tests. The test runner can take multiple optional arguments to customize your test experience. Learn more about the test runner [here](#runner). 95 | 96 | ## Asserts 97 | 98 | | Macro | Shorthand | Description | Details | 99 | | --- | --- | --- | --- | 100 | | ``` ASSERT_IS_NULL ``` | | Tests whether the provided pointer is null. | [Documentation](doc/asserts.md#Assert-NULL) | 101 | | ``` ASSERT_IS_NOT_NULL ``` | | Tests whether the provided pointer is non-null. | [Documentation](doc/asserts.md#Assert-not-NULL) | 102 | | ``` ASSERT_IS_TRUE ``` | | Tests whether the condition is true. | [Documentation](doc/asserts.md#Assert-true) | 103 | | ``` ASSERT_IS_FALSE ``` | | Tests whether the condition is false. | [Documentation](doc/asserts.md#Assert-false) | 104 | | ``` ASSERT_ARE_SAME ``` | | Tests whether the two pointers refer to the same memory location. | [Documentation](doc/asserts.md#Assert-same) | 105 | | ``` ASSERT_ARE_NOT_SAME ``` | | Tests whether the two pointers refer to different memory locations. | [Documentation](doc/asserts.md#Assert-not-same) | 106 | | ``` ASSERT_IS_NAN ``` | | Tests whether the provided float is NaN. | [Documentation](doc/asserts.md#Assert-NaN) | 107 | | ``` ASSERT_ARE_EQUAL ``` | ``` ASSERT_EQ ``` | Tests whether the two values are equal. | [Documentation](doc/asserts.md#Assert-equal) | 108 | | ``` ASSERT_ARE_EQUAL_PRECISION ``` | ```ASSERT_EQ_PRECISION```| Tests whether two floating point numbers are equal using a user provided epsilon. | [Documentation](doc/asserts.md#Assert-equal-precision) | 109 | | ``` ASSERT_ARE_EQUAL_MEM ``` | ``` ASSERT_EQ_MEM ``` | Tests whether the two values are equal by comparing each byte at the given memory locations. | [Documentation](doc/asserts.md#Assert-equal-memory) | 110 | | ``` ASSERT_ARE_EQUAL_CMP ``` | ``` ASSERT_EQ_CMP ``` | Tests whether the two values are equal by using the passed comparator function. | [Documentation](doc/asserts.md#Assert-equal-cmp) | 111 | | ``` ASSERT_ARE_NOT_EQUAL ``` |``` ASSERT_NE ``` | Tests whether the two values are different. | [Documentation](doc/asserts.md#Assert-not-equal) | 112 | | ``` ASSERT_ARE_NOT_EQUAL_PRECISION ``` | ```ASSERT_NE_PRECISION``` | Tests whether two floating point numbers are different using a user provided epsilon. | [Documentation](doc/asserts.md#Assert-not-equal-precision) | 113 | | ``` ASSERT_ARE_NOT_EQUAL_MEM ``` | ```ASSERT_NE_MEM``` | Tests whether the two values are different by comparing each byte at the given memory locations. | [Documentation](doc/asserts.md#Assert-not-equal-mem) | 114 | | ``` ASSERT_ARE_NOT_EQUAL_CMP ``` | ``` ASSERT_NE_CMP ``` | Tests whether the two values are different by using the passed comparator function. | [Documentation](doc/asserts.md#Assert-not-equal-cmp) | 115 | | ``` ASSERT_GREATER ``` | ``` ASSERT_GT ``` | Tests whether the first value is greater than the second value. | 116 | | ``` ASSERT_GREATER_PRECISION ``` | ``` ASSERT_GT_PRECISION ``` | Tests whether the first floating point value is greater than the second floating point value using a user provided epsilon. | 117 | | ``` ASSERT_GREATER_MEM ``` | ```ASSERT_GT_MEM``` | Tests whether the first n bytes at the first memory location is greater than the n first bytes at the second memory location. | 118 | | ``` ASSERT_GREATER_CMP ``` | ``` ASSERT_GT_CMP ``` | Tests whether the first value is greater than the second value by using the passed comparator function. | 119 | | ``` ASSERT_GREATER_EQUAL ``` | ```ASSERT_GE``` | Tests whether the first value is greater than or equal to the second value. | 120 | | ``` ASSERT_GREATER_EQUAL_PRECISION ``` | ```ASSERT_GE_PRECISION``` | Tests whether the first floating point value is greater than or equal to the second floating point value using a user provided epsilon. | 121 | | ``` ASSERT_GREATER_EQUAL_MEM ``` | ```ASSERT_GE_MEM``` | Tests whether the first n bytes at the first memory location is greater than or equal to the n first bytes at the second memory location. | 122 | | ``` ASSERT_GREATER_EQUAL_CMP ``` | ``` ASSERT_GE_CMP ``` | Tests whether the first value is greater than or equal to the second value by using the passed comparator function. | 123 | | ``` ASSERT_LESS ``` | ``` ASSERT_LT ``` | Tests whether the first value is lesser than the second value. | 124 | | ``` ASSERT_LESS_PRECISION ``` | ``` ASSERT_LT_PRECISION ``` | Tests whether the first floating point value is lesser than the second floating point value using a user provided epsilon. | 125 | | ``` ASSERT_LESS_MEM ``` | ```ASSERT_LT_MEM``` | Tests whether the first n bytes at the first memory location is lesser than the n first bytes at the second memory location. | 126 | | ``` ASSERT_LESS_CMP ``` | ``` ASSERT_LT_CMP ``` | Tests whether the first value is lesser than the second value by using the passed comparator function. | 127 | | ``` ASSERT_LESS_EQUAL ``` | ``` ASSERT_LE ``` | Tests whether the first value is lesser than or equal to the second value. | 128 | | ``` ASSERT_LESS_EQUAL_PRECISION ``` | ``` ASSERT_LE_PRECISION ``` | Tests whether the first floating point value is lesser than or equal to the second floating point value using a user provided epsilon. | 129 | | ``` ASSERT_LESS_EQUAL_MEM ``` | ```ASSERT_LE_MEM``` | Tests whether the first n bytes at the first memory location is lesser than or equal to the n first bytes at the second memory location. | 130 | | ``` ASSERT_LESS_EQUAL_CMP ``` | ``` ASSERT_LE_CMP ``` | Tests whether the first value is lesser than or equal to the second value by using the passed comparator function. | 131 | 132 | ## Runner 133 | The runner is the program that executes the tests. 134 | 135 | #### Exit code 136 | The exit code is EXIT_SUCCESS (0) if all tests passed and EXIT_FAILURE (non-zero) if one or more tests failed. 137 | 138 | #### Options 139 | | Short | Long               | Description | 140 | | --- | --- | --- | 141 | | -v | --version | Prints the version number. | 142 | | -h | --help | Prints help/ usage information. | 143 | | -c | --no-color | Don't use any color when printing. | 144 | | -t | --timer | Display execution time for each test. | 145 | | -q | --quiet | No output. | 146 | | -s | --skip | Skips all tests in the passed list of test suits. The argument for this option should be a comma separated list of case-sensitive test suit names that you want to skip. | 147 | | -f | --SIGSEGV | Segmentation fault is handled like other test failures. | 148 | 149 | 150 | ## Contribute 151 | We welcome all contributions, please see the [contribution guidelines](.github/CONTRIBUTING.md). 152 | 153 | ## License 154 | 155 | This project is licensed under the MIT License - see [LICENSE.md](LICENSE.md) for details. 156 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ############################################### 4 | # Convenience script for building with CMake. # 5 | ############################################### 6 | 7 | # Make sure we are in the correct directory. 8 | cd $(dirname "$0") 9 | 10 | # Output diractory name / location 11 | OUTPUT="out" 12 | 13 | # Create output directory if it doesn't exist 14 | if [ ! -d $OUTPUT ] 15 | then 16 | mkdir $OUTPUT 17 | fi 18 | 19 | # Enter output directory 20 | cd $OUTPUT 21 | 22 | # CMake 23 | cmake .. 24 | 25 | # Stopping if CMake fails. 26 | if [ $? -ne 0 ]; then 27 | echo "CMake failed, stopping build." 28 | exit 1 29 | fi 30 | 31 | # Make 32 | make 33 | 34 | # Stopping if Make fails. 35 | if [ $? -ne 0 ]; then 36 | echo "Make failed, stopping build." 37 | exit 1 38 | fi 39 | 40 | -------------------------------------------------------------------------------- /doc/asserts.md: -------------------------------------------------------------------------------- 1 | # EzTest documentation - asserts 2 | Each assert is a macro prefixed with ```ASSERT_```. Some of the macros also have a short-hand version. The short-hand 3 | version has the same underlying functionality. 4 | 5 | --- 6 | 7 | ### Assert NULL 8 | Tests whether the provided pointer is ```NULL```. This test uses ```NULL``` as defined by ```stddef.h```. 9 | 10 | ##### Declaration 11 | ```C 12 | ASSERT_IS_NULL(const void *value); 13 | ``` 14 | ##### Parameters 15 | value The pointer to test for NULL. 16 | 17 | --- 18 | 19 | ### Assert not NULL 20 | Tests whether the provided pointer is non-```NULL```. This test uses ```NULL``` as defined by ```stddef.h```. 21 | 22 | ##### Declaration 23 | ```C 24 | ASSERT_IS_NOT_NULL(const void *value); 25 | ``` 26 | ##### Parameters 27 | value The pointer to test for NULL. 28 | 29 | --- 30 | 31 | ### Assert true 32 | Tests whether the passed condition is ```true```. This test uses the boolean definitions in ```stdbool.h```. 33 | 34 | ##### Declaration 35 | ```C 36 | ASSERT_IS_TRUE(const bool condition); 37 | ``` 38 | ##### Parameters 39 | condition The boolean condition to test. 40 | 41 | --- 42 | 43 | ### Assert false 44 | Tests whether the passed condition is ```false```. This test uses the boolean definitions in ```stdbool.h```. 45 | 46 | ##### Declaration 47 | ```C 48 | ASSERT_IS_FALSE(const bool condition); 49 | ``` 50 | ##### Parameters 51 | condition The boolean condition to test. 52 | 53 | --- 54 | 55 | ### Assert same 56 | Tests whether the two pointers refer to the same memory location. 57 | 58 | ##### Declaration 59 | ```C 60 | ASSERT_ARE_SAME(const void *expected, const void *actual); 61 | ``` 62 | ##### Parameters 63 | expected This is the value the tests expects. 64 | 65 | actual This is the value produced by the code under test. 66 | 67 | --- 68 | 69 | ### Assert not same 70 | Tests whether the two pointers refer to different memory locations. 71 | 72 | ##### Declaration 73 | ```C 74 | ASSERT_ARE_NOT_SAME(const void *unexpected, const void *actual); 75 | ``` 76 | ##### Parameters 77 | unexpected This is the value that should not occur. 78 | 79 | actual This is the value produced by the code under test. 80 | 81 | --- 82 | 83 | ### Assert NaN 84 | Tests whether the passed value is NaN. 85 | 86 | ##### Declaration 87 | ```C 88 | ASSERT_IS_NAN(float value); 89 | ``` 90 | ##### Parameters 91 | value The floating point value to check. 92 | 93 | --- 94 | 95 | ### Assert equal 96 | Tests whether the two values are equal. 97 | 98 | > The equality function for floating point numbers uses the epsilon macro from ```float.h``` in its equality test. It is therefore often better to use [ASSERT EQUAL PRECISION](#assert-equal-precision) when comparing floating point numbers (allowing application specific epsilon). 99 | 100 | ##### Declaration 101 | ```C 102 | ASSERT_ARE_EQUAL(T expected, T actual); 103 | 104 | ASSERT_EQ(T expected, T actual); 105 | ``` 106 | ##### Parameters 107 | expected This is the value that should occur. 108 | 109 | actual This is the value produced by the code under test. 110 | 111 | --- 112 | 113 | ### Assert equal precision 114 | Tests whether two floating point numbers are equal using a user provided epsilon. 115 | 116 | ##### Declaration 117 | ```C 118 | ASSERT_ARE_EQUAL_PRECISION(long double expected, long double actual, long double epsilon); 119 | 120 | ASSERT_EQ_PRECISION(long double expected, long double actual, long double epsilon); 121 | ``` 122 | ##### Parameters 123 | expected This is the value that is expected to be generated by the code under test. 124 | 125 | actual This is the value generated by the code under test. 126 | 127 | epsilon A floating point representing the precision required when testing for equality. 128 | 129 | --- 130 | 131 | ### Assert equal memory 132 | Tests whether the two values are equal by comparing each byte at the given memory locations. 133 | 134 | ##### Declaration 135 | ```C 136 | ASSERT_EQUAL_MEM(const void *expected, const void *actual, size_t size); 137 | 138 | ASSERT_EQ_MEM(const void *expected, const void *actual, size_t size); 139 | ``` 140 | ##### Parameters 141 | 142 | expected A pointer to the expected value. 143 | 144 | actual A pointer to the actual value. 145 | 146 | size The size of the passed types. 147 | 148 | --- 149 | 150 | ### Assert equal cmp 151 | Tests whether the two values are equal by using the passed comparator function. 152 | 153 | ##### Declaration 154 | ```C 155 | ASSERT_ARE_EQUAL_CMP(const void *expected, 156 | const void *actual, 157 | int(*cmp_fn)(const void *ptr1, const void *ptr2)); 158 | 159 | ASSERT_ARE_EQ_CMP(const void *expected, 160 | const void *actual, 161 | int(*cmp_fn)(const void *ptr1, const void *ptr2)); 162 | ``` 163 | ##### Parameters 164 | 165 | expected A pointer to the expected value. 166 | 167 | actual A pointer to the actual value. 168 | 169 | cmp_fn The comparator to use. This should return a negative value if the first parameter is less than the second parameter, 0 (zero) if the values are equal and a positive value if the first value is greater than the second value. 170 | 171 | --- 172 | 173 | ### Assert not equal 174 | Tests whether the two values are different. 175 | 176 | > The equality function for floating point numbers uses the epsilon macro from ```float.h``` in its equality test. It is therefore often better to use [ASSERT NOT EQUAL PRECISION](#assert-not-equal-precision) when comparing floating point numbers (allowing application specific epsilon). 177 | 178 | ##### Declaration 179 | ```C 180 | ASSERT_ARE_NOT_EQUAL(T unexpected, T actual); 181 | 182 | ASSERT_NE(T unexpected, T actual); 183 | ``` 184 | ##### Parameters 185 | 186 | unexpected This is the value that should not occur. 187 | 188 | actual This is the value produced by the code under test. 189 | 190 | --- 191 | 192 | ### Assert not equal precision 193 | Tests whether two floating point numbers are different using a user provided epsilon. 194 | 195 | ##### Declaration 196 | ```C 197 | ASSERT_ARE_NOT_EQUAL_PRECISION(long double unexpected, long double actual, long double epsilon); 198 | 199 | ASSERT_NE_PRECISION(T unexpected, T actual); 200 | ``` 201 | ##### Parameters 202 | 203 | unexpected This is the value that should not occur. 204 | 205 | actual This is the value produced by the code under test. 206 | 207 | epsilon A floating point representing the precision required when testing for equality. 208 | 209 | --- 210 | 211 | ### Assert not equal mem 212 | Tests whether the two values are different by comparing each byte at the given memory locations. 213 | 214 | ##### Declaration 215 | ```C 216 | ASSERT_NOT_EQUAL_MEM(const void *unexpected, const void *actual, size_t size); 217 | 218 | ASSERT_NE_MEM(const void *unexpected, const void *actual, size_t size); 219 | ``` 220 | ##### Parameters 221 | 222 | unexpected A pointer to the unexpected value. 223 | 224 | actual A pointer to the actual value. 225 | 226 | size The size of the passed types. 227 | 228 | --- 229 | ### Assert not equal cmp 230 | Tests whether the two values are different by using the passed comparator function. 231 | 232 | ##### Declaration 233 | ```C 234 | ASSERT_NOT_EQUAL_CMP(const void *unexpected, 235 | const void *actual, 236 | int(*cmp_fn)(const void *ptr1, const void *ptr2)); 237 | 238 | ASSERT_NE_CMP(const void *unexpected, 239 | const void *actual, 240 | int(*cmp_fn)(const void *ptr1, const void *ptr2)); 241 | ``` 242 | ##### Parameters 243 | 244 | unexpected The first value to compare. This is the value that should not occur. 245 | 246 | actual The second value to compare. This is the value that is generated by the code under test. 247 | 248 | cmp_fn The comparator to use. This should return a negative value if the first parameter is less than the second parameter, 0 (zero) if the values are equal and a positive value if the first value is greater than the second value. 249 | 250 | --- -------------------------------------------------------------------------------- /eztest/eztest.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @author havardt 4 | * 5 | * @license MIT 6 | * 7 | */ 8 | 9 | #ifndef EZTEST_H 10 | #define EZTEST_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | struct unit_test 18 | { 19 | char *test_name; 20 | char *test_suite; 21 | void (*setup_fn)(); 22 | void (*teardown_fn)(); 23 | void (*run_fn)(); 24 | 25 | /** Marks each unit test: used for test discovery. */ 26 | uint64_t marker; 27 | }; 28 | 29 | /** Represents the standard ok/ success result value for non-pointer return types. */ 30 | #define EZTEST_RESULT_OK 0 31 | 32 | /** Represents the standard error/ fail result value for non-pointer return types. */ 33 | #define EZTEST_RESULT_ERR (-1) 34 | 35 | #define EZTEST_MARKER 4242424242424242 36 | 37 | /** The max amount of bytes to print when printing value without type. */ 38 | #define EZTEST_MAX_PRINTABLE_LEN 16 39 | 40 | #define EZTEST_BASE_TEST_NAME "eztest_base_test" 41 | 42 | #define EZTEST_RUN_FN_NAME(suite, name) run_##suite##_##name 43 | 44 | #define EZTEST_SETUP_FN_NAME(suite) setup_##suite 45 | 46 | #define EZTEST_TEARDOWN_FN_NAME(suite) teardown_##suite 47 | 48 | #define EZTEST_STRUCT_NAME(suite, name) struct_##suite##_##name 49 | 50 | /** 51 | * Initializes the setup function for the given suite. 52 | * 53 | * @param suite The name of the test suite that this setup function belongs. 54 | * @note Each suite should only have one (1) setup function. 55 | */ 56 | #define SETUP(suite) static void EZTEST_SETUP_FN_NAME(suite)(void) 57 | 58 | /** 59 | * Initializes the teardown function for the given suite. 60 | * 61 | * @param suite The name of the test suite that this teardown function belongs. 62 | * @note Each suite should only have one (1) teardown function. 63 | */ 64 | #define TEARDOWN(suite) static void EZTEST_TEARDOWN_FN_NAME(suite)(void) 65 | 66 | #define EZTEST_UNIT_TEST_STRUCT(suite, name)\ 67 | static struct unit_test EZTEST_STRUCT_NAME(suite, name) __attribute__ ((used, section(".eztest"), aligned(1))) = {\ 68 | .test_name=#name,\ 69 | .test_suite=#suite,\ 70 | .setup_fn = NULL,\ 71 | .teardown_fn = NULL,\ 72 | .run_fn = EZTEST_RUN_FN_NAME(suite, name),\ 73 | .marker = EZTEST_MARKER\ 74 | } 75 | 76 | #define EZTEST_FULL_UNIT_TEST_STRUCT(suite, name)\ 77 | static struct unit_test EZTEST_STRUCT_NAME(suite, name) __attribute__ ((used, section(".eztest"), aligned(1))) = {\ 78 | .test_name=#name,\ 79 | .test_suite=#suite,\ 80 | .setup_fn = EZTEST_SETUP_FN_NAME(suite),\ 81 | .teardown_fn = EZTEST_TEARDOWN_FN_NAME(suite),\ 82 | .run_fn = EZTEST_RUN_FN_NAME(suite, name),\ 83 | .marker = EZTEST_MARKER\ 84 | } 85 | 86 | /** 87 | * Initialize a new unit test. 88 | * 89 | * @param suite The name of the test suite that this test belongs. 90 | * @param name The name of the test. 91 | * @note Suite and test-names must follow C naming rules. 92 | * Suite and test-name combination must be unique for the project. 93 | */ 94 | #define TEST(suite, name)\ 95 | static void EZTEST_RUN_FN_NAME(suite, name)(void);\ 96 | EZTEST_UNIT_TEST_STRUCT(suite, name);\ 97 | static void EZTEST_RUN_FN_NAME(suite, name)(void) 98 | 99 | /** 100 | * Initializes a new unit test with setup and teardown functions. 101 | * 102 | * @param suite The name of the test suite that this test belongs. 103 | * @param name The name of the test. 104 | * @note Suite and test-names must follow C naming rules. 105 | * Suite and test-name combination must be unique for the project. 106 | */ 107 | #define TEST_FULL(suite, name)\ 108 | static void EZTEST_RUN_FN_NAME(suite, name)(void);\ 109 | EZTEST_FULL_UNIT_TEST_STRUCT(suite, name);\ 110 | static void EZTEST_RUN_FN_NAME(suite, name)(void) 111 | 112 | void assert_is_null(const void *value, char *file, int line); 113 | #define ASSERT_IS_NULL(value) assert_is_null(value, __FILE__, __LINE__); 114 | 115 | void assert_is_not_null(const void *value, char *file, int line); 116 | #define ASSERT_IS_NOT_NULL(value) assert_is_not_null(value, __FILE__, __LINE__); 117 | 118 | void assert_is_true(bool condition, char *file, int line); 119 | #define ASSERT_IS_TRUE(condition) assert_is_true(condition, __FILE__, __LINE__); 120 | 121 | void assert_is_false(bool condition, char *file, int line); 122 | #define ASSERT_IS_FALSE(condition) assert_is_false(condition, __FILE__, __LINE__); 123 | 124 | void assert_are_same(const void *expected, const void *actual, char *file, int line); 125 | #define ASSERT_ARE_SAME(expected, actual) assert_are_same(expected, actual, __FILE__, __LINE__); 126 | 127 | void assert_are_not_same(const void *unexpected, const void *actual, char *file, int line); 128 | #define ASSERT_ARE_NOT_SAME(unexpected, actual) assert_are_not_same(unexpected, actual, __FILE__, __LINE__); 129 | 130 | #ifdef NAN 131 | 132 | void assert_is_nan(float value, char *file, int line); 133 | #define ASSERT_IS_NAN(value) assert_is_nan(value, __FILE__, __LINE__); 134 | 135 | #endif 136 | 137 | void assert_are_equal_ch (char expected, char actual, char *file, int line); 138 | void assert_are_equal_sch (signed char expected, signed char actual, char *file, int line); 139 | void assert_are_equal_uch (unsigned char expected, unsigned char actual, char *file, int line); 140 | void assert_are_equal_int (intmax_t expected, intmax_t actual, char *file, int line); 141 | void assert_are_equal_uint(uintmax_t expected, uintmax_t actual, char *file, int line); 142 | void assert_are_equal_dbl (long double expected, long double actual, char *file, int line); 143 | void assert_are_equal_str (const char * expected, const char * actual, char *file, int line); 144 | void assert_are_equal_wstr(const wchar_t * expected, const wchar_t * actual, char *file, int line); 145 | void assert_are_equal (const void * expected, const void * actual, char *file, int line); 146 | /** 147 | * Tests whether the two values are equal. 148 | * 149 | * @param expected The first value to compare. This is the value the tests expects. 150 | * @param actual The second value to compare. This is the value produced by the code under test. 151 | */ 152 | #define ASSERT_ARE_EQUAL(expected, actual) _Generic((expected),\ 153 | char : assert_are_equal_ch, \ 154 | signed char : assert_are_equal_sch, \ 155 | unsigned char : assert_are_equal_uch, \ 156 | \ 157 | short : assert_are_equal_int, \ 158 | unsigned short : assert_are_equal_uint, \ 159 | \ 160 | int : assert_are_equal_int, \ 161 | unsigned int : assert_are_equal_uint, \ 162 | \ 163 | long : assert_are_equal_int, \ 164 | unsigned long : assert_are_equal_uint, \ 165 | \ 166 | long long : assert_are_equal_int, \ 167 | unsigned long long : assert_are_equal_uint, \ 168 | \ 169 | float : assert_are_equal_dbl, \ 170 | double : assert_are_equal_dbl, \ 171 | long double : assert_are_equal_dbl, \ 172 | \ 173 | char * : assert_are_equal_str, \ 174 | const char * : assert_are_equal_str, \ 175 | \ 176 | wchar_t * : assert_are_equal_wstr, \ 177 | const wchar_t * : assert_are_equal_wstr, \ 178 | \ 179 | default : assert_are_equal)(expected, actual, __FILE__, __LINE__) 180 | 181 | /** 182 | * @see ASSERT_ARE_EQUAL(expected, actual); 183 | * 184 | * @remarks This is a short-hand for ASSERT_ARE_EQUAL. 185 | */ 186 | #define ASSERT_EQ(expected, actual) ASSERT_ARE_EQUAL(expected, actual) 187 | 188 | void assert_are_not_equal_ch (char unexpected, char actual, char *file, int line); 189 | void assert_are_not_equal_sch (signed char unexpected, signed char actual, char *file, int line); 190 | void assert_are_not_equal_uch (unsigned char unexpected, unsigned char actual, char *file, int line); 191 | void assert_are_not_equal_int (intmax_t unexpected, intmax_t actual, char *file, int line); 192 | void assert_are_not_equal_uint(uintmax_t unexpected, uintmax_t actual, char *file, int line); 193 | void assert_are_not_equal_dbl (long double unexpected, long double actual, char *file, int line); 194 | void assert_are_not_equal_str (const char * unexpected, const char * actual, char *file, int line); 195 | void assert_are_not_equal_wstr(const wchar_t * unexpected, const wchar_t * actual, char *file, int line); 196 | void assert_are_not_equal (const void * unexpected, const void * actual, char *file, int line); 197 | /** 198 | * Tests for inequality. 199 | * 200 | * @param unexpected The first value to compare. This is the value that should not occur. 201 | * @param actual The second value to compare. This is the value produced by the code under test. 202 | * @note The equality function for floating point numbers uses the epsilon macro from float.h 203 | * in its equality test. It is therefore often better to use assert_are_equal_precision() 204 | * and provide the application specific epsilon. 205 | */ 206 | #define ASSERT_ARE_NOT_EQUAL(unexpected, actual) _Generic((unexpected),\ 207 | char : assert_are_not_equal_ch, \ 208 | signed char : assert_are_not_equal_sch, \ 209 | unsigned char : assert_are_not_equal_uch, \ 210 | \ 211 | short : assert_are_not_equal_int, \ 212 | unsigned short : assert_are_not_equal_uint, \ 213 | \ 214 | int : assert_are_not_equal_int, \ 215 | unsigned int : assert_are_not_equal_uint, \ 216 | \ 217 | long : assert_are_not_equal_int, \ 218 | unsigned long : assert_are_not_equal_uint, \ 219 | \ 220 | long long : assert_are_not_equal_int, \ 221 | unsigned long long : assert_are_not_equal_uint, \ 222 | \ 223 | float : assert_are_not_equal_dbl, \ 224 | double : assert_are_not_equal_dbl, \ 225 | long double : assert_are_not_equal_dbl, \ 226 | \ 227 | char * : assert_are_not_equal_str, \ 228 | const char * : assert_are_not_equal_str, \ 229 | \ 230 | wchar_t * : assert_are_not_equal_wstr, \ 231 | const wchar_t * : assert_are_not_equal_wstr, \ 232 | \ 233 | default : assert_are_not_equal)(unexpected, actual, __FILE__, __LINE__) 234 | 235 | /** 236 | * @see ASSERT_ARE_NOT_EQUAL(unexpected, actual); 237 | * 238 | * @remarks This is a short-hand for ASSERT_ARE_NOT_EQUAL. 239 | */ 240 | #define ASSERT_NE(unexpected, actual) ASSERT_ARE_NOT_EQUAL(unexpected, actual) 241 | 242 | void assert_equal_mem(const void *expected, const void *actual, size_t size, char *file, int line); 243 | /** 244 | * Checks for equality by comparing each byte at the given memory locations. 245 | * 246 | * @param expected A pointer to the expected value. 247 | * @param actual A pointer to the actual value. 248 | * @param size The size of the passed types. 249 | */ 250 | #define ASSERT_EQUAL_MEM(expected, actual, size)\ 251 | assert_equal_mem(expected, actual, size, __FILE__, __LINE__) 252 | 253 | /** 254 | * @see ASSERT_EQUAL_MEM(expected, actual, size); 255 | * 256 | * @remarks This is a short-hand for ASSERT_EQUAL_MEM. 257 | */ 258 | #define ASSERT_EQ_MEM(expected, actual, size) ASSERT_EQUAL_MEM(expected, actual, size) 259 | 260 | void assert_not_equal_mem(const void *unexpected, const void *actual, size_t size, char *file, int line); 261 | /** 262 | * Checks for inequality by comparing each byte at the given memory locations. 263 | * 264 | * @param unexpected A pointer to the unexpected value. 265 | * @param actual A pointer to the actual value. 266 | * @param size The size of the passed types. 267 | */ 268 | #define ASSERT_NOT_EQUAL_MEM(unexpected, actual, size)\ 269 | assert_not_equal_mem(unexpected, actual, size, __FILE__, __LINE__) 270 | 271 | /** 272 | * @see ASSERT_NOT_EQUAL_MEM(unexpected, actual, size); 273 | * 274 | * @remarks This is a short-hand for ASSERT_NOT_EQUAL_MEM. 275 | */ 276 | #define ASSERT_NE_MEM(unexpected, actual, size) ASSERT_NOT_EQUAL_MEM(unexpected, actual, size) 277 | 278 | void assert_greater_mem(const void *greater, const void *lesser, size_t size, char *file, int line); 279 | /** 280 | * Tests whether the first value is greater than the second value by comparing 281 | * the bytes at the memory location. 282 | * 283 | * @param greater The first value to compare. This is the value the user 284 | * expects to be greater than the second value. 285 | * 286 | * @param lesser The second value to compare. This is the value the user 287 | * expects to be lesser than the first value. 288 | */ 289 | #define ASSERT_GREATER_MEM(greater, lesser, size)\ 290 | assert_greater_mem(greater, lesser, size, __FILE__, __LINE__) 291 | 292 | #define ASSERT_GT_MEM(greater, lesser, size)\ 293 | assert_greater_mem(greater, lesser, size, __FILE__, __LINE__) 294 | 295 | void assert_greater_equal_mem(const void *ge, const void *le, size_t size, char *file, int line); 296 | /** 297 | * Tests whether the first value is greater than or equal to the second value 298 | * by comparing the bytes at the memory location. 299 | * 300 | * @param ge The first value to compare. This is the value the user 301 | * expects to be greater than or equal to the second value. 302 | * 303 | * @param le The second value to compare. This is the value the user 304 | * expects to be lesser than or equal to the first value. 305 | */ 306 | #define ASSERT_GREATER_EQUAL_MEM(ge, le, size)\ 307 | assert_greater_equal_mem(ge, le, size, __FILE__, __LINE__) 308 | 309 | #define ASSERT_GE_MEM(ge, le, size)\ 310 | assert_greater_equal_mem(ge, le, size, __FILE__, __LINE__) 311 | 312 | void assert_less_mem(const void *lesser, const void *greater, size_t size, char *file, int line); 313 | /** 314 | * Tests whether the first value is less than the second value by comparing 315 | * the bytes at the memory location. 316 | * 317 | * @param lesser The first value to compare. This is the value the user 318 | * expects to be lesser than the second value. 319 | * 320 | * @param greater The second value to compare. This is the value the user 321 | * expects to be greater than the first value. 322 | */ 323 | #define ASSERT_LESS_MEM(lesser, greater, size)\ 324 | assert_less_mem(lesser, greater, size, __FILE__, __LINE__) 325 | 326 | #define ASSERT_LT_MEM(lesser, greater, size)\ 327 | assert_less_mem(lesser, greater, size, __FILE__, __LINE__) 328 | 329 | void assert_less_equal_mem(const void *le, const void *ge, size_t size, char *file, int line); 330 | /** 331 | * Tests whether the first value is less than or equal to the second value 332 | * by comparing the bytes at the memory location. 333 | * 334 | * @param le The first value to compare. This is the value the user 335 | * expects to be lesser than or equal to the second value. 336 | * 337 | * @param ge The second value to compare. This is the value the user 338 | * expects to be greater than or equal to the first value. 339 | */ 340 | #define ASSERT_LESS_EQUAL_MEM(le, ge, size)\ 341 | assert_less_equal_mem(le, ge, size, __FILE__, __LINE__) 342 | 343 | #define ASSERT_LE_MEM(le, ge, size)\ 344 | assert_less_equal_mem(le, ge, size, __FILE__, __LINE__) 345 | 346 | 347 | void assert_are_equal_cmp(const void *expected, 348 | const void *actual, 349 | int(*cmp_fn)(const void *ptr1, const void *ptr2), 350 | char *file, 351 | int line); 352 | /** 353 | * Tests whether the first value is equal to the second value 354 | * using the passed comparator. 355 | * 356 | * @param expected The first value to compare. This is the value the user 357 | * expects. 358 | * 359 | * @param actual The second value to compare. This is the value that is 360 | * generated by the code under test. 361 | * 362 | * @param cmp_fn The comparator to use. This should return a negative value 363 | * if the first parameter is less than the second parameter, 364 | * 0 (zero) if the values are equal and a positive value if 365 | * the first value is greater than the second value. 366 | */ 367 | #define ASSERT_ARE_EQUAL_CMP(expected, actual, cmp_fn)\ 368 | assert_are_equal_cmp(expected, actual, cmp_fn, __FILE__, __LINE__) 369 | 370 | /** 371 | * @see ASSERT_ARE_EQUAL_CMP(expected, actual, cmp_fn); 372 | * 373 | * @remarks This is a short-hand for ASSERT_ARE_EQUAL_CMP. 374 | */ 375 | #define ASSERT_EQ_CMP(expected, actual, cmp_fn) ASSERT_ARE_EQUAL_CMP(expected, actual, cmp_fn) 376 | 377 | void assert_are_not_equal_cmp(const void *unexpected, 378 | const void *actual, 379 | int(*cmp_fn)(const void *ptr1, const void *ptr2), 380 | char *file, 381 | int line); 382 | /** 383 | * Tests whether the first value is different than the second value 384 | * using the passed comparator. 385 | * 386 | * @param unexpected The first value to compare. This is the value that 387 | * should not occur. 388 | * 389 | * @param actual The second value to compare. This is the value that is 390 | * generated by the code under test. 391 | * 392 | * @param cmp_fn The comparator to use. This should return a negative value 393 | * if the first parameter is less than the second parameter, 394 | * 0 (zero) if the values are equal and a positive value if 395 | * the first value is greater than the second value.* 396 | */ 397 | #define ASSERT_ARE_NOT_EQUAL_CMP(unexpected, actual, cmp_fn)\ 398 | assert_are_not_equal_cmp(unexpected, actual, cmp_fn, __FILE__, __LINE__) 399 | 400 | void assert_greater_cmp(const void *greater, 401 | const void *lesser, 402 | int(*cmp_fn)(const void *ptr1, const void *ptr2), 403 | char *file, 404 | int line); 405 | /** 406 | * Tests whether the first value is greater than the second value 407 | * using the passed comparator. 408 | * 409 | * @param greater The first value to compare. This is the value the user 410 | * expects to be greater than the second value. 411 | * 412 | * @param lesser The second value to compare. This is the value that is 413 | * expected to be lesser than the first value. 414 | * 415 | * @param cmp_fn The comparator to use. This should return a negative value 416 | * if the first parameter is less than the second parameter, 417 | * 0 (zero) if the values are equal and a positive value if 418 | * the first value is greater than the second value. 419 | */ 420 | #define ASSERT_GREATER_CMP(greater, lesser, cmp_fn)\ 421 | assert_greater_cmp(greater, lesser, cmp_fn, __FILE__, __LINE__) 422 | 423 | /** 424 | * @see ASSERT_GREATER_CMP(greater, lesser, cmp_fn); 425 | * 426 | * @remarks This is a short-hand for ASSERT_GREATER_CMP. 427 | */ 428 | #define ASSERT_GT_CMP(greater, lesser, cmp_fn)\ 429 | ASSERT_GREATER_CMP(greater, lesser, cmp_fn) 430 | 431 | void assert_less_cmp(const void *lesser, 432 | const void *greater, 433 | int(*cmp_fn)(const void *ptr1, const void *ptr2), 434 | char *file, 435 | int line); 436 | /** 437 | * Tests whether the first value is lesser than the second value 438 | * using the passed comparator. 439 | * 440 | * @param lesser The first value to compare. This is the value the user 441 | * expects to be lesser than the second value. This value 442 | * is placed as the first parameter of the custom comparator. 443 | * 444 | * @param greater The second value to compare. This is the value that is 445 | * expected to be greater than the first value. This value 446 | * is placed as the second parameter of the custom comparator. 447 | * 448 | * @param cmp_fn The comparator to use. This should return a negative value 449 | * if the first parameter is less than the second parameter, 450 | * 0 (zero) if the values are equal and a positive value if 451 | * the first value is greater than the second value. 452 | */ 453 | #define ASSERT_LESS_CMP(lesser, greater, cmp_fn)\ 454 | assert_less_cmp(lesser, greater, cmp_fn, __FILE__, __LINE__) 455 | 456 | /** 457 | * @see ASSERT_LESS_CMP(lesser, greater, cmp_fn); 458 | * 459 | * @remarks This is a short-hand for ASSERT_LESS_CMP. 460 | */ 461 | #define ASSERT_LT_CMP(lesser, greater, cmp_fn)\ 462 | ASSERT_LESS_CMP(lesser, greater, cmp_fn) 463 | 464 | void assert_less_equal_cmp(const void *le, 465 | const void *ge, 466 | int(*cmp_fn)(const void *ptr1, const void *ptr2), 467 | char *file, 468 | int line); 469 | /** 470 | * Tests whether the first value is lesser or equal to the second value 471 | * using the passed comparator. 472 | * 473 | * @param le The first value to compare. This is the value the user expects 474 | * to be lesser than or equal to the second value. This value is 475 | * placed as the first parameter of the custom comparator. 476 | * 477 | * @param ge The second value to compare. This is the value that is expected 478 | * to be greater than or equal to the first value. This value is 479 | * placed as the second parameter of the custom comparator. 480 | * 481 | * @param cmp_fn The comparator to use. This should return a negative value 482 | * if the first parameter is less than the second parameter, 483 | * 0 (zero) if the values are equal and a positive value if 484 | * the first value is greater than the second value. 485 | */ 486 | #define ASSERT_LESS_EQUAL_CMP(le, ge, cmp_fn)\ 487 | assert_less_equal_cmp(le, ge, cmp_fn, __FILE__, __LINE__) 488 | 489 | /** 490 | * @see ASSERT_LESS_EQUAL_CMP(le, ge, cmp_fn); 491 | * 492 | * @remarks This is a short-hand for ASSERT_LESS_EQUAL_CMP. 493 | */ 494 | #define ASSERT_LE_CMP(le, ge, cmp_fn)\ 495 | ASSERT_LESS_EQUAL_CMP(le, ge, cmp_fn) 496 | 497 | void assert_greater_equal_cmp(const void *ge, 498 | const void *le, 499 | int(*cmp_fn)(const void *ptr1, const void *ptr2), 500 | char *file, 501 | int line); 502 | /** 503 | * Tests whether the first value is greater than or equal to the second 504 | * value using the passed comparator. 505 | * 506 | * @param ge The first value to compare. This is the value the user 507 | * expects to be greater than or equal to the second value. 508 | * 509 | * @param le The second value to compare. This is the value that is 510 | * expected to be lesser than or equal to the first value. 511 | */ 512 | #define ASSERT_GREATER_EQUAL_CMP(ge, le, cmp_fn)\ 513 | assert_greater_equal_cmp(ge, le, cmp_fn, __FILE__, __LINE__) 514 | 515 | /** 516 | * @see ASSERT_GREATER_EQUAL_CMP(ge, le, cmp_fn); 517 | * 518 | * @remarks This is a short-hand for ASSERT_GREATER_EQUAL_CMP. 519 | */ 520 | #define ASSERT_GE_CMP(ge, le, cmp_fn)\ 521 | ASSERT_GREATER_EQUAL_CMP(ge, le, cmp_fn) 522 | 523 | /** 524 | * @see ASSERT_ARE_NOT_EQUAL_CMP(unexpected, actual, cmp_fn); 525 | * 526 | * @remarks This is a short-hand for ASSERT_ARE_NOT_EQUAL_CMP. 527 | */ 528 | #define ASSERT_NE_CMP(unexpected, actual, cmp_fn) ASSERT_ARE_NOT_EQUAL_CMP(unexpected, actual, cmp_fn) 529 | 530 | void assert_are_equal_precision(long double expected, long double actual, long double epsilon, char *file, int line); 531 | /** 532 | * Tests for equality between two floating point numbers. 533 | * 534 | * @param expected The first value to compare. This is the value that is expected 535 | * to be generated by the code under test. 536 | * 537 | * @param actual The second value to compare. This is the value generated by the 538 | * code under test. 539 | * 540 | * @param epsilon A floating point representing the precision required when testing 541 | * for equality. 542 | */ 543 | #define ASSERT_ARE_EQUAL_PRECISION(expected, actual, epsilon)\ 544 | assert_are_equal_precision(expected, actual, epsilon, __FILE__, __LINE__) 545 | 546 | /** 547 | * @see ASSERT_ARE_EQUAL_PRECISION(expected, actual, epsilon); 548 | * 549 | * @remarks This is a short-hand for ASSERT_ARE_EQUAL_PRECISION. 550 | */ 551 | #define ASSERT_EQ_PRECISION(expected, actual, epsilon) ASSERT_ARE_EQUAL_PRECISION(expected, actual, epsilon) 552 | 553 | void assert_are_not_equal_precision(long double unexpected, 554 | long double actual, 555 | long double epsilon, 556 | char * file, 557 | int line); 558 | /** 559 | * Tests for inequality between two floating point numbers. 560 | * 561 | * @param unexpected The first value to compare. 562 | * 563 | * @param actual The second value to compare. This is the value generated by the 564 | * code under test. 565 | * 566 | * @param epsilon A floating point representing the precision required when testing 567 | * for equality. 568 | */ 569 | #define ASSERT_ARE_NOT_EQUAL_PRECISION(unexpected, actual, epsilon)\ 570 | assert_are_not_equal_precision(unexpected, actual, epsilon, __FILE__, __LINE__) 571 | 572 | /** 573 | * @see ASSERT_ARE_NOT_EQUAL_PRECISION(unexpected, actual, epsilon); 574 | * 575 | * @remarks This is a short-hand for ASSERT_ARE_NOT_EQUAL_PRECISION. 576 | */ 577 | #define ASSERT_NE_PRECISION(unexpected, actual, epsilon) ASSERT_ARE_NOT_EQUAL_PRECISION(unexpected, actual, epsilon) 578 | 579 | void assert_greater_ch (char greater, char lesser, char *file, int line); 580 | void assert_greater_sch (signed char greater, signed char lesser, char *file, int line); 581 | void assert_greater_uch (unsigned char greater, unsigned char lesser, char *file, int line); 582 | void assert_greater_int (intmax_t greater, intmax_t lesser, char *file, int line); 583 | void assert_greater_uint(uintmax_t greater, uintmax_t lesser, char *file, int line); 584 | void assert_greater_dbl (long double greater, long double lesser, char *file, int line); 585 | void assert_greater_str (const char * greater, const char * lesser, char *file, int line); 586 | void assert_greater_wstr(const wchar_t * greater, const wchar_t * lesser, char *file, int line); 587 | void assert_greater (const void * greater, const void * lesser, char *file, int line); 588 | /** 589 | * Tests whether the first value is greater than the second value. 590 | * 591 | * @param greater The first value to compare. This is the value the user 592 | * expects to be greater than the second value. 593 | * 594 | * @param lesser The second value to compare. This is the value the user 595 | * expects to be lesser than the first value. 596 | */ 597 | #define ASSERT_GREATER(greater, lesser) _Generic((greater),\ 598 | char : assert_greater_ch, \ 599 | signed char : assert_greater_sch, \ 600 | unsigned char : assert_greater_uch, \ 601 | \ 602 | short : assert_greater_int, \ 603 | unsigned short : assert_greater_uint, \ 604 | \ 605 | int : assert_greater_int, \ 606 | unsigned int : assert_greater_uint, \ 607 | \ 608 | long : assert_greater_int, \ 609 | unsigned long : assert_greater_uint, \ 610 | \ 611 | long long : assert_greater_int, \ 612 | unsigned long long : assert_greater_uint, \ 613 | \ 614 | float : assert_greater_dbl, \ 615 | double : assert_greater_dbl, \ 616 | long double : assert_greater_dbl, \ 617 | \ 618 | char * : assert_greater_str, \ 619 | const char * : assert_greater_str, \ 620 | \ 621 | wchar_t * : assert_greater_wstr, \ 622 | const wchar_t * : assert_greater_wstr, \ 623 | \ 624 | default : assert_greater)(greater, lesser, __FILE__, __LINE__) 625 | 626 | /** 627 | * @see ASSERT_GREATER(greater, less); 628 | * 629 | * @remarks This is just a short-hand for ASSERT_GREATER. 630 | */ 631 | #define ASSERT_GT(greater, lesser) ASSERT_GREATER(greater, lesser) 632 | 633 | void assert_greater_precision(long double greater, 634 | long double lesser, 635 | long double epsilon, 636 | char * file, 637 | int line); 638 | 639 | /** 640 | * Tests whether the first value is greater than the second value. 641 | * 642 | * @param greater The first floating point value to compare. This is the value the user 643 | * expects to be greater than the second value. 644 | * 645 | * @param lesser The second floating point value to compare. This is the value the user 646 | * expects to be lesser than the first value. 647 | * 648 | * @param epsilon A floating point representing the precision required when testing 649 | * for equality. 650 | */ 651 | #define ASSERT_GREATER_PRECISION(greater, less, epsilon)\ 652 | assert_greater_precision(greater, less, epsilon, __FILE__, __LINE__) 653 | 654 | /** 655 | * @see ASSERT_GREATER_PRECISION(greater, less, epsilon); 656 | * 657 | * @remarks This is just a short-hand for ASSERT_GREATER_PRECISION. 658 | */ 659 | #define ASSERT_GT_PRECISION(greater, less, epsilon)\ 660 | assert_greater_precision(greater, less, epsilon, __FILE__, __LINE__) 661 | 662 | void assert_greater_equal_ch (char ge, char le, char *file, int line); 663 | void assert_greater_equal_sch (signed char ge, signed char le, char *file, int line); 664 | void assert_greater_equal_uch (unsigned char ge, unsigned char le, char *file, int line); 665 | void assert_greater_equal_int (intmax_t ge, intmax_t le, char *file, int line); 666 | void assert_greater_equal_uint(uintmax_t ge, uintmax_t le, char *file, int line); 667 | void assert_greater_equal_dbl (long double ge, long double le, char *file, int line); 668 | void assert_greater_equal_str (const char * ge, const char * le, char *file, int line); 669 | void assert_greater_equal_wstr(const wchar_t * ge, const wchar_t * le, char *file, int line); 670 | void assert_greater_equal (const void * ge, const void * le, char *file, int line); 671 | /** 672 | * Tests whether the first value is greater than or equal to the second value. 673 | * 674 | * @param greater The first value to compare. This is the value the user 675 | * expects to be greater than or equal to the second value. 676 | * 677 | * @param lesser The second value to compare. This is the value the user 678 | * expects to be lesser than or equal to the first value. 679 | */ 680 | #define ASSERT_GREATER_EQUAL(ge, le) _Generic((ge),\ 681 | char : assert_greater_equal_ch, \ 682 | signed char : assert_greater_equal_sch, \ 683 | unsigned char : assert_greater_equal_uch, \ 684 | \ 685 | short : assert_greater_equal_int, \ 686 | unsigned short : assert_greater_equal_uint, \ 687 | \ 688 | int : assert_greater_equal_int, \ 689 | unsigned int : assert_greater_equal_uint, \ 690 | \ 691 | long : assert_greater_equal_int, \ 692 | unsigned long : assert_greater_equal_uint, \ 693 | \ 694 | long long : assert_greater_equal_int, \ 695 | unsigned long long : assert_greater_equal_uint, \ 696 | \ 697 | float : assert_greater_equal_dbl, \ 698 | double : assert_greater_equal_dbl, \ 699 | long double : assert_greater_equal_dbl, \ 700 | \ 701 | char * : assert_greater_equal_str, \ 702 | const char * : assert_greater_equal_str, \ 703 | \ 704 | wchar_t * : assert_greater_equal_wstr, \ 705 | const wchar_t * : assert_greater_equal_wstr, \ 706 | \ 707 | default : assert_greater_equal)(ge, le, __FILE__, __LINE__) 708 | 709 | /** 710 | * @see ASSERT_GREATER_EQUAL(ge, le); 711 | * 712 | * @remarks This is just a short-hand for ASSERT_GREATER_EQUAL. 713 | */ 714 | #define ASSERT_GE(ge, le) ASSERT_GREATER_EQUAL(ge, le) 715 | 716 | void assert_greater_equal_precision(long double ge, 717 | long double le, 718 | long double epsilon, 719 | char *file, 720 | int line); 721 | 722 | /** 723 | * Tests whether the first value is greater than or equal to the second value. 724 | * 725 | * @param ge The first floating point value to compare. This is the value the user 726 | * expects to be greater than or equal to the second value. 727 | * 728 | * @param le The second floating point value to compare. This is the value the user 729 | * expects to be lesser than or equal to the first value. 730 | * 731 | * @param epsilon A floating point representing the precision required when testing 732 | * for equality. 733 | */ 734 | #define ASSERT_GREATER_EQUAL_PRECISION(ge, le, epsilon)\ 735 | assert_greater_equal_precision(ge, le, epsilon, __FILE__, __LINE__) 736 | 737 | /** 738 | * @see ASSERT_GREATER_EQUAL_PRECISION(ge, le, epsilon); 739 | * 740 | * @remarks This is just a short-hand for ASSERT_GREATER_EQUAL_PRECISION. 741 | */ 742 | #define ASSERT_GE_PRECISION(ge, le, epsilon)\ 743 | assert_greater_equal_precision(ge, le, epsilon, __FILE__, __LINE__) 744 | 745 | void assert_less_ch (char lesser, char greater, char *file, int line); 746 | void assert_less_sch (signed char lesser, signed char greater, char *file, int line); 747 | void assert_less_uch (unsigned char lesser, unsigned char greater, char *file, int line); 748 | void assert_less_int (intmax_t lesser, intmax_t greater, char *file, int line); 749 | void assert_less_uint(uintmax_t lesser, uintmax_t greater, char *file, int line); 750 | void assert_less_dbl (long double lesser, long double greater, char *file, int line); 751 | void assert_less_str (const char *lesser, const char *greater, char *file, int line); 752 | void assert_less_wstr(const wchar_t *lesser, const wchar_t *greater, char *file, int line); 753 | void assert_less (const void *lesser, const void *greater, char *file, int line); 754 | /** 755 | * Tests whether the first value is lesser than the second value. 756 | * 757 | * @param lesser The first value to compare. This is the value the user 758 | * expects to be lesser than the second value. 759 | * 760 | * @param greater The second value to compare. This is the value the user 761 | * expects to be greater than the first value. 762 | */ 763 | #define ASSERT_LESS(lesser, greater) _Generic((lesser),\ 764 | char : assert_less_ch, \ 765 | signed char : assert_less_sch, \ 766 | unsigned char : assert_less_uch, \ 767 | \ 768 | short : assert_less_int, \ 769 | unsigned short : assert_less_uint, \ 770 | \ 771 | int : assert_less_int, \ 772 | unsigned int : assert_less_uint, \ 773 | \ 774 | long : assert_less_int, \ 775 | unsigned long : assert_less_uint, \ 776 | \ 777 | long long : assert_less_int, \ 778 | unsigned long long : assert_less_uint, \ 779 | \ 780 | float : assert_less_dbl, \ 781 | double : assert_less_dbl, \ 782 | long double : assert_less_dbl, \ 783 | \ 784 | char * : assert_less_str, \ 785 | const char * : assert_less_str, \ 786 | \ 787 | wchar_t * : assert_less_wstr, \ 788 | const wchar_t * : assert_less_wstr, \ 789 | \ 790 | default : assert_less)(lesser, greater, __FILE__, __LINE__) 791 | 792 | /** 793 | * @see ASSERT_LESS(lesser, greater); 794 | * 795 | * @remarks This is just a short-hand for ASSERT_LESS. 796 | */ 797 | #define ASSERT_LT(lesser, greater) ASSERT_LESS(lesser, greater) 798 | 799 | void assert_less_precision(long double lesser, 800 | long double greater, 801 | long double epsilon, 802 | char *file, 803 | int line); 804 | 805 | /** 806 | * Tests whether the first value is lesser than the second value. 807 | * 808 | * @param lesser The first floating point value to compare. This is the value the user 809 | * expects to be lesser than the second value. 810 | * 811 | * @param greater The second floating point value to compare. This is the value the user 812 | * expects to be greater than the first value. 813 | * 814 | * @param epsilon A floating point representing the precision required when testing 815 | * for equality. 816 | */ 817 | #define ASSERT_LESS_PRECISION(lesser, greater, epsilon)\ 818 | assert_less_precision(lesser, greater, epsilon, __FILE__, __LINE__) 819 | 820 | /** 821 | * @see ASSERT_LESS_PRECISION(lesser, greater, epsilon); 822 | * 823 | * @remarks This is just a short-hand for ASSERT_LESS_PRECISION. 824 | */ 825 | #define ASSERT_LT_PRECISION(lesser, greater, epsilon)\ 826 | assert_less_precision(lesser, greater, epsilon, __FILE__, __LINE__) 827 | 828 | void assert_less_equal_ch (char le, char ge, char *file, int line); 829 | void assert_less_equal_sch (signed char le, signed char ge, char *file, int line); 830 | void assert_less_equal_uch (unsigned char le, unsigned char ge, char *file, int line); 831 | void assert_less_equal_int (intmax_t le, intmax_t ge, char *file, int line); 832 | void assert_less_equal_uint(uintmax_t le, uintmax_t ge, char *file, int line); 833 | void assert_less_equal_dbl (long double le, long double ge, char *file, int line); 834 | void assert_less_equal_str (const char *le, const char *ge, char *file, int line); 835 | void assert_less_equal_wstr(const wchar_t *le, const wchar_t *ge, char *file, int line); 836 | void assert_less_equal (const void *le, const void *ge, char *file, int line); 837 | /** 838 | * Tests whether the first value is lesser than or equal to the second value. 839 | * 840 | * @param le The first value to compare. This is the value the user 841 | * expects to be lesser than or equal to the second value. 842 | * 843 | * @param ge The second value to compare. This is the value the user 844 | * expects to be greater than or equal to the first value. 845 | */ 846 | #define ASSERT_LESS_EQUAL(le, ge) _Generic((le),\ 847 | char : assert_less_equal_ch, \ 848 | signed char : assert_less_equal_sch, \ 849 | unsigned char : assert_less_equal_uch, \ 850 | \ 851 | short : assert_less_equal_int, \ 852 | unsigned short : assert_less_equal_uint, \ 853 | \ 854 | int : assert_less_equal_int, \ 855 | unsigned int : assert_less_equal_uint, \ 856 | \ 857 | long : assert_less_equal_int, \ 858 | unsigned long : assert_less_equal_uint, \ 859 | \ 860 | long long : assert_less_equal_int, \ 861 | unsigned long long : assert_less_equal_uint, \ 862 | \ 863 | float : assert_less_equal_dbl, \ 864 | double : assert_less_equal_dbl, \ 865 | long double : assert_less_equal_dbl, \ 866 | \ 867 | char * : assert_less_equal_str, \ 868 | const char * : assert_less_equal_str, \ 869 | \ 870 | wchar_t * : assert_less_equal_wstr, \ 871 | const wchar_t * : assert_less_equal_wstr, \ 872 | \ 873 | default : assert_less_equal)(le, ge, __FILE__, __LINE__) 874 | 875 | /** 876 | * @see ASSERT_LESS_EQUAL(le, ge); 877 | * 878 | * @remarks This is just a short-hand for ASSERT_LESS_EQUAL. 879 | */ 880 | #define ASSERT_LE(le, ge) ASSERT_LESS_EQUAL(le, ge) 881 | 882 | void assert_less_equal_precision(long double le, 883 | long double ge, 884 | long double epsilon, 885 | char *file, 886 | int line); 887 | 888 | /** 889 | * Tests whether the first value is lesser than or equal to the second value. 890 | * 891 | * @param le The first floating point value to compare. This is the value the user 892 | * expects to be lesser than or equal to the second value. 893 | * 894 | * @param ge The second floating point value to compare. This is the value the user 895 | * expects to be greater than or equal to the first value. 896 | * 897 | * @param epsilon A floating point representing the precision required when testing 898 | * for equality. 899 | */ 900 | #define ASSERT_LESS_EQUAL_PRECISION(le, ge, epsilon)\ 901 | assert_less_equal_precision(le, ge, epsilon, __FILE__, __LINE__) 902 | 903 | /** 904 | * @see ASSERT_LESS_EQUAL_PRECISION(le, ge, epsilon); 905 | * 906 | * @remarks This is just a short-hand for ASSERT_LESS_EQUAL_PRECISION. 907 | */ 908 | #define ASSERT_LE_PRECISION(le, ge, epsilon)\ 909 | assert_less_equal_precision(le, ge, epsilon, __FILE__, __LINE__) 910 | 911 | #ifdef TEST_RUNNER 912 | 913 | #include 914 | #include 915 | #include 916 | #include 917 | #include 918 | #include 919 | #include 920 | #include 921 | #include 922 | #include 923 | 924 | /** 925 | * This is the value returned when the runner encounters an error 926 | * and has to exit. The value is positive (rather than the conventional -1) 927 | * because the return value is the amount of failed tests. This is also why 928 | * the value is set so high. 929 | */ 930 | #define EZTEST_EXIT_FAILURE 99999 931 | 932 | #define COLOR_RED "\033[0;31m" 933 | #define COLOR_YELLOW "\033[0;33m" 934 | #define COLOR_GREEN "\033[0;32m" 935 | #define COLOR_NONE "\033[0m" 936 | 937 | /** Represents the application options for EzTest. */ 938 | struct options 939 | { 940 | /** When set to @code true @endcode only default color is used when printing. */ 941 | bool no_color; 942 | /** When set to @code true @endcode the test execution time is displayed for each test */ 943 | bool timer; 944 | /** When set to @code true @endcode EzTest will not print anything. */ 945 | bool quiet; 946 | /** When set to @code true @endcode the skip list will be checked. */ 947 | bool skip; 948 | /** Handles segfault. */ 949 | bool sigsegv; 950 | }; 951 | 952 | enum test_result 953 | { 954 | undefined, 955 | pass, 956 | fail, 957 | skip 958 | }; 959 | 960 | /** Used to separate items in the skip list. */ 961 | static const char *separator = ","; 962 | 963 | /** A list of test suit names to skip separated by @see separator.*/ 964 | static char *skip_list = NULL; 965 | 966 | static const size_t ASSERT_BUFFER_SIZE = 512; 967 | 968 | /** 969 | * Holds the output of asserts for the current test. 970 | * 971 | * @remarks It should be "cleared" between each test. 972 | */ 973 | static char *assert_buffer = NULL; 974 | 975 | /** 976 | * The current length of the assert buffer. 977 | * 978 | * @remarks This exists to remove some strlen calls. 979 | */ 980 | static int assert_buffer_len = 0; 981 | 982 | static int pass_count = 0; 983 | static int fail_count = 0; 984 | static int skip_count = 0; 985 | 986 | /** The current test. */ 987 | static struct unit_test *current = NULL; 988 | 989 | /** Application options */ 990 | static struct options *options = NULL; 991 | 992 | /** The result of the current/ latest test. */ 993 | static enum test_result result = undefined; 994 | 995 | /** Create base/ reference test. */ 996 | TEST(eztest_base_suite, eztest_base_test){} 997 | 998 | //region printers 999 | 1000 | /** 1001 | * Extracts the file name from the given path. 1002 | * Note that the file name includes the file extension. 1003 | * 1004 | * @param path The path of which to extract the file name. 1005 | * @return A char pointer to the first char in the file name. 1006 | */ 1007 | static const char *extract_file_name(char *path) 1008 | { 1009 | char *tmp = strrchr(path, '/'); 1010 | if(tmp == NULL) 1011 | { 1012 | return path; 1013 | } 1014 | path = tmp; 1015 | return ++path; 1016 | } 1017 | 1018 | /** 1019 | * Get the requested color if and only if the application options allow it. 1020 | * 1021 | * @param color The color to request (not NULL). 1022 | * @return If 'no-color' has been set in the application options then 1023 | * @code COLOR_NONE @endcode is returned; otherwise the requested 1024 | * color is returned. 1025 | */ 1026 | static const char *color(const char *color) 1027 | { 1028 | assert(color != NULL); 1029 | 1030 | if(options->no_color) 1031 | { 1032 | return COLOR_NONE; 1033 | } 1034 | return color; 1035 | } 1036 | 1037 | static void register_file_marker(char *file, const int line) 1038 | { 1039 | assert_buffer_len += snprintf( 1040 | assert_buffer + assert_buffer_len, 1041 | ASSERT_BUFFER_SIZE - assert_buffer_len, 1042 | "\n%s└──%s See file %s line %d %s", COLOR_NONE, color(COLOR_YELLOW), extract_file_name(file), line, COLOR_NONE); 1043 | } 1044 | 1045 | /** Prints an overall report of the test results. */ 1046 | static void print_report(void) 1047 | { 1048 | if(options->quiet) return; 1049 | 1050 | printf("-----------------------------------\n" 1051 | "| " 1052 | "%sPASSED" COLOR_NONE " | " 1053 | "%sSKIPPED" COLOR_NONE " | " 1054 | "%sFAILED" COLOR_NONE " |\n" 1055 | "-----------------------------------\n" 1056 | "| " 1057 | " %s%-7d" COLOR_NONE " | " 1058 | " %s%-8d" COLOR_NONE " | " 1059 | " %s%-7d" COLOR_NONE " |\n" 1060 | "-----------------------------------\n\n", 1061 | color(COLOR_GREEN) , 1062 | color(COLOR_YELLOW), 1063 | color(COLOR_RED) , 1064 | color(COLOR_GREEN) , pass_count, 1065 | color(COLOR_YELLOW), skip_count, 1066 | color(COLOR_RED) , fail_count); 1067 | } 1068 | 1069 | /** 1070 | * Prints the test result output if and only if the quiet option has not been set. 1071 | * 1072 | * @param test The unit test to print result for. 1073 | * @param time The test execution time in ms. 1074 | * @param resstr The string representing the result (Eg. PASS, FAIL etc) 1075 | * @param c The requested color of the output result string. 1076 | */ 1077 | static void print_result(const struct unit_test *test, 1078 | const unsigned int time, 1079 | const char *restrict resstr, 1080 | const char *restrict c) 1081 | { 1082 | if(options->quiet) return; 1083 | 1084 | printf("|%s %s %s] %s : %s " COLOR_NONE, 1085 | // Print result with the given color. 1086 | color(c), resstr, COLOR_NONE, 1087 | // Print test suite and name 1088 | test->test_suite, test->test_name); 1089 | 1090 | if(options->timer) 1091 | { 1092 | printf("(%dms)\n", time); 1093 | } 1094 | else 1095 | { 1096 | printf("\n"); 1097 | } 1098 | 1099 | if(assert_buffer_len > 0) 1100 | { 1101 | puts(assert_buffer); 1102 | } 1103 | printf("\n"); 1104 | fflush(stdout); 1105 | } 1106 | 1107 | static void print_failed(const struct unit_test *test, const unsigned int time) 1108 | { 1109 | print_result(test, time, "FAILED", COLOR_RED); 1110 | } 1111 | 1112 | static void print_passed(const struct unit_test *test, const unsigned int time) 1113 | { 1114 | print_result(test, time, "PASSED", COLOR_GREEN); 1115 | } 1116 | 1117 | static void print_skipped(const struct unit_test *test, const unsigned int time) 1118 | { 1119 | print_result(test, time, "SKIPPED", COLOR_YELLOW); 1120 | } 1121 | 1122 | /** 1123 | * Store the n first bytes at the memory location pointed to by the given pointer in hex. 1124 | * 1125 | * @param buffer Location of which the bytes will be written to. 1126 | * @param ptr Pointer to the memory location of which to start. 1127 | * @param n The amount of bytes to print. 1128 | */ 1129 | static void register_bytes(char *buffer, const void *ptr, size_t n) 1130 | { 1131 | const unsigned char *bytes = (const unsigned char *)ptr; 1132 | for (; n > 0; --n, ++bytes) 1133 | { 1134 | snprintf(buffer + strlen(buffer), 128 - strlen(buffer), "%x", *bytes); 1135 | } 1136 | } 1137 | 1138 | /** 1139 | * Registers the current test as a failure and prints the given failure message. 1140 | * 1141 | * @param msg The failure message to print. 1142 | * @param ... Message arguments. 1143 | */ 1144 | static void register_fail(char *file, const int line, const char *msg, ...) 1145 | { 1146 | result = fail; 1147 | 1148 | if(options->quiet) 1149 | { 1150 | return; 1151 | } 1152 | 1153 | assert_buffer_len += snprintf(assert_buffer + assert_buffer_len, ASSERT_BUFFER_SIZE - assert_buffer_len, "%s├── %s", COLOR_NONE, color(COLOR_YELLOW)); 1154 | va_list va; 1155 | va_start(va, msg); 1156 | assert_buffer_len += vsnprintf(assert_buffer + assert_buffer_len, ASSERT_BUFFER_SIZE - assert_buffer_len, msg, va); 1157 | va_end(va); 1158 | register_file_marker(file, line); 1159 | } 1160 | 1161 | //endregion printers 1162 | 1163 | //region asserts 1164 | 1165 | void assert_is_null(const void *value, char *file, const int line) 1166 | { 1167 | if (value != NULL) 1168 | { 1169 | register_fail(file, line, "Assert is null failed: value is not null."); 1170 | } 1171 | } 1172 | 1173 | void assert_is_not_null(const void *value, char *file, const int line) 1174 | { 1175 | if (value == NULL) 1176 | { 1177 | register_fail(file, line, "Assert is not null failed: value is null."); 1178 | } 1179 | } 1180 | 1181 | void assert_is_true(const bool condition, char *file, const int line) 1182 | { 1183 | if(condition != true) 1184 | { 1185 | register_fail(file, line, "Assert is true failed."); 1186 | } 1187 | } 1188 | 1189 | void assert_is_false(const bool condition, char *file, const int line) 1190 | { 1191 | if(condition != false) 1192 | { 1193 | register_fail(file, line, "Assert is false failed."); 1194 | } 1195 | } 1196 | 1197 | void assert_are_same(const void *expected, const void *actual, char *file, const int line) 1198 | { 1199 | if(expected != actual) 1200 | { 1201 | register_fail(file, line, "Assert are same failed: different memory location."); 1202 | } 1203 | } 1204 | 1205 | void assert_are_not_same(const void *unexpected, const void *actual, char *file, const int line) 1206 | { 1207 | if(unexpected == actual) 1208 | { 1209 | register_fail(file, line, "Assert are not same failed: same memory location."); 1210 | } 1211 | } 1212 | 1213 | #ifdef NAN 1214 | 1215 | void assert_is_nan(const float value, char *file, const int line) 1216 | { 1217 | if(!isnan(value)) 1218 | { 1219 | register_fail(file, line, "Assert is NaN failed."); 1220 | } 1221 | } 1222 | 1223 | #endif 1224 | 1225 | void mem_test_failed(const void *ptr1, const void *ptr2, const size_t size, char *file, 1226 | const int line, const char *msg1, const char *msg2) 1227 | { 1228 | result = fail; 1229 | 1230 | if(options->quiet) 1231 | { 1232 | return; 1233 | } 1234 | 1235 | char buf[128]; 1236 | buf[0] = '\0'; 1237 | 1238 | snprintf(buf, 128, "%s '0x", msg1); 1239 | register_bytes(buf, ptr1, (size > EZTEST_MAX_PRINTABLE_LEN ? EZTEST_MAX_PRINTABLE_LEN : size)); 1240 | snprintf(buf + strlen(buf), 128 - strlen(buf), "%s'%s '0x", (size > EZTEST_MAX_PRINTABLE_LEN ? "..." : ""), msg2); 1241 | register_bytes(buf, ptr2, (size > EZTEST_MAX_PRINTABLE_LEN ? EZTEST_MAX_PRINTABLE_LEN : size)); 1242 | snprintf(buf + strlen(buf), 128 - strlen(buf), "%s", (size > EZTEST_MAX_PRINTABLE_LEN ? "...'." : "'.")); 1243 | 1244 | register_fail(file, line, buf); 1245 | } 1246 | 1247 | void assert_equal_mem(const void *expected, const void *actual, const size_t size, char *file, const int line) 1248 | { 1249 | if((expected == NULL && actual != NULL) || 1250 | (expected != NULL && actual == NULL) || 1251 | (expected != NULL && memcmp(expected, actual, size) != 0)) 1252 | { 1253 | mem_test_failed(expected, actual, size, file, line, "Assert are equal failed: expected", ", but got"); 1254 | } 1255 | } 1256 | 1257 | void assert_not_equal_mem(const void *unexpected, const void *actual, const size_t size, char *file, const int line) 1258 | { 1259 | if((unexpected == NULL && actual == NULL) || 1260 | (unexpected != NULL && actual != NULL && memcmp(unexpected, actual, size) == 0)) 1261 | { 1262 | mem_test_failed(unexpected, actual, size, file, line, "Assert not equal failed:", "is equal to"); 1263 | } 1264 | } 1265 | 1266 | 1267 | 1268 | void assert_greater_mem(const void *greater, const void *lesser, const size_t size, char *file, const int line) 1269 | { 1270 | if((greater == NULL && lesser != NULL) || 1271 | (greater == NULL && lesser == NULL) || 1272 | (greater != NULL && lesser != NULL && memcmp(greater, lesser, size) < 1)) 1273 | { 1274 | mem_test_failed(greater, lesser, size, file, line, "Assert greater failed:", "is lesser than or equal to"); 1275 | } 1276 | } 1277 | 1278 | void assert_greater_equal_mem(const void *ge, const void *le, const size_t size, char *file, const int line) 1279 | { 1280 | if((ge == NULL && le != NULL) || 1281 | (ge != NULL && le != NULL && memcmp(ge, le, size) < 0)) 1282 | { 1283 | mem_test_failed(ge, le, size, file, line, "Assert greater equal failed:", "is lesser than"); 1284 | } 1285 | } 1286 | 1287 | void assert_less_mem(const void *lesser, const void *greater, const size_t size, char *file, const int line) 1288 | { 1289 | if((lesser != NULL && greater == NULL) || 1290 | (lesser == NULL && greater == NULL) || 1291 | (lesser != NULL && greater != NULL && memcmp(lesser, greater, size) >= 0)) 1292 | { 1293 | mem_test_failed(lesser, greater, size, file, line, "Assert lesser failed:", "is greater than or equal to"); 1294 | } 1295 | } 1296 | 1297 | void assert_less_equal_mem(const void *le, const void *ge, const size_t size, char *file, const int line) 1298 | { 1299 | if((le != NULL && ge == NULL) || 1300 | (le != NULL && ge != NULL && memcmp(le, ge, size) > 0)) 1301 | { 1302 | mem_test_failed(le, ge, size, file, line, "Assert less or equal failed:", "is greater than"); 1303 | } 1304 | } 1305 | 1306 | void assert_are_equal_cmp(const void *expected, 1307 | const void *actual, 1308 | int(*cmp_fn)(const void *ptr1, const void *ptr2), 1309 | char *file, 1310 | const int line) 1311 | { 1312 | if(cmp_fn(expected, actual) != 0) 1313 | { 1314 | register_fail(file, line, "Assert are equal failed."); 1315 | } 1316 | } 1317 | 1318 | void assert_are_not_equal_cmp(const void *unexpected, 1319 | const void *actual, 1320 | int(*cmp_fn)(const void *ptr1, const void *ptr2), 1321 | char *file, 1322 | const int line) 1323 | { 1324 | if(cmp_fn(unexpected, actual) == 0) 1325 | { 1326 | register_fail(file, line, "Assert not equal failed."); 1327 | } 1328 | } 1329 | 1330 | void assert_greater_cmp(const void *greater, 1331 | const void *lesser, 1332 | int(*cmp_fn)(const void *ptr1, const void *ptr2), 1333 | char *file, 1334 | const int line) 1335 | { 1336 | if(cmp_fn(greater, lesser) < 1) 1337 | { 1338 | register_fail(file, line, "Assert greater failed."); 1339 | } 1340 | } 1341 | 1342 | void assert_greater_equal_cmp(const void *ge, 1343 | const void *le, 1344 | int(*cmp_fn)(const void *ptr1, const void *ptr2), 1345 | char *file, 1346 | const int line) 1347 | { 1348 | if(cmp_fn(ge, le) < 0) 1349 | { 1350 | register_fail(file, line, "Assert greater or equal failed."); 1351 | } 1352 | } 1353 | 1354 | void assert_less_cmp(const void *lesser, 1355 | const void *greater, 1356 | int(*cmp_fn)(const void *ptr1, const void *ptr2), 1357 | char *file, 1358 | const int line) 1359 | { 1360 | if(cmp_fn(lesser, greater) >= 0) 1361 | { 1362 | register_fail(file, line, "Assert less failed."); 1363 | } 1364 | } 1365 | 1366 | 1367 | void assert_less_equal_cmp(const void *le, 1368 | const void *ge, 1369 | int(*cmp_fn)(const void *ptr1, const void *ptr2), 1370 | char *file, 1371 | const int line) 1372 | { 1373 | if(cmp_fn(le, ge) > 0) 1374 | { 1375 | register_fail(file, line, "Assert less or equal failed."); 1376 | } 1377 | } 1378 | 1379 | void assert_are_equal_ch(const char expected, const char actual, char *file, const int line) 1380 | { 1381 | if(expected != actual) 1382 | { 1383 | register_fail(file, line, "Assert are equal failed: expected '%c', but got '%c'.", expected, actual); 1384 | } 1385 | } 1386 | 1387 | void assert_are_equal_sch(const signed char expected, const signed char actual, char *file, const int line) 1388 | { 1389 | if(expected != actual) 1390 | { 1391 | register_fail(file, line, "Assert are equal failed: expected '%c', but got '%c'.", expected, actual); 1392 | } 1393 | } 1394 | 1395 | void assert_are_equal_uch(const unsigned char expected, const unsigned char actual, char *file, const int line) 1396 | { 1397 | if(expected != actual) 1398 | { 1399 | register_fail(file, line, "Assert are equal failed: expected '%c', but got '%c'.", expected, actual); 1400 | } 1401 | } 1402 | 1403 | void assert_are_equal_int(const intmax_t expected, const intmax_t actual, char *file, const int line) 1404 | { 1405 | if(expected != actual) 1406 | { 1407 | register_fail(file, line, "Assert are equal failed: expected '%ld', but got '%ld'.", expected, actual); 1408 | } 1409 | } 1410 | 1411 | void assert_are_equal_uint(const uintmax_t expected, const uintmax_t actual, char *file, const int line) 1412 | { 1413 | if(expected != actual) 1414 | { 1415 | register_fail(file, line, "Assert are equal failed: expected '%ld', but got '%ld'.", expected, actual); 1416 | } 1417 | } 1418 | 1419 | /** 1420 | * Tests the equality of two floating point numbers. 1421 | * 1422 | * @param expected The first and expected value. 1423 | * @param actual The actual value generated by the code under test. 1424 | * 1425 | * @remarks It is important to known that this test uses the epsilon macro from float.h 1426 | * in its equality test. It is therefore often better to use assert_are_equal_precision() 1427 | * and provide the application specific epsilon. 1428 | */ 1429 | void assert_are_equal_dbl(const long double expected, const long double actual, char *file, const int line) 1430 | { 1431 | if(fabsl(expected - actual) > LDBL_EPSILON) 1432 | { 1433 | register_fail(file, line, "Assert are equal failed: expected '%0.8Lf', but got '%0.8Lf'.", expected, actual); 1434 | } 1435 | } 1436 | void assert_are_equal_str(const char *expected, const char *actual, char *file, const int line) 1437 | { 1438 | if((expected == NULL && actual != NULL) || 1439 | (expected != NULL && actual == NULL) || 1440 | (expected != NULL && strcmp(expected, actual) != 0)) 1441 | { 1442 | register_fail(file, line, "Assert are equal failed: expected '%s', but got '%s'.", expected, actual); 1443 | } 1444 | } 1445 | 1446 | void assert_are_equal_wstr(const wchar_t *expected, const wchar_t *actual, char *file, const int line) 1447 | { 1448 | if((expected == NULL && actual != NULL) || 1449 | (expected != NULL && actual == NULL) || 1450 | (expected != NULL && wcscmp(expected, actual) != 0)) 1451 | { 1452 | register_fail(file, line, "Assert are equal failed: expected '%ls', but got '%ls'.", expected, actual); 1453 | } 1454 | } 1455 | 1456 | /** Triggered when attempting to compare using an unsupported data type. */ 1457 | void assert_are_equal(const void *expected, const void *actual, char *file, const int line) 1458 | { 1459 | register_fail(file, line, "Assert are equal failed: unsupported data type."); 1460 | } 1461 | 1462 | void assert_are_not_equal_ch(const char unexpected, const char actual, char *file, const int line) 1463 | { 1464 | if(unexpected == actual) 1465 | { 1466 | register_fail(file, line, "Assert not equal failed: '%c' and '%c' are equal.", unexpected, actual); 1467 | } 1468 | } 1469 | 1470 | void assert_are_not_equal_sch(const signed char unexpected, const signed char actual, char *file, const int line) 1471 | { 1472 | if(unexpected == actual) 1473 | { 1474 | register_fail(file, line, "Assert not equal failed: '%c' and '%c' are equal.", unexpected, actual); 1475 | } 1476 | } 1477 | 1478 | void assert_are_not_equal_uch(const unsigned char unexpected, const unsigned char actual, char *file, const int line) 1479 | { 1480 | if(unexpected == actual) 1481 | { 1482 | register_fail(file, line, "Assert not equal failed: '%c' and '%c' are equal.", unexpected, actual); 1483 | } 1484 | } 1485 | 1486 | void assert_are_not_equal_int(const intmax_t unexpected, const intmax_t actual, char *file, const int line) 1487 | { 1488 | if(unexpected == actual) 1489 | { 1490 | register_fail(file, line, "Assert not equal failed: '%ld' and '%ld' are equal.", unexpected, actual); 1491 | } 1492 | } 1493 | 1494 | void assert_are_not_equal_uint(const uintmax_t unexpected, const uintmax_t actual, char *file, const int line) 1495 | { 1496 | if(unexpected == actual) 1497 | { 1498 | register_fail(file, line, "Assert not equal failed: '%ld' and '%ld' are equal.", unexpected, actual); 1499 | } 1500 | } 1501 | 1502 | /** 1503 | * Tests the equality of two floating point numbers. 1504 | * 1505 | * @param unexpected The first and unexpected value. 1506 | * @param actual The actual value generated by the code under test. 1507 | * 1508 | * @remarks It is important to known that this test uses the epsilon macro from float.h 1509 | * in its equality test. It is therefore often better to use assert_are_equal_precision() 1510 | * and provide the application specific epsilon. 1511 | */ 1512 | void assert_are_not_equal_dbl(const long double unexpected, const long double actual, char *file, const int line) 1513 | { 1514 | if(fabsl(unexpected - actual) <= LDBL_EPSILON) 1515 | { 1516 | register_fail(file, line, "Assert not equal failed: '%0.8Lf' and '%0.8Lf' are equal.", unexpected, actual); 1517 | } 1518 | } 1519 | 1520 | void assert_are_not_equal_str(const char *unexpected, const char *actual, char *file, const int line) 1521 | { 1522 | if((unexpected == NULL && actual == NULL) || 1523 | (unexpected != NULL && actual != NULL && strcmp(unexpected, actual) == 0)) 1524 | { 1525 | register_fail(file, line, "Assert not equal failed: '%s' and '%s' are equal.", unexpected, actual); 1526 | } 1527 | } 1528 | 1529 | void assert_are_not_equal_wstr(const wchar_t *unexpected, const wchar_t *actual, char *file, const int line) 1530 | { 1531 | if((unexpected == NULL && actual == NULL) || 1532 | (unexpected != NULL && actual != NULL && wcscmp(unexpected, actual) == 0)) 1533 | { 1534 | register_fail(file, line, "Assert not equal failed: '%ls' and '%ls' are equal.", unexpected, actual); 1535 | } 1536 | } 1537 | 1538 | /** Triggered when attempting to compare using an unsupported data type. */ 1539 | void assert_are_not_equal(const void *expected, const void *actual, char *file, const int line) 1540 | { 1541 | register_fail(file, line, "Assert not equal failed: unsupported data type."); 1542 | } 1543 | 1544 | void assert_are_equal_precision(const long double expected, 1545 | const long double actual, 1546 | const long double epsilon, 1547 | char *file, 1548 | const int line) 1549 | { 1550 | if(fabsl(expected - actual) > epsilon) 1551 | { 1552 | register_fail(file, line, "Assert are equal failed: expected '%0.8Lf', but got '%0.8Lf'.", expected, actual); 1553 | } 1554 | } 1555 | 1556 | void assert_are_not_equal_precision(const long double unexpected, 1557 | const long double actual, 1558 | const long double epsilon, 1559 | char *file, 1560 | const int line) 1561 | { 1562 | if(fabsl(unexpected - actual) <= epsilon) 1563 | { 1564 | register_fail(file, line, "Assert not equal failed: '%0.8Lf' and '%0.8Lf' are equal.", unexpected, actual); 1565 | } 1566 | } 1567 | 1568 | void assert_greater_ch(const char greater, const char lesser, char *file, const int line) 1569 | { 1570 | if(greater <= lesser) 1571 | { 1572 | register_fail(file, line, "Assert greater failed: '%c' is not greater than '%c'.", greater, lesser); 1573 | } 1574 | } 1575 | 1576 | void assert_greater_sch(const signed char greater, const signed char lesser, char *file, const int line) 1577 | { 1578 | if(greater <= lesser) 1579 | { 1580 | register_fail(file, line, "Assert greater failed: '%c' is not greater than '%c'.", greater, lesser); 1581 | } 1582 | } 1583 | 1584 | void assert_greater_uch(const unsigned char greater, const unsigned char lesser, char *file, const int line) 1585 | { 1586 | if(greater <= lesser) 1587 | { 1588 | register_fail(file, line, "Assert greater failed: '%c' is not greater than '%c'.", greater, lesser); 1589 | } 1590 | } 1591 | 1592 | void assert_greater_int(const intmax_t greater, const intmax_t lesser, char *file, const int line) 1593 | { 1594 | if(greater <= lesser) 1595 | { 1596 | register_fail(file, line, "Assert greater failed: '%ld' is not greater than '%ld'.", greater, lesser); 1597 | } 1598 | } 1599 | 1600 | void assert_greater_uint(const uintmax_t greater, const uintmax_t lesser, char *file, const int line) 1601 | { 1602 | if(greater <= lesser) 1603 | { 1604 | register_fail(file, line, "Assert greater failed: '%ld' is not greater than '%ld'.", greater, lesser); 1605 | } 1606 | } 1607 | 1608 | /** 1609 | * Tests the equality of two floating point numbers. 1610 | * 1611 | * @param greater The value that is expected to be greater. 1612 | * @param lesser The value that is expected to be lesser. 1613 | * 1614 | * @remarks It is important to known that this test uses the epsilon macro from float.h 1615 | * in its equality test. It is therefore often better to use assert_greater_precision() 1616 | * and provide the application specific epsilon. 1617 | */ 1618 | void assert_greater_dbl(const long double greater, const long double lesser, char *file, const int line) 1619 | { 1620 | if(fabsl(greater - lesser) <= LDBL_EPSILON || greater < lesser) 1621 | { 1622 | register_fail(file, line, "Assert greater failed: '%0.8Lf' is not greater than '%0.8Lf'.", greater, lesser); 1623 | } 1624 | } 1625 | void assert_greater_str(const char *greater, const char *lesser, char *file, const int line) 1626 | { 1627 | if((greater == NULL && lesser != NULL) || 1628 | (greater == NULL && lesser == NULL) || 1629 | (greater != NULL && lesser != NULL && strcmp(greater, lesser) <= 0)) 1630 | { 1631 | register_fail(file, line, "Assert greater failed: '%s' is not greater than '%s'.", greater, lesser); 1632 | } 1633 | } 1634 | 1635 | void assert_greater_wstr(const wchar_t *greater, const wchar_t *lesser, char *file, const int line) 1636 | { 1637 | if((greater == NULL && lesser != NULL) || 1638 | (greater == NULL && lesser == NULL) || 1639 | (greater != NULL && lesser != NULL && wcscmp(greater, lesser) <= 0)) 1640 | { 1641 | register_fail(file, line, "Assert greater failed: '%ls' is not greater than '%ls'.", greater, lesser); 1642 | } 1643 | } 1644 | 1645 | /** Triggered when attempting to compare using an unsupported data type. */ 1646 | void assert_greater(const void *greater, const void *lesser, char *file, const int line) 1647 | { 1648 | register_fail(file, line, "Assert greater failed: unsupported data type."); 1649 | } 1650 | 1651 | void assert_greater_precision(const long double greater, 1652 | const long double lesser, 1653 | const long double epsilon, 1654 | char * file, 1655 | const int line) 1656 | { 1657 | if(fabsl(greater - lesser) <= epsilon || greater < lesser) 1658 | { 1659 | register_fail(file, line, "Assert greater failed: '%0.8Lf' is not greater than '%0.8Lf'.", greater, lesser); 1660 | } 1661 | } 1662 | 1663 | void assert_greater_equal_ch(const char ge, const char le, char *file, const int line) 1664 | { 1665 | if(ge < le) 1666 | { 1667 | register_fail(file, line, "Assert greater or equal failed: '%c' is lesser than '%c'.", ge, le); 1668 | } 1669 | } 1670 | 1671 | void assert_greater_equal_sch (const signed char ge, const signed char le, char *file, const int line) 1672 | { 1673 | if(ge < le) 1674 | { 1675 | register_fail(file, line, "Assert greater or equal failed: '%c' is lesser than '%c'.", ge, le); 1676 | } 1677 | } 1678 | 1679 | void assert_greater_equal_uch (const unsigned char ge, const unsigned char le, char *file, const int line) 1680 | { 1681 | if(ge < le) 1682 | { 1683 | register_fail(file, line, "Assert greater or equal failed: '%c' is lesser than '%c'.", ge, le); 1684 | } 1685 | } 1686 | 1687 | void assert_greater_equal_int (const intmax_t ge, const intmax_t le, char *file, const int line) 1688 | { 1689 | if(ge < le) 1690 | { 1691 | register_fail(file, line, "Assert greater or equal failed: '%ld' is lesser than '%ld'.", ge, le); 1692 | } 1693 | } 1694 | 1695 | void assert_greater_equal_uint(const uintmax_t ge, const uintmax_t le, char *file, const int line) 1696 | { 1697 | if(ge < le) 1698 | { 1699 | register_fail(file, line, "Assert greater or equal failed: '%ld' is lesser than '%ld'.", ge, le); 1700 | } 1701 | } 1702 | 1703 | /** 1704 | * Tests the equality of two floating point numbers. 1705 | * 1706 | * @param ge The value that is expected to be greater or equal to the second value. 1707 | * @param le The value that is expected to be less than or equal to the first value. 1708 | * 1709 | * @remarks It is important to known that this test uses the epsilon macro from float.h 1710 | * in its equality test. It is therefore often better to use assert_greater_equal_precision() 1711 | * and provide the application specific epsilon. 1712 | */ 1713 | void assert_greater_equal_dbl(const long double ge, const long double le, char *file, const int line) 1714 | { 1715 | if(fabsl(ge - le) > LDBL_EPSILON && ge < le) 1716 | { 1717 | register_fail(file, line, "Assert greater or equal failed: '%0.8Lf' is lesser than '%0.8Lf'.", ge, le); 1718 | } 1719 | } 1720 | 1721 | void assert_greater_equal_str(const char *ge, const char *le, char *file, const int line) 1722 | { 1723 | if((ge == NULL && le != NULL) || 1724 | (ge != NULL && le != NULL && strcmp(ge, le) < 0)) 1725 | { 1726 | register_fail(file, line, "Assert greater or equal failed: '%s' is lesser than '%s'.", ge, le); 1727 | } 1728 | } 1729 | 1730 | void assert_greater_equal_wstr(const wchar_t *ge, const wchar_t *le, char *file, const int line) 1731 | { 1732 | if((ge == NULL && le != NULL) || 1733 | (ge != NULL && le != NULL && wcscmp(ge, le) < 0)) 1734 | { 1735 | register_fail(file, line, "Assert greater or equal failed: '%ls' is lesser than '%ls'.", ge, le); 1736 | } 1737 | } 1738 | void assert_greater_equal(const void *ge, const void *le, char *file, const int line) 1739 | { 1740 | register_fail(file, line, "Assert greater or equal failed: unsupported data type."); 1741 | } 1742 | 1743 | void assert_greater_equal_precision(long double ge, 1744 | long double le, 1745 | long double epsilon, 1746 | char *file, 1747 | int line) 1748 | { 1749 | if(fabsl(ge - le) > epsilon && ge < le) 1750 | { 1751 | register_fail(file, line, "Assert greater or equal failed: '%0.8Lf' is lesser than '%0.8Lf'.", ge, le); 1752 | } 1753 | } 1754 | 1755 | void assert_less_ch(const char lesser, const char greater, char *file, const int line) 1756 | { 1757 | if(lesser >= greater) 1758 | { 1759 | register_fail(file, line, "Assert less failed: '%c' is not lesser then '%c'.", lesser, greater); 1760 | } 1761 | } 1762 | 1763 | void assert_less_sch(const signed char lesser, const signed char greater, char *file, const int line) 1764 | { 1765 | if(lesser >= greater) 1766 | { 1767 | register_fail(file, line, "Assert less failed: '%c' is not lesser then '%c'.", lesser, greater); 1768 | } 1769 | } 1770 | 1771 | void assert_less_uch(const unsigned char lesser, const unsigned char greater, char *file, const int line) 1772 | { 1773 | if(lesser >= greater) 1774 | { 1775 | register_fail(file, line, "Assert less failed: '%c' is not lesser then '%c'.", lesser, greater); 1776 | } 1777 | } 1778 | 1779 | void assert_less_int(const intmax_t lesser, const intmax_t greater, char *file, const int line) 1780 | { 1781 | if(lesser >= greater) 1782 | { 1783 | register_fail(file, line, "Assert less failed: '%ld' is not lesser then '%ld'.", lesser, greater); 1784 | } 1785 | } 1786 | 1787 | void assert_less_uint(const uintmax_t lesser, const uintmax_t greater, char *file, const int line) 1788 | { 1789 | if(lesser >= greater) 1790 | { 1791 | register_fail(file, line, "Assert less failed: '%ld' is not lesser then '%ld'.", lesser, greater); 1792 | } 1793 | } 1794 | 1795 | /** 1796 | * Tests the equality of two floating point numbers. 1797 | * 1798 | * @param lesser The value that is expected to be lesser. 1799 | * @param greater The value that is expected to be greater. 1800 | * 1801 | * @remarks It is important to known that this test uses the epsilon macro from float.h 1802 | * in its equality test. It is therefore often better to use assert_greater_precision() 1803 | * and provide the application specific epsilon. 1804 | */ 1805 | void assert_less_dbl(const long double lesser, const long double greater, char *file, const int line) 1806 | { 1807 | if(fabsl(greater - lesser) <= LDBL_EPSILON || lesser > greater) 1808 | { 1809 | register_fail(file, line, "Assert less failed: '%0.8Lf' is not lesser then '%0.8Lf'.", lesser, greater); 1810 | } 1811 | } 1812 | 1813 | void assert_less_str(const char *lesser, const char *greater, char *file, const int line) 1814 | { 1815 | if((greater == NULL && lesser != NULL) || 1816 | (greater == NULL && lesser == NULL) || 1817 | (greater != NULL && lesser != NULL && strcmp(lesser, greater) >= 0)) 1818 | { 1819 | register_fail(file, line, "Assert less failed: '%s' is not lesser then '%s'.", lesser, greater); 1820 | } 1821 | } 1822 | 1823 | void assert_less_wstr(const wchar_t *lesser, const wchar_t *greater, char *file, const int line) 1824 | { 1825 | if((greater == NULL && lesser != NULL) || 1826 | (greater == NULL && lesser == NULL) || 1827 | (greater != NULL && lesser != NULL && wcscmp(lesser, greater) >= 0)) 1828 | { 1829 | register_fail(file, line, "Assert less failed: '%ls' is not lesser then '%ls'.", lesser, greater); 1830 | } 1831 | } 1832 | 1833 | /** Triggered when attempting to compare using an unsupported data type. */ 1834 | void assert_less(const void *lesser, const void *greater, char *file, const int line) 1835 | { 1836 | register_fail(file, line, "Assert less failed: unsupported data type."); 1837 | } 1838 | 1839 | void assert_less_precision(const long double lesser, 1840 | const long double greater, 1841 | const long double epsilon, 1842 | char *file, 1843 | const int line) 1844 | { 1845 | if(fabsl(lesser - greater) <= epsilon || lesser > greater) 1846 | { 1847 | register_fail(file, line, "Assert less failed: '%0.8Lf' is not lesser then '%0.8Lf'.", lesser, greater); 1848 | } 1849 | } 1850 | 1851 | void assert_less_equal_ch(const char le, const char ge, char *file, const int line) 1852 | { 1853 | if(le > ge) 1854 | { 1855 | register_fail(file, line, "Assert less or equal failed: '%c' is greater then '%c'.", le, ge); 1856 | } 1857 | } 1858 | 1859 | void assert_less_equal_sch (const signed char le, const signed char ge, char *file, const int line) 1860 | { 1861 | if(le > ge) 1862 | { 1863 | register_fail(file, line, "Assert less or equal failed: '%c' is greater then '%c'.", le, ge); 1864 | } 1865 | } 1866 | 1867 | void assert_less_equal_uch (const unsigned char le, const unsigned char ge, char *file, const int line) 1868 | { 1869 | if(le > ge) 1870 | { 1871 | register_fail(file, line, "Assert less or equal failed: '%c' is greater then '%c'.", le, ge); 1872 | } 1873 | } 1874 | 1875 | void assert_less_equal_int (const intmax_t le, const intmax_t ge, char *file, const int line) 1876 | { 1877 | if(le > ge) 1878 | { 1879 | register_fail(file, line, "Assert less or equal failed: '%ld' is greater then '%ld'.", le, ge); 1880 | } 1881 | } 1882 | 1883 | void assert_less_equal_uint(const uintmax_t le, const uintmax_t ge, char *file, const int line) 1884 | { 1885 | if(le > ge) 1886 | { 1887 | register_fail(file, line, "Assert less or equal failed: '%ld' is greater then '%ld'.", le, ge); 1888 | } 1889 | } 1890 | 1891 | /** 1892 | * Tests the equality of two floating point numbers. 1893 | * 1894 | * @param le The value that is expected to be lesser or equal to the second value. 1895 | * @param ge The value that is expected to be greater than or equal to the first value. 1896 | * 1897 | * @remarks It is important to known that this test uses the epsilon macro from float.h 1898 | * in its equality test. It is therefore often better to use assert_greater_equal_precision() 1899 | * and provide the application specific epsilon. 1900 | */ 1901 | void assert_less_equal_dbl(const long double le, const long double ge, char *file, const int line) 1902 | { 1903 | if(fabsl(ge - le) > LDBL_EPSILON && le > ge) 1904 | { 1905 | register_fail(file, line, "Assert less or equal failed: '%0.8Lf' is greater then '%0.8Lf'.", le, ge); 1906 | } 1907 | } 1908 | 1909 | void assert_less_equal_str(const char *le, const char *ge, char *file, const int line) 1910 | { 1911 | if((ge == NULL && le != NULL) || 1912 | (ge != NULL && le != NULL && strcmp(le, ge) > 0)) 1913 | { 1914 | register_fail(file, line, "Assert less or equal failed: '%s' is greater then '%s'.", le, ge); 1915 | } 1916 | } 1917 | 1918 | void assert_less_equal_wstr(const wchar_t *le, const wchar_t *ge, char *file, const int line) 1919 | { 1920 | if((ge == NULL && le != NULL) || 1921 | (ge != NULL && le != NULL && wcscmp(le, ge) > 0)) 1922 | { 1923 | register_fail(file, line, "Assert less or equal failed: '%ls' is greater then '%ls'.", le, ge); 1924 | } 1925 | } 1926 | void assert_less_equal(const void *le, const void *ge, char *file, const int line) 1927 | { 1928 | register_fail(file, line, "Assert less or equal failed: unsupported data type."); 1929 | } 1930 | 1931 | void assert_less_equal_precision(const long double le, 1932 | const long double ge, 1933 | const long double epsilon, 1934 | char *file, 1935 | const int line) 1936 | { 1937 | if(fabsl(le - ge) > epsilon && le > ge) 1938 | { 1939 | register_fail(file, line, "Assert less or equal failed: '%0.8Lf' is greater then '%0.8Lf'.", le, ge); 1940 | } 1941 | } 1942 | 1943 | 1944 | //endregion asserts 1945 | 1946 | //region runner 1947 | 1948 | /** 1949 | * Discovers the unit test starting at the given address. 1950 | * 1951 | * @param base_test the starting address of which to start the discovery. 1952 | * @return the amount of tests found. 1953 | */ 1954 | static int discover(struct unit_test **base_test) 1955 | { 1956 | int count = 0; 1957 | struct unit_test *tmp = *base_test; 1958 | 1959 | while(true) 1960 | { 1961 | if(tmp->marker == EZTEST_MARKER) 1962 | { 1963 | if(strcmp(tmp->test_name, EZTEST_BASE_TEST_NAME) == 0) 1964 | { 1965 | (*base_test)++; 1966 | tmp++; 1967 | continue; 1968 | } 1969 | tmp++; 1970 | count++; 1971 | } 1972 | else 1973 | { 1974 | break; 1975 | } 1976 | } 1977 | if(!options->quiet) 1978 | { 1979 | printf("Test discovery finished, found %d tests.\n\n", count); 1980 | } 1981 | return count; 1982 | } 1983 | 1984 | static bool should_skip(const struct unit_test *test) 1985 | { 1986 | if(!options->skip || skip_list == NULL) 1987 | { 1988 | return false; 1989 | } 1990 | char *skip_list_cp = malloc((strlen(skip_list) + 1) * sizeof(char)); 1991 | if(skip_list_cp == NULL) 1992 | { 1993 | return false; 1994 | } 1995 | strcpy(skip_list_cp, skip_list); 1996 | 1997 | char *token; 1998 | token = strtok(skip_list_cp, separator); 1999 | while(token != NULL) 2000 | { 2001 | if(strcmp(token, test->test_suite) == 0) 2002 | { 2003 | free(skip_list_cp); 2004 | return true; 2005 | } 2006 | token = strtok(NULL, separator); 2007 | } 2008 | free(skip_list_cp); 2009 | 2010 | return false; 2011 | } 2012 | 2013 | /** 2014 | * Registers the current result by increasing the result counter 2015 | * and printing the result message. 2016 | */ 2017 | static void register_result(const unsigned int time) 2018 | { 2019 | if(result == fail) 2020 | { 2021 | fail_count++; 2022 | print_failed(current, time); 2023 | } 2024 | else if(result == skip) 2025 | { 2026 | skip_count++; 2027 | print_skipped(current, time); 2028 | } 2029 | else 2030 | { 2031 | pass_count++; 2032 | print_passed(current, time); 2033 | } 2034 | } 2035 | 2036 | /** 2037 | * Prints the total test time as long as the quiet options has not been set. 2038 | * 2039 | * @param t The time 2040 | */ 2041 | static void print_test_time(const unsigned int t) 2042 | { 2043 | if(options->quiet) return; 2044 | 2045 | printf("Total elapsed time: %dms\n", t); 2046 | } 2047 | 2048 | /** 2049 | * Executes the passed test, running the setup and teardown functions 2050 | * if they are not @code NULL @endcode 2051 | * 2052 | * @param test The test to run. 2053 | * @return The execution time in milliseconds. 2054 | */ 2055 | static unsigned int execute(const struct unit_test *test) 2056 | { 2057 | clock_t t; 2058 | t = clock(); 2059 | if(test->setup_fn != NULL) 2060 | { 2061 | test->setup_fn(); 2062 | } 2063 | test->run_fn(); 2064 | if(test->teardown_fn != NULL) 2065 | { 2066 | test->teardown_fn(); 2067 | } 2068 | t = clock() - t; 2069 | return ((unsigned int)((((float)t) / CLOCKS_PER_SEC) * 1000)); 2070 | } 2071 | 2072 | /** To be executed on signal: SIGSEGV */ 2073 | static void onSegfault(int signum) 2074 | { 2075 | register_fail("SIGNAL", signum, "Segmentation fault encountered."); 2076 | register_result(0); 2077 | 2078 | signal(signum, SIG_DFL); 2079 | kill(getpid(), signum); 2080 | } 2081 | 2082 | /** 2083 | * Starts running tests. 2084 | * 2085 | * @param opts Application options (not NULL). 2086 | * @return The amount of failed tests. If the runner encounters an error, 2087 | * then EZTEST_EXIT_FAILURE is returned. 2088 | */ 2089 | int eztest_run(struct options *opts) 2090 | { 2091 | assert(opts != NULL); 2092 | 2093 | options = opts; 2094 | current = &EZTEST_STRUCT_NAME(eztest_base_suite, eztest_base_test); 2095 | 2096 | if(options->sigsegv) 2097 | { 2098 | signal(SIGSEGV, onSegfault); 2099 | } 2100 | 2101 | assert_buffer = malloc(ASSERT_BUFFER_SIZE); 2102 | if(assert_buffer == NULL) 2103 | { 2104 | fprintf(stderr, "Failed to allocated memory for the assert buffer."); 2105 | return EZTEST_EXIT_FAILURE; 2106 | } 2107 | 2108 | const int count = discover(¤t); 2109 | 2110 | unsigned int test_time = 0; // Time for the current test. 2111 | unsigned int total_time = 0; // Total time for all tests. 2112 | 2113 | for (int i = 0; i < count; i++, current++) 2114 | { 2115 | if(should_skip(current)) 2116 | { 2117 | result = skip; 2118 | } 2119 | else 2120 | { 2121 | // Reset buffer 2122 | assert_buffer[0] = '\0'; 2123 | assert_buffer_len = 0; 2124 | // Reset result 2125 | result = undefined; // Reset result before running new test. 2126 | // Run test 2127 | test_time = execute(current); 2128 | total_time += test_time; 2129 | } 2130 | register_result(test_time); 2131 | } 2132 | print_report(); 2133 | 2134 | if(options->timer) 2135 | { 2136 | print_test_time(total_time); 2137 | } 2138 | 2139 | free(assert_buffer); 2140 | 2141 | return fail_count; 2142 | } 2143 | 2144 | //endregion runner 2145 | 2146 | 2147 | #endif // TEST_RUNNER 2148 | 2149 | #endif // EZTEST_H 2150 | 2151 | -------------------------------------------------------------------------------- /eztest/runner.c: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | * @author havardt 4 | * 5 | * @license MIT 6 | * 7 | */ 8 | 9 | #define TEST_RUNNER 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include "eztest.h" 19 | 20 | /* Macros */ 21 | 22 | #define __PROGRAM_NAME__ "EzTest" 23 | #define __PROGRAM_VERSION__ "3.0.0" 24 | #define __PROGRAM_AUTHOR__ "havardt" 25 | #define __PROGRAM_WEBSITE__ "https://github.com/havardt/EzTest" 26 | 27 | #define DEFAULT_OPTIONS { .no_color = false, .timer = false, .quiet = false, .skip = false, .sigsegv = false } 28 | 29 | 30 | /* Prototypes */ 31 | 32 | void print_usage ( FILE * ); 33 | int parse_opt ( struct options *, int ); 34 | int handle_opts ( struct options *, int, char ** ); 35 | 36 | 37 | /* Globals */ 38 | 39 | const struct option long_opts[] = { 40 | {"help" , no_argument , NULL, 'h'}, 41 | {"version" , no_argument , NULL, 'v'}, 42 | {"no-color", no_argument , NULL, 'c'}, 43 | {"timer" , no_argument , NULL, 't'}, 44 | {"quiet" , no_argument , NULL, 'q'}, 45 | {"skip" , required_argument, NULL, 's'}, 46 | {"SIGSEGV" , no_argument , NULL, 'f'}, 47 | {0} 48 | }; 49 | 50 | struct options opts = DEFAULT_OPTIONS; 51 | 52 | 53 | int main(int argc, char **argv) 54 | { 55 | if(handle_opts(&opts, argc, argv) != EZTEST_RESULT_OK) 56 | { 57 | return EXIT_FAILURE; 58 | } 59 | 60 | setlocale(LC_ALL, ""); // Needed to print wide chars/ strings. 61 | 62 | return (eztest_run(&opts) == 0 ? EXIT_SUCCESS : EXIT_FAILURE); 63 | } 64 | 65 | /** 66 | * Prints program usage. 67 | * 68 | * @param fd A file descriptor representing the output location. 69 | */ 70 | void print_usage(FILE *fd) 71 | { 72 | assert(fd != NULL); 73 | 74 | fprintf(fd, "\nUsage: %s [OPTIONS]\n\n" 75 | "Options:\n" 76 | " -v --version Print version number.\n" 77 | " -h --help Print help information.\n" 78 | " -c --no-color Only use default color when printing to screen.\n" 79 | " -t --timer Display execution time for each test.\n" 80 | " -q --quiet No output.\n" 81 | " -s --skip Skips all tests in the passed list of test suits.\n" 82 | " -f --SIGSEGV Segmentation fault is displayed like other test failures.\n\n", 83 | __PROGRAM_NAME__); 84 | } 85 | 86 | /** 87 | * Parse application options. 88 | * 89 | * @param opts Pointer to current options. 90 | * @param opt The option to parse. 91 | * @return: On success @code RESULT_OK @endcode; otherwise @code RESULT_ERR @endcode . 92 | */ 93 | int parse_opt(struct options *opts, const int opt) 94 | { 95 | switch(opt) 96 | { 97 | case 'v': 98 | printf("%s version %s\n", __PROGRAM_NAME__, __PROGRAM_VERSION__); 99 | exit(EXIT_SUCCESS); 100 | 101 | case 'h': 102 | print_usage(stdout); 103 | exit(EXIT_SUCCESS); 104 | 105 | case 'c': 106 | opts->no_color = true; 107 | break; 108 | 109 | case 't': 110 | opts->timer = true; 111 | break; 112 | 113 | case 'q': 114 | opts->quiet = true; 115 | break; 116 | 117 | case 's': 118 | opts->skip = true; 119 | skip_list = optarg; 120 | break; 121 | 122 | case 'f': 123 | opts->sigsegv = true; 124 | break; 125 | 126 | default: 127 | return EZTEST_RESULT_ERR; 128 | } 129 | return EZTEST_RESULT_OK; 130 | } 131 | 132 | /** 133 | * Processes application options by parsing given options and setting the 134 | * appropriate options. 135 | * 136 | * @param opts Pointer to application options struct. 137 | * @param argc Argument count. 138 | * @param argv Arguments as strings. 139 | * @return @code RESULT_OK @endcode on success and @code RESULT_ERR @endocode on failure. 140 | * Failure may occur if the user has given an unknown option. 141 | */ 142 | int handle_opts(struct options *opts, const int argc, char **argv) 143 | { 144 | int opt, opt_index; 145 | while((opt = getopt_long(argc, argv, "vhctqfs:", long_opts, &opt_index)) != -1) 146 | { 147 | if(parse_opt(opts, opt) != EZTEST_RESULT_OK) 148 | { 149 | print_usage(stderr); 150 | return EZTEST_RESULT_ERR; 151 | } 152 | } 153 | return EZTEST_RESULT_OK; 154 | } 155 | 156 | --------------------------------------------------------------------------------