Add zone filler tests.

One test has pads of a bunch of different shapes and provokes some
errors to make sure they're caught.

The others are all past issues with the zone filler to make sure we
don't suffer any regressions.  (They should all just pass with no DRC
errors.)
This commit is contained in:
Jeff Young 2021-07-30 17:08:12 +01:00
parent 1dbd4fcb7d
commit 8c69a856fc
18 changed files with 189226 additions and 21 deletions

View File

@ -178,7 +178,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
} }
} }
if( boardItem->Type() != PCB_NETINFO_T ) if( view && boardItem->Type() != PCB_NETINFO_T )
view->Add( boardItem ); view->Add( boardItem );
break; break;
@ -221,7 +221,8 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
if( parentGroup && !( parentGroup->GetFlags() & STRUCT_DELETED ) ) if( parentGroup && !( parentGroup->GetFlags() & STRUCT_DELETED ) )
parentGroup->RemoveItem( boardItem ); parentGroup->RemoveItem( boardItem );
view->Remove( boardItem ); if( view )
view->Remove( boardItem );
if( !( changeFlags & CHT_DONE ) ) if( !( changeFlags & CHT_DONE ) )
{ {
@ -245,7 +246,8 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
case PCB_TARGET_T: // a target (graphic item) case PCB_TARGET_T: // a target (graphic item)
case PCB_MARKER_T: // a marker used to show something case PCB_MARKER_T: // a marker used to show something
case PCB_ZONE_T: case PCB_ZONE_T:
view->Remove( boardItem ); if( view )
view->Remove( boardItem );
if( !( changeFlags & CHT_DONE ) ) if( !( changeFlags & CHT_DONE ) )
{ {
@ -261,7 +263,10 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
wxASSERT( !m_isFootprintEditor ); wxASSERT( !m_isFootprintEditor );
FOOTPRINT* footprint = static_cast<FOOTPRINT*>( boardItem ); FOOTPRINT* footprint = static_cast<FOOTPRINT*>( boardItem );
view->Remove( footprint );
if( view )
view->Remove( footprint );
footprint->ClearFlags(); footprint->ClearFlags();
if( !( changeFlags & CHT_DONE ) ) if( !( changeFlags & CHT_DONE ) )
@ -273,7 +278,8 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
break; break;
case PCB_GROUP_T: case PCB_GROUP_T:
view->Remove( boardItem ); if( view )
view->Remove( boardItem );
if( !( changeFlags & CHT_DONE ) ) if( !( changeFlags & CHT_DONE ) )
{ {
@ -315,15 +321,19 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
connectivity->MarkItemNetAsDirty( static_cast<BOARD_ITEM*>( ent.m_copy ) ); connectivity->MarkItemNetAsDirty( static_cast<BOARD_ITEM*>( ent.m_copy ) );
connectivity->Update( boardItem ); connectivity->Update( boardItem );
view->Update( boardItem );
if( m_isFootprintEditor ) if( view )
{ {
static_cast<FOOTPRINT*>( boardItem )->RunOnChildren( view->Update( boardItem );
[&]( BOARD_ITEM* aChild )
{ if( m_isFootprintEditor )
view->Update( aChild ); {
}); static_cast<FOOTPRINT*>( boardItem )->RunOnChildren(
[&]( BOARD_ITEM* aChild )
{
view->Update( aChild );
});
}
} }
itemsChanged.push_back( boardItem ); itemsChanged.push_back( boardItem );
@ -359,7 +369,9 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
connectivity->RecalculateRatsnest( this ); connectivity->RecalculateRatsnest( this );
connectivity->ClearDynamicRatsnest(); connectivity->ClearDynamicRatsnest();
frame->GetCanvas()->RedrawRatsnest();
if( frame )
frame->GetCanvas()->RedrawRatsnest();
if( m_changes.size() > num_changes ) if( m_changes.size() > num_changes )
{ {
@ -370,7 +382,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
// This should only be modifications from the connectivity algo // This should only be modifications from the connectivity algo
wxASSERT( ( ent.m_type & CHT_TYPE ) == CHT_MODIFY ); wxASSERT( ( ent.m_type & CHT_TYPE ) == CHT_MODIFY );
auto boardItem = static_cast<BOARD_ITEM*>( ent.m_item ); BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( ent.m_item );
if( aCreateUndoEntry ) if( aCreateUndoEntry )
{ {
@ -384,7 +396,8 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
delete ent.m_copy; delete ent.m_copy;
} }
view->Update( boardItem ); if( view )
view->Update( boardItem );
} }
} }
} }
@ -399,7 +412,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
if( aSetDirtyBit ) if( aSetDirtyBit )
frame->OnModify(); frame->OnModify();
else else if( frame )
frame->Update3DView( true, frame->GetDisplayOptions().m_Live3DRefresh ); frame->Update3DView( true, frame->GetDisplayOptions().m_Live3DRefresh );
clear(); clear();

View File

@ -679,7 +679,6 @@ void DRC_ENGINE::RunTests( EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aT
{ {
m_userUnits = aUnits; m_userUnits = aUnits;
// Note: set these first. The phase counts may be dependent on some of them.
m_reportAllTrackErrors = aReportAllTrackErrors; m_reportAllTrackErrors = aReportAllTrackErrors;
m_testFootprints = aTestFootprints; m_testFootprints = aTestFootprints;

3986
qa/data/issue2568.kicad_pcb Normal file

File diff suppressed because it is too large Load Diff

92615
qa/data/issue3812.kicad_pcb Normal file

File diff suppressed because it is too large Load Diff

453
qa/data/issue3812.kicad_pro Normal file
View File

@ -0,0 +1,453 @@
{
"board": {
"design_settings": {
"defaults": {
"board_outline_line_width": 0.049999999999999996,
"copper_line_width": 0.19999999999999998,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": false,
"courtyard_line_width": 0.049999999999999996,
"dimension_precision": 1,
"dimension_units": 0,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": false,
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.09999999999999999,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.09999999999999999,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": false,
"pads": {
"drill": 0.8128,
"height": 1.397,
"width": 1.397
},
"silk_line_width": 0.12,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.15,
"silk_text_upright": false,
"zones": {
"45_degree_only": false,
"min_clearance": 0.508
}
},
"diff_pair_dimensions": [
{
"gap": 0.0,
"via_gap": 0.0,
"width": 0.0
}
],
"drc_exclusions": [],
"meta": {
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"copper_edge_clearance": "error",
"courtyards_overlap": "error",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"hole_clearance": "error",
"hole_near_hole": "error",
"invalid_outline": "error",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "error",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_over_copper": "error",
"silk_overlap": "error",
"skew_out_of_range": "error",
"too_many_vias": "error",
"track_dangling": "warning",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zone_has_empty_net": "error",
"zones_intersect": "error"
},
"rule_severitieslegacy_courtyards_overlap": true,
"rule_severitieslegacy_no_courtyard_defined": true,
"rules": {
"allow_blind_buried_vias": false,
"allow_microvias": false,
"max_error": 0.005,
"min_clearance": 0.0,
"min_copper_edge_clearance": 0.01,
"min_hole_clearance": 0.0,
"min_hole_to_hole": 0.25,
"min_microvia_diameter": 0.19999999999999998,
"min_microvia_drill": 0.09999999999999999,
"min_silk_clearance": 0.0,
"min_through_hole_diameter": 0.39999999999999997,
"min_track_width": 0.19812,
"min_via_annular_width": 0.049999999999999996,
"min_via_diameter": 0.5
},
"track_widths": [
0.0,
0.3,
0.4
],
"via_dimensions": [
{
"diameter": 0.0,
"drill": 0.0
}
],
"zones_allow_external_fillets": false,
"zones_use_no_outline": true
},
"layer_presets": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_label_syntax": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "warning",
"multiple_net_names": "warning",
"net_not_bus_member": "warning",
"no_connect_connected": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "warning",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "kit-dev-coldfire-xilinx_5213.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12.0,
"clearance": 0.15,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.2,
"via_diameter": 0.6,
"via_drill": 0.4,
"wire_width": 6.0
},
{
"bus_width": 12.0,
"clearance": 0.15,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "POWER",
"nets": [
"+3.3V",
"GND",
"GNDA"
],
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.4,
"via_diameter": 0.8,
"via_drill": 0.4,
"wire_width": 6.0
}
],
"meta": {
"version": 0
},
"net_colors": null
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"specctra_dsn": "",
"step": "",
"vmrl": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"drawing": {
"default_bus_thickness": 12.0,
"default_junction_size": 40.0,
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"default_wire_thickness": 6.0,
"field_names": [],
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"pin_symbol_size": 25.0,
"text_offset_ratio": 0.3
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 0
},
"net_format_name": "Pcbnew",
"page_layout_descr_file": "",
"plot_directory": "",
"spice_adjust_passive_values": false,
"spice_external_command": "spice \"%I\"",
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"00000000-0000-0000-0000-000047d80204",
""
],
[
"00000000-0000-0000-0000-000047d80204",
"xilinx"
],
[
"00000000-0000-0000-0000-000047d80202",
"inout_user"
]
],
"text_variables": {}
}

5982
qa/data/issue5320.kicad_pcb Executable file

File diff suppressed because it is too large Load Diff

391
qa/data/issue5320.kicad_pro Executable file
View File

@ -0,0 +1,391 @@
{
"board": {
"design_settings": {
"defaults": {
"board_outline_line_width": 0.09999999999999999,
"copper_line_width": 0.19999999999999998,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": true,
"courtyard_line_width": 0.049999999999999996,
"dimension_precision": 1,
"dimension_units": 0,
"fab_line_width": 0.09999999999999999,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": true,
"other_line_width": 0.09999999999999999,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": true,
"pads": {
"drill": 0.0,
"height": 4.191,
"width": 2.667
},
"silk_line_width": 0.15,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.15,
"silk_text_upright": true,
"zones": {
"45_degree_only": false,
"min_clearance": 0.2794
}
},
"diff_pair_dimensions": [
{
"gap": 0.25,
"via_gap": 0.25,
"width": 0.2
}
],
"drc_exclusions": [],
"meta": {
"version": 0
},
"rule_severities": {
"clearance": "error",
"copper_edge_clearance": "error",
"courtyards_overlap": "error",
"drill_too_small": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"hole_near_hole": "error",
"invalid_outline": "error",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"keepout": "error",
"malformed_courtyard": "error",
"microvia_drill_too_small": "error",
"microvia_too_small": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "error",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"track_dangling": "warning",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_annulus": "error",
"via_dangling": "warning",
"via_hole_larger_than_pad": "error",
"via_too_small": "error",
"zone_has_empty_net": "error",
"zones_intersect": "error"
},
"rules": {
"allow_blind_buried_vias": false,
"allow_microvias": false,
"max_error": 0.005,
"min_clearance": 0.127,
"min_copper_edge_clearance": 0.254,
"min_hole_to_hole": 0.254,
"min_microvia_diameter": 0.127,
"min_microvia_drill": 0.07619999999999999,
"min_through_hole_diameter": 0.254,
"min_track_width": 0.127,
"min_via_annulus": 0.127,
"min_via_diameter": 0.254,
"solder_mask_clearance": 0.0508,
"solder_mask_min_width": 0.1016,
"solder_paste_clearance": 0.0,
"solder_paste_margin_ratio": -0.0
},
"track_widths": [
0.127,
0.127,
0.1524,
0.254,
0.4318,
0.508,
0.762,
1.016,
1.27
],
"via_dimensions": [
{
"diameter": 0.508,
"drill": 0.254
},
{
"diameter": 0.508,
"drill": 0.254
},
{
"diameter": 0.762,
"drill": 0.381
},
{
"diameter": 1.016,
"drill": 0.508
},
{
"diameter": 1.27,
"drill": 0.635
}
],
"zones_use_no_outline": true
},
"layer_presets": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_label_syntax": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_sheet_names": "error",
"global_label_dangling": "error",
"hier_label_mismatch": "error",
"label_dangling": "error",
"multiple_net_names": "error",
"net_not_bus_member": "error",
"no_connect_connected": "error",
"no_connect_dangling": "error",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "warning",
"similar_labels": "error",
"unresolved_variable": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "VHF_Module.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 6.0,
"clearance": 0.127,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.127,
"microvia_drill": 0.762,
"name": "Default",
"track_width": 0.127,
"via_diameter": 0.508,
"via_drill": 0.254,
"wire_width": 6.0
}
],
"hidden_nets": [],
"meta": {
"version": 0
},
"net_colors": null
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "DC_DC_UAV_Converter.net",
"specctra_dsn": "",
"step": "../../../../Mechanical Design/JVAB/VHF Module/Rev 1.0A/VHF_Module_PCB.step",
"vmrl": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"drawing": {
"default_bus_thickness": 12.0,
"default_junction_size": 40.0,
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"default_wire_thickness": 6.0,
"field_names": [],
"pin_symbol_size": 25.0,
"text_offset_ratio": 0.3
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 0
},
"net_format_name": "",
"page_layout_descr_file": "",
"plot_directory": "C:/Temp/",
"spice_adjust_passive_values": false,
"spice_external_command": "spice \"%I\"",
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"4b2c37f4-6e30-41af-bed4-d50bb6c159d5",
""
]
],
"text_variables": {}
}

