KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_cadstar_parts_parser.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 (C) 2022-2023 Roberto Fernandez Bautista <[email protected]>
5 * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
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 <iostream>
23#include <algorithm>
24#include <optional>
25
26#include <pegtl/contrib/analyze.hpp>
27#include <pegtl/contrib/trace.hpp>
28
29// Modules under test:
32
33
34BOOST_AUTO_TEST_SUITE( CadstarPartParser );
35
36
37static std::string getCadstarTestFile( const std::string& aFile )
38{
39 return KI_TEST::GetEeschemaTestDataDir() + "/io/cadstar/" + aFile;
40}
41
42
43BOOST_AUTO_TEST_CASE( AnalyzeGrammar )
44{
45 // Verify the grammar has no loops without progress and other issues
46 // See: https://github.com/taocpp/PEGTL/blob/3.2.7/doc/Grammar-Analysis.md
47 const std::size_t grammarIssues = tao::pegtl::analyze<CADSTAR_PARTS_LIB::GRAMMAR>();
48 BOOST_CHECK_EQUAL( grammarIssues, 0 );
49
50 const std::size_t headerIssues = tao::pegtl::analyze<CADSTAR_PARTS_LIB::VALID_HEADER>();
51 BOOST_CHECK_EQUAL( headerIssues, 0 );
52}
53
54
56{
57 std::string m_CaseName;
58 std::string m_Content;
60};
61
62
63static const std::vector<CHECK_HEADER_CASE> check_header_cases =
64{
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 },
72
73 // There appear to be some files on the internet that just don't have a header and
74 // start straight away with the part definitions.
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 },
86};
87
88
90{
91 for( const auto& c : check_header_cases )
92 {
93 BOOST_TEST_INFO_SCOPE( c.m_CaseName );
95
96 BOOST_CHECK_EQUAL( p.CheckContentHeader( c.m_Content ), c.m_ExpectedResult );
97 }
98}
99
100
102{
104 // Test a programatically generated files (see writeCadstarFile.py)
105 std::vector<std::string> testFiles = { "dummycadstarlib.lib", "dummycadstarlibwithheader.lib" };
106
107 for( auto testFile : testFiles )
108 {
109 auto ret = p.ReadFile( getCadstarTestFile( testFile ) );
110
111 KI_CHECK_OPT_EQUAL( ret.m_FormatNumber, 32 );
112 BOOST_CHECK_EQUAL( ret.m_PartEntries.size(), 100 );
113
114 int i = 0;
115
116 for( CADSTAR_PART_ENTRY& partEntry : ret.m_PartEntries )
117 {
118 // Part header KI_CHECK_OPT_EQUAL
119 BOOST_CHECK_EQUAL( partEntry.m_Name, "PartName" + std::to_string( i ) );
120 KI_CHECK_OPT_EQUAL( partEntry.m_Number, std::to_string( i * 5 ) );
121 KI_CHECK_OPT_EQUAL( partEntry.m_Version, std::to_string( 2 ) );
123 "Part " + std::to_string( i ) + " Description" );
124
125 BOOST_CHECK_EQUAL( partEntry.m_Pcb_component, "FOOTPRINT" + std::to_string( i ) );
126 KI_CHECK_OPT_EQUAL( partEntry.m_Pcb_alternate, "variant" + std::to_string( i * 5 ) );
127 KI_CHECK_OPT_EQUAL( partEntry.m_Value, std::to_string( i ) + " uH" );
128 BOOST_CHECK_EQUAL( partEntry.m_ComponentStem, "L" );
129 KI_CHECK_OPT_EQUAL( partEntry.m_MaxPinCount, i + 10 );
130 BOOST_CHECK_EQUAL( partEntry.m_GateSwappingAllowed, i % 10 != 1 );
131 BOOST_CHECK_EQUAL( partEntry.m_PinsVisible, i % 5 != 1 );
132
133 KI_CHECK_OPT_EQUAL( partEntry.m_SpicePartName, "PartName" + std::to_string( i ) );
134 KI_CHECK_OPT_EQUAL( partEntry.m_SpiceModel, std::to_string( i ) + "uH" );
135
136 KI_CHECK_OPT_EQUAL( partEntry.m_AcceptancePartName, "PartName" + std::to_string( i ) );
137 KI_CHECK_OPT_EQUAL( partEntry.m_AcceptanceText, "Acceptance" + std::to_string( i ) );
138
139 // User part attributes (* lines)
140 BOOST_CHECK_EQUAL( partEntry.m_UserAttributes["UserFieldpartNo"],
141 std::to_string( i * 5 ) );
142 BOOST_CHECK_EQUAL( partEntry.m_UserAttributes["UserFieldpartNoCreated by"],
143 "Person" + std::to_string( i ) );
144
145 // SCH attributes ($ lines)
146 BOOST_CHECK_EQUAL( partEntry.m_SchAttributes["SCH val1"].m_ReadOnly, false );
147 BOOST_CHECK_EQUAL( partEntry.m_SchAttributes["SCH val1"].m_Value,
148 "val" + std::to_string( i ) );
149 BOOST_CHECK_EQUAL( partEntry.m_SchAttributes["SCH val2"].m_ReadOnly, true );
150 BOOST_CHECK_EQUAL( partEntry.m_SchAttributes["SCH val2"].m_Value,
151 "readOnly" + std::to_string( i ) );
152
153 // PCB attributes (% lines)
154 BOOST_CHECK_EQUAL( partEntry.m_PcbAttributes["PCB val1"].m_ReadOnly, false );
155 BOOST_CHECK_EQUAL( partEntry.m_PcbAttributes["PCB val1"].m_Value,
156 "val" + std::to_string( i ) );
157 BOOST_CHECK_EQUAL( partEntry.m_PcbAttributes["PCB val2"].m_ReadOnly, true );
158 BOOST_CHECK_EQUAL( partEntry.m_PcbAttributes["PCB val2"].m_Value,
159 "readOnly" + std::to_string( i ) );
160
161 // Parts attributes (~ lines)
162 BOOST_CHECK_EQUAL( partEntry.m_PartAttributes["Part val1"].m_ReadOnly, false );
163 BOOST_CHECK_EQUAL( partEntry.m_PartAttributes["Part val1"].m_Value,
164 "val" + std::to_string( i ) );
165 BOOST_CHECK_EQUAL( partEntry.m_PartAttributes["Part val2"].m_ReadOnly, true );
166 BOOST_CHECK_EQUAL( partEntry.m_PartAttributes["Part val2"].m_Value,
167 "readOnly" + std::to_string( i ) );
168
169 // PCB and SCH attributes (@ lines)
170 BOOST_CHECK_EQUAL( partEntry.m_SchAndPcbAttributes["SCH and PCB val1"].m_ReadOnly,
171 false );
172 BOOST_CHECK_EQUAL( partEntry.m_SchAndPcbAttributes["SCH and PCB val1"].m_Value,
173 "val" + std::to_string( i ) );
174 BOOST_CHECK_EQUAL( partEntry.m_SchAndPcbAttributes["SCH and PCB val2"].m_ReadOnly,
175 true );
176 BOOST_CHECK_EQUAL( partEntry.m_SchAndPcbAttributes["SCH and PCB val2"].m_Value,
177 "readOnly" + std::to_string( i ) );
178
179 // Check symbol name and pins
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 ) );
183 KI_CHECK_OPT_EQUAL( partEntry.m_Symbols[0].m_SymbolAlternateName,
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 );
188
189 // Check hidden pins
190 BOOST_REQUIRE_EQUAL( partEntry.m_HiddenPins.size(), 1 );
191 BOOST_CHECK_EQUAL( partEntry.m_HiddenPins.count( "GND" ), 1 );
192 i++;
193 }
194 }
195}
196
197
199{
200 std::string test =
201 "# Format 32\r\n"
202 "\r\n"
203 "\r\n"
204 "+N0 'root' &\r\n"
205 "'part1' &\r\n"
206 "'part2'\r\n"
207 "+N1 N0 'subnode1' &\r\n"
208 "'part3' &\r\n"
209 "'part4'\r\n"
210 "\r\n"
211 " \r\n"
212 "\r\n"
213 ".<Part name> (<Part number>):<Part version>;<Description>\r\n"
214 "<PCB Component Refname> (<PCB Alternate Refname>)\r\n"
215 "*VALUE <Value>\r\n"
216 "*PNM 1=A1 2=A2 3=B1 4=B2 5=C1 6=C2\r\n" // <PinId>=<Pinname> <PinId>=<Pinname> etc
217 "*PLB 1=\"VCC\" 2=\"GND\" 3=\"'EN\" 4=\"OUT\" 5=\"OUT\" 6=\"IN\"\r\n" // <id>=<label>
218 "*EQU 4=5, 6=7=8, 9=10=11\r\n" // <PinId>=<PinId>=<PinId> <PinId>=<PinId> etc ...
219 "*SYM Group1\r\n"
220 "*INT 4 5\r\n"
221 "*INT 6 7\r\n"
222 "*SYM Group2\r\n"
223 "*EXT 1 2\r\n"
224 "*EXT 4 7\r\n"
225 "*DFN <Definition name>\r\n"
226 "*NGS\r\n"
227 "*NPV\r\n"
228 "*STM <Component name stem>\r\n"
229 "*MXP 32\r\n" //<Maximum number of connector pins>
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";
248 //"etc ...\r\n"
249 //"/<Signame> <PinIdentifier>.<Position>!<Pintype>:<Loading>\r\n"
250 //"/<Signame> <PinIdentifier>.<Position>!<Pintype>:<Loading>\r\n";
251
253 CADSTAR_PARTS_LIB_MODEL result = csParser.ReadContent( test );
254
256 BOOST_REQUIRE_EQUAL( result.m_HierarchyNodes.size(), 2 ); // root and subnode
257
258 BOOST_REQUIRE_EQUAL( result.m_PartEntries.size(), 1 );
259
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>" );
267
268 // Check pin names (*PNM)
269 BOOST_REQUIRE_EQUAL( result.m_PartEntries[0].m_PinNamesMap.size(), 6 );
270
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" );
278
279 // Check pin labels (*PLB)
280 BOOST_REQUIRE_EQUAL( result.m_PartEntries[0].m_PinLabelsMap.size(), 6 );
281
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" );
289
290 // Check pin equivalences (*EQU)
291 BOOST_REQUIRE_EQUAL( result.m_PartEntries[0].m_PinEquivalences.size(), 3 );
292
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 );
297
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 );
306
307 // Check internal swap groups equivalences (*INT)
308 BOOST_REQUIRE_EQUAL( result.m_PartEntries[0].m_InternalSwapGroup.size(), 1 );
309
310 BOOST_CHECK_EQUAL( result.m_PartEntries[0].m_InternalSwapGroup[0].m_Name.value(), "Group1" );
311
312 std::vector<std::vector<long>>& intgates =
313 result.m_PartEntries[0].m_InternalSwapGroup[0].m_Gates;
314
315 BOOST_REQUIRE_EQUAL( intgates[0].size(), 2 );
316 BOOST_REQUIRE_EQUAL( intgates[1].size(), 2 );
317
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 );
322
323 // Check external swap groups equivalences (*EXT)
324 BOOST_REQUIRE_EQUAL( result.m_PartEntries[0].m_ExternalSwapGroup.size(), 1 );
325
326 BOOST_CHECK_EQUAL( result.m_PartEntries[0].m_ExternalSwapGroup[0].m_Name.value(), "Group2" );
327
328 std::vector<std::vector<long>>& extgates =
329 result.m_PartEntries[0].m_ExternalSwapGroup[0].m_Gates;
330
331 BOOST_REQUIRE_EQUAL( extgates[0].size(), 2 );
332 BOOST_REQUIRE_EQUAL( extgates[1].size(), 2 );
333
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 );
338
339 // Check part Definition
340 BOOST_CHECK_EQUAL( result.m_PartEntries[0].m_PartDefinitionName.value(), "<Definition name>" );
341
342 // Check *NGS
343 BOOST_CHECK_EQUAL( result.m_PartEntries[0].m_GateSwappingAllowed, false );
344
345 // Check *NPV
346 BOOST_CHECK_EQUAL( result.m_PartEntries[0].m_PinsVisible, false );
347
348 // Check *STM
349 BOOST_CHECK_EQUAL( result.m_PartEntries[0].m_ComponentStem, "<Component name stem>" );
350
351 // Check *MXP
352 KI_CHECK_OPT_EQUAL( result.m_PartEntries[0].m_MaxPinCount, 32 );
353
354 // Check *SPI
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>" );
357
358 // Check *PAC
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>" );
361
362 // Check user attributes (* lines)
363 BOOST_REQUIRE_EQUAL( result.m_PartEntries[0].m_UserAttributes.size(), 2 );
364
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" );
368
369 // Check SCH attributes ($ lines)
370 BOOST_REQUIRE_EQUAL( result.m_PartEntries[0].m_SchAttributes.size(), 2 );
371
372 std::map<std::string, CADSTAR_ATTRIBUTE_VALUE>& schAtts =
373 result.m_PartEntries[0].m_SchAttributes;
374
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>" );
377
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>" );
380
381 // Check PCB attributes (% lines)
382 BOOST_REQUIRE_EQUAL( result.m_PartEntries[0].m_PcbAttributes.size(), 2 );
383
384 std::map<std::string, CADSTAR_ATTRIBUTE_VALUE>& pcbAtts =
385 result.m_PartEntries[0].m_PcbAttributes;
386
387 BOOST_CHECK_EQUAL( pcbAtts["<PCB Attribute name1>"].m_ReadOnly, false );
388 BOOST_CHECK_EQUAL( pcbAtts["<PCB Attribute name1>"].m_Value, "<Attribute value1>" );
389
390 BOOST_CHECK_EQUAL( pcbAtts["<PCB Attribute name2>"].m_ReadOnly, true );
391 BOOST_CHECK_EQUAL( pcbAtts["<PCB Attribute name2>"].m_Value, "<Attribute value2>" );
392
393 // Check Part attributes (~ lines)
394 BOOST_REQUIRE_EQUAL( result.m_PartEntries[0].m_PartAttributes.size(), 2 );
395
396 std::map<std::string, CADSTAR_ATTRIBUTE_VALUE>& partAtts =
397 result.m_PartEntries[0].m_PartAttributes;
398
399 BOOST_CHECK_EQUAL( partAtts["<Parts Attribute name1>"].m_ReadOnly, false );
400 BOOST_CHECK_EQUAL( partAtts["<Parts Attribute name1>"].m_Value, "<Attribute value1>" );
401
402 BOOST_CHECK_EQUAL( partAtts["<Parts Attribute name2>"].m_ReadOnly, true );
403 BOOST_CHECK_EQUAL( partAtts["<Parts Attribute name2>"].m_Value, "<Attribute value2>" );
404
405 // Check Combined Sch/PCB attributes (@ lines)
406 BOOST_REQUIRE_EQUAL( result.m_PartEntries[0].m_SchAndPcbAttributes.size(), 2 );
407
408 std::map<std::string, CADSTAR_ATTRIBUTE_VALUE>schAndPcbAtts =
409 result.m_PartEntries[0].m_SchAndPcbAttributes;
410
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>" );
413
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>" );
416
417 // Check symbols
418 std::vector<CADSTAR_PART_SYMBOL_ENTRY> symbols = result.m_PartEntries[0].m_Symbols;
419
420 std::vector<CADSTAR_PART_SYMBOL_ENTRY> expectedSymbols =
421 {
422 {
423 "<SCM Symbol Refname1>",
424 "<SCM Alternate Refname>",
425 {
427 2000 },
429 std::nullopt },
431 std::nullopt }
432 }
433 },
434 {
435 "<SCM Symbol Refname2>",
436 std::nullopt,
437 {
439 1000 },
441 std::nullopt },
443 std::nullopt }
444 }
445 }
446 };
447
448 BOOST_REQUIRE_EQUAL( result.m_PartEntries[0].m_Symbols.size(), expectedSymbols.size() );
449
450 auto itA = symbols.begin();
451 auto itB = expectedSymbols.begin();
452
453 while( itA != symbols.end() || itB != expectedSymbols.end() )
454 {
455 BOOST_TEST_CONTEXT( "With symbol = " << itB->m_SymbolName
456 << " Alternate = "
457 << itB->m_SymbolAlternateName.value_or( "[nullopt]" ) )
458 {
459 BOOST_CHECK_EQUAL( itA->m_SymbolName, itB->m_SymbolName );
460 KI_CHECK_OPT_EQUAL( itA->m_SymbolAlternateName, itB->m_SymbolAlternateName );
461
462 BOOST_REQUIRE_EQUAL( itA->m_Pins.size(), itB->m_Pins.size() );
463
464 auto itPinsA = itA->m_Pins.begin();
465 auto itPinsB = itB->m_Pins.begin();
466
467 while( itPinsA != itA->m_Pins.end() || itPinsB != itB->m_Pins.end() )
468 {
469 BOOST_TEST_CONTEXT( "Pin Identifier = " << itPinsA->m_Identifier )
470 {
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 );
474 KI_CHECK_OPT_EQUAL( itPinsA->m_Loading, itPinsB->m_Loading );
475 }
476
477 ++itPinsA;
478 ++itPinsB;
479 }
480
481 ++itA;
482 ++itB;
483 }
484 }
485
486 // Compare hidden pins
487 std::map<std::string,std::vector<CADSTAR_PART_PIN>> expectedHiddenPins =
488 {
489 {
490 "GND",
491 {
493 }
494 },
495 {
496 "VCC",
497 {
501 }
502 }
503 };
504
505 BOOST_REQUIRE_EQUAL( result.m_PartEntries[0].m_HiddenPins.size(), expectedHiddenPins.size() );
506
507 auto itEntryA = result.m_PartEntries[0].m_HiddenPins.begin();
508 auto itEntryB = expectedHiddenPins.begin();
509
510 while( itEntryA != result.m_PartEntries[0].m_HiddenPins.end()
511 || itEntryB != expectedHiddenPins.end() )
512 {
513 BOOST_TEST_CONTEXT( "Check Hidden pins - Signal = " << itEntryB->first )
514 {
515 BOOST_CHECK_EQUAL( itEntryA->first, itEntryB->first );
516 BOOST_REQUIRE_EQUAL( itEntryA->second.size(), itEntryB->second.size() );
517
518 auto itPinsA = itEntryA->second.begin();
519 auto itPinsB = itEntryB->second.begin();
520
521 while( itPinsA != itEntryA->second.end() || itPinsB != itEntryB->second.end() )
522 {
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 );
526 KI_CHECK_OPT_EQUAL( itPinsA->m_Loading, itPinsB->m_Loading );
527
528 ++itPinsA;
529 ++itPinsB;
530 }
531 }
532
533 ++itEntryA;
534 ++itEntryB;
535 }
536}
537
538
@ TRISTATE_DRIVER
Tristate output pin.
@ INPUT
Input pin.
@ POWER
Power pin.
@ UNCOMMITTED
Uncommitted pin (default)
@ TRISTATE_INPUT
Tristate input pin.
@ GROUND
Ground 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
bool m_PinsVisible
std::optional< std::string > m_Pcb_alternate
std::optional< std::string > m_Version
std::string m_Name
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.