KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_project_archiver.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
20#include <boost/test/unit_test.hpp>
22
24#include <reporter.h>
25
26#include <wx/ffile.h>
27#include <wx/filefn.h>
28#include <wx/filename.h>
29#include <wx/log.h>
30#include <wx/wfstream.h>
31#include <wx/zipstrm.h>
32
33#include <set>
34#include <string>
35
36#if !defined( _WIN32 )
37#include <sys/stat.h>
38#include <unistd.h>
39#endif
40
41
42BOOST_AUTO_TEST_SUITE( ProjectArchiver )
43
44#if !defined( _WIN32 )
45
46namespace
47{
48
49wxString makeProjectDir( const wxString& aTag )
50{
51 wxString dir = wxFileName::GetTempDir() + wxFileName::GetPathSeparator()
52 + wxString::Format( wxT( "kicad-archiver-%s-%ld" ), aTag,
53 static_cast<long>( wxGetLocalTimeMillis().GetValue() ) );
54
55 BOOST_REQUIRE( wxFileName::Mkdir( dir, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) );
56 return dir;
57}
58
59
60void writeFile( const wxString& aPath, const std::string& aContent )
61{
62 wxFFile fp( aPath, wxT( "wb" ) );
63 BOOST_REQUIRE( fp.IsOpened() );
64 BOOST_REQUIRE( fp.Write( aContent.data(), aContent.size() ) == aContent.size() );
65 fp.Close();
66}
67
68
69// Returns false when the file stays readable, which happens when the tests run as root.
70bool makeUnreadable( const wxString& aPath )
71{
72 if( chmod( aPath.fn_str(), 0 ) != 0 )
73 return false;
74
75 wxLogNull noLog;
76 wxFFile probe( aPath, wxT( "rb" ) );
77 return !probe.IsOpened();
78}
79
80
81std::set<wxString> zipEntryNames( const wxString& aZipPath )
82{
83 std::set<wxString> names;
84 wxFFileInputStream stream( aZipPath );
85
86 if( !stream.IsOk() )
87 return names;
88
89 wxZipInputStream zip( stream );
90
91 while( wxZipEntry* entry = zip.GetNextEntry() )
92 {
93 names.insert( entry->GetName() );
94 delete entry;
95 }
96
97 return names;
98}
99
100
101void removeProjectDir( const wxString& aDir, const wxString& aUnreadable )
102{
103 chmod( aUnreadable.fn_str(), 0600 );
104 wxFileName::Rmdir( aDir, wxPATH_RMDIR_RECURSIVE );
105}
106
107} // anonymous namespace
108
109
110BOOST_AUTO_TEST_CASE( Archive_UnreadableFileRaisesNoSystemError )
111{
112 wxString dir = makeProjectDir( wxT( "nodialog" ) );
113 wxString board = dir + wxFileName::GetPathSeparator() + wxT( "board.kicad_pcb" );
114 wxString sheet = dir + wxFileName::GetPathSeparator() + wxT( "sheet.kicad_sch" );
115 wxString zip = dir + wxT( ".zip" );
116
117 writeFile( board, "(kicad_pcb)\n" );
118 writeFile( sheet, "(kicad_sch)\n" );
119
120 if( !makeUnreadable( sheet ) )
121 {
122 BOOST_TEST_MESSAGE( "skipped, the file could not be made unreadable" );
123 removeProjectDir( dir, sheet );
124 return;
125 }
126
127 KI_TEST::SCOPED_COUNTING_WXLOG logOverride( nullptr, wxLOG_Warning );
129
131
132 BOOST_REQUIRE_EQUAL( logOverride.GetCount(), 0u );
133
134 wxRemoveFile( zip );
135 removeProjectDir( dir, sheet );
136}
137
138
139BOOST_AUTO_TEST_CASE( Archive_ReportsUnreadableFileWhenNotVerbose )
140{
141 wxString dir = makeProjectDir( wxT( "quietreport" ) );
142 wxString board = dir + wxFileName::GetPathSeparator() + wxT( "board.kicad_pcb" );
143 wxString sheet = dir + wxFileName::GetPathSeparator() + wxT( "sheet.kicad_sch" );
144 wxString zip = dir + wxT( ".zip" );
145
146 writeFile( board, "(kicad_pcb)\n" );
147 writeFile( sheet, "(kicad_sch)\n" );
148
149 if( !makeUnreadable( sheet ) )
150 {
151 BOOST_TEST_MESSAGE( "skipped, the file could not be made unreadable" );
152 removeProjectDir( dir, sheet );
153 return;
154 }
155
156 wxLogNull noLog;
158
159 PROJECT_ARCHIVER::Archive( dir, zip, reporter, false );
160
161 BOOST_REQUIRE( reporter.HasMessageOfSeverity( RPT_SEVERITY_ERROR ) );
162 BOOST_REQUIRE( reporter.GetMessages().Contains( wxT( "'sheet.kicad_sch': " ) ) );
163
164 wxRemoveFile( zip );
165 removeProjectDir( dir, sheet );
166}
167
168
169BOOST_AUTO_TEST_CASE( Archive_KeepsPartialArchiveWhenAFileIsUnreadable )
170{
171 wxString dir = makeProjectDir( wxT( "partial" ) );
172 wxString board = dir + wxFileName::GetPathSeparator() + wxT( "board.kicad_pcb" );
173 wxString sheet = dir + wxFileName::GetPathSeparator() + wxT( "sheet.kicad_sch" );
174 wxString zip = dir + wxT( ".zip" );
175
176 writeFile( board, "(kicad_pcb)\n" );
177 writeFile( sheet, "(kicad_sch)\n" );
178
179 if( !makeUnreadable( sheet ) )
180 {
181 BOOST_TEST_MESSAGE( "skipped, the file could not be made unreadable" );
182 removeProjectDir( dir, sheet );
183 return;
184 }
185
186 wxLogNull noLog;
188
190
191 std::set<wxString> names = zipEntryNames( zip );
192 BOOST_REQUIRE( names.count( wxT( "board.kicad_pcb" ) ) == 1 );
193 BOOST_REQUIRE( names.count( wxT( "sheet.kicad_sch" ) ) == 0 );
194
195 wxRemoveFile( zip );
196 removeProjectDir( dir, sheet );
197}
198
199#endif // !_WIN32
200
A scoped application of a wxLog target that counts error-level messages.
static bool Archive(const wxString &aSrcDir, const wxString &aDestFile, REPORTER &aReporter, bool aVerbose=true, bool aIncludeExtraFiles=false)
Create an archive of the project.
A wrapper for reporting to a wxString object.
Definition reporter.h:242
@ RPT_SEVERITY_ERROR
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
IbisParser parser & reporter
BOOST_AUTO_TEST_CASE(Archive_UnreadableFileRaisesNoSystemError)
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")