+///////////////////////////////////////////////////////////////////////////////
+// Name: tests/archive/archivetest.h
+// Purpose: Test the archive classes
+// Author: Mike Wetherell
+// RCS-ID: $Id$
+// Copyright: (c) 2004 Mike Wetherell
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#define WX_TEST_ARCHIVE_ITERATOR
+
+#include "wx/archive.h"
+#include "wx/wfstream.h"
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Bit flags for options for the tests
+
+enum Options
+{
+ PipeIn = 0x01, // input streams are non-seekable
+ PipeOut = 0x02, // output streams are non-seekable
+ Stub = 0x04, // the archive should be appended to a stub
+ AllOptions = 0x07
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// TestOutputStream and TestInputStream are memory streams which can be
+// seekable or non-seekable.
+
+class TestOutputStream : public wxOutputStream
+{
+public:
+ TestOutputStream(int options);
+
+ ~TestOutputStream() { delete [] m_data; }
+
+ int GetOptions() const { return m_options; }
+ wxFileOffset GetLength() const { return m_size; }
+
+ // gives away the data, this stream is then empty, and can be reused
+ void GetData(char*& data, size_t& size);
+
+private:
+ void Init();
+
+ wxFileOffset OnSysSeek(wxFileOffset pos, wxSeekMode mode);
+ wxFileOffset OnSysTell() const;
+ size_t OnSysWrite(const void *buffer, size_t size);
+
+ int m_options;
+ size_t m_pos;
+ size_t m_capacity;
+ size_t m_size;
+ char *m_data;
+};
+
+class TestInputStream : public wxInputStream
+{
+public:
+ // ctor takes the data from the output stream, which is then empty
+ TestInputStream(TestOutputStream& out) : m_data(NULL) { SetData(out); }
+ // this ctor 'dups'
+ TestInputStream(const TestInputStream& in);
+ ~TestInputStream() { delete [] m_data; }
+
+ void Rewind();
+ wxFileOffset GetLength() const { return m_size; }
+ void SetData(TestOutputStream& out);
+
+private:
+ wxFileOffset OnSysSeek(wxFileOffset pos, wxSeekMode mode);
+ wxFileOffset OnSysTell() const;
+ size_t OnSysRead(void *buffer, size_t size);
+
+ int m_options;
+ size_t m_pos;
+ size_t m_size;
+ char *m_data;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// wxFFile streams for piping to/from an external program
+
+class PFileInputStream : public wxFFileInputStream
+{
+public:
+ PFileInputStream(const wxString& cmd);
+ ~PFileInputStream();
+};
+
+class PFileOutputStream : public wxFFileOutputStream
+{
+public:
+ PFileOutputStream(const wxString& cmd);
+ ~PFileOutputStream();
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// A class to hold a test entry
+
+class TestEntry
+{
+public:
+ TestEntry(const wxDateTime& dt, int len, const char *data);
+ ~TestEntry() { delete [] m_data; }
+
+ wxDateTime GetDateTime() const { return m_dt; }
+ wxFileOffset GetLength() const { return m_len; }
+ size_t GetSize() const { return m_len; }
+ const char *GetData() const { return m_data; }
+ wxString GetComment() const { return m_comment; }
+ bool IsText() const { return m_isText; }
+
+ void SetComment(const wxString& comment) { m_comment = comment; }
+ void SetDateTime(const wxDateTime& dt) { m_dt = dt; }
+
+private:
+ wxDateTime m_dt;
+ size_t m_len;
+ char *m_data;
+ wxString m_comment;
+ bool m_isText;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// The test case
+
+template <class ClassFactoryT>
+class ArchiveTestCase : public CppUnit::TestCase
+{
+public:
+ ArchiveTestCase(std::string name,
+ int id,
+ ClassFactoryT *factory,
+ int options,
+ const wxString& archiver = wxEmptyString,
+ const wxString& unarchiver = wxEmptyString);
+
+ ~ArchiveTestCase();
+
+protected:
+ // the classes to test
+ typedef typename ClassFactoryT::entry_type EntryT;
+ typedef typename ClassFactoryT::instream_type InputStreamT;
+ typedef typename ClassFactoryT::outstream_type OutputStreamT;
+ typedef typename ClassFactoryT::notifier_type NotifierT;
+ typedef typename ClassFactoryT::iter_type IterT;
+ typedef typename ClassFactoryT::pairiter_type PairIterT;
+
+ // the entry point for the test
+ void runTest();
+
+ // create the test data
+ void CreateTestData();
+ TestEntry& Add(const char *name, const char *data, int len = -1);
+ TestEntry& Add(const char *name, int len = 0, int value = EOF);
+
+ // 'archive up' the test data
+ void CreateArchive(wxOutputStream& out);
+ void CreateArchive(wxOutputStream& out, const wxString& archiver);
+
+ // perform various modifications on the archive
+ void ModifyArchive(wxInputStream& in, wxOutputStream& out);
+
+ // extract the archive and verify its contents
+ void ExtractArchive(wxInputStream& in);
+ void ExtractArchive(wxInputStream& in, const wxString& unarchiver);
+ void VerifyDir(wxString& path, size_t rootlen = 0);
+
+ // tests for the iterators
+ void TestIterator(wxInputStream& in);
+ void TestPairIterator(wxInputStream& in);
+ void TestSmartIterator(wxInputStream& in);
+ void TestSmartPairIterator(wxInputStream& in);
+
+ // try reading two entries at the same time
+ void ReadSimultaneous(TestInputStream& in);
+
+ // overridables
+ virtual void OnCreateArchive(OutputStreamT& WXUNUSED(arc)) { }
+ virtual void OnSetNotifier(EntryT& entry);
+
+ virtual void OnArchiveExtracted(InputStreamT& WXUNUSED(arc),
+ int WXUNUSED(expectedTotal)) { }
+
+ virtual void OnCreateEntry( OutputStreamT& WXUNUSED(arc),
+ TestEntry& WXUNUSED(testEntry),
+ EntryT *entry = NULL) { (void)entry; }
+
+ virtual void OnEntryExtracted( EntryT& WXUNUSED(entry),
+ const TestEntry& WXUNUSED(testEntry),
+ InputStreamT *arc = NULL) { (void)arc; }
+
+ typedef std::map<wxString, TestEntry*> TestEntries;
+ TestEntries m_testEntries; // test data
+ std::auto_ptr<ClassFactoryT> m_factory; // factory to make classes
+ int m_options; // test options
+ wxDateTime m_timeStamp; // timestamp to give test entries
+ int m_id; // select between the possibilites
+ wxString m_archiver; // external archiver
+ wxString m_unarchiver; // external unarchiver
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Base class for the archive test suites
+
+class ArchiveTestSuite : public CppUnit::TestSuite
+{
+public:
+ ArchiveTestSuite(std::string name);
+
+protected:
+ int m_id;
+
+ virtual ArchiveTestSuite *makeSuite();
+
+ virtual CppUnit::Test *makeTest(std::string descr,
+ int id,
+ int options,
+ bool genericInterface,
+ const wxString& archiver,
+ const wxString& unarchiver);
+
+ void AddArchiver(const wxString& cmd) { AddCmd(m_archivers, cmd); }
+ void AddUnArchiver(const wxString &cmd) { AddCmd(m_unarchivers, cmd); }
+ bool IsInPath(const wxString& cmd);
+
+ std::string Description(const wxString& type,
+ int options,
+ bool genericInterface = false,
+ const wxString& archiver = wxEmptyString,
+ const wxString& unarchiver = wxEmptyString);
+
+private:
+ wxString m_name;
+ wxPathList m_path;
+ wxArrayString m_archivers;
+ wxArrayString m_unarchivers;
+
+ void AddCmd(wxArrayString& cmdlist, const wxString& cmd);
+};