75 +
"plugins/altium/eDP_adapter_dvt1_source/eDP_adapter_dvt1.PcbDoc";
77 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
80 m_altiumPlugin.LoadBoard( dataPath, board.get(),
nullptr );
85 BOOST_CHECK( board->GetNetCount() > 0 );
86 BOOST_CHECK( board->Footprints().size() > 0 );
94 std::string dataPath =
97 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
98 m_altiumPlugin.LoadBoard( dataPath, board.get(),
nullptr );
101 BOOST_REQUIRE_GT( board->Footprints().size(), 0 );
103 std::vector<FOOTPRINT*> cached = m_altiumPlugin.GetImportedCachedLibraryFootprints();
106 std::vector<std::unique_ptr<FOOTPRINT>> owned;
109 owned.emplace_back( fp );
113 std::set<FOOTPRINT*> boardFootprints( board->Footprints().begin(), board->Footprints().end() );
118 BOOST_CHECK_MESSAGE( boardFootprints.count( fp ) == 0,
119 "GetImportedCachedLibraryFootprints returned a board-owned footprint" );
136 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
138 m_altiumPlugin.LoadBoard( dataPath, board.get(),
nullptr );
143 std::shared_ptr<NET_SETTINGS> netSettings = board->GetDesignSettings().m_NetSettings;
148 auto& patternAssignments = netSettings->GetNetclassPatternAssignments();
151 BOOST_REQUIRE_MESSAGE( patternAssignments.size() > 0,
152 "Test file must have netclass pattern assignments" );
156 bool foundAssignedNet =
false;
160 if( net->GetNetCode() <= 0 )
164 NETCLASS* directNetclass = net->GetNetClass();
167 std::shared_ptr<NETCLASS> effectiveNetclass =
168 netSettings->GetEffectiveNetClass( net->GetNetname() );
175 directNetclass !=
nullptr,
176 wxString::Format(
"Net '%s' should have a direct netclass assignment",
177 net->GetNetname() ) );
181 foundAssignedNet =
true;
187 wxString::Format(
"Net '%s' should not have default netclass, "
188 "expected effective class or component",
189 net->GetNetname() ) );
195 BOOST_CHECK_MESSAGE( foundAssignedNet,
196 "At least one net should have a non-default netclass assigned" );
206 const std::string& aRelativePath )
210 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
211 aPlugin.
LoadBoard( dataPath, board.get(),
nullptr );
215 int fillZoneCount = 0;
216 int fillZonesWithClearance = 0;
218 for(
ZONE* zone : board->Zones() )
220 if( !zone->IsOnCopperLayer() || zone->GetIsRuleArea() || zone->IsTeardropArea() )
225 if( zone->GetLocalClearance().has_value() && zone->GetLocalClearance().value() > 0 )
226 fillZonesWithClearance++;
229 BOOST_CHECK_GT( fillZoneCount, 0 );
231 BOOST_CHECK_MESSAGE( fillZonesWithClearance == fillZoneCount,
232 wxString::Format(
"%s: %d/%d copper fill zones have clearance set",
233 aRelativePath, fillZonesWithClearance,
241 m_altiumPlugin,
"plugins/altium/eDP_adapter_dvt1_source/eDP_adapter_dvt1.PcbDoc" );
248 "plugins/altium/HiFive/HiFive1.B01.PcbDoc" );
293 auto makeRule = [](
int aPriority,
const wxString& aScope1,
const wxString& aScope2,
305 std::vector<ARULE6> rules = {
306 makeRule( 1, wxT(
"InPolygon And InNet('GND')" ), wxT(
"All" ), 100 ),
307 makeRule( 2, wxT(
"InPolygon" ), wxT(
"All" ), 200 ),
308 makeRule( 3, wxT(
"All" ), wxT(
"All" ), 300 ),
309 makeRule( 4, wxT(
"All" ), wxT(
"All" ), 400 ),
317 rules.erase( rules.begin() );
323 rules.erase( rules.begin() );
343 +
"plugins/altium/issue24456/Fastino_Ground_Isolator.PcbDoc";
345 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
347 m_altiumPlugin.LoadBoard( dataPath, board.get(),
nullptr );
352 int frontExposed = 0;
355 for(
PCB_TRACK* track : board->Tracks() )
370 BOOST_REQUIRE_GT( viaCount, 0 );
374 BOOST_CHECK_MESSAGE( frontExposed == 0,
375 wxString::Format(
"%d of %d vias left front-exposed despite a "
376 "hole-referenced mask",
377 frontExposed, viaCount ) );
378 BOOST_CHECK_MESSAGE( backExposed == 0,
379 wxString::Format(
"%d of %d vias left back-exposed despite a "
380 "hole-referenced mask",
381 backExposed, viaCount ) );
386 const uint32_t holeSize = 300000;
387 const int landWidth = 600000;
390 holeSize, 500000, landWidth ) );
392 holeSize, 30000, landWidth ) );
394 holeSize, 0, landWidth ) );
398 holeSize, 30000, landWidth ) );
412 +
"plugins/altium/issue24456/Fastino_Ground_Isolator.PcbDoc";
414 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
416 m_altiumPlugin.LoadBoard( dataPath, board.get(),
nullptr );
420 const BOARD_STACKUP& stackup = board->GetDesignSettings().GetStackupDescriptor();
422 int dielectricCount = 0;
423 int dielectricWithTangent = 0;
430 for(
int sub = 0; sub < item->GetSublayersCount(); sub++ )
433 if( item->GetThickness( sub ) <= 0 )
438 double tangent = item->GetLossTangent( sub );
442 dielectricWithTangent++;
445 BOOST_CHECK_CLOSE( tangent, 0.020, 1e-6 );
450 BOOST_REQUIRE_GT( dielectricCount, 0 );
454 BOOST_CHECK_MESSAGE( dielectricWithTangent == dielectricCount,
455 wxString::Format(
"Only %d of %d dielectric sublayers received a loss "
456 "tangent from the Altium stackup",
457 dielectricWithTangent, dielectricCount ) );
470 std::string pcbDoc = dataDir +
"Fastino_Ground_Isolator.PcbDoc";
471 std::string prjPcb = dataDir +
"Fastino_Ground_Isolator.PrjPcb";
477 std::map<std::string, UTF8> props;
478 props[
"project_file"] = prjPcb;
480 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
482 m_altiumPlugin.LoadBoard( pcbDoc, board.get(), &props, &
project );
484 const std::map<wxString, wxString>& textVars =
project.GetTextVars();
492 BOOST_CHECK_EQUAL( textVars.at( wxS(
"PROJECT_NAME" ) ), wxS(
"Fastino Ground Isolator" ) );
503 board->SetProject( &
project,
true );
505 bool sawResolvedBoardText =
false;
511 if(
text &&
text->GetText().Contains( wxS(
"${PCB_REVISION}" ) ) )
513 wxString shown =
text->GetShownText(
false );
514 BOOST_CHECK( !shown.Contains( wxS(
"${PCB_REVISION}" ) ) );
515 BOOST_CHECK( shown.Contains( wxS(
"A" ) ) );
516 sawResolvedBoardText =
true;
520 BOOST_CHECK( sawResolvedBoardText );
531 std::string pcbDoc = dataDir +
"Fastino_Ground_Isolator.PcbDoc";
532 std::string prjPcb = dataDir +
"Fastino_Ground_Isolator.PrjPcb";
537 project.GetTextVars()[wxS(
"PCB_REVISION" )] = wxS(
"user-set" );
539 std::map<std::string, UTF8> props;
540 props[
"project_file"] = prjPcb;
542 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
544 m_altiumPlugin.LoadBoard( pcbDoc, board.get(), &props, &
project );
567 +
"plugins/altium/issue24456/Fastino_Ground_Isolator.PcbDoc";
569 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
570 m_altiumPlugin.LoadBoard( dataPath, board.get(),
nullptr );
573 std::vector<PCB_TEXT*> copperTexts;
574 std::vector<PCB_TEXT*> maskTexts;
585 copperTexts.push_back(
text );
587 maskTexts.push_back(
text );
590 BOOST_REQUIRE_MESSAGE( !copperTexts.empty(),
"Board must contain copper-layer text" );
591 BOOST_REQUIRE_MESSAGE( !maskTexts.empty(),
"Board must contain soldermask-layer text" );
596 const int tolerance = 1000;
598 int matchedPairs = 0;
600 for(
PCB_TEXT* copper : copperTexts )
604 if( copper->GetText() != mask->GetText()
605 || copper->GetTextAngle() != mask->GetTextAngle()
606 || copper->IsMirrored() != mask->IsMirrored() )
622 wxString::Format(
"Copper/mask copies of '%s' diverge by (%d, %d) IU",
627 BOOST_CHECK_MESSAGE( matchedPairs > 0,
628 "Expected at least one coincident copper/soldermask text pair" );
644 std::string dataPath =
647 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
648 m_altiumPlugin.LoadBoard( dataPath, board.get(),
nullptr );
654 int diffPairCount = 0;
667 "Imported tuning pattern wraps no copper" );
672 std::set<int> memberNets;
677 BOOST_CHECK( item->GetParentGroup() == pattern );
680 memberNets.insert( bci->GetNetCode() );
711 +
"plugins/altium/issue24847/PCB1.PcbDoc";
713 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
714 m_altiumPlugin.LoadBoard( dataPath, board.get(),
nullptr );
717 BOOST_REQUIRE_GT( board->Footprints().size(), 0 );
719 int keepoutZoneCount = 0;
721 for(
FOOTPRINT* footprint : board->Footprints() )
723 const VECTOR2I fpPos = footprint->GetPosition();
725 for(
ZONE* zone : footprint->Zones() )
729 const VECTOR2I zoneCenter = zone->GetBoundingBox().GetCenter();
730 const double distMm = ( zoneCenter - fpPos ).EuclideanNorm() / 1e6;
733 <<
" at (" << fpPos.
x <<
"," << fpPos.
y
734 <<
") keepout center (" << zoneCenter.
x <<
","
735 << zoneCenter.
y <<
") dist " << distMm <<
" mm" );
739 BOOST_CHECK_MESSAGE( distMm < 2.0,
740 "Keepout in footprint " << footprint->GetReference().ToStdString()
741 <<
" is " << distMm <<
" mm from its footprint origin" );
756 +
"plugins/altium/issue13750/"
757 "altium2kicad_region_soldermask_expansion.PcbDoc";
759 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
760 m_altiumPlugin.LoadBoard( dataPath, board.get(),
nullptr );
763 std::vector<PCB_SHAPE*> copperPolys;
764 std::vector<PCB_SHAPE*> maskPolys;
777 copperPolys.push_back( shape );
779 maskPolys.push_back( shape );
783 BOOST_REQUIRE_EQUAL( copperPolys.size(), 2 );
784 BOOST_REQUIRE_EQUAL( maskPolys.size(), 1 );
789 int exactMatches = 0;
803 BOOST_CHECK_MESSAGE( exactMatches == 1,
"F_Mask relief aperture must exactly match exactly one copper region" );
bool altiumScopeExprMatchesPolygon(const wxString &aExpr)
Return true if an Altium rule scope expression targets polygon pour primitives (matches InPolygon,...
const ARULE6 * selectAltiumPolygonRule(const std::vector< ARULE6 > &aRulesByPriorityAsc)
Select the highest Altium-priority rule whose scope references polygons.
bool altiumViaSideIsTented(bool aTentFlag, bool aManual, bool aFromHole, uint32_t aHoleSize, int32_t aMaskExpansion, int aLandDiameter)
Decide whether one side of an Altium via should be tented when imported into KiCad.
General utilities for PCB file IO for QA programs.
@ BS_ITEM_TYPE_DIELECTRIC
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Manage one layer needed to make a physical board.
Manage layers needed to make a physical board.
const std::vector< BOARD_STACKUP_ITEM * > & GetList() const
SHAPE_POLY_SET & GetPolyShape()
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
A collection of nets and the parameters used to route or test these nets.
static const char Default[]
the name of the default NETCLASS
const wxString GetName() const
Gets the name of this (maybe aggregate) netclass in a format for internal usage or for export to exte...
Handle the data for a net.
std::unordered_set< BOARD_ITEM * > GetBoardItems() const
BOARD * LoadBoard(const wxString &aFileName, BOARD *aAppendToMe, const std::map< std::string, UTF8 > *aProperties, PROJECT *aProject=nullptr) override
Load information from some input file format that this PCB_IO implementation knows about into either ...
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
LENGTH_TUNING_MODE GetTuningMode() const
int GetMaxAmplitude() const
Container for project specific data.
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.
Represent a set of closed polygons.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
SHAPE_POLY_SET CloneDropTriangulation() const
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
Handle a list of polygons defining a copper zone.
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
std::string GetPcbnewTestDataDir()
Utility which returns a path to the data directory where the test board files are stored.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
ALTIUM_PCB_IMPORT_FIXTURE()=default
PCB_IO_ALTIUM_DESIGNER m_altiumPlugin
BOOST_AUTO_TEST_CASE(BoardLoadNoAssertions)
Test basic board loading - verifies that the Altium import doesn't trigger any assertions during the ...
static void checkAllCopperFillZonesHaveClearance(PCB_IO_ALTIUM_DESIGNER &aPlugin, const std::string &aRelativePath)
Verify that copper zones in imported Altium boards have non-zero local clearance values derived from ...
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
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")
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
VECTOR2< int32_t > VECTOR2I