Giter VIP home page Giter VIP logo

mimick's Introduction

Mimick

Unix Build Status Windows Build Status Coverity License Version Gitter Room

A KISS, cross-platform C Mocking library

Philosophy

Warning: this library is still experimental. APIs will change before the beta phase and things will break. Use at your own risk.

Mimick aims to be a simple of use and powerful mocking and stubbing library for C.

It doesn't rely on external code generation or compiler plugin to work -- simply link the library to your tests, and you're good to go!

Mimick works by poisoning the GOT of the target dynamic module at runtime, making any call to the target functions routed to one of its own stubs. The mock API is only sugar on top of the stub API, and provides a default stub suitable for testing interactions and specifying behaviour.

Samples

Here is a simple usage of Mimick to mock the malloc function:

#include <stdlib.h>
#include <assert.h>
#include <mimick/mimick.h>

/* Define the blueprint of a mock identified by `malloc_proto`
   that returns a `void *` and takes a `size_t` parameter. */
mmk_mock_define (malloc_mock, void *, size_t);

int main(void) {
    /* Mock the malloc function in the current module using 
       the `malloc_mock` blueprint. */
    mmk_mock("malloc@self", malloc_mock);

    /* Tell the mock to return NULL and set errno to ENOMEM
       whatever the given parameter is. */
    void *result = NULL;
    mmk_when(malloc(mmk_any(size_t)),
            .then_return = &result,
            .then_errno = ENOMEM);

    assert(malloc(42) == result && errno == ENOMEM);

    mmk_reset(malloc);
}

Or, alternatively:

malloc_mock mock = mmk_mock("malloc@self", malloc_mock);

void *result = NULL;
mmk_when(mock(mmk_any(size_t)),
        .then_return = &result,
        .then_errno = ENOMEM);

assert(malloc(42) == result && errno == ENOMEM);

mmk_reset(mock);

Other samples may be found in the samples directory.

Compatibility matrix

Supported Compilers: GCC 4.6+, Clang 3.5+, MSVC 14+

Legend:

: Supported.
: Unsupported.
?: Not Tested, but is expected to work.
: Does not exist / not applicable.
~: Works on some conditions.

Arch Linux OS X/iOS FreeBSD Windows
x86
x86_64
ARM ?
ARM64 ? ?
PPC

F.A.Q.

Q. Can I mock/stub static functions?
A. No. Static functions are, by definition, private implementations details, and because they are not exported nor visible to the outside world they cannot (and should not) be mocked/stubbed.

Q. Can I mock/stub functions inside a static library?
A. Maybe. Functions inside a static library are moved inside the executable and are not called using the PLT by default. You need to build your library to use Position-Independent Code, otherwise the functions cannot be stubbed nor mocked.

Q. I am mocking a standard library function, but mmk_when and mmk_verify are not working, why is this happening?
A. It's very possible that your compiler is optimizing away your function call inside mmk_when or mmk_verify since it has determined that there are no visible side effects in not calling the function. Compile your tests without optimizations (with a compiler flag or the mmk_no_optimize function attribute if it is available to your compiler), or use the function pointer returned by mmk_mock rather than the function itself.

Q. Does this run on embedded systems / bare metal?
A. Yes, but on very specific conditions. Your code must be position-independent, call functions using a global offset table or similar mechanism, and use an executable format that Mimick can handle (ELF, PE, Mach-O).
You also need to provide definitions for some functions like malloc, realloc, and free.

mimick's People

Contributors

ahcorde avatar audrow avatar blast545 avatar brawner avatar brettrd avatar christophebedard avatar clalancette avatar eboasson avatar felixf4xu avatar hidmic avatar jpace121 avatar mjcarroll avatar phdittmann avatar snaipe avatar traversaro avatar

Stargazers

 avatar

Watchers

 avatar  avatar

mimick's Issues

Support for RISC-V 64

I'm trying to build ROS 2 for a RISC-V 64 target and Mimick makes it not possible.
I've been digging around and looks like @ziyao233 has a PR upstream that provides support to RISC-V. It would be great if you could merge her PR and pack a new version :D

Support for WIN32

Hey there!

I'm trying to build ROS2 for WIN32 and currently I'm struggling to build the Mimick vendor for WIN32.
I've tried opening the mimick_vendor.sln from the build directory to get a closer look but the only error i can see is

