21#include <fmt/format.h>
41constexpr const char* kDeviceLibNickname =
"Device";
54 std::make_unique<SYMBOL_LIBRARY_ADAPTER>( aManager ) );
56 std::optional<LIBRARY_MANAGER_ADAPTER*> adapterOpt =
65 fn.AppendDir(
"libraries" );
66 fn.AppendDir(
"test_project" );
76 path += wxT(
"/libraries" );
77 return std::make_unique<KI_TEST::SCOPED_PROCESS_ENV_VAR>( wxT(
"KICAD9_SYMBOL_DIR" ),
path );
85 if( !wxGetEnv( wxT(
"KICAD_CONFIG_HOME_IS_QA" ),
nullptr ) )
95 fn.AppendDir(
"libraries" );
96 fn.AppendDir(
"test_project" );
111 BOOST_REQUIRE( rows[0]->URI() ==
"${KIPRJMOD}/Device.kicad_sym" );
116 std::vector<LIB_SYMBOL*> symbols = adapter.
GetSymbols(
"Device" );
139 auto tstart = std::chrono::high_resolution_clock::now();
142 constexpr static int interval = 250;
143 constexpr static int timeLimit = 20000;
148 std::this_thread::sleep_for( std::chrono::milliseconds( interval ) );
150 if( std::optional<float> loadStatus = adapter.
AsyncLoadProgress(); loadStatus.has_value() )
152 BOOST_TEST_MESSAGE( fmt::format(
"Loading libraries: ({:.1f}%)", *loadStatus * 100 ) );
154 if( loadStatus >= 1 )
166 if( elapsed > timeLimit )
168 BOOST_TEST_FAIL(
"Exceeded timeout" );
173 auto duration = std::chrono::high_resolution_clock::now() - tstart;
176 fmt::format(
"took {}ms",
177 std::chrono::duration_cast<std::chrono::milliseconds>( duration ).count() ) );
183 BOOST_REQUIRE_GE( rows.size(), 2 );
187 wxString msg = nickname;
190 switch( status.load_status )
194 msg <<
": loaded OK";
200 msg <<
": error: " << status.error->message;
215 wxString loadedNickname;
231 loadedNickname = nickname;
236 if( loadedNickname.IsEmpty() )
252 "global cache entry must be evicted when its owning adapter is destroyed" );
264 if( !wxGetEnv( wxT(
"KICAD_CONFIG_HOME_IS_QA" ),
nullptr ) )
282 adapter->
LoadOne( kDeviceLibNickname );
294 BOOST_REQUIRE_MESSAGE( !adapter->
IsLibraryLoaded( kDeviceLibNickname ),
295 "Project library cache must be cleared by LoadProjectTables "
296 "to prevent dangling LIB_DATA::row pointers" );
300 adapter->
LoadOne( kDeviceLibNickname );
317 if( !wxGetEnv( wxT(
"KICAD_CONFIG_HOME_IS_QA" ),
nullptr ) )
323 std::unique_ptr<KI_TEST::SCOPED_PROCESS_ENV_VAR> scopedSymDirEnvVar = EnsureGlobalSymbolDir();
341 adapter->
LoadOne( kDeviceLibNickname );
352 adapter->
LoadOne( kDeviceLibNickname );
365 BOOST_REQUIRE_MESSAGE( !adapter->
IsLibraryLoaded( kDeviceLibNickname ),
366 "Project library reload must preserve project-over-global "
367 "shadowing for cached nicknames" );
370 adapter->
LoadOne( kDeviceLibNickname );
384 if( !wxGetEnv( wxT(
"KICAD_CONFIG_HOME_IS_QA" ),
nullptr ) )
390 std::unique_ptr<KI_TEST::SCOPED_PROCESS_ENV_VAR> scopedSymDirEnvVar = EnsureGlobalSymbolDir();
401 adapter->
LoadOne( kDeviceLibNickname );
410 adapter->
LoadOne( kDeviceLibNickname );
426 "Removing a project library must expose the same-named global "
427 "library rather than leave a permanent sentinel mask" );
436 if( !wxGetEnv( wxT(
"KICAD_CONFIG_HOME_IS_QA" ),
nullptr ) )
469 if( !wxGetEnv( wxT(
"KICAD_CONFIG_HOME_IS_QA" ),
nullptr ) )
489 row.
SetURI( wxS(
"${KIPRJMOD}/does_not_exist.kicad_sym" ) );
492 std::optional<LIB_STATUS> first = adapter->
LoadOne( wxS(
"Missing" ) );
496 std::optional<LIB_STATUS> second = adapter->
LoadOne( wxS(
"Missing" ) );
499 "A library whose file is missing must not come back as loaded" );
502 BOOST_CHECK_MESSAGE( !row.
IsOk(),
"A row whose library failed to load must be flagged in the table" );
514 deviceDir.AppendDir(
"libraries" );
515 deviceDir.AppendDir(
"test_project" );
521 fixtureDir.AppendDir(
"libraries" );
522 fixtureDir.AppendDir(
"issue24855" );
532 BOOST_REQUIRE_EQUAL( rows.size(), 2 );
538 "Enabled library must be loaded by AsyncLoad" );
541 "Disabled library must not be contacted by AsyncLoad" );
546 validationRow.
SetURI( fixtureDir.GetPathWithSep() + wxT(
"missing.kicad_sym" ) );
547 validationRow.
SetOk(
false );
553 "CheckTableRow must not probe a disabled row's backend" );
562 if( !wxGetEnv( wxT(
"KICAD_CONFIG_HOME_IS_QA" ),
nullptr ) )
568 std::unique_ptr<KI_TEST::SCOPED_PROCESS_ENV_VAR> scopedSymDirEnvVar = EnsureGlobalSymbolDir();
575 adapter->
LoadOne( kDeviceLibNickname );
587 BOOST_CHECK_MESSAGE( !adapter->
HasLibrary( kDeviceLibNickname ),
588 "an unloaded project library must shadow a loaded global library "
589 "of the same nickname" );
591 "GetLibraryNames must not list the global library for a nickname "
592 "shadowed by an unloaded project row" );
594 "GetLibraryDescription must not return the global library's "
595 "description for an unloaded project nickname" );
A generic fixture for loading schematics and associated settings for qa tests.
RAII helper that sets a process-level environment variable for the lifetime of the object.
std::optional< float > AsyncLoadProgress() const
Returns the fraction of the libraries queued by AsyncLoad() that have been processed,...
void CheckTableRow(LIBRARY_TABLE_ROW &aRow)
bool IsLibraryLoaded(const wxString &aNickname)
std::optional< wxString > GetLibraryDescription(const wxString &aNickname) const
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library tables.
std::optional< LIBRARY_TABLE_ROW * > GetRow(const wxString &aNickname, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH) const
Like LIBRARY_MANAGER::GetRow but filtered to the LIBRARY_TABLE_TYPE of this adapter.
std::vector< wxString > GetLibraryNames() const
Returns a list of library nicknames that are available (skips any that failed to load)
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)
std::optional< LIBRARY_MANAGER_ADAPTER * > Adapter(LIBRARY_TABLE_TYPE aType) const
std::optional< LIBRARY_TABLE * > Table(LIBRARY_TABLE_TYPE aType, LIBRARY_TABLE_SCOPE aScope)
Retrieves a given table; creating a new empty project table if a valid project is loaded and the give...
void RegisterAdapter(LIBRARY_TABLE_TYPE aType, std::unique_ptr< LIBRARY_MANAGER_ADAPTER > &&aAdapter)
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
void ProjectChanged()
Notify all adapters that the project has changed.
void SetNickname(const wxString &aNickname)
void SetOk(bool aOk=true)
void SetType(const wxString &aType)
void SetErrorDescription(const wxString &aDescription)
const wxString & ErrorDescription() const
void SetURI(const wxString &aUri)
virtual SETTINGS_MANAGER & GetSettingsManager() const
Container for project specific data.
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)
wxFileName GetTestProjectSchPath() const
std::unique_ptr< KI_TEST::SCOPED_PROCESS_ENV_VAR > EnsureGlobalSymbolDir()
Ensure KICAD9_SYMBOL_DIR points at the QA data libraries so the global sym-lib-table's ${KICAD9_SYMBO...
SYMBOL_LIBRARY_ADAPTER * RegisterSymbolAdapter(LIBRARY_MANAGER &aManager)
Register a fresh SYMBOL_LIBRARY_ADAPTER on the manager and return it.
std::string GetTestDataRootDir()
PGM_BASE & Pgm()
The global program "get" accessor.
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)