/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2022 Roberto Fernandez Bautista * Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include #include "eeschema_test_utils.h" #include #include // SCH_MULTI_UNIT_REFERENCE_MAP struct REANNOTATED_REFERENCE { wxString m_KIID; ///< KIID of the symbol to reannotate wxString m_OriginalRef; ///< Original Reference Designator (prior to reannotating) wxString m_ExpectedRef; ///< Expected Reference Designator (after reannotating) bool m_IncludeInReannotationList; ///< True if reference is "selected" for reannotation }; class TEST_SCH_REFERENCE_LIST_FIXTURE : public KI_TEST::SCHEMATIC_TEST_FIXTURE { protected: void loadTestCase( wxString aSchematicRelativePath, std::vector aRefs ); SCH_SYMBOL* getSymbolByKIID( wxString aKIID, SCH_SHEET_PATH* aSymbolPath ); SCH_REFERENCE_LIST getAdditionalRefs(); void checkAnnotation( std::vector aRefs ); SCH_REFERENCE_LIST m_refsToReannotate; SCH_MULTI_UNIT_REFERENCE_MAP m_lockedRefs; }; void TEST_SCH_REFERENCE_LIST_FIXTURE::loadTestCase( wxString aSchematicRelativePath, std::vector aRefs ) { m_refsToReannotate.Clear(); m_lockedRefs.clear(); loadSchematic( aSchematicRelativePath ); // Create list of references to reannotate for( REANNOTATED_REFERENCE ref : aRefs ) { SCH_SHEET_PATH symbolPath; SCH_SYMBOL* symbol = getSymbolByKIID( ref.m_KIID, &symbolPath ); //Make sure test case is built properly BOOST_REQUIRE_NE( symbol, nullptr ); BOOST_REQUIRE_EQUAL( symbol->GetRef( &symbolPath, true ), ref.m_OriginalRef ); if( ref.m_IncludeInReannotationList ) { symbolPath.AppendSymbol( m_refsToReannotate, symbol ); symbolPath.AppendMultiUnitSymbol( m_lockedRefs, symbol ); } } } SCH_SYMBOL* TEST_SCH_REFERENCE_LIST_FIXTURE::getSymbolByKIID( wxString aKIID, SCH_SHEET_PATH* aSymbolPath ) { SCH_SHEET_LIST sheets = m_schematic.GetSheets(); KIID symKIID( aKIID ); SCH_ITEM* foundItem = sheets.GetItem( symKIID, aSymbolPath ); SCH_SYMBOL* symbol = dynamic_cast( foundItem ); return symbol; }; SCH_REFERENCE_LIST TEST_SCH_REFERENCE_LIST_FIXTURE::getAdditionalRefs() { // Build List of additional references to pass into Annotate() SCH_REFERENCE_LIST allRefs, additionalRefs; m_schematic.GetSheets().GetSymbols( allRefs ); for( size_t i = 0; i < allRefs.GetCount(); ++i ) { if( !m_refsToReannotate.Contains( allRefs[i] ) ) additionalRefs.AddItem( allRefs[i] ); } return additionalRefs; } void TEST_SCH_REFERENCE_LIST_FIXTURE::checkAnnotation( std::vector aRefs ) { for( REANNOTATED_REFERENCE ref : aRefs ) { SCH_SHEET_PATH symbolPath; SCH_SYMBOL* symbol = getSymbolByKIID( ref.m_KIID, &symbolPath ); BOOST_CHECK_EQUAL( symbol->GetRef( &symbolPath, true ), ref.m_ExpectedRef ); } } BOOST_FIXTURE_TEST_SUITE( SchReferenceList, TEST_SCH_REFERENCE_LIST_FIXTURE ) struct REANNOTATION_CASE { std::string m_caseName; wxString m_SchematicRelativePath; int m_StartNumber; std::vector m_ExpectedReannotations; }; // Case 1: same value, same libref // Case 2: same value, different libref // Case 3: different value, same libref // Case 4: Not annotated unit to reannotate // Case 5: Duplicate references static const std::vector reannotationCases = { { "CASE 1. Rename only selected. All units selected", "test_multiunit_reannotate", 1, { { "cf058f25-2bad-4c49-a0c4-f059825c427f", "U99A", "U3A", true }, { "e6c8127f-e282-4128-8744-05f7893bc3ec", "U99B", "U3B", true }, { "db066797-b21c-4c1c-9591-8c7c549f8087", "U99C", "U3C", true }, } }, { "CASE 1. Rename only selected. Only unit B selected (A and C should NOT be reannotated)", "test_multiunit_reannotate", 1, { { "cf058f25-2bad-4c49-a0c4-f059825c427f", "U99A", "U99A", false }, { "e6c8127f-e282-4128-8744-05f7893bc3ec", "U99B", "U2B", true }, { "db066797-b21c-4c1c-9591-8c7c549f8087", "U99C", "U99C", false }, } }, { "CASE 1. Rename only selected. Only units B and C selected (A should NOT be reannotated)", "test_multiunit_reannotate", 1, { { "cf058f25-2bad-4c49-a0c4-f059825c427f", "U99A", "U99A", false }, { "e6c8127f-e282-4128-8744-05f7893bc3ec", "U99B", "U3B", true }, { "db066797-b21c-4c1c-9591-8c7c549f8087", "U99C", "U3C", true }, } }, { "CASE 2. Rename only selected. All units selected", "test_multiunit_reannotate_2", 1, { { "cf058f25-2bad-4c49-a0c4-f059825c427f", "U99A", "U3A", true }, { "e6c8127f-e282-4128-8744-05f7893bc3ec", "U99B", "U3B", true }, { "db066797-b21c-4c1c-9591-8c7c549f8087", "U99C", "U3C", true }, } }, { "CASE 2. Rename only selected. Only unit B selected (A and C should NOT be reannotated)", "test_multiunit_reannotate_2", 1, { { "cf058f25-2bad-4c49-a0c4-f059825c427f", "U99A", "U99A", false }, { "e6c8127f-e282-4128-8744-05f7893bc3ec", "U99B", "U3B", true }, { "db066797-b21c-4c1c-9591-8c7c549f8087", "U99C", "U99C", false }, } }, { "CASE 2. Rename only selected. Only units B and C selected (A should NOT be reannotated)", "test_multiunit_reannotate_2", 1, { { "cf058f25-2bad-4c49-a0c4-f059825c427f", "U99A", "U99A", false }, { "e6c8127f-e282-4128-8744-05f7893bc3ec", "U99B", "U3B", true }, { "db066797-b21c-4c1c-9591-8c7c549f8087", "U99C", "U3C", true }, } }, { "CASE 3. Rename only selected. All units selected", "test_multiunit_reannotate_3", 1, { { "cf058f25-2bad-4c49-a0c4-f059825c427f", "U99A", "U3A", true }, { "e6c8127f-e282-4128-8744-05f7893bc3ec", "U99B", "U3B", true }, { "db066797-b21c-4c1c-9591-8c7c549f8087", "U99C", "U3C", true }, } }, { "CASE 3. Rename only selected. Only unit B selected (A and C should NOT be reannotated)", "test_multiunit_reannotate_3", 1, { { "cf058f25-2bad-4c49-a0c4-f059825c427f", "U99A", "U99A", false }, { "e6c8127f-e282-4128-8744-05f7893bc3ec", "U99B", "U3B", true }, { "db066797-b21c-4c1c-9591-8c7c549f8087", "U99C", "U99C", false }, } }, { "CASE 3. Rename only selected. Only units B and C selected (A should NOT be reannotated)", "test_multiunit_reannotate_3", 1, { { "cf058f25-2bad-4c49-a0c4-f059825c427f", "U99A", "U99A", false }, { "e6c8127f-e282-4128-8744-05f7893bc3ec", "U99B", "U3B", true }, { "db066797-b21c-4c1c-9591-8c7c549f8087", "U99C", "U3C", true }, } }, { "CASE 4 - Not previously annotated (does not get added to multi-unit locked group)", "test_multiunit_reannotate_4", 1, { { "549455c3-ab6e-454e-94b0-5ca9e521ae0b", "U?B", "U2B", true }, } }, { "CASE 5 - Duplicate annotation. 1 selected", "test_multiunit_reannotate_5", 10, { { "d43a1d25-d37a-467a-8b09-10cf2e2ace09", "U2A", "U2A", false }, { "cd562bae-2426-44e6-8196-59eee5439809", "U2B", "U2B", false }, { "3f20a749-efe3-4804-8fef-435caaa8dacb", "U2C", "U2C", false }, { "cf058f25-2bad-4c49-a0c4-f059825c427f", "U2A", "U2A", false }, { "e6c8127f-e282-4128-8744-05f7893bc3ec", "U2B", "U11B", true }, { "db066797-b21c-4c1c-9591-8c7c549f8087", "U2C", "U2C", false }, } }, { "CASE 5 - Duplicate annotation. 2 selected", "test_multiunit_reannotate_5", 10, { { "d43a1d25-d37a-467a-8b09-10cf2e2ace09", "U2A", "U2A", false }, { "cd562bae-2426-44e6-8196-59eee5439809", "U2B", "U11B", true }, { "3f20a749-efe3-4804-8fef-435caaa8dacb", "U2C", "U2C", false }, { "cf058f25-2bad-4c49-a0c4-f059825c427f", "U2A", "U2A", false }, { "e6c8127f-e282-4128-8744-05f7893bc3ec", "U2B", "U12B", true }, { "db066797-b21c-4c1c-9591-8c7c549f8087", "U2C", "U2C", false }, } }, }; // @todo simplify or refactor this test case. // Currently it simulates part of SCH_EDIT_FRAME::AnnotateSymbols BOOST_AUTO_TEST_CASE( Reannotate ) { for( const REANNOTATION_CASE& c : reannotationCases ) { BOOST_TEST_INFO_SCOPE( c.m_caseName ); loadTestCase( c.m_SchematicRelativePath, c.m_ExpectedReannotations ); m_refsToReannotate.RemoveAnnotation(); m_refsToReannotate.SplitReferences(); m_refsToReannotate.Annotate( false, 0, c.m_StartNumber, m_lockedRefs, getAdditionalRefs() ); m_refsToReannotate.UpdateAnnotation(); checkAnnotation( c.m_ExpectedReannotations ); } } struct DUPLICATE_REANNOTATION_CASE { std::string m_caseName; wxString m_SchematicRelativePath; std::vector m_ExpectedReannotations; }; static const std::vector reannotateDuplicatesCases = { { "Reannotate Duplicates. Simple case", "test_multiunit_reannotate_5", { { "d43a1d25-d37a-467a-8b09-10cf2e2ace09", "U2A", "U2A", false }, { "cd562bae-2426-44e6-8196-59eee5439809", "U2B", "U2B", false }, { "3f20a749-efe3-4804-8fef-435caaa8dacb", "U2C", "U2C", false }, { "cf058f25-2bad-4c49-a0c4-f059825c427f", "U2A", "U3A", true }, { "e6c8127f-e282-4128-8744-05f7893bc3ec", "U2B", "U3B", true }, { "db066797-b21c-4c1c-9591-8c7c549f8087", "U2C", "U3C", true }, } }, }; BOOST_AUTO_TEST_CASE( ReannotateDuplicates ) { for( const DUPLICATE_REANNOTATION_CASE& c : reannotateDuplicatesCases ) { BOOST_TEST_INFO_SCOPE( c.m_caseName ); loadTestCase( c.m_SchematicRelativePath, c.m_ExpectedReannotations ); m_refsToReannotate.ReannotateDuplicates( getAdditionalRefs() ); m_refsToReannotate.UpdateAnnotation(); checkAnnotation( c.m_ExpectedReannotations ); } } BOOST_AUTO_TEST_SUITE_END()