KiCad PCB EDA Suite
group_saveload.cpp File Reference
#include <bitset>
#include <string>
#include <boost/filesystem.hpp>
#include <board.h>
#include <footprint.h>
#include <pcb_group.h>
#include <pcb_text.h>
#include <common.h>
#include <pcbnew_utils/board_construction_utils.h>
#include <pcbnew_utils/board_file_utils.h>
#include <qa_utils/wx_utils/unit_test_utils.h>

Go to the source code of this file.

Enumerations

enum  ItemType {
  TEXT0 , TEXT1 , TEXT2 , TEXT3 ,
  TEXT4 , TEXT5 , TEXT6 , TEXT7 ,
  TEXT8 , REMOVED_TEXT , GROUP0 , GROUP1 ,
  GROUP2 , NAME_GROUP3 , NAME_GROUP4 , NAME_GROUP3_DUP ,
  REMOVED_GROUP , NUM_ITEMS
}
 

Functions

std::unique_ptr< BOARDcreateBoard (const std::vector< std::vector< ItemType > > &spec)
 
void testGroupEqual (const PCB_GROUP &group1, const PCB_GROUP &group2)
 
void testGroupsEqual (const GROUPS &groups1, const GROUPS &groups2)
 
void testSaveLoad (const std::vector< std::vector< ItemType > > &spec)
 
 BOOST_AUTO_TEST_CASE (HealthyGroups)
 
 BOOST_AUTO_TEST_CASE (InvalidGroups)
 

Variables

static PCB_TEXTs_removedText = nullptr
 
static PCB_GROUPs_removedGroup = nullptr
 

Enumeration Type Documentation

◆ ItemType

enum ItemType
Enumerator
TEXT0 
TEXT1 
TEXT2 
TEXT3 
TEXT4 
TEXT5 
TEXT6 
TEXT7 
TEXT8 
REMOVED_TEXT 
GROUP0 
GROUP1 
GROUP2 
NAME_GROUP3 
NAME_GROUP4 
NAME_GROUP3_DUP 
REMOVED_GROUP 
NUM_ITEMS 

Definition at line 42 of file group_saveload.cpp.

43{
44 TEXT0,
45 TEXT1,
46 TEXT2,
47 TEXT3,
48 TEXT4,
49 TEXT5,
50 TEXT6,
51 TEXT7,
52 TEXT8,
53 REMOVED_TEXT, // Text not added to board
54 GROUP0,
55 GROUP1,
56 GROUP2,
59 NAME_GROUP3_DUP, // Group with name identical to NAME_GROUP3
60 REMOVED_GROUP, // Group not added to board
62};
@ REMOVED_TEXT
@ TEXT5
@ TEXT8
@ TEXT0
@ NAME_GROUP3_DUP
@ TEXT3
@ TEXT4
@ GROUP1
@ REMOVED_GROUP
@ NAME_GROUP4
@ TEXT6
@ NAME_GROUP3
@ TEXT1
@ TEXT2
@ NUM_ITEMS
@ GROUP2
@ GROUP0
@ TEXT7

Function Documentation

◆ BOOST_AUTO_TEST_CASE() [1/2]

BOOST_AUTO_TEST_CASE ( HealthyGroups  )

Definition at line 224 of file group_saveload.cpp.

225{
226 // Test board with no groups
227 testSaveLoad( {} );
228
229 // Single group
230 testSaveLoad( { { TEXT0 } } );
231 testSaveLoad( { { TEXT0, TEXT1 } } );
232
233 // Two groups
234 testSaveLoad( { { TEXT0, TEXT1 }, { TEXT2, TEXT3 } } );
235 testSaveLoad( { { TEXT0, TEXT1 }, { TEXT2, GROUP0 } } );
236
237 // Subgroups by no cycle
238 testSaveLoad( { { TEXT0, GROUP1 }, { TEXT2 }, { TEXT3, GROUP0 } } );
239 testSaveLoad( { { TEXT0 }, { TEXT2 }, { GROUP1, GROUP0 } } );
240 testSaveLoad( { { TEXT0 }, { TEXT1 }, { TEXT2, NAME_GROUP3 }, { TEXT3 } } );
241 testSaveLoad( { { TEXT0 }, { TEXT1 }, { TEXT2, NAME_GROUP3 }, { TEXT3, GROUP0 } } );
242 testSaveLoad( { { TEXT0 }, { TEXT1 }, { TEXT2 }, { TEXT3 }, { NAME_GROUP3, GROUP0 } } );
243}
void testSaveLoad(const std::vector< std::vector< ItemType > > &spec)

References GROUP0, GROUP1, NAME_GROUP3, testSaveLoad(), TEXT0, TEXT1, TEXT2, and TEXT3.

◆ BOOST_AUTO_TEST_CASE() [2/2]

