26#include <pegtl/contrib/analyze.hpp>
27#include <pegtl/contrib/trace.hpp>
47 const std::size_t grammarIssues = tao::pegtl::analyze<CADSTAR_PARTS_LIB::GRAMMAR>();
48 BOOST_CHECK_EQUAL( grammarIssues, 0 );
50 const std::size_t headerIssues = tao::pegtl::analyze<CADSTAR_PARTS_LIB::VALID_HEADER>();
51 BOOST_CHECK_EQUAL( headerIssues, 0 );
65 {
"1: Normal header",
"# Format 32\r\n",
true },
66 {
"2: Normal header, extra content",
"# Format 32\r\nExtraUnrelatedContent",
true },
67 {
"3: Normal header extra spaces (1)",
"# Format 32\r\n",
true },
68 {
"4: Normal header extra spaces (2)",
"# FORMAT 32\r\n",
true },
69 {
"5: Normal header on 2nd line",
"\r\n# Format 32\r\n",
false },
70 {
"6: Normal header prepended",
"+# Format 32\r\n",
false },
71 {
"7: Normal header prepended spaces",
" # Format 32\r\n",
false },
75 {
"8: No header",
".PART-NAME :1 ;Part Descr\r\n",
true },
76 {
"9: No header, extra content",
".PART-NAME :1 ;Part Descr\r\nExtra",
true },
77 {
"10: No header, on 2nd line",
"\r\n.PART-NAME :1 ;Part Descr\r\n",
true },
78 {
"11: No header, on 3rd line",
"\r\n\r\n.PART-NAME :1 ;Part Descr\r\n",
true },
79 {
"12: No header, on 4th line",
"\r\n\r\n.PART-NAME :1 ;Part Descr\r\n",
true },
80 {
"13: No header, on 4th line",
"\r\n\r\n\r\n\r\n.PART-NAME :1 ;P Descr\r\n",
true },
81 {
"14: No header, on 5th line",
"\r\n\r\n\r\n\r\n\r\n.P-NAME :1 ;PDescr\r\n",
true },
82 {
"15: No header, on 6th line",
"\r\n\r\n\r\n\r\n\r\n\r\n.P-NAM :1 ;PDes\r\n",
false },
83 {
"16: No header, space prepend",
" .PART-NAME :1 ;Part Descr\r\n",
false },
84 {
"17: No header, spaces & 2nd line",
" \r\n.PART-NAME :1 ;Part Descr\r\n",
true },
85 {
"18: No header, 2nd line & space",
" \r\n .PART-NAME :1 ;Part Descr\r\n",
false },
93 BOOST_TEST_INFO_SCOPE( c.m_CaseName );
105 std::vector<std::string> testFiles = {
"dummycadstarlib.lib",
"dummycadstarlibwithheader.lib" };
107 for(
auto testFile : testFiles )
112 BOOST_CHECK_EQUAL( ret.m_PartEntries.size(), 100 );
119 BOOST_CHECK_EQUAL( partEntry.
m_Name,
"PartName" + std::to_string( i ) );
123 "Part " + std::to_string( i ) +
" Description" );
125 BOOST_CHECK_EQUAL( partEntry.
m_Pcb_component,
"FOOTPRINT" + std::to_string( i ) );
141 std::to_string( i * 5 ) );
143 "Person" + std::to_string( i ) );
146 BOOST_CHECK_EQUAL( partEntry.
m_SchAttributes[
"SCH val1"].m_ReadOnly,
false );
148 "val" + std::to_string( i ) );
149 BOOST_CHECK_EQUAL( partEntry.
m_SchAttributes[
"SCH val2"].m_ReadOnly,
true );
151 "readOnly" + std::to_string( i ) );
154 BOOST_CHECK_EQUAL( partEntry.
m_PcbAttributes[
"PCB val1"].m_ReadOnly,
false );
156 "val" + std::to_string( i ) );
157 BOOST_CHECK_EQUAL( partEntry.
m_PcbAttributes[
"PCB val2"].m_ReadOnly,
true );
159 "readOnly" + std::to_string( i ) );
162 BOOST_CHECK_EQUAL( partEntry.
m_PartAttributes[
"Part val1"].m_ReadOnly,
false );
164 "val" + std::to_string( i ) );
165 BOOST_CHECK_EQUAL( partEntry.
m_PartAttributes[
"Part val2"].m_ReadOnly,
true );
167 "readOnly" + std::to_string( i ) );
173 "val" + std::to_string( i ) );
177 "readOnly" + std::to_string( i ) );
180 BOOST_REQUIRE_EQUAL( partEntry.
m_Symbols.size(), 1 );
181 BOOST_CHECK_EQUAL( partEntry.
m_Symbols[0].m_SymbolName,
182 "Symbol" + std::to_string( i ) );
184 std::optional<std::string>() );
185 BOOST_REQUIRE_EQUAL( partEntry.
m_Symbols[0].m_Pins.size(), 2 );
186 BOOST_CHECK_EQUAL( partEntry.
m_Symbols[0].m_Pins[0].m_Identifier, 1 );
187 BOOST_CHECK_EQUAL( partEntry.
m_Symbols[0].m_Pins[1].m_Identifier, 2 );
190 BOOST_REQUIRE_EQUAL( partEntry.
m_HiddenPins.size(), 1 );
191 BOOST_CHECK_EQUAL( partEntry.
m_HiddenPins.count(
"GND" ), 1 );
207 "+N1 N0 'subnode1' &\r\n"
213 ".<Part name> (<Part number>):<Part version>;<Description>\r\n"
214 "<PCB Component Refname> (<PCB Alternate Refname>)\r\n"
216 "*PNM 1=A1 2=A2 3=B1 4=B2 5=C1 6=C2\r\n"
217 "*PLB 1=\"VCC\" 2=\"GND\" 3=\"'EN\" 4=\"OUT\" 5=\"OUT\" 6=\"IN\"\r\n"
218 "*EQU 4=5, 6=7=8, 9=10=11\r\n"
225 "*DFN <Definition name>\r\n"
228 "*STM <Component name stem>\r\n"
230 "*SPI (<Part name>) <Model> <Value>\r\n"
231 "*PAC (<Part name>) <Acceptance Text>\r\n"
232 "*userAttribute userAttributeVal\r\n"
233 "*\"User spaced name\" userSpacedAttributeVal\r\n"
234 "$<SCM Attribute name1>(<Attribute value for name1>)\r\n"
235 "$!<SCM Attribute name2>(\"<Attribute value for name2>\")\r\n"
236 "%<PCB Attribute name1>(\"<Attribute value1>\")\r\n"
237 "%!\"<PCB Attribute name2>\"(<Attribute value2>)\r\n"
238 "~<Parts Attribute name1>(<Attribute value1>)\r\n"
239 "~!<Parts Attribute name2>(<Attribute value2>)\r\n"
240 "@<SCM/PCB Attribute name1>(<Attribute value1>)\r\n"
241 "@!<SCM/PCB Attribute name2>(<Attribute value2>)\r\n"
242 "<SCM Symbol Refname1> (<SCM Alternate Refname>)\r\n"
243 "1.0!TD:2000 2.1!TI 3.2!T\r\n"
244 "<SCM Symbol Refname2>\r\n"
245 "4.2!U:1000 5.1!I 6.3!Q\r\n"
246 "/GND 7.0!G:2000\r\n"
247 "/VCC 8.0!P:2000 9.1 10.0\r\n";
260 BOOST_CHECK_EQUAL( result.
m_PartEntries[0].m_Name,
"<Part name>" );
261 BOOST_CHECK_EQUAL( result.
m_PartEntries[0].m_Number.value(),
"<Part number>" );
262 BOOST_CHECK_EQUAL( result.
m_PartEntries[0].m_Version.value(),
"<Part version>" );
263 BOOST_CHECK_EQUAL( result.
m_PartEntries[0].m_Description.value(),
"<Description>" );
264 BOOST_CHECK_EQUAL( result.
m_PartEntries[0].m_Pcb_component,
"<PCB Component Refname>" );
265 BOOST_CHECK_EQUAL( result.
m_PartEntries[0].m_Pcb_alternate.value(),
"<PCB Alternate Refname>" );
266 BOOST_CHECK_EQUAL( result.
m_PartEntries[0].m_Value.value(),
"<Value>" );
269 BOOST_REQUIRE_EQUAL( result.
m_PartEntries[0].m_PinNamesMap.size(), 6 );
271 std::map<long, std::string>& pinNames = result.
m_PartEntries[0].m_PinNamesMap;
272 BOOST_CHECK_EQUAL( pinNames[1],
"A1" );
273 BOOST_CHECK_EQUAL( pinNames[2],
"A2" );
274 BOOST_CHECK_EQUAL( pinNames[3],
"B1" );
275 BOOST_CHECK_EQUAL( pinNames[4],
"B2" );
276 BOOST_CHECK_EQUAL( pinNames[5],
"C1" );
277 BOOST_CHECK_EQUAL( pinNames[6],
"C2" );
280 BOOST_REQUIRE_EQUAL( result.
m_PartEntries[0].m_PinLabelsMap.size(), 6 );
282 std::map<long, std::string>& pinlabels = result.
m_PartEntries[0].m_PinLabelsMap;
283 BOOST_CHECK_EQUAL( pinlabels[1],
"VCC" );
284 BOOST_CHECK_EQUAL( pinlabels[2],
"GND" );
285 BOOST_CHECK_EQUAL( pinlabels[3],
"'EN" );
286 BOOST_CHECK_EQUAL( pinlabels[4],
"OUT" );
287 BOOST_CHECK_EQUAL( pinlabels[5],
"OUT" );
288 BOOST_CHECK_EQUAL( pinlabels[6],
"IN" );
291 BOOST_REQUIRE_EQUAL( result.
m_PartEntries[0].m_PinEquivalences.size(), 3 );
293 std::vector<std::vector<long>>& pinEqus = result.
m_PartEntries[0].m_PinEquivalences;
294 BOOST_REQUIRE_EQUAL( pinEqus[0].size(), 2 );
295 BOOST_REQUIRE_EQUAL( pinEqus[1].size(), 3 );
296 BOOST_REQUIRE_EQUAL( pinEqus[2].size(), 3 );
298 BOOST_CHECK_EQUAL( pinEqus[0][0], 4 );
299 BOOST_CHECK_EQUAL( pinEqus[0][1], 5 );
300 BOOST_CHECK_EQUAL( pinEqus[1][0], 6 );
301 BOOST_CHECK_EQUAL( pinEqus[1][1], 7 );
302 BOOST_CHECK_EQUAL( pinEqus[1][2], 8 );
303 BOOST_CHECK_EQUAL( pinEqus[2][0], 9 );
304 BOOST_CHECK_EQUAL( pinEqus[2][1], 10 );
305 BOOST_CHECK_EQUAL( pinEqus[2][2], 11 );
308 BOOST_REQUIRE_EQUAL( result.
m_PartEntries[0].m_InternalSwapGroup.size(), 1 );
310 BOOST_CHECK_EQUAL( result.
m_PartEntries[0].m_InternalSwapGroup[0].m_Name.value(),
"Group1" );
312 std::vector<std::vector<long>>& intgates =
315 BOOST_REQUIRE_EQUAL( intgates[0].size(), 2 );
316 BOOST_REQUIRE_EQUAL( intgates[1].size(), 2 );
318 BOOST_CHECK_EQUAL( intgates[0][0], 4 );
319 BOOST_CHECK_EQUAL( intgates[0][1], 5 );
320 BOOST_CHECK_EQUAL( intgates[1][0], 6 );
321 BOOST_CHECK_EQUAL( intgates[1][1], 7 );
324 BOOST_REQUIRE_EQUAL( result.
m_PartEntries[0].m_ExternalSwapGroup.size(), 1 );
326 BOOST_CHECK_EQUAL( result.
m_PartEntries[0].m_ExternalSwapGroup[0].m_Name.value(),
"Group2" );
328 std::vector<std::vector<long>>& extgates =
331 BOOST_REQUIRE_EQUAL( extgates[0].size(), 2 );
332 BOOST_REQUIRE_EQUAL( extgates[1].size(), 2 );
334 BOOST_CHECK_EQUAL( extgates[0][0], 1 );
335 BOOST_CHECK_EQUAL( extgates[0][1], 2 );
336 BOOST_CHECK_EQUAL( extgates[1][0], 4 );
337 BOOST_CHECK_EQUAL( extgates[1][1], 7 );
340 BOOST_CHECK_EQUAL( result.
m_PartEntries[0].m_PartDefinitionName.value(),
"<Definition name>" );
343 BOOST_CHECK_EQUAL( result.
m_PartEntries[0].m_GateSwappingAllowed,
false );
346 BOOST_CHECK_EQUAL( result.
m_PartEntries[0].m_PinsVisible,
false );
349 BOOST_CHECK_EQUAL( result.
m_PartEntries[0].m_ComponentStem,
"<Component name stem>" );
355 BOOST_CHECK_EQUAL( result.
m_PartEntries[0].m_SpicePartName.value(),
"<Part name>" );
356 BOOST_CHECK_EQUAL( result.
m_PartEntries[0].m_SpiceModel.value(),
"<Model> <Value>" );
359 BOOST_CHECK_EQUAL( result.
m_PartEntries[0].m_AcceptancePartName.value(),
"<Part name>" );
360 BOOST_CHECK_EQUAL( result.
m_PartEntries[0].m_AcceptanceText.value(),
"<Acceptance Text>" );
363 BOOST_REQUIRE_EQUAL( result.
m_PartEntries[0].m_UserAttributes.size(), 2 );
365 std::map<std::string, std::string>& userAtts = result.
m_PartEntries[0].m_UserAttributes;
366 BOOST_CHECK_EQUAL( userAtts[
"userAttribute"],
"userAttributeVal" );
367 BOOST_CHECK_EQUAL( userAtts[
"User spaced name"],
"userSpacedAttributeVal" );
370 BOOST_REQUIRE_EQUAL( result.
m_PartEntries[0].m_SchAttributes.size(), 2 );
372 std::map<std::string, CADSTAR_ATTRIBUTE_VALUE>& schAtts =
375 BOOST_CHECK_EQUAL( schAtts[
"<SCM Attribute name1>"].m_ReadOnly,
false );
376 BOOST_CHECK_EQUAL( schAtts[
"<SCM Attribute name1>"].m_Value,
"<Attribute value for name1>" );
378 BOOST_CHECK_EQUAL( schAtts[
"<SCM Attribute name2>"].m_ReadOnly,
true );
379 BOOST_CHECK_EQUAL( schAtts[
"<SCM Attribute name2>"].m_Value,
"<Attribute value for name2>" );
382 BOOST_REQUIRE_EQUAL( result.
m_PartEntries[0].m_PcbAttributes.size(), 2 );
384 std::map<std::string, CADSTAR_ATTRIBUTE_VALUE>& pcbAtts =
387 BOOST_CHECK_EQUAL( pcbAtts[
"<PCB Attribute name1>"].m_ReadOnly,
false );
388 BOOST_CHECK_EQUAL( pcbAtts[
"<PCB Attribute name1>"].m_Value,
"<Attribute value1>" );
390 BOOST_CHECK_EQUAL( pcbAtts[
"<PCB Attribute name2>"].m_ReadOnly,
true );
391 BOOST_CHECK_EQUAL( pcbAtts[
"<PCB Attribute name2>"].m_Value,
"<Attribute value2>" );
394 BOOST_REQUIRE_EQUAL( result.
m_PartEntries[0].m_PartAttributes.size(), 2 );
396 std::map<std::string, CADSTAR_ATTRIBUTE_VALUE>& partAtts =
399 BOOST_CHECK_EQUAL( partAtts[
"<Parts Attribute name1>"].m_ReadOnly,
false );
400 BOOST_CHECK_EQUAL( partAtts[
"<Parts Attribute name1>"].m_Value,
"<Attribute value1>" );
402 BOOST_CHECK_EQUAL( partAtts[
"<Parts Attribute name2>"].m_ReadOnly,
true );
403 BOOST_CHECK_EQUAL( partAtts[
"<Parts Attribute name2>"].m_Value,
"<Attribute value2>" );
406 BOOST_REQUIRE_EQUAL( result.
m_PartEntries[0].m_SchAndPcbAttributes.size(), 2 );
408 std::map<std::string, CADSTAR_ATTRIBUTE_VALUE>schAndPcbAtts =
411 BOOST_CHECK_EQUAL( schAndPcbAtts[
"<SCM/PCB Attribute name1>"].m_ReadOnly,
false );
412 BOOST_CHECK_EQUAL( schAndPcbAtts[
"<SCM/PCB Attribute name1>"].m_Value,
"<Attribute value1>" );
414 BOOST_CHECK_EQUAL( schAndPcbAtts[
"<SCM/PCB Attribute name2>"].m_ReadOnly,
true );
415 BOOST_CHECK_EQUAL( schAndPcbAtts[
"<SCM/PCB Attribute name2>"].m_Value,
"<Attribute value2>" );
418 std::vector<CADSTAR_PART_SYMBOL_ENTRY> symbols = result.
m_PartEntries[0].m_Symbols;
420 std::vector<CADSTAR_PART_SYMBOL_ENTRY> expectedSymbols =
423 "<SCM Symbol Refname1>",
424 "<SCM Alternate Refname>",
435 "<SCM Symbol Refname2>",
448 BOOST_REQUIRE_EQUAL( result.
m_PartEntries[0].m_Symbols.size(), expectedSymbols.size() );
450 auto itA = symbols.begin();
451 auto itB = expectedSymbols.begin();
453 while( itA != symbols.end() || itB != expectedSymbols.end() )
455 BOOST_TEST_CONTEXT(
"With symbol = " << itB->m_SymbolName
457 << itB->m_SymbolAlternateName.value_or(
"[nullopt]" ) )
459 BOOST_CHECK_EQUAL( itA->m_SymbolName, itB->m_SymbolName );
462 BOOST_REQUIRE_EQUAL( itA->m_Pins.size(), itB->m_Pins.size() );
464 auto itPinsA = itA->m_Pins.begin();
465 auto itPinsB = itB->m_Pins.begin();
467 while( itPinsA != itA->m_Pins.end() || itPinsB != itB->m_Pins.end() )
469 BOOST_TEST_CONTEXT(
"Pin Identifier = " << itPinsA->m_Identifier )
471 BOOST_CHECK_EQUAL( itPinsA->m_Identifier, itPinsB->m_Identifier );
472 BOOST_CHECK( itPinsA->m_Position == itPinsB->m_Position );
473 BOOST_CHECK( itPinsA->m_Type == itPinsB->m_Type );
487 std::map<std::string,std::vector<CADSTAR_PART_PIN>> expectedHiddenPins =
505 BOOST_REQUIRE_EQUAL( result.
m_PartEntries[0].m_HiddenPins.size(), expectedHiddenPins.size() );
507 auto itEntryA = result.
m_PartEntries[0].m_HiddenPins.begin();
508 auto itEntryB = expectedHiddenPins.begin();
510 while( itEntryA != result.
m_PartEntries[0].m_HiddenPins.end()
511 || itEntryB != expectedHiddenPins.end() )
513 BOOST_TEST_CONTEXT(
"Check Hidden pins - Signal = " << itEntryB->first )
515 BOOST_CHECK_EQUAL( itEntryA->first, itEntryB->first );
516 BOOST_REQUIRE_EQUAL( itEntryA->second.size(), itEntryB->second.size() );
518 auto itPinsA = itEntryA->second.begin();
519 auto itPinsB = itEntryB->second.begin();
521 while( itPinsA != itEntryA->second.end() || itPinsB != itEntryB->second.end() )
523 BOOST_CHECK_EQUAL( itPinsA->m_Identifier, itPinsB->m_Identifier );
524 BOOST_CHECK( itPinsA->m_Position == itPinsB->m_Position );
525 BOOST_CHECK( itPinsA->m_Type == itPinsB->m_Type );
@ TRISTATE_DRIVER
Tristate output pin.
@ UNCOMMITTED
Uncommitted pin (default)
@ TRISTATE_INPUT
Tristate input pin.
@ TRISTATE_BIDIR
Tristate bi-directional driver pin.
@ OUTPUT_NOT_NORM_OR
Output pin not normally OR tieable.
CADSTAR_PARTS_LIB_MODEL ReadFile(const std::filesystem::path &aPath) const
CADSTAR_PARTS_LIB_MODEL ReadContent(const std::string &aSource) const
bool CheckContentHeader(const std::string &aSource) const
std::string GetEeschemaTestDataDir()
Get the configured location of Eeschema test data.
CADSTAR Parts Library (*.lib) model - a data structure describing the contents of the file format.
std::optional< long > m_FormatNumber
std::map< long, CADSTAR_PART_NODE > m_HierarchyNodes
std::vector< CADSTAR_PART_ENTRY > m_PartEntries
std::string m_ComponentStem
std::map< std::string, std::vector< CADSTAR_PART_PIN > > m_HiddenPins
Pins with an implied electrical connection to a net, not part of any symbol (Note: we probably will n...
bool m_GateSwappingAllowed
std::map< std::string, CADSTAR_ATTRIBUTE_VALUE > m_SchAttributes
Dollar sign ($) line $[!]<SCM Attribute name>(<Attribute value>) Attributes related to the schematic ...
std::map< std::string, CADSTAR_ATTRIBUTE_VALUE > m_SchAndPcbAttributes
At symbol (@) line [@[!]<SCM/PCB Attribute name>(<Attribute value>)] Attributes related to the PCB co...
std::vector< CADSTAR_PART_SYMBOL_ENTRY > m_Symbols
Symbols that form this part.
std::map< std::string, std::string > m_UserAttributes
Star (*) line *<User-defined name> This line is ignored by CADSTAR.
std::optional< std::string > m_AcceptancePartName
std::optional< std::string > m_Pcb_alternate
std::optional< std::string > m_Version
std::optional< std::string > m_SpicePartName
std::optional< std::string > m_Description
std::optional< std::string > m_Number
std::string m_Pcb_component
std::optional< std::string > m_SpiceModel
std::optional< long > m_MaxPinCount
std::optional< std::string > m_AcceptanceText
std::map< std::string, CADSTAR_ATTRIBUTE_VALUE > m_PcbAttributes
Percentage sign (%) line %[!]<PCB Attribute name>(<Attribute value>) Attributes related to the PCB co...
std::optional< std::string > m_Value
std::map< std::string, CADSTAR_ATTRIBUTE_VALUE > m_PartAttributes
Tilde (~) line ~[!]<Parts Library Attribute Name>(<Attribute Value>) Attributes related to the Part i...
static std::string getCadstarTestFile(const std::string &aFile)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
static const std::vector< CHECK_HEADER_CASE > check_header_cases
BOOST_AUTO_TEST_CASE(AnalyzeGrammar)
BOOST_AUTO_TEST_SUITE_END()
#define KI_CHECK_OPT_EQUAL(lhs, rhs)
Work around to allow printing std::optional types.