// // See the file LICENSE for redistribution information. // // Copyright (c) 2002,2009 Oracle. All rights reserved. // // // Test program for XmlInputStream (unit tests for the class, plus some functional tests // System includes #include #include #include #include "string.h" // XQilla includes #include // Xerces includes #include #include #include // DB XML includes (external) #include "dbxml/DbXml.hpp" // test code includes #include "../util/TestLogging.hpp" // utility stuff for stream type manipulation namespace DbXmlInputStreamTest { enum StreamType { NONE, LOCALFILE, URL, MEMBUF, STDIN }; std::string typeToString(StreamType type) { std::string str("unknown"); switch(type) { case LOCALFILE: str.assign("Local File"); break; case URL: str.assign("URL"); break; case MEMBUF: str.assign("Memory Buffer"); break; case STDIN: str.assign("Standard Input"); break; default: break; } return str; } } using namespace DbXml; using namespace DbXmlTest; using namespace std; using namespace DbXmlInputStreamTest; void doTest(TestLogger &log, const std::string &testid, bool cdb, bool transacted, bool nodeLevelStorage, bool indexNodes, const std::string &path2DbEnv, StreamType type, const std::string &localFile, const std::string &baseId); void usage(const std::string &progname, int exitCode); int main(int argc, char **argv) { string testid; // arbitrary id for test (used for file names) bool transacted(false); // true iff a transacted environment is used bool cdb(false); // true iff a CDS environment is used bool nodeLevelStorage(false); // node level storage (whole docs otherwise) bool indexNodes(false); // use the DBXML_INDEX_NODES flag bool verifyLog(false); // true iff log file is to be verified string path2DbEnv; // path to DB XML env (must exist) string logDir("./"); // path to dir to contain log file StreamType streamType(NONE); // type of input stream string localFile; // path to an XML file string baseId; // baseId for URL int err(1); cout << "inputstreams" << endl; cerr << "inputstreams" << endl; for(int i=1; iremove(tenv, path2DbEnv.c_str(), 0); DB_ENV *env; (void) db_env_create(&env, 0); if (flags & DB_INIT_CDB) env->set_flags(env, DB_CDB_ALLDB, 1); int err = env->open(env, path2DbEnv.c_str(), flags, 0); if (err) { cerr << "Failed to open DB_ENV: " << err << endl; exit(-1); } XmlManager db(env, DBXML_ADOPT_DBENV); db.setDefaultContainerType(nodeLevelStorage ? XmlContainer::NodeContainer : XmlContainer::WholedocContainer); db.setDefaultContainerFlags(indexNodes ? DBXML_INDEX_NODES : DBXML_NO_INDEX_NODES); XmlTransaction *txn = 0; if(transacted) { txn = new XmlTransaction(db.createTransaction()); } XmlContainer *container = 0; string containerName = testid + ".dbxml"; if(transacted) { container = new XmlContainer(db.createContainer(*txn, containerName)); } else { container = new XmlContainer(db.createContainer(containerName)); } ostringstream os; os << "Created the container '" << container->getName() << "'"; os << " ("; switch (container->getContainerType()) { case XmlContainer::WholedocContainer: os << "whole document storage"; break; case XmlContainer::NodeContainer: os << "node level storage"; break; default: os << "unknown storage"; break; } os << ")"; TEST_MSG(log, os.str()); if(transacted) { txn->commit(); delete txn; } /////////////////////////////////////////////////////// switch(type) { case LOCALFILE: testLocalFile(log, transacted, db, container, localFile); break; case URL: testURL(log, transacted, db, container, baseId, localFile); break; case MEMBUF: testMemoryBuffer(log, transacted, db, container); break; case STDIN: TEST_MSG(log, "Tests for stdin streams TBD"); cerr << "Tests for stdin streams TBD" << endl; break; default: TEST_MSG(log, "No recognised stream type specified: %1") << type; cerr << "No recognised stream type specified: " << type << endl; break; } /////////////////////////////////////////////////////// // clean up delete container; TEST_MSG(log, "Completed test"); } void testLocalFile(TestLogger &log, bool transacted, XmlManager &db, XmlContainer *container, const std::string &localFile) { if(localFile.length() == 0) { ERROR_MSG(log, "No local file specified!"); return; } // basic manipulation of a stream XmlInputStream *xis = db.createLocalFileInputStream(localFile); TEST_MSG(log, "Created a stream on the file '%1'") << localFile; basicStreamManipulation(log, xis); delete xis; // load a document from the input stream { XmlInputStream *xis = db.createLocalFileInputStream(localFile); TEST_MSG(log, "Created a stream on the file '%1'") << localFile; XmlTransaction *txn = 0; if(transacted) { txn = new XmlTransaction(db.createTransaction()); } XmlUpdateContext uc = db.createUpdateContext(); loadDocument(log, xis, container, uc, *txn, transacted); if(transacted) { txn->commit(); delete txn; } // container has adopted stream to put document - do not delete here } { // fail case - file not existing is tested in Tcl code } // use the input stream to read a document { XmlInputStream *xis = db.createLocalFileInputStream(localFile); TEST_MSG(log, "Created a stream on the file '%1'") << localFile; streamDocument(log, xis, db); } } void testURL(TestLogger &log, bool transacted, XmlManager &db, XmlContainer *container, const std::string &baseId, const std::string &localFile) { if(localFile.length() == 0) { ERROR_MSG(log, "No local file specified!"); return; } if(baseId.length() == 0) { ERROR_MSG(log, "No baseId specified!"); return; } string systemId(localFile); // basic manipulation of a stream XmlInputStream *xis = db.createURLInputStream(baseId, systemId); TEST_MSG(log, "Created a stream using base ID '%1' and system ID '%2'") << baseId << systemId; basicStreamManipulation(log, xis); delete xis; // load a document from the input stream { XmlInputStream *xis = db.createURLInputStream(baseId, systemId); TEST_MSG(log, "Created a stream using base ID '%1' and system ID '%2'") << baseId << systemId; XmlTransaction *txn = 0; if(transacted) { txn = new XmlTransaction(db.createTransaction()); } XmlUpdateContext uc = db.createUpdateContext(); loadDocument(log, xis, container, uc, *txn, transacted); if(transacted) { txn->commit(); delete txn; } // container has adopted stream to put document - do not delete here } // use the input stream to read a document { XmlInputStream *xis = db.createURLInputStream(baseId, systemId); TEST_MSG(log, "Created a stream using base ID '%1' and system ID '%2'") << baseId << systemId; streamDocument(log, xis, db); } // TODO - use a public ID { // fail case - file not existing is tested in Tcl code } } void testMemoryBuffer(TestLogger &log, bool transacted, XmlManager &db, XmlContainer *container) { // basic manipulation of a stream const char *buf = "\ \ \ barfoobar \ \ "; const char *bufId = "TESTBUF"; bool adoptBuffer(false); XmlInputStream *xis = db.createMemBufInputStream(buf, (unsigned int)::strlen(buf), bufId, adoptBuffer); TEST_MSG(log, "Created a stream on a memory buffer of length %1") << (unsigned int)::strlen(buf); basicStreamManipulation(log, xis); delete xis; // load a document from the input stream { XmlInputStream *xis = db.createMemBufInputStream(buf, (unsigned int)::strlen(buf), bufId, adoptBuffer); TEST_MSG(log, "Created a stream on a memory buffer of length %1") << (unsigned int)::strlen(buf); XmlTransaction *txn = 0; if(transacted) { txn = new XmlTransaction(db.createTransaction()); } XmlUpdateContext uc = db.createUpdateContext(); loadDocument(log, xis, container, uc, *txn, transacted); if(transacted) { txn->commit(); delete txn; } // container has adopted stream to put document - do not delete here } // use the input stream to read a document { XmlInputStream *xis = db.createMemBufInputStream(buf, (unsigned int)::strlen(buf), bufId, adoptBuffer); TEST_MSG(log, "Created a stream on a memory buffer of length %1") << (unsigned int)::strlen(buf); streamDocument(log, xis, db); } } // basic manipulation of a stream - get position, read, get position void basicStreamManipulation(TestLogger &log, XmlInputStream *xis) { unsigned int pos = xis->curPos(); if(pos == 0) { TEST_MSG(log, "Initial position is 0"); } else { ERROR_MSG(log, "Initial position should be 0 but is %1") << pos; } char buf[1024]; unsigned int count = xis->readBytes(buf, 1023); if(count > 0) { TEST_MSG(log, "Read %1 bytes") << count; } else { ERROR_MSG(log, "Could not read from the stream"); } pos = xis->curPos(); if(pos > 0) { TEST_MSG(log, "Current position is %1") << pos; } else { ERROR_MSG(log, "Position still stuck at 0"); } } // use a stream to load a document into a container void loadDocument(TestLogger &log, XmlInputStream *xis, XmlContainer *container, XmlUpdateContext &uc, XmlTransaction &txn, bool transacted) { string name("mydoc"); string given_name; if(transacted) { given_name.assign(container->putDocument(txn, name, xis, uc)); } else { given_name.assign(container->putDocument(name, xis, uc)); } TEST_MSG(log, "Loaded document, given name is '%1'") << given_name; // sanity check XmlDocument *doc = 0; if(transacted) { doc = new XmlDocument(container->getDocument(txn, given_name)); } else { doc = new XmlDocument(container->getDocument(given_name)); } string buf; unsigned int len = (unsigned int)doc->getContent(buf).length(); TEST_MSG(log, "Got document, has string length of %1") << len; delete doc; } // stream a document directly void streamDocument(TestLogger &log, XmlInputStream *xis, XmlManager &db) { // stream content as an XmlData XmlDocument doc = db.createDocument(); doc.setName("foo"); doc.setContentAsXmlInputStream(xis); TEST_MSG(log, "Created a document and attached the input stream"); XmlData content = doc.getContent(); unsigned int count = (unsigned int)content.get_size(); if(count != 0) { TEST_MSG(log, "Streamed an XmlData object of size %1") << count; } else { ERROR_MSG(log, "Unable to stream document? XmlData is empty"); } if(count < 1024) { char buf[1024]; strncpy(buf, (char*)content.get_data(), count); buf[count] = '\0'; ostringstream os; os << "Content streamed is:\n" << buf << "\n"; TEST_MSG(log, os.str()); } else { WARNING_MSG(log, "Not looking at content - buffer too small"); } }