wxWidgets/tests/archive/ziptest.cpp
Michael Wetherell 716e748b2f In the past some streams returned Eof() before the end was read past rather
after, and also some streams give an error instead of Eof(). Test the archive
streams work with parent streams that have any of these behaviours.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@36429 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2005-12-18 13:58:55 +00:00

273 lines
7.7 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// Name: tests/archive/ziptest.cpp
// Purpose: Test the zip classes
// Author: Mike Wetherell
// RCS-ID: $Id$
// Copyright: (c) 2004 Mike Wetherell
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#ifdef __BORLANDC__
# pragma hdrstop
#endif
#ifndef WX_PRECOMP
# include "wx/wx.h"
#endif
#if wxUSE_STREAMS && wxUSE_ZIPSTREAM
#include "archivetest.h"
#include "wx/zipstrm.h"
using std::string;
using std::auto_ptr;
///////////////////////////////////////////////////////////////////////////////
// ArchiveTestCase<wxZipClassFactory> could be used directly, but instead this
// derived class is used so that zip specific features can be tested.
class ZipTestCase : public ArchiveTestCase<wxZipClassFactory>
{
public:
ZipTestCase(string name,
int options,
const wxString& archiver = wxEmptyString,
const wxString& unarchiver = wxEmptyString)
:
ArchiveTestCase<wxZipClassFactory>(name, new wxZipClassFactory,
options, archiver, unarchiver),
m_count(0)
{ }
protected:
void OnCreateArchive(wxZipOutputStream& zip);
void OnArchiveExtracted(wxZipInputStream& zip, int expectedTotal);
void OnCreateEntry(wxZipOutputStream& zip,
TestEntry& testEntry,
wxZipEntry *entry);
void OnEntryExtracted(wxZipEntry& entry,
const TestEntry& testEntry,
wxZipInputStream *arc);
void OnSetNotifier(EntryT& entry);
int m_count;
wxString m_comment;
};
void ZipTestCase::OnCreateArchive(wxZipOutputStream& zip)
{
m_comment << _T("Comment for test ") << m_id;
zip.SetComment(m_comment);
}
void ZipTestCase::OnArchiveExtracted(wxZipInputStream& zip, int expectedTotal)
{
CPPUNIT_ASSERT(zip.GetComment() == m_comment);
CPPUNIT_ASSERT(zip.GetTotalEntries() == expectedTotal);
}
void ZipTestCase::OnCreateEntry(wxZipOutputStream& zip,
TestEntry& testEntry,
wxZipEntry *entry)
{
zip.SetLevel((m_id + m_count) % 10);
if (entry) {
switch ((m_id + m_count) % 5) {
case 0:
{
wxString comment = _T("Comment for ") + entry->GetName();
entry->SetComment(comment);
// lowercase the expected result, and the notifier should do
// the same for the zip entries when ModifyArchive() runs
testEntry.SetComment(comment.Lower());
break;
}
case 2:
entry->SetMethod(wxZIP_METHOD_STORE);
break;
case 4:
entry->SetMethod(wxZIP_METHOD_DEFLATE);
break;
}
entry->SetIsText(testEntry.IsText());
}
m_count++;
}
void ZipTestCase::OnEntryExtracted(wxZipEntry& entry,
const TestEntry& testEntry,
wxZipInputStream *arc)
{
// provide some context for the error message so that we know which
// iteration of the loop we were on
wxString name = _T(" '") + entry.GetName() + _T("'");
string error_entry(name.mb_str());
string error_context(" failed for entry" + error_entry);
CPPUNIT_ASSERT_MESSAGE("GetComment" + error_context,
entry.GetComment() == testEntry.GetComment());
// for seekable streams, GetNextEntry() doesn't read the local header so
// call OpenEntry() to do it
if (arc && (m_options & PipeIn) == 0 && entry.IsDir())
arc->OpenEntry(entry);
CPPUNIT_ASSERT_MESSAGE("IsText" + error_context,
entry.IsText() == testEntry.IsText());
CPPUNIT_ASSERT_MESSAGE("Extra/LocalExtra mismatch for entry" + error_entry,
(entry.GetExtraLen() != 0 && entry.GetLocalExtraLen() != 0) ||
(entry.GetExtraLen() == 0 && entry.GetLocalExtraLen() == 0));
}
// check the notifier mechanism by using it to fold the entry comments to
// lowercase
//
class ZipNotifier : public wxZipNotifier
{
public:
void OnEntryUpdated(wxZipEntry& entry);
};
void ZipNotifier::OnEntryUpdated(wxZipEntry& entry)
{
entry.SetComment(entry.GetComment().Lower());
}
void ZipTestCase::OnSetNotifier(EntryT& entry)
{
static ZipNotifier notifier;
entry.SetNotifier(notifier);
}
///////////////////////////////////////////////////////////////////////////////
// 'zip - -' produces local headers without the size field set. This is a
// case not covered by all the other tests, so this class tests it as a
// special case
class ZipPipeTestCase : public CppUnit::TestCase
{
public:
ZipPipeTestCase(string name, int options) :
CppUnit::TestCase(TestId::MakeId() + name),
m_options(options),
m_id(TestId::GetId())
{ }
protected:
void runTest();
int m_options;
int m_id;
};
void ZipPipeTestCase::runTest()
{
TestOutputStream out(m_options);
wxString testdata = _T("test data to pipe through zip");
wxString cmd = _T("echo ") + testdata + _T(" | zip -q - -");
{
PFileInputStream in(cmd);
if (in.Ok())
out.Write(in);
}
TestInputStream in(out, m_id % ((m_options & PipeIn) ? 4 : 3));
wxZipInputStream zip(in);
auto_ptr<wxZipEntry> entry(zip.GetNextEntry());
CPPUNIT_ASSERT(entry.get() != NULL);
if ((m_options & PipeIn) == 0)
CPPUNIT_ASSERT(entry->GetSize() != wxInvalidOffset);
char buf[64];
size_t len = zip.Read(buf, sizeof(buf) - 1).LastRead();
while (len > 0 && buf[len - 1] <= 32)
--len;
buf[len] = 0;
CPPUNIT_ASSERT(zip.Eof());
CPPUNIT_ASSERT(wxString(buf, *wxConvCurrent) == testdata);
}
///////////////////////////////////////////////////////////////////////////////
// Zip suite
class ziptest : public ArchiveTestSuite
{
public:
ziptest();
static CppUnit::Test *suite() { return (new ziptest)->makeSuite(); }
protected:
ArchiveTestSuite *makeSuite();
CppUnit::Test *makeTest(string descr, int options,
bool genericInterface, const wxString& archiver,
const wxString& unarchiver);
};
ziptest::ziptest()
: ArchiveTestSuite("zip")
{
AddArchiver(_T("zip -qr %s *"));
AddUnArchiver(_T("unzip -q %s"));
}
ArchiveTestSuite *ziptest::makeSuite()
{
ArchiveTestSuite::makeSuite();
#ifndef WXARC_NO_POPEN
// if have popen then can check the piped output of 'zip - -'
if (IsInPath(_T("zip")))
for (int options = 0; options <= PipeIn; options += PipeIn) {
string name = Description(_T("ZipPipeTestCase"), options,
false, _T(""), _T("zip -q - -"));
addTest(new ZipPipeTestCase(name, options));
}
#endif
return this;
}
CppUnit::Test *ziptest::makeTest(
string descr,
int options,
bool genericInterface,
const wxString& archiver,
const wxString& unarchiver)
{
// unzip doesn't support piping in the zip
if ((options & PipeIn) && !unarchiver.empty())
return NULL;
if (genericInterface)
return new ArchiveTestCase<wxArchiveClassFactory>(
descr, new wxZipClassFactory,
options, archiver, unarchiver);
else
return new ZipTestCase(descr, options, archiver, unarchiver);
}
CPPUNIT_TEST_SUITE_REGISTRATION(ziptest);
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(ziptest, "archive");
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(ziptest, "archive/zip");
#endif // wxUSE_STREAMS && wxUSE_ZIPSTREAM