25#include <boost/test/unit_test.hpp>
40#include <wx/filename.h>
41#include <wx/stdpaths.h>
50 wxString tempDir = wxStandardPaths::Get().GetTempDir();
51 wxString projectPath = tempDir + wxFileName::GetPathSeparator() + wxT(
"test_project.kicad_pro");
55 m_schematic = std::make_unique<SCHEMATIC>(
nullptr );
65 if( wxFileExists( file ) )
74 wxString tempDir = wxStandardPaths::Get().GetTempDir();
75 wxString fileName = wxFileName::CreateTempFileName( tempDir + wxFileName::GetPathSeparator() + aPrefix );
97 m_schematic->CreateDefaultScreens();
100 std::vector<SCH_SHEET*> topSheets = m_schematic->GetTopLevelSheets();
103 SCH_SCREEN* screen = topSheets[0]->GetScreen();
108 topSheets[0]->SetName(
"Main Sheet" );
112 BOOST_CHECK( !currentSheet.
empty() );
113 if( !currentSheet.
empty() )
115 BOOST_CHECK( currentSheet.
Last() != &m_schematic->Root() );
120 wxString fileName = GetTempFileName(
"test_schematic" );
121 fileName +=
".kicad_sch";
122 m_tempFiles.push_back( fileName );
125 BOOST_CHECK_NO_THROW( io.
SaveSchematicFile( fileName, topSheets[0], m_schematic.get() ) );
128 BOOST_CHECK( wxFileExists( fileName ) );
131 m_schematic->Reset();
132 SCH_SHEET* defaultSheet = m_schematic->GetTopLevelSheet( 0 );
134 BOOST_CHECK_NO_THROW( loadedSheet = io.
LoadSchematicFile( fileName, m_schematic.get() ) );
135 BOOST_CHECK( loadedSheet !=
nullptr );
140 m_schematic->AddTopLevelSheet( loadedSheet );
141 m_schematic->RemoveTopLevelSheet( defaultSheet );
145 BOOST_CHECK( m_schematic->IsValid() );
149 BOOST_CHECK( !currentSheet2.
empty() );
150 if( !currentSheet2.
empty() )
152 BOOST_CHECK( currentSheet2.
Last() != &m_schematic->Root() );
157 wxString fileName2 = GetTempFileName(
"test_schematic_resave" );
158 fileName2 +=
".kicad_sch";
159 m_tempFiles.push_back( fileName2 );
161 std::vector<SCH_SHEET*> topSheets2 = m_schematic->GetTopLevelSheets();
166 BOOST_CHECK_NO_THROW( io.
SaveSchematicFile( fileName2, topSheets2[0], m_schematic.get() ) );
169 BOOST_CHECK( wxFileExists( fileName2 ) );
180 m_schematic->CreateDefaultScreens();
182 std::vector<SCH_SHEET*> topSheets = m_schematic->GetTopLevelSheets();
185 SCH_SCREEN* screen = topSheets[0]->GetScreen();
190 subSheet->
SetName(
"SubSheet" );
195 screen->
Append( subSheet );
198 wxString mainFileName = GetTempFileName(
"test_main" );
199 mainFileName +=
".kicad_sch";
200 m_tempFiles.push_back( mainFileName );
203 wxString subFileName = GetTempFileName(
"test_sub" );
204 subFileName +=
".kicad_sch";
205 m_tempFiles.push_back( subFileName );
208 BOOST_CHECK_NO_THROW( io.
SaveSchematicFile( mainFileName, topSheets[0], m_schematic.get() ) );
209 BOOST_CHECK_NO_THROW( io.
SaveSchematicFile( subFileName, subSheet, m_schematic.get() ) );
212 m_schematic->Reset();
213 SCH_SHEET* defaultSheet = m_schematic->GetTopLevelSheet( 0 );
215 BOOST_CHECK_NO_THROW( loadedSheet = io.
LoadSchematicFile( mainFileName, m_schematic.get() ) );
216 BOOST_CHECK( loadedSheet !=
nullptr );
220 m_schematic->AddTopLevelSheet( loadedSheet );
221 m_schematic->RemoveTopLevelSheet( defaultSheet );
225 m_schematic->RefreshHierarchy();
232 wxString mainFileName2 = GetTempFileName(
"test_main_resave" );
233 mainFileName2 +=
".kicad_sch";
234 m_tempFiles.push_back( mainFileName2 );
236 std::vector<SCH_SHEET*> topSheets2 = m_schematic->GetTopLevelSheets();
240 BOOST_CHECK_NO_THROW( io.
SaveSchematicFile( mainFileName2, topSheets2[0], m_schematic.get() ) );
243 BOOST_CHECK( wxFileExists( mainFileName2 ) );
250 m_schematic->CreateDefaultScreens();
252 std::vector<SCH_SHEET*> topSheets = m_schematic->GetTopLevelSheets();
255 SCH_SCREEN* screen = topSheets[0]->GetScreen();
260 std::unique_ptr<SCH_SHAPE> polygon = std::make_unique<SCH_SHAPE>(
SHAPE_T::POLY );
273 screen->
Append( polygon.release() );
275 wxString fileName = GetTempFileName(
"test_polygon_reload" );
276 fileName +=
".kicad_sch";
277 m_tempFiles.push_back( fileName );
280 BOOST_CHECK_NO_THROW( io.
SaveSchematicFile( fileName, topSheets[0], m_schematic.get() ) );
281 BOOST_CHECK( wxFileExists( fileName ) );
283 m_schematic->Reset();
286 BOOST_CHECK_NO_THROW( loadedSheet = io.
LoadSchematicFile( fileName, m_schematic.get() ) );
297 loadedPolygon = shape;
305 BOOST_REQUIRE_EQUAL( outline.
PointCount(), 4 );
320 BOOST_REQUIRE_EQUAL( segments.size(), 3 );
326 for(
SHAPE* segment : segments )
340 fn.AppendDir(
"legacy_hierarchy" );
341 fn.SetName(
"legacy_hierarchy" );
343 wxString mainFile = fn.GetFullPath();
352 BOOST_CHECK_NO_THROW( loadedSheet = io.
LoadSchematicFile( mainFile, m_schematic.get() ) );
358 m_schematic->Reset();
359 SCH_SHEET* defaultSheet = m_schematic->GetTopLevelSheet( 0 );
360 m_schematic->AddTopLevelSheet( loadedSheet );
361 m_schematic->RemoveTopLevelSheet( defaultSheet );
365 m_schematic->RefreshHierarchy();
371 BOOST_REQUIRE_EQUAL( hierarchy.size(), 3 );
374 for(
size_t i = 0; i < hierarchy.size(); i++ )
377 BOOST_TEST_MESSAGE(
"\nSheet path [" + std::to_string(i) +
"]: " +
path.PathHumanReadable(
false ).ToStdString() );
383 BOOST_CHECK(
path.LastScreen() !=
nullptr );
385 if(
path.LastScreen() )
402 std::map<wxString, int> referenceCount;
403 int totalInstances = 0;
408 if( !
path.LastScreen() )
426 if( symbolInstance.
m_Path.empty() )
430 " has EMPTY instance path!" );
436 " -> " + symbolInstance.
m_Reference.ToStdString() +
437 " (path: " + symbolInstance.
m_Path.
AsString().ToStdString() +
")" );
443 " has NO instance for path " +
path.Path().AsString().ToStdString() );
451 BOOST_TEST_MESSAGE(
" Unique references: " + std::to_string( referenceCount.size() ) );
457 BOOST_CHECK( totalInstances > 0 );
461 for(
const auto& pair : referenceCount )
463 BOOST_TEST_MESSAGE(
" " + pair.first.ToStdString() +
": " + std::to_string( pair.second ) );
468 wxString saveFile = GetTempFileName(
"legacy_hierarchy_resave" );
470 m_tempFiles.push_back( saveFile );
472 std::vector<SCH_SHEET*> topSheets = m_schematic->GetTopLevelSheets();
476 BOOST_CHECK_NO_THROW( io.
SaveSchematicFile( saveFile, topSheets[0], m_schematic.get() ) );
477 BOOST_CHECK( wxFileExists( saveFile ) );
491 m_schematic->CreateDefaultScreens();
493 std::vector<SCH_SHEET*> topSheets = m_schematic->GetTopLevelSheets();
502 subSheet->
SetName(
"SubSheet" );
506 topScreen->
Append( subSheet );
508 m_schematic->RefreshHierarchy();
512 wxString wksPath = GetTempFileName(
"embed_wks" );
513 wksPath +=
".kicad_wks";
514 m_tempFiles.push_back( wksPath );
517 wxFFile wksFile( wksPath,
"wb" );
519 const wxString wksBody = wxT(
"(kicad_wks)" );
523 BOOST_REQUIRE( m_schematic->GetEmbeddedFiles()->AddFile( wxFileName( wksPath ),
false )
525 BOOST_REQUIRE( !m_schematic->GetEmbeddedFiles()->IsEmpty() );
527 wxString topFileName = GetTempFileName(
"embed_main" );
528 topFileName +=
".kicad_sch";
529 m_tempFiles.push_back( topFileName );
532 BOOST_CHECK_NO_THROW( io.
SaveSchematicFile( topFileName, topSheet, m_schematic.get() ) );
535 wxFFile readback( topFileName,
"rb" );
537 BOOST_REQUIRE( readback.IsOpened() && readback.ReadAll( &contents ) );
539 const wxString embeddedName = wxFileName( wksPath ).GetFullName();
541 BOOST_CHECK_MESSAGE( contents.Contains(
"embedded_files" ),
542 "Top-level sheet file is missing (embedded_files) block" );
543 BOOST_CHECK_MESSAGE( contents.Contains( embeddedName ),
544 "Top-level sheet file is missing the embedded worksheet entry" );
545 BOOST_CHECK_MESSAGE( contents.Contains(
"(type worksheet)" ),
546 "Top-level sheet file is missing (type worksheet) marker" );
556 m_schematic->CreateDefaultScreens();
558 std::vector<SCH_SHEET*> topSheets = m_schematic->GetTopLevelSheets();
561 SCH_SCREEN* screen = topSheets[0]->GetScreen();
564 m_project->GetTextVars()[wxT(
"SUBSHEET_FILE" )] = wxT(
"resolved_subsheet" );
568 subSheet->
SetName(
"SubSheet" );
570 subSheet->
SetFileName(
"${SUBSHEET_FILE}.kicad_sch" );
571 screen->
Append( subSheet );
574 wxString mainFileName = GetTempFileName(
"tv_main" );
575 mainFileName +=
".kicad_sch";
576 m_tempFiles.push_back( mainFileName );
578 wxFileName subOnDisk( mainFileName );
579 subOnDisk.SetFullName(
"resolved_subsheet.kicad_sch" );
580 wxString subFileName = subOnDisk.GetFullPath();
581 m_tempFiles.push_back( subFileName );
585 BOOST_REQUIRE_NO_THROW( io.
SaveSchematicFile( mainFileName, topSheets[0], m_schematic.get() ) );
586 BOOST_REQUIRE_NO_THROW( io.
SaveSchematicFile( subFileName, subSheet, m_schematic.get() ) );
588 m_schematic->Reset();
589 SCH_SHEET* defaultSheet = m_schematic->GetTopLevelSheet( 0 );
591 BOOST_REQUIRE_NO_THROW( loadedSheet = io.
LoadSchematicFile( mainFileName, m_schematic.get() ) );
594 m_schematic->AddTopLevelSheet( loadedSheet );
595 m_schematic->RemoveTopLevelSheet( defaultSheet );
597 m_schematic->RefreshHierarchy();
602 loadedSub =
static_cast<SCH_SHEET*
>( item );
612 "Sub-sheet screen filename still contains an unresolved text variable: "
616 BOOST_CHECK_EQUAL( loadedScreenFn.GetFullName(), wxString(
"resolved_subsheet.kicad_sch" ) );
constexpr EDA_IU_SCALE schIUScale
void SetFlags(EDA_ITEM_FLAGS aMask)
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
SHAPE_POLY_SET & GetPolyShape()
const std::vector< SEG > & GetHatchLines() const
EE_TYPE OfType(KICAD_T aType) const
wxString AsString() const
wxString AsString() const
Container for project specific data.
A SCH_IO derivation for loading schematic files using the new s-expression file format.
void SaveSchematicFile(const wxString &aFileName, SCH_SHEET *aSheet, SCHEMATIC *aSchematic, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Write aSchematic to a storage file in a format that this SCH_IO implementation knows about,...
SCH_SHEET * LoadSchematicFile(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load information from some input file format that this SCH_IO implementation knows about,...
Base class for any item which can be embedded within the SCHEMATIC container class,...
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
EE_RTREE & Items()
Get the full RTree, usually for iterating.
const wxString & GetFileName() const
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const override
Make a set of SHAPE objects representing the SCH_SHAPE.
void UpdateHatching() const override
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
void CheckForMissingSymbolInstances(const wxString &aProjectName)
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
bool empty() const
Forwarded method from std::vector.
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
void SetFileName(const wxString &aFilename)
wxString GetFileName() const
Return the filename corresponding to this sheet.
void SetName(const wxString &aName)
SCH_SCREEN * GetScreen() const
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
bool GetInstance(SCH_SYMBOL_INSTANCE &aInstance, const KIID_PATH &aSheetPath, bool aTestFromEnd=false) const
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
bool IsClosed() const override
int PointCount() const
Return the number of points (vertices) in this line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
const VECTOR2I & CLastPoint() const
Return the last point in the line chain.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
const SEG & GetSeg() const
An abstract shape on 2D plane.
Simple container to manage line stroke parameters.
#define IS_MOVING
Item being moved.
static const std::string KiCadSchematicFileExtension
std::string GetEeschemaTestDataDir()
Get the configured location of Eeschema test data.
std::vector< wxString > m_tempFiles
wxString GetTempFileName(const wxString &aPrefix)
SETTINGS_MANAGER m_settingsManager
std::unique_ptr< SCHEMATIC > m_schematic
A simple container for schematic symbol instance information.
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(TestSaveLoadSimpleSchematic)
Test that we can save and reload a schematic with the virtual root pattern and that symbol instances ...
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")
BOOST_CHECK_EQUAL(result, "25.4")
VECTOR2< int32_t > VECTOR2I