ThrowTheSwitch / CMock

CMock - Mock/stub generator for C
http://throwtheswitch.org
MIT License
672 stars 273 forks source link

Ceedling crashes when mock not expected #351

Closed professor-frink closed 6 months ago

professor-frink commented 3 years ago

Hi,

Setup: Ceedling:: 0.28.1 CMock:: 2.4.4 Unity:: 2.4.1 CException:: 1.3.1 OS: Windows 7 Ruby: ruby 2.4.1p111 (2017-03-22 revision 58053) [x64-mingw32]

Here's the general setup to replicate the issue:

  1. Module under test: A, function: a_testme();
  2. a_testme depends on Module B. Function bool b_testMeDependsOnThis(void);
  3. I declare the "mock_b.h" and I see the mock is being created
  4. I run a test just calling a_testme() WITHOUT calling b_testMeDependsOnThis_ExpectAndReturn(true); and I get the following error

            ERROR: Test executable "test_a.bin" failed.
            > Produced no output to $stdout.
            > And exited with status: [0] (count of failed tests).
            > This is often a symptom of a bad memory access in source or test code.
    
            rake aborted!
    
            vendor/ceedling/lib/ceedling/generator_helper.rb:36:in `test_results_error_handler'
            vendor/ceedling/lib/ceedling/generator.rb:162:in `generate_test_results'
            vendor/ceedling/lib/ceedling/rules_tests.rake:47:in `block in <top (required)>'
            vendor/ceedling/lib/ceedling/task_invoker.rb:74:in `invoke_test_results'
            vendor/ceedling/lib/ceedling/test_invoker.rb:104:in `block in setup_and_invoke'
            vendor/ceedling/lib/ceedling/test_invoker.rb:63:in `each'
            vendor/ceedling/lib/ceedling/test_invoker.rb:63:in `setup_and_invoke'
            vendor/ceedling/lib/ceedling/rules_tests.rake:62:in `block (2 levels) in <top (required)>'
            C:/Ruby24-x64/bin/ceedling:23:in `load'
            C:/Ruby24-x64/bin/ceedling:23:in `<main>'
            Tasks: TOP => build/test/results/test_a.pass
            (See full trace by running task with --trace)

Sorry if this is a duplicate, or just my lack of understanding of CMock usage, but in my trying to write characterization tests for this module, it makes it very difficult to know where I might have missed a mock call without having at least some line number information indicating where the first missing mock call should be. I can work through it by just choosing a code path and inserting the mocks where I think they should be, but still it would make things hugely more productive if there were some "default mock handler" that just indicates the line number where the missing mock should be in the module under test. Or maybe I am just misusing CMock and Ceedling :-).

Any help would be greatly appreciated.

Thanks!

mvandervoord commented 3 years ago

Hi.

You're in luck. Cmock handles missing mocks just as you describe. If you've #included the mock, and you have a mock that doesn't get called during a test, it will notify you of the test and the mock call that is missing.

What you're seeing here is that your test executable is crashing, and therefore Ceedling doesn't have any more information to work with.

If it's just the existence of the mock or not, it may be a bug you've run into (hopefully just because you're running an older version of Ceedling). More likely, though, it's as the error code mentions: Your test is likely crashing due to a memory problem. This is often an uninitialized pointer or something to that effect.

If you'd like to copy/paste the test and the function you're testing here, we can probable help you sort it out.

professor-frink commented 3 years ago

Hi - Ok, I found the problem but thought I'd share in case it helps with documentation. Worst case it's just me not completely reading the documentation :-).

Attempt to recreate in a fresh environment Ceedling:: 0.28.1 CException:: 1.3.1.18 CMock:: 2.4.4.215 Unity:: 2.4.1.120

  1. Created blinky example.
  2. Added new module LED.h which has one function - void LED_on(void) with an empty body
  3. In BlinkyTask, added a call to LED_on();
  4. Added new test (including "mock_LED.h") WITHOUT call to LED_on_Expect() - Works as expected. Failed test summary indicating Function LED_on called more times than expected.

I tried to replicate this in my problem project environment by simply copying pasting the Blinky code and ONLY testing BlinkyTask. No luck.

Luckily I copied over the project.yml from Blinky to my problem project as well (my project was under version control) so I could see the diffs. One diff in particular that was included in my code (but was missing from Blinky example) was the following:

in order to add common defines: 1) remove the trailing [] from the :common: section 2) add entries to the :common: section (e.g. :test: has TEST defined) :commmon: &common_defines [] :test:

By simply deleting UNITY_EXCLUDE_SETJMP_H the test runner no longer crashes and the test (correctly) fails as expected indicating the correct location of the missing mock calls.

The weird thing is, I don't know why I had that line in my project.yml to begin with, but it doesn't seem to affect any of my tests. In any case - if this is a me problem, then thanks for the support! If this is a documentation update I could help out with, I'd be happy to contribute somehow.

Cheers, Frink