KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_project_file.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.TXT for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
28
33#include <wx/filename.h>
34
35#include <filesystem>
36#include <fstream>
37
38namespace fs = std::filesystem;
39
40
42{
43public:
45 {
46 m_tempDir = fs::temp_directory_path() / "kicad_project_file_test";
47 fs::remove_all( m_tempDir );
48 fs::create_directories( m_tempDir );
49 }
50
52 {
53 fs::remove_all( m_tempDir );
54 }
55
56 fs::path m_tempDir;
57};
58
59
60BOOST_FIXTURE_TEST_SUITE( ProjectFile, PROJECT_FILE_TEST_FIXTURE )
61
62
63
68BOOST_AUTO_TEST_CASE( SaveAsUpdatesTopLevelSheetNames )
69{
70 fs::path oldProjectDir = m_tempDir / "old_project";
71 fs::path newProjectDir = m_tempDir / "new_project";
72 fs::create_directories( oldProjectDir );
73 fs::create_directories( newProjectDir );
74
75 wxString oldProjectPath = wxString( oldProjectDir.string() ) + wxFileName::GetPathSeparator()
76 + wxS( "old_project." ) + FILEEXT::ProjectFileExtension;
77
78 PROJECT_FILE projectFile( oldProjectPath );
79
80 // Add a top-level sheet with name matching the project name
81 TOP_LEVEL_SHEET_INFO sheetInfo;
82 sheetInfo.uuid = KIID();
83 sheetInfo.name = wxS( "old_project" );
84 sheetInfo.filename = wxS( "old_project.kicad_sch" );
85
86 projectFile.GetTopLevelSheets().push_back( sheetInfo );
87
88 // Add another sheet with a custom name that should NOT be changed
89 TOP_LEVEL_SHEET_INFO customSheet;
90 customSheet.uuid = KIID();
91 customSheet.name = wxS( "CustomSheet" );
92 customSheet.filename = wxS( "custom_sheet.kicad_sch" );
93
94 projectFile.GetTopLevelSheets().push_back( customSheet );
95
96 // Perform SaveAs to new project
97 projectFile.SaveAs( wxString( newProjectDir.string() ), wxS( "new_project" ) );
98
99 // Verify the sheet name was updated
100 const std::vector<TOP_LEVEL_SHEET_INFO>& sheets = projectFile.GetTopLevelSheets();
101
102 BOOST_REQUIRE_EQUAL( sheets.size(), 2 );
103
104 // First sheet's name should be updated to match the new project name
105 BOOST_CHECK_EQUAL( sheets[0].name, wxS( "new_project" ) );
106
107 // First sheet's filename should also be updated
108 BOOST_CHECK_EQUAL( sheets[0].filename, wxS( "new_project.kicad_sch" ) );
109
110 // Second sheet's custom name should remain unchanged
111 BOOST_CHECK_EQUAL( sheets[1].name, wxS( "CustomSheet" ) );
112
113 // Second sheet's filename should remain unchanged
114 BOOST_CHECK_EQUAL( sheets[1].filename, wxS( "custom_sheet.kicad_sch" ) );
115}
116
117
127BOOST_AUTO_TEST_CASE( LoadFixesStaleTopLevelSheetReferences )
128{
129 fs::path projectDir = m_tempDir / "my_project";
130 fs::create_directories( projectDir );
131
132 // Write a .kicad_pro that references "default.kicad_sch" (as if copied from a template)
133 std::string proContent = R"({
134 "meta": {
135 "filename": "my_project.kicad_pro",
136 "version": 3
137 },
138 "schematic": {
139 "top_level_sheets": [
140 {
141 "uuid": "00000000-0000-0000-0000-000000000000",
142 "name": "default",
143 "filename": "default.kicad_sch"
144 }
145 ]
146 }
147 })";
148
149 fs::path proPath = projectDir / "my_project.kicad_pro";
150 std::ofstream proFile( proPath );
151 proFile << proContent;
152 proFile.close();
153
154 // Create the renamed schematic file (as if the template copy renamed it)
155 fs::path schPath = projectDir / "my_project.kicad_sch";
156 std::ofstream schFile( schPath );
157 schFile << "(kicad_sch (version 20231120) (generator \"eeschema\") (generator_version \"9.99\")";
158 schFile << " (uuid \"12345678-1234-1234-1234-123456789abc\")";
159 schFile << " (paper \"A4\"))";
160 schFile.close();
161
162 // Load the project using SETTINGS_MANAGER
163 SETTINGS_MANAGER settingsManager;
164 settingsManager.LoadProject( wxString( proPath.string() ) );
165
166 PROJECT& project = settingsManager.Prj();
167 PROJECT_FILE& projectFile = project.GetProjectFile();
168
169 const std::vector<TOP_LEVEL_SHEET_INFO>& sheets = projectFile.GetTopLevelSheets();
170
171 BOOST_REQUIRE_EQUAL( sheets.size(), 1 );
172
173 // The filename should have been corrected from "default.kicad_sch" to "my_project.kicad_sch"
174 BOOST_CHECK_EQUAL( sheets[0].filename, wxS( "my_project.kicad_sch" ) );
175
176 // The name should also be updated
177 BOOST_CHECK_EQUAL( sheets[0].name, wxS( "my_project" ) );
178}
179
180
184BOOST_AUTO_TEST_CASE( LoadPreservesValidTopLevelSheetReferences )
185{
186 fs::path projectDir = m_tempDir / "valid_project";
187 fs::create_directories( projectDir );
188
189 // Write a .kicad_pro with valid references
190 std::string proContent = R"({
191 "meta": {
192 "filename": "valid_project.kicad_pro",
193 "version": 3
194 },
195 "schematic": {
196 "top_level_sheets": [
197 {
198 "uuid": "00000000-0000-0000-0000-000000000000",
199 "name": "valid_project",
200 "filename": "valid_project.kicad_sch"
201 }
202 ]
203 }
204 })";
205
206 fs::path proPath = projectDir / "valid_project.kicad_pro";
207 std::ofstream proFile( proPath );
208 proFile << proContent;
209 proFile.close();
210
211 // Create the schematic file that matches the reference
212 fs::path schPath = projectDir / "valid_project.kicad_sch";
213 std::ofstream schFile( schPath );
214 schFile << "(kicad_sch (version 20231120) (generator \"eeschema\") (generator_version \"9.99\")";
215 schFile << " (uuid \"12345678-1234-1234-1234-123456789abc\")";
216 schFile << " (paper \"A4\"))";
217 schFile.close();
218
219 SETTINGS_MANAGER settingsManager;
220 settingsManager.LoadProject( wxString( proPath.string() ) );
221
222 PROJECT& project = settingsManager.Prj();
223 PROJECT_FILE& projectFile = project.GetProjectFile();
224
225 const std::vector<TOP_LEVEL_SHEET_INFO>& sheets = projectFile.GetTopLevelSheets();
226
227 BOOST_REQUIRE_EQUAL( sheets.size(), 1 );
228
229 // References should be unchanged
230 BOOST_CHECK_EQUAL( sheets[0].filename, wxS( "valid_project.kicad_sch" ) );
231 BOOST_CHECK_EQUAL( sheets[0].name, wxS( "valid_project" ) );
232}
233
234
248BOOST_AUTO_TEST_CASE( LoadProjectByAbsolutePathIsStable )
249{
250 fs::path projectDir = m_tempDir / "jobset_project";
251 fs::create_directories( projectDir );
252
253 std::string proContent = R"({
254 "meta": {
255 "filename": "jobset_project.kicad_pro",
256 "version": 3
257 }
258 })";
259
260 fs::path proPath = projectDir / "jobset_project.kicad_pro";
261 std::ofstream proFile( proPath );
262 proFile << proContent;
263 proFile.close();
264
265 wxFileName absFn( wxString( proPath.string() ) );
266 absFn.MakeAbsolute();
267 wxString absPath = absFn.GetFullPath();
268
269 SETTINGS_MANAGER settingsManager;
270
271 // Load as the fixed jobset runner does: by absolute path.
272 BOOST_REQUIRE( settingsManager.LoadProject( absPath ) );
273
274 PROJECT* heldProject = settingsManager.GetProject( absPath );
275 BOOST_REQUIRE( heldProject != nullptr );
276
277 // Simulate the kiface board loader resolving and (re)loading the project by its absolute path.
278 BOOST_REQUIRE( settingsManager.LoadProject( absPath, true ) );
279
280 // The second load must be a no-op for the held pointer; the project must not have been evicted.
281 PROJECT* afterReload = settingsManager.GetProject( absPath );
282 BOOST_CHECK( afterReload == heldProject );
283
284 // The held pointer must still resolve to the same project name (i.e. it was not freed).
285 BOOST_CHECK_EQUAL( heldProject->GetProjectFullName(), absPath );
286}
287
288
const char * name
Definition kiid.h:48
The backing store for a PROJECT, in JSON format.
bool SaveAs(const wxString &aDirectory, const wxString &aFile)
std::vector< TOP_LEVEL_SHEET_INFO > & GetTopLevelSheets()
Container for project specific data.
Definition project.h:66
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition project.cpp:181
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Load a project or sets up a new project with a specified path.
PROJECT * GetProject(const wxString &aFullPath) const
Retrieve a loaded project by name.
PROJECT & Prj() const
A helper while we are not MDI-capable – return the one and only project.
static const std::string ProjectFileExtension
Information about a top-level schematic sheet.
KIID uuid
Unique identifier for the sheet.
wxString name
Display name for the sheet.
wxString filename
Relative path to the sheet file.
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(SaveAsUpdatesTopLevelSheetNames)
Test that SaveAs updates top-level sheet names when they match the old project name.
BOOST_CHECK_EQUAL(result, "25.4")
Definition of file extensions used in Kicad.