mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-06 03:50:13 +02:00
deleting test stuff from this PR... that's harder than I expected
This commit is contained in:
parent
711aeded0c
commit
78ca80feae
11 changed files with 1 additions and 445 deletions
29
.github/workflows/unit-tests.yml
vendored
29
.github/workflows/unit-tests.yml
vendored
|
@ -1,29 +0,0 @@
|
||||||
name: Run Unit Tests
|
|
||||||
|
|
||||||
on: [push, pull_request]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Configure and build with CMake
|
|
||||||
run: |
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake -DUNIT_TEST=ON ..
|
|
||||||
cmake --build .
|
|
||||||
|
|
||||||
- name: Run unit tests
|
|
||||||
run: |
|
|
||||||
set -e # Exit immediately on non-zero exit code
|
|
||||||
cd build/test
|
|
||||||
dir -s
|
|
||||||
for test_executable in *; do
|
|
||||||
if [ -f "$test_executable" ] && [ -x "$test_executable" ]; then
|
|
||||||
./"$test_executable"
|
|
||||||
fi
|
|
||||||
done
|
|
|
@ -1,6 +0,0 @@
|
||||||
cmake_minimum_required(VERSION 3.10)
|
|
||||||
|
|
||||||
project(BatteryEmulator)
|
|
||||||
|
|
||||||
# add_subdirectory(Software/src/devboard/utils)
|
|
||||||
add_subdirectory(test)
|
|
|
@ -1 +0,0 @@
|
||||||
# add_library(utils_library events.cpp)
|
|
|
@ -1,5 +1,6 @@
|
||||||
#ifndef __EVENTS_H__
|
#ifndef __EVENTS_H__
|
||||||
#define __EVENTS_H__
|
#define __EVENTS_H__
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifndef UNIT_TEST
|
#ifndef UNIT_TEST
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
@ -7,8 +8,6 @@ extern unsigned long previous_millis;
|
||||||
extern uint32_t time_seconds;
|
extern uint32_t time_seconds;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define EVENTS_ENUM_TYPE(XX) \
|
#define EVENTS_ENUM_TYPE(XX) \
|
||||||
XX(EVENT_CAN_FAILURE) \
|
XX(EVENT_CAN_FAILURE) \
|
||||||
XX(EVENT_CAN_WARNING) \
|
XX(EVENT_CAN_WARNING) \
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
g++ events_test.cpp ../../../test/test_lib.cpp -o events_test.exe -DUNIT_TEST -I.
|
|
|
@ -1,18 +0,0 @@
|
||||||
# Include the directory with your source files
|
|
||||||
include_directories(${CMAKE_SOURCE_DIR}/Software/src/devboard/utils .)
|
|
||||||
|
|
||||||
# Create a variable to store the list of test files
|
|
||||||
file(GLOB TEST_SOURCES utils/*.cpp)
|
|
||||||
|
|
||||||
# Loop through each test source file and create an executable
|
|
||||||
foreach(TEST_SOURCE ${TEST_SOURCES})
|
|
||||||
# Extract the test name without extension
|
|
||||||
get_filename_component(TEST_NAME ${TEST_SOURCE} NAME_WE)
|
|
||||||
|
|
||||||
# Create an executable for the test
|
|
||||||
add_executable(${TEST_NAME} ${TEST_SOURCE} test_lib.cpp)
|
|
||||||
|
|
||||||
# Apply the target_compile_definitions for the test
|
|
||||||
target_compile_definitions(${TEST_NAME} PRIVATE UNIT_TEST)
|
|
||||||
|
|
||||||
endforeach()
|
|
209
test/microtest.h
209
test/microtest.h
|
@ -1,209 +0,0 @@
|
||||||
//
|
|
||||||
// microtest.h
|
|
||||||
//
|
|
||||||
// URL: https://github.com/torpedro/microtest.h
|
|
||||||
// Author: Pedro Flemming (http://torpedro.com/)
|
|
||||||
// License: MIT License (https://github.com/torpedro/microtest.h/blob/master/LICENSE)
|
|
||||||
// Copyright (c) 2017 Pedro Flemming
|
|
||||||
//
|
|
||||||
// This is a small header-only C++ unit testing framework.
|
|
||||||
// It allows to define small unit tests with set of assertions available.
|
|
||||||
//
|
|
||||||
#ifndef __MICROTEST_H__
|
|
||||||
#define __MICROTEST_H__
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
////////////////
|
|
||||||
// Assertions //
|
|
||||||
////////////////
|
|
||||||
|
|
||||||
#define ASSERT(cond) ASSERT_TRUE(cond);
|
|
||||||
|
|
||||||
#define ASSERT_TRUE(cond) \
|
|
||||||
if (!(cond)) \
|
|
||||||
throw mt::AssertFailedException(#cond, __FILE__, __LINE__);
|
|
||||||
|
|
||||||
#define ASSERT_FALSE(cond) \
|
|
||||||
if (cond) \
|
|
||||||
throw mt::AssertFailedException(#cond, __FILE__, __LINE__);
|
|
||||||
|
|
||||||
#define ASSERT_NULL(value) ASSERT_TRUE(value == NULL);
|
|
||||||
|
|
||||||
#define ASSERT_NOTNULL(value) ASSERT_TRUE(value != NULL);
|
|
||||||
|
|
||||||
#define ASSERT_STREQ(a, b) \
|
|
||||||
if (std::string(a).compare(std::string(b)) != 0) { \
|
|
||||||
printf("%s{ info} %s", mt::yellow(), mt::def()); \
|
|
||||||
std::cout << "Actual values: " << a << " != " << b << std::endl; \
|
|
||||||
throw mt::AssertFailedException(#a " == " #b, __FILE__, __LINE__); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ASSERT_STRNEQ(a, b) \
|
|
||||||
if (std::string(a).compare(std::string(b)) != = 0) { \
|
|
||||||
printf("%s{ info} %s", mt::yellow(), mt::def()); \
|
|
||||||
std::cout << "Actual values: " << a << " == " << b << std::endl; \
|
|
||||||
throw mt::AssertFailedException(#a " != " #b, __FILE__, __LINE__); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ASSERT_EQ(a, b) \
|
|
||||||
if (a != b) { \
|
|
||||||
printf("%s{ info} %s", mt::yellow(), mt::def()); \
|
|
||||||
std::cout << "Actual values: " << a << " != " << b << std::endl; \
|
|
||||||
} \
|
|
||||||
ASSERT(a == b);
|
|
||||||
|
|
||||||
#define ASSERT_NEQ(a, b) \
|
|
||||||
if (a == b) { \
|
|
||||||
printf("%s{ info} %s", mt::yellow(), mt::def()); \
|
|
||||||
std::cout << "Actual values: " << a << " == " << b << std::endl; \
|
|
||||||
} \
|
|
||||||
ASSERT(a != b);
|
|
||||||
|
|
||||||
////////////////
|
|
||||||
// Unit Tests //
|
|
||||||
////////////////
|
|
||||||
|
|
||||||
#define TEST(name) \
|
|
||||||
void name(); \
|
|
||||||
namespace { \
|
|
||||||
bool __##name = mt::TestsManager::AddTest(name, #name); \
|
|
||||||
} \
|
|
||||||
void name()
|
|
||||||
|
|
||||||
///////////////
|
|
||||||
// Framework //
|
|
||||||
///////////////
|
|
||||||
|
|
||||||
namespace mt {
|
|
||||||
|
|
||||||
inline const char* red() {
|
|
||||||
return "\033[1;31m";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char* green() {
|
|
||||||
return "\033[0;32m";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char* yellow() {
|
|
||||||
return "\033[0;33m";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char* def() {
|
|
||||||
return "\033[0m";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void printRunning(const char* message, FILE* file = stdout) {
|
|
||||||
fprintf(file, "%s{ running}%s %s\n", green(), def(), message);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void printOk(const char* message, FILE* file = stdout) {
|
|
||||||
fprintf(file, "%s{ ok}%s %s\n", green(), def(), message);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void printFailed(const char* message, FILE* file = stdout) {
|
|
||||||
fprintf(file, "%s{ failed} %s%s\n", red(), message, def());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exception that is thrown when an assertion fails.
|
|
||||||
class AssertFailedException : public std::exception {
|
|
||||||
public:
|
|
||||||
AssertFailedException(std::string description, std::string filepath, int line)
|
|
||||||
: std::exception(), description_(description), filepath_(filepath), line_(line){};
|
|
||||||
|
|
||||||
virtual const char* what() const throw() { return description_.c_str(); }
|
|
||||||
|
|
||||||
inline const char* getFilepath() { return filepath_.c_str(); }
|
|
||||||
|
|
||||||
inline int getLine() { return line_; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::string description_;
|
|
||||||
std::string filepath_;
|
|
||||||
int line_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TestsManager {
|
|
||||||
// Note: static initialization fiasco
|
|
||||||
// http://www.parashift.com/c++-faq-lite/static-init-order.html
|
|
||||||
// http://www.parashift.com/c++-faq-lite/static-init-order-on-first-use.html
|
|
||||||
public:
|
|
||||||
struct Test {
|
|
||||||
const char* name;
|
|
||||||
void (*fn)(void);
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::vector<Test>& tests() {
|
|
||||||
static std::vector<Test> tests_;
|
|
||||||
return tests_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds a new test to the current set of tests.
|
|
||||||
// Returns false if a test with the same name already exists.
|
|
||||||
inline static bool AddTest(void (*fn)(void), const char* name) {
|
|
||||||
tests().push_back({name, fn});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run all tests that are registered.
|
|
||||||
// Returns the number of tests that failed.
|
|
||||||
inline static size_t RunAllTests(FILE* file = stdout) {
|
|
||||||
size_t num_failed = 0;
|
|
||||||
|
|
||||||
for (const Test& test : tests()) {
|
|
||||||
// Run the test.
|
|
||||||
// If an AsserFailedException is thrown, the test has failed.
|
|
||||||
try {
|
|
||||||
printRunning(test.name, file);
|
|
||||||
|
|
||||||
(*test.fn)();
|
|
||||||
|
|
||||||
printOk(test.name, file);
|
|
||||||
|
|
||||||
} catch (AssertFailedException& e) {
|
|
||||||
printFailed(test.name, file);
|
|
||||||
fprintf(file, " %sAssertion failed: %s%s\n", red(), e.what(), def());
|
|
||||||
fprintf(file, " %s%s:%d%s\n", red(), e.getFilepath(), e.getLine(), def());
|
|
||||||
++num_failed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int return_code = (num_failed > 0) ? 1 : 0;
|
|
||||||
return return_code;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Class that will capture the arguments passed to the program.
|
|
||||||
class Runtime {
|
|
||||||
public:
|
|
||||||
static const std::vector<std::string>& args(int argc = -1, char** argv = NULL) {
|
|
||||||
static std::vector<std::string> args_;
|
|
||||||
if (argc >= 0) {
|
|
||||||
for (int i = 0; i < argc; ++i) {
|
|
||||||
args_.push_back(argv[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return args_;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace mt
|
|
||||||
|
|
||||||
#define TEST_MAIN() \
|
|
||||||
int main(int argc, char* argv[]) { \
|
|
||||||
mt::Runtime::args(argc, argv); \
|
|
||||||
\
|
|
||||||
size_t num_failed = mt::TestsManager::RunAllTests(stdout); \
|
|
||||||
if (num_failed == 0) { \
|
|
||||||
fprintf(stdout, "%s{ summary} All tests succeeded!%s\n", mt::green(), mt::def()); \
|
|
||||||
return 0; \
|
|
||||||
} else { \
|
|
||||||
double percentage = 100.0 * num_failed / mt::TestsManager::tests().size(); \
|
|
||||||
fprintf(stderr, "%s{ summary} %lu tests failed (%.2f%%)%s\n", mt::red(), num_failed, percentage, mt::def()); \
|
|
||||||
return -1; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // __MICROTEST_H__
|
|
|
@ -1,6 +0,0 @@
|
||||||
#include "test_lib.h"
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
MySerial Serial;
|
|
||||||
|
|
||||||
unsigned long testlib_millis = 0;
|
|
|
@ -1,43 +0,0 @@
|
||||||
#ifndef __TEST_LIB_H__
|
|
||||||
#define __TEST_LIB_H__
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
#include "microtest.h"
|
|
||||||
|
|
||||||
class MySerial;
|
|
||||||
|
|
||||||
extern unsigned long testlib_millis;
|
|
||||||
|
|
||||||
/* Mock millis() */
|
|
||||||
static inline unsigned long millis(void) {
|
|
||||||
return testlib_millis;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mock Serial class */
|
|
||||||
class MySerial {
|
|
||||||
public:
|
|
||||||
size_t println(const char* s) {
|
|
||||||
return print(s, true); // Call print with newline argument true
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t print(const char* s) {
|
|
||||||
return print(s, false); // Call print with newline argument false
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
size_t print(const char* s, bool newline) {
|
|
||||||
size_t length = printf("%s", s); // Print the string without newline
|
|
||||||
if (newline) {
|
|
||||||
printf("\n"); // Add a newline if specified
|
|
||||||
length++; // Increment length to account for the added newline character
|
|
||||||
}
|
|
||||||
return length; // Return the total length printed
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
extern MySerial Serial;
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,83 +0,0 @@
|
||||||
// The test library must be included first!
|
|
||||||
#include "../test_lib.h"
|
|
||||||
|
|
||||||
#include "../../Software/src/devboard/utils/events.h"
|
|
||||||
|
|
||||||
#define EVENTLOGGING
|
|
||||||
#define DUMMY_EVENT_ENABLED true
|
|
||||||
|
|
||||||
/* Helper functions */
|
|
||||||
static char event_message[256]; // Declare the event_message variable
|
|
||||||
|
|
||||||
static void reset_event_msg(void) {
|
|
||||||
snprintf(event_message, sizeof(event_message), "");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(init_events_test) {
|
|
||||||
init_events();
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < EVENT_NOF_EVENTS; i++) {
|
|
||||||
ASSERT_EQ(entries[i].occurences, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(update_event_timestamps_test) {
|
|
||||||
// Reset
|
|
||||||
init_events();
|
|
||||||
time_seconds = 0;
|
|
||||||
|
|
||||||
// No delta, so time shouldn't increase
|
|
||||||
testlib_millis = 0;
|
|
||||||
update_event_timestamps();
|
|
||||||
ASSERT_EQ(time_seconds, 0);
|
|
||||||
|
|
||||||
// Almost time to bump the seconds
|
|
||||||
testlib_millis = 999;
|
|
||||||
update_event_timestamps();
|
|
||||||
ASSERT_EQ(time_seconds, 0);
|
|
||||||
ASSERT_EQ(previous_millis, 0);
|
|
||||||
|
|
||||||
// millis == 1000, so we should add a second
|
|
||||||
testlib_millis = 1000;
|
|
||||||
update_event_timestamps();
|
|
||||||
ASSERT_EQ(time_seconds, 1);
|
|
||||||
ASSERT_EQ(previous_millis, 1000);
|
|
||||||
|
|
||||||
// We shouldn't add more seconds until 2000 now
|
|
||||||
testlib_millis = 1999;
|
|
||||||
update_event_timestamps();
|
|
||||||
ASSERT_EQ(time_seconds, 1);
|
|
||||||
ASSERT_EQ(previous_millis, 1000);
|
|
||||||
testlib_millis = 2000;
|
|
||||||
update_event_timestamps();
|
|
||||||
ASSERT_EQ(time_seconds, 2);
|
|
||||||
ASSERT_EQ(previous_millis, 2000);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(set_event_test) {
|
|
||||||
// Reset
|
|
||||||
init_events();
|
|
||||||
time_seconds = 0;
|
|
||||||
|
|
||||||
// Initially, the event should not have any data or occurences
|
|
||||||
ASSERT_EQ(entries[EVENT_CELL_OVER_VOLTAGE].data, 0);
|
|
||||||
ASSERT_EQ(entries[EVENT_CELL_OVER_VOLTAGE].occurences, 0);
|
|
||||||
ASSERT_EQ(entries[EVENT_CELL_OVER_VOLTAGE].timestamp, 0);
|
|
||||||
// Set current time and overvoltage event for cell 23
|
|
||||||
time_seconds = 345;
|
|
||||||
set_event(EVENT_CELL_OVER_VOLTAGE, 123);
|
|
||||||
// Ensure proper event data
|
|
||||||
ASSERT_EQ(entries[EVENT_CELL_OVER_VOLTAGE].data, 123);
|
|
||||||
ASSERT_EQ(entries[EVENT_CELL_OVER_VOLTAGE].occurences, 1);
|
|
||||||
ASSERT_EQ(entries[EVENT_CELL_OVER_VOLTAGE].timestamp, 345);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(event_message_test) {
|
|
||||||
reset_event_msg();
|
|
||||||
|
|
||||||
set_event(EVENT_DUMMY, 0); // Set dummy event with no data
|
|
||||||
|
|
||||||
ASSERT_STREQ("The dummy event was set!", event_message);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_MAIN();
|
|
|
@ -1,47 +0,0 @@
|
||||||
// The test library must be included first!
|
|
||||||
#include "../test_lib.h"
|
|
||||||
|
|
||||||
#include "../../Software/src/devboard/utils/timer.cpp"
|
|
||||||
|
|
||||||
/* Helper functions */
|
|
||||||
|
|
||||||
/* Test functions */
|
|
||||||
|
|
||||||
TEST(timer_test) {
|
|
||||||
unsigned long test_interval = 10;
|
|
||||||
bool result;
|
|
||||||
|
|
||||||
// Create a timer, assert that it hasn't elapsed immediately
|
|
||||||
testlib_millis = 30;
|
|
||||||
MyTimer timer(test_interval);
|
|
||||||
result = timer.elapsed();
|
|
||||||
ASSERT_EQ(result, false);
|
|
||||||
|
|
||||||
// Test interval - 1, shouldn't have elapsed
|
|
||||||
testlib_millis += test_interval - 1;
|
|
||||||
result = timer.elapsed();
|
|
||||||
ASSERT_EQ(result, false);
|
|
||||||
|
|
||||||
// Add 1, so now it should have elapsed
|
|
||||||
testlib_millis += 1;
|
|
||||||
result = timer.elapsed();
|
|
||||||
ASSERT_EQ(result, true);
|
|
||||||
|
|
||||||
// The timer should have reset when it elapsed
|
|
||||||
result = timer.elapsed();
|
|
||||||
ASSERT_EQ(result, false);
|
|
||||||
|
|
||||||
// Test close to the next interval
|
|
||||||
testlib_millis += test_interval - 1;
|
|
||||||
result = timer.elapsed();
|
|
||||||
ASSERT_EQ(result, false);
|
|
||||||
|
|
||||||
// Add 1, ensure that the timer elapses but only once
|
|
||||||
testlib_millis += 1;
|
|
||||||
result = timer.elapsed();
|
|
||||||
ASSERT_EQ(result, true);
|
|
||||||
result = timer.elapsed();
|
|
||||||
ASSERT_EQ(result, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_MAIN();
|
|
Loading…
Add table
Add a link
Reference in a new issue