Custom build for 'C:\dev\ros2_foxy_custom\build\mimick_vendor\CMakeFiles\ffe1b1d7f3514bb94e1360e32db04917\mimick-4c742d61d4f47a58492c1afbd825fad1c9e05a09-mkdir.rule;C:\dev\ros2_foxy_custom\build\mimick_vendor\CMakeFiles\ffe1b1d7f3514bb94e1360e32db04917\mimick-4c742d61d4f47a58492c1afbd825fad1c9e05a09-download.rule;C:\dev\ros2_foxy_custom\build\mimick_vendor\CMakeFiles\ffe1b1d7f3514bb94e1360e32db04917\mimick-4c742d61d4f47a58492c1afbd825fad1c9e05a09-update.rule;C:\dev\ros2_foxy_custom\build\mimick_vendor\CMakeFiles\ffe1b1d7f3514bb94e1360e32db04917\mimick-4c742d61d4f47a58492c1afbd825fad1c9e05a09-patch.rule;C:\dev\ros2_foxy_custom\build\mimick_vendor\CMakeFiles\ffe1b1d7f3514bb94e1360e32db04917\mimick-4c742d61d4f47a58492c1afbd825fad1c9e05a09-configure.rule;C:\dev\ros2_foxy_custom\build\mimick_vendor\CMakeFiles\ffe1b1d7f3514bb94e1360e32db04917\mimick-4c742d61d4f47a58492c1afbd825fad1c9e05a09-build.rule;C:\dev\ros2_foxy_custom\build\mimick_vendor\CMakeFiles\ffe1b1d7f3514bb94e1360e32db04917\mimick-4c742d61d4f47a58492c1afbd825fad1c9e05a09-install.rule;C:\dev\ros2_foxy_custom\build\mimick_vendor\CMakeFiles\fc7e7970b379d1a271c8de359019ce83\mimick-4c742d61d4f47a58492c1afbd825fad1c9e05a09-complete.rule;C:\dev\ros2_foxy_custom\build\mimick_vendor\CMakeFiles\d490d8c63ec77fda518bad3d3ae6d6fb\mimick-4c742d61d4f47a58492c1afbd825fad1c9e05a09.rule' exited with code 1. mimick-4c742d61d4f47a58492c1afbd825fad1c9e05a09

When trying to build mimick with cmake and msbuild I can only use

cmake -G "Visual Studio 16 2019" ..

Any -A options lead to configuration errors.

Running
msbuild ALL_BUILD.vcxproj
leads to muliple errors, no matter which configuration is used (Realease/Debug).

"C:\dev\Mimick\build\ALL_BUILD.vcxproj" (default target) (1) ->
"C:\dev\Mimick\build\mimick_tests.vcxproj" (default target) (3) ->
"C:\dev\Mimick\build\test\mmk_test_c.vcxproj" (default target) (4) ->
"C:\dev\Mimick\build\mimick.vcxproj" (default target) (6) ->
(_MASM target) ->
  C:\dev\Mimick\src\asm\trampoline-i386-cdecl.asm(24): error A2008: syntax error : . [C:\dev\Mimick\build\mimick.vcxproj]
  C:\dev\Mimick\src\asm\trampoline-i386-cdecl.asm(25): error A2008: syntax error : . [C:\dev\Mimick\build\mimick.vcxproj]
  C:\dev\Mimick\src\asm\trampoline-i386-cdecl.asm(33): error A2070: invalid instruction operands [C:\dev\Mimick\build\mimick.vcxproj]
  C:\dev\Mimick\src\asm\trampoline-i386-cdecl.asm(36): error A2070: invalid instruction operands [C:\dev\Mimick\build\mimick.vcxproj]
  C:\dev\Mimick\src\asm\trampoline-i386-cdecl.asm(38): error A2070: invalid instruction operands [C:\dev\Mimick\build\mimick.vcxproj]
  C:\dev\Mimick\src\asm\trampoline-i386-cdecl.asm(39): error A2024: invalid operand size for instruction [C:\dev\Mimick\build\mimick.vcxproj]
  C:\dev\Mimick\src\asm\trampoline-i386-cdecl.asm(40): error A2070: invalid instruction operands [C:\dev\Mimick\build\mimick.vcxproj]
  C:\dev\Mimick\src\asm\trampoline-i386-cdecl.asm(42): error A2024: invalid operand size for instruction [C:\dev\Mimick\build\mimick.vcxproj]
  C:\dev\Mimick\src\asm\trampoline-i386-cdecl.asm(46): error A2070: invalid instruction operands [C:\dev\Mimick\build\mimick.vcxproj]
  C:\dev\Mimick\src\asm\trampoline-i386-cdecl.asm(47): error A2024: invalid operand size for instruction [C:\dev\Mimick\build\mimick.vcxproj]
  C:\dev\Mimick\src\asm\trampoline-i386-cdecl.asm(50): error A2070: invalid instruction operands [C:\dev\Mimick\build\mimick.vcxproj]
  C:\dev\Mimick\src\asm\trampoline-i386-cdecl.asm(52): error A2024: invalid operand size for instruction [C:\dev\Mimick\build\mimick.vcxproj]
  C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VC\v160\BuildCustomizations\masm.targets(70,5): error MSB3721: The command "ml64.exe /c
