gcov: add in cmake and adapt defaults

1) Introduce LWS_WITH_GCOV to build with gcc / clang coverage instrumentation.

$ cd build
$ make clean && rm -f `find . -name "*.gcno" -o -name "*.gcda"` && make -j16 && sudo make install && sudo /usr/local/bin/libwebsockets-test-server -s
...
$ gcov `find . -name *.c.gcno | grep -v test-apps` -b | sed "/\.h.\$/,/^$/d"

The above are available in two helper scripts

 - scripts/build-gcov.sh
 - scripts/gcov.sh

2)

CMake defaults changed:

 - LWS_WITH_ZIP_FOPS: OFF
 - LWS_WITH_RANGES: OFF
 - LWS_WITHOUT_EXTENSIONS: ON
 - LWS_WITH_ZLIB: OFF

New CMake controls that default-OFF:

 - LWS_WITH_GENHASH
 - LWS_WITH_GENRSA

these are implied by LWS_WITH_JWS (which is implied by LWS_WITH_ACME)

3) rename ./lib/tls/XXX/server.c and client.c to XXX-server.c / XXX-client.c.

This is because gcov dumps its results using the .c filename part only,
the copies overwrite each other if there are different .c files in the tree
with the same filename part.

4) Add onetime test-client mode and test to ./test-apps/attack.sh

5) Add gcov howto in READMEs/README.build.md using attack.sh
This commit is contained in:
Andy Green 2017-11-14 11:25:54 +08:00
parent 516001db8a
commit 5b74d7108b
16 changed files with 106 additions and 57 deletions

View File

@ -22,6 +22,11 @@ os:
language: generic
install:
- ./scripts/travis_install.sh
# - ./travis-tool.sh github_package jimhester/covr
#after_success:
# - Rscript -e 'covr::coveralls()'
script:
- if [ "$COVERITY_SCAN_BRANCH" != 1 -a "$TRAVIS_OS_NAME" = "osx" ]; then mkdir build && cd build && cmake -DOPENSSL_ROOT_DIR="/usr/local/opt/openssl" $CMAKE_ARGS .. && cmake --build .; else if [ "$COVERITY_SCAN_BRANCH" != 1 -a "$TRAVIS_OS_NAME" = "linux" ]; then mkdir build && cd build && cmake $CMAKE_ARGS .. && cmake --build .; fi ; fi
sudo: required

View File

