KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_issue24403_directive_label_i18n.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 modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * 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, see <https://www.gnu.org/licenses/>.
18 */
19
33
34#include <boost/test/unit_test.hpp>
36#include <eeschema_test_utils.h>
37
38#include <wx/ffile.h>
39#include <wx/filename.h>
40#include <wx/stdpaths.h>
41
42#include <sch_field.h>
44#include <sch_label.h>
45#include <sch_screen.h>
46#include <sch_sheet.h>
47#include <schematic.h>
49
50
52{
55 {
56 wxString tempDir = wxStandardPaths::Get().GetTempDir();
57 wxString projectPath =
58 tempDir + wxFileName::GetPathSeparator() + wxT( "issue24403_project.kicad_pro" );
59 m_tempFiles.push_back( projectPath );
60
61 m_settingsManager.LoadProject( projectPath.ToStdString() );
62 m_schematic = std::make_unique<SCHEMATIC>( nullptr );
63 m_schematic->SetProject( &m_settingsManager.Prj() );
64 }
65
67 {
68 for( const wxString& file : m_tempFiles )
69 {
70 if( wxFileExists( file ) )
71 wxRemoveFile( file );
72 }
73
74 m_schematic.reset();
75 }
76
77 wxString MakeTempSchematicPath( const wxString& aPrefix )
78 {
79 // wxFileName::CreateTempFileName() creates (and tracks) the file it returns. Track both
80 // the base file and the .kicad_sch path we hand out so cleanup removes everything.
81 wxString tempDir = wxStandardPaths::Get().GetTempDir();
82 wxString baseName = wxFileName::CreateTempFileName(
83 tempDir + wxFileName::GetPathSeparator() + aPrefix );
84 m_tempFiles.push_back( baseName );
85
86 wxString fileName = baseName + wxT( ".kicad_sch" );
87 m_tempFiles.push_back( fileName );
88 return fileName;
89 }
90
91 SCH_DIRECTIVE_LABEL* AddDirectiveLabel( const wxString& aFieldName,
92 const wxString& aNetClassName )
93 {
94 std::vector<SCH_SHEET*> topSheets = m_schematic->GetTopLevelSheets();
95 BOOST_REQUIRE( !topSheets.empty() );
96
97 SCH_SCREEN* screen = topSheets[0]->GetScreen();
98 BOOST_REQUIRE( screen );
99
100 SCH_DIRECTIVE_LABEL* label = new SCH_DIRECTIVE_LABEL( VECTOR2I( 0, 0 ) );
101 label->GetFields().emplace_back( label, FIELD_T::USER, aFieldName );
102 label->GetFields().back().SetText( aNetClassName );
103
104 screen->Append( label );
105 return label;
106 }
107
109 std::unique_ptr<SCHEMATIC> m_schematic;
110 std::vector<wxString> m_tempFiles;
111};
112
113
114BOOST_FIXTURE_TEST_SUITE( Issue24403DirectiveLabelI18n, DIRECTIVE_LABEL_I18N_FIXTURE )
115
116
117
122BOOST_AUTO_TEST_CASE( CanonicalNetclassEmittedForTranslatedFieldName )
123{
124 m_schematic->CreateDefaultScreens();
125
126 // Simulate a directive label whose field name carries a translated form, mirroring the
127 // state produced by a German UI under the buggy 10.0.x code path.
128 AddDirectiveLabel( wxT( "Netzklasse" ), wxT( "HighSpeed" ) );
129
130 std::vector<SCH_SHEET*> topSheets = m_schematic->GetTopLevelSheets();
132 wxString outFile = MakeTempSchematicPath( "issue24403_de" );
133
134 BOOST_REQUIRE_NO_THROW( io.SaveSchematicFile( outFile, topSheets[0], m_schematic.get() ) );
135
136 wxFFile read( outFile, "rb" );
137 wxString contents;
138 BOOST_REQUIRE( read.IsOpened() && read.ReadAll( &contents ) );
139
140 BOOST_CHECK_MESSAGE( contents.Contains( wxT( "\"Netclass\"" ) ),
141 "Saved schematic must contain canonical \"Netclass\" token" );
142 BOOST_CHECK_MESSAGE( !contents.Contains( wxT( "\"Netzklasse\"" ) ),
143 "Saved schematic must not contain translated \"Netzklasse\" token" );
144 BOOST_CHECK_MESSAGE( contents.Contains( wxT( "HighSpeed" ) ),
145 "Saved schematic must preserve the net class value" );
146}
147
148
154BOOST_AUTO_TEST_CASE( TranslatedFieldNameRoundTripsAsCanonical )
155{
156 m_schematic->CreateDefaultScreens();
157
158 // A file written by a German UI, kept verbatim in qa/data so it still carries the
159 // pre-migration "Netzklasse" field name. Never re-save it from KiCad; the loader
160 // migrates the token and the fixture loses its purpose.
161 wxString legacyFile = wxString::FromUTF8( KI_TEST::GetEeschemaTestDataDir() )
162 + wxS( "issue24403_legacy_de.kicad_sch" );
163
165 SCH_SHEET* loaded = nullptr;
166 BOOST_REQUIRE_NO_THROW( loaded = io.LoadSchematicFile( legacyFile, m_schematic.get() ) );
167 BOOST_REQUIRE( loaded );
168
169 // Mount the loaded sheet so we can re-serialise through the standard SaveSchematicFile path.
170 SCH_SHEET* defaultSheet = m_schematic->GetTopLevelSheet( 0 );
171 m_schematic->AddTopLevelSheet( loaded );
172 m_schematic->RemoveTopLevelSheet( defaultSheet );
173 delete defaultSheet;
174
175 SCH_SCREEN* screen = loaded->GetScreen();
176 BOOST_REQUIRE( screen );
177
178 int directiveCount = 0;
179 int netclassFieldCount = 0;
180
181 for( SCH_ITEM* item : screen->Items().OfType( SCH_DIRECTIVE_LABEL_T ) )
182 {
183 directiveCount++;
184
185 SCH_DIRECTIVE_LABEL* directive = static_cast<SCH_DIRECTIVE_LABEL*>( item );
186
187 for( const SCH_FIELD& field : directive->GetFields() )
188 {
189 if( field.GetCanonicalName() == wxT( "Netclass" ) )
190 {
191 netclassFieldCount++;
192 BOOST_CHECK_EQUAL( field.GetText().ToStdString(), std::string( "HighSpeed" ) );
193 }
194 }
195 }
196
197 BOOST_CHECK_EQUAL( directiveCount, 1 );
198 BOOST_CHECK_EQUAL( netclassFieldCount, 1 );
199
200 // After re-saving, the file must converge on the canonical token regardless of the form it
201 // was loaded with.
202 wxString resaved = MakeTempSchematicPath( "issue24403_legacy_de_resave" );
203 std::vector<SCH_SHEET*> topSheets = m_schematic->GetTopLevelSheets();
204 BOOST_REQUIRE( !topSheets.empty() );
205
206 BOOST_REQUIRE_NO_THROW( io.SaveSchematicFile( resaved, topSheets[0], m_schematic.get() ) );
207
208 wxFFile resavedFile( resaved, "rb" );
209 wxString resavedContents;
210 BOOST_REQUIRE( resavedFile.IsOpened() && resavedFile.ReadAll( &resavedContents ) );
211
212 BOOST_CHECK_MESSAGE( resavedContents.Contains( wxT( "\"Netclass\"" ) ),
213 "Re-saved schematic must use canonical \"Netclass\" token" );
214 BOOST_CHECK_MESSAGE( !resavedContents.Contains( wxT( "\"Netzklasse\"" ) ),
215 "Re-saved schematic must drop the translated form" );
216}
217
218
224BOOST_AUTO_TEST_CASE( IsNetclassLabelFieldNameRecognisesTranslations )
225{
226 BOOST_CHECK( SCH_FIELD::IsNetclassLabelFieldName( wxT( "Netclass" ) ) );
227 BOOST_CHECK( SCH_FIELD::IsNetclassLabelFieldName( wxT( "Net Class" ) ) );
228 BOOST_CHECK( SCH_FIELD::IsNetclassLabelFieldName( wxString::FromUTF8( "Netzklasse" ) ) );
229 BOOST_CHECK( SCH_FIELD::IsNetclassLabelFieldName( wxString::FromUTF8( "Classe de xarxa" ) ) );
230 BOOST_CHECK( SCH_FIELD::IsNetclassLabelFieldName( wxString::FromUTF8( "Classe d'Equipot" ) ) );
231 BOOST_CHECK( SCH_FIELD::IsNetclassLabelFieldName( wxString::FromUTF8( "Clase de red" ) ) );
232 BOOST_CHECK( SCH_FIELD::IsNetclassLabelFieldName( wxString::FromUTF8( "网络类" ) ) );
233
234 BOOST_CHECK( !SCH_FIELD::IsNetclassLabelFieldName( wxT( "Component Class" ) ) );
235 BOOST_CHECK( !SCH_FIELD::IsNetclassLabelFieldName( wxT( "Reference" ) ) );
236 BOOST_CHECK( !SCH_FIELD::IsNetclassLabelFieldName( wxEmptyString ) );
237}
238
239
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:221
static bool IsNetclassLabelFieldName(const wxString &aName)
Test whether aName is one of the known translations of the directive-label net class field name (used...
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,...
Definition sch_item.h:162
std::vector< SCH_FIELD > & GetFields()
Definition sch_label.h:210
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:115
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:44
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:139
std::string GetEeschemaTestDataDir()
Get the configured location of Eeschema test data.
SCH_DIRECTIVE_LABEL * AddDirectiveLabel(const wxString &aFieldName, const wxString &aNetClassName)
wxString MakeTempSchematicPath(const wxString &aPrefix)
@ USER
The field ID hasn't been set yet; field is invalid.
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(CanonicalNetclassEmittedForTranslatedFieldName)
The serializer must always emit the canonical "Netclass" token for the directive-label net class fiel...
BOOST_CHECK_EQUAL(result, "25.4")
@ SCH_DIRECTIVE_LABEL_T
Definition typeinfo.h:168
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683