29#include <wx/filename.h>
37namespace fs = std::filesystem;
46 m_tempDir = fs::temp_directory_path() /
"kicad_project_file_test";
67 fs::path projectPath = m_tempDir /
"api_kitchen_sink.kicad_pro";
76 project.m_IP2581Bom.sections = wxString();
96 fs::path oldProjectDir = m_tempDir /
"old_project";
97 fs::path newProjectDir = m_tempDir /
"new_project";
98 fs::create_directories( oldProjectDir );
99 fs::create_directories( newProjectDir );
101 wxString oldProjectPath = wxString( oldProjectDir.string() ) + wxFileName::GetPathSeparator()
109 sheetInfo.
name = wxS(
"old_project" );
110 sheetInfo.
filename = wxS(
"old_project.kicad_sch" );
117 customSheet.
name = wxS(
"CustomSheet" );
118 customSheet.
filename = wxS(
"custom_sheet.kicad_sch" );
123 projectFile.
SaveAs( wxString( newProjectDir.string() ), wxS(
"new_project" ) );
126 const std::vector<TOP_LEVEL_SHEET_INFO>& sheets = projectFile.
GetTopLevelSheets();
128 BOOST_REQUIRE_EQUAL( sheets.size(), 2 );
155 fs::path projectDir = m_tempDir /
"my_project";
156 fs::create_directories( projectDir );
159 std::string proContent = R
"({
161 "filename": "my_project.kicad_pro",
165 "top_level_sheets": [
167 "uuid": "00000000-0000-0000-0000-000000000000",
169 "filename": "default.kicad_sch"
175 fs::path proPath = projectDir / "my_project.kicad_pro";
176 std::ofstream proFile( proPath );
177 proFile << proContent;
181 fs::path schPath = projectDir /
"my_project.kicad_sch";
182 std::ofstream schFile( schPath );
183 schFile <<
"(kicad_sch (version 20231120) (generator \"eeschema\") (generator_version \"9.99\")";
184 schFile <<
" (uuid \"12345678-1234-1234-1234-123456789abc\")";
185 schFile <<
" (paper \"A4\"))";
190 settingsManager.
LoadProject( wxString( proPath.string() ) );
195 const std::vector<TOP_LEVEL_SHEET_INFO>& sheets = projectFile.
GetTopLevelSheets();
197 BOOST_REQUIRE_EQUAL( sheets.size(), 1 );
212 fs::path projectDir = m_tempDir /
"valid_project";
213 fs::create_directories( projectDir );
216 std::string proContent = R
"({
218 "filename": "valid_project.kicad_pro",
222 "top_level_sheets": [
224 "uuid": "00000000-0000-0000-0000-000000000000",
225 "name": "valid_project",
226 "filename": "valid_project.kicad_sch"
232 fs::path proPath = projectDir / "valid_project.kicad_pro";
233 std::ofstream proFile( proPath );
234 proFile << proContent;
238 fs::path schPath = projectDir /
"valid_project.kicad_sch";
239 std::ofstream schFile( schPath );
240 schFile <<
"(kicad_sch (version 20231120) (generator \"eeschema\") (generator_version \"9.99\")";
241 schFile <<
" (uuid \"12345678-1234-1234-1234-123456789abc\")";
242 schFile <<
" (paper \"A4\"))";
246 settingsManager.
LoadProject( wxString( proPath.string() ) );
251 const std::vector<TOP_LEVEL_SHEET_INFO>& sheets = projectFile.
GetTopLevelSheets();
253 BOOST_REQUIRE_EQUAL( sheets.size(), 1 );
276 fs::path projectDir = m_tempDir /
"jobset_project";
277 fs::create_directories( projectDir );
279 std::string proContent = R
"({
281 "filename": "jobset_project.kicad_pro",
286 fs::path proPath = projectDir / "jobset_project.kicad_pro";
287 std::ofstream proFile( proPath );
288 proFile << proContent;
291 wxFileName absFn( wxString( proPath.string() ) );
292 absFn.MakeAbsolute();
293 wxString absPath = absFn.GetFullPath();
308 BOOST_CHECK( afterReload == heldProject );
326 fs::path projADir = m_tempDir /
"proj_a";
327 fs::path projBDir = m_tempDir /
"proj_b";
328 fs::create_directories( projADir );
329 fs::create_directories( projBDir );
334 const std::string projectName =
"shared_name";
336 auto writeProject = [&](
const fs::path& aDir )
338 std::string content =
"{\n"
340 " \"filename\": \"" + projectName +
".kicad_pro\",\n"
343 " \"schematic\": {\n"
344 " \"top_level_sheets\": [\n"
346 " \"uuid\": \"00000000-0000-0000-0000-000000000000\",\n"
347 " \"name\": \"" + projectName +
"\",\n"
348 " \"filename\": \"" + projectName +
".kicad_sch\"\n"
353 std::ofstream out( aDir / ( projectName +
".kicad_pro" ) );
357 std::ofstream sch( aDir / ( projectName +
".kicad_sch" ) );
358 sch <<
"(kicad_sch (version 20231120) (generator \"eeschema\") (generator_version \"9.99\")";
359 sch <<
" (uuid \"12345678-1234-1234-1234-123456789abc\") (paper \"A4\"))";
363 fs::path proAPath = projADir / ( projectName +
".kicad_pro" );
364 fs::path proBPath = projBDir / ( projectName +
".kicad_pro" );
365 writeProject( projADir );
366 writeProject( projBDir );
385 auto readFile = [](
const fs::path& aPath )
387 std::ifstream in( aPath );
388 std::stringstream buffer;
389 buffer << in.rdbuf();
394 std::string savedB =
readFile( proBPath );
395 BOOST_CHECK_MESSAGE( savedB.find(
"OWNER" ) != std::string::npos,
396 "unloaded project must be saved to its own directory" );
399 std::string savedA =
readFile( proAPath );
400 BOOST_CHECK_MESSAGE( savedA.find(
"OWNER" ) == std::string::npos,
401 "active project's file must not receive the unloaded project's data" );
408 auto projectPath = [&](
const std::string& aName )
410 fs::path dir = m_tempDir / aName;
411 fs::create_directories( dir );
412 return wxString( ( dir / ( aName +
".kicad_pro" ) ).
string() );
415 const wxString active = projectPath(
"z_active" );
416 const wxString passive = projectPath(
"a_passive" );
417 const wxString
next = projectPath(
"m_next" );
426 BOOST_CHECK( mgr.
GetProject( active ) ==
nullptr );
427 BOOST_CHECK( mgr.
GetProject( passive ) !=
nullptr );
443 fs::path projectDir = m_tempDir /
"unchanged_project";
444 fs::create_directories( projectDir );
446 fs::path proPath = projectDir /
"unchanged_project.kicad_pro";
451 std::ofstream seed( proPath );
452 seed << R
"({"meta":{"version":3}})";
461 auto readFile = [](
const fs::path& aPath )
463 std::ifstream in( aPath );
464 std::stringstream buffer;
465 buffer << in.rdbuf();
472 nlohmann::json js = nlohmann::json::parse(
readFile( proPath ) );
473 js[
"board"].erase(
"ipc2581" );
474 js[
"schematic"].erase(
"bus_aliases" );
476 std::ofstream out( proPath );
477 out << std::setw( 2 ) << js << std::endl;
481 std::string before =
readFile( proPath );
482 BOOST_REQUIRE( before.find(
"ipc2581" ) == std::string::npos );
483 BOOST_REQUIRE( before.find(
"bus_aliases" ) == std::string::npos );
491 BOOST_CHECK( !projectFile.
SaveToFile( wxString( projectDir.string() ) ) );
503 nlohmann::json saved = nlohmann::json::parse(
readFile( proPath ) );
504 BOOST_CHECK( saved[
"schematic"][
"bus_aliases"].is_object() );
505 BOOST_CHECK( saved[
"schematic"][
"bus_aliases"].
empty() );
511 const fs::path projectPath = m_tempDir /
"aliases.kicad_pro";
512 const nlohmann::json aliases = { {
"USB", {
"D+",
"D-" } } };
515 std::ofstream output( projectPath );
516 output << nlohmann::json( { {
"meta", { {
"version", 3 } } },
517 {
"schematic", { {
"bus_aliases", aliases } } } } ).
dump( 2 );
526 BOOST_REQUIRE_EQUAL(
project.m_BusAliases.size(), 1 );
527 BOOST_CHECK(
project.m_BusAliases.at(
"USB" ) == std::vector<wxString>( {
"D+",
"D-" } ) );
529 std::ifstream input( projectPath );
530 const nlohmann::json saved = nlohmann::json::parse( input );
532 BOOST_CHECK( saved[
"schematic"][
"bus_aliases"] == aliases );
538 const fs::path legacyPath = m_tempDir /
"field_names.pro";
539 const fs::path projectPath = m_tempDir /
"field_names.kicad_pro";
542 std::ofstream output( legacyPath );
543 output <<
"[schematic_editor]\n"
544 "FieldNameTemplates=(templatefields (field (name \"Manufacturer\") visible url))\n";
550 const auto& fields =
project.m_TemplateFieldNames.GetTemplateFieldNames( TEMPLATES::SCOPE::PROJECT );
551 BOOST_REQUIRE_EQUAL( fields.size(), 1 );
553 BOOST_CHECK( fields[0].m_Visible );
554 BOOST_CHECK( fields[0].m_URL );
556 const nlohmann::json saved = nlohmann::json::parse(
project.FormatAsString() );
557 const auto& fieldNames = saved[
"schematic"][
"drawing"][
"field_names"];
559 BOOST_REQUIRE_EQUAL( fieldNames.size(), 1 );
566 const fs::path projectPath = m_tempDir /
"field_names.kicad_pro";
567 nlohmann::json projectJson = { {
"meta", { {
"version", 4 } } } };
568 projectJson[
"schematic"][
"drawing"][
"field_names"] =
569 nlohmann::json::array( { { {
"name",
"Manufacturer" }, {
"visible",
true }, {
"url",
false } } } );
571 auto writeProject = [&]()
573 std::ofstream output( projectPath );
574 output << projectJson.dump( 2 );
581 BOOST_REQUIRE_EQUAL(
project.m_TemplateFieldNames.GetTemplateFieldNames( TEMPLATES::SCOPE::PROJECT ).size(), 1 );
583 projectJson[
"schematic"][
"drawing"][
"field_names"] = nlohmann::json::array();
587 BOOST_CHECK(
project.m_TemplateFieldNames.GetTemplateFieldNames( TEMPLATES::SCOPE::PROJECT ).empty() );
std::optional< nlohmann::json > GetJson(const std::string &aPath) const
Fetches a JSON object that is a subset of this JSON_SETTINGS object, using a path of the form "key1....
~PROJECT_FILE_TEST_FIXTURE()
PROJECT_FILE_TEST_FIXTURE()
The backing store for a PROJECT, in JSON format.
std::map< wxString, wxString > m_TextVars
bool m_BusAliasesDefined
An explicit alias table was loaded or set, including a deliberately empty table.
struct IP2581_BOM m_IP2581Bom
Layer pair list for the board.
bool SaveAs(const wxString &aDirectory, const wxString &aFile)
std::vector< TOP_LEVEL_SHEET_INFO > & GetTopLevelSheets()
bool SaveToFile(const wxString &aDirectory="", bool aForce=false) override
Calls Store() and then writes the contents of the JSON document to a file.
Container for project specific data.
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
virtual PROJECT_FILE & GetProjectFile() const
bool SaveProject(const wxString &aFullPath=wxEmptyString, PROJECT *aProject=nullptr)
Save a loaded project.
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.
bool UnloadProject(PROJECT *aProject, bool aSave=true)
Save, unload and unregister the given PROJECT.
PROJECT & Prj() const
A helper while we are not MDI-capable – return the one and only project.
static bool empty(const wxTextEntryBase *aCtrl)
static const std::string ProjectFileExtension
std::string GetTestDataRootDir()
static bool readFile(const wxString &aFileName, wxString &aOut, size_t aLimit=0)
Read a file into aOut.
std::optional< wxString > sections
Table 4 section key, unset when the mode picks the sections.
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(Ipc2581ExplicitEmptySectionsRoundTrips)
BOOST_CHECK_EQUAL(result, "25.4")
wxString dump(const wxArrayString &aArray)
Debug helper for printing wxArrayString contents.
Definition of file extensions used in Kicad.