74 PCB_DIFFER ourDiffer( m_ancestor.get(), m_ours.get() );
75 PCB_DIFFER theirDiffer( m_ancestor.get(), m_theirs.get() );
81 BOOST_CHECK(
plan.Resolved() );
82 BOOST_CHECK(
plan.actions.empty() );
85 std::unique_ptr<BOARD> merged = applier.
Apply();
90 m_ancestor->GetItemSet().size() );
100 m_ancestor->GetProject()->GetProjectFile().m_BoardDrawingSheetFile = wxS(
"ancestor.kicad_wks" );
101 m_ours->GetProject()->GetProjectFile().m_BoardDrawingSheetFile = wxS(
"ours.kicad_wks" );
102 m_theirs->GetProject()->GetProjectFile().m_BoardDrawingSheetFile = wxS(
"ancestor.kicad_wks" );
108 std::unique_ptr<BOARD> merged = applier.
Apply();
129 victim =
static_cast<PCB_TRACK*
>( item );
139 PCB_DIFFER ourDiffer( m_ancestor.get(), m_ours.get() );
140 PCB_DIFFER theirDiffer( m_ancestor.get(), m_theirs.get() );
146 std::unique_ptr<BOARD> merged = applier.
Apply();
152 for(
BOARD_ITEM* item : merged->GetItemSet() )
154 if( item && item->m_Uuid == victimUuid )
161 BOOST_CHECK( found );
174 subject =
static_cast<PCB_TRACK*
>( item );
180 int originalWidth = subject->
GetWidth();
181 int newWidth = originalWidth + 75000;
185 PCB_DIFFER ourDiffer( m_ancestor.get(), m_ours.get() );
186 PCB_DIFFER theirDiffer( m_ancestor.get(), m_theirs.get() );
192 std::unique_ptr<BOARD> merged = applier.
Apply();
198 for(
BOARD_ITEM* item : merged->GetItemSet() )
200 if( item && item->m_Uuid == subjectUuid && item->Type() ==
PCB_TRACE_T )
208 BOOST_CHECK( found );
218 for(
BOARD_ITEM* item : m_ours->GetItemSet() )
232 for(
BOARD_ITEM* item : m_theirs->GetItemSet() )
234 if( item && item->m_Uuid == victimUuid )
248 PCB_DIFFER ourDiffer( m_ancestor.get(), m_ours.get() );
249 PCB_DIFFER theirDiffer( m_ancestor.get(), m_theirs.get() );
255 std::unique_ptr<BOARD> merged = applier.
Apply();
259 for(
BOARD_ITEM* item : merged->GetItemSet() )
261 BOOST_CHECK( !item || item->m_Uuid != victimUuid );
270 PCB_DIFFER ourDiffer( m_ancestor.get(), m_ours.get() );
271 PCB_DIFFER theirDiffer( m_ancestor.get(), m_theirs.get() );
277 std::unique_ptr<BOARD> merged = applier.
Apply();
281 plan.requiresZoneRefill );
283 plan.requiresConnectivityRebuild );
292 ZONE* victim =
nullptr;
294 for(
BOARD_ITEM* item : m_theirs->GetItemSet() )
298 victim =
static_cast<ZONE*
>( item );
317 PCB_DIFFER ourDiffer( m_ancestor.get(), m_ours.get() );
318 PCB_DIFFER theirDiffer( m_ancestor.get(), m_theirs.get() );
323 std::unique_ptr<BOARD> merged = applier.
Apply();
328 for(
BOARD_ITEM* item : merged->GetItemSet() )
330 if( item && item->m_Uuid == subjectUuid && item->Type() ==
PCB_ZONE_T )
332 ZONE* z =
static_cast<ZONE*
>( item );
340 BOOST_CHECK( found );
354 for(
BOARD_ITEM* item : m_ours->GetItemSet() )
358 subject =
static_cast<PCB_TRACK*
>( item );
364 int oursWidth = subject->
GetWidth() + 50000;
365 int theirsWidth = subject->
GetWidth() + 75000;
373 for(
BOARD_ITEM* item : m_theirs->GetItemSet() )
375 if( item && item->m_Uuid == subjectUuid && item->Type() ==
PCB_TRACE_T )
382 PCB_DIFFER ourDiffer( m_ancestor.get(), m_ours.get() );
383 PCB_DIFFER theirDiffer( m_ancestor.get(), m_theirs.get() );
388 std::unique_ptr<BOARD> merged = applier.
Apply();
395 for(
BOARD_ITEM* item : merged->GetItemSet() )
397 if( item && item->m_Uuid == subjectUuid && item->Type() ==
PCB_TRACE_T )
399 int mergedWidth =
static_cast<PCB_TRACK*
>( item )->GetWidth();
400 BOOST_CHECK( mergedWidth == oursWidth || mergedWidth == theirsWidth );
417 for(
BOARD_ITEM* item : aBoard->GetItemSet() )
426 PCB_TRACK* ancTrack = firstTrack( m_ancestor.get() );
433 for(
BOARD_ITEM* item : aBoard->GetItemSet() )
435 if( item && item->Type() ==
PCB_TRACE_T && item->m_Uuid == subjectUuid )
442 PCB_TRACK* oursTrack = trackByUuid( m_ours.get() );
443 PCB_TRACK* theirsTrack = trackByUuid( m_theirs.get() );
449 const int oursWidth = ancTrack->
GetWidth() + 11000;
450 const int theirsStart = ancTrack->
GetStartX() + 22000;
451 const int ancEndX = ancTrack->
GetEndX();
452 const int customEndY = ancTrack->
GetEndY() + 33000;
462 action.
id.push_back( subjectUuid );
465 auto addProp = [&](
const wxString& aName,
PROP_RES aKind )
478 customRes.
name = wxS(
"End Y" );
481 action.
props.push_back( customRes );
486 plan.actions.push_back( action );
489 std::unique_ptr<BOARD> merged = applier.
Apply();
494 for(
BOARD_ITEM* item : merged->GetItemSet() )
496 if( item && item->Type() ==
PCB_TRACE_T && item->m_Uuid == subjectUuid )
498 mergedTrack =
static_cast<PCB_TRACK*
>( item );
530 for(
FOOTPRINT* candidate : m_ours->Footprints() )
535 for(
PAD* candidatePad : candidate->Pads() )
537 if( candidatePad && candidatePad->IsOnCopperLayer() )
553 const KIID padUuid =
pad->m_Uuid;
556 const wxString oursPadNumber = wxS(
"QA_CHILD_RESOLVE" );
557 pad->SetNumber( oursPadNumber );
562 action.
id.push_back( fpUuid );
563 action.
id.push_back( padUuid );
567 numberRes.
name = wxS(
"Pad Number" );
569 action.
props.push_back( numberRes );
572 plan.actions.push_back( action );
575 std::unique_ptr<BOARD> merged = applier.
Apply();
581 PAD* mergedPad =
nullptr;
583 for(
FOOTPRINT* mergedFp : merged->Footprints() )
585 if( !mergedFp || mergedFp->m_Uuid != fpUuid )
588 for(
PAD* candidate : mergedFp->Pads() )
590 if( candidate->m_Uuid == padUuid )
592 mergedPad = candidate;
612 PAD* victimPad =
nullptr;
614 for(
FOOTPRINT* candidate : m_ancestor->Footprints() )
616 if( candidate && !candidate->Pads().empty() )
619 victimPad = candidate->Pads().front();
636 action.
id.push_back( fpUuid );
637 action.
id.push_back( padUuid );
641 plan.actions.push_back( action );
644 std::unique_ptr<BOARD> merged = applier.
Apply();
649 for(
FOOTPRINT* mergedFp : merged->Footprints() )
651 if( !mergedFp || mergedFp->m_Uuid != fpUuid )
654 for(
PAD*
pad : mergedFp->Pads() )
656 if(
pad &&
pad->m_Uuid == padUuid )
661 BOOST_CHECK( found );
674 for(
FOOTPRINT* candidate : m_ours->Footprints() )
679 for(
PAD* candidatePad : candidate->Pads() )
681 if( candidatePad && candidatePad->IsOnCopperLayer() )
697 const KIID padUuid =
pad->m_Uuid;
698 const wxString oursPadNumber = wxS(
"QA_CHILD_TAKE_OURS" );
699 pad->SetNumber( oursPadNumber );
702 action.
id.push_back( fpUuid );
703 action.
id.push_back( padUuid );
707 plan.actions.push_back( action );
710 std::unique_ptr<BOARD> merged = applier.
Apply();
713 PAD* mergedPad =
nullptr;
715 for(
FOOTPRINT* mergedFp : merged->Footprints() )
717 if( !mergedFp || mergedFp->m_Uuid != fpUuid )
720 for(
PAD* candidate : mergedFp->Pads() )
722 if( candidate && candidate->m_Uuid == padUuid )
724 mergedPad = candidate;
743 PAD* victimPad =
nullptr;
745 for(
FOOTPRINT* candidate : m_ancestor->Footprints() )
747 if( candidate && !candidate->Pads().empty() )
750 victimPad = candidate->Pads().front();
762 action.
id.push_back( fpUuid );
763 action.
id.push_back( padUuid );
767 plan.actions.push_back( action );
770 std::unique_ptr<BOARD> merged = applier.
Apply();
773 for(
FOOTPRINT* mergedFp : merged->Footprints() )
775 if( !mergedFp || mergedFp->m_Uuid != fpUuid )
778 for(
PAD*
pad : mergedFp->Pads() )
779 BOOST_CHECK( !
pad ||
pad->m_Uuid != padUuid );
787 const KIID fpUuid = m_ancestor->Footprints().front()->m_Uuid;
789 for(
BOARD* board : { m_ancestor.get(), m_ours.get(), m_theirs.get() } )
791 auto* fp =
dynamic_cast<FOOTPRINT*
>( board->ResolveItem( fpUuid,
true ) );
794 for(
const wxString&
name : { wxS(
"Production" ), wxS(
"Prototype" ) } )
799 fp->SetVariant( variant );
803 for(
BOARD*
source : { m_ours.get(), m_theirs.get() } )
805 auto* fp =
dynamic_cast<FOOTPRINT*
>(
source->ResolveItem( fpUuid,
true ) );
807 const wxString
text =
source == m_ours.get() ? wxS(
"QA_OURS" ) : wxS(
"QA_THEIRS" );
808 fp->Value().SetText(
text );
809 fp->Value().SetUuid(
KIID() );
813 BOOST_REQUIRE_EQUAL( diff.
changes.size(), 1u );
814 BOOST_REQUIRE_EQUAL( diff.
changes[0].children.size(), 1u );
818 action.
id = diff.
changes[0].children[0].id;
821 plan.actions.push_back( action );
824 std::unique_ptr<BOARD> merged = applier.
Apply();
826 auto* mergedFp =
dynamic_cast<FOOTPRINT*
>( merged->ResolveItem( fpUuid,
true ) );
829 BOOST_CHECK( mergedFp->Value().GetParent() == mergedFp );
830 BOOST_CHECK( merged->ResolveItem( mergedFp->Value().m_Uuid,
true ) == &mergedFp->Value() );
832 for(
const wxString&
name : { wxS(
"Production" ), wxS(
"Prototype" ) } )
846 const KIID fpUuid = m_ancestor->Footprints().front()->m_Uuid;
847 const wxString fieldName = wxS(
"QA_RemovedField" );
849 for(
BOARD* board : { m_ancestor.get(), m_ours.get(), m_theirs.get() } )
851 auto* fp =
dynamic_cast<FOOTPRINT*
>( board->ResolveItem( fpUuid,
true ) );
854 field->SetText( wxS(
"Original text" ) );
857 for(
const wxString&
name : { wxS(
"Production" ), wxS(
"Prototype" ) } )
862 fp->SetVariant( variant );
866 auto* oursFp =
dynamic_cast<FOOTPRINT*
>( m_ours->ResolveItem( fpUuid,
true ) );
868 PCB_FIELD* removedField = oursFp->GetField( fieldName );
870 oursFp->Remove( removedField );
873 PCB_DIFFER differ( m_ancestor.get(), m_ours.get() );
875 BOOST_REQUIRE_EQUAL( diff.
changes.size(), 1u );
876 BOOST_REQUIRE_EQUAL( diff.
changes[0].children.size(), 1u );
881 action.
id = diff.
changes[0].children[0].id;
884 plan.actions.push_back( action );
887 std::unique_ptr<BOARD> merged = applier.
Apply();
889 auto* mergedFp =
dynamic_cast<FOOTPRINT*
>( merged->ResolveItem( fpUuid,
true ) );
891 BOOST_CHECK( mergedFp->GetField( fieldName ) ==
nullptr );
893 for(
const wxString&
name : { wxS(
"Production" ), wxS(
"Prototype" ) } )
std::set< BOARD_ITEM *, CompareByUuid > BOARD_ITEM_SET
Set of BOARD_ITEMs ordered by UUID.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Information pertinent to a Pcbnew printed circuit board.
static DIFF_VALUE FromInt(int aValue)
Three-way merge plan generator.
MERGE_PLAN Plan(const DOCUMENT_DIFF &aAncestorOurs, const DOCUMENT_DIFF &aAncestorTheirs) const
Plan the merge given the canonical pair of diffs.
Diff two already-parsed BOARDs and produce a DOCUMENT_DIFF.
DOCUMENT_DIFF Diff() override
Produce a DOCUMENT_DIFF of the inputs the concrete differ was constructed with.
Materialize a MERGE_PLAN into a real merged BOARD.
std::unique_ptr< BOARD > Apply()
Produce the merged board.
const REPORT & GetReport() const
const wxString & GetNumber() const
virtual void SetWidth(int aWidth)
virtual int GetWidth() const
Handle a list of polygons defining a copper zone.
bool GetDoNotAllowTracks() const
void SetDoNotAllowTracks(bool aEnable)
void SetAssignedPriority(unsigned aPriority)
unsigned GetAssignedPriority() const
static std::vector< PENDING_PROPERTY > plan(const EDA_ITEM &aSource, const EDA_ITEM &aTarget, const std::set< wxString > &aEnabledKeys)
Target properties to write, paired with values read off the source.
PROP_RES
Resolution kind for a single property of a single item.
void LoadBoard(SETTINGS_MANAGER &aSettingsManager, const wxString &aRelPath, std::unique_ptr< BOARD > &aBoard)
The full set of changes between two parsed documents of one type.
std::vector< ITEM_CHANGE > changes
std::vector< PROPERTY_RESOLUTION > props
Result of planning a 3-way merge.
std::size_t propertiesFailed
std::size_t propertiesApplied
bool drcSeveritiesTouched
bool projectFileTouched
True iff the applier resolved state that lives in the .kicad_pro or a project sibling file.
std::size_t itemsTakenOurs
bool requiresConnectivityRebuild
wxString drawingSheetFile
Drawing sheet path the applier resolved (from a doc-level resolution).
Three-board fixture: ancestor, ours, theirs all start from the same fixture load.
std::unique_ptr< BOARD > m_ours
std::unique_ptr< BOARD > m_ancestor
std::unique_ptr< BOARD > m_theirs
@ USER
The field ID hasn't been set yet; field is invalid.
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(IdenticalInputsProduceIdenticalOutput)
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")
BOOST_CHECK_EQUAL(result, "25.4")
@ PCB_ZONE_T
class ZONE, a copper pour area
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)