Browse Source

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.)
6.0.7
Jeff Young 4 years ago
parent
commit
8c69a856fc
  1. 45
      pcbnew/board_commit.cpp
  2. 1
      pcbnew/drc/drc_engine.cpp
  3. 3986
      qa/data/issue2568.kicad_pcb
  4. 92615
      qa/data/issue3812.kicad_pcb
  5. 453
      qa/data/issue3812.kicad_pro
  6. 5982
      qa/data/issue5320.kicad_pcb
  7. 391
      qa/data/issue5320.kicad_pro
  8. 8151
      qa/data/issue5830.kicad_pcb
  9. 422
      qa/data/issue5830.kicad_pro
  10. 72671
      qa/data/issue6284.kicad_pcb
  11. 2060
      qa/data/issue7086.kicad_pcb
  12. 2169
      qa/data/zone_filler.kicad_pcb
  13. 18
      qa/pcbnew/CMakeLists.txt
  14. 233
      qa/pcbnew/test_zone_filler.cpp
  15. 6
      qa/pcbnew_utils/CMakeLists.txt
  16. 34
      qa/pcbnew_utils/board_file_utils.cpp
  17. 9
      qa/pcbnew_utils/include/pcbnew_utils/board_file_utils.h
  18. 1
      qa/qa_utils/CMakeLists.txt

45
pcbnew/board_commit.cpp

@ -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 );
break;
@ -221,7 +221,8 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
if( parentGroup && !( parentGroup->GetFlags() & STRUCT_DELETED ) )
parentGroup->RemoveItem( boardItem );
view->Remove( boardItem );
if( view )
view->Remove( boardItem );
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_MARKER_T: // a marker used to show something
case PCB_ZONE_T:
view->Remove( boardItem );
if( view )
view->Remove( boardItem );
if( !( changeFlags & CHT_DONE ) )
{
@ -261,7 +263,10 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
wxASSERT( !m_isFootprintEditor );
FOOTPRINT* footprint = static_cast<FOOTPRINT*>( boardItem );
view->Remove( footprint );
if( view )
view->Remove( footprint );
footprint->ClearFlags();
if( !( changeFlags & CHT_DONE ) )
@ -273,7 +278,8 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
break;
case PCB_GROUP_T:
view->Remove( boardItem );
if( view )
view->Remove( boardItem );
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->Update( boardItem );
view->Update( boardItem );
if( m_isFootprintEditor )
if( view )
{
static_cast<FOOTPRINT*>( boardItem )->RunOnChildren(
[&]( BOARD_ITEM* aChild )
{
view->Update( aChild );
});
view->Update( boardItem );
if( m_isFootprintEditor )
{
static_cast<FOOTPRINT*>( boardItem )->RunOnChildren(
[&]( BOARD_ITEM* aChild )
{
view->Update( aChild );
});
}
}
itemsChanged.push_back( boardItem );
@ -359,7 +369,9 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
connectivity->RecalculateRatsnest( this );
connectivity->ClearDynamicRatsnest();
frame->GetCanvas()->RedrawRatsnest();
if( frame )
frame->GetCanvas()->RedrawRatsnest();
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
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 )
{
@ -384,7 +396,8 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
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 )
frame->OnModify();
else
else if( frame )
frame->Update3DView( true, frame->GetDisplayOptions().m_Live3DRefresh );
clear();

1
pcbnew/drc/drc_engine.cpp

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

3986
qa/data/issue2568.kicad_pcb
File diff suppressed because it is too large
View File

92615
qa/data/issue3812.kicad_pcb
File diff suppressed because it is too large
View File

453
qa/data/issue3812.kicad_pro

@ -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
File diff suppressed because it is too large
View File

391
qa/data/issue5320.kicad_pro

@ -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
File diff suppressed because it is too large
View File

422
qa/data/issue5830.kicad_pro

@ -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
File diff suppressed because it is too large
View File

2060
qa/data/issue7086.kicad_pcb
File diff suppressed because it is too large
View File

2169
qa/data/zone_filler.kicad_pcb
File diff suppressed because it is too large
View File

18
qa/pcbnew/CMakeLists.txt

@ -37,6 +37,7 @@ set( QA_PCBNEW_SRCS
test_lset.cpp
test_pad_naming.cpp
test_libeval_compiler.cpp
test_zone_filler.cpp
drc/test_drc_courtyard_invalid.cpp
drc/test_drc_courtyard_overlap.cpp
@ -64,6 +65,23 @@ target_compile_definitions( qa_pcbnew
# multi-threaded build
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
qa_pcbnew_utils
3d-viewer

233
qa/pcbnew/test_zone_filler.cpp

@ -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()

6
qa/pcbnew_utils/CMakeLists.txt

@ -83,3 +83,9 @@ target_link_libraries( qa_pcbnew_utils PUBLIC
target_compile_definitions( qa_pcbnew_utils
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\")"
)

34
qa/pcbnew_utils/board_file_utils.cpp

@ -35,6 +35,33 @@
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 )
{
PCB_IO io;
@ -76,8 +103,9 @@ std::unique_ptr<BOARD_ITEM> ReadBoardItemFromStream( std::istream& aStream )
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::ifstream file_stream;
@ -96,4 +124,6 @@ std::unique_ptr<BOARD> ReadBoardFromFileOrStream(
return ReadItemFromStream<BOARD>( *in_stream );
}
} // namespace KI_TEST

9
qa/pcbnew_utils/include/pcbnew_utils/board_file_utils.h

@ -38,6 +38,11 @@ class BOARD_ITEM;
*/
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.
*
@ -92,8 +97,8 @@ template <typename ITEM> std::unique_ptr<ITEM> ReadItemFromStream( std::istream&
* @param aFallback: the fallback stream
* @return a #BOARD, if successful
*/
std::unique_ptr<BOARD> ReadBoardFromFileOrStream(
const std::string& aFilename, std::istream& aFallback = std::cin );
std::unique_ptr<BOARD> ReadBoardFromFileOrStream( const std::string& aFilename,
std::istream& aFallback = std::cin );
} // namespace KI_TEST

1
qa/qa_utils/CMakeLists.txt

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

Loading…
Cancel
Save