|
KiCad PCB EDA Suite
|
Test suite for IPC-2581 export validation. More...
#include <pcbnew_utils/board_test_utils.h>#include <pcbnew_utils/board_file_utils.h>#include <qa_utils/file_utils.h>#include <qa_utils/wx_utils/unit_test_utils.h>#include <pcbnew/pcb_io/ipc2581/pcb_io_ipc2581.h>#include <pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h>#include <board.h>#include <board_design_settings.h>#include <board_stackup_manager/board_stackup.h>#include <footprint.h>#include <netinfo.h>#include <pad.h>#include <pcb_shape.h>#include <pcb_textbox.h>#include <pcb_track.h>#include <base_units.h>#include <wx/dir.h>#include <wx/file.h>#include <wx/filename.h>#include <wx/process.h>#include <wx/txtstrm.h>#include <cmath>#include <fstream>#include <regex>#include <sstream>Go to the source code of this file.
Classes | |
| struct | IPC2581_EXPORT_FIXTURE |
Functions | |
| BOOST_AUTO_TEST_CASE (SurfaceFinishExport) | |
| Test that surface finish is exported correctly (Issue #22690) | |
| BOOST_AUTO_TEST_CASE (NoSurfaceFinishExport) | |
| Test that boards without surface finish don't generate coating layers. | |
| BOOST_AUTO_TEST_CASE (SchemaValidationVersionB) | |
| Validate IPC-2581B export against schema for multiple boards. | |
| BOOST_AUTO_TEST_CASE (SchemaValidationVersionC) | |
| Validate IPC-2581C export against schema for multiple boards. | |
| BOOST_AUTO_TEST_CASE (FunctionModeSchemaValidation) | |
| Test export of boards with complex features. | |
| BOOST_AUTO_TEST_CASE (FunctionModeSuppressedReferences) | |
| Section keys the Table 4 data sets never produce on their own, where a referring attribute has to be suppressed rather than its section dragged back in. | |
| BOOST_AUTO_TEST_CASE (ComplexBoardExport) | |
| BOOST_AUTO_TEST_CASE (DegenerateTrackArcExportsAsLine) | |
| BOOST_AUTO_TEST_CASE (TextBoxUsesDrawPosition) | |
| Test that text boxes use their calculated drawing position in IPC-2581 output. | |
| BOOST_AUTO_TEST_CASE (SmdPadSolderMaskExport_Issue16658) | |
| Test that SMD pad solder mask openings are exported (Issue #16658) | |
, or PinRef/@componentRef attributes, which are | |
Test that footprints with empty references produce valid XML attributes. Footprints with blank GetReference() must not produce empty refDes, RefDes/ schema-invalid qualified names. | |
| BOOST_AUTO_TEST_CASE (EmptyRefDesProducesValidXml) | |
| BOOST_AUTO_TEST_CASE (FlippedComponentRotation) | |
| Test that flipped component rotation is not inverted (Finding A / Issue #18013) | |
| BOOST_AUTO_TEST_CASE (ContentBomRef) | |
| Test that Content section includes BomRef when BOM is emitted. | |
| BOOST_AUTO_TEST_CASE (KnockoutTextMultiContour_Issue23968) | |
| Test that knockout text with holes emits schema-valid XML (Issue #23968) | |
| BOOST_AUTO_TEST_CASE (BackdrillSpecEncoding) | |
| Verify IPC-2581 backdrill encoding matches the schema and expresses the correct must-not-cut layer. | |
| BOOST_AUTO_TEST_CASE (ExposedPadPasteRespected_Issue24318) | |
| Test that SMD pads without F.Paste in their layer set are not added to the solder paste layer (Issue #24318). | |
| static std::string | LayerFeatureRegion (const std::string &aXml, const std::string &aLayerRef) |
| Extract the text of the first LayerFeature block for a given layer reference. | |
| BOOST_AUTO_TEST_CASE (GrRectCornerRadius_Issue24754) | |
| Test that a rounded gr_rect keeps its corner radius on export (Issue #24754). | |
| BOOST_AUTO_TEST_CASE (BackOnlyMaskNoFrontOpening_Issue24753) | |
| Test that a back-only masked through-hole pad gets no F.Mask opening (Issue #24753). | |
| BOOST_AUTO_TEST_CASE (RoundRectMaskRadius_Issue24751) | |
| Test that a roundrect pad's mask aperture shrinks its radius with its size (Issue #24751). | |
| BOOST_AUTO_TEST_CASE (MultiLayerFootprintGraphic_Issue24752) | |
| Test that a multi-layer footprint graphic is emitted on every layer (Issue #24752). | |
| BOOST_AUTO_TEST_CASE (SolderMaskMarginExpandsMaskPrimitive_Issue24749) | |
| Test that the per-layer solder mask margin expands the exported mask primitive (Issue #24749). | |
| BOOST_AUTO_TEST_CASE (SchemaValidation_Issue25149) | |
| Validate the minimal boards attached to issue #25149 against the IPC-2581C schema. | |
| BOOST_AUTO_TEST_CASE (NoClosedOutline_Issue25149) | |
| A board with no closed outline must export without crashing and omit Profile (Issue #25149). | |
| BOOST_AUTO_TEST_CASE (ProcessLayerViaPads_Issue25149) | |
| Process-layer via pads must sit in a Set at the via position (Issue #25149). | |
Test suite for IPC-2581 export validation.
Tests per GitLab issues:
Definition in file test_ipc2581_export.cpp.
| BOOST_AUTO_TEST_CASE | ( | BackdrillSpecEncoding | ) |
Verify IPC-2581 backdrill encoding matches the schema and expresses the correct must-not-cut layer.
KiCad's PADSTACK::DRILL_PROPS::end is the must-cut layer (per the UI "must-cut" labels). The IPC-2581 standard expects the must-not-cut layer, which is the next signal layer past the must-cut layer. The exporter must emit one Spec containing three sibling Backdrill children with type START_LAYER, MUST_NOT_CUT_LAYER, and MAX_STUB_LENGTH, each carrying its value in a Property child.
Definition at line 901 of file test_ipc2581_export.cpp.
References BOARD::Add(), PADSTACK::ALL_LAYERS, B_Cu, BOOST_REQUIRE(), BOARD_STACKUP::BuildDefaultStackupList(), COUNTERSINK, F_Cu, BOARD::GetDesignSettings(), BOARD_DESIGN_SETTINGS::GetStackupDescriptor(), In3_Cu, PADSTACK::NORMAL, pcbIUScale, BOARD::SetCopperLayerCount(), and via.
| BOOST_AUTO_TEST_CASE | ( | BackOnlyMaskNoFrontOpening_Issue24753 | ) |
Test that a back-only masked through-hole pad gets no F.Mask opening (Issue #24753).
A pad on *.Cu with an explicit B.Mask (and no F.Mask) must not be added to the F.Mask LayerFeature. The implicit-mask heuristic only applies when the pad authors no mask side.
Definition at line 1201 of file test_ipc2581_export.cpp.
References BOARD::Add(), FOOTPRINT::Add(), PADSTACK::ALL_LAYERS, B_Cu, B_Mask, BOOST_REQUIRE(), F_Cu, FOOTPRINT, LayerFeatureRegion(), KI_TEST::LoadStringData(), PADSTACK::NORMAL, OVAL, PAD, pad, pcbIUScale, PTH, BOARD::SetCopperLayerCount(), FOOTPRINT::SetPosition(), and FOOTPRINT::SetReference().
| BOOST_AUTO_TEST_CASE | ( | ComplexBoardExport | ) |
Definition at line 545 of file test_ipc2581_export.cpp.
References BOOST_TEST_CONTEXT().
| BOOST_AUTO_TEST_CASE | ( | ContentBomRef | ) |
Test that Content section includes BomRef when BOM is emitted.
Definition at line 829 of file test_ipc2581_export.cpp.
References BOOST_REQUIRE().
| BOOST_AUTO_TEST_CASE | ( | DegenerateTrackArcExportsAsLine | ) |
Definition at line 583 of file test_ipc2581_export.cpp.
References BOARD::Add(), BOOST_REQUIRE(), F_Cu, pcbIUScale, BOARD::SetCopperLayerCount(), PCB_TRACK::SetEnd(), BOARD_CONNECTED_ITEM::SetLayer(), PCB_ARC::SetMid(), BOARD_CONNECTED_ITEM::SetNet(), PCB_TRACK::SetStart(), and PCB_TRACK::SetWidth().
| BOOST_AUTO_TEST_CASE | ( | EmptyRefDesProducesValidXml | ) |
Definition at line 744 of file test_ipc2581_export.cpp.
References BOOST_REQUIRE(), and BOOST_TEST_CONTEXT().
| BOOST_AUTO_TEST_CASE | ( | ExposedPadPasteRespected_Issue24318 | ) |
Test that SMD pads without F.Paste in their layer set are not added to the solder paste layer (Issue #24318).
Exposed-pad QFN/QFP footprints commonly use a copper-only thermal pad (F.Cu + F.Mask, no F.Paste) plus several separate paste-only apertures. The earlier #16658 fix implicitly added every copper SMD pad to the paste layer, which contaminated the stencil for these footprints. Mask is still implicit for SMD pads (every copper pad needs a mask opening), but paste must be respected exactly as authored.
Definition at line 991 of file test_ipc2581_export.cpp.
References BOARD::Add(), FOOTPRINT::Add(), PADSTACK::ALL_LAYERS, BOOST_REQUIRE(), F_Cu, F_Mask, F_Paste, FOOTPRINT, FOOTPRINT::GetPosition(), HEATSINK, PADSTACK::NORMAL, PAD, pcbIUScale, RECTANGLE, PAD::SetAttribute(), PAD::SetLayerSet(), PAD::SetNumber(), PAD::SetPadstackMode(), FOOTPRINT::SetPosition(), PAD::SetPosition(), PAD::SetProperty(), FOOTPRINT::SetReference(), PAD::SetShape(), PAD::SetSize(), and SMD.
| BOOST_AUTO_TEST_CASE | ( | FlippedComponentRotation | ) |
Test that flipped component rotation is not inverted (Finding A / Issue #18013)
IPC-2581C 3.3.2 defines positive rotation as CCW from board top. mirror="true" handles the X-axis negation for bottom components. The component rotation must be the normalized board-top angle, NOT its inverse.
Definition at line 784 of file test_ipc2581_export.cpp.
References BOOST_REQUIRE().
| BOOST_AUTO_TEST_CASE | ( | FunctionModeSchemaValidation | ) |
Test export of boards with complex features.
Tests boards with zones, custom pads, and other features that may exercise edge cases in the IPC-2581 exporter. Every IPC-2581 data set must produce a schema-valid file in both revisions, including with net names and reference designators withheld.
Definition at line 450 of file test_ipc2581_export.cpp.
References BOOST_TEST_CONTEXT().
| BOOST_AUTO_TEST_CASE | ( | FunctionModeSuppressedReferences | ) |
Section keys the Table 4 data sets never produce on their own, where a referring attribute has to be suppressed rather than its section dragged back in.
Definition at line 506 of file test_ipc2581_export.cpp.
References BOOST_REQUIRE(), and BOOST_TEST_CONTEXT().
| BOOST_AUTO_TEST_CASE | ( | GrRectCornerRadius_Issue24754 | ) |
Test that a rounded gr_rect keeps its corner radius on export (Issue #24754).
The exporter used to emit a RectRound with all corner flags off and a radius of stroke_width/2, discarding the shape's real corner radius. A gr_rect with a 0.75 mm corner radius must round its corners and carry that radius in the RectRound primitive.
Definition at line 1153 of file test_ipc2581_export.cpp.
References BOARD::Add(), BOOST_REQUIRE(), Edge_Cuts, KI_TEST::LoadStringData(), pcbIUScale, RECTANGLE, BOARD::SetCopperLayerCount(), EDA_SHAPE::SetCornerRadius(), PCB_SHAPE::SetEnd(), EDA_SHAPE::SetFilled(), PCB_SHAPE::SetLayer(), PCB_SHAPE::SetStart(), PCB_SHAPE::SetStroke(), and SOLID.
| BOOST_AUTO_TEST_CASE | ( | KnockoutTextMultiContour_Issue23968 | ) |
Test that knockout text with holes emits schema-valid XML (Issue #23968)
Knockout text renders as a filled polygon with each glyph contour becoming a separate outline. The IPC-2581 FeaturesType allows only one Feature child, so when a knockout text produces more than one Contour it must be wrapped in a UserSpecial (which itself is a Feature that may contain any number of child Features).
test_copper_graphics.kicad_pcb contains a knockout text "Otherwise" on B.Cu, whose 'O' glyph produces two contours (outer and inner), which reproduces the multi-contour case.
Definition at line 868 of file test_ipc2581_export.cpp.
References BOOST_REQUIRE(), and BOOST_TEST_CONTEXT().
| BOOST_AUTO_TEST_CASE | ( | MultiLayerFootprintGraphic_Issue24752 | ) |
Test that a multi-layer footprint graphic is emitted on every layer (Issue #24752).
An fp_poly on F.Cu + F.Mask used to export only on its primary layer (F.Cu). KiCad plots it on both, so the F.Mask copy must be present too.
Definition at line 1300 of file test_ipc2581_export.cpp.
References BOARD::Add(), FOOTPRINT::Add(), SHAPE_POLY_SET::Append(), BOOST_REQUIRE(), F_Cu, F_Mask, FOOTPRINT, LayerFeatureRegion(), KI_TEST::LoadStringData(), SHAPE_POLY_SET::NewOutline(), pcbIUScale, POLY, BOARD::SetCopperLayerCount(), EDA_SHAPE::SetFilled(), PCB_SHAPE::SetLayerSet(), PCB_SHAPE::SetPolyShape(), FOOTPRINT::SetPosition(), FOOTPRINT::SetReference(), PCB_SHAPE::SetStroke(), and SOLID.
| BOOST_AUTO_TEST_CASE | ( | NoClosedOutline_Issue25149 | ) |
A board with no closed outline must export without crashing and omit Profile (Issue #25149).
Definition at line 1454 of file test_ipc2581_export.cpp.
References BOOST_REQUIRE().
| BOOST_AUTO_TEST_CASE | ( | NoSurfaceFinishExport | ) |
Test that boards without surface finish don't generate coating layers.
Definition at line 316 of file test_ipc2581_export.cpp.
References BOOST_REQUIRE(), and BOARD_STACKUP::m_FinishType.
| BOOST_AUTO_TEST_CASE | ( | ProcessLayerViaPads_Issue25149 | ) |
Process-layer via pads must sit in a Set at the via position (Issue #25149).
Definition at line 1476 of file test_ipc2581_export.cpp.
References BOOST_REQUIRE(), LayerFeatureRegion(), and KI_TEST::LoadStringData().
| BOOST_AUTO_TEST_CASE | ( | RoundRectMaskRadius_Issue24751 | ) |
Test that a roundrect pad's mask aperture shrinks its radius with its size (Issue #24751).
A roundrect pad with a negative mask margin has a smaller mask aperture, and its corner radius must shrink by the per-side margin too. The exporter used to reuse the copper radius, and the shape-dict key ignored the layer/expansion so the mask referenced the copper shape.
Definition at line 1251 of file test_ipc2581_export.cpp.
References BOARD::Add(), FOOTPRINT::Add(), PADSTACK::ALL_LAYERS, BOOST_REQUIRE(), F_Cu, F_Mask, FOOTPRINT, KI_TEST::LoadStringData(), PADSTACK::NORMAL, PAD, pad, pcbIUScale, ROUNDRECT, BOARD::SetCopperLayerCount(), FOOTPRINT::SetPosition(), FOOTPRINT::SetReference(), and SMD.
| BOOST_AUTO_TEST_CASE | ( | SchemaValidation_Issue25149 | ) |
Validate the minimal boards attached to issue #25149 against the IPC-2581C schema.
Definition at line 1422 of file test_ipc2581_export.cpp.
References BOOST_REQUIRE(), and BOOST_TEST_CONTEXT().
| BOOST_AUTO_TEST_CASE | ( | SchemaValidationVersionB | ) |
Validate IPC-2581B export against schema for multiple boards.
This test exports each board in VALIDATION_TEST_BOARDS to IPC-2581B format and validates against the IPC-2581B1.xsd schema using xmllint (if available).
Definition at line 360 of file test_ipc2581_export.cpp.
References BOOST_TEST_CONTEXT().
| BOOST_AUTO_TEST_CASE | ( | SchemaValidationVersionC | ) |
Validate IPC-2581C export against schema for multiple boards.
This test exports each board in VALIDATION_TEST_BOARDS to IPC-2581C format and validates against the IPC-2581C.xsd schema using xmllint (if available).
Definition at line 403 of file test_ipc2581_export.cpp.
References BOOST_TEST_CONTEXT().
| BOOST_AUTO_TEST_CASE | ( | SmdPadSolderMaskExport_Issue16658 | ) |
Test that SMD pad solder mask openings are exported (Issue #16658)
This test verifies that SMD pads which have implicit solder mask openings (pads on copper layers that don't explicitly include F_Mask/B_Mask in their layer set) still get exported with solder mask features in the IPC-2581 output.
Definition at line 676 of file test_ipc2581_export.cpp.
References BOOST_REQUIRE(), F_Cu, F_Mask, pad, and SMD.
| BOOST_AUTO_TEST_CASE | ( | SolderMaskMarginExpandsMaskPrimitive_Issue24749 | ) |
Test that the per-layer solder mask margin expands the exported mask primitive (Issue #24749).
The standard-primitive cache was keyed on pad geometry alone, so the copper primitive (no expansion) processed first was reused verbatim for the mask layer, dropping the solder mask margin. A 1.0 mm circular pad with a 0.5 mm mask margin must therefore export a 2.0 mm mask circle, not a 1.0 mm one.
Definition at line 1355 of file test_ipc2581_export.cpp.
References std::abs(), BOARD::Add(), FOOTPRINT::Add(), PADSTACK::ALL_LAYERS, BOOST_REQUIRE(), CIRCLE, F_Cu, F_Mask, FOOTPRINT, PADSTACK::NORMAL, PAD, pad, pcbIUScale, FOOTPRINT::SetPosition(), FOOTPRINT::SetReference(), and SMD.
| BOOST_AUTO_TEST_CASE | ( | SurfaceFinishExport | ) |
Test that surface finish is exported correctly (Issue #22690)
This test verifies that when a board has a surface finish defined:
Definition at line 270 of file test_ipc2581_export.cpp.
References BOOST_AUTO_TEST_CASE(), BOOST_CHECK_EQUAL(), BOOST_REQUIRE(), and BOARD_STACKUP::m_FinishType.
| BOOST_AUTO_TEST_CASE | ( | TextBoxUsesDrawPosition | ) |
Test that text boxes use their calculated drawing position in IPC-2581 output.
Unlike ordinary text, PCB_TEXTBOX stores its anchor in the box geometry and overrides GetDrawPos() to calculate it. GetTextPos() is normally zero, so using it places the exported text at the board origin.
Definition at line 622 of file test_ipc2581_export.cpp.
References BOARD::Add(), BOOST_REQUIRE(), F_SilkS, GR_TEXT_H_ALIGN_LEFT, GR_TEXT_V_ALIGN_TOP, pcbIUScale, PCB_TEXTBOX::SetBorderEnabled(), PCB_SHAPE::SetEnd(), EDA_TEXT::SetHorizJustify(), PCB_SHAPE::SetLayer(), PCB_TEXTBOX::SetMarginLeft(), PCB_TEXTBOX::SetMarginTop(), PCB_SHAPE::SetStart(), EDA_TEXT::SetText(), PCB_TEXTBOX::SetTextSize(), PCB_TEXTBOX::SetTextThickness(), and EDA_TEXT::SetVertJustify().
|
static |
Extract the text of the first LayerFeature block for a given layer reference.
Returns an empty string when no such LayerFeature exists.
Definition at line 1129 of file test_ipc2581_export.cpp.
References end.
Referenced by BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), and BOOST_AUTO_TEST_CASE().