@ -20,12 +20,12 @@ option(LWS_IPV6 "Compile with support for ipv6" OFF)
option(LWS_UNIX_SOCK "Compile with support for UNIX domain socket" OFF)
option(LWS_WITH_PLUGINS "Support plugins for protocols and extensions" OFF)
option(LWS_WITH_HTTP_PROXY "Support for rewriting HTTP proxying (requires libhubbub)" OFF)
option(LWS_WITH_ZIP_FOPS "Support serving pre-zipped files" ON)
option(LWS_WITH_ZIP_FOPS "Support serving pre-zipped files" OFF)
option(LWS_WITH_SOCKS5 "Allow use of SOCKS5 proxy on client connections" OFF)
option(LWS_WITH_GENERIC_SESSIONS "With the Generic Sessions plugin" OFF)
option(LWS_WITH_PEER_LIMITS "Track peers and restrict resources a single peer can allocate" OFF)
option(LWS_WITH_ACCESS_LOG "Support generating Apache-compatible access logs" OFF)
option(LWS_WITH_RANGES "Support http ranges (RFC7233)" ON)
option(LWS_WITH_RANGES "Support http ranges (RFC7233)" OFF)
option(LWS_WITH_SERVER_STATUS "Support json + jscript server monitoring" OFF)
option(LWS_WITH_ACME "Enable support for ACME automatic cert acquisition + maintenance (letsencrypt etc)" OFF)
#
@ -71,8 +71,8 @@ option(LWS_WITHOUT_TEST_FRAGGLE "Don't build the ping test application" OFF)
#
# Extensions (permessage-deflate)
#
option(LWS_WITHOUT_EXTENSIONS "Don't compile with extensions" OFF)
option(LWS_WITH_ZLIB "Include zlib support (required for extensions)" ON)
option(LWS_WITHOUT_EXTENSIONS "Don't compile with extensions" ON)
option(LWS_WITH_ZLIB "Include zlib support (required for extensions)" OFF)
option(LWS_WITH_BUNDLED_ZLIB "Use bundled zlib version (Windows only)" ${LWS_WITH_BUNDLED_ZLIB_DEFAULT})
#
# Helpers + misc
@ -91,7 +91,10 @@ option(LWS_WITH_NO_LOGS "Disable all logging from being compiled in" OFF)
option(LWS_AVOID_SIGPIPE_IGN "Android 7+ reportedly needs this" OFF)
option(LWS_WITH_STATS "Keep statistics of lws internal operations" OFF)
option(LWS_WITH_JWS "JSON Web Signature (RFC7515) API" OFF)
option(LWS_WITH_GENHASH "Enable support for Generic Hash (SHA1 + SHA2 with api independent of TLS backend)" OFF)
option(LWS_WITH_GENRSA "Enable support for Generic RSA (RSA with api independent of TLS backend)" OFF)
option(LWS_WITH_SELFTESTS "Selftests run at context creation" OFF)
option(LWS_WITH_GCOV "Build with gcc gcov coverage instrumentation" OFF)
#
# End of user settings
#
@ -176,6 +179,8 @@ endif()
if (LWS_WITH_JWS)
set(LWS_WITH_LEJP 1)
set(LWS_WITH_GENHASH 1)
set(LWS_WITH_GENRSA 1)
endif()
if (LWS_WITH_PLUGINS AND NOT LWS_WITH_LIBUV)
@ -188,6 +193,12 @@ message(STATUS "LWS_WITH_SMTP --> Enabling LWS_WITH_LIBUV")
set(LWS_WITH_LIBUV 1)
endif()
if (LWS_WITH_PLUGINS OR LWS_WITH_CGI)
# sshd plugin
set(LWS_WITH_GENHASH 1)
set(LWS_WITH_GENRSA 1)
endif()
if (LWS_WITH_GENERIC_SESSIONS)
set(LWS_WITH_SQLITE3 1)
set(LWS_WITH_SMTP 1)
@ -271,10 +282,8 @@ if (NOT (LWS_WITH_STATIC OR LWS_WITH_SHARED))
message(FATAL_ERROR "Makes no sense to compile with neither static nor shared libraries.")
endif()
if (NOT LWS_WITHOUT_EXTENSIONS)
if (NOT LWS_WITH_ZLIB)
message(FATAL_ERROR "zlib is required for extensions.")
endif()
if (NOT LWS_WITHOUT_EXTENSIONS OR LWS_WITH_ZIP_FOPS)
set(LWS_WITH_ZLIB 1)
endif()
set(LWS_ZLIB_LIBRARIES CACHE PATH "Path to the zlib library")
@ -728,15 +737,31 @@ if (LWS_WITH_SSL)
if (LWS_WITH_MBEDTLS)
list(APPEND SOURCES
lib/tls/mbedtls/ssl.c
lib/tls/mbedtls/lws-genhash.c
lib/tls/mbedtls/lws-genrsa.c
)
if (LWS_WITH_GENHASH)
list(APPEND SOURCES
lib/tls/mbedtls/lws-genhash.c
)
endif()
if (LWS_WITH_GENRSA)
list(APPEND SOURCES
lib/tls/mbedtls/lws-genrsa.c
)
endif()
else()
list(APPEND SOURCES
lib/tls/openssl/ssl.c
lib/tls/openssl/lws-genhash.c
lib/tls/openssl/lws-genrsa.c
)
if (LWS_WITH_GENHASH)
list(APPEND SOURCES
lib/tls/openssl/lws-genhash.c
)
endif()
if (LWS_WITH_GENRSA)
list(APPEND SOURCES
lib/tls/openssl/lws-genrsa.c
)
endif()
endif()
if (NOT LWS_WITHOUT_SERVER)
@ -744,10 +769,10 @@ if (LWS_WITH_SSL)
lib/server/ssl-server.c)
if (LWS_WITH_MBEDTLS)
list(APPEND SOURCES
lib/tls/mbedtls/server.c)
lib/tls/mbedtls/mbedtls-server.c)
else()
list(APPEND SOURCES
lib/tls/openssl/server.c)
lib/tls/openssl/openssl-server.c)
endif()
endif()
if (NOT LWS_WITHOUT_CLIENT)
@ -755,10 +780,10 @@ if (LWS_WITH_SSL)
lib/client/ssl-client.c)
if (LWS_WITH_MBEDTLS)
list(APPEND SOURCES
lib/tls/mbedtls/client.c)
lib/tls/mbedtls/mbedtls-client.c)
else()
list(APPEND SOURCES
lib/tls/openssl/client.c)
lib/tls/openssl/openssl-client.c)
endif()
endif()
@ -908,10 +933,13 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_C_COMPILER_ID
if (LWS_HAVE_VISIBILITY)
set(VISIBILITY_FLAG -fvisibility=hidden)
endif()
if (LWS_WITH_GCOV)
set (GCOV_FLAGS "-fprofile-arcs -ftest-coverage -O0")
endif()
if ((UNIX OR LWS_WITH_ESP8266) AND NOT LWS_WITH_ESP32)
set(CMAKE_C_FLAGS "-Wall -Wsign-compare -Wignored-qualifiers -Wtype-limits -Wuninitialized -Werror ${VISIBILITY_FLAG} -Wundef ${CMAKE_C_FLAGS}" )
set(CMAKE_C_FLAGS "-Wall -Wsign-compare -Wignored-qualifiers -Wtype-limits -Wuninitialized -Werror ${VISIBILITY_FLAG} -Wundef ${GCOV_FLAGS} ${CMAKE_C_FLAGS}" )
else()
set(CMAKE_C_FLAGS "-Wall ${VISIBILITY_FLAG} ${CMAKE_C_FLAGS}" )
set(CMAKE_C_FLAGS "-Wall -Wsign-compare -Wignored-qualifiers -Wtype-limits -Wuninitialized -Werror ${VISIBILITY_FLAG} ${GCOV_FLAGS} ${CMAKE_C_FLAGS}" )
endif()
endif ()

