forked from 0ad/0ad
# More XML stuff
Added some tests for Xeromyces. Refactored it a bit to make it testable. This was SVN commit r6768.
This commit is contained in:
parent
2bc48fc1e7
commit
fd20cda5b6
@ -14,7 +14,7 @@ const char* UnfinishedHeaderMagicStr = "XMBu";
|
||||
bool XMBFile::Initialise(const char* FileData)
|
||||
{
|
||||
m_Pointer = FileData;
|
||||
char Header[5];
|
||||
char Header[5] = { 0 };
|
||||
strncpy_s(Header, 5, m_Pointer, 4);
|
||||
m_Pointer += 4;
|
||||
// (c.f. @return documentation of this function)
|
||||
|
@ -165,8 +165,8 @@ PSRETURN CXeromyces::Load(const VfsPath& filename)
|
||||
// zeroed because zip files only have 2 second resolution.
|
||||
const int suffixLength = 22;
|
||||
char suffix[suffixLength+1];
|
||||
int ret = sprintf(suffix, "_%08x%08xB.xmb", (int)(fileInfo.MTime() & ~1), (int)fileInfo.Size());
|
||||
debug_assert(ret == suffixLength);
|
||||
int printed = sprintf(suffix, "_%08x%08xB.xmb", (int)(fileInfo.MTime() & ~1), (int)fileInfo.Size());
|
||||
debug_assert(printed == suffixLength);
|
||||
VfsPath xmbFilename = change_extension(filename, suffix);
|
||||
|
||||
VfsPath xmbPath;
|
||||
@ -199,12 +199,35 @@ PSRETURN CXeromyces::Load(const VfsPath& filename)
|
||||
return PSRETURN_Xeromyces_XMLOpenFailed;
|
||||
}
|
||||
|
||||
WriteBuffer writeBuffer;
|
||||
PSRETURN ret = ConvertXMLtoXMB(filename.string().c_str(), source, writeBuffer);
|
||||
if (ret)
|
||||
{
|
||||
if (ret == PSRETURN_Xeromyces_XMLParseError)
|
||||
LOG(CLogger::Error, LOG_CATEGORY, "CXeromyces: Errors in XML file '%s'", filename.string().c_str());
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Save the file to disk, so it can be loaded quickly next time
|
||||
g_VFS->CreateFile(xmbPath, writeBuffer.Data(), writeBuffer.Size());
|
||||
|
||||
XMBBuffer = writeBuffer.Data(); // add a reference
|
||||
|
||||
// Set up the XMBFile
|
||||
const bool ok = Initialise((const char*)XMBBuffer.get());
|
||||
debug_assert(ok);
|
||||
|
||||
return PSRETURN_OK;
|
||||
}
|
||||
|
||||
// Reads from source, returns output in writeBuffer
|
||||
PSRETURN CXeromyces::ConvertXMLtoXMB(const char* filename, InputSource& source, WriteBuffer& writeBuffer)
|
||||
{
|
||||
// Set up the Xerces parser
|
||||
SAX2XMLReader* Parser = XMLReaderFactory::createXMLReader();
|
||||
|
||||
// Enable validation
|
||||
Parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
|
||||
Parser->setFeature(XMLUni::fgXercesDynamic, true);
|
||||
// Disable DTDs
|
||||
Parser->setFeature(XMLUni::fgXercesLoadExternalDTD, false);
|
||||
|
||||
XeroHandler handler;
|
||||
Parser->setContentHandler(&handler);
|
||||
@ -212,7 +235,7 @@ PSRETURN CXeromyces::Load(const VfsPath& filename)
|
||||
CXercesErrorHandler errorHandler;
|
||||
Parser->setErrorHandler(&errorHandler);
|
||||
|
||||
CVFSEntityResolver entityResolver(filename.string().c_str());
|
||||
CVFSEntityResolver entityResolver(filename);
|
||||
Parser->setEntityResolver(&entityResolver);
|
||||
|
||||
// Build a tree inside handler
|
||||
@ -227,24 +250,14 @@ PSRETURN CXeromyces::Load(const VfsPath& filename)
|
||||
delete Parser;
|
||||
|
||||
if (errorHandler.GetSawErrors())
|
||||
{
|
||||
LOG(CLogger::Error, LOG_CATEGORY, "CXeromyces: Errors in XML file '%s'", filename.string().c_str());
|
||||
return PSRETURN_Xeromyces_XMLParseError;
|
||||
// The internal tree of the XeroHandler will be cleaned up automatically
|
||||
}
|
||||
|
||||
// Convert the data structures into the XMB format
|
||||
handler.CreateXMB();
|
||||
|
||||
// Save the file to disk, so it can be loaded quickly next time
|
||||
WriteBuffer& writeBuffer = handler.writeBuffer;
|
||||
g_VFS->CreateFile(xmbPath, writeBuffer.Data(), writeBuffer.Size());
|
||||
|
||||
XMBBuffer = writeBuffer.Data(); // add a reference
|
||||
|
||||
// Set up the XMBFile
|
||||
const bool ok = Initialise((const char*)XMBBuffer.get());
|
||||
debug_assert(ok);
|
||||
// Copy the (refcounted) buffer into the output parameter
|
||||
writeBuffer = handler.writeBuffer;
|
||||
|
||||
return PSRETURN_OK;
|
||||
}
|
||||
|
@ -15,9 +15,12 @@ ERROR_TYPE(Xeromyces, XMLParseError);
|
||||
#include "XeroXMB.h"
|
||||
#include "ps/Filesystem.h"
|
||||
|
||||
#include "XML.h" // XXX remove this
|
||||
|
||||
class CXeromyces : public XMBFile
|
||||
{
|
||||
friend class TestXeromyces;
|
||||
friend class TestXeroXMB;
|
||||
public:
|
||||
CXeromyces();
|
||||
~CXeromyces();
|
||||
@ -35,6 +38,8 @@ private:
|
||||
|
||||
bool ReadXMBFile(const VfsPath& filename);
|
||||
|
||||
static PSRETURN ConvertXMLtoXMB(const char* filename, InputSource& source, WriteBuffer& writeBuffer); // XXX remove filename
|
||||
|
||||
shared_ptr<u8> XMBBuffer;
|
||||
|
||||
static int XercesLoaded; // for once-only initialisation
|
||||
|
76
source/ps/XML/tests/test_XeroXMB.h
Normal file
76
source/ps/XML/tests/test_XeroXMB.h
Normal file
@ -0,0 +1,76 @@
|
||||
#include "lib/self_test.h"
|
||||
|
||||
#include "ps/XML/Xeromyces.h"
|
||||
|
||||
#include <xercesc/framework/MemBufInputSource.hpp>
|
||||
|
||||
XERCES_CPP_NAMESPACE_USE
|
||||
|
||||
class TestXeroXMB : public CxxTest::TestSuite
|
||||
{
|
||||
private:
|
||||
shared_ptr<u8> m_Buffer;
|
||||
|
||||
XMBFile parse(const char* doc)
|
||||
{
|
||||
XMLPlatformUtils::Initialize();
|
||||
MemBufInputSource source((const XMLByte*)doc, strlen(doc), "null");
|
||||
WriteBuffer buffer;
|
||||
PSRETURN ret = CXeromyces::ConvertXMLtoXMB("/dev/null", source, buffer);
|
||||
TS_ASSERT_EQUALS(ret, PSRETURN_OK);
|
||||
|
||||
XMBFile xmb;
|
||||
m_Buffer = buffer.Data(); // hold a reference
|
||||
TS_ASSERT(xmb.Initialise((const char*)m_Buffer.get()));
|
||||
return xmb;
|
||||
}
|
||||
|
||||
public:
|
||||
void test_basic()
|
||||
{
|
||||
XMBFile xmb (parse("<test>\n<foo x=' y '> bar </foo>\n</test>"));
|
||||
|
||||
TS_ASSERT_DIFFERS(xmb.GetElementID("test"), -1);
|
||||
TS_ASSERT_DIFFERS(xmb.GetElementID("foo"), -1);
|
||||
TS_ASSERT_EQUALS(xmb.GetElementID("bar"), -1);
|
||||
|
||||
TS_ASSERT_DIFFERS(xmb.GetAttributeID("x"), -1);
|
||||
TS_ASSERT_EQUALS(xmb.GetAttributeID("y"), -1);
|
||||
TS_ASSERT_EQUALS(xmb.GetAttributeID("test"), -1);
|
||||
|
||||
int el_test = xmb.GetElementID("test");
|
||||
int el_foo = xmb.GetElementID("foo");
|
||||
int at_x = xmb.GetAttributeID("x");
|
||||
|
||||
XMBElement root = xmb.GetRoot();
|
||||
TS_ASSERT_EQUALS(root.GetNodeName(), el_test);
|
||||
// TS_ASSERT_EQUALS(root.GetLineNumber(), 1);
|
||||
TS_ASSERT_EQUALS(CStr(root.GetText()), "");
|
||||
|
||||
TS_ASSERT_EQUALS(root.GetChildNodes().Count, 1);
|
||||
XMBElement child = root.GetChildNodes().Item(0);
|
||||
TS_ASSERT_EQUALS(child.GetNodeName(), el_foo);
|
||||
// TS_ASSERT_EQUALS(child.GetLineNumber(), 2);
|
||||
TS_ASSERT_EQUALS(child.GetChildNodes().Count, 0);
|
||||
TS_ASSERT_EQUALS(CStr(child.GetText()), "bar");
|
||||
|
||||
TS_ASSERT_EQUALS(child.GetAttributes().Count, 1);
|
||||
XMBAttribute attr = child.GetAttributes().Item(0);
|
||||
TS_ASSERT_EQUALS(attr.Name, at_x);
|
||||
TS_ASSERT_EQUALS(CStr(attr.Value), " y ");
|
||||
}
|
||||
|
||||
void test_doctype_ignored()
|
||||
{
|
||||
XMBFile xmb (parse("<!DOCTYPE foo SYSTEM \"file:///dev/urandom\"><foo/>"));
|
||||
|
||||
TS_ASSERT_DIFFERS(xmb.GetElementID("foo"), -1);
|
||||
}
|
||||
|
||||
void test_complex_parse()
|
||||
{
|
||||
XMBFile xmb (parse("<test>\t\n \tx <>&"'<![CDATA[foo]]>bar\n<x/>\nbaz<?cheese?>qux</test>"));
|
||||
TS_ASSERT_EQUALS(CStr(xmb.GetRoot().GetText()), "x <>&\"'foobar\n\nbazqux");
|
||||
}
|
||||
|
||||
};
|
@ -93,6 +93,14 @@ public:
|
||||
"<foo>abcde&f<g>h\"i'j</foo>\n"
|
||||
);
|
||||
}
|
||||
void test_parse_doctype()
|
||||
{
|
||||
try_parse_save(
|
||||
"<!DOCTYPE foo SYSTEM \"file:///dev/urandom\"><foo/>",
|
||||
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
|
||||
"<foo/>\n"
|
||||
);
|
||||
}
|
||||
void test_parse_ignored()
|
||||
{
|
||||
try_parse_save(
|
||||
|
Loading…
Reference in New Issue
Block a user