/nologo /safeseh /Zi /Fo"mimick.dir\Debug\trampoline-i386-cdecl.obj" /D"WIN32" /D"_WINDOWS" /D"_CRT_SECURE_NO_WARNINGS" /D"WIN32_LEAN_AND_MEAN" /D"CMAKE_INTDIR="Debug"" /
I "C:\dev\Mimick\include" /I "C:\dev\Mimick\src" /I "C:\dev\Mimick\build\src" /W3 /errorReport:prompt  /Ta"C:\dev\Mimick\src\asm\trampoline-i386-cdecl.asm"" exited with c
ode 1. [C:\dev\Mimick\build\mimick.vcxproj]

So I'm having a hard time figuring out how to make it work but to be honest this could also be because I've only worked with rather small and simple CMakeLists so far and never really had to bother much about what's going on "behind the scenes" :D

Could you point me in the right direction here?

Mimick issue for ros2 foxy m1 Mac build

I tried to compile ros2 on apple silicon Mac, and get several errors with mimics.

--- stderr: mimick_vendor
Cloning into 'mimick-ext'...
Note: switching to '99a35f3d2067708931945c64ac9caee80a0ef50e'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

git switch -c

Or undo this operation with:

git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at 99a35f3 Update cmake minimum version to 2.8.12 (#15)
Undefined symbols for architecture arm64:
"_mmk_trampoline", referenced from:
_create_trampoline in libmimick.a(trampoline.c.o)
"_mmk_trampoline_end", referenced from:
_create_trampoline in libmimick.a(trampoline.c.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[5]: *** [sample/strdup/strdup_test] Error 1
make[4]: *** [sample/strdup/CMakeFiles/strdup_test.dir/all] Error 2
make[3]: *** [all] Error 2
make[2]: *** [mimick-ext-prefix/src/mimick-ext-stamp/mimick-ext-build] Error 2
make[1]: *** [CMakeFiles/mimick-ext.dir/all] Error 2
make: *** [all] Error 2
make: INTERNAL: Exiting with 9 jobserver tokens available; should be 8!

Failed <<< mimick_vendor [6.73s, exited with code 2]
Aborted <<< console_bridge_vendor [2.48s]
Aborted <<< qt_gui [1.40s]
Aborted <<< resource_retriever [2.64s]
Aborted <<< rosidl_runtime_cpp [5.30s]
Aborted <<< zstd_vendor [41.8s]
Aborted <<< foonathan_memory_vendor [48.2s]
Aborted <<< rviz_ogre_vendor [50.5s]

Summary: 103 packages finished [1min 1s]
1 package failed: mimick_vendor
7 packages aborted: console_bridge_vendor foonathan_memory_vendor qt_gui resource_retriever rosidl_runtime_cpp rviz_ogre_vendor zstd_vendor
15 packages had stderr output: ament_index_cpp fastcdr foonathan_memory_vendor mimick_vendor orocos_kdl resource_retriever rosidl_runtime_cpp rosidl_typesupport_interface rviz_ogre_vendor shared_queues_vendor test_osrf_testing_tools_cpp tlsf uncrustify_vendor yaml_cpp_vendor zstd_vendor
198 packages not processed

I think issue in the mimick_vendor/mimick-ext-prefix/src/mimick-ext/src/asm/trampoline-aarch64.S

Mark asm code with no-executable-stack fails to build on M1 mac

#26 is not compatible with M1 macs.

System: macOS Ventura 13.4
Machine: MacBook Pro Apple M1 Max

Repeating details from #26 (comment):

% clang --version
Apple clang version 14.0.3 (clang-1403.0.22.14.1)
Target: arm64-apple-darwin22.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
[  4%] Building ASM object CMakeFiles/mimick.dir/src/asm/trampoline-aarch64.S.o
/Users/rhys/Code/ros2/rolling/ros2-rolling/src/Mimick/src/asm/trampoline-aarch64.S:80:19: error: unexpected token in '.section' directive
.section .note.GNU-stack, "", @progbits

Mimick issue for ros2 foxy - debian 10 i386

I am using docker container (docker pull i386/debian:10.7). As usual I followed instructions to install ros2 foxy from official webpage.
After performing colcon build, mimick-ext fails.

Starting >>> mimick_vendor
--- stderr: mimick_vendor                                                                                                                                
Cloning into 'mimick-ext'...
Note: checking out 'f171450b5ebaa3d2538c762a059dfc6ab7a01039'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at f171450 Add armv7l as a 32-bit ARM architecture. (#16)
/root/ros2_foxy/build/mimick_vendor/mimick-ext-prefix/src/mimick-ext/src/asm/trampoline-x86_64-systemv.S: Assembler messages:
/root/ros2_foxy/build/mimick_vendor/mimick-ext-prefix/src/mimick-ext/src/asm/trampoline-x86_64-systemv.S:39: Error: bad register name `%r11'
/root/ros2_foxy/build/mimick_vendor/mimick-ext-prefix/src/mimick-ext/src/asm/trampoline-x86_64-systemv.S:41: Error: bad register name `%r11'
/root/ros2_foxy/build/mimick_vendor/mimick-ext-prefix/src/mimick-ext/src/asm/trampoline-x86_64-systemv.S:42: Error: bad register name `%r11)'
/root/ros2_foxy/build/mimick_vendor/mimick-ext-prefix/src/mimick-ext/src/asm/trampoline-x86_64-systemv.S:44: Error: bad register name `%rdi'
/root/ros2_foxy/build/mimick_vendor/mimick-ext-prefix/src/mimick-ext/src/asm/trampoline-x86_64-systemv.S:45: Error: bad register name `%rsi'
/root/ros2_foxy/build/mimick_vendor/mimick-ext-prefix/src/mimick-ext/src/asm/trampoline-x86_64-systemv.S:46: Error: bad register name `%rdx'
/root/ros2_foxy/build/mimick_vendor/mimick-ext-prefix/src/mimick-ext/src/asm/trampoline-x86_64-systemv.S:47: Error: bad register name `%rcx'
.....
.....
.....
/root/ros2_foxy/build/mimick_vendor/mimick-ext-prefix/src/mimick-ext/src/asm/trampoline-x86_64-systemv.S:100: Error: bad register name `%r11'
make[5]: *** [CMakeFiles/mimick.dir/build.make:63: CMakeFiles/mimick.dir/src/asm/trampoline-x86_64-systemv.S.o] Error 1
make[4]: *** [CMakeFiles/Makefile2:112: CMakeFiles/mimick.dir/all] Error 2
make[3]: *** [Makefile:141: all] Error 2
make[2]: *** [CMakeFiles/mimick-ext.dir/build.make:111: mimick-ext-prefix/src/mimick-ext-stamp/mimick-ext-build] Error 2
make[1]: *** [CMakeFiles/Makefile2:137: CMakeFiles/mimick-ext.dir/all] Error 2
make: *** [Makefile:141: all] Error 2
---
Failed   <<< mimick_vendor [15.9s, exited with code 2]

I am also not quite sure, why its refering to 32-bit ARM architecture. It should be 32bit AMD instead

Mimick does not seem to work on Ubuntu 24.04 aarch64

When trying to run Mimick on Ubuntu 24.04 aarch64, it fails to start up.

Steps to reproduce:

  1. Clone this repository: git clone https://github.com/ros2/Mimick
  2. cd Mimick
  3. mkdir build
  4. cd build
  5. cmake ..
  6. make
  7. ./sample/strdup/strdup_test

That last step will print something like:

mimick: Initialization error: could not find definitions for vital function(s): 'abort' 'vfprintf'
Aborted (core dumped)

A few other notes:

  • Running this test on Ubuntu 22.04 aarch64 works fine.
  • Running this test on Ubuntu 24.04 amd64 works fine.
  • This failure seems to have something to do with glibc (which happens to be version 2.39 in Ubuntu 24.40). In particular, Mimick is expecting that there is an exported symbol called _r_debug in glibc that contains the symbols for things like abort and vfprintf. That symbol does indeed exist, but it seems not to contain the symbols Mimick wants.

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.