Files
kicad-source-mirror/qa/tests/eeschema/test_symbol_library.cpp
T
2025-10-15 22:18:54 -04:00

166 lines
5.1 KiB
C++

/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
* @author Jon Evans <jon@craftyjon.com>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <fmt/format.h>
#include <qa_utils/wx_utils/unit_test_utils.h>
#include <pgm_base.h>
#include "eeschema_test_utils.h"
#include <libraries/symbol_library_adapter.h>
// NOTE: this is for the new symbol library manager adapter and
// library manager system. There is also test_symbol_library_manager.cpp
// which is for the old code; that one can be removed once the old
// library manager doesn't exist anymore
class TEST_SYMBOL_LIBRARY_FIXTURE : public KI_TEST::SCHEMATIC_TEST_FIXTURE
{
};
BOOST_FIXTURE_TEST_SUITE( SymbolLibrary, TEST_SYMBOL_LIBRARY_FIXTURE )
BOOST_AUTO_TEST_CASE( ProjectLibraryTable )
{
if( !wxGetEnv( wxT( "KICAD_CONFIG_HOME_IS_QA" ), nullptr ) )
{
BOOST_TEST_MESSAGE( "QA test is running using unknown config home; skipping" );
return;
}
LIBRARY_MANAGER manager;
manager.LoadGlobalTables();
wxFileName fn( KI_TEST::GetTestDataRootDir(), "test_project.kicad_sch" );
fn.AppendDir( "libraries" );
fn.AppendDir( "test_project" );
std::vector<LIBRARY_TABLE_ROW*> rows = manager.Rows( LIBRARY_TABLE_TYPE::SYMBOL );
BOOST_REQUIRE( rows.size() == 3 );
BOOST_REQUIRE( rows[0]->Nickname() == "Device" );
LoadSchematic( fn.GetFullPath() );
PROJECT& project = SettingsManager().Prj();
manager.LoadProjectTables( project.GetProjectDirectory() );
rows = manager.Rows( LIBRARY_TABLE_TYPE::SYMBOL );
BOOST_REQUIRE( rows.size() == 4 );
BOOST_REQUIRE( rows[0]->Nickname() == "Device" );
BOOST_REQUIRE( rows[0]->URI() == "${KIPRJMOD}/Device.kicad_sym" );
SYMBOL_LIBRARY_ADAPTER adapter( manager );
adapter.LoadOne( "Device" );
std::vector<LIB_SYMBOL*> symbols = adapter.GetSymbols( "Device" );
// Check that the project's copy of Device is the one being returned
BOOST_REQUIRE( symbols.size() == 3 );
symbols = adapter.GetSymbols( "power" );
BOOST_TEST_MESSAGE( symbols.size() );
BOOST_REQUIRE( adapter.LoadSymbol( "Device", "R" ) );
}
// If you want to do benchmarking, it can be useful to run this testcase standalone with
// the KICAD_CONFIG_HOME and KICAD9_SYMBOL_DIR environment variables set to an actual KiCad
// installation so that you can benchmark a typical load
BOOST_AUTO_TEST_CASE( AsyncLoad )
{
LIBRARY_MANAGER manager;
manager.LoadGlobalTables();
Pgm().GetSettingsManager().LoadProject( "" );
SYMBOL_LIBRARY_ADAPTER adapter( manager );
auto tstart = std::chrono::high_resolution_clock::now();
adapter.AsyncLoad();
constexpr static int interval = 250;
constexpr static int timeLimit = 20000;
int elapsed = 0;
while( true )
{
std::this_thread::sleep_for( std::chrono::milliseconds( interval ) );
if( std::optional<float> loadStatus = adapter.AsyncLoadProgress(); loadStatus.has_value() )
{
BOOST_TEST_MESSAGE( fmt::format( "Loading libraries: ({:.1f}%)", *loadStatus * 100 ) );
if( loadStatus >= 1 )
break;
}
else
{
// Just informational; this could be fine when running in a QA context
BOOST_TEST_MESSAGE( "Async load not in progress" );
break;
}
elapsed += interval;
if( elapsed > timeLimit )
{
BOOST_TEST_FAIL( "Exceeded timeout" );
break;
}
}
auto duration = std::chrono::high_resolution_clock::now() - tstart;
BOOST_TEST_MESSAGE(
fmt::format( "took {}ms",
std::chrono::duration_cast<std::chrono::milliseconds>( duration ).count() ) );
adapter.BlockUntilLoaded();
std::vector<LIBRARY_TABLE_ROW*> rows = manager.Rows( LIBRARY_TABLE_TYPE::SYMBOL );
BOOST_REQUIRE_GE( rows.size(), 2 );
for( auto& [nickname, status] : adapter.GetLibraryStatuses() )
{
wxString msg = nickname;
BOOST_REQUIRE( status.load_status != LOAD_STATUS::LOADING );
switch( status.load_status )
{
default:
case LOAD_STATUS::LOADED:
msg << ": loaded OK";
BOOST_REQUIRE( !status.error.has_value() );
break;
case LOAD_STATUS::ERROR:
BOOST_REQUIRE( status.error.has_value() );
msg << ": error: " << status.error->message;
break;
}
BOOST_TEST_MESSAGE( msg );
}
}
BOOST_AUTO_TEST_SUITE_END()