ThrowTheSwitch / Ceedling

Ruby-based unit testing and build system for C projects
http://throwtheswitch.org
Other
595 stars 247 forks source link

newbie questions about a bulk of errors. #126

Closed andyinno closed 7 years ago

andyinno commented 7 years ago

Hello,

I am trying to start using ceedling and I am a bit lost. I followed some example that runs correctly, I can mock some simple header following the tutorial https://dmitryfrank.com/articles/unit_testing_embedded_c_applications

As soon as I started integrating all the stuff in a brand new project that use some freertos library I receive a bulk of errors while trying to compile some simple example.

My setup is targetting a avr xmega device. I'm using cmake as makefile generator and I plan to use ceedling by it's side for the testing.

I placed some basic versions of avr/io.h and similar files. I exported the function of freertos that I use in a brand new .h file that I placed in the support folder under test.

#ifndef TASK_H
#define TASK_H

typedef void (*TaskFunction_t)( void * );
typedef unsigned char UBaseType_t;
typedef char BaseType_t;
typedef void * TaskHandle_t;

BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
                        const char * const pcName,
                        const uint16_t usStackDepth,
                        void * const pvParameters,
                        UBaseType_t uxPriority,
                        TaskHandle_t * const pxCreatedTask ); 

#endif

As soon as I mocked this function with a

#include <mock_task.h>

I receive a lot of errors related to cmock.

build/test/mocks/mock_task.c:37:3: error: unknown type name ‘CMOCK_MEM_INDEX_TYPE’
CMOCK_MEM_INDEX_TYPE xTaskCreate_CallInstance;
^~~~~~~~~~~~~~~~~~~~
build/test/mocks/mock_task.c: In function ‘mock_task_Verify’:
build/test/mocks/mock_task.c:48:37: error: ‘CMOCK_GUTS_NONE’ undeclared (first use in this function)
 Mock.xTaskCreate_CallInstance = CMOCK_GUTS_NONE;
                                 ^~~~~~~~~~~~~~~
build/test/mocks/mock_task.c:48:37: note: each undeclared identifier is reported only once for each function it appears in
In file included from ../Src/Tests/Unity/src/unity.h:16:0,
             from build/test/mocks/mock_task.c:5:
build/test/mocks/mock_task.c:50:83: error: ‘CMockStringCalledLess’ undeclared (first use in this function)
   UNITY_TEST_ASSERT(CMOCK_GUTS_NONE == Mock.xTaskCreate_CallInstance, cmock_line, CMockStringCalledLess);

I am a bit lost because it looks like that the mocking can't find itself. Any hint on why this is happening?

relevant informations:

ceedling version
Ceedling:: 0.25.0
CException:: 1.3.1.18
 CMock:: 2.4.3.215
 Unity:: 2.4.0.120
0ge commented 7 years ago

I have no idea about your issue (sorry), but since you are using an AVR Xmega, you might be interested in a script I wrote some time back. It converts a device-specific header (e.g. iox32e5.h) into a testable version. It supports interrupts and registers (with some limitations - see file comments).

It takes the file path as argument and creates a testable copy (e.g. python iox32e5.h would output a iox32e5_testable.h). You then need to modify io.h to include the testable version, as below.

#elif defined (__AVR_ATxmega32E5__)
#ifdef TEST
#include <avr/iox32e5_testable.h>
#else
#  include <avr/iox32e5.h>
#endif

Anyway, it was just something I throw together quickly, so I make no guarantees of it's exactness, but it has worked fine for me for x16e5 and x32e5.

Script

andyinno commented 7 years ago

Hello 0ge,

thank you for your kind reply.

Yes, mine is an x32e5 too so it could work flawlessy.

I will give it a try. anyway I have the feeling that everything is in some way with the include order that is handled by cmock because I cannot reproduce it with a simple repository with just a couple of functions.

mvandervoord commented 7 years ago

I suspect that the root issues might be that (1) your test file doesn't

include cmock.h and (2) that you are using angle brackets to tell the

compiler you're loading a system file instead of "" to tell it your mock is in one of your paths.

Mark

On Tue, Feb 14, 2017 at 5:57 AM andyinno notifications@github.com wrote:

Hello 0ge,

thank you for your kind reply.

Yes, mine is an x32e5 too so it could work flawlessy.

I will give it a try. anyway I have the feeling that everything is in some way with the include order that is handled by cmock because I cannot reproduce it with a simple repository with just a couple of functions.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/ThrowTheSwitch/Ceedling/issues/126#issuecomment-279675945, or mute the thread https://github.com/notifications/unsubscribe-auth/AABAf5jgn797OPYgZbdeX8shgCI9FWJMks5rcYiDgaJpZM4MAQcD .

andyinno commented 7 years ago

Hi mvandervoord, I tried to work around what you are suggesting. In a header file I have a #include instead of a "FreeRTOS.h" so yes, this helped a lot.

regarding (1) I don't see any difference from including it or not.

In any case I receive the same output after checking all the includes.

mvandervoord commented 7 years ago

If you open mock_task.c, does the top look like this?

/* AUTOGENERATED FILE. DO NOT EDIT. */
#include <string.h>
#include <stdlib.h>
#include <setjmp.h>
#include "unity.h"
#include "cmock.h"
#include "mock_task.h"

And you're still getting the error that it can't find the types in cmock.h?

andyinno commented 7 years ago

Hi mvandervoord,

I can confirm that the top of the file is the same you posted.

I am attaching to this post a zip file with some includes that maybe could be useful. CeedlingError.zip

The included files are a dump of the terminal with rake test:all --trace the source file and relative header the mocked files generated. project.yml

mvandervoord commented 7 years ago

Hm. One thing I notice from your zip (and I don't know that this is actually THE problem, but it is probably A problem) is that your source paths probably include a lot more than you care for them to. For example, they include your test folders (which is never something you want them to include). Also, they include the build directories (which again, sounds bad).

You have your source specified as any C file in any folder under the parent folder of where your project file is:

  :source:
    - ../**

I don't think that is probably what you want. If nothing else, you want to make sure it doesn't include the build and test folders. I suspect there are other folders you want to disclude also. Maybe disclude everything in TestCeedling to start?

  :source:
    - ../**
    - -:../TestCeedling/**

Really, I'd just like to say that the ** operator, while useful, can get carried away really quickly. It's almost always better to specify paths fully... or, if you DO use them, keep them specific to a certain subfolder where you know everything inside is valuable.

Can you try to fix that quick and see if this problem still exists?

andyinno commented 7 years ago

Hi mvandervoord,

thank you for your really helpful suggestion. As you pointed out moving the TestCeedling folder out of the Src directory did the trick. I then updated the source path with explicit directories instead of the ** also if it was not needed.

The reason I put the TestCeedling dir as subdirectory of Src is that I usually apply this scheme with cmake and I add the test subdirectory only if it is a debug build. Different tools different standard and way to work.

Now it compile correctly. Back on the road :)

mvandervoord commented 7 years ago

As a clarification (and for anyone coming across this in the future): I don't believe you need to physically move the folder out, just that you need to make sure you don't include TestCeedling as part of your "source" when you tell Ceedling about it. You should be able to locate that folder whereever you like. :)