164 BOOST_REQUIRE_MESSAGE( Start(), LastError() );
166 kiapi::common::types::DocumentSpecifier document;
168 wxFileName boardPath( testDataDir, wxS(
"api_kitchen_sink.kicad_pcb" ) );
170 BOOST_REQUIRE_MESSAGE( Client().OpenDocument( boardPath.GetFullPath(), &document ),
171 "OpenDocument failed: " + Client().LastError() );
173 BOOST_REQUIRE( document.type() == kiapi::common::types::DOCTYPE_PCB );
174 BOOST_REQUIRE( boardPath.GetFullName().Matches( document.board_filename() ) );
176 int footprintCount = 0;
178 BOOST_REQUIRE_MESSAGE( Client().GetItemsCount( document, kiapi::common::types::KOT_PCB_FOOTPRINT, &footprintCount ),
179 "GetItems failed: " + Client().LastError() );
181 BOOST_CHECK_GT( footprintCount, 0 );
189 BOOST_REQUIRE_MESSAGE( Start(), LastError() );
191 kiapi::common::types::DocumentSpecifier document;
194 BOOST_REQUIRE_MESSAGE( Client().OpenDocument( boardPath.GetFullPath(), &document ),
195 "OpenDocument failed: " + Client().LastError() );
199 BOOST_REQUIRE_MESSAGE( Client().GetFirstFootprint( document, &footprint ),
200 "GetFirstFootprint failed: " + Client().LastError() );
205 kiapi::common::commands::DeleteItems request;
206 *request.mutable_header()->mutable_document() = document;
209 kiapi::common::ApiResponse response;
211 BOOST_REQUIRE_MESSAGE( Client().SendCommand( request, &response ),
212 "DeleteItems failed: " + Client().LastError() );
213 BOOST_REQUIRE_EQUAL( response.status().status(), kiapi::common::AS_OK );
215 kiapi::common::commands::DeleteItemsResponse deleteResponse;
217 BOOST_REQUIRE( response.message().UnpackTo( &deleteResponse ) );
218 BOOST_REQUIRE_EQUAL( deleteResponse.deleted_items_size(), 1 );
220 kiapi::common::commands::ItemDeletionStatus::IDS_IMMUTABLE );
224 BOOST_REQUIRE_MESSAGE( Client().GetFirstFootprint( document, &after ),
225 "GetFirstFootprint after delete failed: " + Client().LastError() );
236 BOOST_REQUIRE_MESSAGE( Start(), LastError() );
239 wxFileName boardPathA( testDataDir, wxS(
"api_kitchen_sink.kicad_pcb" ) );
240 wxFileName boardPathB( testDataDir, wxS(
"padstacks.kicad_pcb" ) );
242 kiapi::common::types::DocumentSpecifier documentA;
244 BOOST_REQUIRE_MESSAGE( Client().OpenDocument( boardPathA.GetFullPath(), &documentA ),
245 "OpenDocument for first board failed: " + Client().LastError() );
249 BOOST_REQUIRE_MESSAGE( Client().GetFirstFootprint( documentA, &footprintA ),
250 "GetFirstFootprint for first board failed: " + Client().LastError() );
253 kiapi::common::ApiStatusCode closeStatusA = kiapi::common::AS_UNKNOWN;
255 BOOST_REQUIRE_MESSAGE( Client().CloseDocument( &documentA, &closeStatusA ),
256 "CloseDocument for first board failed: " + Client().LastError() );
259 kiapi::common::types::DocumentSpecifier documentB;
261 BOOST_REQUIRE_MESSAGE( Client().OpenDocument( boardPathB.GetFullPath(), &documentB ),
262 "OpenDocument for second board failed: " + Client().LastError() );
266 BOOST_REQUIRE_MESSAGE( Client().GetFirstFootprint( documentB, &footprintB ),
267 "GetFirstFootprint for second board failed: " + Client().LastError() );
269 BOOST_CHECK_NE( footprintA.
Similarity( footprintB ), 1.0 );
271 kiapi::common::ApiStatusCode closeStatus = kiapi::common::AS_UNKNOWN;
273 BOOST_REQUIRE_MESSAGE( Client().CloseDocument( &documentB, &closeStatus ),
274 "CloseDocument failed: " + Client().LastError() );
277 BOOST_REQUIRE_MESSAGE( Client().CloseDocument(
nullptr, &closeStatus ),
278 "CloseDocument after already closed failed: " + Client().LastError() );
285 BOOST_REQUIRE_MESSAGE( Start(), LastError() );
287 kiapi::common::types::DocumentSpecifier document;
290 BOOST_REQUIRE_MESSAGE( Client().OpenDocument( boardPath.GetFullPath(), &document ),
291 "OpenDocument failed: " + Client().LastError() );
293 kiapi::board::commands::BoardDesignRulesResponse rulesResponse;
297 "GetBoardDesignRules failed: " + error );
299 BOOST_CHECK_GE( rulesResponse.rules().constraints().min_clearance().value_nm(), 0 );
300 BOOST_CHECK_GE( rulesResponse.rules().constraints().min_track_width().value_nm(), 0 );
301 BOOST_CHECK( rulesResponse.custom_rules_status() == kiapi::board::commands::CRS_VALID );
307 BOOST_REQUIRE_MESSAGE( Start(), LastError() );
312 BOOST_REQUIRE_MESSAGE( fixtureCopy.
Create( ©Error ), copyError );
314 kiapi::common::types::DocumentSpecifier document;
316 BOOST_REQUIRE_MESSAGE( Client().OpenDocument( fixtureCopy.
BoardPath(), &document ),
317 "OpenDocument failed: " + Client().LastError() );
319 kiapi::board::commands::BoardDesignRulesResponse getResponse;
322 "Initial GetBoardDesignRules failed: " + copyError );
324 int newWidth = getResponse.rules().constraints().min_track_width().value_nm() + 1000;
326 kiapi::board::commands::SetBoardDesignRules setRequest;
327 *setRequest.mutable_board() = document;
328 *setRequest.mutable_rules()->mutable_constraints() = getResponse.rules().constraints();
329 setRequest.mutable_rules()->mutable_constraints()->mutable_min_track_width()->set_value_nm( newWidth );
331 kiapi::common::ApiResponse setApiResponse;
333 BOOST_REQUIRE_MESSAGE( Client().SendCommand( setRequest, &setApiResponse ),
334 "SetBoardDesignRules failed to send: " + Client().LastError() );
335 BOOST_REQUIRE( setApiResponse.status().status() == kiapi::common::AS_OK );
337 kiapi::board::commands::BoardDesignRulesResponse setResponse;
338 BOOST_REQUIRE( setApiResponse.message().UnpackTo( &setResponse ) );
340 BOOST_CHECK_EQUAL( setResponse.rules().constraints().min_track_width().value_nm(), newWidth );
342 kiapi::board::commands::BoardDesignRulesResponse verifyResponse;
345 "Verification GetBoardDesignRules failed: " + copyError );
347 BOOST_CHECK_EQUAL( verifyResponse.rules().constraints().min_track_width().value_nm(), newWidth );
353 BOOST_REQUIRE_MESSAGE( Start(), LastError() );
358 BOOST_REQUIRE_MESSAGE( fixtureCopy.
Create( ©Error ), copyError );
360 kiapi::common::types::DocumentSpecifier document;
362 BOOST_REQUIRE_MESSAGE( Client().OpenDocument( fixtureCopy.
BoardPath(), &document ),
363 "OpenDocument failed: " + Client().LastError() );
365 kiapi::board::commands::BoardDesignRulesResponse getResponse;
368 "Initial GetBoardDesignRules failed: " + copyError );
370 kiapi::board::commands::SetBoardDesignRules setRequest;
371 *setRequest.mutable_board() = document;
372 *setRequest.mutable_rules()->mutable_constraints() = getResponse.rules().constraints();
373 setRequest.mutable_rules()->mutable_constraints()->mutable_min_track_width()->set_value_nm( 1000000000 );
375 kiapi::common::ApiResponse response;
377 BOOST_REQUIRE_MESSAGE( Client().SendCommand( setRequest, &response ),
378 "SetBoardDesignRules failed to send: " + Client().LastError() );
380 BOOST_CHECK( response.status().status() == kiapi::common::AS_BAD_REQUEST );
381 BOOST_CHECK( !response.status().error_message().empty() );
387 BOOST_REQUIRE_MESSAGE( Start(), LastError() );
392 BOOST_REQUIRE_MESSAGE( fixtureCopy.
Create( ©Error ), copyError );
394 kiapi::common::types::DocumentSpecifier document;
396 BOOST_REQUIRE_MESSAGE( Client().OpenDocument( fixtureCopy.
BoardPath(), &document ),
397 "OpenDocument failed: " + Client().LastError() );
399 kiapi::board::commands::BoardDesignRulesResponse getResponse;
401 "Initial GetBoardDesignRules failed: " + copyError );
403 auto applySeverityAndVerify = [&]( kiapi::common::types::RuleSeverity aSeverity )
405 kiapi::board::commands::SetBoardDesignRules setRequest;
406 *setRequest.mutable_board() = document;
408 kiapi::board::DrcSeveritySetting* setting = setRequest.mutable_rules()->add_severities();
409 setting->set_rule_type( kiapi::board::DrcErrorType::DRCET_UNCONNECTED_ITEMS );
410 setting->set_severity( aSeverity );
412 kiapi::common::ApiResponse setApiResponse;
413 BOOST_REQUIRE_MESSAGE( Client().SendCommand( setRequest, &setApiResponse ),
414 "SetBoardDesignRules failed to send: " + Client().LastError() );
415 BOOST_REQUIRE( setApiResponse.status().status() == kiapi::common::AS_OK );
417 kiapi::board::commands::BoardDesignRulesResponse verifyResponse;
419 "Verification GetBoardDesignRules failed: " + copyError );
423 for(
const kiapi::board::DrcSeveritySetting& severity : verifyResponse.rules().severities() )
425 if( severity.rule_type() == kiapi::board::DrcErrorType::DRCET_UNCONNECTED_ITEMS )
428 BOOST_CHECK( severity.severity() == aSeverity );
433 BOOST_CHECK( found );
436 applySeverityAndVerify( kiapi::common::types::RS_IGNORE );
437 applySeverityAndVerify( kiapi::common::types::RS_ERROR );
443 BOOST_REQUIRE_MESSAGE( Start(), LastError() );
445 kiapi::common::types::DocumentSpecifier document;
448 BOOST_REQUIRE_MESSAGE( Client().OpenDocument( boardPath.GetFullPath(), &document ),
449 "OpenDocument failed: " + Client().LastError() );
451 kiapi::board::commands::CustomRulesResponse response;
455 "GetCustomDesignRules failed: " + error );
457 BOOST_CHECK( response.status() == kiapi::board::commands::CRS_VALID );
458 BOOST_CHECK_GT( response.rules_size(), 0 );
460 bool foundFixtureRule =
false;
462 for(
const kiapi::board::CustomRule& rule : response.rules() )
464 if( rule.name() ==
"myrule" )
466 foundFixtureRule =
true;
474 BOOST_CHECK( foundFixtureRule );
480 BOOST_REQUIRE_MESSAGE( Start(), LastError() );
485 BOOST_REQUIRE_MESSAGE( fixtureCopy.
Create( ©Error ), copyError );
487 kiapi::common::types::DocumentSpecifier document;
489 BOOST_REQUIRE_MESSAGE( Client().OpenDocument( fixtureCopy.
BoardPath(), &document ),
490 "OpenDocument failed: " + Client().LastError() );
492 kiapi::board::commands::CustomRulesResponse response;
496 "GetCustomDesignRules failed: " + error );
498 BOOST_CHECK( response.status() == kiapi::board::commands::CRS_VALID );
499 BOOST_CHECK_GT( response.rules_size(), 0 );
501 kiapi::board::commands::SetCustomDesignRules setRequest;
502 *setRequest.mutable_board() = document;
504 setRequest.mutable_rules()->CopyFrom( response.rules() );
506 kiapi::board::CustomRule* rule = setRequest.add_rules();
507 rule->set_name(
"api_roundtrip_rule" );
508 rule->set_condition(
"A.NetClass == 'HV'" );
509 rule->set_layer_mode( kiapi::board::CRLM_OUTER );
510 rule->set_severity( kiapi::common::types::RS_WARNING );
512 kiapi::board::CustomRuleConstraint* annular = rule->add_constraints();
513 annular->set_type( kiapi::board::CRCT_TRACK_WIDTH );
514 annular->mutable_numeric()->set_min( 3000000 );
515 annular->mutable_numeric()->set_opt( 4000000 );
516 annular->mutable_numeric()->set_max( 5000000 );
518 kiapi::board::CustomRuleConstraint* disallow = rule->add_constraints();
519 disallow->set_type( kiapi::board::CRCT_DISALLOW );
520 disallow->mutable_disallow()->add_types( kiapi::board::CRDT_BLIND_VIAS );
522 kiapi::common::ApiResponse setApiResponse;
524 BOOST_REQUIRE_MESSAGE( Client().SendCommand( setRequest, &setApiResponse ),
525 "SetCustomDesignRules failed to send: " + Client().LastError() );
526 BOOST_REQUIRE( setApiResponse.status().status() == kiapi::common::AS_OK );
528 kiapi::board::commands::CustomRulesResponse setResponse;
529 BOOST_REQUIRE( setApiResponse.message().UnpackTo( &setResponse ) );
531 int num_rules = setResponse.rules_size();
532 BOOST_CHECK( setResponse.status() == kiapi::board::commands::CRS_VALID );
534 BOOST_CHECK_EQUAL( setResponse.rules( num_rules - 1 ).name(),
"api_roundtrip_rule" );
540 BOOST_REQUIRE_MESSAGE( Start(), LastError() );
545 BOOST_REQUIRE_MESSAGE( fixtureCopy.
Create( ©Error, wxS(
"issue25846/custom_rules.kicad_dru" ) ),
548 kiapi::common::types::DocumentSpecifier document;
550 BOOST_REQUIRE_MESSAGE( Client().OpenDocument( fixtureCopy.
BoardPath(), &document ),
551 "OpenDocument failed: " + Client().LastError() );
553 kiapi::board::commands::CustomRulesResponse getResponse;
557 "GetCustomDesignRules failed: " + error );
558 BOOST_REQUIRE( getResponse.status() == kiapi::board::commands::CRS_VALID );
559 BOOST_REQUIRE_GT( getResponse.rules_size(), 0 );
561 bool sawReturnPath =
false;
563 for(
const kiapi::board::CustomRule& rule : getResponse.rules() )
565 for(
const kiapi::board::CustomRuleConstraint& constraint : rule.constraints() )
567 if( constraint.type() != kiapi::board::CRCT_NET_CHAIN_RETURN_PATH )
570 sawReturnPath =
true;
576 BOOST_CHECK( sawReturnPath );
578 kiapi::board::commands::SetCustomDesignRules setRequest;
579 *setRequest.mutable_board() = document;
580 setRequest.mutable_rules()->CopyFrom( getResponse.rules() );
582 kiapi::common::ApiResponse setApiResponse;
584 BOOST_REQUIRE_MESSAGE( Client().SendCommand( setRequest, &setApiResponse ),
585 "SetCustomDesignRules failed to send: " + Client().LastError() );
586 BOOST_REQUIRE_MESSAGE( setApiResponse.status().status() == kiapi::common::AS_OK,
587 setApiResponse.status().error_message() );
589 kiapi::board::commands::CustomRulesResponse setResponse;
590 BOOST_REQUIRE( setApiResponse.message().UnpackTo( &setResponse ) );
591 BOOST_REQUIRE( setResponse.status() == kiapi::board::commands::CRS_VALID );
592 BOOST_REQUIRE_EQUAL( setResponse.rules_size(), getResponse.rules_size() );
594 for(
int ii = 0; ii < getResponse.rules_size(); ++ii )
596 BOOST_CHECK_MESSAGE( setResponse.rules( ii ).SerializeAsString() == getResponse.rules( ii ).SerializeAsString(),
597 getResponse.rules( ii ).name() <<
" changed in the round trip" );
604 BOOST_REQUIRE_MESSAGE( Start(), LastError() );
608 kiapi::common::types::DocumentSpecifier projectDoc;
610 BOOST_REQUIRE_MESSAGE( Client().OpenDocument( testDataDir + wxS(
"basic_test.kicad_pro" ),
611 kiapi::common::types::DOCTYPE_PROJECT, &projectDoc ),
612 "OpenDocument for project failed: " + Client().LastError() );
614 BOOST_REQUIRE( projectDoc.type() == kiapi::common::types::DOCTYPE_PROJECT );
616 kiapi::common::types::DocumentSpecifier boardDoc;
618 BOOST_REQUIRE_MESSAGE( Client().OpenDocument( testDataDir + wxS(
"basic_test.kicad_pcb" ),
619 kiapi::common::types::DOCTYPE_PCB, &boardDoc ),
620 "OpenDocument for board failed: " + Client().LastError() );
622 BOOST_REQUIRE( boardDoc.type() == kiapi::common::types::DOCTYPE_PCB );
625 int footprintCount = 0;
626 BOOST_REQUIRE_MESSAGE( Client().GetItemsCount( boardDoc, kiapi::common::types::KOT_PCB_FOOTPRINT, &footprintCount ),
627 "GetItems for board failed: " + Client().LastError() );
628 BOOST_CHECK_GT( footprintCount, 0 );
630 kiapi::common::types::DocumentSpecifier schDoc;
632 BOOST_REQUIRE_MESSAGE( Client().OpenDocument( testDataDir + wxS(
"basic_test.kicad_sch" ),
633 kiapi::common::types::DOCTYPE_SCHEMATIC, &schDoc ),
634 "OpenDocument for schematic failed: " + Client().LastError() );
636 BOOST_REQUIRE( schDoc.type() == kiapi::common::types::DOCTYPE_SCHEMATIC );
640 BOOST_REQUIRE_MESSAGE( Client().GetItemsCount( boardDoc, kiapi::common::types::KOT_PCB_FOOTPRINT, &footprintCount ),
641 "GetItems for board after opening schematic failed: " + Client().LastError() );
642 BOOST_CHECK_GT( footprintCount, 0 );
647 kiapi::common::types::DocumentSpecifier otherBoardDoc;
649 BOOST_REQUIRE_MESSAGE(
650 !Client().OpenDocument( otherDataDir + wxS(
"api_kitchen_sink.kicad_pcb" ),
651 kiapi::common::types::DOCTYPE_PCB, &otherBoardDoc ),
652 "OpenDocument for a different-project board should have failed" );
654 BOOST_CHECK( Client().LastError().Contains( wxS(
"already open" ) ) );
660 BOOST_REQUIRE_MESSAGE( Start(), LastError() );
663 [&]( kiapi::common::types::DocumentType aType,
const wxString& aExpectedExt )
668 wxFileName fileWithExt( tempDir.
ChildPathStr(
"new_doc" + aExpectedExt ) );
669 wxFileName projectWithExt( tempDir.
ChildPathStr(
"new_doc.kicad_pro" ) );
671 kiapi::common::types::DocumentSpecifier document;
673 BOOST_REQUIRE_MESSAGE( Client().CreateDocument( tempFn, aType, &document ),
674 "CreateDocument failed: " + Client().LastError() );
676 BOOST_CHECK( document.type() == aType );
677 BOOST_CHECK( document.project().name() == projectWithExt.GetName() );
678 BOOST_CHECK( document.project().path() == projectWithExt.GetPath( wxPATH_GET_SEPARATOR | wxPATH_GET_VOLUME ) );
680 kiapi::common::ApiResponse response;
681 kiapi::common::commands::GetDocumentModifiedState state;
682 state.mutable_document()->CopyFrom( document );
683 BOOST_CHECK( Client().SendCommand( state, &response ) );
686 BOOST_CHECK( !wxFileName( fileWithExt ).FileExists() );
687 BOOST_CHECK( !wxFileName( projectWithExt ).FileExists() );
689 kiapi::common::commands::SaveDocument
save;
690 save.mutable_document()->CopyFrom( document );
691 BOOST_CHECK( Client().SendCommand(
save, &response ) );
693 BOOST_CHECK( wxFileName( fileWithExt ).FileExists() );
694 BOOST_CHECK( wxFileName( projectWithExt ).FileExists() );
697 std::map<kiapi::common::types::DocumentType, wxString> cases = {
698 { kiapi::common::types::DOCTYPE_PCB, wxS(
".kicad_pcb" )},
699 { kiapi::common::types::DOCTYPE_SCHEMATIC, wxS(
".kicad_sch" ) }
702 for(
const auto& [docType, ext] : cases )
706 test( docType, ext );
714 using namespace kiapi::common::commands;
716 BOOST_REQUIRE_MESSAGE( Start(), LastError() );
719 [&]( kiapi::common::types::DocumentType aType,
const wxString& aExistingPath )
722 wxString docFileName = tempDir.
ChildPathStr(
"new_doc" );
724 kiapi::common::types::DocumentSpecifier existingDoc;
726 BOOST_REQUIRE_MESSAGE( Client().OpenDocument( aExistingPath, aType, &existingDoc ),
727 "OpenDocument failed: " + Client().LastError() );
729 SetPageSettings modify;
730 modify.mutable_document()->CopyFrom( existingDoc );
731 modify.mutable_page_settings()->set_orientation( kiapi::common::types::PO_PORTRAIT );
732 kiapi::common::ApiResponse response;
733 BOOST_CHECK( Client().SendCommand( modify, &response ) );
735 GetDocumentModifiedState stateQuery;
736 stateQuery.mutable_document()->CopyFrom( existingDoc );
737 BOOST_CHECK( Client().SendCommand( stateQuery, &response ) );
738 GetDocumentModifiedStateResponse state;
739 BOOST_CHECK( response.message().UnpackTo( &state ) );
740 BOOST_CHECK( state.state() == DocumentModifiedState::DMS_MODIFIED );
742 kiapi::common::types::DocumentSpecifier newDoc;
744 BOOST_REQUIRE( !Client().CreateDocument( docFileName, aType, &newDoc ) );
746 BOOST_CHECK( Client().LastError().Contains( wxS(
"save or revert" ) ) );
748 kiapi::common::commands::RevertDocument revert;
749 revert.mutable_document()->CopyFrom( existingDoc );
750 BOOST_CHECK( Client().SendCommand( revert, &response ) );
752 BOOST_REQUIRE( Client().CreateDocument( docFileName, aType, &newDoc ) );
754 BOOST_CHECK( Client().CloseAllDocuments() );
757 std::map<kiapi::common::types::DocumentType, wxString> cases = {
758 { kiapi::common::types::DOCTYPE_PCB,
760 { kiapi::common::types::DOCTYPE_SCHEMATIC,
764 for(
const auto& [docType,
path] : cases )
776 BOOST_REQUIRE_MESSAGE( Start(), LastError() );
779 [&]( kiapi::common::types::DocumentType aType,
const wxString& aSourcePath,
780 const wxString& aSourceName,
const wxString& aDocumentExt )
784 wxString sourceCopy = tempDir.
ChildPathStr( aSourceName );
785 BOOST_REQUIRE( wxCopyFile( aSourcePath, sourceCopy,
true ) );
787 kiapi::common::types::DocumentSpecifier document;
789 BOOST_REQUIRE_MESSAGE( Client().OpenDocument( sourceCopy, aType, &document ),
790 "OpenDocument failed: " + Client().LastError() );
792 wxFileName newDocFile( tempDir.
ChildPathStr(
"renamed" + aDocumentExt ) );
793 wxFileName newProjectFile( tempDir.
ChildPathStr(
"renamed.kicad_pro" ) );
795 kiapi::common::commands::SaveDocumentAs saveAs;
796 saveAs.mutable_document()->CopyFrom( document );
797 saveAs.set_path( tempDir.
ChildPathStr(
"renamed" ).ToStdString() );
799 kiapi::common::ApiResponse response;
800 BOOST_REQUIRE_MESSAGE( Client().SendCommand( saveAs, &response ),
801 "SaveDocumentAs failed to send: " + Client().LastError() );
802 BOOST_REQUIRE( response.status().status() == kiapi::common::AS_OK );
804 BOOST_CHECK( newDocFile.FileExists() );
805 BOOST_CHECK( newProjectFile.FileExists() );
807 kiapi::common::commands::GetOpenDocuments openDocs;
808 openDocs.set_type( aType );
809 BOOST_REQUIRE( Client().SendCommand( openDocs, &response ) );
811 kiapi::common::commands::GetOpenDocumentsResponse docsResponse;
812 BOOST_REQUIRE( response.message().UnpackTo( &docsResponse ) );
813 BOOST_REQUIRE_EQUAL( docsResponse.documents_size(), 1 );
815 kiapi::common::types::DocumentSpecifier renamedDoc = docsResponse.documents( 0 );
820 wxString expectedProjectPath = ( aType == kiapi::common::types::DOCTYPE_PCB )
821 ? newProjectFile.GetPath()
822 : newProjectFile.GetPath( wxPATH_GET_SEPARATOR | wxPATH_GET_VOLUME );
824 BOOST_CHECK_EQUAL( renamedDoc.project().path(), expectedProjectPath.ToStdString() );
825 BOOST_CHECK_EQUAL( renamedDoc.project().name(), newProjectFile.GetName().ToStdString() );
827 if( aType == kiapi::common::types::DOCTYPE_PCB )
828 BOOST_CHECK_EQUAL( renamedDoc.board_filename(), newDocFile.GetFullName().ToStdString() );
831 kiapi::common::commands::GetDocumentModifiedState stateQuery;
832 stateQuery.mutable_document()->CopyFrom( document );
833 BOOST_CHECK( Client().SendCommand( stateQuery, &response ) );
834 BOOST_CHECK( response.status().status() != kiapi::common::AS_OK );
837 stateQuery.mutable_document()->CopyFrom( renamedDoc );
838 BOOST_CHECK( Client().SendCommand( stateQuery, &response ) );
839 BOOST_REQUIRE( response.status().status() == kiapi::common::AS_OK );
841 kiapi::common::commands::GetDocumentModifiedStateResponse state;
843 BOOST_CHECK( state.state() == kiapi::common::commands::DocumentModifiedState::DMS_UNMODIFIED );
845 kiapi::common::commands::SaveDocument
save;
846 save.mutable_document()->CopyFrom( renamedDoc );
847 BOOST_CHECK( Client().SendCommand(
save, &response ) );
848 BOOST_CHECK( response.status().status() == kiapi::common::AS_OK );
851 kiapi::common::ApiStatusCode closeStatus = kiapi::common::AS_UNKNOWN;
852 BOOST_REQUIRE_MESSAGE( Client().CloseDocument( &renamedDoc, &closeStatus ),
853 "CloseDocument after SaveAs failed: " + Client().LastError() );
861 wxString documentExt;
864 std::map<kiapi::common::types::DocumentType, SaveAsCase> cases = {
865 { kiapi::common::types::DOCTYPE_PCB,
867 wxS(
"api_kitchen_sink.kicad_pcb" ), wxS(
".kicad_pcb" ) } },
868 { kiapi::common::types::DOCTYPE_SCHEMATIC,
870 wxS(
"api_kitchen_sink.kicad_sch" ), wxS(
".kicad_sch" ) } }
873 for(
const auto& [docType,
source] : cases )
885 BOOST_REQUIRE_MESSAGE( Start(), LastError() );
891 kiapi::common::types::DocumentSpecifier document;
893 BOOST_REQUIRE_MESSAGE( Client().OpenDocument( sourcePath, &document ),
894 "OpenDocument failed: " + Client().LastError() );
896 kiapi::common::ApiResponse response;
899 kiapi::common::commands::SaveDocumentAs emptyPath;
900 emptyPath.mutable_document()->CopyFrom( document );
901 BOOST_CHECK( Client().SendCommand( emptyPath, &response ) );
902 BOOST_CHECK( response.status().status() == kiapi::common::AS_BAD_REQUEST );
903 BOOST_CHECK( wxString( response.status().error_message() ).Contains( wxS(
"path is required" ) ) );
906 kiapi::common::commands::SaveDocumentAs staleDoc;
907 staleDoc.mutable_document()->CopyFrom( document );
908 staleDoc.mutable_document()->set_board_filename(
"no_such_board.kicad_pcb" );
909 staleDoc.set_path( tempDir.
ChildPathStr(
"never_written" ).ToStdString() );
910 BOOST_CHECK( Client().SendCommand( staleDoc, &response ) );
911 BOOST_CHECK( response.status().status() == kiapi::common::AS_BAD_REQUEST );
913 BOOST_CHECK( !wxFileName( tempDir.
ChildPathStr(
"never_written.kicad_pcb" ) ).FileExists() );
915 Client().CloseAllDocuments();
921 BOOST_REQUIRE_MESSAGE( Start(), LastError() );
927 kiapi::common::types::DocumentSpecifier document;
929 BOOST_REQUIRE_MESSAGE( Client().OpenDocument( sourcePath, &document ),
930 "OpenDocument failed: " + Client().LastError() );
935 kiapi::common::commands::SaveDocumentAs saveAs;
936 saveAs.mutable_document()->CopyFrom( document );
937 saveAs.set_path( ( subdir + wxS(
"/moved" ) ).
ToStdString() );
939 kiapi::common::ApiResponse response;
940 BOOST_REQUIRE_MESSAGE( Client().SendCommand( saveAs, &response ),
941 "SaveDocumentAs failed to send: " + Client().LastError() );
942 BOOST_REQUIRE( response.status().status() == kiapi::common::AS_OK );
944 BOOST_CHECK( wxFileName( subdir + wxS(
"/moved.kicad_pcb" ) ).FileExists() );
945 BOOST_CHECK( wxFileName( subdir + wxS(
"/moved.kicad_pro" ) ).FileExists() );
948 kiapi::common::types::DocumentSpecifier otherBoard;
949 BOOST_REQUIRE_MESSAGE( !Client().OpenDocument( sourcePath, &otherBoard ),
950 "Opening a board from the old project directory should have failed" );
951 BOOST_CHECK( Client().LastError().Contains( wxS(
"already open" ) ) );
953 Client().CloseAllDocuments();
BOOST_CHECK_EQUAL(result, "25.4")