From 5783623c501de92d4ad846038798ef1a3defaf5a Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh <stambaughw@gmail.com> Date: Sun, 16 Mar 2025 12:39:06 -0400 Subject: [PATCH] Add code to test if schematic file belongs to another project. --- eeschema/sch_screen.cpp | 42 +++++++++ eeschema/sch_screen.h | 21 ++++- qa/tests/eeschema/CMakeLists.txt | 3 +- qa/tests/eeschema/test_sch_screen.cpp | 123 ++++++++++++++++++++++++++ 4 files changed, 187 insertions(+), 2 deletions(-) create mode 100644 qa/tests/eeschema/test_sch_screen.cpp diff --git a/eeschema/sch_screen.cpp b/eeschema/sch_screen.cpp index c1fda63329..be777478e1 100644 --- a/eeschema/sch_screen.cpp +++ b/eeschema/sch_screen.cpp @@ -1594,6 +1594,48 @@ std::set<wxString> SCH_SCREEN::GetSheetNames() const } +bool SCH_SCREEN::HasInstanceDataFromOtherProjects() const +{ + wxCHECK( Schematic(), false ); + + SCH_SHEET_LIST hierarchy = Schematic()->Hierarchy(); + + for( const SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) ) + { + const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( item ); + + const std::vector<SCH_SYMBOL_INSTANCE> symbolInstances = symbol->GetInstances(); + + for( const SCH_SYMBOL_INSTANCE& instance : symbolInstances ) + { + if( !hierarchy.HasPath( instance.m_Path ) ) + return true; + } + } + + return false; +} + + +bool SCH_SCREEN::InProjectPath() const +{ + wxCHECK( Schematic() && !m_fileName.IsEmpty(), false ); + + wxFileName thisScreenFn( m_fileName ); + wxFileName thisProjectFn( Schematic()->Prj().GetProjectFullName() ); + + wxCHECK( thisProjectFn.IsAbsolute(), false ); + + if( thisScreenFn.GetDirCount() < thisProjectFn.GetDirCount() ) + return false; + + while( thisProjectFn.GetDirCount() != thisScreenFn.GetDirCount() ) + thisScreenFn.RemoveLastDir(); + + return thisScreenFn.GetPath() == thisProjectFn.GetPath(); +} + + #if defined(DEBUG) void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const { diff --git a/eeschema/sch_screen.h b/eeschema/sch_screen.h index 9281d868fb..ec14f778a0 100644 --- a/eeschema/sch_screen.h +++ b/eeschema/sch_screen.h @@ -65,6 +65,7 @@ class SCH_EDIT_FRAME; class SCH_SHEET_LIST; class SCH_IO_KICAD_SEXPR_PARSER; class SCH_IO_KICAD_SEXPR; +class TEST_SCH_SCREEN_FIXTURE; enum SCH_LINE_TEST_T { @@ -548,6 +549,14 @@ public: bool HasSymbolFieldNamesWithWhiteSpace() const; + /** + * Check if the schematic file is in the current project path. + * + * @retval true if the schematic file resides in the current project path or a sub-folder. + * @retval false if the schematic file does not reside within the current project path. + */ + bool InProjectPath() const; + #if defined(DEBUG) void Show( int nestLevel, std::ostream& os ) const override; #endif @@ -592,11 +601,22 @@ public: */ std::set<wxString> GetSheetNames() const; + /** + * Check symbols for instance data from other projects. + * + * @retval true if the schematic contains symbols and/or sheets with instances from a + * project other than the current project. + * @retval false if the schematic does not contain symbols and/or sheets with instances + * from a project other than the current project. + */ + bool HasInstanceDataFromOtherProjects() const; + private: friend SCH_EDIT_FRAME; // Only to populate m_symbolInstances. friend SCH_IO_KICAD_SEXPR_PARSER; // Only to load instance information from schematic file. friend SCH_IO_KICAD_SEXPR; // Only to save the loaded instance information to schematic file. friend SCH_IO_ALTIUM; + friend TEST_SCH_SCREEN_FIXTURE; bool doIsJunction( const VECTOR2I& aPosition, bool aBreakCrossings, bool* aHasExplicitJunctionDot, bool* aHasBusEntry ) const; @@ -618,7 +638,6 @@ private: */ size_t getLibSymbolNameMatches( const SCH_SYMBOL& aSymbol, std::vector<wxString>& aMatches ); - /** * Compare two #BUS_ALIAS objects by name. For sorting in the set. */ diff --git a/qa/tests/eeschema/CMakeLists.txt b/qa/tests/eeschema/CMakeLists.txt index fa4c3e145a..4128fd680f 100644 --- a/qa/tests/eeschema/CMakeLists.txt +++ b/qa/tests/eeschema/CMakeLists.txt @@ -76,6 +76,7 @@ set( QA_EESCHEMA_SRCS test_sch_pin.cpp test_sch_rtree.cpp test_sch_reference_list.cpp + test_sch_screen.cpp test_sch_sheet.cpp test_sch_sheet_path.cpp test_sch_sheet_list.cpp @@ -125,4 +126,4 @@ target_compile_definitions( qa_eeschema kicad_add_boost_test( qa_eeschema qa_eeschema ) -setup_qa_env( qa_eeschema ) \ No newline at end of file +setup_qa_env( qa_eeschema ) diff --git a/qa/tests/eeschema/test_sch_screen.cpp b/qa/tests/eeschema/test_sch_screen.cpp new file mode 100644 index 0000000000..087e26a05f --- /dev/null +++ b/qa/tests/eeschema/test_sch_screen.cpp @@ -0,0 +1,123 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright The 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 <http://www.gnu.org/licenses/>. + */ + +/** + * @file + * Test suite for SCH_SCREEN + */ + +#include <qa_utils/wx_utils/unit_test_utils.h> +#include "eeschema_test_utils.h" + +#include <schematic.h> +#include <wildcards_and_files_ext.h> + +// Code under test +#include <sch_screen.h> + +#include <qa_utils/uuid_test_utils.h> +#include <qa_utils/wx_utils/wx_assert.h> + +class TEST_SCH_SCREEN_FIXTURE : public KI_TEST::SCHEMATIC_TEST_FIXTURE +{ +protected: + wxFileName GetSchematicPath( const wxString& aRelativePath ) override; +}; + + +wxFileName TEST_SCH_SCREEN_FIXTURE::GetSchematicPath( const wxString& aRelativePath ) +{ + wxFileName fn( KI_TEST::GetEeschemaTestDataDir() ); + + wxString path = fn.GetFullPath(); + path += aRelativePath + wxT( "." ) + FILEEXT::KiCadSchematicFileExtension; + + return wxFileName( path ); +} + + +/** + * Declare the test suite + */ +BOOST_FIXTURE_TEST_SUITE( SchScreen, TEST_SCH_SCREEN_FIXTURE ) + + +/** + * Test SCH_SCREEN::InProjectPath(). + */ +BOOST_AUTO_TEST_CASE( TestInProjectPath ) +{ + LoadSchematic( "schematic_object_tests/not_shared_by_multiple_projects/" + "not_shared_by_multiple_projects" ); + + SCH_SCREEN testScreen( &m_schematic ); + wxFileName testFn( m_schematic.RootScreen()->GetFileName() ); + + // File is in same folder as project. + testFn.SetName( "test" ); + testScreen.SetFileName( testFn.GetFullPath() ); + BOOST_CHECK( testScreen.InProjectPath() ); + + // File is in a sub-folder inside project. + testFn.AppendDir( "sch" ); + testScreen.SetFileName( testFn.GetFullPath() ); + BOOST_CHECK( testScreen.InProjectPath() ); + + // File is one folder below poject folder. + testFn.RemoveLastDir(); + testFn.RemoveLastDir(); + testScreen.SetFileName( testFn.GetFullPath() ); + BOOST_CHECK( !testScreen.InProjectPath() ); + + // File is in a completely different path with the same folder depth. + testFn.SetPath( "/home/foo/kicad" ); + + wxFileName projectFn( m_schematic.Prj().GetProjectFullName() ); + + // Just in case someone has a build path with no subfolders. + BOOST_CHECK( testFn.GetDirCount() < projectFn.GetDirCount() ); + + int subDirCount = 1; + + while( projectFn.GetDirCount() != testFn.GetDirCount() ) + { + testFn.AppendDir( wxString::Format( wxS( "subdir%d" ), subDirCount ) ); + subDirCount += 1; + } + + testScreen.SetFileName( testFn.GetFullPath() ); + BOOST_CHECK( !testScreen.InProjectPath() ); +} + + +/** + * Test SCH_SCREEN::HasInstanceDataFromOtherProjects(). + */ +BOOST_AUTO_TEST_CASE( TestSharedByMultipleProjects ) +{ + LoadSchematic( "schematic_object_tests/not_shared_by_multiple_projects/" + "not_shared_by_multiple_projects" ); + + const SCH_SCREEN* rootScreen = m_schematic.RootScreen(); + BOOST_CHECK( !rootScreen->HasInstanceDataFromOtherProjects() ); + BOOST_CHECK( rootScreen->InProjectPath() ); +} + + +BOOST_AUTO_TEST_SUITE_END()