KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_drc_issue24264.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
22
23#include <board.h>
25#include <drc/drc_engine.h>
26#include <drc/drc_item.h>
27#include <drc/drc_report.h>
28#include <pcb_marker.h>
30
31#include <fstream>
32#include <sstream>
33
34#include <json_common.h>
35
36
38{
40 std::unique_ptr<BOARD> m_board;
41};
42
43
44// https://gitlab.com/kicad/code/kicad/-/issues/24264
45//
46// A custom rule that pins a constraint to "(severity exclusion)" should produce a marker that
47// appears in the JSON DRC report as excluded. Before the fix, the JSON output reported these
48// markers as plain errors with "excluded": false, while the interactive DRC dialog correctly
49// treated them as exclusions.
50BOOST_FIXTURE_TEST_CASE( DRCRuleSeverityExclusionMarkedExcluded, ISSUE24264_FIXTURE )
51{
52 KI_TEST::LoadBoard( m_settingsManager, "issue24264/issue24264", m_board );
53
54 BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
55
56 // Silence unrelated checks that can fire on the imported reproduction board
61
62 auto& drcEngine = bds.m_DRCEngine;
63
64 BOOST_REQUIRE( drcEngine );
65
66 drcEngine->SetViolationHandler(
67 [&]( const std::shared_ptr<DRC_ITEM>& aItem, const VECTOR2I& aPos, int aLayer,
68 const std::function<void( PCB_MARKER* )>& aPathGenerator )
69 {
70 PCB_MARKER* marker = new PCB_MARKER( aItem, aPos, aLayer );
71
72 if( aPathGenerator )
73 aPathGenerator( marker );
74
75 m_board->Add( marker );
76 } );
77
78 drcEngine->RunTests( EDA_UNITS::MM, true, false );
79 drcEngine->ClearViolationHandler();
80
81 // Find the rule-driven courtyard exclusion marker
82 int courtyardCount = 0;
83 int courtyardExcluded = 0;
84
85 for( PCB_MARKER* marker : m_board->Markers() )
86 {
87 if( marker->GetRCItem()->GetErrorCode() == DRCE_OVERLAPPING_FOOTPRINTS )
88 {
89 ++courtyardCount;
90
91 if( marker->GetSeverity() == RPT_SEVERITY_EXCLUSION )
92 ++courtyardExcluded;
93 }
94 }
95
96 BOOST_TEST_MESSAGE( "Courtyard markers found: " << courtyardCount
97 << ", excluded: " << courtyardExcluded );
98
99 BOOST_REQUIRE_GE( courtyardCount, 1 );
100 BOOST_CHECK_EQUAL( courtyardExcluded, courtyardCount );
101
102 // Now exercise the report writer path used by `kicad-cli pcb drc` and check the JSON output
103 auto markersProvider = std::make_shared<DRC_ITEMS_PROVIDER>(
105 auto ratsnestProvider = std::make_shared<DRC_ITEMS_PROVIDER>(
106 m_board.get(), MARKER_BASE::MARKER_RATSNEST );
107 auto fpWarningsProvider = std::make_shared<DRC_ITEMS_PROVIDER>(
108 m_board.get(), MARKER_BASE::MARKER_PARITY );
109
111 markersProvider->SetSeverities( allSev );
112 ratsnestProvider->SetSeverities( allSev );
113 fpWarningsProvider->SetSeverities( allSev );
114
115 DRC_REPORT report( m_board.get(), EDA_UNITS::MM, markersProvider, ratsnestProvider,
116 fpWarningsProvider );
117
118 // wxFileName::CreateTempFileName reserves a unique path; we write directly to it instead
119 // of swapping the extension so we do not leave the reserved file behind.
120 wxString jsonPath = wxFileName::CreateTempFileName( wxT( "kicad-drc-24264-json-" ) );
121 wxString textPath = wxFileName::CreateTempFileName( wxT( "kicad-drc-24264-text-" ) );
122
124 BOOST_REQUIRE( report.WriteTextReport( textPath ) );
125
126 std::ifstream reportStream( jsonPath.fn_str() );
127 BOOST_REQUIRE( reportStream.is_open() );
128
129 nlohmann::json reportJson;
130 reportStream >> reportJson;
131 reportStream.close();
132 wxRemoveFile( jsonPath );
133
134 BOOST_REQUIRE( reportJson.contains( "violations" ) );
135
136 int sawCourtyardExcluded = 0;
137
138 for( const auto& violation : reportJson["violations"] )
139 {
140 if( violation.value( "type", std::string() ) == "courtyards_overlap" )
141 {
142 BOOST_CHECK( violation.value( "excluded", false ) );
143
144 if( violation.value( "excluded", false ) )
145 ++sawCourtyardExcluded;
146 }
147 }
148
149 BOOST_CHECK_EQUAL( sawCourtyardExcluded, courtyardCount );
150
151 // Text report should also surface the exclusion suffix from RC_ITEM::ShowReport()
152 std::ifstream textStream( textPath.fn_str() );
153 BOOST_REQUIRE( textStream.is_open() );
154
155 std::stringstream textBuf;
156 textBuf << textStream.rdbuf();
157 textStream.close();
158 wxRemoveFile( textPath );
159
160 const std::string textReport = textBuf.str();
161
162 BOOST_TEST_MESSAGE( "Text report excerpt:\n" << textReport );
163 BOOST_CHECK( textReport.find( "courtyards_overlap" ) != std::string::npos );
164 BOOST_CHECK( textReport.find( "(excluded)" ) != std::string::npos );
165}
Container for design settings for a BOARD object.
std::map< int, SEVERITY > m_DRCSeverities
std::shared_ptr< DRC_ENGINE > m_DRCEngine
bool WriteJsonReport(const wxString &aFullFileName)
bool WriteTextReport(const wxString &aFullFileName)
@ MARKER_DRAWING_SHEET
Definition marker_base.h:52
@ DRCE_UNCONNECTED_ITEMS
Definition drc_item.h:36
@ DRCE_LIB_FOOTPRINT_ISSUES
Definition drc_item.h:79
@ DRCE_OVERLAPPING_FOOTPRINTS
Definition drc_item.h:62
@ DRCE_FOOTPRINT_TYPE_MISMATCH
Definition drc_item.h:78
@ DRCE_LIB_FOOTPRINT_MISMATCH
Definition drc_item.h:80
void LoadBoard(SETTINGS_MANAGER &aSettingsManager, const wxString &aRelPath, std::unique_ptr< BOARD > &aBoard)
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_EXCLUSION
@ RPT_SEVERITY_IGNORE
std::unique_ptr< BOARD > m_board
SETTINGS_MANAGER m_settingsManager
BOOST_FIXTURE_TEST_CASE(DRCRuleSeverityExclusionMarkedExcluded, ISSUE24264_FIXTURE)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_TEST_MESSAGE("\n=== Real-World Polygon PIP Benchmark ===\n"<< formatTable(table))
BOOST_CHECK_EQUAL(result, "25.4")
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683