KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_symbol_library.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 * @author Jon Evans <[email protected]>
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <fmt/format.h>
22#include <mock_pgm_base.h>
24#include <pgm_base.h>
25#include "eeschema_test_utils.h"
26
28
29// NOTE: this is for the new symbol library manager adapter and
30// library manager system. There is also test_symbol_library_manager.cpp
31// which is for the old code; that one can be removed once the old
32// library manager doesn't exist anymore
33
34
38
39BOOST_FIXTURE_TEST_SUITE( SymbolLibrary, TEST_SYMBOL_LIBRARY_FIXTURE )
40
41BOOST_AUTO_TEST_CASE( ProjectLibraryTable )
42{
43 if( !wxGetEnv( wxT( "KICAD_CONFIG_HOME_IS_QA" ), nullptr ) )
44 {
45 BOOST_TEST_MESSAGE( "QA test is running using unknown config home; skipping" );
46 return;
47 }
48
49 LIBRARY_MANAGER manager;
50 manager.LoadGlobalTables();
51
52 wxFileName fn( KI_TEST::GetTestDataRootDir(), "test_project.kicad_sch" );
53 fn.AppendDir( "libraries" );
54 fn.AppendDir( "test_project" );
55
56 std::vector<LIBRARY_TABLE_ROW*> rows = manager.Rows( LIBRARY_TABLE_TYPE::SYMBOL );
57
58 BOOST_REQUIRE( rows.size() == 3 );
59 BOOST_REQUIRE( rows[0]->Nickname() == "Device" );
60
61 LoadSchematic( fn.GetFullPath() );
62 PROJECT& project = SettingsManager().Prj();
63 manager.LoadProjectTables( project.GetProjectDirectory() );
64
65 rows = manager.Rows( LIBRARY_TABLE_TYPE::SYMBOL );
66
67 BOOST_REQUIRE( rows.size() == 4 );
68 BOOST_REQUIRE( rows[0]->Nickname() == "Device" );
69 BOOST_REQUIRE( rows[0]->URI() == "${KIPRJMOD}/Device.kicad_sym" );
70
71 SYMBOL_LIBRARY_ADAPTER adapter( manager );
72 adapter.LoadOne( "Device" );
73
74 std::vector<LIB_SYMBOL*> symbols = adapter.GetSymbols( "Device" );
75
76 // Check that the project's copy of Device is the one being returned
77 BOOST_REQUIRE( symbols.size() == 3 );
78
79 symbols = adapter.GetSymbols( "power" );
80 BOOST_TEST_MESSAGE( symbols.size() );
81
82 BOOST_REQUIRE( adapter.LoadSymbol( "Device", "R" ) );
83}
84
85
86// If you want to do benchmarking, it can be useful to run this testcase standalone with
87// the KICAD_CONFIG_HOME and KICAD9_SYMBOL_DIR environment variables set to an actual KiCad
88// installation so that you can benchmark a typical load
90{
91 LIBRARY_MANAGER manager;
92 manager.LoadGlobalTables();
93
95 SYMBOL_LIBRARY_ADAPTER adapter( manager );
96
97 auto tstart = std::chrono::high_resolution_clock::now();
98 adapter.AsyncLoad();
99
100 constexpr static int interval = 250;
101 constexpr static int timeLimit = 20000;
102 int elapsed = 0;
103
104 while( true )
105 {
106 std::this_thread::sleep_for( std::chrono::milliseconds( interval ) );
107
108 if( std::optional<float> loadStatus = adapter.AsyncLoadProgress(); loadStatus.has_value() )
109 {
110 BOOST_TEST_MESSAGE( fmt::format( "Loading libraries: ({:.1f}%)", *loadStatus * 100 ) );
111
112 if( loadStatus >= 1 )
113 break;
114 }
115 else
116 {
117 // Just informational; this could be fine when running in a QA context
118 BOOST_TEST_MESSAGE( "Async load not in progress" );
119 break;
120 }
121
122 elapsed += interval;
123
124 if( elapsed > timeLimit )
125 {
126 BOOST_TEST_FAIL( "Exceeded timeout" );
127 break;
128 }
129 }
130
131 auto duration = std::chrono::high_resolution_clock::now() - tstart;
132
134 fmt::format( "took {}ms",
135 std::chrono::duration_cast<std::chrono::milliseconds>( duration ).count() ) );
136
137 adapter.BlockUntilLoaded();
138
139 std::vector<LIBRARY_TABLE_ROW*> rows = manager.Rows( LIBRARY_TABLE_TYPE::SYMBOL );
140
141 BOOST_REQUIRE_GE( rows.size(), 2 );
142
143 for( auto& [nickname, status] : adapter.GetLibraryStatuses() )
144 {
145 wxString msg = nickname;
146 BOOST_REQUIRE( status.load_status != LOAD_STATUS::LOADING );
147
148 switch( status.load_status )
149 {
150 default:
152 msg << ": loaded OK";
153 BOOST_REQUIRE( !status.error.has_value() );
154 break;
155
157 BOOST_REQUIRE( status.error.has_value() );
158 msg << ": error: " << status.error->message;
159 break;
160 }
161
162 BOOST_TEST_MESSAGE( msg );
163 }
164}
165
A generic fixture for loading schematics and associated settings for qa tests.
std::optional< float > AsyncLoadProgress() const
Returns async load progress between 0.0 and 1.0, or nullopt if load is not in progress.
void AsyncLoad()
Loads all available libraries for this adapter type in the background.
std::vector< std::pair< wxString, LIB_STATUS > > GetLibraryStatuses() const
Returns a list of all library nicknames and their status (even if they failed to load)
void LoadProjectTables(std::initializer_list< LIBRARY_TABLE_TYPE > aTablesToLoad={})
(Re)loads the project library tables in the given list, or all tables if no list is given
std::vector< LIBRARY_TABLE_ROW * > Rows(LIBRARY_TABLE_TYPE aType, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH, bool aIncludeInvalid=false) const
Returns a flattened list of libraries of the given type.
void LoadGlobalTables(std::initializer_list< LIBRARY_TABLE_TYPE > aTablesToLoad={})
(Re)loads the global library tables in the given list, or all tables if no list is given
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:132
Container for project specific data.
Definition project.h:65
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Load a project or sets up a new project with a specified path.
An interface to the global shared library manager that is schematic-specific and linked to one projec...
std::optional< LIB_STATUS > LoadOne(LIB_DATA *aLib) override
Loads or reloads the given library, if it exists.
LIB_SYMBOL * LoadSymbol(const wxString &aNickname, const wxString &aName)
Load a LIB_SYMBOL having aName from the library given by aNickname.
std::vector< LIB_SYMBOL * > GetSymbols(const wxString &aNickname, SYMBOL_TYPE aType=SYMBOL_TYPE::ALL_SYMBOLS)
std::string GetTestDataRootDir()
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
static void LoadSchematic(SCHEMATIC *aSchematic, SCH_SHEET *aRootSheet, const wxString &aFileName)
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")
BOOST_AUTO_TEST_CASE(ProjectLibraryTable)