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 along
17 * with this program. If not, see <http://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 // First write a synthetic file containing the legacy translated form so we exercise the
159 // loader's migration path directly.
160 wxString legacyFile = MakeTempSchematicPath( "issue24403_legacy_de" );
161
162 {
163 wxFFile out( legacyFile, "wb" );
164 BOOST_REQUIRE( out.IsOpened() );
165
166 const wxString body = wxT(
167 "(kicad_sch (version 20260512) (generator \"qa_test\") (generator_version \"9.99\")\n"
168 " (paper \"A4\")\n"
169 " (lib_symbols)\n"
170 " (directive_label \"\" (length 2.54) (shape round)\n"
171 " (at 0 0 0)\n"
172 " (effects (font (size 1.27 1.27)) (justify left bottom))\n"
173 " (uuid \"00000000-0000-0000-0000-000000024403\")\n"
174 " (property \"Netzklasse\" \"HighSpeed\" (at 0 -1 0)\n"
175 " (effects (font (size 1.27 1.27)) (justify left bottom))\n"
176 " )\n"
177 " )\n"
178 " (sheet_instances (path \"/\" (page \"1\")))\n"
179 ")\n" );
180
181 BOOST_REQUIRE( out.Write( body ) );
182 }
183
185 SCH_SHEET* loaded = nullptr;
186 BOOST_REQUIRE_NO_THROW( loaded = io.LoadSchematicFile( legacyFile, m_schematic.get() ) );
187 BOOST_REQUIRE( loaded );
188
189 // Mount the loaded sheet so we can re-serialise through the standard SaveSchematicFile path.
190 SCH_SHEET* defaultSheet = m_schematic->GetTopLevelSheet( 0 );
191 m_schematic->AddTopLevelSheet( loaded );
192 m_schematic->RemoveTopLevelSheet( defaultSheet );
193 delete defaultSheet;
194
195 SCH_SCREEN* screen = loaded->GetScreen();
196 BOOST_REQUIRE( screen );
197
198 int directiveCount = 0;
199 int netclassFieldCount = 0;
200
201 for( SCH_ITEM* item : screen->Items().OfType( SCH_DIRECTIVE_LABEL_T ) )
202 {
203 directiveCount++;
204
205 SCH_DIRECTIVE_LABEL* directive = static_cast<SCH_DIRECTIVE_LABEL*>( item );
206
207 for( const SCH_FIELD& field : directive->GetFields() )
208 {
209 if( field.GetCanonicalName() == wxT( "Netclass" ) )
210 {
211 netclassFieldCount++;
212 BOOST_CHECK_EQUAL( field.GetText().ToStdString(), std::string( "HighSpeed" ) );
213 }
214 }
215 }
216
217 BOOST_CHECK_EQUAL( directiveCount, 1 );
218 BOOST_CHECK_EQUAL( netclassFieldCount, 1 );
219
220 // After re-saving, the file must converge on the canonical token regardless of the form it
221 // was loaded with.
222 wxString resaved = MakeTempSchematicPath( "issue24403_legacy_de_resave" );
223 std::vector<SCH_SHEET*> topSheets = m_schematic->GetTopLevelSheets();
224 BOOST_REQUIRE( !topSheets.empty() );
225
226 BOOST_REQUIRE_NO_THROW( io.SaveSchematicFile( resaved, topSheets[0], m_schematic.get() ) );
227
228 wxFFile resavedFile( resaved, "rb" );
229 wxString resavedContents;
230 BOOST_REQUIRE( resavedFile.IsOpened() && resavedFile.ReadAll( &resavedContents ) );
231
232 BOOST_CHECK_MESSAGE( resavedContents.Contains( wxT( "\"Netclass\"" ) ),
233 "Re-saved schematic must use canonical \"Netclass\" token" );
234 BOOST_CHECK_MESSAGE( !resavedContents.Contains( wxT( "\"Netzklasse\"" ) ),
235 "Re-saved schematic must drop the translated form" );
236}
237
238
244BOOST_AUTO_TEST_CASE( IsNetclassLabelFieldNameRecognisesTranslations )
245{
246 BOOST_CHECK( SCH_FIELD::IsNetclassLabelFieldName( wxT( "Netclass" ) ) );
247 BOOST_CHECK( SCH_FIELD::IsNetclassLabelFieldName( wxT( "Net Class" ) ) );
248 BOOST_CHECK( SCH_FIELD::IsNetclassLabelFieldName( wxString::FromUTF8( "Netzklasse" ) ) );
249 BOOST_CHECK( SCH_FIELD::IsNetclassLabelFieldName( wxString::FromUTF8( "Classe de xarxa" ) ) );
250 BOOST_CHECK( SCH_FIELD::IsNetclassLabelFieldName( wxString::FromUTF8( "Classe d'Equipot" ) ) );
251 BOOST_CHECK( SCH_FIELD::IsNetclassLabelFieldName( wxString::FromUTF8( "Clase de red" ) ) );
252 BOOST_CHECK( SCH_FIELD::IsNetclassLabelFieldName( wxString::FromUTF8( "网络类" ) ) );
253
254 BOOST_CHECK( !SCH_FIELD::IsNetclassLabelFieldName( wxT( "Component Class" ) ) );
255 BOOST_CHECK( !SCH_FIELD::IsNetclassLabelFieldName( wxT( "Reference" ) ) );
256 BOOST_CHECK( !SCH_FIELD::IsNetclassLabelFieldName( wxEmptyString ) );
257}
258
259
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:225
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:166
std::vector< SCH_FIELD > & GetFields()
Definition sch_label.h:214
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:119
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:143
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_MESSAGE(totalMismatches==0, std::to_string(totalMismatches)+" board(s) with strategy disagreements")
BOOST_CHECK_EQUAL(result, "25.4")
@ SCH_DIRECTIVE_LABEL_T
Definition typeinfo.h:172
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687