59 wxFileName tempDir = MakeTempDir();
60 wxFileName boardFile( tempDir.GetFullPath(), wxT(
"backdrill_board.kicad_pcb" ) );
72 via->SetSecondaryDrillStartLayer(
F_Cu );
77 via->SetFrontPostMachiningAngle( 900 );
85 wxFileName excellonFile( tempDir.GetFullPath(), wxT(
"backdrill_board_Backdrills_Drill_1_4.drl" ) );
88 wxFFile excellonStream( excellonFile.GetFullPath(), wxT(
"rb" ) );
89 wxString excellonContents;
91 BOOST_CHECK( excellonContents.Contains( wxT(
"TF.FileFunction,NonPlated,1,4,Blind" ) ) );
92 BOOST_CHECK( excellonContents.Contains( wxT(
"; Backdrill" ) ) );
93 BOOST_CHECK( excellonContents.Contains( wxT(
"post-machining" ) ) );
95 wxFileName layerPairFile( tempDir.GetFullPath(), wxT(
"backdrill_board-front-in3-backdrill.drl" ) );
98 wxFFile layerPairStream( layerPairFile.GetFullPath(), wxT(
"rb" ) );
99 wxString layerPairContents;
100 BOOST_REQUIRE( layerPairStream.ReadAll( &layerPairContents ) );
101 BOOST_CHECK( layerPairContents.Contains( wxT(
"; backdrill" ) ) );
103 wxFileName pthFile( tempDir.GetFullPath(), wxT(
"backdrill_board-PTH.drl" ) );
106 wxFFile pthStream( pthFile.GetFullPath(), wxT(
"rb" ) );
107 wxString pthContents;
109 BOOST_CHECK( pthContents.Contains( wxT(
"; Post-machining front countersink dia 0.600mm depth 0.150mm angle 90deg" ) ) );
116 wxFileName gerberFile( tempDir.GetFullPath(), wxT(
"backdrill_board_Backdrills_Drill_1_4-drl.gbr" ) );
119 wxFFile gerberStream( gerberFile.GetFullPath(), wxT(
"rb" ) );
120 wxString gerberContents;
122 BOOST_CHECK( gerberContents.Contains( wxT(
"%TA.AperFunction,BackDrill*%" ) ) );
123 BOOST_CHECK( gerberContents.Contains( wxT(
"%TF.FileFunction,NonPlated,1,4,Blind,Drill*%" ) ) );
125 wxFileName gerberLayerPairFile( tempDir.GetFullPath(),
126 wxT(
"backdrill_board-front-in3-backdrill-drl.gbr" ) );
129 wxFFile gerberLayerPairStream( gerberLayerPairFile.GetFullPath(), wxT(
"rb" ) );
130 wxString gerberLayerPairContents;
131 BOOST_REQUIRE( gerberLayerPairStream.ReadAll( &gerberLayerPairContents ) );
132 BOOST_CHECK( gerberLayerPairContents.Contains( wxT(
"%TF.FileFunction,NonPlated,1,4,Blind,Drill*%" ) ) );
133 BOOST_CHECK( gerberLayerPairContents.Contains( wxT(
"%TA.AperFunction,BackDrill*%" ) ) );
135 wxFileName odbRoot( tempDir.GetFullPath(), wxEmptyString );
136 odbRoot.AppendDir( wxT(
"odb_out" ) );
137 BOOST_REQUIRE( odbRoot.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) );
140 std::map<std::string, UTF8> props;
141 props[
"units"] =
"mm";
142 props[
"sigfig"] =
"4";
143 BOOST_REQUIRE_NO_THROW( odbExporter.
SaveBoard( odbRoot.GetFullPath(), &board, &props ) );
145 wxFileName drill1Dir( odbRoot.GetFullPath(), wxEmptyString );
146 drill1Dir.AppendDir( wxT(
"steps" ) );
147 drill1Dir.AppendDir( wxT(
"pcb" ) );
148 drill1Dir.AppendDir( wxT(
"layers" ) );
149 drill1Dir.AppendDir( wxT(
"drill1" ) );
152 wxFileName toolsFile( drill1Dir.GetFullPath(), wxT(
"tools" ) );
155 wxFFile toolsStream( toolsFile.GetFullPath(), wxT(
"rb" ) );
156 wxString toolsContents;
158 BOOST_CHECK( toolsContents.Contains( wxT(
"TYPE=NON_PLATED" ) ) );
159 BOOST_CHECK( toolsContents.Contains( wxT(
"TYPE2=BLIND" ) ) );
161 wxFileName matrixFile( odbRoot.GetFullPath(), wxEmptyString );
162 matrixFile.AppendDir( wxT(
"matrix" ) );
163 matrixFile.SetFullName( wxT(
"matrix" ) );
166 wxFFile matrixStream( matrixFile.GetFullPath(), wxT(
"rb" ) );
167 wxString matrixContents;
169 BOOST_CHECK( matrixContents.Contains( wxT(
"ADD_TYPE=BACKDRILL" ) ) );
171 matrixStream.Close();
173 gerberStream.Close();
174 gerberLayerPairStream.Close();
175 excellonStream.Close();
176 layerPairStream.Close();
179 wxFileName::Rmdir( odbRoot.GetFullPath(), wxPATH_RMDIR_RECURSIVE );
180 wxFileName::Rmdir( tempDir.GetFullPath(), wxPATH_RMDIR_RECURSIVE );
189 wxFileName tempDir = MakeTempDir();
190 wxFileName boardFile( tempDir.GetFullPath(), wxT(
"backdrill_pair_board.kicad_pcb" ) );
196 auto topVia =
new PCB_VIA( &board );
197 topVia->SetPosition(
VECTOR2I( 0, 0 ) );
199 topVia->SetDrill(
pcbIUScale.mmToIU( 0.30 ) );
200 topVia->SetWidth(
pcbIUScale.mmToIU( 0.60 ) );
201 topVia->SetSecondaryDrillSize(
pcbIUScale.mmToIU( 0.40 ) );
202 topVia->SetSecondaryDrillStartLayer(
F_Cu );
203 topVia->SetSecondaryDrillEndLayer(
In1_Cu );
206 auto bottomVia =
new PCB_VIA( &board );
208 bottomVia->SetLayerPair(
F_Cu,
B_Cu );
209 bottomVia->SetDrill(
pcbIUScale.mmToIU( 0.30 ) );
210 bottomVia->SetWidth(
pcbIUScale.mmToIU( 0.60 ) );
211 bottomVia->SetTertiaryDrillSize(
pcbIUScale.mmToIU( 0.40 ) );
212 bottomVia->SetTertiaryDrillStartLayer(
B_Cu );
213 bottomVia->SetTertiaryDrillEndLayer(
In3_Cu );
214 board.
Add( bottomVia );
222 wxFileName topBackdrillFile( tempDir.GetFullPath(),
223 wxT(
"backdrill_pair_board_Backdrills_Drill_1_2.drl" ) );
225 "Front-side backdrill drill file should be produced" );
228 wxFileName bottomBackdrillFile( tempDir.GetFullPath(),
229 wxT(
"backdrill_pair_board_Backdrills_Drill_6_4.drl" ) );
231 "Back-side (tertiary) backdrill drill file should be produced" );
233 if( bottomBackdrillFile.FileExists() )
235 wxFFile stream( bottomBackdrillFile.GetFullPath(), wxT(
"rb" ) );
238 BOOST_CHECK( contents.Contains( wxT(
"; Backdrill" ) ) );
242 wxFileName::Rmdir( tempDir.GetFullPath(), wxPATH_RMDIR_RECURSIVE );
251 wxFileName tempDir = MakeTempDir();
252 wxFileName boardFile( tempDir.GetFullPath(), wxT(
"dual_backdrill_board.kicad_pcb" ) );
264 via->SetSecondaryDrillStartLayer(
F_Cu );
265 via->SetSecondaryDrillEndLayer(
In1_Cu );
267 via->SetTertiaryDrillStartLayer(
B_Cu );
277 wxFileName topBackdrillFile( tempDir.GetFullPath(),
278 wxT(
"dual_backdrill_board_Backdrills_Drill_1_2.drl" ) );
279 BOOST_CHECK( topBackdrillFile.FileExists() );
281 wxFileName bottomBackdrillFile( tempDir.GetFullPath(),
282 wxT(
"dual_backdrill_board_Backdrills_Drill_6_4.drl" ) );
283 BOOST_CHECK( bottomBackdrillFile.FileExists() );
285 wxFileName::Rmdir( tempDir.GetFullPath(), wxPATH_RMDIR_RECURSIVE );
293 wxFileName tempDir = MakeTempDir();
294 wxFileName boardFile( tempDir.GetFullPath(), wxT(
"precision_board.kicad_pcb" ) );
313 wxFileName gerberFile5( tempDir.GetFullPath(), wxT(
"precision_board-PTH-drl.gbr" ) );
316 wxFFile gerberStream5( gerberFile5.GetFullPath(), wxT(
"rb" ) );
317 wxString gerberContents5;
320 "Expected 'Fmt 4.5' in gerber header with precision=5" );
321 BOOST_CHECK( !gerberContents5.Contains( wxT(
"Fmt 4.6" ) ) );
322 gerberStream5.Close();
330 wxFFile gerberStream6( gerberFile5.GetFullPath(), wxT(
"rb" ) );
331 wxString gerberContents6;
334 "Expected 'Fmt 4.6' in gerber header with precision=6" );
335 BOOST_CHECK( !gerberContents6.Contains( wxT(
"Fmt 4.5" ) ) );
336 gerberStream6.Close();
338 wxFileName::Rmdir( tempDir.GetFullPath(), wxPATH_RMDIR_RECURSIVE );
379 wxFileName tempDir = MakeTempDir();
380 wxFileName boardFile( tempDir.GetFullPath(), wxT(
"test_board_with_drills.kicad_pcb" ) );
393 wxFileName reportFile( tempDir.GetFullPath(), wxT(
"test_board_with_drills-drl.rpt" ) );
399 BOOST_CHECK( reportFile.FileExists() );
401 wxFFile reportStream( reportFile.GetFullPath(), wxT(
"rb" ) );
402 wxString reportContents;
404 BOOST_CHECK( reportContents.Contains( wxT(
"T1" ) ) );
405 BOOST_CHECK( reportContents.Contains( wxT(
"0.300mm" ) ) );
406 reportStream.Close();
408 wxFileName::Rmdir( tempDir.GetFullPath(), wxPATH_RMDIR_RECURSIVE );
420 wxFileName tempDir = MakeTempDir();
421 wxFileName boardFile( tempDir.GetFullPath(), wxT(
"silk_rect_board.kicad_pcb" ) );
436 wxFileName odbRoot( tempDir.GetFullPath(), wxEmptyString );
437 odbRoot.AppendDir( wxT(
"odb_out" ) );
438 BOOST_REQUIRE( odbRoot.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) );
441 std::map<std::string, UTF8> props;
442 props[
"units"] =
"mm";
443 props[
"sigfig"] =
"4";
444 BOOST_REQUIRE_NO_THROW( odbExporter.
SaveBoard( odbRoot.GetFullPath(), &board, &props ) );
446 wxFileName silkFeatures( odbRoot.GetFullPath(), wxT(
"features" ) );
447 silkFeatures.AppendDir( wxT(
"steps" ) );
448 silkFeatures.AppendDir( wxT(
"pcb" ) );
449 silkFeatures.AppendDir( wxT(
"layers" ) );
450 silkFeatures.AppendDir( wxT(
"f.silkscreen" ) );
453 wxFFile silkStream( silkFeatures.GetFullPath(), wxT(
"rb" ) );
454 wxString silkContents;
460 wxStringTokenizer lines( silkContents, wxT(
"\n" ) );
462 while( lines.HasMoreTokens() )
464 if( lines.GetNextToken().StartsWith( wxT(
"L " ) ) )
471 BOOST_CHECK( !silkContents.Contains( wxT(
"donut_rc" ) ) );
473 wxFileName::Rmdir( odbRoot.GetFullPath(), wxPATH_RMDIR_RECURSIVE );
474 wxFileName::Rmdir( tempDir.GetFullPath(), wxPATH_RMDIR_RECURSIVE );
506 wxFileName tempDir = MakeTempDir();
507 wxFileName boardFile( tempDir.GetFullPath(), wxT(
"plated_slot_board.kicad_pcb" ) );
523 wxFileName odbRoot( tempDir.GetFullPath(), wxEmptyString );
524 odbRoot.AppendDir( wxT(
"odb_out" ) );
525 BOOST_REQUIRE( odbRoot.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) );
528 std::map<std::string, UTF8> props;
529 props[
"units"] =
"mm";
530 props[
"sigfig"] =
"4";
531 BOOST_REQUIRE_NO_THROW( odbExporter.
SaveBoard( odbRoot.GetFullPath(), &board, &props ) );
533 auto layerDir = [&](
const wxString& aLayer )
535 wxFileName dir( odbRoot.GetFullPath(), wxEmptyString );
536 dir.AppendDir( wxT(
"steps" ) );
537 dir.AppendDir( wxT(
"pcb" ) );
538 dir.AppendDir( wxT(
"layers" ) );
539 dir.AppendDir( aLayer );
544 auto readFile = [](
const wxFileName& aFile )
546 wxFFile stream( aFile.GetFullPath(), wxT(
"rb" ) );
555 auto countLinesStartingWith = [](
const wxString& aContents,
const wxString& aPrefix )
558 wxStringTokenizer lines( aContents, wxT(
"\n" ) );
560 while( lines.HasMoreTokens() )
562 wxString line = lines.GetNextToken();
565 if( line.StartsWith( aPrefix ) )
572 auto containsOvalSymbol = [](
const wxString& aContents )
574 wxStringTokenizer lines( aContents, wxT(
"\n" ) );
576 while( lines.HasMoreTokens() )
578 wxString line = lines.GetNextToken();
581 if( line.StartsWith( wxT(
"$" ) ) && line.Contains( wxT(
"oval" ) ) )
590 wxFileName platedDir = layerDir( wxT(
"drill_plated_f.cu-b.cu" ) );
591 BOOST_REQUIRE_MESSAGE( platedDir.DirExists(),
"Plated drill layer should exist" );
593 wxFileName platedFeatures( platedDir.GetFullPath(), wxT(
"features" ) );
595 wxString platedContents =
readFile( platedFeatures );
599 "Plated slot should use an oval symbol" );
601 wxFileName platedTools( platedDir.GetFullPath(), wxT(
"tools" ) );
603 wxString platedToolsContents =
readFile( platedTools );
604 BOOST_CHECK_EQUAL( countLinesStartingWith( platedToolsContents, wxT(
"TYPE=PLATED" ) ), 1 );
605 BOOST_CHECK_EQUAL( countLinesStartingWith( platedToolsContents, wxT(
"TYPE=NON_PLATED" ) ), 0 );
609 wxFileName nonPlatedDir = layerDir( wxT(
"drill_non-plated_f.cu-b.cu" ) );
610 BOOST_REQUIRE_MESSAGE( nonPlatedDir.DirExists(),
"Non-plated drill layer should exist" );
612 wxFileName nonPlatedFeatures( nonPlatedDir.GetFullPath(), wxT(
"features" ) );
614 wxString nonPlatedContents =
readFile( nonPlatedFeatures );
616 BOOST_CHECK_EQUAL( countLinesStartingWith( nonPlatedContents, wxT(
"P " ) ), 1 );
618 "Non-plated slot should still export an oval symbol" );
620 wxFileName nonPlatedTools( nonPlatedDir.GetFullPath(), wxT(
"tools" ) );
622 wxString nonPlatedToolsContents =
readFile( nonPlatedTools );
623 BOOST_CHECK_EQUAL( countLinesStartingWith( nonPlatedToolsContents, wxT(
"TYPE=NON_PLATED" ) ),
625 BOOST_CHECK_EQUAL( countLinesStartingWith( nonPlatedToolsContents, wxT(
"TYPE=PLATED" ) ), 0 );
627 wxFileName::Rmdir( odbRoot.GetFullPath(), wxPATH_RMDIR_RECURSIVE );
628 wxFileName::Rmdir( tempDir.GetFullPath(), wxPATH_RMDIR_RECURSIVE );
BOOST_CHECK_EQUAL(result, "25.4")