Skip to content
This repository has been archived by the owner on Jul 22, 2020. It is now read-only.

serial.tutorial

Klemens David Morgenstern edited this page May 6, 2018 · 1 revision

Output

The metal.serial headers provide a set of macros, which will generate binary code that can be read on the host by metal.serial. In order to use them we need to implement one function, write_metal_serial that takes one byte and writes it to our communication channel. For our example we'll use std::putchar to write the byte to stdout.

void write_metal_serial(char c) {std::putchar(c);}

Now for the simplest example, we don't use any test macros, but only a printf and a exit-code tracker.

int main()
{
	METAL_SERIAL_INIT(); //initalize communication
	
	METAL_SERIAL_PRINTF("This message is generated from %s(%d).", STR(__FILE__), INT(__LINE__));
	
	METAL_SERIAL_EXIT(42); //use 42 as the exit code
	return 0;
}

The format string will not be read from the binary data, but directly from the source file (hence saving space), while the STR and INT tags tell the library in which format the data should be transmitted. metal.serial uses boost.format to implement the formatting. This allows us to use a formatting tool like printf without using any heap.

Running a test

This library is structured as a simplified form of metal.unit, which will illustrate more of the test output.

Based on what we discussed in the prior section, we can now write a simple test:

int main()
{
	METAL_SERIAL_INIT(); //initalize communication
	METAL_SERIAL_ASSERT(true);
	int x = 143;
	METAL_SERIAL_EXPECT_EQUAL(12, x);
	METAL_SERIAL_TEST_EXIT();
	return 0;
}

Unlike metal.unit, this library requires explicit mentions of initialization and exiting. This is because the binary needs to contain a sequence informing it about the initialization and exit of the test application.

The given test would then produce a binary, that if read by metal.serial might produce output like this.

	Initializing metal serial from test.cpp:9
    test.cpp(10) assertion succeeded [true]: true
    test.cpp(12) expectation failed [equality]: 12 == x; [12 == 143]
	Exiting serial execution with 0

Test Structure

Test cases

A test can be written directly into the main function, but we also provide a solution to seperate test cases using METAL_CALL. In hosted mode these entering and leaving test cases will be documented. This allows grouping tests and controlling the test flow. The same tests

Tests not written inside cases are called free tests.

void test_cases_1()
{
    METAL_SERIAL_ASSERT_EQUAL(42, 42);
}

void test_cases_2()
{
    METAL_SERIAL_ASSERT_NOT_EQUAL(42, 42);
}

int main(int argc, char *argv[])
{
	METAL_SERIAL_INIT();
    METAL_SERIAL_EXPECT_EQUAL(42,0);
    METAL_SERIAL_CALL(&test_cases_1, "Test Case 1");
    METAL_SERIAL_CALL(&test_cases_2, "Test Case 2");
    METAL_SERIAL_TEST_EXIT();
	return 0;
}

Which would provide output like this.

	Initializing metal serial from cases.cpp:15
    cases.cpp(16) expectation failed [equality]: 42 == 0; [42 == 0]
    cases.cpp(17) entering test case [Test Case 1]
    cases.cpp(6) assertion succeeded [equality]: 42 == 42; [42 == 42]
    leaving test case [Test Case 1]: { executed : 1, warnings : 0, errors : 0}
    cases.cpp(18) entering test case [Test Case 2]
    cases.cpp(11) assertion failed [equality]: 42 != 42; [42 != 42]
    leaving test case [Test Case 1]: { executed : 1, warnings : 0, errors : 1}
    free tests : { executed : 1, warnings : 1, errors : 0}
    full test report: { executed : 2, warnings : 1, errors : 1}

Currently METAL_SERIAL_CALL only accepts function pointers with the signature void().

Header files

There are three ways to include the macros for the test.

Header Language Comment
<metal/serial.h> C Macros in C style
<metal/serial.hpp> C++ Macros in C++ style