Open MichaelBMiner opened 2 years ago
I think the warning is very informative: please use strong typing of the variables. Welcome to the embedded world.
And secondly: It seems like you are trying to run your arm executable on your PC (or is the terminal output from the arm chip?).
I think the warning is very informative: please use strong typing of the variables. Welcome to the embedded world.
And secondly: It seems like you are trying to run your arm executable on your PC (or is the terminal output from the arm chip?).
I run ceedling as part of a Jenkins pipeline. Jenkins runs in Ubuntu which is able to compile/run this. The very obvious overflow warning is something I know about and does not affect the tests. All tests fail in the same way. Can you please explain why the warning message leads you to strongly typed variables?
Because I assume Jenkins is running x86_64 architecture, which has different basic types than arm cortex-a7. Because of that difference it leads me to assume you are trying to run arm binary on a x86_64 and compiler is telling you that with a warning of an incompatible type (that sources are not portable enough).
Because I assume Jenkins is running x86_64 architecture, which has different basic types than arm cortex-a7. Because of that difference it leads me to assume you are trying to run arm binary on a x86_64 and compiler is telling you that with a warning of an incompatible type (that sources are not portable enough).
When you put it like that it makes sense. I was trying to build with gcc and the Ubuntu version of these files. I will give that another shot.
Because I assume Jenkins is running x86_64 architecture, which has different basic types than arm cortex-a7. Because of that difference it leads me to assume you are trying to run arm binary on a x86_64 and compiler is telling you that with a warning of an incompatible type (that sources are not portable enough).
This all stems from the inability to mock socket.h. Socket.h is in many places,
I can get everything to build until I place in a need to mock socket.h. project.txt
We have made a mock for socket.h but we want to be able to use the _Expect, _ExpectAndReturn functions offered by ceedling mocks.
Your screenshot is again showing only x86_64 socket.h
yet you were compiling for arm (seen now that you moved to x86_64).
I think you have 2 options here. Compile and run it as x86_64 on your Jenkins (based on latest project.txt
you picked this path) or have a cortex-a7 with ubuntu and then (either cross or) compile it for cortex-a7 and find the matching socket.h
for that.
Mocking the socket.h
itself should not produce a problem (not sure how much architecture specific it is), so you can just write what kind of problem you get with it, so that we see what is missing from your ubuntu socket.h
.
My socket.h is coming from /usr/include/linux. This is from Ubuntu itself. My application can be built on either system.
My goal is to use gcc and compile for x86_64. My only issue is no matter where I take socket.h from ceedling is unable to find it.
Edit: My workspace and my jenkins server run Ubuntu 20.04.
So you have in your test source file
#include "mock_socket.h"
yet Ceedling reports which error? Does it output/print something like "mocking socket.h" in command line when running a test command?
Test 'test_can.c'
-----------------
Generating include list for libsocketcan.h...
Generating include list for socket.h...
Creating mock for libsocketcan...
Creating mock for socket...
WARNING: No function prototypes found!
In file included from test/comms/test_can.c:6:
build/test/mocks/mock_socket.h:6:10: fatal error: socket.h: No such file or directory
6 | #include "socket.h"
| ^~~~~~~~~~
compilation terminated.
ERROR: Shell command failed.
> Shell executed command:
'gcc -E -I"/var/lib/gems/2.7.0/gems/ceedling-0.31.1/vendor/unity/src" -I"/var/lib/gems/2.7.0/gems/ceedling-0.31.1/vendor/cmock/src" -I"build/test/mocks" -I"test" -I"test/comms" -I"test/test_utilities" -I"test/support" -I"test/support" -I"src" -I"src/comms" -I"src/utilities" -I"include" -I"include/comms" -I"include/utilities" -DCEEDLING_TESTS -DCEEDLING_TESTS -DGNU_COMPILER "test/comms/test_can.c" -o "build/test/preprocess/files/test_can.c"'
> And exited with status: [1].
rake aborted!
ShellExecutionException: ShellExecutionException
/var/lib/gems/2.7.0/gems/ceedling-0.31.1/lib/ceedling/tool_executor.rb:88:in `exec'
/var/lib/gems/2.7.0/gems/ceedling-0.31.1/lib/ceedling/preprocessinator_file_handler.rb:12:in `preprocess_file'
/var/lib/gems/2.7.0/gems/ceedling-0.31.1/lib/ceedling/preprocessinator.rb:48:in `preprocess_file'
/var/lib/gems/2.7.0/gems/ceedling-0.31.1/lib/ceedling/preprocessinator.rb:12:in `block in setup'
/var/lib/gems/2.7.0/gems/ceedling-0.31.1/lib/ceedling/preprocessinator_helper.rb:37:in `preprocess_test_file'
/var/lib/gems/2.7.0/gems/ceedling-0.31.1/lib/ceedling/preprocessinator.rb:33:in `preprocess_test_and_invoke_test_mocks'
/var/lib/gems/2.7.0/gems/ceedling-0.31.1/lib/ceedling/test_invoker.rb:84:in `block in setup_and_invoke'
/var/lib/gems/2.7.0/gems/ceedling-0.31.1/lib/ceedling/test_invoker.rb:51:in `each'
/var/lib/gems/2.7.0/gems/ceedling-0.31.1/lib/ceedling/test_invoker.rb:51:in `setup_and_invoke'
/var/lib/gems/2.7.0/gems/ceedling-0.31.1/lib/ceedling/rules_tests.rake:70:in `block (2 levels) in <top (required)>'
/var/lib/gems/2.7.0/gems/ceedling-0.31.1/bin/ceedling:345:in `block in <top (required)>'
/var/lib/gems/2.7.0/gems/ceedling-0.31.1/bin/ceedling:332:in `<top (required)>'
/usr/local/bin/ceedling:23:in `load'
/usr/local/bin/ceedling:23:in `<main>'
Tasks: TOP => test:test_can.c
(See full trace by running task with --trace)
ERROR: Ceedling Failed
I am trying to mock
int32_t can_filter_enable(){
int32_t ret = setsockopt(can_rx_socket, SOL_CAN_RAW, CAN_RAW_FILTER, &can_filter_array, sizeof(struct can_filter) * CAN_RAW_FILTER_MAX);
if (ret != SUCCESS) {
logger_log_error(&can_logger, LOG_ERR, errno, "Error - Could not enable can filter %s", can_logging_buffer);
}
return ret;
}
setsockopt is coming from sys/socket.h. I have attempted to put that path into my yml file. It cannot find it. I cannot use setsockopt_ExpectAndReturn.
The message WARNING: No function prototypes found!
suggests that it found socket.h, it just didn't make a mock for it because there weren't any function prototypes in the header. I see you're running the preprocessor... if you look in build/test/preprocess
and find socket.h
, does it have any function prototypes? If not, look at the original socket.h and see if there are #ifdefs or anything that might be required?
In the includes folder there is socket.h which contains
--- []
In the files folder socket.h contains a lot. All functions are extern. Same as the socket.h file given by Ubuntu.
Ah. That last point might be the key. Try adding this to your project.yml:
:cmock:
:treat_extern: :include
I get the same error. The socket.h files in preprocess are the same as well.
I added the treat_extern as requested
:cmock:
:mock_prefix: mock_
:when_no_prototypes: :warn
:enforce_strict_ordering: TRUE
:unity_helper_path: test/support/unity_helper.h
:treat_extern: :include
:plugins:
- :ignore
- :callback
:treat_as:
uint8: HEX8
uint16: HEX16
uint32: UINT32
int8: INT8
bool: UINT8
I believe I've misled you. Try :treat_externs:
(note the s
)
Is there a debug message I can attempt to print? I get the same result.
:cmock:
:mock_prefix: mock_
:when_no_prototypes: :warn
:enforce_strict_ordering: TRUE
:unity_helper_path: test/support/unity_helper.h
:treat_externs: include
:plugins:
- :ignore
- :callback
:treat_as:
uint8: HEX8
uint16: HEX16
uint32: UINT32
int8: INT8
bool: UINT8
:) now this one is on you :treat_externs: :include
(note the extra :
)
What we're attempting to do is tell CMock that when it encounters externed functions, it should mock them. By default it ignores them. If all the functions in that file are being ignored, it leads to the warning you've received... and that leads to it not bothering to create a mock for it.
That last behavior annoys me, now that I'm saying it out loud. It should be fine to warn you that there are no prototypes, and produce a header file anyway. I'll have to fix that... but this should get you running for now.
I have tried it a few ways but always get the same result (As above). To make sure I understand you I decided to search GitHub for other peoples code.
It's not "too many". It's the correct number. This is correct:
:treat_externs: :include
Any other method is incorrect. Ruby symbols start with a :
, and we have a hash of a symbol giving us another symbol... so all 3 :
are required.
Updating it to this method still results in the same problem for you? It still tells you that there are no function prototypes? Can you paste a single function here so I can see what else it might be getting confused about?
This is the function
int32_t can_filter_enable(){
int32_t ret = setsockopt(can_rx_socket, SOL_CAN_RAW, CAN_RAW_FILTER, &can_filter_array, sizeof(struct can_filter) * CAN_RAW_FILTER_MAX);
if (ret != SUCCESS) {
logger_log_error(&can_logger, LOG_ERR, errno, "Error - Could not enable can filter %s", can_logging_buffer);
}
return ret;
}
My apologies. I meant one of the function prototypes that you are trying to mock, ideally from the preprocessor/files directory since that is the one that is getting fed into CMock.
setsockopt is the function I am attempting to mock. It is in socket.h and the function prototype is
extern int setsockopt (int __fd, int __level, int __optname,
const void *__optval, socklen_t __optlen) __THROW;
Edit, just re-read your message. I will get the correct one now.
In the preprocess files folder I get
extern int setsockopt (int __fd, int __level, int __optname,
const void *__optval, socklen_t __optlen)
__attribute__ ((__nothrow__ , __leaf__))
;
If you were to manually edit the original header file and remove __attribute__ ((__nothrow__ , __leaf__))
briefly (we'll put it back in a moment), is CMock then able to preprocess it? I'm wondering if it's getting confused by that.
I changed the function prototype to
extern int setsockopt (int __fd, int __level, int __optname,
const void *__optval, socklen_t __optlen);
In the preprocessor socket.h I have
extern int setsockopt (int __fd, int __level, int __optname,
const void *__optval, socklen_t __optlen);
But the error is the same
Hm. And if you remove the extern manually it's still the same?
It otherwise looks like a simple function which should be mockable.
Changing the function prototype to
int setsockopt (int __fd, int __level, int __optname,
const void *__optval, socklen_t __optlen);
Same error
Edit: Looking through the source header file, there are no ifdefs around my function.
In my test_file attached above. If I take out #include "mock_socket.h"
everything works fine. I cannot fully test that function as I cannot force a failure. On Ubuntu the setsockopt
always fails.
Ok. So I've scrolled back up to review all of this stuff. I'm not sure why it's still telling you WARNING: No function prototypes found!
but it doesn't address the original issue you were discussing with @Letme anyway. The fact still remains that when it does make a mock, it doesn't seem to be including socket.h
.
For this, you will probably want to force it to include a specific version, like:
:paths:
:include:
- /whatever/the/path/is/
I did do something like that. I have the paths and files sections filled as so
:paths:
:test:
- +:test/**
:source:
- src/**
:support:
- test/support
:include:
- include/**
- /usr/include/sys/socket.h
- /usr/include/libsocketcan.h
:files:
:include:
- +:/usr/include/**
- +:/usr/include/sys/**
You seem to have those backwards, maybe?:
:test:
- +:test/**
:source:
- src/**
:support:
- test/support
:include:
- include/**
- +:/usr/include/**
- +:/usr/include/sys/**
:files:
:include:
- /usr/include/sys/socket.h
- /usr/include/libsocketcan.h
In any case, you can use the following:
ceedling files:include
That should list all the files it's found in the places you've specified. If you don't see socket.h on the list, it's not found it.
An interesting note. The file socket.h in /usr/include/sys/socket.h is a linked file to ../x86_64-linux-gnu/sys/socket.h
Running ceedling files:include I can see 10 files. One of which is - /usr/include/x86_64-linux-gnu/sys/socket.h
. I still get the error that socket.h cannot be found. My yml file should have everything we discussed.
project.txt
If I copy the socket.h header file into my includes folder. Everything magically works
Interesting. So your socket.h
is a symlink? I wonder if that has anything to do with the issue. I've not used them a lot with ruby, but I would have assumed it would just open the linked file. I'll have to do some reading up on that.
I figured that could be an issue so I removed it, and placed the absolute path. I can see it is being included but still not found. Not sure what else to do at this point.
So, ceedling is finding your socket.h file, because it's listed when you do ceedling files:include
... but the compiler isn't seeing it when you want to compile, which is strange. All the include paths should be getting added to the command line for the compiler.
if you run ceedling verbosity[4] test:all
and then scroll up to look at the compilation call for the failing line, is there a -I
to include /usr/include/x86_64-linux-gnu/sys/
?
None of the compile messages have a -I for the included file.
Test 'test_can.c'
-----------------
> Shell executed command:
'gcc -E -MM -MG -I"/var/lib/gems/2.7.0/gems/ceedling-0.31.1/vendor/unity/src" -I"/var/lib/gems/2.7.0/gems/ceedling-0.31.1/vendor/cmock/src" -I"build/test/mocks" -I"test" -I"test/comms" -I"test/test_utilities" -I"test/support" -I"test/support" -I"src" -I"src/comms" -I"src/utilities" -I"include" -I"include/comms" -I"include/utilities" -DCEEDLING_TESTS -DCEEDLING_TESTS -DGNU_COMPILER "build/temp/_test_can.c"'
> Produced output:
_test_can.o: build/temp/_test_can.c \
/var/lib/gems/2.7.0/gems/ceedling-0.31.1/vendor/unity/src/unity.h \
/var/lib/gems/2.7.0/gems/ceedling-0.31.1/vendor/unity/src/unity_internals.h \
@@@@unity.h include/comms/evcc_can.h include/utilities/logger.h \
@@@@evcc_can.h @@@@logger.h mock_libsocketcan.h @@@@mock_libsocketcan.h \
mock_socket.h @@@@mock_socket.h
Generating include list for libsocketcan.h...
> Shell executed command:
'gcc -E -MM -MG -I"/var/lib/gems/2.7.0/gems/ceedling-0.31.1/vendor/unity/src" -I"/var/lib/gems/2.7.0/gems/ceedling-0.31.1/vendor/cmock/src" -I"build/test/mocks" -I"test" -I"test/comms" -I"test/test_utilities" -I"test/support" -I"test/support" -I"src" -I"src/comms" -I"src/utilities" -I"include" -I"include/comms" -I"include/utilities" -DCEEDLING_TESTS -DCEEDLING_TESTS -DGNU_COMPILER "build/temp/_libsocketcan.h"'
> Produced output:
_libsocketcan.o: build/temp/_libsocketcan.h @@@@linux/can/netlink.h
> Shell executed command:
'gcc -E -I"/var/lib/gems/2.7.0/gems/ceedling-0.31.1/vendor/unity/src" -I"/var/lib/gems/2.7.0/gems/ceedling-0.31.1/vendor/cmock/src" -I"build/test/mocks" -I"test" -I"test/comms" -I"test/test_utilities" -I"test/support" -I"test/support" -I"src" -I"src/comms" -I"src/utilities" -I"include" -I"include/comms" -I"include/utilities" -DCEEDLING_TESTS -DCEEDLING_TESTS -DGNU_COMPILER "/usr/include/libsocketcan.h" -o "build/test/preprocess/files/libsocketcan.h"'
Generating include list for socket.h...
> Shell executed command:
'gcc -E -MM -MG -I"/var/lib/gems/2.7.0/gems/ceedling-0.31.1/vendor/unity/src" -I"/var/lib/gems/2.7.0/gems/ceedling-0.31.1/vendor/cmock/src" -I"build/test/mocks" -I"test" -I"test/comms" -I"test/test_utilities" -I"test/support" -I"test/support" -I"src" -I"src/comms" -I"src/utilities" -I"include" -I"include/comms" -I"include/utilities" -DCEEDLING_TESTS -DCEEDLING_TESTS -DGNU_COMPILER "build/temp/_socket.h"'
> Produced output:
_socket.o: build/temp/_socket.h @@@@features.h \
@@@@bits/types/struct_iovec.h @@@@stddef.h @@@@bits/socket.h
> Shell executed command:
'gcc -E -I"/var/lib/gems/2.7.0/gems/ceedling-0.31.1/vendor/unity/src" -I"/var/lib/gems/2.7.0/gems/ceedling-0.31.1/vendor/cmock/src" -I"build/test/mocks" -I"test" -I"test/comms" -I"test/test_utilities" -I"test/support" -I"test/support" -I"src" -I"src/comms" -I"src/utilities" -I"include" -I"include/comms" -I"include/utilities" -DCEEDLING_TESTS -DCEEDLING_TESTS -DGNU_COMPILER "/usr/include/x86_64-linux-gnu/sys/socket.h" -o "build/test/preprocess/files/socket.h"'
Creating mock for libsocketcan...
Creating mock for socket...
In file included from test/comms/test_can.c:6:
build/test/mocks/mock_socket.h:6:10: fatal error: socket.h: No such file or directory
6 | #include "socket.h"
| ^~~~~~~~~~
compilation terminated.
ERROR: Shell command failed.
> Shell executed command:
'gcc -E -I"/var/lib/gems/2.7.0/gems/ceedling-0.31.1/vendor/unity/src" -I"/var/lib/gems/2.7.0/gems/ceedling-0.31.1/vendor/cmock/src" -I"build/test/mocks" -I"test" -I"test/comms" -I"test/test_utilities" -I"test/support" -I"test/support" -I"src" -I"src/comms" -I"src/utilities" -I"include" -I"include/comms" -I"include/utilities" -DCEEDLING_TESTS -DCEEDLING_TESTS -DGNU_COMPILER "test/comms/test_can.c" -o "build/test/preprocess/files/test_can.c"'
> And exited with status: [1].
Ah. Yeah, a file directly added is not an include. Compilers don't accept that. Instead let's work on the path then. Let's try adding the path directly to the include list (no fancy globs, just a straight path):
:test:
- +:test/**
:source:
- src/**
:support:
- test/support
:include:
- include/**
- /usr/include/sys/
I changed it a bit to give me the folder socket.h is in.
:paths:
:test:
- +:test/**
:source:
- src/**
:support:
- test/support
:include:
- include/**
- /usr/include/x86_64-linux-gnu/sys/
New errors about nesting too deeply
:files:
:include:
- +:/usr/include/libsocketcan.h
- +:/usr/include/x86_64-linux-gnu/sys/socket.h
I hope this can be done correctly. If not I am ok to copy the necessary header files into test/support
as this does solve the issue.
What the what?
Do those files actually include themselves repeatedly as the compiler seems to believe they do?
My file logger.c includes logger.h which includes errno and stdio.
Does unistd.h
include unistd.h
as the error suggests? Does errno.h
include errno.h
?
unistd.h has
/* Define some macros helping to catch buffer overflows. */
#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
# include <bits/unistd.h>
#endif
/* System-specific extensions. */
#include <bits/unistd_ext.h>
stdio.h includes
#ifdef __USE_EXTERN_INLINES
# include <bits/stdio.h>
#endif
#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
# include <bits/stdio2.h>
#endif
It seems to stop there.
Not sure what is happening. My co-worker had a good idea for our Jenkins server. Before running ceedling we run a script that copies the needed header files into a known folder. This will likely be in test/support
. The Jenkins workspace is wiped on every pipeline run. This should save us from library updates while keeping out project.yml
simple. It is a workaround and not a fix, but this will be more time efficient for our team!
Thank you for all of your help, I hope you are able to make changes based on this conversation. Feel free to close this if you feel it is no longer an issue.
I have copied what I think are all the necessary header files into my project test support folder. I have tried to replicate the Linux code structure in usr/include
.
I am not told
Compiling test_can_runner.c...
In file included from build/test/mocks/mock_if.h:6,
from build/test/runners/test_can_runner.c:13:
test/support/usr/include/net/if.h:90:21: error: field ‘ifa_addr’ has incomplete type
90 | struct sockaddr ifa_addr; /* Address of interface. */
Is there an easy solution for this? I have nothing special in my project at this point. Would it be possible to share it?
Hello,
My ceedling tests run and pass using GCC and what I would call the default project.yml file. I am trying to get my tests running with an external toolset which is generated from a Yocto build.
Every test in my project now fails giving the error
To build my project I have to run source to setup the environment.
source /opt/fsl-imx-fb/5.10-hardknott/environment-setup-cortexa7t2hf-neon-poky-linux-gnueabi
I then open eclipse and am able to build/deploy my application. I am attempting to follow the same steps in my project.yml file (attached). When eclipse builds my application it builds and links as follows.
My tests compile and link but never successfully run. It seems the error is related to how the code is linked. Can anyone see an issue? project.txt