#include #include "core/app/load.hpp" #include "core/domain/modules.hpp" #include "core/domain/system.hpp" #include #include #include // app::load_module is pure core: import a module, drop singleton signals, infer // signal types, return counts or an error — no Print/dialog/FTXUI. The parse // helper import_type_from_name is likewise UI-free. TEST_CASE("import_type_from_name maps names case-insensitively") { ImportType t; CHECK(app::import_type_from_name("mentor", t)); CHECK(t == ImportType::IMPORT_MENTOR); CHECK(app::import_type_from_name("ALTIUM", t)); CHECK(t == ImportType::IMPORT_ALTIUM); CHECK(app::import_type_from_name("Ods", t)); CHECK(t == ImportType::IMPORT_ODS); CHECK_FALSE(app::import_type_from_name("kicad", t)); CHECK_FALSE(app::import_type_from_name("", t)); } TEST_CASE("load_module imports, drops singletons and reports counts") { // Minimal Mentor netlist: two parts; NETA/NETB span both parts (2 pins // each, kept), LONELY sits on one pin only (dropped as a singleton). const char *path = "test_load_in.net"; { std::ofstream f(path); f << "COMP: 'C1' 'J1'\n" " Explicit Pin: '1' 'x' 'NETA'\n" " Explicit Pin: '2' 'x' 'NETB'\n" " Explicit Pin: '3' 'x' 'LONELY'\n" "COMP: 'C2' 'J2'\n" " Explicit Pin: '1' 'x' 'NETA'\n" " Explicit Pin: '2' 'x' 'NETB'\n"; } System sys; app::LoadResult r = app::load_module(&sys, "M", path, ImportType::IMPORT_MENTOR); CHECK(r.ok); CHECK(r.error.empty()); CHECK(r.parts == 2); CHECK(r.signals == 2); // NETA, NETB — LONELY dropped CHECK(r.dropped == 1); // LONELY std::remove(path); } TEST_CASE("load_module fails cleanly on a missing file") { // ImportBase opens read-only and System::Load checks is_open(), so a missing // file is a clean error — and no empty module is left in the system. System sys; app::LoadResult r = app::load_module( &sys, "M", "/nonexistent-dir-xyz/nope.net", ImportType::IMPORT_MENTOR); CHECK_FALSE(r.ok); CHECK(r.error.find("cannot open") != std::string::npos); CHECK(sys.modules()->size() == 0); }