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/run-make-from-ci.sh b/FlashMQTests/run-make-from-ci.sh index a1b3b062..0e40d801 100755 --- a/FlashMQTests/run-make-from-ci.sh +++ b/FlashMQTests/run-make-from-ci.sh @@ -1,6 +1,6 @@ #!/bin/bash -extra_configs=() +extra_configs=("CMAKE_BUILD_TYPE=Debug") compiler="g++" while [ -n "$*" ]; do diff --git a/FlashMQTests/run-tests-from-ci.sh b/FlashMQTests/run-tests-from-ci.sh index 6ad2ceb6..14baaaf9 100755 --- a/FlashMQTests/run-tests-from-ci.sh +++ b/FlashMQTests/run-tests-from-ci.sh @@ -4,7 +4,7 @@ STDERR_LOG=$(mktemp) cd buildtests || exit 1 -if ./flashmq-tests 2> "$STDERR_LOG" ; then +if gdb --batch -x ../show-frames-on-hook.pdb.py --args ./flashmq-tests 2> "$STDERR_LOG" ; then echo -e '\033[01;32mSUCCESS!\033[00m' else echo -e '\033[01;31mBummer\033[00m' diff --git a/FlashMQTests/show-frames-on-hook.pdb.py b/FlashMQTests/show-frames-on-hook.pdb.py new file mode 100644 index 00000000..bd57c952 --- /dev/null +++ b/FlashMQTests/show-frames-on-hook.pdb.py @@ -0,0 +1,57 @@ +# NB: the gdb object is given to us by gdb, we don't need to import it + +# Making gdb a bit quieter +gdb.execute("set print thread-events off") +gdb.execute("set print inferior-events off") + +# since our class runs in a separate thread and has different variables we'll +# need to store $issues inside GDB itself +gdb.execute("set $issues = 0") + +class ShowFrames(gdb.Breakpoint): + def stop(self): + # 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() + if frame.name().startswith("MainTests::testAsserts"): + return False + frame = frame.older() + + # This is a real assert triggering + gdb.execute("set $issues += 1") + + frame = gdb.selected_frame() + + indentation = "" + while frame: + print(f"{indentation}- [{frame.name()}]") + indentation += " " + + try: + block = frame.block() + except: + # doc: If the frame does not have a block – for example, if there is no debugging information for the code in question – then this will throw an exception. + pass + else: + for variable in block: + print(f"{indentation}{variable.print_name} = ", end='') + if variable.print_name in ['maintests']: + print("(skipped)") + else: + try: + print(f"{variable.value(frame)} ({variable.type})") + except Exception as e: + print(f"({e})") + if frame.name().startswith('MainTests::'): + # if we go further up we'll end up in test runner's code, not too interesting + break + frame = frame.older() + + return False + +ShowFrames("trigger_gdb_if_attached") +gdb.execute("run") +gdb.execute("quit $issues") diff --git a/FlashMQTests/testhelpers.cpp b/FlashMQTests/testhelpers.cpp index 0edad193..371d4566 100644 --- a/FlashMQTests/testhelpers.cpp +++ b/FlashMQTests/testhelpers.cpp @@ -7,12 +7,20 @@ int assert_count; int assert_fail_count; bool asserts_print; +void trigger_gdb_if_attached() +{ + // separate function to make it easier to hook into from gdb. + // if you don't have gdb attached this is a noop. +} + bool fmq_assert(bool b, const char *failmsg, const char *actual, const char *expected, const char *file, int line) { assert_count++; if (!b) { + trigger_gdb_if_attached(); + assert_fail_count++; if (asserts_print)