Add legacy contracts

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
Joey Yakimowich-Payne 2026-08-11 12:23:07 +09:00
commit f3067bfd2e
2 changed files with 136 additions and 0 deletions

View file

@ -0,0 +1,98 @@
#include "test_support.h"
#include <cstddef>
#include <cstdint>
#include <cstring>
#include "../../switch_pro_descriptors.h"
namespace {
template <std::size_t ActualSize, std::size_t ExpectedSize>
bool bytes_equal(
const uint8_t (&actual)[ActualSize],
const uint8_t (&expected)[ExpectedSize]) {
return ActualSize == ExpectedSize &&
std::memcmp(actual, expected, ExpectedSize) == 0;
}
bool legacy_device_descriptor_matches_exact_bytes() {
// Given: the captured legacy device descriptor bytes.
static constexpr uint8_t expected[] = {
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x7E,
0x05, 0x09, 0x20, 0x10, 0x02, 0x01, 0x02, 0x03, 0x01,
};
// When: the compiled legacy descriptor is inspected.
// Then: its identity and all 18 bytes remain unchanged.
CHECK(sizeof(switch_pro_device_descriptor) == 18);
CHECK(bytes_equal(switch_pro_device_descriptor, expected));
return true;
}
bool legacy_configuration_descriptor_matches_exact_bytes() {
// Given: the captured single-interface legacy configuration.
static constexpr uint8_t expected[] = {
0x09, 0x02, 0x29, 0x00, 0x01, 0x01, 0x00, 0xA0, 0xFA,
0x09, 0x04, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00,
0x09, 0x21, 0x11, 0x01, 0x00, 0x01, 0x22, 0xCB, 0x00,
0x07, 0x05, 0x81, 0x03, 0x40, 0x00, 0x08,
0x07, 0x05, 0x01, 0x03, 0x40, 0x00, 0x08,
};
// When: the compiled legacy configuration is inspected.
// Then: the interface and both interrupt endpoints remain byte-identical.
CHECK(sizeof(switch_pro_configuration_descriptor) == 41);
CHECK(bytes_equal(switch_pro_configuration_descriptor, expected));
return true;
}
bool legacy_hid_report_descriptor_matches_exact_bytes() {
// Given: the complete captured 203-byte legacy HID report descriptor.
static constexpr uint8_t expected[] = {
0x05, 0x01, 0x15, 0x00, 0x09, 0x04, 0xA1, 0x01, 0x85, 0x30, 0x05, 0x01, 0x05, 0x09, 0x19, 0x01,
0x29, 0x0A, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x0A, 0x55, 0x00, 0x65, 0x00, 0x81, 0x02,
0x05, 0x09, 0x19, 0x0B, 0x29, 0x0E, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x04, 0x81, 0x02,
0x75, 0x01, 0x95, 0x02, 0x81, 0x03, 0x0B, 0x01, 0x00, 0x01, 0x00, 0xA1, 0x00, 0x0B, 0x30, 0x00,
0x01, 0x00, 0x0B, 0x31, 0x00, 0x01, 0x00, 0x0B, 0x32, 0x00, 0x01, 0x00, 0x0B, 0x35, 0x00, 0x01,
0x00, 0x15, 0x00, 0x27, 0xFF, 0xFF, 0x00, 0x00, 0x75, 0x10, 0x95, 0x04, 0x81, 0x02, 0xC0, 0x0B,
0x39, 0x00, 0x01, 0x00, 0x15, 0x00, 0x25, 0x07, 0x35, 0x00, 0x46, 0x3B, 0x01, 0x65, 0x14, 0x75,
0x04, 0x95, 0x01, 0x81, 0x02, 0x05, 0x09, 0x19, 0x0F, 0x29, 0x12, 0x15, 0x00, 0x25, 0x01, 0x75,
0x01, 0x95, 0x04, 0x81, 0x02, 0x75, 0x08, 0x95, 0x34, 0x81, 0x03, 0x06, 0x00, 0xFF, 0x85, 0x21,
0x09, 0x01, 0x75, 0x08, 0x95, 0x3F, 0x81, 0x03, 0x85, 0x81, 0x09, 0x02, 0x75, 0x08, 0x95, 0x3F,
0x81, 0x03, 0x85, 0x01, 0x09, 0x03, 0x75, 0x08, 0x95, 0x3F, 0x91, 0x83, 0x85, 0x10, 0x09, 0x04,
0x75, 0x08, 0x95, 0x3F, 0x91, 0x83, 0x85, 0x80, 0x09, 0x05, 0x75, 0x08, 0x95, 0x3F, 0x91, 0x83,
0x85, 0x82, 0x09, 0x06, 0x75, 0x08, 0x95, 0x3F, 0x91, 0x83, 0xC0,
};
// When: the compiled legacy HID descriptor is inspected.
// Then: every report item remains byte-identical.
CHECK(sizeof(switch_pro_report_descriptor) == 203);
CHECK(bytes_equal(switch_pro_report_descriptor, expected));
return true;
}
bool legacy_string_descriptors_match_exact_bytes() {
// Given: the legacy language, manufacturer, product, and serial strings.
static constexpr uint8_t language[] = {0x09, 0x04};
static constexpr uint8_t manufacturer[] = "Nintendo Co., Ltd.";
static constexpr uint8_t product[] = "Pro Controller";
static constexpr uint8_t version[] = "000000000001";
// When: the compiled string tables are inspected.
// Then: every string byte and terminator remains unchanged.
CHECK(bytes_equal(switch_pro_string_language, language));
CHECK(bytes_equal(switch_pro_string_manufacturer, manufacturer));
CHECK(bytes_equal(switch_pro_string_product, product));
CHECK(bytes_equal(switch_pro_string_version, version));
return true;
}
} // namespace
void run_legacy_descriptor_tests(TestRunner& runner) {
runner.run("legacy device descriptor exact bytes", legacy_device_descriptor_matches_exact_bytes);
runner.run("legacy configuration descriptor exact bytes", legacy_configuration_descriptor_matches_exact_bytes);
runner.run("legacy HID report descriptor exact bytes", legacy_hid_report_descriptor_matches_exact_bytes);
runner.run("legacy string descriptors exact bytes", legacy_string_descriptors_match_exact_bytes);
}

View file

@ -0,0 +1,38 @@
#pragma once
#include <cstdio>
class TestRunner {
public:
void run(const char* name, bool (*test)()) {
if (test()) {
std::printf("PASS %s\n", name);
return;
}
++failures_;
std::printf("FAIL %s\n", name);
}
int result() const {
return failures_ == 0 ? 0 : 1;
}
private:
int failures_ = 0;
};
#define CHECK(condition) \
do { \
if (!(condition)) { \
std::fprintf(stderr, " %s:%d: %s\n", __FILE__, __LINE__, #condition); \
return false; \
} \
} while (false)
void run_legacy_descriptor_tests(TestRunner& runner);
void run_switch2_command_tests(TestRunner& runner);
void run_switch2_descriptor_tests(TestRunner& runner);
void run_switch2_report_tests(TestRunner& runner);
void run_switch_input_tests(TestRunner& runner);
void run_switch_uart_protocol_tests(TestRunner& runner);