In the past some streams returned Eof() before the end was read past rather
[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 private:
83 wxFileOffset OnSysSeek(wxFileOffset pos, wxSeekMode mode);
84 wxFileOffset OnSysTell() const;
85 size_t OnSysRead(void *buffer, size_t size);
86
87 int m_options;
88 size_t m_pos;
89 size_t m_size;
90 char *m_data;
91 int m_eoftype;
92 };
93
94
95 ///////////////////////////////////////////////////////////////////////////////
96 // wxFFile streams for piping to/from an external program
97
98 class PFileInputStream : public wxFFileInputStream
99 {
100 public:
101 PFileInputStream(const wxString& cmd);
102 ~PFileInputStream();
103 };
104
105 class PFileOutputStream : public wxFFileOutputStream
106 {
107 public:
108 PFileOutputStream(const wxString& cmd);
109 ~PFileOutputStream();
110 };
111
112
113 ///////////////////////////////////////////////////////////////////////////////
114 // A class to hold a test entry
115
116 class TestEntry
117 {
118 public:
119 TestEntry(const wxDateTime& dt, int len, const char *data);
120 ~TestEntry() { delete [] m_data; }
121
122 wxDateTime GetDateTime() const { return m_dt; }
123 wxFileOffset GetLength() const { return m_len; }
124 size_t GetSize() const { return m_len; }
125 const char *GetData() const { return m_data; }
126 wxString GetComment() const { return m_comment; }
127 bool IsText() const { return m_isText; }
128
129 void SetComment(const wxString& comment) { m_comment = comment; }
130 void SetDateTime(const wxDateTime& dt) { m_dt = dt; }
131
132 private:
133 wxDateTime m_dt;
134 size_t m_len;
135 char *m_data;
136 wxString m_comment;
137 bool m_isText;
138 };
139
140
141 ///////////////////////////////////////////////////////////////////////////////
142 // The test case
143
144 template <class ClassFactoryT>
145 class ArchiveTestCase : public CppUnit::TestCase
146 {
147 public:
148 ArchiveTestCase(std::string name,
149 ClassFactoryT *factory,
150 int options,
151 const wxString& archiver = wxEmptyString,
152 const wxString& unarchiver = wxEmptyString);
153
154 ~ArchiveTestCase();
155
156 protected:
157 // the classes to test
158 typedef typename ClassFactoryT::entry_type EntryT;
159 typedef typename ClassFactoryT::instream_type InputStreamT;
160 typedef typename ClassFactoryT::outstream_type OutputStreamT;
161 typedef typename ClassFactoryT::notifier_type NotifierT;
162 typedef typename ClassFactoryT::iter_type IterT;
163 typedef typename ClassFactoryT::pairiter_type PairIterT;
164
165 // the entry point for the test
166 void runTest();
167
168 // create the test data
169 void CreateTestData();
170 TestEntry& Add(const char *name, const char *data, int len = -1);
171 TestEntry& Add(const char *name, int len = 0, int value = EOF);
172
173 // 'archive up' the test data
174 void CreateArchive(wxOutputStream& out);
175 void CreateArchive(wxOutputStream& out, const wxString& archiver);
176
177 // perform various modifications on the archive
178 void ModifyArchive(wxInputStream& in, wxOutputStream& out);
179
180 // extract the archive and verify its contents
181 void ExtractArchive(wxInputStream& in);
182 void ExtractArchive(wxInputStream& in, const wxString& unarchiver);
183 void VerifyDir(wxString& path, size_t rootlen = 0);
184
185 // tests for the iterators
186 void TestIterator(wxInputStream& in);
187 void TestPairIterator(wxInputStream& in);
188 void TestSmartIterator(wxInputStream& in);
189 void TestSmartPairIterator(wxInputStream& in);
190
191 // try reading two entries at the same time
192 void ReadSimultaneous(TestInputStream& in);
193
194 // overridables
195 virtual void OnCreateArchive(OutputStreamT& WXUNUSED(arc)) { }
196 virtual void OnSetNotifier(EntryT& entry);
197
198 virtual void OnArchiveExtracted(InputStreamT& WXUNUSED(arc),
199 int WXUNUSED(expectedTotal)) { }
200
201 virtual void OnCreateEntry( OutputStreamT& WXUNUSED(arc),
202 TestEntry& WXUNUSED(testEntry),
203 EntryT *entry = NULL) { (void)entry; }
204
205 virtual void OnEntryExtracted( EntryT& WXUNUSED(entry),
206 const TestEntry& WXUNUSED(testEntry),
207 InputStreamT *arc = NULL) { (void)arc; }
208
209 typedef std::map<wxString, TestEntry*> TestEntries;
210 TestEntries m_testEntries; // test data
211 std::auto_ptr<ClassFactoryT> m_factory; // factory to make classes
212 int m_options; // test options
213 wxDateTime m_timeStamp; // timestamp to give test entries
214 int m_id; // select between the possibilites
215 wxString m_archiver; // external archiver
216 wxString m_unarchiver; // external unarchiver
217 };
218
219
220 ///////////////////////////////////////////////////////////////////////////////
221 // Make ids
222
223 class TestId
224 {
225 public:
226 // make a new id and return it as a string
227 static std::string MakeId();
228 // get the current id
229 static int GetId() { return m_seed; }
230 private:
231 // seed for generating the ids
232 static int m_seed;
233 };
234
235
236 ///////////////////////////////////////////////////////////////////////////////
237 // Base class for the archive test suites
238
239 class ArchiveTestSuite : public CppUnit::TestSuite
240 {
241 public:
242 ArchiveTestSuite(std::string name);
243
244 protected:
245 virtual ArchiveTestSuite *makeSuite();
246
247 virtual CppUnit::Test *makeTest(std::string descr,
248 int options,
249 bool genericInterface,
250 const wxString& archiver,
251 const wxString& unarchiver);
252
253 void AddArchiver(const wxString& cmd) { AddCmd(m_archivers, cmd); }
254 void AddUnArchiver(const wxString &cmd) { AddCmd(m_unarchivers, cmd); }
255 bool IsInPath(const wxString& cmd);
256
257 std::string Description(const wxString& type,
258 int options,
259 bool genericInterface = false,
260 const wxString& archiver = wxEmptyString,
261 const wxString& unarchiver = wxEmptyString);
262
263 private:
264 wxString m_name;
265 wxPathList m_path;
266 wxArrayString m_archivers;
267 wxArrayString m_unarchivers;
268
269 void AddCmd(wxArrayString& cmdlist, const wxString& cmd);
270 };