Inital commit
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
find_package(Unity REQUIRED)
|
||||
find_package(CMock REQUIRED)
|
||||
|
||||
set(TEST_TARGETS "")
|
||||
|
||||
# STK tests
|
||||
add_executable(test_stk test_stk.c)
|
||||
target_include_directories(test_stk PRIVATE "${CMAKE_SOURCE_DIR}")
|
||||
target_link_libraries(test_stk PRIVATE stkshid Unity::Unity)
|
||||
target_compile_features(test_stk PRIVATE c_std_23)
|
||||
add_test(NAME test_stk COMMAND test_stk)
|
||||
list(APPEND TEST_TARGETS test_stk)
|
||||
|
||||
# 'check' builds all suites and runs CTest with full Unity output.
|
||||
# USES_TERMINAL keeps ANSI colors alive through Ninja's output buffering.
|
||||
add_custom_target(check
|
||||
COMMAND ${CMAKE_CTEST_COMMAND}
|
||||
--test-dir "${CMAKE_BINARY_DIR}"
|
||||
--output-on-failure
|
||||
--progress
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||
USES_TERMINAL
|
||||
DEPENDS ${TEST_TARGETS}
|
||||
)
|
||||
|
||||
if (ENABLE_COVERAGE)
|
||||
set(COVERAGE_DIR "${CMAKE_BINARY_DIR}/coverage")
|
||||
add_custom_target(coverage
|
||||
COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${COVERAGE_DIR}"
|
||||
COMMAND ${GCOVR_EXE}
|
||||
--gcov-executable "${GCOV_EXECUTABLE}"
|
||||
--root "${CMAKE_SOURCE_DIR}"
|
||||
--filter "${CMAKE_SOURCE_DIR}/stk/"
|
||||
--exclude "${CMAKE_SOURCE_DIR}/tests/"
|
||||
--exclude ".*Mock.*"
|
||||
--exclude ".*unity.*"
|
||||
--exclude ".*cmock.*"
|
||||
--html-details "${COVERAGE_DIR}/index.html"
|
||||
--txt
|
||||
--print-summary
|
||||
"${CMAKE_BINARY_DIR}"
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||
USES_TERMINAL
|
||||
DEPENDS ${TEST_TARGETS}
|
||||
COMMENT "Coverage report: ${COVERAGE_DIR}/index.html"
|
||||
)
|
||||
endif()
|
||||
@@ -0,0 +1,156 @@
|
||||
#include "unity.h"
|
||||
#include "stk/stk.h"
|
||||
|
||||
void setUp(void) {}
|
||||
void tearDown(void) {}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// stk_config_t
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void test_config_has_correct_fields(void) {
|
||||
stk_config_t cfg = {
|
||||
.vendor_id = STK_DEFAULT_VID,
|
||||
.product_id = STK_DEFAULT_PID,
|
||||
};
|
||||
TEST_ASSERT_EQUAL_UINT16(STK_DEFAULT_VID, cfg.vendor_id);
|
||||
TEST_ASSERT_EQUAL_UINT16(STK_DEFAULT_PID, cfg.product_id);
|
||||
}
|
||||
|
||||
void test_config_defaults_match_vid_pid(void) {
|
||||
TEST_ASSERT_EQUAL_UINT16(0x1209, STK_DEFAULT_VID);
|
||||
TEST_ASSERT_EQUAL_UINT16(0x4F54, STK_DEFAULT_PID);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// stk_state_t
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void test_state_defaults_to_zero(void) {
|
||||
stk_state_t state = { 0 };
|
||||
for (int i = 0; i < STK_NUM_AXES; i++)
|
||||
TEST_ASSERT_EQUAL_INT16(0, state.axes[i]);
|
||||
TEST_ASSERT_EQUAL_UINT32(0, state.buttons);
|
||||
}
|
||||
|
||||
void test_state_has_expected_size(void) {
|
||||
// 8 axes * 2 bytes + 4 bytes buttons = 20 bytes
|
||||
TEST_ASSERT_EQUAL_INT(20, (int)sizeof(stk_state_t));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Axis range constants
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void test_axis_range_is_valid(void) {
|
||||
TEST_ASSERT_TRUE(STK_AXIS_MIN < STK_AXIS_MID);
|
||||
TEST_ASSERT_TRUE(STK_AXIS_MID < STK_AXIS_MAX);
|
||||
}
|
||||
|
||||
void test_axis_mid_is_center(void) {
|
||||
TEST_ASSERT_EQUAL_INT(
|
||||
(STK_AXIS_MIN + STK_AXIS_MAX + 1) / 2,
|
||||
STK_AXIS_MID);
|
||||
}
|
||||
|
||||
void test_axis_range_values(void) {
|
||||
TEST_ASSERT_EQUAL_INT(0, STK_AXIS_MIN);
|
||||
TEST_ASSERT_EQUAL_INT(2047, STK_AXIS_MAX);
|
||||
TEST_ASSERT_EQUAL_INT(1024, STK_AXIS_MID);
|
||||
}
|
||||
|
||||
void test_axis_count(void) {
|
||||
TEST_ASSERT_EQUAL_INT(8, STK_NUM_AXES);
|
||||
}
|
||||
|
||||
void test_button_count(void) {
|
||||
TEST_ASSERT_EQUAL_INT(24, STK_NUM_BUTTONS);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Named axis accessors
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void test_named_accessors_map_correct_indices(void) {
|
||||
stk_state_t state = { 0 };
|
||||
state.axes[1] = 111;
|
||||
state.axes[2] = 222;
|
||||
state.axes[4] = 333;
|
||||
state.axes[5] = 444;
|
||||
|
||||
TEST_ASSERT_EQUAL_INT16(111, stk_right_x(&state));
|
||||
TEST_ASSERT_EQUAL_INT16(222, stk_right_y(&state));
|
||||
TEST_ASSERT_EQUAL_INT16(333, stk_throttle(&state));
|
||||
TEST_ASSERT_EQUAL_INT16(444, stk_left_x(&state));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Button helper
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void test_button_pressed_returns_false_for_unset_bits(void) {
|
||||
stk_state_t state = { .buttons = 0 };
|
||||
for (int i = 0; i < STK_NUM_BUTTONS; i++)
|
||||
TEST_ASSERT_FALSE(stk_button_pressed(&state, (uint8_t)i));
|
||||
}
|
||||
|
||||
void test_button_pressed_returns_true_for_set_bits(void) {
|
||||
stk_state_t state = { .buttons = (1u << 3) | (1u << 17) };
|
||||
TEST_ASSERT_TRUE(stk_button_pressed(&state, 3));
|
||||
TEST_ASSERT_TRUE(stk_button_pressed(&state, 17));
|
||||
TEST_ASSERT_FALSE(stk_button_pressed(&state, 0));
|
||||
TEST_ASSERT_FALSE(stk_button_pressed(&state, 23));
|
||||
}
|
||||
|
||||
void test_button_pressed_out_of_range_returns_false(void) {
|
||||
stk_state_t state = { .buttons = 0xFFFFFFFFu };
|
||||
TEST_ASSERT_FALSE(stk_button_pressed(&state, 24));
|
||||
TEST_ASSERT_FALSE(stk_button_pressed(&state, 31));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// API error handling
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void test_open_with_null_config_fails(void) {
|
||||
TEST_ASSERT_NOT_EQUAL_INT(0, stk_open(NULL));
|
||||
}
|
||||
|
||||
void test_read_with_null_state_fails(void) {
|
||||
TEST_ASSERT_NOT_EQUAL_INT(0, stk_read(NULL));
|
||||
}
|
||||
|
||||
void test_read_without_open_fails(void) {
|
||||
stk_state_t state = { 0 };
|
||||
TEST_ASSERT_NOT_EQUAL_INT(0, stk_read(&state));
|
||||
}
|
||||
|
||||
void test_close_is_safe_without_open(void) {
|
||||
stk_close(); // should not crash
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Main
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
int main(void) {
|
||||
UNITY_BEGIN();
|
||||
RUN_TEST(test_config_has_correct_fields);
|
||||
RUN_TEST(test_config_defaults_match_vid_pid);
|
||||
RUN_TEST(test_state_defaults_to_zero);
|
||||
RUN_TEST(test_state_has_expected_size);
|
||||
RUN_TEST(test_axis_range_is_valid);
|
||||
RUN_TEST(test_axis_mid_is_center);
|
||||
RUN_TEST(test_axis_range_values);
|
||||
RUN_TEST(test_axis_count);
|
||||
RUN_TEST(test_button_count);
|
||||
RUN_TEST(test_named_accessors_map_correct_indices);
|
||||
RUN_TEST(test_button_pressed_returns_false_for_unset_bits);
|
||||
RUN_TEST(test_button_pressed_returns_true_for_set_bits);
|
||||
RUN_TEST(test_button_pressed_out_of_range_returns_false);
|
||||
RUN_TEST(test_open_with_null_config_fails);
|
||||
RUN_TEST(test_read_with_null_state_fails);
|
||||
RUN_TEST(test_read_without_open_fails);
|
||||
RUN_TEST(test_close_is_safe_without_open);
|
||||
return UNITY_END();
|
||||
}
|
||||
Reference in New Issue
Block a user