27#include <boost/test/unit_test.hpp>
51 BOOST_CHECK( !variant.
GetDNP() );
54 BOOST_CHECK( variant.
GetFields().empty() );
62 BOOST_CHECK( variant.
GetDNP() );
83 BOOST_CHECK( board.
HasVariant(
"Production" ) );
92 BOOST_CHECK( board.
HasVariant(
"production" ) );
93 BOOST_CHECK( board.
HasVariant(
"PRODUCTION" ) );
94 BOOST_CHECK( board.
HasVariant(
"PrOdUcTiOn" ) );
135 prodVariant.
SetDNP(
false );
146 debugVariant.
SetDNP(
true );
225 prodVariant.
SetDNP(
true );
235 BOOST_CHECK( board.
HasVariant(
"production" ) );
236 BOOST_CHECK( board.
HasVariant(
"PRODUCTION" ) );
258 prodVariant.
SetDNP(
false );
281 prodVariant.
SetDNP(
false );
299 prodVariant.
SetDNP(
true );
307 BOOST_CHECK( copyVariant->
GetDNP() );
316 BOOST_CHECK( assignedVariant->
GetDNP() );
351 wxString variantToken = wxT(
"VARIANT" );
355 wxString descToken = wxT(
"VARIANT_DESC" );
360 wxString defaultToken = wxT(
"VARIANT" );
362 BOOST_CHECK( defaultToken.IsEmpty() );
369 "(export (version 1)\n"
373 " (footprint Resistor_SMD:R_0603_1608Metric)\n"
374 " (libsource (lib Device) (part R))\n"
376 " (variant (name Alt)\n"
377 " (property (name dnp) (value 1))\n"
378 " (property (name exclude_from_bom) (value 0))\n"
380 " (field (name Value) \"22K\")\n"
381 " (field (name Footprint) \"Resistor_SMD:R_0805_2012Metric\")\n"
395 BOOST_REQUIRE_EQUAL( parsedNetlist.
GetCount(), 1 );
402 BOOST_CHECK( variant->
m_dnp );
406 auto valueIt = variant->
m_fields.find(
"Value" );
407 BOOST_CHECK( valueIt != variant->
m_fields.end() );
410 auto fpIt = variant->
m_fields.find(
"Footprint" );
411 BOOST_CHECK( fpIt != variant->
m_fields.end() );
477 wxString unicodeValue = wxT(
"1kΩ ±5% 日本語" );
487 wxString specialChars = wxT(
"R<1K>\"test\"'value'" );
496 wxString unicodeDesc = wxT(
"Variante für Produktion — 测试" );
515 BOOST_CHECK( board.
HasVariant(
"Variant1" ) );
522 BOOST_CHECK( !board.
HasVariant(
"Variant1" ) );
523 BOOST_CHECK( board.
HasVariant(
"Variant2" ) );
545 BOOST_CHECK( !board.
HasVariant(
"OldName" ) );
570 BOOST_CHECK( names.GetCount() >= 4 );
573 BOOST_CHECK( !names[0].IsEmpty() );
576 bool foundAlpha =
false;
577 bool foundBeta =
false;
578 bool foundZebra =
false;
580 for(
size_t i = 1; i < names.GetCount(); i++ )
582 if( names[i] == wxT(
"Alpha" ) )
584 else if( names[i] == wxT(
"Beta" ) )
586 else if( names[i] == wxT(
"Zebra" ) )
590 BOOST_CHECK( foundAlpha );
591 BOOST_CHECK( foundBeta );
592 BOOST_CHECK( foundZebra );
669 LIB_ID fpid( wxT(
"Resistor_SMD" ), wxT(
"R_0805_2012Metric" ) );
670 wxString reference = wxT(
"R1" );
671 wxString value = wxT(
"10K" );
673 std::vector<KIID> kiids;
680 variantA.
m_dnp =
true;
686 variantA.
m_fields[wxT(
"Datasheet" )] = wxT(
"https://example.com/datasheet.pdf" );
691 variantB.
m_dnp =
false;
697 variantB.
m_fields[wxT(
"Value" )] = wxT(
"22K" );
701 for(
const auto& [variantName, componentVariant] : component.
GetVariants() )
706 if( componentVariant.m_hasDnp )
707 fpVariant->
SetDNP( componentVariant.m_dnp );
709 if( componentVariant.m_hasExcludedFromBOM )
712 if( componentVariant.m_hasExcludedFromPosFiles )
715 for(
const auto& [fieldName, fieldValue] : componentVariant.m_fields )
722 BOOST_CHECK( fpVariantA->
GetDNP() );
725 BOOST_CHECK( fpVariantA->
HasFieldValue( wxT(
"Datasheet" ) ) );
727 wxT(
"https://example.com/datasheet.pdf" ) );
732 BOOST_CHECK( !fpVariantB->
GetDNP() );
769 initialVariant.
SetDNP(
true );
775 LIB_ID fpid( wxT(
"Resistor_SMD" ), wxT(
"R_0805_2012Metric" ) );
777 std::vector<KIID> kiids;
778 COMPONENT component( fpid, wxT(
"R1" ), wxT(
"10K" ),
path, kiids );
781 partialVariant.
m_dnp =
true;
787 for(
const auto& [variantName, componentVariant] : component.
GetVariants() )
793 bool targetDnp = componentVariant.m_hasDnp ? componentVariant.m_dnp : fp.
IsDNP();
794 fpVariant->
SetDNP( targetDnp );
796 bool targetBOM = componentVariant.m_hasExcludedFromBOM
797 ? componentVariant.m_excludedFromBOM
801 bool targetPos = componentVariant.m_hasExcludedFromPosFiles
802 ? componentVariant.m_excludedFromPosFiles
826 variantWithAll.
m_dnp =
true;
834 BOOST_CHECK( variantWithAll.
m_hasDnp );
835 BOOST_CHECK( variantWithAll.
m_dnp );
843 variantPartial.
m_dnp =
true;
847 BOOST_CHECK( variantPartial.
m_hasDnp );
853 variantAllFalse.
m_dnp =
false;
860 BOOST_CHECK( variantAllFalse.
m_hasDnp );
861 BOOST_CHECK( !variantAllFalse.
m_dnp );
878 fp.
SetFPID(
LIB_ID( wxT(
"Resistor_SMD" ), wxT(
"R_0805" ) ) );
890 fpVariant->
SetDNP(
true );
913 fpVariant->
SetDNP( targetDnp );
919 "DNP should be reset to base value (false) when no explicit override" );
921 "ExcludedFromBOM should be reset to base value (false) when no override" );
923 "ExcludedFromPosFiles should be reset to base (false) when no override" );
943 std::unique_ptr<BOARD> board( pcbIo.
LoadBoard( dataPath,
nullptr ) );
952 for(
FOOTPRINT* fp : board->Footprints() )
954 if( fp->GetReference() == wxT(
"R2" ) )
956 wxString fpName = fp->GetFPID().GetLibItemName();
958 if( fpName.Contains( wxT(
"C_1210" ) ) )
960 else if( fpName.Contains( wxT(
"C_3640" ) ) )
967 BOOST_REQUIRE_MESSAGE( r2_c1210,
"Should find R2 with C_1210 footprint (variant footprint)" );
968 BOOST_REQUIRE_MESSAGE( r2_c3640,
"Should find R2 with C_3640 footprint (base footprint)" );
988 "C_1210 Variant A DNP should be false (no schematic override)" );
990 "C_1210 Variant A ExcludedFromBOM should be false (no override)" );
992 "C_1210 Variant A ExcludedFromPosFiles should be false (no override)" );
1009 if( c3640_variantA )
1019 "C_3640 Variant A DNP should be false (no schematic override)" );
1021 "C_3640 Variant A ExcludedFromBOM should be false (no override)" );
1023 "C_3640 Variant A ExcludedFromPosFiles should be false (no override)" );
1041 std::unique_ptr<BOARD> board( pcbIo.
LoadBoard( dataPath,
nullptr ) );
1046 BOOST_CHECK( board->HasVariant(
"Variant A" ) );
1055 for(
FOOTPRINT* fp : board->Footprints() )
1057 const wxString& ref = fp->GetReference();
1059 if( ref == wxT(
"R1" ) )
1066 BOOST_CHECK( variantA->
HasFieldValue( wxT(
"Datasheet" ) ) );
1070 else if( ref == wxT(
"R2" ) )
1075 wxString fpName = fp->GetFPID().GetLibItemName();
1077 if( fpName.Contains( wxT(
"C_3640" ) ) )
1083 BOOST_CHECK( !variantA->
GetDNP() );
1089 else if( ref == wxT(
"R3" ) )
1096 BOOST_CHECK( variantA->
GetDNP() );
1125 auto runExport = [&](
const wxString& aVariant,
bool aCsv ) -> std::string
1143 std::string defaultAscii = runExport( wxEmptyString,
false );
1144 BOOST_CHECK( defaultAscii.find(
"10K" ) != std::string::npos );
1145 BOOST_CHECK( defaultAscii.find(
"22K" ) == std::string::npos );
1147 std::string altPopAscii = runExport( wxS(
"AltPop" ),
false );
1148 BOOST_CHECK( altPopAscii.find(
"22K" ) != std::string::npos );
1149 BOOST_CHECK( altPopAscii.find(
"10K" ) == std::string::npos );
1152 std::string defaultCsv = runExport( wxEmptyString,
true );
1153 BOOST_CHECK( defaultCsv.find(
"10K" ) != std::string::npos );
1154 BOOST_CHECK( defaultCsv.find(
"22K" ) == std::string::npos );
1156 std::string altPopCsv = runExport( wxS(
"AltPop" ),
true );
1157 BOOST_CHECK( altPopCsv.find(
"22K" ) != std::string::npos );
1158 BOOST_CHECK( altPopCsv.find(
"10K" ) == std::string::npos );
1161 auto runReport = [&](
const wxString& aVariant ) -> std::string
1164 true,
true,
false,
false,
false );
1169 std::string defaultReport = runReport( wxEmptyString );
1170 BOOST_CHECK( defaultReport.find(
"10K" ) != std::string::npos );
1171 BOOST_CHECK( defaultReport.find(
"22K" ) == std::string::npos );
1173 std::string altPopReport = runReport( wxS(
"AltPop" ) );
1174 BOOST_CHECK( altPopReport.find(
"22K" ) != std::string::npos );
1175 BOOST_CHECK( altPopReport.find(
"10K" ) == std::string::npos );
1193 fp.
SetFPID(
LIB_ID( wxT(
"Capacitor_SMD" ), wxT(
"C_0805" ) ) );
1203 fpVariant->
SetDNP(
true );
1206 BOOST_CHECK( fp.
GetVariant(
"TestVariant" ) !=
nullptr );
1215 std::set<wxString> excessVariants;
1218 excessVariants.insert( variantName );
1223 BOOST_CHECK( excessVariants.count(
"TestVariant" ) == 1 );
1225 for(
const wxString& excess : excessVariants )
1229 "Stale variant must be removed when netlist has no variant data" );
1231 "All variants should be cleaned up" );
1244 fp.
SetFPID(
LIB_ID( wxT(
"Package_SO" ), wxT(
"SOIC-8" ) ) );
1253 prodVariant->
SetDNP(
true );
1263 std::set<wxString> excessVariants;
1266 excessVariants.insert( variantName );
1269 excessVariants.erase(
"Production" );
1272 BOOST_CHECK( excessVariants.count(
"Debug" ) == 1 );
1274 for(
const wxString& excess : excessVariants )
1278 "Production variant should be preserved (in netlist)" );
1280 "Debug variant should be removed (not in netlist)" );
General utilities for PCB file IO for QA programs.
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.
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(bool aAllowExtraText, 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 #PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
BOARD * LoadBoard(const wxString &aFileName, BOARD *aAppendToMe, const std::map< std::string, UTF8 > *aProperties=nullptr, PROJECT *aProject=nullptr) override
Load information from some input file format that this PCB_IO implementation knows about into either ...
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,...
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_hasExcludedFromPosFiles
nlohmann::ordered_map< wxString, wxString > m_fields
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_CHECK_MESSAGE(totalMismatches==0, std::to_string(totalMismatches)+" board(s) with strategy disagreements")
BOOST_TEST_MESSAGE("\n=== Real-World Polygon PIP Benchmark ===\n"<< formatTable(table))
BOOST_CHECK_EQUAL(result, "25.4")
BOOST_AUTO_TEST_CASE(FootprintVariantBasics)
Test FOOTPRINT_VARIANT class basic operations.