]>
Commit | Line | Data |
---|---|---|
e6477b92 MW |
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 |