KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_remote_symbol_import.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,
12 * but 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
20#include <boost/test/unit_test.hpp>
21
22#include <eeschema_settings.h>
23#include <picosha2.h>
27
28#include <wx/filefn.h>
29#include <wx/filename.h>
30#include <wx/stdpaths.h>
31
32
33namespace
34{
35std::string symbolPayload( const char* aName )
36{
37 return wxString::Format(
38 wxS( "(kicad_symbol_lib (version 20220914) (generator kicad_symbol_editor)\n"
39 " (symbol \"%s\" (in_bom yes) (on_board yes)\n"
40 " (property \"Reference\" \"R\" (at 0 0 0)\n"
41 " (effects (font (size 1.27 1.27)))\n"
42 " )\n"
43 " (property \"Value\" \"%s\" (at 0 0 0)\n"
44 " (effects (font (size 1.27 1.27)))\n"
45 " )\n"
46 " (property \"Footprint\" \"\" (at 0 0 0)\n"
47 " (effects (font (size 1.27 1.27)) hide)\n"
48 " )\n"
49 " (property \"Datasheet\" \"\" (at 0 0 0)\n"
50 " (effects (font (size 1.27 1.27)) hide)\n"
51 " )\n"
52 " (symbol \"%s_0_1\"\n"
53 " (rectangle (start -1.27 -1.27) (end 1.27 1.27)\n"
54 " (stroke (width 0) (type default))\n"
55 " (fill (type background))\n"
56 " )\n"
57 " )\n"
58 " (symbol \"%s_1_1\"\n"
59 " (pin passive line (at -3.81 0 0) (length 2.54)\n"
60 " (name \"PIN\" (effects (font (size 1.27 1.27))))\n"
61 " (number \"1\" (effects (font (size 1.27 1.27))))\n"
62 " )\n"
63 " )\n"
64 " )\n"
65 ")\n" ),
66 wxString::FromUTF8( aName ), wxString::FromUTF8( aName ),
67 wxString::FromUTF8( aName ), wxString::FromUTF8( aName ) )
68 .ToStdString();
69}
70
71
72wxString sha256Hex( const std::string& aPayload )
73{
74 std::string hashHex;
75 picosha2::hash256_hex_string( aPayload.begin(), aPayload.end(), hashHex );
76 return wxString::FromUTF8( hashHex.c_str() );
77}
78
79
80wxString tempDir()
81{
82 wxString path = wxFileName::CreateTempFileName( wxS( "remote-symbol-import" ) );
83 wxRemoveFile( path );
84 wxMkdir( path );
85 return path;
86}
87
88
90{
92 metadata.provider_name = wxString( "Acme" );
93 metadata.provider_version = wxString( "1.0.0" );
94 metadata.api_base_url = wxString( "https://provider.example.test/api" );
95 metadata.max_download_bytes = 4096;
96 metadata.parts_v1 = true;
97 metadata.direct_downloads_v1 = true;
98 return metadata;
99}
100
101REMOTE_SYMBOL_IMPORT_CONTEXT importContext()
102{
104 context.symbol_name = wxString( "R" );
105 context.library_name = wxString( "Device" );
106 return context;
107}
108
109
111{
113 manifest.part_id = wxString( "acme-res-10k" );
114 manifest.display_name = wxString( "RC0603FR-0710KL" );
115
117 const std::string symbolBlob = symbolPayload( "R" );
118 symbol.asset_type = wxString( "symbol" );
119 symbol.name = wxString( "acme-res-10k.kicad_sym" );
120 symbol.content_type = wxString( "application/x-kicad-symbol" );
121 symbol.size_bytes = static_cast<long long>( symbolBlob.size() );
122 symbol.sha256 = sha256Hex( symbolBlob );
123 symbol.download_url = wxString( "https://provider.example.test/downloads/acme-res-10k.kicad_sym" );
124 symbol.required = true;
125 symbol.target_library = wxString( "Device" );
126 symbol.target_name = wxString( "R" );
127
129 footprint.asset_type = wxString( "footprint" );
130 footprint.name = wxString( "R_0603.pretty" );
131 footprint.content_type = wxString( "application/x-kicad-footprint" );
132 footprint.size_bytes = 44;
133 footprint.sha256 = wxString( "8d8090740282c9ec23541a148af0ae57543e0da581e00e714e066dc4a1adefb0" );
134 footprint.download_url = wxString( "https://provider.example.test/downloads/R_0603.pretty" );
135 footprint.required = false;
136 footprint.target_library = wxString( "Resistor_SMD" );
137 footprint.target_name = wxString( "R_0603_1608Metric" );
138
139 manifest.assets = { symbol, footprint };
140 return manifest;
141}
142} // namespace
143
144
145BOOST_AUTO_TEST_SUITE( RemoteSymbolImportTests )
146
147BOOST_AUTO_TEST_CASE( ImportWritesDownloadedAssets )
148{
149 const wxString outputDir = tempDir();
151 BOOST_REQUIRE( settings );
152 settings->m_RemoteSymbol.destination_dir = outputDir;
153 settings->m_RemoteSymbol.library_prefix = wxString( "testremote" );
154 settings->m_RemoteSymbol.add_to_global_table = true;
155
157 [&]( const wxString& aUrl, REMOTE_SYMBOL_FETCH_RESPONSE& aResponse, wxString& aError )
158 {
159 wxUnusedVar( aError );
160 aResponse.status_code = 200;
161
162 if( aUrl.EndsWith( wxString( "acme-res-10k.kicad_sym" ) ) )
163 {
164 aResponse.content_type = wxString( "application/x-kicad-symbol" );
165 const std::string payload = symbolPayload( "R" );
166 aResponse.payload.assign( payload.begin(), payload.end() );
167 return true;
168 }
169
170 aResponse.content_type = wxString( "application/x-kicad-footprint" );
171 const std::string payload = "(module \"R_0603_1608Metric\" (layer \"F.Cu\"))\n";
172 aResponse.payload.assign( payload.begin(), payload.end() );
173 return true;
174 } );
175
176 REMOTE_SYMBOL_IMPORT_JOB job( nullptr, &downloader );
177 wxString error;
178
179 BOOST_REQUIRE( job.Import( provider(), importContext(), manifest(), false, error ) );
180
181 wxFileName symbolPath( outputDir, wxString() );
182 symbolPath.AppendDir( wxString( "symbols" ) );
183 symbolPath.SetFullName( wxString( "testremote_device.kicad_sym" ) );
184 BOOST_CHECK( symbolPath.FileExists() );
185
186 wxFileName footprintPath( outputDir, wxString() );
187 footprintPath.AppendDir( wxString( "footprints" ) );
188 footprintPath.AppendDir( wxString( "testremote_resistor_smd.pretty" ) );
189 footprintPath.SetFullName( wxString( "R_0603_1608Metric.kicad_mod" ) );
190 BOOST_CHECK( footprintPath.FileExists() );
191}
192
193BOOST_AUTO_TEST_CASE( ImportRejectsSymbolPayloadThatDoesNotContainExpectedName )
194{
195 const wxString outputDir = tempDir();
197 BOOST_REQUIRE( settings );
198 settings->m_RemoteSymbol.destination_dir = outputDir;
199 settings->m_RemoteSymbol.library_prefix = wxString( "testremote" );
200 settings->m_RemoteSymbol.add_to_global_table = true;
201
203 [&]( const wxString& aUrl, REMOTE_SYMBOL_FETCH_RESPONSE& aResponse, wxString& aError )
204 {
205 wxUnusedVar( aError );
206 aResponse.status_code = 200;
207
208 if( aUrl.EndsWith( wxString( "acme-res-10k.kicad_sym" ) ) )
209 {
210 aResponse.content_type = wxString( "application/x-kicad-symbol" );
211 const std::string payload = symbolPayload( "WrongName" );
212 aResponse.payload.assign( payload.begin(), payload.end() );
213 return true;
214 }
215
216 aResponse.content_type = wxString( "application/x-kicad-footprint" );
217 const std::string payload = "(module \"R_0603_1608Metric\" (layer \"F.Cu\"))\n";
218 aResponse.payload.assign( payload.begin(), payload.end() );
219 return true;
220 } );
221
222 REMOTE_SYMBOL_IMPORT_JOB job( nullptr, &downloader );
223 wxString error;
224
225 BOOST_CHECK( !job.Import( provider(), importContext(), manifest(), false, error ) );
226 BOOST_CHECK( !error.IsEmpty() );
227}
228
REMOTE_PROVIDER_SETTINGS m_RemoteSymbol
T * GetAppSettings(const char *aFilename)
std::vector< REMOTE_PROVIDER_PART_ASSET > assets
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
std::string path
BOOST_AUTO_TEST_CASE(ImportWritesDownloadedAssets)