QA: Move to a self-registering plugin system for QA utils

This means that utility programs no longer have to be manually
added to the COMBINED_UTILITY, they self-register their
information at static init time. This is basically the same concept
as the Boost test registration.

All utilities need to do now is register their UTILITY_PROGRAM info
struct with the UTILITY_REGISTRY::Register method. No headers required.
This commit is contained in:
John Beard 2019-11-22 11:58:20 +08:00
parent eb61c1bbc4
commit 1b1e514544
20 changed files with 131 additions and 319 deletions

View File

@ -27,6 +27,7 @@
#define __SHAPE_FILE_IO_H
#include <cstdio>
#include <string>
class SHAPE;

View File

@ -21,28 +21,11 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <qa_utils/utility_program.h>
#include "tools/coroutines/coroutine_tools.h"
#include "tools/io_benchmark/io_benchmark.h"
#include "tools/sexpr_parser/sexpr_parse.h"
/**
* List of registered tools.
*
* This is a pretty rudimentary way to register, but for a simple purpose,
* it's effective enough. When you have a new tool, add it to this list.
*/
const static std::vector<KI_TEST::UTILITY_PROGRAM*> known_tools = {
&coroutine_tool,
&io_benchmark_tool,
&sexpr_parser_tool,
};
#include <qa_utils/utility_registry.h>
int main( int argc, char** argv )
{
KI_TEST::COMBINED_UTILITY c_util( known_tools );
KI_TEST::COMBINED_UTILITY c_util;
return c_util.HandleCommandLine( argc, argv );
}

View File

@ -1,10 +0,0 @@
#ifndef COROUTINES_UTILTY_H
#define COROUTINES_UTILTY_H
#include <qa_utils/utility_program.h>
/// A tool to test a simple coroutine
extern KI_TEST::UTILITY_PROGRAM coroutine_tool;
#endif

View File

@ -21,17 +21,19 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "coroutine_tools.h"
#include <cstdio>
#include <string>
#include <common.h>
#include <functional>
#include <tool/coroutine.h>
#include <qa_utils/utility_registry.h>
#include <common.h>
#include <wx/cmdline.h>
#include <cstdio>
#include <string>
typedef COROUTINE<int, int> MyCoroutine;
@ -131,8 +133,8 @@ static int coroutine_main_func( int argc, char** argv )
/*
* Define the tool interface
*/
KI_TEST::UTILITY_PROGRAM coroutine_tool = {
"coroutine",
"Test a simple coroutine",
coroutine_main_func,
};
static bool registered = UTILITY_REGISTRY::Register( {
"coroutine",
"Test a simple coroutine",
coroutine_main_func,
} );

View File

@ -21,8 +21,6 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "io_benchmark.h"
#include <wx/wx.h>
#include <richio.h>
@ -37,6 +35,7 @@
#include <wx/filename.h>
#include <qa_utils/stdstream_line_reader.h>
#include <qa_utils/utility_registry.h>
using CLOCK = std::chrono::steady_clock;
@ -423,8 +422,8 @@ int io_benchmark_func( int argc, char* argv[] )
}
KI_TEST::UTILITY_PROGRAM io_benchmark_tool = {
"io_benchmark",
"Benchmark various kinds of IO methods",
io_benchmark_func,
};
static bool registered = UTILITY_REGISTRY::Register( {
"io_benchmark",
"Benchmark various kinds of IO methods",
io_benchmark_func,
} );

View File

@ -1,31 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2018-2019 KiCad Developers, see CHANGELOG.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
*/
#ifndef QA_COMMON_TOOLS_IO_BENCHMARK__H
#define QA_COMMON_TOOLS_IO_BENCHMARK__H
#include <qa_utils/utility_program.h>
extern KI_TEST::UTILITY_PROGRAM io_benchmark_tool;
#endif // QA_COMMON_TOOLS_IO_BENCHMARK__H

View File

@ -27,10 +27,10 @@
* for benchmarking, testing, etc.
*/
#include "sexpr_parse.h"
#include <sexpr/sexpr_parser.h>
#include <qa_utils/utility_registry.h>
#include <common.h>
#include <profile.h>
@ -154,8 +154,8 @@ int sexpr_parser_func( int argc, char* argv[] )
}
KI_TEST::UTILITY_PROGRAM sexpr_parser_tool = {
"sexpr_parser",
"Benchmark s-expression parsing",
sexpr_parser_func,
};
static bool registered = UTILITY_REGISTRY::Register( {
"sexpr_parser",
"Benchmark s-expression parsing",
sexpr_parser_func,
} );

View File

@ -1,31 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 KiCad Developers, see CHANGELOG.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
*/
#ifndef QA_COMMON_TOOLS_SEXPR_PARSE__H
#define QA_COMMON_TOOLS_SEXPR_PARSE__H
#include <qa_utils/utility_program.h>
extern KI_TEST::UTILITY_PROGRAM sexpr_parser_tool;
#endif // QA_COMMON_TOOLS_SEXPR_PARSE__H