BOOST_AUTO_TEST_CASE ( InvalidGroups  )

Definition at line 246 of file group_saveload.cpp.

247{
248 // A cycle
249 std::unique_ptr<BOARD> board1 = createBoard( { { TEXT0, GROUP1 }, { TEXT2, GROUP0 } } );
250 BOOST_CHECK_EQUAL( board1->GroupsSanityCheck(), "Cycle detected in group membership" );
251
252 // More complex cycle
253 board1 = createBoard( { { TEXT0, GROUP1 }, { TEXT1 }, { TEXT2, NAME_GROUP4 },
254 { TEXT3, GROUP2 }, { TEXT4, NAME_GROUP3 } } );
255 BOOST_CHECK_EQUAL( board1->GroupsSanityCheck(), "Cycle detected in group membership" );
256
257 // Delete the removed group since the test is over
258 board1.reset( nullptr );
259 delete s_removedGroup;
260 s_removedGroup = nullptr;
261
262 // Delete the removed text since the test is over
263 board1.reset( nullptr );
264 delete s_removedText;
265 s_removedText = nullptr;
266}
std::unique_ptr< BOARD > createBoard(const std::vector< std::vector< ItemType > > &spec)
static PCB_GROUP * s_removedGroup
static PCB_TEXT * s_removedText

References createBoard(), GROUP0, GROUP1, GROUP2, NAME_GROUP3, NAME_GROUP4, s_removedGroup, s_removedText, TEXT0, TEXT1, TEXT2, TEXT3, and TEXT4.

◆ createBoard()

std::unique_ptr< BOARD > createBoard ( const std::vector< std::vector< ItemType > > &  spec)

Definition at line 76 of file group_saveload.cpp.

77{
78 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
79 std::vector<BOARD_ITEM*> items;
80
81 // Create text items and add to board.
82 for( int idx = 0; idx <= REMOVED_TEXT; idx++ )
83 {
84 PCB_TEXT* textItem = new PCB_TEXT( board.get() );
85 textItem->SetText( wxString::Format( _( "some text-%d" ), idx ) );
86
87 // Don't add REMOVED_TEXT to the board
88 if( idx < REMOVED_TEXT )
89 board->Add( textItem );
90
91 items.push_back( textItem );
92 }
93
94 // Create groups
95 for( int idx = 0; idx < ( NUM_ITEMS - GROUP0 ); idx++ )
96 {
97 PCB_GROUP* gr = new PCB_GROUP( board.get() );
98
99 if( idx >= ( NAME_GROUP3 - GROUP0 ) )
100 {
101 wxString name = wxString::Format( _( "group-%d" ),
102 ( idx == ( NAME_GROUP3_DUP - GROUP0 ) ) ? 3 : idx );
103 gr->SetName( name );
104 BOOST_CHECK_EQUAL( gr->GetName(), name );
105 }
106
107 items.push_back( gr );
108 }
109
110 std::bitset<NUM_ITEMS> used;
111
112 // Populate groups based on spec
113 for( int offset = 0; offset < ( NUM_ITEMS - GROUP0 ); offset++ )
114 {
115 int groupIdx = GROUP0 + offset;
116
117 PCB_GROUP* group = static_cast<PCB_GROUP*>( items[groupIdx] );
118
119 if( offset < spec.size() )
120 {
121 const std::vector<ItemType>& groupSpec = spec[offset];
122
123 for( ItemType item : groupSpec )
124 {
125 used.set( static_cast<size_t>( item ) );
126 group->AddItem( items[item] );
127 }
128
129 BOOST_CHECK_EQUAL( group->GetItems().size(), groupSpec.size() );
130 board->Add( group );
131 }
132 else if( groupIdx != REMOVED_GROUP && used.test( groupIdx ) )
133 {
134 // This group is used in another group, so it must be on the board
135 board->Add( group );
136 }
137 else if( groupIdx != REMOVED_GROUP )
138 {
139 // If the group isn't used, delete it
140 delete group;
141 }
142 }
143
144 // Delete the removed text item if it isn't used
145 if( used.test( REMOVED_TEXT ) )
146 s_removedText = static_cast<PCB_TEXT*>( items[REMOVED_TEXT] );
147 else
148 delete items[REMOVED_TEXT];
149
150 // Delete the removed group item if it isn't used
151 if( used.test( REMOVED_GROUP ) )
152 s_removedGroup = static_cast<PCB_GROUP*>( items[REMOVED_GROUP] );
153 else
154 delete items[REMOVED_GROUP];
155
156 BOOST_TEST_CHECKPOINT( "Returning fresh board" );
157 return board;
158}
const char * name
Definition: DXF_plotter.cpp:56
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:163
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:51
void SetName(const wxString &aName)
Definition: pcb_group.h:66
wxString GetName() const
Definition: pcb_group.h:65
#define _(s)
ItemType
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200

