Forward port test case that corrupts archives to see if they can crash an input stream.
[wxWidgets.git] / tests / archive / archivetest.h
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/archive/archivetest.h
3 // Purpose: Test the archive classes
4 // Author: Mike Wetherell
5 // RCS-ID: $Id$
6 // Copyright: (c) 2004 Mike Wetherell
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
9
10 #define WX_TEST_ARCHIVE_ITERATOR
11
12 #include "wx/archive.h"
13 #include "wx/wfstream.h"
14
15
16 ///////////////////////////////////////////////////////////////////////////////
17 // Bit flags for options for the tests
18
19 enum Options
20 {
21 PipeIn = 0x01, // input streams are non-seekable
22 PipeOut = 0x02, // output streams are non-seekable
23 Stub = 0x04, // the archive should be appended to a stub
24 AllOptions = 0x07
25 };
26
27
28 ///////////////////////////////////////////////////////////////////////////////
29 // TestOutputStream and TestInputStream are memory streams which can be
30 // seekable or non-seekable.
31
32 class TestOutputStream : public wxOutputStream
33 {
34 public:
35 TestOutputStream(int options);
36
37 ~TestOutputStream() { delete [] m_data; }
38
39 int GetOptions() const { return m_options; }
40 wxFileOffset GetLength() const { return m_size; }
41 bool IsSeekable() const { return (m_options & PipeOut) == 0; }
42
43 // gives away the data, this stream is then empty, and can be reused
44 void GetData(char*& data, size_t& size);
45
46 private:
47 void Init();
48
49 wxFileOffset OnSysSeek(wxFileOffset pos, wxSeekMode mode);
50 wxFileOffset OnSysTell() const;
51 size_t OnSysWrite(const void *buffer, size_t size);
52
53 int m_options;
54 size_t m_pos;
55 size_t m_capacity;
56 size_t m_size;
57 char *m_data;
58 };
59
60 class TestInputStream : public wxInputStream
61 {
62 public:
63 // various streams have implemented eof differently, so check the archive
64 // stream works with all the possibilities (bit flags that can be ORed)
65 enum EofTypes {
66 AtLast = 0x01, // eof before an attempt to read past the last byte
67 WithError = 0x02 // give an error instead of eof
68 };
69
70 // ctor takes the data from the output stream, which is then empty
71 TestInputStream(TestOutputStream& out, int eoftype)
72 : m_data(NULL), m_eoftype(eoftype) { SetData(out); }
73 // this ctor 'dups'
74 TestInputStream(const TestInputStream& in);
75 ~TestInputStream() { delete [] m_data; }
76
77 void Rewind();
78 wxFileOffset GetLength() const { return m_size; }
79 bool IsSeekable() const { return (m_options & PipeIn) == 0; }
80 void SetData(TestOutputStream& out);
81
82 void Chop(size_t size) { m_size = size; }
83 char& operator [](size_t pos) { return m_data[pos]; }
84
85 private:
86 wxFileOffset OnSysSeek(wxFileOffset pos, wxSeekMode mode);
87 wxFileOffset OnSysTell() const;
88 size_t OnSysRead(void *buffer, size_t size);
89
90 int m_options;
91 size_t m_pos;
92 size_t m_size;
93 char *m_data;
94 int m_eoftype;
95 };
96
97
98 ///////////////////////////////////////////////////////////////////////////////
99 // wxFFile streams for piping to/from an external program
100
101 class PFileInputStream : public wxFFileInputStream
102 {
103 public:
104 PFileInputStream(const wxString& cmd);
105 ~PFileInputStream();
106 };
107
108 class PFileOutputStream : public wxFFileOutputStream
109 {
110 public:
111 PFileOutputStream(const wxString& cmd);
112 ~PFileOutputStream();
113 };
114
115
116 ///////////////////////////////////////////////////////////////////////////////
117 // A class to hold a test entry
118
119 class TestEntry
120 {
121 public:
122 TestEntry(const wxDateTime& dt, int len, const char *data);
123 ~TestEntry() { delete [] m_data; }
124
125 wxDateTime GetDateTime() const { return m_dt; }
126 wxFileOffset GetLength() const { return m_len; }
127 size_t GetSize() const { return m_len; }
128 const char *GetData() const { return m_data; }
129 wxString GetComment() const { return m_comment; }
130 bool IsText() const { return m_isText; }
131
132 void SetComment(const wxString& comment) { m_comment = comment; }
133 void SetDateTime(const wxDateTime& dt) { m_dt = dt; }
134
135 private:
136 wxDateTime m_dt;
137 size_t m_len;
138 char *m_data;
139 wxString m_comment;
140 bool m_isText;
141 };
142
143
144 ///////////////////////////////////////////////////////////////////////////////
145 // The test case
146
147 template <class ClassFactoryT>
148 class ArchiveTestCase : public CppUnit::TestCase
149 {
150 public:
151 ArchiveTestCase(std::string name,
152 ClassFactoryT *factory,
153 int options,
154 const wxString& archiver = wxEmptyString,
155 const wxString& unarchiver = wxEmptyString);
156
157 ~ArchiveTestCase();
158
159 protected:
160 // the classes to test
161 typedef typename ClassFactoryT::entry_type EntryT;
162 typedef typename ClassFactoryT::instream_type InputStreamT;
163 typedef typename ClassFactoryT::outstream_type OutputStreamT;
164 typedef typename ClassFactoryT::notifier_type NotifierT;
165 typedef typename ClassFactoryT::iter_type IterT;
166 typedef typename ClassFactoryT::pairiter_type PairIterT;
167
168 // the entry point for the test
169 void runTest();
170
171 // create the test data
172 void CreateTestData();
173 TestEntry& Add(const char *name, const char *data, int len = -1);
174 TestEntry& Add(const char *name, int len = 0, int value = EOF);
175
176 // 'archive up' the test data
177 void CreateArchive(wxOutputStream& out);
178 void CreateArchive(wxOutputStream& out, const wxString& archiver);
179
180 // perform various modifications on the archive
181 void ModifyArchive(wxInputStream& in, wxOutputStream& out);
182
183 // extract the archive and verify its contents
184 void ExtractArchive(wxInputStream& in);
185 void ExtractArchive(wxInputStream& in, const wxString& unarchiver);
186 void VerifyDir(wxString& path, size_t rootlen = 0);
187
188 // tests for the iterators
189 void TestIterator(wxInputStream& in);
190 void TestPairIterator(wxInputStream& in);
191 void TestSmartIterator(wxInputStream& in);
192 void TestSmartPairIterator(wxInputStream& in);
193
194 // try reading two entries at the same time
195 void ReadSimultaneous(TestInputStream& in);
196
197 // overridables
198 virtual void OnCreateArchive(OutputStreamT& WXUNUSED(arc)) { }
199 virtual void OnSetNotifier(EntryT& entry);
200
201 virtual void OnArchiveExtracted(InputStreamT& WXUNUSED(arc),
202 int WXUNUSED(expectedTotal)) { }
203
204 virtual void OnCreateEntry( OutputStreamT& WXUNUSED(arc),
205 TestEntry& WXUNUSED(testEntry),
206 EntryT *entry = NULL) { (void)entry; }
207
208 virtual void OnEntryExtracted( EntryT& WXUNUSED(entry),
209 const TestEntry& WXUNUSED(testEntry),
210 InputStreamT *arc = NULL) { (void)arc; }
211
212 typedef std::map<wxString, TestEntry*> TestEntries;
213 TestEntries m_testEntries; // test data
214 std::auto_ptr<ClassFactoryT> m_factory; // factory to make classes
215 int m_options; // test options
216 wxDateTime m_timeStamp; // timestamp to give test entries
217 int m_id; // select between the possibilites
218 wxString m_archiver; // external archiver
219 wxString m_unarchiver; // external unarchiver
220 };
221
222
223 ///////////////////////////////////////////////////////////////////////////////
224 // Make ids
225
226 class TestId
227 {
228 public:
229 // make a new id and return it as a string
230 static std::string MakeId();
231 // get the current id
232 static int GetId() { return m_seed; }
233 private:
234 // seed for generating the ids
235 static int m_seed;
236 };
237
238
239 ///////////////////////////////////////////////////////////////////////////////
240 // Base class for the archive test suites
241
242 class ArchiveTestSuite : public CppUnit::TestSuite
243 {
244 public:
245 ArchiveTestSuite(std::string name);
246
247 protected:
248 virtual ArchiveTestSuite *makeSuite();
249
250 virtual CppUnit::Test *makeTest(std::string descr,
251 int options,
252 bool genericInterface,
253 const wxString& archiver,
254 const wxString& unarchiver);
255
256 void AddArchiver(const wxString& cmd) { AddCmd(m_archivers, cmd); }
257 void AddUnArchiver(const wxString &cmd) { AddCmd(m_unarchivers, cmd); }
258 bool IsInPath(const wxString& cmd);
259
260 std::string Description(const wxString& type,
261 int options,
262 bool genericInterface = false,
263 const wxString& archiver = wxEmptyString,
264 const wxString& unarchiver = wxEmptyString);
265
266 private:
267 wxString m_name;
268 wxPathList m_path;
269 wxArrayString m_archivers;
270 wxArrayString m_unarchivers;
271
272 void AddCmd(wxArrayString& cmdlist, const wxString& cmd);
273 };