Implement device management (#199)
- Added `tt::hal::Device` and functions (de)register devices and search for them. - Refactored apps: `Power` and `Display` settings apps now use the device API to find devices. - Implemented the new API for all existing drivers for all devices, including the simulator. - Updated HAL Configuration to return `std::shared_ptr` instead of raw pointers. - Added test project for headless tests and implemented tests for the new code.
This commit is contained in:
committed by
GitHub
parent
c87200a80d
commit
cff0605b0a
@@ -4,6 +4,8 @@ set(DOCTESTINC ${PROJECT_SOURCE_DIR}/Include)
|
||||
|
||||
enable_testing()
|
||||
add_subdirectory(TactilityCore)
|
||||
add_subdirectory(TactilityHeadless)
|
||||
|
||||
add_custom_target(build-tests)
|
||||
add_dependencies(build-tests TactilityCoreTests)
|
||||
add_dependencies(build-tests TactilityHeadlessTests)
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
project(TactilityCoreTests)
|
||||
|
||||
enable_language(C CXX ASM)
|
||||
|
||||
set(CMAKE_CXX_COMPILER g++)
|
||||
|
||||
file(GLOB_RECURSE TEST_SOURCES ${PROJECT_SOURCE_DIR}/*.cpp)
|
||||
add_executable(TactilityHeadlessTests EXCLUDE_FROM_ALL ${TEST_SOURCES})
|
||||
|
||||
add_definitions(-D_Nullable=)
|
||||
add_definitions(-D_Nonnull=)
|
||||
|
||||
target_include_directories(TactilityHeadlessTests PRIVATE
|
||||
${DOCTESTINC}
|
||||
)
|
||||
|
||||
add_test(NAME TactilityHeadlessTests
|
||||
COMMAND TactilityHeadlessTests
|
||||
)
|
||||
|
||||
target_link_libraries(TactilityHeadlessTests PRIVATE
|
||||
Tactility
|
||||
TactilityCore
|
||||
TactilityHeadless
|
||||
Simulator
|
||||
SDL2::SDL2-static SDL2-static
|
||||
)
|
||||
@@ -0,0 +1,98 @@
|
||||
#include "doctest.h"
|
||||
#include <Tactility/hal/Device.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
using namespace tt;
|
||||
|
||||
class TestDevice final : public hal::Device {
|
||||
|
||||
private:
|
||||
|
||||
hal::Device::Type type;
|
||||
std::string name;
|
||||
std::string description;
|
||||
|
||||
public:
|
||||
|
||||
TestDevice(hal::Device::Type type, std::string name, std::string description) :
|
||||
type(type),
|
||||
name(std::move(name)),
|
||||
description(std::move(description))
|
||||
{}
|
||||
|
||||
TestDevice() : TestDevice(hal::Device::Type::Power, "PowerMock", "PowerMock description") {}
|
||||
|
||||
~TestDevice() final = default;
|
||||
|
||||
Type getType() const final { return type; }
|
||||
std::string getName() const final { return name; }
|
||||
std::string getDescription() const final { return description; }
|
||||
};
|
||||
|
||||
class DeviceAutoRegistration {
|
||||
|
||||
std::shared_ptr<hal::Device> device;
|
||||
|
||||
public:
|
||||
|
||||
explicit DeviceAutoRegistration(std::shared_ptr<hal::Device> inDevice) : device(std::move(inDevice)) {
|
||||
hal::registerDevice(device);
|
||||
}
|
||||
|
||||
~DeviceAutoRegistration() {
|
||||
hal::deregisterDevice(device);
|
||||
}
|
||||
};
|
||||
|
||||
/** We add 3 tests into 1 to ensure cleanup happens */
|
||||
TEST_CASE("registering and deregistering a device works") {
|
||||
auto device = std::make_shared<TestDevice>();
|
||||
|
||||
// Pre-registration
|
||||
CHECK_EQ(hal::findDevice(device->getId()), nullptr);
|
||||
|
||||
// Registration
|
||||
hal::registerDevice(device);
|
||||
auto found_device = hal::findDevice(device->getId());
|
||||
CHECK_NE(found_device, nullptr);
|
||||
CHECK_EQ(found_device->getId(), device->getId());
|
||||
|
||||
// Deregistration
|
||||
hal::deregisterDevice(device);
|
||||
CHECK_EQ(hal::findDevice(device->getId()), nullptr);
|
||||
found_device = nullptr; // to decrease use count
|
||||
CHECK_EQ(device.use_count(), 1);
|
||||
}
|
||||
|
||||
TEST_CASE("find device by id") {
|
||||
auto device = std::make_shared<TestDevice>();
|
||||
DeviceAutoRegistration auto_registration(device);
|
||||
|
||||
auto found_device = hal::findDevice(device->getId());
|
||||
CHECK_NE(found_device, nullptr);
|
||||
CHECK_EQ(found_device->getId(), device->getId());
|
||||
}
|
||||
|
||||
TEST_CASE("find device by name") {
|
||||
auto device = std::make_shared<TestDevice>();
|
||||
DeviceAutoRegistration auto_registration(device);
|
||||
|
||||
auto found_device = hal::findDevice(device->getName());
|
||||
CHECK_NE(found_device, nullptr);
|
||||
CHECK_EQ(found_device->getId(), device->getId());
|
||||
}
|
||||
|
||||
TEST_CASE("find device by type") {
|
||||
// Headless mode shouldn't have a display, so we want to create one to find only our own display as unique device
|
||||
// We first verify the initial assumption that there is no display:
|
||||
auto unexpected_display = hal::findFirstDevice<TestDevice>(hal::Device::Type::Display);
|
||||
CHECK_EQ(unexpected_display, nullptr);
|
||||
|
||||
auto device = std::make_shared<TestDevice>(hal::Device::Type::Display, "DisplayMock", "");
|
||||
DeviceAutoRegistration auto_registration(device);
|
||||
|
||||
auto found_device = hal::findFirstDevice<TestDevice>(hal::Device::Type::Display);
|
||||
CHECK_NE(found_device, nullptr);
|
||||
CHECK_EQ(found_device->getId(), device->getId());
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
#define DOCTEST_CONFIG_IMPLEMENT
|
||||
#include "doctest.h"
|
||||
#include <cassert>
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
typedef struct {
|
||||
int argc;
|
||||
char** argv;
|
||||
int result;
|
||||
} TestTaskData;
|
||||
|
||||
void test_task(void* parameter) {
|
||||
auto* data = (TestTaskData*)parameter;
|
||||
|
||||
doctest::Context context;
|
||||
|
||||
context.applyCommandLine(data->argc, data->argv);
|
||||
|
||||
// overrides
|
||||
context.setOption("no-breaks", true); // don't break in the debugger when assertions fail
|
||||
|
||||
data->result = context.run();
|
||||
|
||||
if (context.shouldExit()) { // important - query flags (and --exit) rely on the user doing this
|
||||
vTaskEndScheduler();
|
||||
}
|
||||
|
||||
vTaskDelete(nullptr);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
TestTaskData data = {
|
||||
.argc = argc,
|
||||
.argv = argv,
|
||||
.result = 0
|
||||
};
|
||||
|
||||
BaseType_t task_result = xTaskCreate(
|
||||
test_task,
|
||||
"test_task",
|
||||
8192,
|
||||
&data,
|
||||
1,
|
||||
nullptr
|
||||
);
|
||||
assert(task_result == pdPASS);
|
||||
|
||||
vTaskStartScheduler();
|
||||
}
|
||||
Reference in New Issue
Block a user