8151
qa/data/issue5830.kicad_pcb Normal file

File diff suppressed because it is too large Load Diff

422
qa/data/issue5830.kicad_pro Executable file
View File

@ -0,0 +1,422 @@
{
"board": {
"design_settings": {
"defaults": {
"board_outline_line_width": 0.09999999999999999,
"copper_line_width": 0.19999999999999998,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": false,
"courtyard_line_width": 0.049999999999999996,
"dimension_precision": 1,
"dimension_units": 0,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": false,
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.09999999999999999,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.15,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": false,
"pads": {
"drill": 0.762,
"height": 1.524,
"width": 1.524
},
"silk_line_width": 0.15,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.15,
"silk_text_upright": false,
"zones": {
"45_degree_only": false,
"min_clearance": 0.19999999999999998
}
},
"diff_pair_dimensions": [
{
"gap": 0.25,
"via_gap": 0.25,
"width": 0.2
}
],
"drc_exclusions": [],
"meta": {
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"copper_edge_clearance": "error",
"courtyards_overlap": "error",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"hole_clearance": "error",
"hole_near_hole": "error",
"invalid_outline": "error",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "error",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"too_many_vias": "error",
"track_dangling": "ignore",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zone_has_empty_net": "error",
"zones_intersect": "error"
},
"rules": {
"allow_blind_buried_vias": false,
"allow_microvias": false,
"max_error": 0.005,
"min_clearance": 0.0,
"min_copper_edge_clearance": 0.01,
"min_hole_clearance": 0.0,
"min_hole_to_hole": 0.25,
"min_microvia_diameter": 0.19999999999999998,
"min_microvia_drill": 0.09999999999999999,
"min_silk_clearance": 0.0,
"min_through_hole_diameter": 0.3,
"min_track_width": 0.19999999999999998,
"min_via_annular_width": 0.049999999999999996,
"min_via_annulus": 0.049999999999999996,
"min_via_diameter": 0.39999999999999997,
"use_height_for_length_calcs": true
},
"track_widths": [
0.254
],
"via_dimensions": [
{
"diameter": 0.7,
"drill": 0.4
}
],
"zones_allow_external_fillets": false,
"zones_use_no_outline": false
},
"layer_presets": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_label_syntax": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_sheet_names": "error",
"global_label_dangling": "error",
"hier_label_mismatch": "error",
"label_dangling": "error",
"multiple_net_names": "error",
"net_not_bus_member": "error",
"no_connect_connected": "error",
"no_connect_dangling": "error",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "warning",
"similar_labels": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "i2c-moist-sensor.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12.0,
"clearance": 0.1778,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.508,
"microvia_drill": 0.127,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.254,
"via_diameter": 0.7,
"via_drill": 0.4,
"wire_width": 6.0
},
{
"bus_width": 12.0,
"clearance": 0.6,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.508,
"microvia_drill": 0.127,
"name": "excitation",
"nets": [
"/SENSOR_TRACK"
],
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.254,
"via_diameter": 0.7,
"via_drill": 0.4,
"wire_width": 6.0
},
{
"bus_width": 12.0,
"clearance": 0.2032,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.508,
"microvia_drill": 0.127,
"name": "sensor",
"nets": [],
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 5.0,
"via_diameter": 0.7,
"via_drill": 0.4,
"wire_width": 6.0
}
],
"meta": {
"version": 1
},
"net_colors": null
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"specctra_dsn": "",
"step": "",
"vmrl": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"drawing": {
"default_bus_thickness": 12.0,
"default_junction_size": 40.0,
"default_line_thickness": 6.0,
"default_text_size": 60.0,
"default_wire_thickness": 6.0,
"field_names": [],
"pin_symbol_size": 25.0,
"text_offset_ratio": 0.3
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 0
},
"net_format_name": "",
"page_layout_descr_file": "",
"plot_directory": "",
"spice_adjust_passive_values": false,
"spice_external_command": "spice \"%I\"",
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"461f436e-5fb7-473e-8e98-c8cc0b26cceb",
""
]
],
"text_variables": {}
}

