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