#include #include "core/app/verify.hpp" #include "core/domain/connect.hpp" #include "core/domain/modules.hpp" #include "core/domain/parts.hpp" #include "core/domain/pins.hpp" #include "core/domain/signals.hpp" #include "core/domain/system.hpp" // app::verify is pure core: it takes a System* and returns a VerifyReport of // structured findings, with no Print/dialog/FTXUI. These tests build small // systems by hand and assert the report — no UI involved. TEST_CASE("verify on a null or empty system reports nothing") { app::VerifyReport none = app::verify(nullptr); CHECK(none.typed_pins == 0); CHECK(none.total_nets == 0); CHECK(none.role_mismatches.empty()); System sys; app::VerifyReport r = app::verify(&sys); CHECK(r.typed_pins == 0); CHECK(r.total_nets == 0); CHECK(r.bridged_nets == 0); CHECK(r.net_inconsistencies.empty()); CHECK(r.orphan_total() == 0); CHECK(r.model_total() == 0); } TEST_CASE("verify flags a bridged net that mixes Power and GndShield") { // Two cards, one wired pin pair: A.NETA (Power) <-> B.NETB (GndShield). System sys; Module *a = sys.modules()->merge("A"); Module *b = sys.modules()->merge("B"); Part *ja = new Part("J1"); a->add(ja); Part *jb = new Part("P1"); b->add(jb); Pin *pa = new Pin("1"); ja->add(pa); Pin *pb = new Pin("1"); jb->add(pb); Signal *sa = a->signals->merge("NETA"); sa->type = SignalType::Power; Signal *sb = b->signals->merge("NETB"); sb->type = SignalType::GndShield; sa->add(pa); pa->connect(sa); sb->add(pb); pb->connect(sb); Connection *c = new Connection("A.J1<->B.P1", a, ja, b, jb); c->transform_name = "identity"; c->pin_map.emplace_back(pa, pb); sys.connections()->add(c); app::VerifyReport r = app::verify(&sys); CHECK(r.total_nets == 1); CHECK(r.bridged_nets == 1); REQUIRE(r.net_inconsistencies.size() == 1); CHECK(r.net_inconsistencies[0].members.size() == 2); // Both endpoints are present with their declared types. bool seen_power = false, seen_gnd = false; for (const auto &m : r.net_inconsistencies[0].members) { if (m.type == SignalType::Power) seen_power = true; if (m.type == SignalType::GndShield) seen_gnd = true; } CHECK(seen_power); CHECK(seen_gnd); } TEST_CASE("verify counts orphan pins by their import origin") { System sys; Module *m = sys.modules()->merge("M"); Part *p = new Part("J1"); m->add(p); Pin *imp = new Pin("1"); imp->nc_origin = NcOrigin::ImportedUnconnected; p->add(imp); Pin *drp = new Pin("2"); drp->nc_origin = NcOrigin::DroppedSingleton; p->add(drp); Pin *wired = new Pin("3"); p->add(wired); Signal *s = m->signals->merge("NET"); s->add(wired); wired->connect(s); app::VerifyReport r = app::verify(&sys); CHECK(r.orphan_imported == 1); CHECK(r.orphan_dropped == 1); CHECK(r.orphan_total() == 2); // Per-pin detail carries the path and origin (the dashboard lists the // dropped ones under the NC health row). REQUIRE(r.orphans.size() == 2); int n_dropped = 0; bool dropped_path_ok = false; for (const auto &o : r.orphans) { if (o.dropped) { ++n_dropped; if (o.module == "M" && o.part == "J1" && o.pin == "2") dropped_path_ok = true; } } CHECK(n_dropped == 1); CHECK(dropped_path_ok); }