References _, Format(), PCB_GROUP::GetName(), group, GROUP0, name, NAME_GROUP3, NAME_GROUP3_DUP, NUM_ITEMS, REMOVED_GROUP, REMOVED_TEXT, s_removedGroup, s_removedText, PCB_GROUP::SetName(), and EDA_TEXT::SetText().

Referenced by BOOST_AUTO_TEST_CASE(), and testSaveLoad().

◆ testGroupEqual()

void testGroupEqual ( const PCB_GROUP group1,
const PCB_GROUP group2 
)

Definition at line 162 of file group_saveload.cpp.

163{
164 BOOST_CHECK_EQUAL( group1.m_Uuid.AsString(), group2.m_Uuid.AsString() );
165 BOOST_CHECK_EQUAL( group1.GetName(), group2.GetName() );
166
167 const std::unordered_set<BOARD_ITEM*>& items1 = group1.GetItems();
168 const std::unordered_set<BOARD_ITEM*>& items2 = group2.GetItems();
169
170 BOOST_CHECK_EQUAL( items1.size(), items2.size() );
171
172 // Test that the sets items1 and items2 are identical, by checking m_Uuid
173 for( BOARD_ITEM* item1 : items1 )
174 {
175 auto cmp = [&]( BOARD_ITEM* elem )
176 {
177 return elem->m_Uuid.AsString() == item1->m_Uuid.AsString();
178 };
179
180 auto item2 = std::find_if( items2.begin(), items2.end(), cmp );
181
182 BOOST_CHECK( item2 != items2.end() );
183 }
184}
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:58
const KIID m_Uuid
Definition: eda_item.h:494
wxString AsString() const
Definition: kiid.cpp:251
std::unordered_set< BOARD_ITEM * > & GetItems()
Definition: pcb_group.h:68
BOOST_CHECK(box.ClosestPointTo(VECTOR2D(0, 0))==VECTOR2D(1, 2))
Test suite for KiCad math code.

References KIID::AsString(), BOOST_CHECK(), PCB_GROUP::GetItems(), PCB_GROUP::GetName(), and EDA_ITEM::m_Uuid.

Referenced by testGroupsEqual().

◆ testGroupsEqual()

void testGroupsEqual ( const GROUPS &  groups1,
const GROUPS &  groups2 
)

Definition at line 188 of file group_saveload.cpp.

189{
190 BOOST_CHECK_EQUAL( groups1.size(), groups2.size() );
191
192 for( PCB_GROUP* group1 : groups1 )
193 {
194 auto cmp = [&]( BOARD_ITEM* elem )
195 {
196 return elem->m_Uuid.AsString() == group1->m_Uuid.AsString();
197 };
198
199 auto group2 = std::find_if( groups2.begin(), groups2.end(), cmp );
200
201 BOOST_CHECK( group2 != groups2.end() );
202
203 testGroupEqual( *group1, **group2 );
204 }
205}
void testGroupEqual(const PCB_GROUP &group1, const PCB_GROUP &group2)

References BOOST_CHECK(), and testGroupEqual().

Referenced by testSaveLoad().

◆ testSaveLoad()

void testSaveLoad ( const std::vector< std::vector< ItemType > > &  spec)

Definition at line 212 of file group_saveload.cpp.

213{
214 std::unique_ptr<BOARD> board1 = createBoard( spec );
215 auto path = boost::filesystem::temp_directory_path() / "group_saveload_tst.kicad_pcb";
216 ::KI_TEST::DumpBoardToFile( *board1, path.string() );
217
218 std::unique_ptr<BOARD> board2 = ::KI_TEST::ReadBoardFromFileOrStream( path.string() );
219 testGroupsEqual( board1->Groups(), board2->Groups() );
220}
void testGroupsEqual(const GROUPS &groups1, const GROUPS &groups2)
std::unique_ptr< BOARD > ReadBoardFromFileOrStream(const std::string &aFilename, std::istream &aFallback)
Read a board from a file, or another stream, as appropriate.
void DumpBoardToFile(BOARD &board, const std::string &aFilename)
Utility function to simply write a Board out to a file.

References createBoard(), KI_TEST::DumpBoardToFile(), path, KI_TEST::ReadBoardFromFileOrStream(), and testGroupsEqual().

Referenced by BOOST_AUTO_TEST_CASE().

Variable Documentation

◆ s_removedGroup

PCB_GROUP* s_removedGroup = nullptr
static

Definition at line 68 of file group_saveload.cpp.

Referenced by BOOST_AUTO_TEST_CASE(), and createBoard().

◆ s_removedText

PCB_TEXT* s_removedText = nullptr
static

Definition at line 67 of file group_saveload.cpp.

Referenced by BOOST_AUTO_TEST_CASE(), and createBoard().