View File

@ -23,28 +23,9 @@
#include <qa_utils/utility_program.h>
#include "tools/drc_tool/drc_tool.h"
#include "tools/pcb_parser/pcb_parser_tool.h"
#include "tools/polygon_generator/polygon_generator.h"
#include "tools/polygon_triangulation/polygon_triangulation.h"
/**
* List of registered tools.
*
* This is a pretty rudimentary way to register, but for a simple purpose,
* it's effective enough. When you have a new tool, add it to this list.
*/
const static std::vector<KI_TEST::UTILITY_PROGRAM*> known_tools = {
&drc_tool,
&pcb_parser_tool,
&polygon_generator_tool,
&polygon_triangulation_tool,
};
int main( int argc, char** argv )
{
KI_TEST::COMBINED_UTILITY c_util( known_tools );
KI_TEST::COMBINED_UTILITY c_util;
return c_util.HandleCommandLine( argc, argv );
}

View File

@ -21,8 +21,6 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "drc_tool.h"
#include <cstdio>
#include <string>
@ -38,6 +36,7 @@
#include <drc/drc_marker_factory.h>
#include <qa_utils/stdstream_line_reader.h>
#include <qa_utils/utility_registry.h>
using DRC_DURATION = std::chrono::microseconds;
@ -332,11 +331,5 @@ int drc_main_func( int argc, char** argv )
}
/*
* Define the tool interface
*/
KI_TEST::UTILITY_PROGRAM drc_tool = {
"drc",
"Run selected DRC function on a PCB",
drc_main_func,
};
static bool registered = UTILITY_REGISTRY::Register(
{ "drc", "Run selected DRC function on a PCB", drc_main_func } );

View File

@ -1,32 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2018 KiCad Developers, see CHANGELOG.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
*/
#ifndef PCBNEW_TOOLS_DRC_TOOL_H
#define PCBNEW_TOOLS_DRC_TOOL_H
#include <qa_utils/utility_program.h>
/// A tool to run DRC tools on KiCad PCBs from the command line
extern KI_TEST::UTILITY_PROGRAM drc_tool;
#endif //PCBNEW_TOOLS_DRC_TOOL_H

View File

@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "pcb_parser_tool.h"
#include <qa_utils/utility_registry.h>
#include <cstdio>
#include <string>
@ -39,6 +39,8 @@
#include <wx/cmdline.h>
#include <qa_utils/stdstream_line_reader.h>
#include <qa_utils/utility_registry.h>
using PARSE_DURATION = std::chrono::microseconds;
@ -163,11 +165,5 @@ int pcb_parser_main_func( int argc, char** argv )
}
/*
* Define the tool interface
*/
KI_TEST::UTILITY_PROGRAM pcb_parser_tool = {
"pcb_parser",
"Parse a KiCad PCB file",
pcb_parser_main_func,
};
static bool registered = UTILITY_REGISTRY::Register(
{ "pcb_parser", "Parse a KiCad PCB file", pcb_parser_main_func } );

View File

@ -1,32 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2018 KiCad Developers, see CHANGELOG.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
*/
#ifndef PCBNEW_TOOLS_PCB_PARSER_UTILITY_H
#define PCBNEW_TOOLS_PCB_PARSER_UTILITY_H
#include <qa_utils/utility_program.h>
/// A tool to parse kicad PCBs from the command line
extern KI_TEST::UTILITY_PROGRAM pcb_parser_tool;
#endif //PCBNEW_TOOLS_PCB_PARSER_UTILITY_H

View File

@ -23,14 +23,14 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "polygon_generator.h"
#include <geometry/shape_file_io.h>
#include <geometry/shape_line_chain.h>
#include <geometry/shape_poly_set.h>
#include <pcbnew_utils/board_file_utils.h>
#include <qa_utils/utility_registry.h>
#include <class_board.h>
#include <class_drawsegment.h>
#include <class_module.h>
@ -102,11 +102,9 @@ int polygon_gererator_main( int argc, char* argv[] )
return KI_TEST::RET_CODES::OK;
}
/*
* Define the tool interface
*/
KI_TEST::UTILITY_PROGRAM polygon_generator_tool = {
"polygon_generator",
"Dump board geometry as a set of polygons",
polygon_gererator_main,
};
static bool registered = UTILITY_REGISTRY::Register( {
"polygon_generator",
"Dump board geometry as a set of polygons",
polygon_gererator_main,
} );

View File

@ -1,32 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 KiCad Developers, see CHANGELOG.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
*/
#ifndef PCBNEW_TOOLS_POLYGON_GENERATOR_UTILITY_H
#define PCBNEW_TOOLS_POLYGON_GENERATOR_UTILITY_H
#include <qa_utils/utility_program.h>
/// A tool to parse kicad PCBs from the command line
extern KI_TEST::UTILITY_PROGRAM polygon_generator_tool;
#endif //PCBNEW_TOOLS_POLYGON_GENERATOR_UTILITY_H

View File

