Coder Social home page Coder Social logo

lingjf / h2unit Goto Github PK

View Code? Open in Web Editor NEW
10.0 0.0 6.0 4.58 MB

Light-weight (as light as hydrogen) unit test framework for C/C++, since 2012

License: Apache License 2.0

C 0.45% C++ 98.45% Makefile 0.01% CMake 0.21% Python 0.70% Shell 0.11% Starlark 0.08%
unittest c cplusplus single-file header-only dependency-break dynamic-mock dynamic-stub matcher memory-leak-detection

h2unit's Introduction

h₂unit

Release CI Standard Linux macOS Windows WSL Cygwin MinGW GCC Clang MSVC Arch

What's h₂unit

H₂UNIT is a xUnit unit test framework for C/C++, a light-weight framework as light as chemical hydrogen.

How to use it

Example is a helpful manual document.

All the code of following features can be found in the example folder, test h2unit by h2unit, and it is executable, the result is visable.

Design is Difference

1. Dynamic STUB

Unit test cases should be easy to maintain. Dependency breaking is the key way.

Typically, function pointer replacement is a common solution to break dependency.

/* product code */ 
int foobar_impl(int a, char* b)
{
   ......
}
int (*foobar) (int a, char* b) = foobar_impl;
void do_call_foobar()
{
   ......
   z = foobar(x, y);
   ......
}
/* unit test code */
int foobar_fake(int a, char* b)
{
   ......
   return 1;
}
CASE(case name)
{
   foobar = foobar_fake;
   do_call_foobar();
   foobar = foobar_impl;
}

The most disadvantage of function pointer replacement is changing of product source code.
Objective of Dynamic STUB is same as function pointer replacement, but it is unnecessary to change product source code.

CASE(case name)
{
   STUB(foobar, foobar_fake);
   do_call_foobar();
}

With help of lambda, fake_function can following with STUB.

CASE(case name)
{
   STUBS(foobar, int, (int a, char* b)) {
      OK(1, a);
      sprintf(b, "return value by argument");
      return 1;
   }
   do_call_foobar();
}

2. Dynamic MOCK

Compare to Dynamic STUB, Dynamic MOCK provide a easy way to check call times, input arguments and inject return value.

CASE(case name)
{
   MOCK(foobar, int(int a, char* b)).Once(1, "A").Return(11);
   do_call_foobar();
}

Expect foobar called with a equals 1, b equals "A" 1 time in this case, and make it returns 11.

3. JSON Compare

run result

4. Matcher

Matchers, as popularized by the Hamcrest framework are an alternative way to write complex expection in OK or MOCK.

5. Header-only Single-file

Only need to include 1 ONE いち source file: h2unit.h

h2unit.h contains main() function, and main() will execute test cases. user no need to write main() anymore.

Supported platform

  • Linux gcc 5.5+ (regex support, SFINAE support), clang 7+, x86, x86_64, arm64(aarch64)
  • macOS 10.14+ 10.15 11.05, xcode 10.3+
  • Windows Visual Studio 2019+ 16+ MSVC 14.20+ _MSC_VER 1913+
  • Windows Cygwin, MinGW 64, ucrt64, clang64
  • Windows WSL (Debian, Ubuntu, Kali, openSUSE)

h2unit's People

Contributors

lingjf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

h2unit's Issues

Compile failed under 64bit system

compile error message:

h2unit.cpp: In member function ‘void h2unit_case::stub(void_, void_, const char*)’:
h2unit.cpp:918: error: ‘p’ was not declared in this scope

Can't dynamic stub functions by name in MAC OS

It success to dynamic stub by function pointer, but it fail to dynamic stub by function name. It can be reproduced in unit test environment.

H2CASE(dynamic_stub, "test dynamic stub local static function")

Analysis:
mprotect() failed because the address which is generated by 'nm' with the function name.
nm's output symbol address is incorrect (comparing with function pointer).

Merge h2unit.cpp into single h2unit.h file

Currently end-user should include two files: h2unit.cpp and h2unit.h.
If there two files can be merged into one file , it will be more simple to use.

C++ class can be wrote in header file, static member method and static variable can be used to implement global instance. I have wrote a test, it works.

The difficult is how to implement memory leak detection for C source file.
A work around is that consider C source file as C++ source file and compile with C++ compiler.

Can't take over assert() macro

A normal idea to replace assert() is undefine assert first, then define assert to new function. Include assert.h (cassert) before re-define assert.
But in actual, assert.h does not following #ifndef/#define/#endif mode , so the normal idea does not work.
More information refer to /user/include/assert.h

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.