Separate out zip specific parts of the archive test suite
[wxWidgets.git] / tests / archive / ziptest.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/archive/ziptest.cpp
3 // Purpose: Test the zip classes
4 // Author: Mike Wetherell
5 // RCS-ID: $Id$
6 // Copyright: (c) 2004 Mike Wetherell
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
9
10 #include "testprec.h"
11
12 #ifdef __BORLANDC__
13 # pragma hdrstop
14 #endif
15
16 #ifndef WX_PRECOMP
17 # include "wx/wx.h"
18 #endif
19
20 #if wxUSE_STREAMS && wxUSE_ZIPSTREAM
21
22 #include "archivetest.h"
23 #include "wx/zipstrm.h"
24
25 using std::string;
26 using std::auto_ptr;
27
28
29 ///////////////////////////////////////////////////////////////////////////////
30 // ArchiveTestCase<wxZipClassFactory> could be used directly, but instead this
31 // derived class is used so that zip specific features can be tested.
32
33 class ZipTestCase : public ArchiveTestCase<wxZipClassFactory>
34 {
35 public:
36 ZipTestCase(string name,
37 int id,
38 int options,
39 const wxString& archiver = wxEmptyString,
40 const wxString& unarchiver = wxEmptyString)
41 :
42 ArchiveTestCase<wxZipClassFactory>(name, id, new wxZipClassFactory,
43 options, archiver, unarchiver),
44 m_count(0)
45 { }
46
47 protected:
48 void OnCreateArchive(wxZipOutputStream& zip);
49
50 void OnArchiveExtracted(wxZipInputStream& zip, int expectedTotal);
51
52 void OnCreateEntry(wxZipOutputStream& zip,
53 TestEntry& testEntry,
54 wxZipEntry *entry);
55
56 void OnEntryExtracted(wxZipEntry& entry,
57 const TestEntry& testEntry,
58 wxZipInputStream *arc);
59
60 void OnSetNotifier(EntryT& entry);
61
62 int m_count;
63 wxString m_comment;
64 };
65
66 void ZipTestCase::OnCreateArchive(wxZipOutputStream& zip)
67 {
68 m_comment << _T("Comment for test ") << m_id;
69 zip.SetComment(m_comment);
70 }
71
72 void ZipTestCase::OnArchiveExtracted(wxZipInputStream& zip, int expectedTotal)
73 {
74 CPPUNIT_ASSERT(zip.GetComment() == m_comment);
75 CPPUNIT_ASSERT(zip.GetTotalEntries() == expectedTotal);
76 }
77
78 void ZipTestCase::OnCreateEntry(wxZipOutputStream& zip,
79 TestEntry& testEntry,
80 wxZipEntry *entry)
81 {
82 zip.SetLevel((m_id + m_count) % 10);
83
84 if (entry) {
85 switch ((m_id + m_count) % 5) {
86 case 0:
87 {
88 wxString comment = _T("Comment for ") + entry->GetName();
89 entry->SetComment(comment);
90 // lowercase the expected result, and the notifier should do
91 // the same for the zip entries when ModifyArchive() runs
92 testEntry.SetComment(comment.Lower());
93 break;
94 }
95 case 2:
96 entry->SetMethod(wxZIP_METHOD_STORE);
97 break;
98 case 4:
99 entry->SetMethod(wxZIP_METHOD_DEFLATE);
100 break;
101 }
102 entry->SetIsText(testEntry.IsText());
103 }
104
105 m_count++;
106 }
107
108 void ZipTestCase::OnEntryExtracted(wxZipEntry& entry,
109 const TestEntry& testEntry,
110 wxZipInputStream *arc)
111 {
112 // provide some context for the error message so that we know which
113 // iteration of the loop we were on
114 wxString name = _T(" '") + entry.GetName() + _T("'");
115 string error_entry(name.mb_str());
116 string error_context(" failed for entry" + error_entry);
117
118 CPPUNIT_ASSERT_MESSAGE("GetComment" + error_context,
119 entry.GetComment() == testEntry.GetComment());
120
121 // for seekable streams, GetNextEntry() doesn't read the local header so
122 // call OpenEntry() to do it
123 if (arc && (m_options & PipeIn) == 0 && entry.IsDir())
124 arc->OpenEntry(entry);
125
126 CPPUNIT_ASSERT_MESSAGE("IsText" + error_context,
127 entry.IsText() == testEntry.IsText());
128
129 CPPUNIT_ASSERT_MESSAGE("Extra/LocalExtra mismatch for entry" + error_entry,
130 (entry.GetExtraLen() != 0 && entry.GetLocalExtraLen() != 0) ||
131 (entry.GetExtraLen() == 0 && entry.GetLocalExtraLen() == 0));
132 }
133
134 // check the notifier mechanism by using it to fold the entry comments to
135 // lowercase
136 //
137 class ZipNotifier : public wxZipNotifier
138 {
139 public:
140 void OnEntryUpdated(wxZipEntry& entry);
141 };
142
143 void ZipNotifier::OnEntryUpdated(wxZipEntry& entry)
144 {
145 entry.SetComment(entry.GetComment().Lower());
146 }
147
148 void ZipTestCase::OnSetNotifier(EntryT& entry)
149 {
150 static ZipNotifier notifier;
151 entry.SetNotifier(notifier);
152 }
153
154
155 ///////////////////////////////////////////////////////////////////////////////
156 // 'zip - -' produces local headers without the size field set. This is a
157 // case not covered by all the other tests, so this class tests it as a
158 // special case
159
160 class ZipPipeTestCase : public CppUnit::TestCase
161 {
162 public:
163 ZipPipeTestCase(string name, int options) :
164 CppUnit::TestCase(name), m_options(options) { }
165
166 protected:
167 void runTest();
168 int m_options;
169 };
170
171 void ZipPipeTestCase::runTest()
172 {
173 TestOutputStream out(m_options);
174
175 wxString testdata = _T("test data to pipe through zip");
176 wxString cmd = _T("echo ") + testdata + _T(" | zip -q - -");
177
178 {
179 PFileInputStream in(cmd);
180 if (in.Ok())
181 out.Write(in);
182 }
183
184 TestInputStream in(out);
185 wxZipInputStream zip(in);
186
187 auto_ptr<wxZipEntry> entry(zip.GetNextEntry());
188 CPPUNIT_ASSERT(entry.get() != NULL);
189
190 if ((m_options & PipeIn) == 0)
191 CPPUNIT_ASSERT(entry->GetSize() != wxInvalidOffset);
192
193 char buf[64];
194 size_t len = zip.Read(buf, sizeof(buf) - 1).LastRead();
195
196 while (len > 0 && buf[len - 1] <= 32)
197 --len;
198 buf[len] = 0;
199
200 CPPUNIT_ASSERT(zip.Eof());
201 CPPUNIT_ASSERT(wxString(buf, *wxConvCurrent) == testdata);
202 }
203
204
205 ///////////////////////////////////////////////////////////////////////////////
206 // Zip suite
207
208 class ziptest : public ArchiveTestSuite
209 {
210 public:
211 ziptest();
212 static CppUnit::Test *suite() { return (new ziptest)->makeSuite(); }
213
214 protected:
215 ArchiveTestSuite *makeSuite();
216
217 CppUnit::Test *makeTest(string descr, int id, int options,
218 bool genericInterface, const wxString& archiver,
219 const wxString& unarchiver);
220 };
221
222 ziptest::ziptest()
223 : ArchiveTestSuite("zip")
224 {
225 AddArchiver(_T("zip -qr %s *"));
226 AddUnArchiver(_T("unzip -q %s"));
227 }
228
229 ArchiveTestSuite *ziptest::makeSuite()
230 {
231 ArchiveTestSuite::makeSuite();
232
233 #ifndef WXARC_NO_POPEN
234 // if have popen then can check the piped output of 'zip - -'
235 if (IsInPath(_T("zip")))
236 for (int options = 0; options <= PipeIn; options += PipeIn) {
237 string name = Description(_T("ZipPipeTestCase"), options,
238 false, _T(""), _T("zip -q - -"));
239 addTest(new ZipPipeTestCase(name, options));
240 m_id++;
241 }
242 #endif
243
244 return this;
245 }
246
247 CppUnit::Test *ziptest::makeTest(
248 string descr,
249 int id,
250 int options,
251 bool genericInterface,
252 const wxString& archiver,
253 const wxString& unarchiver)
254 {
255 // unzip doesn't support piping in the zip
256 if ((options & PipeIn) && !unarchiver.empty())
257 return NULL;
258
259 if (genericInterface)
260 return new ArchiveTestCase<wxArchiveClassFactory>(
261 descr, id, new wxZipClassFactory,
262 options, archiver, unarchiver);
263 else
264 return new ZipTestCase(descr, id, options, archiver, unarchiver);
265 }
266
267 CPPUNIT_TEST_SUITE_REGISTRATION(ziptest);
268 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(ziptest, "archive");
269 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(ziptest, "archive/zip");
270
271 #endif // wxUSE_STREAMS && wxUSE_ZIPSTREAM