@ -22,13 +22,13 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "polygon_triangulation.h"
#include <geometry/shape_line_chain.h>
#include <geometry/shape_poly_set.h>
#include <pcbnew_utils/board_file_utils.h>
#include <qa_utils/utility_registry.h>
#include <class_board.h>
#include <class_zone.h>
#include <profile.h>
@ -269,11 +269,9 @@ int polygon_triangulation_main( int argc, char *argv[] )
return KI_TEST::RET_CODES::OK;
}
/*
* Define the tool interface
*/
KI_TEST::UTILITY_PROGRAM polygon_triangulation_tool = {
"polygon_triangulation",
"Process polygon trianguation on a PCB",
polygon_triangulation_main,
};
static bool registered = UTILITY_REGISTRY::Register( {
"polygon_triangulation",
"Process polygon triangulation on a PCB",
polygon_triangulation_main,
} );

View File

@ -1,32 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 KiCad Developers, see CHANGELOG.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
*/
#ifndef PCBNEW_TOOLS_POLYGON_TRIANGULATION_UTILITY_H
#define PCBNEW_TOOLS_POLYGON_TRIANGULATION_UTILITY_H
#include <qa_utils/utility_program.h>
/// A tool to parse kicad PCBs from the command line
extern KI_TEST::UTILITY_PROGRAM polygon_triangulation_tool;
#endif //PCBNEW_TOOLS_POLYGON_TRIANGULATION_UTILITY_H

View File

@ -70,6 +70,15 @@ struct UTILITY_PROGRAM
/// A function that provides the program for a given command line
using FUNC = std::function<int( int argc, char** argv )>;
UTILITY_PROGRAM( const std::string& aName, const std::string& aDesc, FUNC aMainFunc )
: m_name( aName ), m_desc( aDesc ), m_func( aMainFunc )
{
}
UTILITY_PROGRAM() : m_func( nullptr )
{
}
/// The name of the program (this is used to select one)
std::string m_name;
@ -88,9 +97,6 @@ struct UTILITY_PROGRAM
class COMBINED_UTILITY
{
public:
using UTIL_LIST = std::vector<UTILITY_PROGRAM*>;
COMBINED_UTILITY( const UTIL_LIST& aSubUtils );
/**
* Take in a a command line and:
@ -125,9 +131,6 @@ private:
* @param os stream to print to
*/
void printUsage( char* name, std::ostream& os ) const;
/// List of known sub-utils
const UTIL_LIST& m_subUtils;
};
} // namespace KI_TEST

View File

@ -0,0 +1,55 @@
#ifndef UTILITY_REGISTRY_H
#define UTILITY_REGISTRY_H
#include <qa_utils/utility_program.h>
#include <map>
#include <memory>
#include <string>
/**
* A class to handle the registration of utility programs
*/
class UTILITY_REGISTRY
{
public:
using PLUGIN_MAP = std::map<std::string, KI_TEST::UTILITY_PROGRAM>;
/**
* Register a utility program factory function against an ID string.
*
* This will be used to create the required utility program if needed.
*
* @param aName the name of the utility program
* @param aFactory the factory function that will construct the plugin
* @return true if registered OK
*/
static bool Register( const KI_TEST::UTILITY_PROGRAM& aProgInfo )
{
PLUGIN_MAP& map = GetInfoMap();
if( map.find( aProgInfo.m_name ) == map.end() )
{
map[aProgInfo.m_name] = aProgInfo;
return true;
}
// Already exists in map
return false;
}
/**
* Accessor for the static registry map.
* This is needed to prevent the Static Init Order Fiasco that might occur
* if we just accessed a static class member.
*/
static PLUGIN_MAP& GetInfoMap()
{
static PLUGIN_MAP info_map;
return info_map;
}
};
#endif // UTILITY_REGISTRY_H

View File

@ -21,32 +21,35 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <qa_utils/utility_program.h>
#include <qa_utils/utility_registry.h>
#include <wx/msgout.h>
namespace KI_TEST
{
COMBINED_UTILITY::COMBINED_UTILITY( const UTIL_LIST& aSubUtils ) : m_subUtils( aSubUtils )
{
}
void COMBINED_UTILITY::showSubUtilityList( std::ostream& os ) const
{
for( const auto& tool : m_subUtils )
for( const auto& it : UTILITY_REGISTRY::GetInfoMap() )
{
os << tool->m_name << ": \t" << tool->m_desc << std::endl;
const UTILITY_PROGRAM& prog = it.second;
os << "Reg: " << prog.m_name << ": \t" << prog.m_desc << std::endl;
}
}
UTILITY_PROGRAM::FUNC* COMBINED_UTILITY::findSubUtility( const std::string& aName ) const
{
for( const auto& tool : m_subUtils )
try
{
if( tool->m_name == aName )
return &tool->m_func;
UTILITY_PROGRAM& prog = UTILITY_REGISTRY::GetInfoMap().at( aName );
return &prog.m_func;
}
catch( const std::out_of_range& e )
{
// not found in map
}
return nullptr;