72671
qa/data/issue6284.kicad_pcb Normal file

File diff suppressed because it is too large Load Diff

2060
qa/data/issue7086.kicad_pcb Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -37,6 +37,7 @@ set( QA_PCBNEW_SRCS
test_lset.cpp test_lset.cpp
test_pad_naming.cpp test_pad_naming.cpp
test_libeval_compiler.cpp test_libeval_compiler.cpp
test_zone_filler.cpp
drc/test_drc_courtyard_invalid.cpp drc/test_drc_courtyard_invalid.cpp
drc/test_drc_courtyard_overlap.cpp drc/test_drc_courtyard_overlap.cpp
@ -64,6 +65,23 @@ target_compile_definitions( qa_pcbnew
# multi-threaded build # multi-threaded build
add_dependencies( qa_pcbnew pcbnew ) add_dependencies( qa_pcbnew pcbnew )
include_directories( BEFORE ${INC_BEFORE} )
include_directories(
${CMAKE_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/3d-viewer
${CMAKE_SOURCE_DIR}/common
${CMAKE_SOURCE_DIR}/pcbnew
${CMAKE_SOURCE_DIR}/pcbnew/router
${CMAKE_SOURCE_DIR}/pcbnew/tools
${CMAKE_SOURCE_DIR}/pcbnew/dialogs
${CMAKE_SOURCE_DIR}/polygon
${CMAKE_SOURCE_DIR}/common/geometry
${CMAKE_SOURCE_DIR}/qa/qa_utils
${Boost_INCLUDE_DIR}
${INC_AFTER}
)
target_link_libraries( qa_pcbnew target_link_libraries( qa_pcbnew
qa_pcbnew_utils qa_pcbnew_utils
3d-viewer 3d-viewer

View File

@ -0,0 +1,233 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 201 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <string>
#include <wx/toplevel.h>
#include <qa_utils/wx_utils/unit_test_utils.h>
#include <pcbnew_utils/board_file_utils.h>
#include <board.h>
#include <board_design_settings.h>
#include <pad.h>
#include <pcb_track.h>
#include <footprint.h>
#include <drc/drc_item.h>
#include <drc/drc_engine.h>
#include <zone_filler.h>
#include <board_commit.h>
#include <tool/tool_manager.h>
#include <zone_filler_tool.h>
#include <settings/settings_manager.h>
struct ZONE_FILL_TEST_FIXTURE
{
ZONE_FILL_TEST_FIXTURE() :
m_settingsManager( true /* headless */ )
{
}
void loadBoard( const wxString& relPath )
{
wxString boardPath = KI_TEST::GetPcbnewTestDataDir() + relPath + ".kicad_pcb";
wxString projectPath = KI_TEST::GetPcbnewTestDataDir() + relPath + ".kicad_pro";
wxFileName pro( projectPath );
if( pro.Exists() )
m_settingsManager.LoadProject( pro.GetFullPath() );
m_board = KI_TEST::ReadBoardFromFileOrStream( boardPath );
if( pro.Exists() )
m_board->SetProject( &m_settingsManager.Prj() );
m_DRCEngine = std::make_shared<DRC_ENGINE>( m_board.get(), &m_board->GetDesignSettings() );
m_DRCEngine->InitEngine( wxFileName() );
m_board->GetDesignSettings().m_DRCEngine = m_DRCEngine;
m_toolMgr = std::make_unique<TOOL_MANAGER>();
m_toolMgr->SetEnvironment( m_board.get(), nullptr, nullptr, nullptr, nullptr );
m_toolMgr->RegisterTool( new ZONE_FILLER_TOOL );
}
void fillZones( int aFillVersion )
{
ZONE_FILLER_TOOL* fillerTool = m_toolMgr->GetTool<ZONE_FILLER_TOOL>();
BOARD_COMMIT commit( fillerTool );
ZONE_FILLER filler( m_board.get(), &commit );
std::vector<ZONE*> toFill;
m_board->GetDesignSettings().m_ZoneFillVersion = aFillVersion;
for( ZONE* zone : m_board->Zones() )
toFill.push_back( zone );
if( filler.Fill( toFill, false, nullptr ) )
commit.Push( _( "Fill Zone(s)" ), false, false );
}
SETTINGS_MANAGER m_settingsManager;
std::unique_ptr<BOARD> m_board;
std::unique_ptr<TOOL_MANAGER> m_toolMgr;
std::shared_ptr<DRC_ENGINE> m_DRCEngine;
};
BOOST_FIXTURE_TEST_SUITE( TestZoneFiller, ZONE_FILL_TEST_FIXTURE )
constexpr int delta = KiROUND( 0.006 * IU_PER_MM );
BOOST_AUTO_TEST_CASE( RegressionZoneFillTests )
{
for( const wxString& relPath : { "issue2568", "issue3812", "issue5320", "issue5830",
"issue6284", "issue7086" } )
{
loadBoard( relPath );
for( int fillVersion : { 5, 6 } )
{
fillZones( fillVersion );
std::vector<DRC_ITEM> violations;
m_DRCEngine->SetViolationHandler(
[&]( const std::shared_ptr<DRC_ITEM>& aItem, wxPoint aPos )
{
if( aItem->GetErrorCode() == DRCE_CLEARANCE )
violations.push_back( *aItem );
} );
m_DRCEngine->RunTests( EDA_UNITS::MILLIMETRES, true, false );
if( violations.empty() )
{
BOOST_TEST_MESSAGE( wxString::Format( "Passed: %s (V%d fill algo)",
relPath,
fillVersion ) );
}
else
{
std::map<KIID, EDA_ITEM*> itemMap;
m_board->FillItemMap( itemMap );
for( const DRC_ITEM& item : violations )
{
BOOST_ERROR( item.ShowReport( EDA_UNITS::MILLIMETRES, RPT_SEVERITY_ERROR,
itemMap ) );
}
}
}
}
}
BOOST_AUTO_TEST_CASE( BasicZoneFills )
{
loadBoard( "zone_filler" );
fillZones( 6 );
// Now that the zones are filled we're going to increase the size of -some- pads and
// tracks so that they generate DRC errors. The test then makes sure that those errors
// are generated, and that the other pads and tracks do -not- generate errors.
for( PAD* pad : m_board->Footprints()[0]->Pads() )
{
if( pad->GetName() == "2" || pad->GetName() == "4" || pad->GetName() == "6" )
pad->SetSize( pad->GetSize() + wxSize( delta, delta ) );
}
int ii = 0;
KIID arc8;
KIID arc12;
for( PCB_TRACK* track : m_board->Tracks() )
{
if( track->Type() == PCB_ARC_T )
{
ii++;
if( ii == 8 )
{
arc8 = track->m_Uuid;
track->SetWidth( track->GetWidth() + delta + delta );
}
else if( ii == 12 )
{
arc12 = track->m_Uuid;
track->Move( wxPoint( -delta, -delta ) );
}
}
}
bool foundPad2Error = false;
bool foundPad4Error = false;
bool foundPad6Error = false;
bool foundArc8Error = false;
bool foundArc12Error = false;
bool foundOtherError = false;
m_DRCEngine->InitEngine( wxFileName() ); // Just to be sure to be sure
m_DRCEngine->SetViolationHandler(
[&]( const std::shared_ptr<DRC_ITEM>& aItem, wxPoint aPos )
{
if( aItem->GetErrorCode() == DRCE_CLEARANCE )
{
BOARD_ITEM* item_a = m_board->GetItem( aItem->GetMainItemID() );
PAD* pad_a = dynamic_cast<PAD*>( item_a );
PCB_TRACK* trk_a = dynamic_cast<PCB_TRACK*>( item_a );
BOARD_ITEM* item_b = m_board->GetItem( aItem->GetAuxItemID() );
PAD* pad_b = dynamic_cast<PAD*>( item_b );
PCB_TRACK* trk_b = dynamic_cast<PCB_TRACK*>( item_b );
if( pad_a && pad_a->GetName() == "2" ) foundPad2Error = true;
else if( pad_a && pad_a->GetName() == "4" ) foundPad4Error = true;
else if( pad_a && pad_a->GetName() == "6" ) foundPad6Error = true;
else if( pad_b && pad_b->GetName() == "2" ) foundPad2Error = true;
else if( pad_b && pad_b->GetName() == "4" ) foundPad4Error = true;
else if( pad_b && pad_b->GetName() == "6" ) foundPad6Error = true;
else if( trk_a && trk_a->m_Uuid == arc8 ) foundArc8Error = true;
else if( trk_a && trk_a->m_Uuid == arc12 ) foundArc12Error = true;
else if( trk_b && trk_b->m_Uuid == arc8 ) foundArc8Error = true;
else if( trk_b && trk_b->m_Uuid == arc12 ) foundArc12Error = true;
else foundOtherError = true;
}
} );
m_DRCEngine->RunTests( EDA_UNITS::MILLIMETRES, true, false );
BOOST_CHECK_EQUAL( foundPad2Error, true );
BOOST_CHECK_EQUAL( foundPad4Error, true );
BOOST_CHECK_EQUAL( foundPad6Error, true );
BOOST_CHECK_EQUAL( foundArc8Error, true );
BOOST_CHECK_EQUAL( foundArc12Error, true );
BOOST_CHECK_EQUAL( foundOtherError, false );
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -83,3 +83,9 @@ target_link_libraries( qa_pcbnew_utils PUBLIC
target_compile_definitions( qa_pcbnew_utils target_compile_definitions( qa_pcbnew_utils
PUBLIC PCBNEW PUBLIC PCBNEW
) )
# Pass in the default data location
set_source_files_properties( board_file_utils.cpp PROPERTIES
COMPILE_DEFINITIONS "QA_PCBNEW_DATA_LOCATION=(\"${CMAKE_CURRENT_SOURCE_DIR}/../data\")"
)

View File

@ -35,6 +35,33 @@
namespace KI_TEST namespace KI_TEST
{ {
#ifndef QA_PCBNEW_DATA_LOCATION
#define QA_PCBNEW_DATA_LOCATION "???"
#endif
std::string GetPcbnewTestDataDir()
{
const char* env = std::getenv( "KICAD_TEST_PCBNEW_DATA_DIR" );
std::string fn;
if( !env )
{
// Use the compiled-in location of the data dir (i.e. where the files were at build time)
fn = QA_PCBNEW_DATA_LOCATION;
}
else
{
// Use whatever was given in the env var
fn = env;
}
// Ensure the string ends in / to force a directory interpretation
fn += "/";
return fn;
}
void DumpBoardToFile( BOARD& board, const std::string& aFilename ) void DumpBoardToFile( BOARD& board, const std::string& aFilename )
{ {
PCB_IO io; PCB_IO io;
@ -76,8 +103,9 @@ std::unique_ptr<BOARD_ITEM> ReadBoardItemFromStream( std::istream& aStream )
return board; return board;
} }
std::unique_ptr<BOARD> ReadBoardFromFileOrStream(
const std::string& aFilename, std::istream& aFallback ) std::unique_ptr<BOARD> ReadBoardFromFileOrStream( const std::string& aFilename,
std::istream& aFallback )
{ {
std::istream* in_stream = nullptr; std::istream* in_stream = nullptr;
std::ifstream file_stream; std::ifstream file_stream;
@ -96,4 +124,6 @@ std::unique_ptr<BOARD> ReadBoardFromFileOrStream(
return ReadItemFromStream<BOARD>( *in_stream ); return ReadItemFromStream<BOARD>( *in_stream );
} }
} // namespace KI_TEST } // namespace KI_TEST

View File

@ -38,6 +38,11 @@ class BOARD_ITEM;
*/ */
namespace KI_TEST namespace KI_TEST
{ {
/**
* Utility which returns a path to the data directory where the test board files are stored.
*/
std::string GetPcbnewTestDataDir();
/** /**
* Utility function to simply write a Board out to a file. * Utility function to simply write a Board out to a file.
* *
@ -92,8 +97,8 @@ template <typename ITEM> std::unique_ptr<ITEM> ReadItemFromStream( std::istream&
* @param aFallback: the fallback stream * @param aFallback: the fallback stream
* @return a #BOARD, if successful * @return a #BOARD, if successful
*/ */
std::unique_ptr<BOARD> ReadBoardFromFileOrStream( std::unique_ptr<BOARD> ReadBoardFromFileOrStream( const std::string& aFilename,
const std::string& aFilename, std::istream& aFallback = std::cin ); std::istream& aFallback = std::cin );
} // namespace KI_TEST } // namespace KI_TEST

View File

@ -24,6 +24,7 @@ find_package( Boost COMPONENTS unit_test_framework filesystem system REQUIRED )
set( QA_UTIL_COMMON_SRC set( QA_UTIL_COMMON_SRC
stdstream_line_reader.cpp stdstream_line_reader.cpp
utility_program.cpp utility_program.cpp
mock_pgm.cpp
geometry/line_chain_construction.cpp geometry/line_chain_construction.cpp
geometry/poly_set_construction.cpp geometry/poly_set_construction.cpp