X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/716e748b2fe86beba88b390f4e6c81d2e268035a..0d1903dbda864780eec30efdc4e91776bdbfd21b:/tests/archive/archivetest.cpp diff --git a/tests/archive/archivetest.cpp b/tests/archive/archivetest.cpp index 379950a5d5..fa122d1f03 100644 --- a/tests/archive/archivetest.cpp +++ b/tests/archive/archivetest.cpp @@ -2,7 +2,6 @@ // Name: tests/archive/archive.cpp // Purpose: Test the archive classes // Author: Mike Wetherell -// RCS-ID: $Id$ // Copyright: (c) 2004 Mike Wetherell // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// @@ -51,9 +50,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 @@ -216,6 +212,8 @@ void TestInputStream::Rewind() m_wbacksize = 0; m_wbackcur = 0; } + + Reset(); } void TestInputStream::SetData(TestOutputStream& out) @@ -224,7 +222,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) @@ -268,10 +265,12 @@ size_t TestInputStream::OnSysRead(void *buffer, size_t 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; } @@ -332,7 +331,7 @@ private: TempDir::TempDir() { - wxString tmp = wxFileName::CreateTempFileName(_T("arctest-")); + wxString tmp = wxFileName::CreateTempFileName(wxT("arctest-")); if (!tmp.empty()) { wxRemoveFile(tmp); m_original = wxGetCwd(); @@ -353,26 +352,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(); @@ -385,7 +384,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()); + } } @@ -404,7 +405,7 @@ void TempDir::RemoveDir(wxString& path) # define WXARC_pclose(fp) #endif -#ifdef __WXMSW__ +#ifdef __WINDOWS__ # define WXARC_b "b" #else # define WXARC_b @@ -575,13 +576,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()) { @@ -608,7 +609,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, @@ -644,7 +645,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()); @@ -656,7 +657,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 @@ -666,16 +667,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); } @@ -684,8 +688,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); } } @@ -701,10 +705,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); @@ -716,7 +720,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) { @@ -791,7 +795,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); @@ -801,10 +805,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 @@ -815,7 +823,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()); @@ -875,7 +883,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) @@ -884,19 +892,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); } @@ -926,11 +938,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); @@ -941,7 +953,7 @@ void ArchiveTestCase::VerifyDir(wxString& path, const TestEntry& testEntry = *it->second; -#if 0 //ndef __WXMSW__ +#if 0 //ndef __WINDOWS__ CPPUNIT_ASSERT_MESSAGE("timestamp check" + error_context, testEntry.GetDateTime() == wxFileName(path).GetModificationTime()); @@ -949,7 +961,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); @@ -1109,8 +1121,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; @@ -1168,6 +1180,91 @@ 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 @@ -1177,7 +1274,7 @@ int TestId::m_seed = 6219; string TestId::MakeId() { m_seed = (m_seed * 171) % 30269; - return wxString::Format(_T("%-6d"), m_seed).mb_str(); + return string(wxString::Format(wxT("%-6d"), m_seed).mb_str()); } @@ -1188,10 +1285,10 @@ ArchiveTestSuite::ArchiveTestSuite(string name) : CppUnit::TestSuite("archive/" + name), 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 @@ -1205,9 +1302,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(); } @@ -1240,6 +1337,23 @@ ArchiveTestSuite *ArchiveTestSuite::makeSuite() addTest(test); } + 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; } @@ -1264,33 +1378,39 @@ string ArchiveTestSuite::Description(const wxString& type, wxString descr; 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()); } @@ -1304,4 +1424,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