diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index c8acffb2..6290c7a3 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -26,4 +26,7 @@ jobs: - run: sudo apt install -y cmake libssl-dev libcurl4-openssl-dev ${{ matrix.aptpkg }} # Building - run: ./run-make-from-ci.sh --compiler "${{ matrix.compiler }}" + # Test prerequisites + - run: sudo apt install -y gdb + # Testing - run: ./run-tests-from-ci.sh diff --git a/.github/workflows/testing_non_sse.yml b/.github/workflows/testing_non_sse.yml index 450f5d24..7c9e77ee 100644 --- a/.github/workflows/testing_non_sse.yml +++ b/.github/workflows/testing_non_sse.yml @@ -26,4 +26,7 @@ jobs: - run: sudo apt install -y cmake libssl-dev libcurl4-openssl-dev ${{ matrix.aptpkg }} # Building - run: ./run-make-from-ci.sh --compiler "${{ matrix.compiler }}" --extra-config "FMQ_NO_SSE=1" + # Test prerequisites + - run: sudo apt install -y gdb + # Testing - run: ./run-tests-from-ci.sh diff --git a/FlashMQTests/fmq-generate-core-file.py b/FlashMQTests/fmq-generate-core-file.py new file mode 100644 index 00000000..4bae697c --- /dev/null +++ b/FlashMQTests/fmq-generate-core-file.py @@ -0,0 +1,35 @@ +import time +import os + + +class FMQGenerateCoreFile(gdb.Command): + """Generate a corefile with a dynamic name instead of core.PID""" + + def __init__(self): + super().__init__("fmq-generate-core-file", gdb.COMMAND_USER) + + def invoke(self, arg, from_tty): + # Are in in[MainTests::testAsserts]? If yes don't do anything (this is testing the framework on bootup) + frame = gdb.selected_frame() + while frame: + # The name is a bit compiler dependent, I've seen: + # MainTests::testAsserts + # MainTests::testAsserts() + frame_name = frame.name() or '' + if frame_name.startswith("MainTests::testAsserts"): + return False + frame = frame.older() + + # This is something else + try: + runid = f".{os.environ['FMQ_RUN_ID']}." + except KeyError: + runid = "." + gdb.execute( + f"generate-core-file core{runid}{time.strftime('%Y-%d-%mT%H%M%S')}.{time.thread_time_ns()}" + ) + issues = gdb.convenience_variable('issues') or 0 + gdb.set_convenience_variable('issues', issues + 1) + + +FMQGenerateCoreFile() # this registers the CLI command diff --git a/FlashMQTests/main.cpp b/FlashMQTests/main.cpp index 9c73834f..52903caf 100644 --- a/FlashMQTests/main.cpp +++ b/FlashMQTests/main.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -9,8 +10,15 @@ void printHelp(const std::string &arg0) std::cout << "Usage: " << arg0 << " [ --skip-tests-with-internet ] [ --skip-server-tests ] " << " " << std::endl; } +void signal_noop(int signal) +{ + std::cout << "Signal NoOP (if you used save-core-on-sigvtalrm.gdb a core dump will now be created)" << std::endl; +} + int main(int argc, char *argv[]) { + std::signal(SIGVTALRM, signal_noop); + bool skip_tests_with_internet = false; bool skip_server_tests = false; std::vector tests; diff --git a/FlashMQTests/run-tests-from-ci.sh b/FlashMQTests/run-tests-from-ci.sh index 6ad2ceb6..6ed95b4a 100755 --- a/FlashMQTests/run-tests-from-ci.sh +++ b/FlashMQTests/run-tests-from-ci.sh @@ -2,13 +2,27 @@ STDERR_LOG=$(mktemp) + +export FMQ_RUN_ID=$EPOCHSECONDS # this is only granular to the second but that should be fine + cd buildtests || exit 1 -if ./flashmq-tests 2> "$STDERR_LOG" ; then +if gdb --batch -x ../fmq-generate-core-file.py -x ../save-core-on-sigvtalrm.gdb --args ./flashmq-tests 2> "$STDERR_LOG" ; then echo -e '\033[01;32mSUCCESS!\033[00m' else echo -e '\033[01;31mBummer\033[00m' echo -e "\n\nTail of stderr:\n\n" tail -n 200 "$STDERR_LOG" + + for i in "core.${FMQ_RUN_ID}."* + do + [[ "$i" == "core.${FMQ_RUN_ID}.*" ]] && break + echo "" + echo ",#############################################," + echo "| $i |" + echo "'#############################################'" + gdb --batch --ex "bt -full" "./flashmq-tests" "$i" + done + exit 1 fi diff --git a/FlashMQTests/save-core-on-sigvtalrm.gdb b/FlashMQTests/save-core-on-sigvtalrm.gdb new file mode 100644 index 00000000..fabdd152 --- /dev/null +++ b/FlashMQTests/save-core-on-sigvtalrm.gdb @@ -0,0 +1,16 @@ +# Less verbose gdb please +set print thread-events off +set print inferior-events off + +# fmq-generate-core-file will increase $issues when it dumps +set $issues = 0 + +catch signal SIGVTALRM +commands + fmq-generate-core-file + continue +end + +run + +exit $issues diff --git a/FlashMQTests/testhelpers.cpp b/FlashMQTests/testhelpers.cpp index 0edad193..97bf52d9 100644 --- a/FlashMQTests/testhelpers.cpp +++ b/FlashMQTests/testhelpers.cpp @@ -1,6 +1,7 @@ #include "testhelpers.h" #include +#include #include int assert_count; @@ -15,6 +16,8 @@ bool fmq_assert(bool b, const char *failmsg, const char *actual, const char *exp { assert_fail_count++; + raise(SIGVTALRM); // to create a corefile using GDB (if attached) + if (asserts_print) { // There are two types of failmsg: unformatted ones and formatted ones.