Tests and Coverage - AboudyKreidieh/truck-code GitHub Wiki
This page details unit and integration test coverage within the truck-code
computational framework. Unit and integration testing within the framework is conducted using Boost.Test Framework, a popular tool for unit testing among C++ developers. This tool supports the inclusion of various types of assertions to check and match the expected and actual outputs of various methods. In addition, upon completion, the Boost Test framework provides a clear output log depicting which and whether any tests failed and what the specific failure was the result of (as seen in this section).
The remainder of this page is organized as follows. In the first section, we discuss how necessary packages such as Boost can be installed and integrated into the framework to support testing. The, in the second section, we discuss how tests are and can be added to support the integration of new features. In the third section, we explain how unit tests can be run on QNX-compatible devices to ensure that the framework is running correctly. Finally, in the last section we specify have the unit test coverage of the variable features and scripts can be analyzed to identify and account for potential vulnerabilities within the system.
Before you begin writing new tests or compiling old ones, you will need to install a version of Boost that is compatible with QNX 7.0. The procedure for doing so comes courtesy of https://github.com/bonewell/franca-capi-someip-sample/wiki/Build-for-QNX-7.0.
First of all, begin by downloading Boost 1.55.0 from the following link. Once you have done so, install Boost's header files and static libraries by running the following commands:
Note: Be sure to modify </path/to/truck-code>
to match your actual path.
tar -xvf boost_1_55_0.tar.gz
cd boost_1_55_0
patch -p1 < </path/to/truck-code>/boost.patch
./bootstrap.sh
./b2 install link=static toolset=qcc cxxflags="-Vgcc_ntox86_64" target-os=qnxnto --prefix=</path/to/truck-code>/thirdparty/boost
The include paths and created static objects will now be located in </path/to/truck-code>/thirdparty/boost
under include
and libs
, respectively.
Unit tests within the framework are written periodically to support new software features. As mentioned in the previous section, this is done using the Boost.Test Framework. A typical unit test, by definition, is designed to cover a single unit of code, consisting of either a few lines of code within the codebase or a single method. These tests can be found in blank
. Integration tests, on the other hand, validate the functionality of several objects and methods once they are being run in unison to support the implementation of a single of multiple binaries and/or processes. These tests can be found in blank
.
A typical unit test within the two aforementioned folders of the form depicted below:
#define BOOST_TEST_MODULE "ModuleName"
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_SUITE( TestsName )
BOOST_AUTO_TEST_CASE( test_name )
{
// INSERT CODE HERE
}
BOOST_AUTO_TEST_SUITE_END()
The BOOST_AUTO_TEST_SUITE
macro prepares the initialization of a process named ModuleName that is responsible for executing several tests. The individual tests, named test_name, are then each placed under a separate BOOST_AUTO_TEST_CASE
function. These individual unit tests can then take advantage of the various macros Boost.Test supports for validation and assertion purposes. Popular macros include:
-
BOOST_CHECK(val)
: Asserts thatval
is True, returns a generic error message otherwise. Continues on error. -
BOOST_REQUIRE(val)
: Asserts thatval
is True, returns a generic error message otherwise. Throws on error. -
BOOST_ERROR("...")
: Returns an error with the string error message defined as input. Continues on error. -
BOOST_FAIL("...")
: Returns an error with the string error message defined as input. Throws on error. -
BOOST_CHECK_MESSAGE(val, "...")
: Asserts thatval
is True, and returns the specific message otherwise. Continues on error. -
BOOST_CHECK_EQUAL(val1, val2)
: Asserts that two values match, and if they don't, returns a generic error message. Continues on error.
As an example, take the code snippet below. This snippet is derived from a test conducted on the PDUInterpreter::print
method (see implementation in include/jbus/j1939_interpreters.cpp
). The test begins by creating a simple test object with predefined variables. It then runs the import
method (the purpose of the test), and uses the test_import
method (see implementation in codebase) to assert the the predefined inputs match the expected outputs. This is done using the BOOST_CHECK
macro. Finally, all variables that were created by the unit test are promptly deleted and data is freed.
BOOST_AUTO_TEST_SUITE( test_PDUInterpreter )
BOOST_AUTO_TEST_CASE( test_print_pdu )
{
// initialize variables
FILE* fp;
vector<string> expected;
PDUInterpreter* interpreter = new PDUInterpreter();
j1939_pdu_typ* pdu = new j1939_pdu_typ();
pdu->timestamp.hour = 23;
pdu->timestamp.minute = 59;
pdu->timestamp.second = 59;
pdu->timestamp.millisecond = 999;
pdu->priority = 0;
pdu->pdu_format = 1;
pdu->pdu_specific = 2;
pdu->src_address = 3;
for (int i=0; i<8; ++i)
pdu->data_field[i] = 4+i;
pdu->num_bytes = 8;
// test the numeric case
fp = fopen("/tmp/test.txt", "w");
expected = {
"PDU 23:59:59.999 0 1 2 3 8 4 5 6 7 8 9 10 11"
};
interpreter->print((void*)pdu, fp, true);
fclose(fp);
BOOST_CHECK(check_import_match("/tmp/test.txt", expected));
// test the non-numeric case
fp = fopen("/tmp/test.txt", "w");
expected = {
"PDU 23:59:59.999",
" Priority 0",
" Protocol Data Unit Format (PF) 1",
" PDU Specific (PS) 2",
" Source Address 3",
" Number of bytes 8",
" Data Field 4 5 6 7 8 9 10 11"
};
interpreter->print((void*)pdu, fp, false);
fclose(fp);
BOOST_CHECK(check_import_match("/tmp/test.txt", expected));
// free memory
delete pdu;
delete interpreter;
}
BOOST_AUTO_TEST_SUITE_END()