KiCad PCB EDA Suite
Loading...
Searching...
No Matches
qa_pns_regressions_main.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.
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, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#define BOOST_TEST_NO_MAIN
25
26#include <wx/cmdline.h>
27#include <wx/stdstream.h>
28#include <wx/wfstream.h>
29#include <wx/textfile.h>
30
31#include <io/io_utils.h>
32
36#include <wx/dir.h>
37
38#include "pns_log_file.h"
40
41#include <boost/test/unit_test.hpp>
42
43using namespace boost::unit_test;
44
45std::map<wxString, wxString> g_testBoards;
47
49{
50 PNS_TEST_CASE( const wxString & aName, const wxString& aPath ) : m_name( aName ), m_dataPath( aPath ){};
51
52 wxString GetDataPath() const { return m_dataPath; }
53 wxString GetName() const { return m_name; }
54 wxString m_dataPath;
55 wxString m_name;
56};
57
58
77
78
80{
81public:
82 static bool RunTest( PNS_TEST_CASE* aTestData )
83 {
84 BOOST_TEST_MESSAGE( "Running testcase " << aTestData->GetName() );
85
86 PNS_LOG_FILE logFile;
87 PNS_LOG_PLAYER player;
88
89 auto hash = logFile.GetLogBoardHash( aTestData->GetDataPath() );
90
91 wxString boardFilename;
92
93 if( hash.has_value() )
94 {
95 auto it = g_testBoards.find( *hash );
96 if ( it != g_testBoards.end() )
97 {
98 boardFilename = it->second;
99 BOOST_TEST_MESSAGE( "found matching board: " << boardFilename );
100 }
101 }
102
103 if( !logFile.Load( wxString( aTestData->GetDataPath() ), m_logger.m_Reporter, boardFilename ) )
104 {
105 BOOST_TEST_ERROR( "Failed to load test " << aTestData->GetName() << " from " << aTestData->GetDataPath() );
106 return false;
107 }
108
109 player.SetReporter( m_logger.m_Reporter );
110 player.ReplayLog( &logFile, 0 );
111
112 auto cstate = player.GetRouterUpdatedItems();
113 auto expected = logFile.GetExpectedResult();
114
115 BOOST_TEST_MESSAGE( "- expected: " << expected.m_heads.size() << " heads, " << expected.m_removedIds.size()
116 << " removed items, " << expected.m_addedItems.size() << " added items" );
117 BOOST_TEST_MESSAGE( "- computed: " << cstate.m_heads.size() << " heads, " << cstate.m_removedIds.size()
118 << " removed items, " << cstate.m_addedItems.size() << " added items" );
119
120 bool pass = cstate.Compare( expected );
121
122 BOOST_CHECK( pass );
123
124 return pass;
125 }
126
128};
129
130
132
133std::vector<wxString> scanSubdirs( const wxString& absPath, bool aFiles, wxString filespec = wxEmptyString )
134{
135 std::vector<wxString> rv;
136
137 wxDir dir( absPath );
138 if( !dir.IsOpened() )
139 {
140 BOOST_TEST_ERROR( "Failed to open directory: " << absPath );
141 return rv;
142 }
143
144 wxString dirName;
145
146 bool hasFiles = dir.GetFirst( &dirName, filespec, aFiles ? wxDIR_FILES : wxDIR_DIRS );
147 while( hasFiles )
148 {
149 rv.push_back( dirName );
150 hasFiles = dir.GetNext( &dirName );
151 }
152
153 return rv;
154}
155
156void scanAndHashBoards( const wxString& aPath )
157{
158 for( const wxString& brdFile : scanSubdirs( aPath, true, wxT("*.kicad_pcb") ) )
159 {
160 wxFileName path ( aPath );
161 path.SetName( brdFile );
162 std::optional<wxString> hash = IO_UTILS::fileHashMMH3( path.GetFullPath() );
163 if( hash )
164 {
165 BOOST_TEST_MESSAGE("- file: " << std::left << std::setw(50) << brdFile << " hash: " << ( *hash ) );
166 g_testBoards[ *hash ] = path.GetFullPath();
167 }
168 }
169}
170
171std::vector<PNS_TEST_CASE*> createTestCases()
172{
173 std::vector<PNS_TEST_CASE*> testCases;
174
175 wxFileName absPath( KI_TEST::GetPcbnewTestDataDir() );
176 absPath.AppendDir (wxT("pns_regressions"));
177
178 wxFileName boardsPath( absPath );
179 boardsPath.AppendDir(wxT("boards"));
180
181 scanAndHashBoards( boardsPath.GetFullPath() );
182
183 for( const wxString& subdir : scanSubdirs( absPath.GetFullPath(), false ) )
184 {
185 if( !subdir.CmpNoCase( wxT("boards") ) )
186 continue;
187
188 wxFileName path( absPath );
189 path.AppendDir( subdir );
190
191 for( const wxString& logName: scanSubdirs( path.GetFullPath(), true, wxT("*.log") ) )
192 {
193 wxFileName logPath( path );
194 logPath.SetName( logName );
195
196 BOOST_TEST_MESSAGE( "Add case " << logPath.GetFullPath() );
197
198 testCases.push_back( new PNS_TEST_CASE( subdir, logPath.GetFullPath() ) );
199 }
200 }
201
202 return testCases;
203}
204
205
207{
208 test_suite* pnsTestSuite = BOOST_TEST_SUITE( "pns_regressions" );
209
210 auto testCases = createTestCases();
211
212 for( auto& c : testCases )
213 {
214 pnsTestSuite->add(
215 BOOST_TEST_CASE_NAME( std::bind( &PNS_TEST_FIXTURE::RunTest, c ), c->GetName().ToStdString() ) );
216 }
217
218 framework::master_test_suite().p_name.value = "P&S router regressions";
219 framework::master_test_suite().add( pnsTestSuite );
220 return true;
221}
222
223
224int main( int argc, char* argv[] )
225{
226 return unit_test_main( &init_pns_test_suite, argc, argv );
227}
228
General utilities for PCB file IO for QA programs.
KI_TEST::CONSOLE_LOG * m_Log
KI_TEST::CONSOLE_MSG_REPORTER * m_Reporter
const std::optional< wxString > GetLogBoardHash(const wxString &logFileName)
const COMMIT_STATE & GetExpectedResult() const
bool Load(const wxFileName &logFileName, REPORTER *aRpt, const wxString boardFileName=wxT(""))
const PNS_LOG_FILE::COMMIT_STATE GetRouterUpdatedItems()
void ReplayLog(PNS_LOG_FILE *aLog, int aStartEventIndex=0, int aFrom=0, int aTo=-1, bool aUpdateExpectedResult=false)
void SetReporter(REPORTER *aReporter)
std::optional< wxString > fileHashMMH3(const wxString &aFilePath)
Calculates an MMH3 hash of a given file.
Definition io_utils.cpp:90
std::string GetPcbnewTestDataDir()
Utility which returns a path to the data directory where the test board files are stored.
std::vector< PNS_TEST_CASE * > createTestCases()
void scanAndHashBoards(const wxString &aPath)
std::map< wxString, wxString > g_testBoards
bool init_pns_test_suite()
bool g_showDetailedLog
std::vector< wxString > scanSubdirs(const wxString &absPath, bool aFiles, wxString filespec=wxEmptyString)
wxString GetName() const
PNS_TEST_CASE(const wxString &aName, const wxString &aPath)
wxString GetDataPath() const
static bool RunTest(PNS_TEST_CASE *aTestData)
static FIXTURE_LOGGER m_logger
std::string path
VECTOR3I expected(15, 30, 45)
BOOST_TEST_MESSAGE("\n=== Real-World Polygon PIP Benchmark ===\n"<< formatTable(table))