31#include <boost/test/unit_test.hpp>
55 BOOST_CHECK( !variant.
GetDNP() );
58 BOOST_CHECK( variant.
GetFields().empty() );
66 BOOST_CHECK( variant.
GetDNP() );
87 BOOST_CHECK( board.
HasVariant(
"Production" ) );
96 BOOST_CHECK( board.
HasVariant(
"production" ) );
97 BOOST_CHECK( board.
HasVariant(
"PRODUCTION" ) );
98 BOOST_CHECK( board.
HasVariant(
"PrOdUcTiOn" ) );
139 prodVariant.
SetDNP(
false );
150 debugVariant.
SetDNP(
true );
229 prodVariant.
SetDNP(
true );
239 BOOST_CHECK( board.
HasVariant(
"production" ) );
240 BOOST_CHECK( board.
HasVariant(
"PRODUCTION" ) );
262 prodVariant.
SetDNP(
false );
285 prodVariant.
SetDNP(
false );
303 prodVariant.
SetDNP(
true );
311 BOOST_CHECK( copyVariant->
GetDNP() );
320 BOOST_CHECK( assignedVariant->
GetDNP() );
355 wxString variantToken = wxT(
"VARIANT" );
359 wxString descToken = wxT(
"VARIANT_DESC" );
364 wxString defaultToken = wxT(
"VARIANT" );
366 BOOST_CHECK( defaultToken.IsEmpty() );
373 "(export (version 1)\n"
377 " (footprint Resistor_SMD:R_0603_1608Metric)\n"
378 " (libsource (lib Device) (part R))\n"
380 " (variant (name Alt)\n"
381 " (property (name dnp) (value 1))\n"
382 " (property (name exclude_from_bom) (value 0))\n"
384 " (field (name Value) \"22K\")\n"
385 " (field (name Footprint) \"Resistor_SMD:R_0805_2012Metric\")\n"
399 BOOST_REQUIRE_EQUAL( parsedNetlist.
GetCount(), 1 );
406 BOOST_CHECK( variant->
m_dnp );
410 auto valueIt = variant->
m_fields.find(
"Value" );
411 BOOST_CHECK( valueIt != variant->
m_fields.end() );
414 auto fpIt = variant->
m_fields.find(
"Footprint" );
415 BOOST_CHECK( fpIt != variant->
m_fields.end() );
481 wxString unicodeValue = wxT(
"1kΩ ±5% 日本語" );
491 wxString specialChars = wxT(
"R<1K>\"test\"'value'" );
500 wxString unicodeDesc = wxT(
"Variante für Produktion — 测试" );
519 BOOST_CHECK( board.
HasVariant(
"Variant1" ) );
526 BOOST_CHECK( !board.
HasVariant(
"Variant1" ) );
527 BOOST_CHECK( board.
HasVariant(
"Variant2" ) );
549 BOOST_CHECK( !board.
HasVariant(
"OldName" ) );
574 BOOST_CHECK( names.GetCount() >= 4 );
577 BOOST_CHECK( !names[0].IsEmpty() );
580 bool foundAlpha =
false;
581 bool foundBeta =
false;
582 bool foundZebra =
false;
584 for(
size_t i = 1; i < names.GetCount(); i++ )
586 if( names[i] == wxT(
"Alpha" ) )
588 else if( names[i] == wxT(
"Beta" ) )
590 else if( names[i] == wxT(
"Zebra" ) )
594 BOOST_CHECK( foundAlpha );
595 BOOST_CHECK( foundBeta );
596 BOOST_CHECK( foundZebra );
673 LIB_ID fpid( wxT(
"Resistor_SMD" ), wxT(
"R_0805_2012Metric" ) );
674 wxString reference = wxT(
"R1" );
675 wxString value = wxT(
"10K" );
677 std::vector<KIID> kiids;
684 variantA.
m_dnp =
true;
690 variantA.
m_fields[wxT(
"Datasheet" )] = wxT(
"https://example.com/datasheet.pdf" );
695 variantB.
m_dnp =
false;
701 variantB.
m_fields[wxT(
"Value" )] = wxT(
"22K" );
705 for(
const auto& [variantName, componentVariant] : component.
GetVariants() )
710 if( componentVariant.m_hasDnp )
711 fpVariant->
SetDNP( componentVariant.m_dnp );
713 if( componentVariant.m_hasExcludedFromBOM )
716 if( componentVariant.m_hasExcludedFromPosFiles )
719 for(
const auto& [fieldName, fieldValue] : componentVariant.m_fields )
726 BOOST_CHECK( fpVariantA->
GetDNP() );
729 BOOST_CHECK( fpVariantA->
HasFieldValue( wxT(
"Datasheet" ) ) );
731 wxT(
"https://example.com/datasheet.pdf" ) );
736 BOOST_CHECK( !fpVariantB->
GetDNP() );
773 initialVariant.
SetDNP(
true );
779 LIB_ID fpid( wxT(
"Resistor_SMD" ), wxT(
"R_0805_2012Metric" ) );
781 std::vector<KIID> kiids;
782 COMPONENT component( fpid, wxT(
"R1" ), wxT(
"10K" ),
path, kiids );
785 partialVariant.
m_dnp =
true;
791 for(
const auto& [variantName, componentVariant] : component.
GetVariants() )
797 bool targetDnp = componentVariant.m_hasDnp ? componentVariant.m_dnp : fp.
IsDNP();
798 fpVariant->
SetDNP( targetDnp );
800 bool targetBOM = componentVariant.m_hasExcludedFromBOM
801 ? componentVariant.m_excludedFromBOM
805 bool targetPos = componentVariant.m_hasExcludedFromPosFiles
806 ? componentVariant.m_excludedFromPosFiles
830 variantWithAll.
m_dnp =
true;
838 BOOST_CHECK( variantWithAll.
m_hasDnp );
839 BOOST_CHECK( variantWithAll.
m_dnp );
847 variantPartial.
m_dnp =
true;
851 BOOST_CHECK( variantPartial.
m_hasDnp );
857 variantAllFalse.
m_dnp =
false;
864 BOOST_CHECK( variantAllFalse.
m_hasDnp );
865 BOOST_CHECK( !variantAllFalse.
m_dnp );
882 fp.
SetFPID(
LIB_ID( wxT(
"Resistor_SMD" ), wxT(
"R_0805" ) ) );
894 fpVariant->
SetDNP(
true );
917 fpVariant->
SetDNP( targetDnp );
923 "DNP should be reset to base value (false) when no explicit override" );
925 "ExcludedFromBOM should be reset to base value (false) when no override" );
927 "ExcludedFromPosFiles should be reset to base (false) when no override" );
947 std::unique_ptr<BOARD> board( pcbIo.
LoadBoard( dataPath,
nullptr ) );
956 for(
FOOTPRINT* fp : board->Footprints() )
958 if( fp->GetReference() == wxT(
"R2" ) )
960 wxString fpName = fp->GetFPID().GetLibItemName();
962 if( fpName.Contains( wxT(
"C_1210" ) ) )
964 else if( fpName.Contains( wxT(
"C_3640" ) ) )
971 BOOST_REQUIRE_MESSAGE( r2_c1210,
"Should find R2 with C_1210 footprint (variant footprint)" );
972 BOOST_REQUIRE_MESSAGE( r2_c3640,
"Should find R2 with C_3640 footprint (base footprint)" );
992 "C_1210 Variant A DNP should be false (no schematic override)" );
994 "C_1210 Variant A ExcludedFromBOM should be false (no override)" );
996 "C_1210 Variant A ExcludedFromPosFiles should be false (no override)" );
1013 if( c3640_variantA )
1023 "C_3640 Variant A DNP should be false (no schematic override)" );
1025 "C_3640 Variant A ExcludedFromBOM should be false (no override)" );
1027 "C_3640 Variant A ExcludedFromPosFiles should be false (no override)" );
1045 std::unique_ptr<BOARD> board( pcbIo.
LoadBoard( dataPath,
nullptr ) );
1050 BOOST_CHECK( board->HasVariant(
"Variant A" ) );
1059 for(
FOOTPRINT* fp : board->Footprints() )
1061 const wxString& ref = fp->GetReference();
1063 if( ref == wxT(
"R1" ) )
1070 BOOST_CHECK( variantA->
HasFieldValue( wxT(
"Datasheet" ) ) );
1074 else if( ref == wxT(
"R2" ) )
1079 wxString fpName = fp->GetFPID().GetLibItemName();
1081 if( fpName.Contains( wxT(
"C_3640" ) ) )
1087 BOOST_CHECK( !variantA->
GetDNP() );
1093 else if( ref == wxT(
"R3" ) )
1100 BOOST_CHECK( variantA->
GetDNP() );
1129 auto runExport = [&](
const wxString& aVariant,
bool aCsv ) -> std::string
1147 std::string defaultAscii = runExport( wxEmptyString,
false );
1148 BOOST_CHECK( defaultAscii.find(
"10K" ) != std::string::npos );
1149 BOOST_CHECK( defaultAscii.find(
"22K" ) == std::string::npos );
1151 std::string altPopAscii = runExport( wxS(
"AltPop" ),
false );
1152 BOOST_CHECK( altPopAscii.find(
"22K" ) != std::string::npos );
1153 BOOST_CHECK( altPopAscii.find(
"10K" ) == std::string::npos );
1156 std::string defaultCsv = runExport( wxEmptyString,
true );
1157 BOOST_CHECK( defaultCsv.find(
"10K" ) != std::string::npos );
1158 BOOST_CHECK( defaultCsv.find(
"22K" ) == std::string::npos );
1160 std::string altPopCsv = runExport( wxS(
"AltPop" ),
true );
1161 BOOST_CHECK( altPopCsv.find(
"22K" ) != std::string::npos );
1162 BOOST_CHECK( altPopCsv.find(
"10K" ) == std::string::npos );
1165 auto runReport = [&](
const wxString& aVariant ) -> std::string
1168 true,
true,
false,
false,
false );
1173 std::string defaultReport = runReport( wxEmptyString );
1174 BOOST_CHECK( defaultReport.find(
"10K" ) != std::string::npos );
1175 BOOST_CHECK( defaultReport.find(
"22K" ) == std::string::npos );
1177 std::string altPopReport = runReport( wxS(
"AltPop" ) );
1178 BOOST_CHECK( altPopReport.find(
"22K" ) != std::string::npos );
1179 BOOST_CHECK( altPopReport.find(
"10K" ) == std::string::npos );
1197 fp.
SetFPID(
LIB_ID( wxT(
"Capacitor_SMD" ), wxT(
"C_0805" ) ) );
1207 fpVariant->
SetDNP(
true );
1210 BOOST_CHECK( fp.
GetVariant(
"TestVariant" ) !=
nullptr );
1219 std::set<wxString> excessVariants;
1222 excessVariants.insert( variantName );
1227 BOOST_CHECK( excessVariants.count(
"TestVariant" ) == 1 );
1229 for(
const wxString& excess : excessVariants )
1233 "Stale variant must be removed when netlist has no variant data" );
1235 "All variants should be cleaned up" );
1248 fp.
SetFPID(
LIB_ID( wxT(
"Package_SO" ), wxT(
"SOIC-8" ) ) );
1257 prodVariant->
SetDNP(
true );
1267 std::set<wxString> excessVariants;
1270 excessVariants.insert( variantName );
1273 excessVariants.erase(
"Production" );
1276 BOOST_CHECK( excessVariants.count(
"Debug" ) == 1 );
1278 for(
const wxString& excess : excessVariants )
1282 "Production variant should be preserved (in netlist)" );
1284 "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.