Browse Source

unittests: Add C++ constructors test

master
Joakim Nohlgård 6 years ago
parent
commit
0f477b8b44
  1. 1
      tests/unittests/tests-cpp_ctors/Makefile
  2. 1
      tests/unittests/tests-cpp_ctors/Makefile.include
  3. 18
      tests/unittests/tests-cpp_ctors/README.md
  4. 36
      tests/unittests/tests-cpp_ctors/tests-cpp_ctors-class.cpp
  5. 63
      tests/unittests/tests-cpp_ctors/tests-cpp_ctors-trampoline.c
  6. 37
      tests/unittests/tests-cpp_ctors/tests-cpp_ctors.cpp
  7. 56
      tests/unittests/tests-cpp_ctors/tests-cpp_ctors.h

1
tests/unittests/tests-cpp_ctors/Makefile

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

1
tests/unittests/tests-cpp_ctors/Makefile.include

@ -0,0 +1 @@
FEATURES_REQUIRED += cpp

18
tests/unittests/tests-cpp_ctors/README.md

@ -0,0 +1,18 @@
The purpose of this test is to ensure that C++ constructors are executed
properly during the startup of RIOT. This requires that the port calls
constructors somewhere during C-library initialization. On newlib ports this is
done by __libc_init_array(), other ports may need to manually iterate through
the list of initializer functions (usually .init_array), and call each one in
order.
There are three tests:
- Global constructor
- Static constructor
- Local constructor
The global constructor test checks to see if the constructor of a global object
has been run during the boot process. The static constructor test does the
same, but for static object inside a function. The local constructor test checks
that a locally created object does have its constructor run.
The local constructor test will only fail if there is a significant problem with
the C++ tool chain, since it does not rely on any external C++ support code.

36
tests/unittests/tests-cpp_ctors/tests-cpp_ctors-class.cpp

@ -0,0 +1,36 @@
/*
* Copyright (C) 2016-2017 Eistec AB
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
#include "tests-cpp_ctors.h"
volatile long tests_cpp_ctors_magic1 = 12345;
volatile long tests_cpp_ctors_magic2 = 11111111;
void *tests_cpp_ctors_order[8];
namespace RIOTTestCPP {
MyClass::MyClass()
{
var = tests_cpp_ctors_magic1;
}
MyClass::MyClass(long value) : var(value)
{
}
long MyClass::value()
{
return var;
}
void MyClass::inc()
{
++var;
}
} /* namespace RIOTTestCPP */

63
tests/unittests/tests-cpp_ctors/tests-cpp_ctors-trampoline.c

@ -0,0 +1,63 @@
/*
* Copyright (C) 2016-2017 Eistec AB
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
#include "embUnit.h"
#include "embUnit/embUnit.h"
#include "tests-cpp_ctors.h"
#include "thread.h" /* For thread_getpid() */
long tests_cpp_ctors_global_value(void);
long tests_cpp_ctors_static_value(void);
long tests_cpp_ctors_local_value(long number);
extern volatile long tests_cpp_ctors_magic1;
extern volatile long tests_cpp_ctors_magic2;
extern void *tests_cpp_ctors_order[8];
static void tests_cpp_global_ctors(void)
{
long expected = tests_cpp_ctors_magic1;
long actual = tests_cpp_ctors_global_value();
/* Test to ensure that global constructors have executed */
TEST_ASSERT_EQUAL_INT(expected, actual);
}
static void tests_cpp_static_ctors(void)
{
for (long i = 1; i < 10; ++i) {
long expected = tests_cpp_ctors_magic2 + i;
long actual = tests_cpp_ctors_static_value();
TEST_ASSERT_EQUAL_INT(expected, actual);
}
}
static void tests_cpp_local_ctors(void)
{
/* Test to ensure that local constructors are executed properly */
long expected = thread_getpid() + 1;
long actual = tests_cpp_ctors_local_value(thread_getpid());
TEST_ASSERT_EQUAL_INT(expected, actual);
}
Test *tests_cpp_ctors_tests(void)
{
EMB_UNIT_TESTFIXTURES(fixtures) {
new_TestFixture(tests_cpp_local_ctors),
new_TestFixture(tests_cpp_global_ctors),
new_TestFixture(tests_cpp_static_ctors),
};
EMB_UNIT_TESTCALLER(cpp_tests, NULL, NULL, fixtures);
return (Test *)&cpp_tests;
}
void tests_cpp_ctors(void)
{
TESTS_RUN(tests_cpp_ctors_tests());
}

37
tests/unittests/tests-cpp_ctors/tests-cpp_ctors.cpp

@ -0,0 +1,37 @@
/*
* Copyright (C) 2016-2017 Eistec AB
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
#include "tests-cpp_ctors.h"
using RIOTTestCPP::MyClass;
MyClass global_obj;
extern "C" {
long tests_cpp_ctors_global_value(void);
long tests_cpp_ctors_static_value(void);
long tests_cpp_ctors_local_value(long);
}
extern volatile long tests_cpp_ctors_magic2;
long tests_cpp_ctors_local_value(long number) {
MyClass local_obj(number);
local_obj.inc();
return local_obj.value();
}
long tests_cpp_ctors_static_value() {
static MyClass static_obj(tests_cpp_ctors_magic2);
static_obj.inc();
return static_obj.value();
}
long tests_cpp_ctors_global_value() {
return global_obj.value();
}

56
tests/unittests/tests-cpp_ctors/tests-cpp_ctors.h

@ -0,0 +1,56 @@
/*
* Copyright (C) 2016-2017 Eistec AB
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @addtogroup unittests
* @{
*
* @file
* @brief Unittests for C++ constructors
*
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
*/
#ifndef TESTS_CPP_CTORS_H
#define TESTS_CPP_CTORS_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief The entry point of this test suite.
*/
void tests_cpp(void);
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
namespace RIOTTestCPP {
/**
* @brief Simple class used for testing constructor calls
*/
class MyClass {
private:
volatile long var;
public:
MyClass();
explicit MyClass(long value);
long value();
void inc();
};
}
#endif
#endif /* TESTS_CPP_CTORS_H */
/** @} */
Loading…
Cancel
Save