dextool

Suite of C/C++ tooling built on LLVM/Clang

View project on GitHub

Embedded Systems

It can be a bit tricky to use mutation testing for embedded systems. The most common problem is that the test framework that is used is a simple, custom made framework. Dextool allow you, as the user, to write your own analyser of the test suites output without changing dextool or the test framework.

There is an additional feature enabled when using this and that is the unstable signal. A test suite that is executed on developer breadboards can have intermitten problems such as the JTAG-probe glitching, the breadboard failed to power up, the test suite deadlock the breadboard etc. See the documentation further down for how to use unstable.

Note that you probably want to turn schemata off if the way that the tests are executed do not pass on the environment variable DEXTOOL_MUTID to the tests.

Custom Test Analyzer

Dextool need some help to understand the output from the test suite.

To be able to find test cases that kill zero mutants, detect new test cases and dropped test cases it needs to find all these test cases at the beginning when it is measuring the performance of the test suite. This is why the passed: is important.

To be able to map which test case killed which mutant it needs help finding the test cases that failed when the mutant where injected. This is where the failed: part comes in.

To be able to test a mutant again because the test suite is unstable when it is executed on the injected mutant it needs some help. This is signaled from the analyzer by writing unstable: to stdout.

The requirement on the script is that it should parse the files that contains the output from the test suite. These are passed as argument one and two to the script.

The analyzer should write to stdout with the following pattern for each test case:

  • passed test: passed:<name of test>
  • failed test: failed:<name of test>
  • unstable test: unstable:<name of test>

One line per test case.

Assume we have a test framework that generates results to stdout.

Execute some tests and copy the stdout result to a file named stdout.txt.

Example:

# Processing test cases.
(Passed) OnePlusOne
(Failed) TwoPlusTwo
test.c:6: Fail
      Expected: Add(2, 2)
      Which is: 4
To be equal to: 5
(Passed) TestStuff
# 3 tests processed. Summary:
# PASSED: 2
# FAILED: 1

Create a file test_analyze.sh that will identify passed and a failing test from stdout/stderr:

#!/bin/bash
# The arguments are paths to stdout ($1) and stderr ($2).
# This script assumes that nothing is in stderr.

# Using a more complex while loop to avoid side effects such as trimming leading
# whitespace, interpreting backslash sequences, and skipping the trailing line
# if it's missing a terminating linefeed. If these are concerns, you can do:
while IFS="" read -r L || [ -n "$L" ]; do
    echo "$L"|grep -h "(Failed)" > /dev/null
    if [[ $? -eq 0  ]]; then
        echo "failed:"$(echo "$L"|sed -e 's/(Failed)//')
    fi
    echo "$L"|grep -h "(Passed)" > /dev/null
    if [[ $? -eq 0  ]]; then
        echo "passed:"$(echo "$L"|sed -e 's/(Passed)//')
    fi
done < $1

Don’t forget to make it executable:

chmod 755 test_analyze.sh

Check that the script works on your example:

touch stderr.txt
./test_analyze.sh stdout.txt stderr.txt
passed: OnePlusOne
failed: TwoPlusTwo
passed: TestStuff

And configure dextool to use it. Either via CLI (--test-case-analyze-cmd) or config:

analyze_cmd = "test_analyze.sh"