X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/da865fdd325f7833246eecd665849b14f43e19d7..1ec4e9c2b72a01a7ba7da569e0f8d04a81aaba10:/tests/archive/archivetest.cpp?ds=sidebyside diff --git a/tests/archive/archivetest.cpp b/tests/archive/archivetest.cpp index 1e09053104..7e8262d0f8 100644 --- a/tests/archive/archivetest.cpp +++ b/tests/archive/archivetest.cpp @@ -42,7 +42,7 @@ using std::auto_ptr; (__GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)) # define WXARC_MEMBER_TEMPLATES #endif -#if defined _MSC_VER && _MSC_VER >= 1310 +#if defined _MSC_VER && _MSC_VER >= 1310 && !defined __WIN64__ # define WXARC_MEMBER_TEMPLATES #endif #if defined __BORLANDC__ && __BORLANDC__ >= 0x530 @@ -51,9 +51,6 @@ using std::auto_ptr; #if defined __DMC__ && __DMC__ >= 0x832 # define WXARC_MEMBER_TEMPLATES #endif -#if defined __MWERKS__ && __MWERKS__ >= 0x2200 -# define WXARC_MEMBER_TEMPLATES -#endif #if defined __HP_aCC && __HP_aCC > 33300 # define WXARC_MEMBER_TEMPLATES #endif @@ -196,7 +193,8 @@ TestInputStream::TestInputStream(const TestInputStream& in) : wxInputStream(), m_options(in.m_options), m_pos(in.m_pos), - m_size(in.m_size) + m_size(in.m_size), + m_eoftype(in.m_eoftype) { m_data = new char[m_size]; memcpy(m_data, in.m_data, m_size); @@ -215,6 +213,8 @@ void TestInputStream::Rewind() m_wbacksize = 0; m_wbackcur = 0; } + + Reset(); } void TestInputStream::SetData(TestOutputStream& out) @@ -223,7 +223,6 @@ void TestInputStream::SetData(TestOutputStream& out) m_options = out.GetOptions(); out.GetData(m_data, m_size); Rewind(); - Reset(); } wxFileOffset TestInputStream::OnSysSeek(wxFileOffset pos, wxSeekMode mode) @@ -251,16 +250,30 @@ size_t TestInputStream::OnSysRead(void *buffer, size_t size) { if (!IsOk() || !size) return 0; - if (m_size <= m_pos) { - m_lasterror = wxSTREAM_EOF; - return 0; + + size_t count; + + if (m_pos >= m_size) + count = 0; + else if (m_size - m_pos < size) + count = m_size - m_pos; + else + count = size; + + if (count) { + memcpy(buffer, m_data + m_pos, count); + m_pos += count; } - if (m_size - m_pos < size) - size = m_size - m_pos; - memcpy(buffer, m_data + m_pos, size); - m_pos += size; - return size; + if (((m_eoftype & AtLast) != 0 && m_pos >= m_size) || count < size) + { + if ((m_eoftype & WithError) != 0) + m_lasterror = wxSTREAM_READ_ERROR; + else + m_lasterror = wxSTREAM_EOF; + } + + return count; } @@ -319,7 +332,7 @@ private: TempDir::TempDir() { - wxString tmp = wxFileName::CreateTempFileName(_T("arctest-")); + wxString tmp = wxFileName::CreateTempFileName(wxT("arctest-")); if (!tmp.empty()) { wxRemoveFile(tmp); m_original = wxGetCwd(); @@ -340,26 +353,26 @@ TempDir::~TempDir() void TempDir::RemoveDir(wxString& path) { wxCHECK_RET(!m_tmp.empty() && path.substr(0, m_tmp.length()) == m_tmp, - _T("remove '") + path + _T("' fails safety check")); + wxT("remove '") + path + wxT("' fails safety check")); const wxChar *files[] = { - _T("text/empty"), - _T("text/small"), - _T("bin/bin1000"), - _T("bin/bin4095"), - _T("bin/bin4096"), - _T("bin/bin4097"), - _T("bin/bin16384"), - _T("zero/zero5"), - _T("zero/zero1024"), - _T("zero/zero32768"), - _T("zero/zero16385"), - _T("zero/newname"), - _T("newfile"), + wxT("text/empty"), + wxT("text/small"), + wxT("bin/bin1000"), + wxT("bin/bin4095"), + wxT("bin/bin4096"), + wxT("bin/bin4097"), + wxT("bin/bin16384"), + wxT("zero/zero5"), + wxT("zero/zero1024"), + wxT("zero/zero32768"), + wxT("zero/zero16385"), + wxT("zero/newname"), + wxT("newfile"), }; const wxChar *dirs[] = { - _T("text/"), _T("bin/"), _T("zero/"), _T("empty/") + wxT("text/"), wxT("bin/"), wxT("zero/"), wxT("empty/") }; wxString tmp = m_tmp + wxFileName::GetPathSeparator(); @@ -372,7 +385,9 @@ void TempDir::RemoveDir(wxString& path) wxRmdir(tmp + wxFileName(dirs[i], wxPATH_UNIX).GetFullPath()); if (!wxRmdir(m_tmp)) - wxLogSysError(_T("can't remove temporary dir '%s'"), m_tmp.c_str()); + { + wxLogSysError(wxT("can't remove temporary dir '%s'"), m_tmp.c_str()); + } } @@ -391,7 +406,7 @@ void TempDir::RemoveDir(wxString& path) # define WXARC_pclose(fp) #endif -#ifdef __WXMSW__ +#ifdef __WINDOWS__ # define WXARC_b "b" #else # define WXARC_b @@ -424,17 +439,16 @@ PFileOutputStream::~PFileOutputStream() template ArchiveTestCase::ArchiveTestCase( string name, - int id, ClassFactoryT *factory, int options, const wxString& archiver, const wxString& unarchiver) : - CppUnit::TestCase(name), + CppUnit::TestCase(TestId::MakeId() + name), m_factory(factory), m_options(options), m_timeStamp(1, wxDateTime::Mar, 2004, 12, 0), - m_id(id), + m_id(TestId::GetId()), m_archiver(archiver), m_unarchiver(unarchiver) { @@ -464,7 +478,7 @@ void ArchiveTestCase::runTest() // check archive could be created CPPUNIT_ASSERT(out.GetLength() > 0); - TestInputStream in(out); + TestInputStream in(out, m_id % ((m_options & PipeIn) ? 4 : 3)); TestIterator(in); in.Rewind(); @@ -563,13 +577,13 @@ void ArchiveTestCase::CreateArchive(wxOutputStream& out) // It should be possible to create a directory entry just by supplying // a name that looks like a directory, or alternatively any old name // can be identified as a directory using SetIsDir or PutNextDirEntry - bool setIsDir = name.Last() == _T('/') && (choices & 1); + bool setIsDir = name.Last() == wxT('/') && (choices & 1); if (setIsDir) name.erase(name.length() - 1); // provide some context for the error message so that we know which // iteration of the loop we were on - string error_entry((_T(" '") + name + _T("'")).mb_str()); + string error_entry((wxT(" '") + name + wxT("'")).mb_str()); string error_context(" failed for entry" + error_entry); if ((choices & 2) || testEntry.IsText()) { @@ -596,7 +610,7 @@ void ArchiveTestCase::CreateArchive(wxOutputStream& out) testEntry.GetLength())); } - if (it->first.Last() != _T('/')) { + if (it->first.Last() != wxT('/')) { // for non-dirs write the data arc->Write(testEntry.GetData(), testEntry.GetSize()); CPPUNIT_ASSERT_MESSAGE("LastWrite check" + error_context, @@ -632,7 +646,7 @@ void ArchiveTestCase::CreateArchive(wxOutputStream& out, TestEntry& entry = *i->second; if (fn.IsDir()) { - fn.Mkdir(0777, wxPATH_MKDIR_FULL); + wxFileName::Mkdir(fn.GetPath(), 0777, wxPATH_MKDIR_FULL); } else { wxFileName::Mkdir(fn.GetPath(), 0777, wxPATH_MKDIR_FULL); wxFFileOutputStream fileout(fn.GetFullPath()); @@ -644,7 +658,7 @@ void ArchiveTestCase::CreateArchive(wxOutputStream& out, wxFileName fn(i->first, wxPATH_UNIX); TestEntry& entry = *i->second; wxDateTime dt = entry.GetDateTime(); -#ifdef __WXMSW__ +#ifdef __WINDOWS__ if (fn.IsDir()) entry.SetDateTime(wxDateTime()); else @@ -654,16 +668,19 @@ void ArchiveTestCase::CreateArchive(wxOutputStream& out, if ((m_options & PipeOut) == 0) { wxFileName fn(tmpdir.GetName()); - fn.SetExt(_T("arc")); + fn.SetExt(wxT("arc")); wxString tmparc = fn.GetPath(wxPATH_GET_SEPARATOR) + fn.GetFullName(); // call the archiver to create an archive file - system(wxString::Format(archiver, tmparc.c_str()).mb_str()); + if ( system(wxString::Format(archiver, tmparc.c_str()).mb_str()) == -1 ) + { + wxLogError("Failed to run acrhiver command \"%s\"", archiver); + } // then load the archive file { wxFFileInputStream in(tmparc); - if (in.Ok()) + if (in.IsOk()) out.Write(in); } @@ -672,8 +689,8 @@ void ArchiveTestCase::CreateArchive(wxOutputStream& out, else { // for the non-seekable test, have the archiver output to "-" // and read the archive via a pipe - PFileInputStream in(wxString::Format(archiver, _T("-"))); - if (in.Ok()) + PFileInputStream in(wxString::Format(archiver, wxT("-"))); + if (in.IsOk()) out.Write(in); } } @@ -689,10 +706,10 @@ void ArchiveTestCase::ModifyArchive(wxInputStream& in, auto_ptr arcOut(m_factory->NewStream(out)); EntryT *pEntry; - const wxString deleteName = _T("bin/bin1000"); - const wxString renameFrom = _T("zero/zero1024"); - const wxString renameTo = _T("zero/newname"); - const wxString newName = _T("newfile"); + const wxString deleteName = wxT("bin/bin1000"); + const wxString renameFrom = wxT("zero/zero1024"); + const wxString renameTo = wxT("zero/newname"); + const wxString newName = wxT("newfile"); const char *newData = "New file added as a test\n"; arcOut->CopyArchiveMetaData(*arcIn); @@ -704,7 +721,7 @@ void ArchiveTestCase::ModifyArchive(wxInputStream& in, // provide some context for the error message so that we know which // iteration of the loop we were on - string error_entry((_T(" '") + name + _T("'")).mb_str()); + string error_entry((wxT(" '") + name + wxT("'")).mb_str()); string error_context(" failed for entry" + error_entry); if (name == deleteName) { @@ -779,7 +796,7 @@ void ArchiveTestCase::ExtractArchive(wxInputStream& in) // provide some context for the error message so that we know which // iteration of the loop we were on - string error_entry((_T(" '") + name + _T("'")).mb_str()); + string error_entry((wxT(" '") + name + wxT("'")).mb_str()); string error_context(" failed for entry" + error_entry); TestEntries::iterator it = m_testEntries.find(name); @@ -789,10 +806,14 @@ void ArchiveTestCase::ExtractArchive(wxInputStream& in) const TestEntry& testEntry = *it->second; +#ifndef __WINDOWS__ + // On Windows some archivers compensate for Windows DST handling, but + // other don't, so disable the test for now. wxDateTime dt = testEntry.GetDateTime(); if (dt.IsValid()) CPPUNIT_ASSERT_MESSAGE("timestamp check" + error_context, dt == entry->GetDateTime()); +#endif // non-seekable entries are allowed to have GetSize == wxInvalidOffset // until the end of the entry's data has been read past @@ -803,7 +824,7 @@ void ArchiveTestCase::ExtractArchive(wxInputStream& in) "arc->GetLength() == entry->GetSize()" + error_context, arc->GetLength() == entry->GetSize()); - if (name.Last() != _T('/')) + if (name.Last() != wxT('/')) { CPPUNIT_ASSERT_MESSAGE("!IsDir" + error_context, !entry->IsDir()); @@ -863,7 +884,7 @@ void ArchiveTestCase::ExtractArchive(wxInputStream& in, if ((m_options & PipeIn) == 0) { wxFileName fn(tmpdir.GetName()); - fn.SetExt(_T("arc")); + fn.SetExt(wxT("arc")); wxString tmparc = fn.GetPath(wxPATH_GET_SEPARATOR) + fn.GetFullName(); if (m_options & Stub) @@ -872,19 +893,23 @@ void ArchiveTestCase::ExtractArchive(wxInputStream& in, // write the archive to a temporary file { wxFFileOutputStream out(tmparc); - if (out.Ok()) + if (out.IsOk()) out.Write(in); } // call unarchiver - system(wxString::Format(unarchiver, tmparc.c_str()).mb_str()); + if ( system(wxString::Format(unarchiver, tmparc.c_str()).mb_str()) == -1 ) + { + wxLogError("Failed to run unarchiver command \"%s\"", unarchiver); + } + wxRemoveFile(tmparc); } else { // for the non-seekable test, have the archiver extract "-" and // feed it the archive via a pipe - PFileOutputStream out(wxString::Format(unarchiver, _T("-"))); - if (out.Ok()) + PFileOutputStream out(wxString::Format(unarchiver, wxT("-"))); + if (out.IsOk()) out.Write(in); } @@ -914,11 +939,11 @@ void ArchiveTestCase::VerifyDir(wxString& path, bool isDir = wxDirExists(path); if (isDir) - name += _T("/"); + name += wxT("/"); // provide some context for the error message so that we know which // iteration of the loop we were on - string error_entry((_T(" '") + name + _T("'")).mb_str()); + string error_entry((wxT(" '") + name + wxT("'")).mb_str()); string error_context(" failed for entry" + error_entry); TestEntries::iterator it = m_testEntries.find(name); @@ -929,7 +954,7 @@ void ArchiveTestCase::VerifyDir(wxString& path, const TestEntry& testEntry = *it->second; -#ifndef __WXMSW__ +#if 0 //ndef __WINDOWS__ CPPUNIT_ASSERT_MESSAGE("timestamp check" + error_context, testEntry.GetDateTime() == wxFileName(path).GetModificationTime()); @@ -937,7 +962,7 @@ void ArchiveTestCase::VerifyDir(wxString& path, if (!isDir) { wxFFileInputStream in(path); CPPUNIT_ASSERT_MESSAGE( - "entry not found in archive" + error_entry, in.Ok()); + "entry not found in archive" + error_entry, in.IsOk()); size_t size = (size_t)in.GetLength(); wxCharBuffer buf(size); @@ -1097,8 +1122,8 @@ void ArchiveTestCase::ReadSimultaneous(TestInputStream& in) #endif // the names of two entries to read - const wxChar *name = _T("text/small"); - const wxChar *name2 = _T("bin/bin1000"); + const wxChar *name = wxT("text/small"); + const wxChar *name2 = wxT("bin/bin1000"); // open them typename ArchiveCatalog::iterator j; @@ -1156,18 +1181,115 @@ void ArchiveTestCase::OnSetNotifier(EntryT& entry) } +/////////////////////////////////////////////////////////////////////////////// +// An additional case to check that reading corrupt archives doesn't crash + +class CorruptionTestCase : public CppUnit::TestCase +{ +public: + CorruptionTestCase(std::string name, + wxArchiveClassFactory *factory, + int options) + : CppUnit::TestCase(TestId::MakeId() + name), + m_factory(factory), + m_options(options) + { } + +protected: + // the entry point for the test + void runTest(); + + void CreateArchive(wxOutputStream& out); + void ExtractArchive(wxInputStream& in); + + auto_ptr m_factory; // factory to make classes + int m_options; // test options +}; + +void CorruptionTestCase::runTest() +{ + TestOutputStream out(m_options); + CreateArchive(out); + TestInputStream in(out, 0); + wxFileOffset len = in.GetLength(); + + // try flipping one byte in the archive + int pos; + for (pos = 0; pos < len; pos++) { + char n = in[pos]; + in[pos] = ~n; + ExtractArchive(in); + in.Rewind(); + in[pos] = n; + } + + // try zeroing one byte in the archive + for (pos = 0; pos < len; pos++) { + char n = in[pos]; + in[pos] = 0; + ExtractArchive(in); + in.Rewind(); + in[pos] = n; + } + + // try chopping the archive off + for (int size = 1; size <= len; size++) { + in.Chop(size); + ExtractArchive(in); + in.Rewind(); + } +} + +void CorruptionTestCase::CreateArchive(wxOutputStream& out) +{ + auto_ptr arc(m_factory->NewStream(out)); + + arc->PutNextDirEntry(wxT("dir")); + arc->PutNextEntry(wxT("file")); + arc->Write(wxT("foo"), 3); +} + +void CorruptionTestCase::ExtractArchive(wxInputStream& in) +{ + auto_ptr arc(m_factory->NewStream(in)); + auto_ptr entry(arc->GetNextEntry()); + + while (entry.get() != NULL) { + char buf[1024]; + + while (arc->IsOk()) + arc->Read(buf, sizeof(buf)); + + auto_ptr next(arc->GetNextEntry()); + entry = next; + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// Make the ids + +int TestId::m_seed = 6219; + +// static +string TestId::MakeId() +{ + m_seed = (m_seed * 171) % 30269; + return string(wxString::Format(wxT("%-6d"), m_seed).mb_str()); +} + + /////////////////////////////////////////////////////////////////////////////// // Suite base ArchiveTestSuite::ArchiveTestSuite(string name) : CppUnit::TestSuite("archive/" + name), - m_id(0), m_name(name.c_str(), *wxConvCurrent) { - m_name = _T("wx") + m_name.Left(1).Upper() + m_name.Mid(1).Lower(); - m_path.AddEnvList(_T("PATH")); - m_archivers.push_back(_T("")); - m_unarchivers.push_back(_T("")); + m_name = wxT("wx") + m_name.Left(1).Upper() + m_name.Mid(1).Lower(); + m_path.AddEnvList(wxT("PATH")); + m_archivers.push_back(wxT("")); + m_unarchivers.push_back(wxT("")); } // add the command for an external archiver to the list, testing for it in @@ -1181,9 +1303,9 @@ void ArchiveTestSuite::AddCmd(wxArrayString& cmdlist, const wxString& cmd) bool ArchiveTestSuite::IsInPath(const wxString& cmd) { - wxString c = cmd.BeforeFirst(_T(' ')); -#ifdef __WXMSW__ - c += _T(".exe"); + wxString c = cmd.BeforeFirst(wxT(' ')); +#ifdef __WINDOWS__ + c += wxT(".exe"); #endif return !m_path.FindValidPath(c).empty(); } @@ -1209,21 +1331,35 @@ ArchiveTestSuite *ArchiveTestSuite::makeSuite() string descr = Description(m_name, options, generic != 0, *j, *i); - CppUnit::Test *test = makeTest(descr, m_id, options, + CppUnit::Test *test = makeTest(descr, options, generic != 0, *j, *i); - if (test) { + if (test) addTest(test); - m_id++; - } } + for (int options = 0; options <= PipeIn; options += PipeIn) + { + wxObject *pObj = wxCreateDynamicObject(m_name + wxT("ClassFactory")); + wxArchiveClassFactory *factory; + factory = wxDynamicCast(pObj, wxArchiveClassFactory); + + if (factory) { + string descr(m_name.mb_str()); + descr = "CorruptionTestCase (" + descr + ")"; + + if (options) + descr += " (PipeIn)"; + + addTest(new CorruptionTestCase(descr, factory, options)); + } + } + return this; } CppUnit::Test *ArchiveTestSuite::makeTest( string WXUNUSED(descr), - int WXUNUSED(id), int WXUNUSED(options), bool WXUNUSED(genericInterface), const wxString& WXUNUSED(archiver), @@ -1241,36 +1377,41 @@ string ArchiveTestSuite::Description(const wxString& type, const wxString& unarchiver) { wxString descr; - descr << m_id << _T(" "); if (genericInterface) - descr << _T("wxArchive (") << type << _T(")"); + descr << wxT("wxArchive (") << type << wxT(")"); else descr << type; if (!archiver.empty()) { - const wxChar *fn = (options & PipeOut) != 0 ? _T("-") : _T("file"); - descr << _T(" (") << wxString::Format(archiver, fn) << _T(")"); + const wxChar *fn = (options & PipeOut) != 0 ? wxT("-") : wxT("file"); + const wxString cmd = archiver.Contains("%s") + ? wxString::Format(archiver, fn) + : archiver; + descr << wxT(" (") << cmd << wxT(")"); } if (!unarchiver.empty()) { - const wxChar *fn = (options & PipeIn) != 0 ? _T("-") : _T("file"); - descr << _T(" (") << wxString::Format(unarchiver, fn) << _T(")"); + const wxChar *fn = (options & PipeIn) != 0 ? wxT("-") : wxT("file"); + const wxString cmd = unarchiver.Contains("%s") + ? wxString::Format(unarchiver, fn) + : unarchiver; + descr << wxT(" (") << cmd << wxT(")"); } wxString optstr; if ((options & PipeIn) != 0) - optstr += _T("|PipeIn"); + optstr += wxT("|PipeIn"); if ((options & PipeOut) != 0) - optstr += _T("|PipeOut"); + optstr += wxT("|PipeOut"); if ((options & Stub) != 0) - optstr += _T("|Stub"); + optstr += wxT("|Stub"); if (!optstr.empty()) - optstr = _T(" (") + optstr.substr(1) + _T(")"); + optstr = wxT(" (") + optstr.substr(1) + wxT(")"); descr << optstr; - return (const char*)descr.mb_str(); + return string(descr.mb_str()); } @@ -1284,4 +1425,9 @@ template class ArchiveTestCase; template class ArchiveTestCase; #endif +#if wxUSE_TARSTREAM +#include "wx/tarstrm.h" +template class ArchiveTestCase; +#endif + #endif // wxUSE_STREAMS && wxUSE_ARCHIVE_STREAMS