| 20 | #include "test.h" |
| 21 | |
| 22 | FL_TEST_FILE(FL_FILEPATH) { |
| 23 | |
| 24 | using namespace fl; |
| 25 | |
| 26 | // Compile-time invariants — these enforce the design at the type system level. |
| 27 | // Failure to compile these is a Phase 1 regression. |
| 28 | |
| 29 | FL_STATIC_ASSERT(static_cast<fl::u8>(fl::Bus::AUTO) == 0, |
| 30 | "Bus::AUTO must be the zero/default sentinel"); |
| 31 | FL_STATIC_ASSERT(static_cast<fl::u8>(fl::Bus::RMT) != static_cast<fl::u8>(fl::Bus::PARLIO), |
| 32 | "Bus enum values must be distinct"); |
| 33 | FL_STATIC_ASSERT(sizeof(fl::Bus) == 1, |
| 34 | "Bus underlying type should be u8 to keep ChannelOptions cheap"); |
| 35 | |
| 36 | // DefaultBus<Chipset> resolves on the host (FL_IS_STUB is set under tests). |
| 37 | FL_STATIC_ASSERT(fl::DefaultBus<fl::ClocklessChipset>::value == fl::Bus::STUB, |
| 38 | "Host default clockless bus should be STUB"); |
| 39 | FL_STATIC_ASSERT(fl::DefaultBus<fl::SpiChipsetConfig>::value == fl::Bus::STUB, |
| 40 | "Host default SPI bus should be STUB"); |
| 41 | |
| 42 | // Capability traits: BusSupports defaults to false_type for unknown pairs and is |
| 43 | // true_type for the stub clockless specialization. |
| 44 | FL_STATIC_ASSERT(fl::BusSupports<fl::Bus::STUB, fl::ClocklessChipset>::value, |
| 45 | "Stub bus must support clockless chipsets"); |
| 46 | FL_STATIC_ASSERT(!fl::BusSupports<fl::Bus::STUB, fl::SpiChipsetConfig>::value, |
| 47 | "Stub bus does not (yet) support SPI chipsets"); |
| 48 | FL_STATIC_ASSERT(!fl::BusSupports<fl::Bus::RMT, fl::SpiChipsetConfig>::value, |
| 49 | "Bus values without specializations must default to false_type"); |
| 50 | |
| 51 | FL_TEST_CASE("BusTraits<Bus::STUB>::instance returns a stable singleton") { |
| 52 | auto& a = fl::BusTraits<fl::Bus::STUB>::instance(); |
| 53 | auto& b = fl::BusTraits<fl::Bus::STUB>::instance(); |
| 54 | FL_CHECK(&a == &b); |
| 55 | } |
| 56 | |
| 57 | FL_TEST_CASE("BusTraits<Bus::STUB>::Driver implements IChannelDriver contract") { |
| 58 | using Driver = fl::BusTraits<fl::Bus::STUB>::Driver; |
| 59 | fl::IChannelDriver* iface = &fl::BusTraits<fl::Bus::STUB>::instance(); |
| 60 | FL_REQUIRE(iface != nullptr); |
| 61 | FL_CHECK(iface->getName() == fl::string::from_literal("STUB")); |
| 62 | FL_CHECK(iface->getCapabilities().supportsClockless); |
| 63 | FL_CHECK_FALSE(iface->getCapabilities().supportsSpi); |
| 64 | // Cast back to concrete type to exercise the alias. |
| 65 | Driver* concrete = static_cast<Driver*>(iface); |
| 66 | FL_CHECK(concrete != nullptr); |
| 67 | } |
| 68 | |
| 69 | FL_TEST_CASE("BusTraits<Bus::STUB>::instancePtr returns a non-null shared_ptr") { |
| 70 | auto p = fl::BusTraits<fl::Bus::STUB>::instancePtr(); |
| 71 | FL_REQUIRE(p != nullptr); |
| 72 | // instance() and *instancePtr() must reference the same object. |
| 73 | FL_CHECK(p.get() == &fl::BusTraits<fl::Bus::STUB>::instance()); |
| 74 | } |
| 75 | |
| 76 | FL_TEST_CASE("enableDrivers<Bus::STUB>() registers the stub driver with ChannelManager") { |
| 77 | // Snapshot driver count before; explicit enableDrivers should add (or |
| 78 | // replace, if the legacy auto-init already registered) by name. |
| 79 | auto& mgr = fl::ChannelManager::instance(); |
nothing calls this directly
no test coverage detected