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