mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 18:23:15 +02:00
This change completely removes the LIB_ALIAS design pattern an replaces it by allowing LIB_PART objects to inherit from other LIB_PART objects. The initial implementation only allows for single inheritance and only supports the mandatory fields in the derived part because that is all that the current symbol library file format will support. Once the new file format is implemented and saving to the old file format is deprecated, more complex inheritance will be added. The LIB_ALIAS information saved in the document files was move into the LIB_PART object. This change impacts virtually every part of the schematic and symbol library editor code so this commit message is woefully incomplete. REMOVE: Removed the symbol aliases concept from the schematic and symbol editors and the symbol viewer. NEW: Replace the symbol alias concept with simple inheritance that allows a library symbol to be derived from another library symbol.
405 lines
13 KiB
C++
405 lines
13 KiB
C++
/*
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
*
|
|
* Copyright (C) 2019 KiCad Developers, see CHANGELOG.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 2
|
|
* 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, you may find one here:
|
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
|
* or you may write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* Test suite for LIB_PART
|
|
*/
|
|
|
|
#include <unit_test_utils/unit_test_utils.h>
|
|
|
|
// Code under test
|
|
#include <class_libentry.h>
|
|
#include <lib_rectangle.h>
|
|
#include <lib_arc.h>
|
|
#include <lib_pin.h>
|
|
|
|
#include "lib_field_test_utils.h"
|
|
|
|
class TEST_LIB_PART_FIXTURE
|
|
{
|
|
public:
|
|
TEST_LIB_PART_FIXTURE() : m_part_no_data( "part_name", nullptr )
|
|
{
|
|
}
|
|
|
|
///> Part with no extra data set
|
|
LIB_PART m_part_no_data;
|
|
};
|
|
|
|
|
|
/**
|
|
* Declare the test suite
|
|
*/
|
|
BOOST_FIXTURE_TEST_SUITE( LibPart, TEST_LIB_PART_FIXTURE )
|
|
|
|
|
|
/**
|
|
* Check that we can get the basic properties out as expected
|
|
*/
|
|
BOOST_AUTO_TEST_CASE( DefaultProperties )
|
|
{
|
|
BOOST_CHECK_EQUAL( m_part_no_data.GetName(), "part_name" );
|
|
|
|
// Didn't set a library, so this is empty
|
|
BOOST_CHECK_EQUAL( m_part_no_data.GetLibraryName(), "" );
|
|
BOOST_CHECK_EQUAL( m_part_no_data.GetLib(), nullptr );
|
|
|
|
// only get the root
|
|
BOOST_CHECK_EQUAL( m_part_no_data.IsRoot(), true );
|
|
BOOST_CHECK_EQUAL( m_part_no_data.IsAlias(), false );
|
|
BOOST_CHECK_EQUAL( m_part_no_data.SharedPtr().use_count(), 2 );
|
|
|
|
// no sub units
|
|
BOOST_CHECK_EQUAL( m_part_no_data.GetUnitCount(), 1 );
|
|
BOOST_CHECK_EQUAL( m_part_no_data.IsMulti(), false );
|
|
|
|
// no conversion
|
|
BOOST_CHECK_EQUAL( m_part_no_data.HasConversion(), false );
|
|
}
|
|
|
|
|
|
/**
|
|
* Check the drawings on a "blank" LIB_PART
|
|
*/
|
|
BOOST_AUTO_TEST_CASE( DefaultDrawings )
|
|
{
|
|
// default drawings exist
|
|
BOOST_CHECK_EQUAL( m_part_no_data.GetDrawItems().size(), 4 );
|
|
BOOST_CHECK_EQUAL( m_part_no_data.GetNextDrawItem( NULL, LIB_PIN_T ), (LIB_ITEM*)NULL );
|
|
}
|
|
|
|
|
|
/**
|
|
* Check the default fields are present as expected
|
|
*/
|
|
BOOST_AUTO_TEST_CASE( DefaultFields )
|
|
{
|
|
LIB_FIELDS fields;
|
|
m_part_no_data.GetFields( fields );
|
|
|
|
// Should get the 4 default fields
|
|
BOOST_CHECK_PREDICATE( KI_TEST::AreDefaultFieldsCorrect, ( fields ) );
|
|
|
|
// but no more (we didn't set them)
|
|
BOOST_CHECK_EQUAL( fields.size(), NumFieldType::MANDATORY_FIELDS );
|
|
|
|
// also check the default field accessors
|
|
BOOST_CHECK_PREDICATE( KI_TEST::FieldNameIdMatches,
|
|
( m_part_no_data.GetReferenceField() )( "Reference" )( NumFieldType::REFERENCE ) );
|
|
BOOST_CHECK_PREDICATE( KI_TEST::FieldNameIdMatches,
|
|
( m_part_no_data.GetValueField() )( "Value" )( NumFieldType::VALUE ) );
|
|
BOOST_CHECK_PREDICATE( KI_TEST::FieldNameIdMatches,
|
|
( m_part_no_data.GetFootprintField() )( "Footprint" )( NumFieldType::FOOTPRINT ) );
|
|
}
|
|
|
|
|
|
/**
|
|
* Test adding fields to a LIB_PART
|
|
*/
|
|
BOOST_AUTO_TEST_CASE( AddedFields )
|
|
{
|
|
LIB_FIELDS fields;
|
|
m_part_no_data.GetFields( fields );
|
|
|
|
// Ctor takes non-const ref (?!)
|
|
const std::string newFieldName = "new_field";
|
|
wxString nonConstNewFieldName = newFieldName;
|
|
fields.push_back( LIB_FIELD( 42, nonConstNewFieldName ) );
|
|
|
|
// fairly roundabout way to add a field, but it is what it is
|
|
m_part_no_data.SetFields( fields );
|
|
|
|
// Should get the 4 default fields
|
|
BOOST_CHECK_PREDICATE( KI_TEST::AreDefaultFieldsCorrect, ( fields ) );
|
|
|
|
// and our new one
|
|
BOOST_REQUIRE_EQUAL( fields.size(), NumFieldType::MANDATORY_FIELDS + 1 );
|
|
|
|
BOOST_CHECK_PREDICATE( KI_TEST::FieldNameIdMatches,
|
|
( fields[NumFieldType::MANDATORY_FIELDS] )( newFieldName )( 42 ) );
|
|
|
|
// Check by-id lookup
|
|
|
|
LIB_FIELD* gotNewField = m_part_no_data.GetField( 42 );
|
|
|
|
BOOST_REQUIRE_NE( gotNewField, nullptr );
|
|
|
|
BOOST_CHECK_PREDICATE( KI_TEST::FieldNameIdMatches, ( *gotNewField )( newFieldName )( 42 ) );
|
|
|
|
// Check by-name lookup
|
|
|
|
gotNewField = m_part_no_data.FindField( newFieldName );
|
|
|
|
BOOST_REQUIRE_NE( gotNewField, nullptr );
|
|
BOOST_CHECK_PREDICATE( KI_TEST::FieldNameIdMatches, ( *gotNewField )( newFieldName )( 42 ) );
|
|
}
|
|
|
|
|
|
/**
|
|
* Test adding draw items to a LIB_PART
|
|
*/
|
|
BOOST_AUTO_TEST_CASE( AddedDrawItems )
|
|
{
|
|
}
|
|
|
|
|
|
struct TEST_LIB_PART_SUBREF_CASE
|
|
{
|
|
int m_index;
|
|
bool m_addSep;
|
|
std::string m_expSubRef;
|
|
};
|
|
|
|
|
|
/**
|
|
* Test the subreference indexing
|
|
*/
|
|
BOOST_AUTO_TEST_CASE( SubReference )
|
|
{
|
|
const std::vector<TEST_LIB_PART_SUBREF_CASE> cases = {
|
|
{
|
|
1,
|
|
false,
|
|
"A",
|
|
},
|
|
{
|
|
2,
|
|
false,
|
|
"B",
|
|
},
|
|
{
|
|
26,
|
|
false,
|
|
"Z",
|
|
},
|
|
{
|
|
27,
|
|
false,
|
|
"AA",
|
|
},
|
|
{ // haven't configured a separator, so should be nothing
|
|
1,
|
|
true,
|
|
"A",
|
|
},
|
|
};
|
|
|
|
for( const auto& c : cases )
|
|
{
|
|
BOOST_TEST_CONTEXT(
|
|
"Subref: " << c.m_index << ", " << c.m_addSep << " -> '" << c.m_expSubRef << "'" )
|
|
{
|
|
const auto subref = m_part_no_data.SubReference( c.m_index, c.m_addSep );
|
|
BOOST_CHECK_EQUAL( subref, c.m_expSubRef );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Check the compare method.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE( Compare )
|
|
{
|
|
// Identical root part to m_part_no_data sans time stamp.
|
|
LIB_PART testPart( "part_name" );
|
|
|
|
// Self comparison test.
|
|
BOOST_CHECK_EQUAL( m_part_no_data.Compare( m_part_no_data ), 0 );
|
|
|
|
// Test for identical LIB_PART.
|
|
BOOST_CHECK_EQUAL( m_part_no_data.Compare( testPart ), 0 );
|
|
|
|
// Test name.
|
|
testPart.SetName( "tart_name" );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) < 0 );
|
|
testPart.SetName( "cart_name" );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) > 0 );
|
|
testPart.SetName( "part_name" );
|
|
|
|
// LIB_ID comparison tests.
|
|
LIB_ID id = testPart.GetLibId();
|
|
id.SetLibItemName( "tart_name" );
|
|
testPart.SetLibId( id );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) < 0 );
|
|
id.SetLibItemName( "cart_name" );
|
|
testPart.SetLibId( id );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) > 0 );
|
|
id.SetLibItemName( "part_name" );
|
|
testPart.SetLibId( id );
|
|
|
|
// Unit count comparison tests.
|
|
testPart.SetUnitCount( 2 );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) < 0 );
|
|
testPart.SetUnitCount( 1 );
|
|
m_part_no_data.SetUnitCount( 2 );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) > 0 );
|
|
m_part_no_data.SetUnitCount( 1 );
|
|
|
|
// Options flag comparison tests.
|
|
testPart.SetPower();
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) < 0 );
|
|
testPart.SetNormal();
|
|
m_part_no_data.SetPower();
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) > 0 );
|
|
m_part_no_data.SetNormal();
|
|
|
|
// Draw item list size comparison tests.
|
|
testPart.AddDrawItem( new LIB_RECTANGLE( &testPart ) );
|
|
m_part_no_data.AddDrawItem( new LIB_RECTANGLE( &m_part_no_data ) );
|
|
BOOST_CHECK_EQUAL( m_part_no_data.Compare( testPart ), 0 );
|
|
m_part_no_data.RemoveDrawItem( m_part_no_data.GetNextDrawItem( nullptr, LIB_RECTANGLE_T ) );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) < 0 );
|
|
testPart.RemoveDrawItem( testPart.GetNextDrawItem( nullptr, LIB_RECTANGLE_T ) );
|
|
m_part_no_data.AddDrawItem( new LIB_RECTANGLE( &m_part_no_data ) );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) > 0 );
|
|
m_part_no_data.RemoveDrawItem( m_part_no_data.GetNextDrawItem( nullptr, LIB_RECTANGLE_T ) );
|
|
|
|
// Draw item list contents comparison tests.
|
|
testPart.AddDrawItem( new LIB_RECTANGLE( &testPart ) );
|
|
m_part_no_data.AddDrawItem( new LIB_ARC( &m_part_no_data ) );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) < 0 );
|
|
m_part_no_data.RemoveDrawItem( m_part_no_data.GetNextDrawItem( nullptr, LIB_ARC_T ) );
|
|
m_part_no_data.AddDrawItem( new LIB_PIN( &m_part_no_data ) );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) > 0 );
|
|
m_part_no_data.RemoveDrawItem( m_part_no_data.GetNextDrawItem( nullptr, LIB_PIN_T ) );
|
|
testPart.RemoveDrawItem( testPart.GetNextDrawItem( nullptr, LIB_RECTANGLE_T ) );
|
|
|
|
// Footprint filter array comparison tests.
|
|
wxArrayString footPrintFilters;
|
|
BOOST_CHECK( m_part_no_data.GetFootprints() == footPrintFilters );
|
|
footPrintFilters.Add( "b" );
|
|
testPart.SetFootprintFilters( footPrintFilters );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) < 0 );
|
|
m_part_no_data.SetFootprintFilters( footPrintFilters );
|
|
footPrintFilters.Clear();
|
|
testPart.SetFootprintFilters( footPrintFilters );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) > 0 );
|
|
footPrintFilters.Clear();
|
|
m_part_no_data.SetFootprintFilters( footPrintFilters );
|
|
testPart.SetFootprintFilters( footPrintFilters );
|
|
|
|
// Description string tests.
|
|
m_part_no_data.SetDescription( "b" );
|
|
testPart.SetDescription( "b" );
|
|
BOOST_CHECK_EQUAL( m_part_no_data.Compare( testPart ), 0 );
|
|
m_part_no_data.SetDescription( "a" );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) < 0 );
|
|
m_part_no_data.SetDescription( "c" );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) > 0 );
|
|
m_part_no_data.SetDescription( wxEmptyString );
|
|
testPart.SetDescription( wxEmptyString );
|
|
|
|
// Key word string tests.
|
|
m_part_no_data.SetKeyWords( "b" );
|
|
testPart.SetKeyWords( "b" );
|
|
BOOST_CHECK_EQUAL( m_part_no_data.Compare( testPart ), 0 );
|
|
m_part_no_data.SetKeyWords( "a" );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) < 0 );
|
|
m_part_no_data.SetKeyWords( "c" );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) > 0 );
|
|
m_part_no_data.SetKeyWords( wxEmptyString );
|
|
testPart.SetKeyWords( wxEmptyString );
|
|
|
|
// Documentation file string tests.
|
|
m_part_no_data.SetDocFileName( "b" );
|
|
testPart.SetDocFileName( "b" );
|
|
BOOST_CHECK_EQUAL( m_part_no_data.Compare( testPart ), 0 );
|
|
m_part_no_data.SetDocFileName( "a" );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) < 0 );
|
|
m_part_no_data.SetDocFileName( "c" );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) > 0 );
|
|
m_part_no_data.SetDocFileName( wxEmptyString );
|
|
testPart.SetDocFileName( wxEmptyString );
|
|
|
|
// Pin name offset comparison tests.
|
|
testPart.SetPinNameOffset( testPart.GetPinNameOffset() + 1 );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) < 0 );
|
|
testPart.SetPinNameOffset( testPart.GetPinNameOffset() - 2 );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) > 0 );
|
|
testPart.SetPinNameOffset( testPart.GetPinNameOffset() + 1 );
|
|
|
|
// Units locked flag comparision tests.
|
|
testPart.LockUnits( true );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) < 0 );
|
|
testPart.LockUnits( false );
|
|
m_part_no_data.LockUnits( true );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) > 0 );
|
|
m_part_no_data.LockUnits( false );
|
|
|
|
// Show pin names flag comparison tests.
|
|
m_part_no_data.SetShowPinNames( false );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) < 0 );
|
|
m_part_no_data.SetShowPinNames( true );
|
|
testPart.SetShowPinNames( false );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) > 0 );
|
|
testPart.SetShowPinNames( true );
|
|
|
|
// Show pin numbers flag comparison tests.
|
|
m_part_no_data.SetShowPinNumbers( false );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) < 0 );
|
|
m_part_no_data.SetShowPinNumbers( true );
|
|
testPart.SetShowPinNumbers( false );
|
|
BOOST_CHECK( m_part_no_data.Compare( testPart ) > 0 );
|
|
testPart.SetShowPinNumbers( true );
|
|
|
|
// Time stamp comparison tests.
|
|
}
|
|
|
|
|
|
/**
|
|
* Check inheritance support.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE( Inheritance )
|
|
{
|
|
std::unique_ptr< LIB_PART > parent( new LIB_PART( "parent" ) );
|
|
BOOST_CHECK( parent->IsRoot() );
|
|
std::unique_ptr< LIB_PART > child1( new LIB_PART( "child1", parent.get() ) );
|
|
BOOST_CHECK( child1->IsAlias() );
|
|
PART_SPTR parentRef = child1->GetParent().lock();
|
|
BOOST_CHECK( parentRef );
|
|
BOOST_CHECK( parentRef == parent->SharedPtr() );
|
|
BOOST_CHECK_EQUAL( parent->SharedPtr().use_count(), 3 );
|
|
BOOST_CHECK_EQUAL( child1->GetUnitCount(), 1 );
|
|
parent->SetUnitCount( 4 );
|
|
BOOST_CHECK_EQUAL( child1->GetUnitCount(), 4 );
|
|
child1->SetParent();
|
|
BOOST_CHECK_EQUAL( child1->GetUnitCount(), 1 );
|
|
parentRef.reset();
|
|
BOOST_CHECK_EQUAL( parent->SharedPtr().use_count(), 2 );
|
|
}
|
|
|
|
|
|
/**
|
|
* Check the copy constructor.
|
|
*/
|
|
BOOST_AUTO_TEST_CASE( CopyConstructor )
|
|
{
|
|
std::shared_ptr< LIB_PART > copy( new LIB_PART( m_part_no_data ) );
|
|
BOOST_CHECK( m_part_no_data == *copy.get() );
|
|
}
|
|
|
|
|
|
BOOST_AUTO_TEST_SUITE_END()
|