View File

@ -431,14 +431,25 @@ Testing with h2spec (https://github.com/summerwind/h2spec)
$ h2spec -h 127.0.0.1 -p 7681 -t -k -v -o 1
```
At the time of writing, http/2 support is not fully complete; however all the
h2spec tests pass.
```
145 tests, 144 passed, 1 skipped, 0 failed
145 tests, 145 passed, 0 skipped, 0 failed
```
@section coverage Automated Coverage Testing
./test-apps/attack.sh contains scripted tests that are the basis
of the automated test coverage assessment available for gcc and clang.
To reproduce
$ cd build
$ cmake .. -DLWS_WITH_GCOV=1 -DCMAKE_BUILD_TYPE=DEBUG
$ ../scripts/build-gcov.sh
$ ../test-apps/attack.sh
$ ../scripts/gcov.sh
...
Lines executed:51.24% of 8279
@section windowsprebuilt Using Windows binary builds on Appveyor

View File

@ -148,6 +148,7 @@
#cmakedefine LWS_HAVE__STAT32I64
#cmakedefine LWS_WITH_JWS
#cmakedefine LWS_WITH_ACME
#cmakedefine LWS_WITH_SELFTESTS
/* OpenSSL various APIs */

View File

@ -28,7 +28,10 @@ build:
-DLWS_MBEDTLS_INCLUDE_DIRS="${IDF_PATH}/components/openssl/include;${IDF_PATH}/components/mbedtls/include;${IDF_PATH}/components/mbedtls/port/include" \
-DLWS_WITH_STATS=0 \
-DLWS_WITH_HTTP2=1 \
-DLWS_WITH_RANGES=1 \
-DLWS_WITH_ACME=1 \
-DLWS_WITH_ZLIB=1 \
-DLWS_WITH_ZIP_FOPS=1 \
-DZLIB_LIBRARY=$(BUILD_DIR_BASE)/zlib/libzlib.a \
-DZLIB_INCLUDE_DIR=$(COMPONENT_PATH)/../zlib \
-DLWS_WITH_ESP32=1 \

View File

@ -328,6 +328,7 @@ lws_tls_server_accept(struct lws *wsi)
return LWS_SSL_CAPABLE_ERROR;
}
#if defined(LWS_WITH_ACME)
/*
* mbedtls doesn't support SAN for cert creation. So we use a known-good
* tls-sni-01 cert from OpenSSL that worked on Let's Encrypt, and just replace
@ -620,4 +621,4 @@ fail:
return -1;
}
#endif
#endif

View File

@ -278,8 +278,9 @@ lws_ssl_SSL_CTX_destroy(struct lws_vhost *vhost)
if (!vhost->user_supplied_ssl_ctx && vhost->ssl_client_ctx)
SSL_CTX_free(vhost->ssl_client_ctx);
#if defined(LWS_WITH_ACME)
lws_tls_acme_sni_cert_destroy(vhost);
#endif
}
void

View File

@ -493,6 +493,7 @@ lws_tls_server_accept(struct lws *wsi)
return LWS_SSL_CAPABLE_ERROR;
}
#if defined(LWS_WITH_ACME)
static int
lws_tls_openssl_rsa_new_key(RSA **rsa, int bits)
{
@ -818,3 +819,4 @@ bail0:
return ret;
}
#endif

View File

@ -416,8 +416,9 @@ lws_ssl_SSL_CTX_destroy(struct lws_vhost *vhost)
if (!vhost->user_supplied_ssl_ctx && vhost->ssl_client_ctx)
SSL_CTX_free(vhost->ssl_client_ctx);
#if defined(LWS_WITH_ACME)
lws_tls_acme_sni_cert_destroy(vhost);
#endif
}
void

View File

@ -21,35 +21,6 @@
#include "private-libwebsockets.h"
int
lws_alloc_vfs_file(struct lws_context *context, const char *filename,
uint8_t **buf, lws_filepos_t *amount)
{
lws_filepos_t len;
lws_fop_flags_t flags = LWS_O_RDONLY;
lws_fop_fd_t fops_fd = lws_vfs_file_open(
lws_get_fops(context), filename, &flags);
int ret = 1;
if (!fops_fd)
return 1;
len = lws_vfs_get_length(fops_fd);
*buf = lws_malloc((size_t)len, "lws_alloc_vfs_file");
if (!*buf)
goto bail;
if (lws_vfs_file_read(fops_fd, amount, *buf, len))
goto bail;
ret = 0;
bail:
lws_vfs_file_close(&fops_fd);
return ret;
}
int
lws_ssl_anybody_has_buffered_read_tsi(struct lws_context *context, int tsi)
{

6
scripts/build-gcov.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/sh
cmake .. -DLWS_WITH_GCOV=1 && \
make clean && \
rm -f `find . -name "*.gcno" -o -name "*.gcda"` && \
make -j16 && sudo make install

3
scripts/gcov.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
gcov `find . -name *.c.gcno | grep -v test-apps` -b | sed "/\.h.\$/,/^$/d"

View File

@ -2,6 +2,8 @@
#
# attack the test server and try to make it fall over
#
# Requires the library to have been built with cmake .. -DCMAKE_BUILD_TYPE=DEBUG
SERVER=127.0.0.1
PORT=7681
LOG=/tmp/lwslog
@ -777,6 +779,16 @@ echo
echo "--- survived OK ---"
kill -2 $CPID
# coverage...
# run the test client against mirror for one period and exit
libwebsockets-test-server -s 2>> $LOG &
CPID=$!
libwebsockets-test-client 127.0.0.1 -s -O
curl -v -F text=hello -F send=SEND -F upload=@../README.md https://127.0.0.1:7681/formtest -k
kill -2 $CPID
exit 0

View File

@ -43,7 +43,7 @@ struct lws_poly_gen {
#define block_size (3 * 4096)
static int deny_deflate, longlived, mirror_lifetime, test_post;
static int deny_deflate, longlived, mirror_lifetime, test_post, once;
static struct lws *wsi_dumb, *wsi_mirror;
static struct lws *wsi_multi[3];
static volatile int force_exit;
@ -360,7 +360,7 @@ callback_lws_mirror(struct lws *wsi, enum lws_callback_reasons reason,
"rxb %d, rx_count %d\n", mirror_lifetime, rxb,
rx_count);
wsi_mirror = NULL;
if (flag_echo)
if (flag_echo || once)
force_exit = 1;
break;
@ -536,6 +536,7 @@ static struct option options[] = {
{ "justmirror", no_argument, NULL, 'j' },
{ "longlived", no_argument, NULL, 'l' },
{ "post", no_argument, NULL, 'o' },
{ "once", no_argument, NULL, 'O' },
{ "pingpong-secs", required_argument, NULL, 'P' },
{ "ssl-cert", required_argument, NULL, 'C' },
{ "ssl-key", required_argument, NULL, 'K' },
@ -584,7 +585,7 @@ int main(int argc, char **argv)
goto usage;
while (n >= 0) {
n = getopt_long(argc, argv, "Sjnuv:hsp:d:lC:K:A:P:moe", options,
n = getopt_long(argc, argv, "Sjnuv:hsp:d:lC:K:A:P:moeO", options,
NULL);
if (n < 0)
continue;
@ -628,6 +629,9 @@ int main(int argc, char **argv)
case 'o':
test_post = 1;
break;
case 'O':
once = 1;
break;
case 'n':
flag_no_mirror_traffic = 1;
lwsl_notice("Disabled sending mirror data (for pingpong testing)\n");