27#include <boost/test/unit_test.hpp>
57 BOOST_CHECK( !variant.
GetDNP() );
61 BOOST_CHECK( variant.
GetFields().empty() );
70 BOOST_CHECK( variant.
GetDNP() );
92 BOOST_CHECK( board.
HasVariant(
"Production" ) );
101 BOOST_CHECK( board.
HasVariant(
"production" ) );
102 BOOST_CHECK( board.
HasVariant(
"PRODUCTION" ) );
103 BOOST_CHECK( board.
HasVariant(
"PrOdUcTiOn" ) );
144 prodVariant.
SetDNP(
false );
155 debugVariant.
SetDNP(
true );
176 prodVariant.
SetDNP(
true );
180 wxString token = wxS(
"DNP" );
184 token = wxS(
"DNP" );
188 token = wxS(
"EXCLUDE_FROM_SIM" );
192 token = wxS(
"EXCLUDE_FROM_SIM" );
300 prodVariant.
SetDNP(
true );
310 BOOST_CHECK( board.
HasVariant(
"production" ) );
311 BOOST_CHECK( board.
HasVariant(
"PRODUCTION" ) );
333 prodVariant.
SetDNP(
false );
356 prodVariant.
SetDNP(
false );
374 prodVariant.
SetDNP(
true );
383 BOOST_CHECK( copyVariant->
GetDNP() );
393 BOOST_CHECK( assignedVariant->
GetDNP() );
429 wxString variantToken = wxT(
"VARIANT" );
433 wxString descToken = wxT(
"VARIANT_DESC" );
438 wxString defaultToken = wxT(
"VARIANT" );
440 BOOST_CHECK( defaultToken.IsEmpty() );
447 "(export (version 1)\n"
451 " (footprint Resistor_SMD:R_0603_1608Metric)\n"
452 " (libsource (lib Device) (part R))\n"
454 " (variant (name Alt)\n"
455 " (property (name dnp) (value 1))\n"
456 " (property (name exclude_from_bom) (value 0))\n"
457 " (property (name exclude_from_sim) (value 1))\n"
459 " (field (name Value) \"22K\")\n"
460 " (field (name Footprint) \"Resistor_SMD:R_0805_2012Metric\")\n"
474 BOOST_REQUIRE_EQUAL( parsedNetlist.
GetCount(), 1 );
481 BOOST_CHECK( variant->
m_dnp );
487 auto valueIt = variant->
m_fields.find(
"Value" );
488 BOOST_CHECK( valueIt != variant->
m_fields.end() );
491 auto fpIt = variant->
m_fields.find(
"Footprint" );
492 BOOST_CHECK( fpIt != variant->
m_fields.end() );
558 wxString unicodeValue = wxT(
"1kΩ ±5% 日本語" );
568 wxString specialChars = wxT(
"R<1K>\"test\"'value'" );
577 wxString unicodeDesc = wxT(
"Variante für Produktion — 测试" );
596 BOOST_CHECK( board.
HasVariant(
"Variant1" ) );
603 BOOST_CHECK( !board.
HasVariant(
"Variant1" ) );
604 BOOST_CHECK( board.
HasVariant(
"Variant2" ) );
626 BOOST_CHECK( !board.
HasVariant(
"OldName" ) );
651 BOOST_CHECK( names.GetCount() >= 4 );
654 BOOST_CHECK( !names[0].IsEmpty() );
657 bool foundAlpha =
false;
658 bool foundBeta =
false;
659 bool foundZebra =
false;
661 for(
size_t i = 1; i < names.GetCount(); i++ )
663 if( names[i] == wxT(
"Alpha" ) )
665 else if( names[i] == wxT(
"Beta" ) )
667 else if( names[i] == wxT(
"Zebra" ) )
671 BOOST_CHECK( foundAlpha );
672 BOOST_CHECK( foundBeta );
673 BOOST_CHECK( foundZebra );
758 LIB_ID fpid( wxT(
"Resistor_SMD" ), wxT(
"R_0805_2012Metric" ) );
759 wxString reference = wxT(
"R1" );
760 wxString value = wxT(
"10K" );
762 std::vector<KIID> kiids;
769 variantA.
m_dnp =
true;
777 variantA.
m_fields[wxT(
"Datasheet" )] = wxT(
"https://example.com/datasheet.pdf" );
782 variantB.
m_dnp =
false;
790 variantB.
m_fields[wxT(
"Value" )] = wxT(
"22K" );
794 for(
const auto& [variantName, componentVariant] : component.
GetVariants() )
799 if( componentVariant.m_hasDnp )
800 fpVariant->
SetDNP( componentVariant.m_dnp );
802 if( componentVariant.m_hasExcludedFromBOM )
805 if( componentVariant.m_hasExcludedFromSim )
808 if( componentVariant.m_hasExcludedFromPosFiles )
811 for(
const auto& [fieldName, fieldValue] : componentVariant.m_fields )
818 BOOST_CHECK( fpVariantA->
GetDNP() );
822 BOOST_CHECK( fpVariantA->
HasFieldValue( wxT(
"Datasheet" ) ) );
824 wxT(
"https://example.com/datasheet.pdf" ) );
829 BOOST_CHECK( !fpVariantB->
GetDNP() );
870 initialVariant.
SetDNP(
true );
877 LIB_ID fpid( wxT(
"Resistor_SMD" ), wxT(
"R_0805_2012Metric" ) );
879 std::vector<KIID> kiids;
880 COMPONENT component( fpid, wxT(
"R1" ), wxT(
"10K" ),
path, kiids );
883 partialVariant.
m_dnp =
true;
889 for(
const auto& [variantName, componentVariant] : component.
GetVariants() )
895 bool targetDnp = componentVariant.m_hasDnp ? componentVariant.m_dnp : fp.
IsDNP();
896 fpVariant->
SetDNP( targetDnp );
898 bool targetBOM = componentVariant.m_hasExcludedFromBOM
899 ? componentVariant.m_excludedFromBOM
903 bool targetSim = componentVariant.m_hasExcludedFromSim
904 ? componentVariant.m_excludedFromSim
908 bool targetPos = componentVariant.m_hasExcludedFromPosFiles
909 ? componentVariant.m_excludedFromPosFiles
937 fp.
SetFPID(
LIB_ID( wxT(
"Resistor_SMD" ), wxT(
"R_0805" ) ) );
950 fpVariant->
SetDNP(
true );
977 fpVariant->
SetDNP( targetDnp );
984 "DNP should be reset to base value (false) when no explicit override" );
986 "ExcludedFromBOM should be reset to base value (false) when no override" );
988 "ExcludedFromSim should be reset to base value (false) when no override" );
990 "ExcludedFromPosFiles should be reset to base (false) when no override" );
1010 std::unique_ptr<BOARD> board = pcbIo.
LoadBoard( dataPath );
1019 for(
FOOTPRINT* fp : board->Footprints() )
1021 if( fp->GetReference() == wxT(
"R2" ) )
1023 wxString fpName = fp->GetFPID().GetLibItemName();
1025 if( fpName.Contains( wxT(
"C_1210" ) ) )
1027 else if( fpName.Contains( wxT(
"C_3640" ) ) )
1034 BOOST_REQUIRE_MESSAGE( r2_c1210,
"Should find R2 with C_1210 footprint (variant footprint)" );
1035 BOOST_REQUIRE_MESSAGE( r2_c3640,
"Should find R2 with C_3640 footprint (base footprint)" );
1046 if( c1210_variantA )
1054 BOOST_CHECK_MESSAGE( !c1210_variantA->
GetDNP(),
1055 "C_1210 Variant A DNP should be false (no schematic override)" );
1057 "C_1210 Variant A ExcludedFromBOM should be false (no override)" );
1059 "C_1210 Variant A ExcludedFromPosFiles should be false (no override)" );
1075 BOOST_REQUIRE_MESSAGE( c3640_variantA,
1076 "C_3640 must have Variant A data to hide it when Variant A is active" );
1084 BOOST_CHECK_MESSAGE( c3640_variantA->
GetDNP(),
1085 "C_3640 Variant A DNP should be true (it is not active for Variant A)" );
1097 std::unique_ptr<BOARD> board = pcbIo.
LoadBoard( dataPath );
1102 BOOST_CHECK( board->HasVariant(
"Variant A" ) );
1111 for(
FOOTPRINT* fp : board->Footprints() )
1113 const wxString& ref = fp->GetReference();
1115 if( ref == wxT(
"R1" ) )
1122 BOOST_CHECK( variantA->
HasFieldValue( wxT(
"Datasheet" ) ) );
1126 else if( ref == wxT(
"R2" ) )
1128 wxString fpName = fp->GetFPID().GetLibItemName();
1130 if( fpName.Contains( wxT(
"C_3640" ) ) )
1136 BOOST_CHECK( variantA->
GetDNP() );
1138 else if( fpName.Contains( wxT(
"C_1210" ) ) )
1143 BOOST_CHECK( fp->IsDNP() );
1146 BOOST_CHECK( !variantA->
GetDNP() );
1149 else if( ref == wxT(
"R3" ) )
1156 BOOST_CHECK( variantA->
GetDNP() );
1185 auto runExport = [&](
const wxString& aVariant,
bool aCsv ) -> std::string
1203 std::string defaultAscii = runExport( wxEmptyString,
false );
1204 BOOST_CHECK( defaultAscii.find(
"10K" ) != std::string::npos );
1205 BOOST_CHECK( defaultAscii.find(
"22K" ) == std::string::npos );
1207 std::string altPopAscii = runExport( wxS(
"AltPop" ),
false );
1208 BOOST_CHECK( altPopAscii.find(
"22K" ) != std::string::npos );
1209 BOOST_CHECK( altPopAscii.find(
"10K" ) == std::string::npos );
1212 std::string defaultCsv = runExport( wxEmptyString,
true );
1213 BOOST_CHECK( defaultCsv.find(
"10K" ) != std::string::npos );
1214 BOOST_CHECK( defaultCsv.find(
"22K" ) == std::string::npos );
1216 std::string altPopCsv = runExport( wxS(
"AltPop" ),
true );
1217 BOOST_CHECK( altPopCsv.find(
"22K" ) != std::string::npos );
1218 BOOST_CHECK( altPopCsv.find(
"10K" ) == std::string::npos );
1221 auto runReport = [&](
const wxString& aVariant ) -> std::string
1224 true,
true,
false,
false,
false );
1229 std::string defaultReport = runReport( wxEmptyString );
1230 BOOST_CHECK( defaultReport.find(
"10K" ) != std::string::npos );
1231 BOOST_CHECK( defaultReport.find(
"22K" ) == std::string::npos );
1233 std::string altPopReport = runReport( wxS(
"AltPop" ) );
1234 BOOST_CHECK( altPopReport.find(
"22K" ) != std::string::npos );
1235 BOOST_CHECK( altPopReport.find(
"10K" ) == std::string::npos );
1253 fp.
SetFPID(
LIB_ID( wxT(
"Capacitor_SMD" ), wxT(
"C_0805" ) ) );
1263 fpVariant->
SetDNP(
true );
1266 BOOST_CHECK( fp.
GetVariant(
"TestVariant" ) !=
nullptr );
1275 std::set<wxString> excessVariants;
1278 excessVariants.insert( variantName );
1283 BOOST_CHECK( excessVariants.count(
"TestVariant" ) == 1 );
1285 for(
const wxString& excess : excessVariants )
1288 BOOST_CHECK_MESSAGE( fp.
GetVariant(
"TestVariant" ) ==
nullptr,
1289 "Stale variant must be removed when netlist has no variant data" );
1291 "All variants should be cleaned up" );
1304 fp.
SetFPID(
LIB_ID( wxT(
"Package_SO" ), wxT(
"SOIC-8" ) ) );
1313 prodVariant->
SetDNP(
true );
1323 std::set<wxString> excessVariants;
1326 excessVariants.insert( variantName );
1329 excessVariants.erase(
"Production" );
1332 BOOST_CHECK( excessVariants.count(
"Debug" ) == 1 );
1334 for(
const wxString& excess : excessVariants )
1337 BOOST_CHECK_MESSAGE( fp.
GetVariant(
"Production" ) !=
nullptr,
1338 "Production variant should be preserved (in netlist)" );
1339 BOOST_CHECK_MESSAGE( fp.
GetVariant(
"Debug" ) ==
nullptr,
1340 "Debug variant should be removed (not in netlist)" );
1364 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
1365 board->SetProject( &settingsManager.
Prj() );
1366 board->AddVariant(
"Variant A" );
1369 BOOST_REQUIRE_EQUAL( baseFpid.
Parse( wxS(
"TestLib:C_3640" ) ), -1 );
1372 BOOST_REQUIRE_EQUAL( variantFpid.
Parse( wxS(
"TestLib:C_1210" ) ), -1 );
1379 board->Add( baseFp );
1383 variantFp->
SetFPID( variantFpid );
1384 board->Add( variantFp );
1390 netlist.AddVariant(
"Variant A" );
1393 std::vector<KIID>{
KIID() } );
1397 variantA.m_dnp =
false;
1398 variantA.m_hasDnp =
true;
1400 netlist.AddComponent( component );
1403 toolMgr.
SetEnvironment( board.get(),
nullptr,
nullptr,
nullptr,
nullptr );
1416 "Base FP must be visible in the default variant" );
1418 "Variant A FP must be hidden in the default variant (globally DNP)" );
1423 "Variant A FP must be visible when Variant A is active" );
1425 "Base FP must be hidden when Variant A is active (issue #23298)" );
General utilities for PCB file IO for QA programs.
Update the BOARD with a new netlist.
bool UpdateNetlist(NETLIST &aNetlist)
Update the board's components according to the new netlist.
void SetWillDrag(bool aWillDrag)
void SetIsDryRun(bool aEnabled)
Enable dry run mode (just report, no changes to PCB).
void SetDeleteUnusedFootprints(bool aEnabled)
void SetReplaceFootprints(bool aEnabled)
Information pertinent to a Pcbnew printed circuit board.
void SetCurrentVariant(const wxString &aVariant)
const std::vector< wxString > & GetVariantNames() const
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
wxArrayString GetVariantNamesForUI() const
Return the variant names for UI display.
void DeleteVariant(const wxString &aVariantName)
bool ResolveTextVar(wxString *token, int aDepth) const
bool HasVariant(const wxString &aVariantName) const
void AddVariant(const wxString &aVariantName)
wxString GetVariantDescription(const wxString &aVariantName) const
wxString GetCurrentVariant() const
void RenameVariant(const wxString &aOldName, const wxString &aNewName)
void SetVariantDescription(const wxString &aVariantName, const wxString &aDescription)
Store all of the related component information found in a netlist.
void AddVariant(const COMPONENT_VARIANT &aVariant)
const COMPONENT_VARIANT * GetVariant(const wxString &aVariantName) const
const CASE_INSENSITIVE_MAP< COMPONENT_VARIANT > & GetVariants() const
The parser for reading the KiCad s-expression netlist format.
void Parse()
Function Parse parse the full netlist.
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Store information read from a netlist along with the flags used to update the NETLIST in the BOARD.
unsigned GetCount() const
COMPONENT * GetComponent(unsigned aIndex)
Return the COMPONENT at aIndex.
wxString GetShownText(RESOLUTION_CONTEXT aContext, int aDepth=0) const override
Return the string actually shown after processing of the base text.
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
A PCB_IO derivation for saving and loading Pcbnew s-expression formatted files.
std::unique_ptr< BOARD > LoadBoard(const wxString &aFileName, const std::map< std::string, UTF8 > *aProperties=nullptr, PROJECT *aProject=nullptr)
Load information from some input file format that this PCB_IO implementation knows about into new BOA...
The ASCII format of the kicad place file is:
std::string GenPositionData()
build a string filled with the position data
void SetVariant(const wxString &aVariant)
Set the variant name for variant-aware export.
std::string GenReportData()
build a string filled with the pad report data This report does not used options aForceSmdItems,...
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Load a project or sets up a new project with a specified path.
PROJECT & Prj() const
A helper while we are not MDI-capable – return the one and only project.
Is a LINE_READER that reads from a multiline 8 bit wide std::string.
std::string GetPcbnewTestDataDir()
Utility which returns a path to the data directory where the test board files are stored.
bool m_excludedFromPosFiles
bool m_hasExcludedFromBOM
bool m_hasExcludedFromSim
bool m_hasExcludedFromPosFiles
nlohmann::ordered_map< wxString, wxString > m_fields
wxString GetDefaultFieldName(FIELD_T aFieldId, TRANSLATION aTranslation)
Return a default symbol field name for a mandatory field type.
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")
BOOST_CHECK_EQUAL(result, "25.4")
BOOST_AUTO_TEST_CASE(FootprintVariantBasics)
Test FOOTPRINT_VARIANT class basic operations.