-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a test with a cpp executable including all mbed TLS headers #1454
Add a test with a cpp executable including all mbed TLS headers #1454
Conversation
And we've got a winner:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should build the C++ program by default. Other than that, looks good.
programs/Makefile
Outdated
@@ -67,6 +69,7 @@ APPS = aes/aescrypt2$(EXEXT) aes/crypt_and_hash$(EXEXT) \ | |||
random/gen_random_ctr_drbg$(EXEXT) \ | |||
test/ssl_cert_test$(EXEXT) test/benchmark$(EXEXT) \ | |||
test/selftest$(EXEXT) test/udp_proxy$(EXEXT) \ | |||
test/header_test$(EXEXT) \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should build this program by default. People who only have a C compiler and no C++ compiler, or who've set CC
but not CXX
, should be able to run make
.
This applies to other build systems as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
programs/test/header_test.cpp
Outdated
#else | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#define mbedtls_printf printf |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why bother with these definitions here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wanted to keep the same include format as in the other mbed TLS files, but I guess it's not necessary here for now. Removed it.
This feature can be enabled by either:
|
programs/test/header_test.cpp
Outdated
int main( int argc, char *argv[] ) | ||
{ | ||
(void) argc; | ||
(void) argv; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing return
in a non void function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In C++, that's allowed in main
, by special dispensation. main
has an implicit return 0
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have no objections, just one minor remark.
programs/test/header_test.cpp
Outdated
|
||
int main( int argc, char *argv[] ) | ||
{ | ||
(void) argc; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
C standard allows main to take no arguments, which seems to be exactly what is needed here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good tip, done.
programs/test/header_test.cpp
Outdated
#include "mbedtls/timing.h" | ||
#include "mbedtls/x509.h" | ||
|
||
#if defined(MBEDTLS_PLATFORM_C) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checking MEBDTLS_x_C
should be done for all modules. Or if we always build this test with full config then why check here. For any reason if implementation for a header is missing, stubs can be provided in this test completeness sake.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can include any header file in any configuration, it's up to each header file to exclude things that shouldn't be included in a given configuration. MBEDTLS_PLATFORM_C
is special in that regard.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file was intended for our CI and mainly for the cmake build, but I left a possibility for people to test their configuration with the most common exclusions - custom config.h and custom platform macros. Do you think that I should change this code, if so - how?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And - are you concerned about Including all headers despite having a smaller configuration? There are no guards in the headers anyway, .c files have ifdef guards.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I known that the guards are in C files. My question was why guard platform.h
unlike others.
programs/Makefile
Outdated
@@ -241,6 +247,10 @@ test/benchmark$(EXEXT): test/benchmark.c $(DEP) | |||
echo " CC test/benchmark.c" | |||
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/benchmark.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ | |||
|
|||
test/header_test$(EXEXT): test/header_test.cpp $(DEP) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To make this test self sufficient perhaps execute config.pl with full config.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, but that's up to test scripts such as all.sh
, not the job of the build scripts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean by self sufficient?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My idea was to have a make target that indicates whether the headers are compatible with C++. But general consensus here is do the config outside Makefile. Hence ignore this.
programs/Makefile
Outdated
@@ -76,6 +78,10 @@ ifdef PTHREAD | |||
APPS += ssl/ssl_pthread_server$(EXEXT) | |||
endif | |||
|
|||
ifdef TEST_CPP | |||
APPS += test/header_test$(EXEXT) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this test tests C++ compatibility of the headers with full config. It is different from other tests/programs that all build with one valid config. Please check if a full config is valid for other programs.
If not I would rather make it mutually exclusive with all other programs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This tests headers with any config - there are usually no ifdef guards in headers, hence nothing really should change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In all.sh
we should enable the full config and build this. The actual Makefile
should just take the configs it's given.
Note this fix relates to existing bug #477 (IOTSSL-761), which should be closed when we merge this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the efforts @AndrzejKurek. If you could respond to my review feedback before I approve I'd be grateful.
programs/.gitignore
Outdated
@@ -45,6 +45,7 @@ ssl/mini_client | |||
test/benchmark | |||
test/ecp-bench | |||
test/selftest | |||
test/header_test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think header_test
really conveys what we want to do here. Can we call it something like cpp_dummy_build
? Or at least something that says it's a C++ test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done - renamed to cpp_dummy_build.
programs/Makefile
Outdated
@@ -76,6 +78,10 @@ ifdef PTHREAD | |||
APPS += ssl/ssl_pthread_server$(EXEXT) | |||
endif | |||
|
|||
ifdef TEST_CPP | |||
APPS += test/header_test$(EXEXT) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In all.sh
we should enable the full config and build this. The actual Makefile
should just take the configs it's given.
programs/test/header_test.cpp
Outdated
/* | ||
* A C++ program that includes all of the mbed TLS header files, in order to | ||
* test if no errors are raised in the process. | ||
* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than say we want to check we build without errors...
/*
* A C++ program that includes all of the mbed TLS header files, in order to
* test if no errors are raised in the process.
I'd like to state the purpose more clearly, so I'd propose:
/*
* This program is a dummy C++ program to ensure Mbed TLS library header files
* can be included and built with a C++ compiler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, updated as suggested.
programs/test/header_test.cpp
Outdated
#include "mbedtls/memory_buffer_alloc.h" | ||
#endif | ||
|
||
int main( int argc, char *argv[] ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok - this is probably a naive question, but is this adequate? Shouldn't we want to check it links with a token function?
Mbed TLS works with C++ by compiling in C (not C++) as a C library, which the C++ linker can then resolve without the usual name mangling. As a build test, we're only confirming the preprocessor and compiler work - not the linker.
Can I propose we should call mbedlts_platform_setup()
and then mbedtls_printf("CPP Build test\n")
as a simple sanity test? (And the mbedtls_platform_teardown()
for completeness).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we want to check this properly, we need to link with every function in the library. This would detect a missing extern "C"
somewhere.
This means the .cpp
source file would have to be automatically generated, which requires a rather different approach.
Automatically generating the source file would have the advantage that the list of headers would also be automatically generated. With a static file, we have to remember to add new headers. Fortunately this doesn't happen often. Still, we should add a check script (or code in an existing script) to verify that all the headers are included.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think trying to link every API function and/or a script to confirm every module is included is too much work for the moment, and a distraction from other issues. Feel free to raise those as issues if you want for the future.
However, I think we can link to a couple of files as I suggest above at little extra cost, and at least that would confirm the linker is working for something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a basic set of calls as suggested.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All my comments are answered. Approving.
@gilles-peskine-arm - can you please approve, and then mark as 'ready for merge' as you see appropriate? |
Sorry for marking as ready for merge - I thought that 2 approvals are enough for that. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's there is good. But there's no Visual Studio project. Please add one or justify why it isn't needed.
@gilles-peskine-arm |
Re-adding "needs review" + "needs work" as there is one "change requested" review. |
@AndrzejKurek - Looks like there's a small amount of rework and then we're good. Could you please look at this please? If you don't have access to Visual Studio, please let me know and we'll do something else. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, however I'll hold the approval until the PR is rebased (and re-reviewed), or until it's decided the rebase is not necessary.
tests/scripts/all.sh
Outdated
if [ $TEST_CXX -ne 0 ]; then | ||
msg "build: Unix make, gcc and g++ test" # ~ 30s | ||
cleanup | ||
make TEST_CPP=1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason for this being CPP
rather than CXX
like elsewhere? It's far from being a blocker, but it is possible to make it consistent, I'd take the opportunity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, CPP is the C preprocessor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I can change it, I just used it as an abbreviation of C++ (as in cppreference, not cxxreference).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update - Removed the flag alltogether.
tests/scripts/all.sh
Outdated
|
||
msg "build: cmake, gcc and g++ test" # ~ 30s | ||
cleanup | ||
CC=gcc cmake -D TEST_CPP=YES . |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why test with both make and cmake? We run some tests with each to validate our build system. But here we're just building a program which has no purpose other than validating that it can be built. Any build system would do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I opted for a larger coverage of build systems, just in case someone forces the CXX compiler for cmake to something not working.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update - Removed the cmake test.
tests/scripts/all.sh
Outdated
|
||
msg "build: cmake, gcc and g++ test" # ~ 30s | ||
cleanup | ||
CC=gcc cmake -D TEST_CPP=YES . |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does CC=gcc
influence the C++ compiler? Seems strange to me, I'd expect the C++ compiler to be ${CXX}
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does not, It's just the usual syntax used for other tests in all.sh, and I thought it's a prerequisite to compile the usual sources (which are getting compiled during this test too).
Just a general note on this PR: when it is merge, there should be an announcement on the relevant channels so that all developers know that from now on, every time you create a new module, you also new to add it's header to the C++ testing file. |
In case of any problems with the 'extern "C"' directives, building the executable will fail
Remove unnecessary defines from the test. Test by defining TEST_CPP using makefiles or cmake.
Change the name of header_test to cpp_dumy_build Update the test description to better reflect its contents
Remove the cmake test
2a4a106
to
05be06c
Compare
I have rebased this PR, incorporated all of the comments, thus making the cpp test mandatory in all.sh (with no flag for removal), removed the cmake test in all.sh. |
tests/scripts/all.sh
Outdated
@@ -580,6 +581,10 @@ msg "test/build: key-exchanges (gcc)" # ~ 1 min | |||
cleanup | |||
record_status tests/scripts/key-exchanges.pl | |||
|
|||
msg "build: Unix make, gcc and g++ test" # ~ 30s | |||
cleanup | |||
make TEST_CPP=1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we merge this with an existing build?
Advantage: faster.
Downside: slightly less good reports if it fails since we'd have to look closer at the logs to see if it's the fault of the C++. But this is all.sh
anyway, we don't.
I'm not suggesting to add TEST_CPP=1
to an existing command line, that would make it harder to backport this script. Rather, add this after an existing make
, before a subsequent cleanup
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So you'd like to have the following code below:
msg "build: Unix make, -Os (gcc)" # ~ 30s
cleanup
make CC=gcc CFLAGS='-Werror -Wall -Wextra -Os'
+make TEST_CPP=1
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's fine with me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated, with additional logs to make things clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a faithful rebase of my previous approval, plus almost-sorting the list of headers, plus an entry in all.sh
. I have some reservations, but I'm willing to approve in a pinch.
programs/test/cpp_dummy_build.cpp
Outdated
#include "mbedtls/md2.h" | ||
#include "mbedtls/md4.h" | ||
#include "mbedtls/md5.h" | ||
#include "mbedtls/md.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for sorting this list, but I'd prefer if it was sorted in binary order, rather than in some locale where punctuation is not sorted or sorted in a second pass and in a non-ASCII order (md.h
should come before md2.h
, ssl.h
should come before ssl_anything.h
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's the order reported by ls when using en_US.UTF-8. Could you suggest any other locale that would yield results that you've mentioned and could be considered more "default"? I'm curious, because that's what it would boil down to - checking it by hand, if not running the lengthy all-sh.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use the C
locale for universally reproducible results.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
tests/scripts/all.sh
Outdated
msg "build: Unix make, gcc and g++ test" # ~ 30s | ||
cleanup | ||
make TEST_CPP=1 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to add a check that cpp_dummy_build.cpp
lists all the headers except for whitelisted ones.
check_headers_in_cpp () {
ls include/mbedtls >headers.txt
<programs/test/cpp_dummy_build.cpp sed -n 's/"$//; s!^#include "mbedtls/!!p' |
sort |
diff headers.txt -
rm headers.txt
}
record_status check_headers_in_cpp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will there be any whitelisted ones? Currently, this fails only because check-config.h is not included there (there's no need to test it since it does not have any extern directives), but there's no problem in adding it there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check_config.h
is the only whitelisted one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a check, included the check-config.h in the dummy build file.
change the g++ test to be incremental, to save time reorganize header order in cpp_dummy_build.cpp according to c locale
@gilles-peskine-arm, @k-stachowiak, @mazimkhan - Could I kindly ask for your re-review? |
@@ -77,6 +79,10 @@ ifdef PTHREAD | |||
APPS += ssl/ssl_pthread_server$(EXEXT) | |||
endif | |||
|
|||
ifdef TEST_CPP | |||
APPS += test/cpp_dummy_build$(EXEXT) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you run make TEST_CPP=1
and later make clean
, then test/cpp_dummy_build
doesn't get cleaned. There's a similar preexisting defect with ssl/ssl_pthread_server
. The defect with test/cpp_dummy_build
is worse because we include it in our test scripts.
I won't block the PR for that, but please, in order of preference, either:
- arrange for
make clean
to removetest/cpp_dummy_build
(andssl/ssl_pthread_server
) regardless of the value ofTEST_CPP
; - or file an issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AndrzejKurek is out for a couple of weeks, so I've raised this as issue #1862, so we can at least merge what we have, and fix this later, as it's a minor issue,
CircleCI is failing, but that can be disregarded. |
Related to #1426 - in order to avoid such mistakes in the future, a test with all the mbed TLS headers included during a c++ executable building is added.
Internal ref: IOTSSL-2172