#include #include "system/parts.hpp" #include "system/pin_model.hpp" #include "system/pin_spec.hpp" #include "system/pins.hpp" #include #include namespace { // A stand-in PinModel: knows VCC (power) and CLK (clock input), has a 3-pin // canonical layout, and says nothing about anything else. struct FakeModel : PinModel { PinSpec spec_for(const std::string &name) const override { PinSpec s; if (name == "VCC") { s.function = PinFunction::Power; s.direction = PinDirection::Power; s.source = SpecSource::Bsdl; } else if (name == "CLK") { s.function = PinFunction::Clock; s.direction = PinDirection::In; s.source = SpecSource::Bsdl; } return s; // else default: source == None } std::vector layout() const override { return {"VCC", "CLK", "GND"}; } SpecSource source() const override { return SpecSource::Bsdl; } }; } // namespace TEST_CASE("apply_model materialises layout pins and sets specs where the model speaks") { Part part("U1"); part.add(new Pin("VCC")); // already present; CLK and GND are not FakeModel m; ApplyReport r = apply_model(&part, m); // CLK and GND materialised from layout(); VCC was already there. CHECK(r.materialised == 2); CHECK(part.exists("CLK")); CHECK(part.exists("GND")); CHECK(r.pins_total == 3); // Specs set only where the model speaks (VCC, CLK), not GND. CHECK(part.get("VCC")->spec.function == PinFunction::Power); CHECK(part.get("VCC")->spec.source == SpecSource::Bsdl); CHECK(part.get("CLK")->spec.function == PinFunction::Clock); CHECK(part.get("GND")->spec.source == SpecSource::None); CHECK(r.set == 2); } TEST_CASE("apply_model does not overwrite a spec the model is silent about") { Part part("U2"); Pin *p = new Pin("DATA"); p->spec.function = PinFunction::Signal; p->spec.source = SpecSource::Bsdl; // a prior model wrote this part.add(p); FakeModel m; // says nothing about DATA apply_model(&part, m); CHECK(part.get("DATA")->spec.function == PinFunction::Signal); CHECK(part.get("DATA")->spec.source == SpecSource::Bsdl); } TEST_CASE("apply_model never overwrites a higher-precedence source") { Part part("U3"); Pin *p = new Pin("VCC"); p->spec.function = PinFunction::Ground; // user-set, deliberately != the model p->spec.source = SpecSource::UserOverride; part.add(p); FakeModel m; // would set VCC = Power / Bsdl apply_model(&part, m); // UserOverride (rank 5) outranks Bsdl (rank 4): kept untouched. CHECK(part.get("VCC")->spec.source == SpecSource::UserOverride); CHECK(part.get("VCC")->spec.function == PinFunction::Ground); }