35#include <pegtl/contrib/analyze.hpp>
53 BOOST_REQUIRE( tao::pegtl::analyze< LIBRARY_TABLE_GRAMMAR::LIB_TABLE_FILE >( 1 ) == 0 );
60 tl::expected<LIBRARY_TABLE_IR, LIBRARY_PARSE_ERROR>
result = parser.
ParseBuffer(
"" );
67 std::vector<std::string> cases = {
73 p.append(
"libraries/" );
77 for(
const std::string&
path : cases )
94 wxString expected_error;
96 bool check_formatted =
true;
99 std::vector<TESTCASE> cases = {
100 { .filename =
"sym-lib-table", .expected_rows = 224 },
101 { .filename =
"fp-lib-table", .expected_rows = 146 },
102 { .filename =
"nested-symbols", .expected_rows = 6 },
103 { .filename =
"nested-disabled", .expected_rows = 4 },
104 { .filename =
"nested-hidden", .expected_rows = 4 },
105 { .filename =
"cycle", .expected_rows = 2 },
106 { .filename =
"sym-hand-edited", .expected_rows = 2, .check_formatted =
false },
107 { .filename =
"corrupted", .expected_error =
"Syntax error at line 6, column 9" },
108 { .filename =
"truncated", .expected_error =
"Syntax error at line 11, column 1" }
112 fn.AppendDir(
"libraries" );
114 for(
const auto& [filename, expected_error, expected_rows, check_formatted] : cases )
118 fn.SetName( filename );
123 BOOST_REQUIRE_MESSAGE(
table.Rows().size() == expected_rows,
124 wxString::Format(
"Expected %zu rows but got %zu",
125 expected_rows,
table.Rows().size() ) );
127 BOOST_REQUIRE_MESSAGE(
table.ErrorDescription() == expected_error,
128 wxString::Format(
"Expected error '%s' but got '%s'",
129 expected_error,
table.ErrorDescription() ) );
132 if( !
table.IsOk() || !check_formatted )
136 inFp.open( fn.GetFullPath().fn_str() );
139 std::stringstream inBuf;
140 inBuf << inFp.rdbuf();
141 std::string inData = inBuf.str();
144 table.Format( &formatter );
146 KICAD_FORMAT::FORMAT_MODE::LIBRARY_TABLE );
148 if( formatter.
GetString().compare( inData ) != 0 )
200 fn.AppendDir(
"libraries" );
203 fn.SetName(
"nested-disabled" );
206 BOOST_REQUIRE_MESSAGE( disabledTable.
Rows().size() == 4,
207 wxString::Format(
"Expected 4 rows but got %zu",
208 disabledTable.
Rows().size() ) );
211 bool foundDisabledRow =
false;
217 BOOST_REQUIRE_MESSAGE( row.Disabled(),
218 "Nested table row should have disabled flag set" );
219 foundDisabledRow =
true;
223 BOOST_REQUIRE_MESSAGE( foundDisabledRow,
224 "Disabled nested table row not found in parsed table" );
227 fn.SetName(
"nested-hidden" );
230 BOOST_REQUIRE_MESSAGE( hiddenTable.
Rows().size() == 4,
231 wxString::Format(
"Expected 4 rows but got %zu",
232 hiddenTable.
Rows().size() ) );
234 bool foundHiddenRow =
false;
240 BOOST_REQUIRE_MESSAGE( row.Hidden(),
241 "Nested table row should have hidden flag set" );
242 foundHiddenRow =
true;
246 BOOST_REQUIRE_MESSAGE( foundHiddenRow,
247 "Hidden nested table row not found in parsed table" );
266 std::vector<const LIBRARY_TABLE_ROW*> seededPointers;
267 std::vector<wxString> seededUris;
269 for(
int i = 0; i < 4; ++i )
272 row.
SetNickname( wxString::Format( wxS(
"seed_%d" ), i ) );
273 row.
SetURI( wxString::Format( wxS(
"${KIPRJMOD}/libs/seed_%d.kicad_sym" ), i ) );
276 seededPointers.push_back( &row );
277 seededUris.push_back( row.
URI() );
283 for(
int i = 0; i < 64; ++i )
286 row.
SetNickname( wxString::Format( wxS(
"extra_%d" ), i ) );
287 row.
SetURI( wxString::Format( wxS(
"${KIPRJMOD}/libs/extra_%d.kicad_sym" ), i ) );
290 for(
size_t j = 0; j < seededPointers.size(); ++j )
292 BOOST_REQUIRE_MESSAGE(
293 seededPointers[j]->URI() == seededUris[j],
295 wxS(
"Seed row %zu pointer was invalidated after inserting %d rows: "
296 "expected URI '%s', got '%s'" ),
297 j, i + 1, seededUris[j], seededPointers[j]->URI() ) );
321 bool expectedPcmManaged;
322 wxString description;
325 std::vector<CASE> cases = {
326 { wxS(
"${KICAD10_3RD_PARTY}/symbols/foo/foo.kicad_sym" ),
true,
327 wxS(
"Versioned 3RD_PARTY template should be recognised as PCM-managed" ) },
328 { wxS(
"${KICAD9_3RD_PARTY}/symbols/legacy/legacy.kicad_sym" ),
true,
329 wxS(
"Legacy versioned 3RD_PARTY template should still match the wildcard" ) },
330 { wxS(
"${KICAD10_3RD_PARTY}/footprints/bar/bar.pretty" ),
true,
331 wxS(
"Footprint library using 3RD_PARTY template should match" ) },
332 { wxS(
"${KICAD_USER_LIB}/symbols/test.kicad_sym" ),
false,
333 wxS(
"Row using a different env var must not be flagged as PCM-managed" ) },
334 { wxS(
"${KIPRJMOD}/libs/local.kicad_sym" ),
false,
335 wxS(
"Project-relative row must not be flagged as PCM-managed" ) },
336 { wxS(
"/abs/path/to/lib.kicad_sym" ),
false,
337 wxS(
"Absolute path row must not be flagged as PCM-managed" ) },
338 { wxS(
"${}" ),
false,
339 wxS(
"Malformed empty var name must not match" ) },
340 { wxS(
"${KICAD10_3RD_PARTY_EXTRA}/foo" ),
false,
341 wxS(
"Similar-but-different var name must not match" ) },
344 for(
const CASE& c : cases )
352 actual == c.expectedPcmManaged,
353 wxString::Format( wxS(
"%s: URI='%s' expected=%d actual=%d" ),
354 c.description, c.uri, c.expectedPcmManaged ? 1 : 0,
364 fn.AppendDir(
"libraries" );
365 fn.SetName(
"sym-lib-table" );
367 wxFileName tmpFn = wxFileName::CreateTempFileName(
"kicad_test_ro_" );
368 wxCopyFile( fn.GetFullPath(), tmpFn.GetFullPath() );
378 tmpFn.SetPermissions( wxS_IRUSR | wxS_IRGRP | wxS_IROTH );
384 if( wxFileName( tmpFn.GetFullPath() ).IsFileWritable() )
387 "read-only permissions (running as root?)" );
401 tmpFn.SetPermissions( wxS_IRUSR | wxS_IWUSR );
402 wxRemoveFile( tmpFn.GetFullPath() );
412 wxString tablePath = wxT(
"/some/read-only/path/sym-lib-table" );
413 wxString nickname1 = wxT(
"LibA" );
414 wxString nickname2 = wxT(
"LibB" );
458 if( stockPath.IsFileReadable() )
460 BOOST_TEST_MESSAGE(
"Skipping: stock design-block-lib-table exists; test only applies when "
461 "no stock table is installed" );
465 const wxString tablePath =
472 bool existed =
false;
475 explicit FILE_RESTORE(
const wxString& aPath ) :
path( aPath )
477 existed = wxFileName::FileExists(
path );
481 wxFFile in(
path, wxT(
"rb" ) );
482 in.ReadAll( &contents );
490 wxFFile out(
path, wxT(
"wb" ) );
491 out.Write( contents );
493 else if( wxFileName::FileExists(
path ) )
495 wxRemoveFile(
path );
498 } restore( tablePath );
506 "CreateGlobalTable must not write a dangling row when the stock table is absent" );
526 const bool hadEntry = vars.count( templateVar ) > 0;
544 vars[templateVar] = savedEntry;
546 vars.erase( templateVar );
556 for(
const auto& [nickname, uri] : aUserRows )
570 return std::ranges::count_if( aTable.
Rows(),
573 return aRow.Type() == LIBRARY_TABLE_ROW::TABLE_TYPE_NAME
574 && aRow.Nickname() == wxS(
"KiCad" );
586 const wxString stockPath = wxS(
"${KICAD10_SYMBOL_DIR}/sym-lib-table" );
589 { wxS(
"MyParts" ), wxS(
"${KIPRJMOD}/../libs/MyParts.kicad_sym" ) },
590 { wxS(
"MyPassives" ), wxS(
"/home/user/kicad/MyPassives.kicad_sym" ) },
593 const size_t rowsBefore =
table.Rows().size();
607 const wxString stockPath = wxS(
"${KICAD10_SYMBOL_DIR}/sym-lib-table" );
610 { wxS(
"Device" ), wxS(
"${KICAD9_SYMBOL_DIR}/Device.kicad_sym" ) },
611 { wxS(
"MyParts" ), wxS(
"${KIPRJMOD}/../libs/MyParts.kicad_sym" ) },
617 BOOST_CHECK( modified );
621 BOOST_CHECK(
table.Row( wxS(
"MyParts" ) ).has_value() );
622 BOOST_CHECK( !
table.Row( wxS(
"Device" ) ).has_value() );
629 const wxString stockPath = wxS(
"${KICAD10_SYMBOL_DIR}/sym-lib-table" );
637 chained.
SetURI( wxS(
"${KICAD9_SYMBOL_DIR}/sym-lib-table" ) );
641 mine.
SetURI( wxS(
"${KIPRJMOD}/../libs/MyParts.kicad_sym" ) );
642 mine.
SetType( wxS(
"KiCad" ) );
647 BOOST_CHECK( modified );
650 auto migrated =
table.Row( wxS(
"KiCad" ) );
KiCad uses environment variables internally for determining the base paths for libraries,...
void SetDefinedExternally(bool aIsDefinedExternally=true)
std::map< wxString, std::map< wxString, LIB_OVERRIDE > > m_LibOverrides
Overrides for libraries in read-only nested tables.
static wxString StockTableTokenizedURI(LIBRARY_TABLE_TYPE aType)
void ClearLibOverride(const wxString &aTablePath, const wxString &aNickname)
Removes any override for a library that no longer needs one.
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...
static wxString DefaultGlobalTablePath(LIBRARY_TABLE_TYPE aType)
void SetLibOverride(const wxString &aTablePath, const wxString &aNickname, bool aDisabled, bool aHidden)
Set a user override for a library in a read-only nested table.
static bool CreateGlobalTable(LIBRARY_TABLE_TYPE aType, bool aPopulateDefaultLibraries)
static bool IsPcmManagedRow(const LIBRARY_TABLE_ROW &aRow)
Return true if a library table row was added by the Plugin and Content Manager.
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
static wxString StockTableReferenceURI(LIBRARY_TABLE_TYPE aType)
static wxString StockTablePath(LIBRARY_TABLE_TYPE aType)
tl::expected< LIBRARY_TABLE_IR, LIBRARY_PARSE_ERROR > ParseBuffer(const std::string &aBuffer)
tl::expected< LIBRARY_TABLE_IR, LIBRARY_PARSE_ERROR > Parse(const std::filesystem::path &aPath)
void SetNickname(const wxString &aNickname)
void SetType(const wxString &aType)
static const wxString TABLE_TYPE_NAME
void SetURI(const wxString &aUri)
const wxString & URI() const
LIBRARY_RESULT< void > Save()
bool IsReadOnly() const
Returns true if the underlying file exists but is not writable.
const std::deque< LIBRARY_TABLE_ROW > & Rows() const
virtual COMMON_SETTINGS * GetCommonSettings() const
virtual SETTINGS_MANAGER & GetSettingsManager() const
T * GetAppSettings(const char *aFilename)
Return a handle to the a given settings by type.
static KICOMMON_API bool MigrateBuiltInLibraries(LIBRARY_TABLE &aTable, LIBRARY_TABLE_TYPE aType, const wxString &aStockPath, bool aStockPathValid)
Migrates built-in (stock) library references in an imported global library table to the current versi...
Functions related to environment variables, including help functions.
std::map< wxString, ENV_VAR_ITEM > ENV_VAR_MAP
tl::expected< ResultType, LIBRARY_ERROR > LIBRARY_RESULT
KICOMMON_API wxString GetVersionedEnvVarName(const wxString &aBaseName)
Construct a versioned environment variable based on this KiCad major version.
std::string GetTestDataRootDir()
PGM_BASE & Pgm()
The global program "get" accessor.
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
static size_t countChainedKiCadRows(const LIBRARY_TABLE &aTable)
BOOST_AUTO_TEST_CASE(Grammar)
static LIBRARY_TABLE makeImportedSymbolTable(const std::vector< std::pair< wxString, wxString > > &aUserRows)
Builds an in-memory symbol library table seeded with the given user rows.
BOOST_CHECK_MESSAGE(totalMismatches==0, std::to_string(totalMismatches)+" board(s) with strategy disagreements")
BOOST_TEST_MESSAGE("\n=== Real-World Polygon PIP Benchmark ===\n"<< formatTable(table))
std::vector< std::vector< std::string > > table
BOOST_TEST_CONTEXT("Test Clearance")
wxString result
Test unit parsing edge cases and error handling.
BOOST_CHECK_EQUAL(result, "25.4")