aboutsummaryrefslogtreecommitdiffstats
path: root/document/src/tests/fieldsettest.cpp
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@yahoo-inc.com>2016-06-15 23:09:44 +0200
committerJon Bratseth <bratseth@yahoo-inc.com>2016-06-15 23:09:44 +0200
commit72231250ed81e10d66bfe70701e64fa5fe50f712 (patch)
tree2728bba1131a6f6e5bdf95afec7d7ff9358dac50 /document/src/tests/fieldsettest.cpp
Publish
Diffstat (limited to 'document/src/tests/fieldsettest.cpp')
-rw-r--r--document/src/tests/fieldsettest.cpp348
1 files changed, 348 insertions, 0 deletions
diff --git a/document/src/tests/fieldsettest.cpp b/document/src/tests/fieldsettest.cpp
new file mode 100644
index 00000000000..41a530c4b17
--- /dev/null
+++ b/document/src/tests/fieldsettest.cpp
@@ -0,0 +1,348 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include <vespa/fastos/fastos.h>
+#include <vespa/document/base/testdocman.h>
+#include <vespa/document/fieldset/fieldsetrepo.h>
+#include <vespa/document/fieldvalue/fieldvalues.h>
+#include <vespa/vespalib/io/fileutil.h>
+#include <vespa/vdstestlib/cppunit/macros.h>
+
+#include <vespa/document/annotation/spantree.h>
+#include <vespa/document/config/config-documenttypes.h>
+#include <vespa/document/datatype/annotationreferencedatatype.h>
+#include <vespa/document/repo/configbuilder.h>
+#include <vespa/document/repo/documenttyperepo.h>
+#include <vespa/vespalib/objects/nbostream.h>
+#include <fstream>
+
+using vespalib::nbostream;
+
+using namespace document::config_builder;
+
+namespace document {
+
+struct FieldSetTest : public CppUnit::TestFixture {
+ void testParsing();
+ void testContains();
+ void testCopyDocumentFields();
+ void testDocumentSubsetCopy();
+ void testStripFields();
+ void testSerialize();
+
+ CPPUNIT_TEST_SUITE(FieldSetTest);
+ CPPUNIT_TEST(testParsing);
+ CPPUNIT_TEST(testSerialize);
+ CPPUNIT_TEST(testContains);
+ CPPUNIT_TEST(testCopyDocumentFields);
+ CPPUNIT_TEST(testDocumentSubsetCopy);
+ CPPUNIT_TEST(testStripFields);
+ CPPUNIT_TEST_SUITE_END();
+
+ std::string stringifyFields(const Document& doc) const;
+ std::string doCopyFields(const Document& src,
+ const DocumentTypeRepo& docRepo,
+ const std::string& fieldSetStr,
+ Document* dest = 0) const;
+ std::string doCopyDocument(const Document& src,
+ const DocumentTypeRepo& docRepo,
+ const std::string& fieldSetStr);
+ std::string doStripFields(const Document& doc,
+ const DocumentTypeRepo& docRepo,
+ const std::string& fieldSetStr);
+ Document::UP createTestDocument(const TestDocMan& testDocMan) const;
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(FieldSetTest);
+
+void FieldSetTest::testParsing()
+{
+ TestDocMan testDocMan;
+ const DocumentTypeRepo& docRepo = testDocMan.getTypeRepo();
+
+ FieldSetRepo repo;
+
+ dynamic_cast<AllFields&>(*repo.parse(docRepo, "[all]"));
+ dynamic_cast<NoFields&>(*repo.parse(docRepo, "[none]"));
+ dynamic_cast<DocIdOnly&>(*repo.parse(docRepo, "[id]"));
+ dynamic_cast<HeaderFields&>(*repo.parse(docRepo, "[header]"));
+ dynamic_cast<BodyFields&>(*repo.parse(docRepo, "[body]"));
+
+ FieldSet::UP set = repo.parse(docRepo, "testdoctype1:headerval,content");
+ FieldCollection& coll = dynamic_cast<FieldCollection&>(*set);
+
+ std::ostringstream ost;
+ for (Field::Set::const_iterator iter = coll.getFields().begin();
+ iter != coll.getFields().end();
+ ++iter) {
+ ost << (*iter)->getName() << " ";
+ }
+
+ CPPUNIT_ASSERT_EQUAL(std::string("content headerval "), ost.str());
+}
+
+namespace {
+
+bool checkContains(FieldSetRepo& r, const DocumentTypeRepo& repo,
+ const std::string& str1, const std::string str2) {
+ FieldSet::UP set1 = r.parse(repo, str1);
+ FieldSet::UP set2 = r.parse(repo, str2);
+
+ return set1->contains(*set2);
+}
+
+bool checkError(FieldSetRepo& r, const DocumentTypeRepo& repo,
+ const std::string& str) {
+ try {
+ r.parse(repo, str);
+ return false;
+ } catch (...) {
+ return true;
+ }
+}
+
+}
+
+void FieldSetTest::testContains()
+{
+ TestDocMan testDocMan;
+ const DocumentTypeRepo& repo = testDocMan.getTypeRepo();
+ const DocumentType& type = *repo.getDocumentType("testdoctype1");
+
+ const Field& headerField = type.getField("headerval");
+ const Field& bodyField = type.getField("content");
+
+ NoFields none;
+ AllFields all;
+ DocIdOnly id;
+ HeaderFields h;
+ BodyFields b;
+
+ CPPUNIT_ASSERT_EQUAL(false, headerField.contains(
+ type.getField("headerlongval")));
+ CPPUNIT_ASSERT_EQUAL(true, headerField.contains(headerField));
+ CPPUNIT_ASSERT_EQUAL(true, headerField.contains(id));
+ CPPUNIT_ASSERT_EQUAL(false, headerField.contains(all));
+ CPPUNIT_ASSERT_EQUAL(true, headerField.contains(none));
+ CPPUNIT_ASSERT_EQUAL(false, none.contains(headerField));
+ CPPUNIT_ASSERT_EQUAL(true, all.contains(headerField));
+ CPPUNIT_ASSERT_EQUAL(true, all.contains(none));
+ CPPUNIT_ASSERT_EQUAL(false, none.contains(all));
+ CPPUNIT_ASSERT_EQUAL(true, all.contains(id));
+ CPPUNIT_ASSERT_EQUAL(false, none.contains(id));
+ CPPUNIT_ASSERT_EQUAL(true, id.contains(none));
+
+ CPPUNIT_ASSERT_EQUAL(true, h.contains(headerField));
+ CPPUNIT_ASSERT_EQUAL(false, h.contains(bodyField));
+
+ CPPUNIT_ASSERT_EQUAL(false, b.contains(headerField));
+ CPPUNIT_ASSERT_EQUAL(true, b.contains(bodyField));
+
+ FieldSetRepo r;
+ CPPUNIT_ASSERT_EQUAL(true, checkContains(r, repo, "[body]",
+ "testdoctype1:content"));
+ CPPUNIT_ASSERT_EQUAL(false, checkContains(r, repo, "[header]",
+ "testdoctype1:content"));
+ CPPUNIT_ASSERT_EQUAL(true, checkContains(r, repo,
+ "testdoctype1:content,headerval",
+ "testdoctype1:content"));
+ CPPUNIT_ASSERT_EQUAL(false, checkContains(r, repo,
+ "testdoctype1:content",
+ "testdoctype1:content,headerval"));
+ CPPUNIT_ASSERT_EQUAL(true, checkContains(r, repo,
+ "testdoctype1:headerval,content",
+ "testdoctype1:content,headerval"));
+
+ CPPUNIT_ASSERT(checkError(r, repo, "nodoctype"));
+ CPPUNIT_ASSERT(checkError(r, repo, "unknowndoctype:foo"));
+ CPPUNIT_ASSERT(checkError(r, repo, "testdoctype1:unknownfield"));
+ CPPUNIT_ASSERT(checkError(r, repo, "[badid]"));
+}
+
+std::string
+FieldSetTest::stringifyFields(const Document& doc) const
+{
+ std::vector<std::string> output;
+ const StructFieldValue& fields(doc.getFields());
+ for (StructFieldValue::const_iterator
+ it(fields.begin()), e(fields.end());
+ it != e; ++it)
+ {
+ std::ostringstream ss;
+ const Field& f(it.field());
+ ss << f.getName() << ": ";
+ FieldValue::UP val(fields.getValue(f));
+ if (val.get()) {
+ ss << val->toString();
+ } else {
+ ss << "(null)";
+ }
+ output.push_back(ss.str());
+ }
+ std::ostringstream ret;
+ std::sort(output.begin(), output.end());
+ std::copy(output.begin(), output.end(),
+ std::ostream_iterator<std::string>(ret, "\n"));
+ return ret.str();
+}
+
+std::string
+FieldSetTest::doCopyFields(const Document& src,
+ const DocumentTypeRepo& docRepo,
+ const std::string& fieldSetStr,
+ Document* dest) const
+{
+ Document destDoc(src.getType(), DocumentId("doc:test:fieldsdest"));
+ if (!dest) {
+ dest = &destDoc;
+ }
+ FieldSetRepo repo;
+ FieldSet::UP fset = repo.parse(docRepo, fieldSetStr);
+ FieldSet::copyFields(*dest, src, *fset);
+ return stringifyFields(*dest);
+}
+
+std::string
+FieldSetTest::doStripFields(const Document& doc,
+ const DocumentTypeRepo& docRepo,
+ const std::string& fieldSetStr)
+{
+ Document::UP copy(doc.clone());
+ FieldSetRepo repo;
+ FieldSet::UP fset = repo.parse(docRepo, fieldSetStr);
+ FieldSet::stripFields(*copy, *fset);
+ return stringifyFields(*copy);
+}
+
+Document::UP
+FieldSetTest::createTestDocument(const TestDocMan& testDocMan) const
+{
+ Document::UP doc(testDocMan.createDocument("megafoo megabar",
+ "doc:test:fieldssrc",
+ "testdoctype1"));
+ doc->setValue(doc->getField("headerval"), IntFieldValue(5678));
+ doc->setValue(doc->getField("hstringval"),
+ StringFieldValue("hello fantastic world"));
+ return doc;
+}
+
+void
+FieldSetTest::testCopyDocumentFields()
+{
+ TestDocMan testDocMan;
+ const DocumentTypeRepo& repo = testDocMan.getTypeRepo();
+ Document::UP src(createTestDocument(testDocMan));
+
+ CPPUNIT_ASSERT_EQUAL(std::string("content: megafoo megabar\n"),
+ doCopyFields(*src, repo, "[body]"));
+ CPPUNIT_ASSERT_EQUAL(std::string(""),
+ doCopyFields(*src, repo, "[none]"));
+ CPPUNIT_ASSERT_EQUAL(std::string("headerval: 5678\n"
+ "hstringval: hello fantastic world\n"),
+ doCopyFields(*src, repo, "[header]"));
+ CPPUNIT_ASSERT_EQUAL(std::string("content: megafoo megabar\n"
+ "headerval: 5678\n"
+ "hstringval: hello fantastic world\n"),
+ doCopyFields(*src, repo, "[all]"));
+ CPPUNIT_ASSERT_EQUAL(std::string("content: megafoo megabar\n"
+ "hstringval: hello fantastic world\n"),
+ doCopyFields(*src, repo, "testdoctype1:hstringval,content"));
+ // Test that we overwrite already set fields in destination document
+ {
+ Document dest(src->getType(), DocumentId("doc:foo:bar"));
+ dest.setValue(dest.getField("content"), StringFieldValue("overwriteme"));
+ CPPUNIT_ASSERT_EQUAL(std::string("content: megafoo megabar\n"),
+ doCopyFields(*src, repo, "[body]", &dest));
+ }
+}
+
+std::string
+FieldSetTest::doCopyDocument(const Document& src,
+ const DocumentTypeRepo& docRepo,
+ const std::string& fieldSetStr)
+{
+ FieldSetRepo repo;
+ FieldSet::UP fset = repo.parse(docRepo, fieldSetStr);
+ Document::UP doc(FieldSet::createDocumentSubsetCopy(src, *fset));
+ return stringifyFields(*doc);
+}
+
+
+void
+FieldSetTest::testDocumentSubsetCopy()
+{
+ TestDocMan testDocMan;
+ const DocumentTypeRepo& repo = testDocMan.getTypeRepo();
+ Document::UP src(createTestDocument(testDocMan));
+
+ {
+ Document::UP doc(FieldSet::createDocumentSubsetCopy(*src, AllFields()));
+ // Test that document id and type are copied correctly.
+ CPPUNIT_ASSERT(doc.get());
+ CPPUNIT_ASSERT_EQUAL(src->getId(), doc->getId());
+ CPPUNIT_ASSERT_EQUAL(src->getType(), doc->getType());
+ CPPUNIT_ASSERT_EQUAL(doCopyFields(*src, repo, "[all]"),
+ stringifyFields(*doc));
+ }
+
+ const char* fieldSets[] = {
+ "[all]",
+ "[none]",
+ "[header]",
+ "[body]",
+ "testdoctype1:hstringval,content"
+ };
+ for (size_t i = 0; i < sizeof(fieldSets) / sizeof(fieldSets[0]); ++i) {
+ CPPUNIT_ASSERT_EQUAL(doCopyFields(*src, repo, fieldSets[i]),
+ doCopyDocument(*src, repo, fieldSets[i]));
+ }
+}
+
+void
+FieldSetTest::testSerialize()
+{
+ TestDocMan testDocMan;
+ const DocumentTypeRepo& docRepo = testDocMan.getTypeRepo();
+
+ const char* fieldSets[] = {
+ "[all]",
+ "[none]",
+ "[header]",
+ "[docid]",
+ "[body]",
+ "testdoctype1:content",
+ "testdoctype1:content,hstringval"
+ };
+
+ FieldSetRepo repo;
+ for (size_t i = 0; i < sizeof(fieldSets) / sizeof(fieldSets[0]); ++i) {
+ FieldSet::UP fs = repo.parse(docRepo, fieldSets[i]);
+ CPPUNIT_ASSERT_EQUAL(vespalib::string(fieldSets[i]), repo.serialize(*fs));
+ }
+}
+
+void
+FieldSetTest::testStripFields()
+{
+ TestDocMan testDocMan;
+ const DocumentTypeRepo& repo = testDocMan.getTypeRepo();
+ Document::UP src(createTestDocument(testDocMan));
+
+ CPPUNIT_ASSERT_EQUAL(std::string("content: megafoo megabar\n"),
+ doStripFields(*src, repo, "[body]"));
+ CPPUNIT_ASSERT_EQUAL(std::string(""),
+ doStripFields(*src, repo, "[none]"));
+ CPPUNIT_ASSERT_EQUAL(std::string(""),
+ doStripFields(*src, repo, "[id]"));
+ CPPUNIT_ASSERT_EQUAL(std::string("headerval: 5678\n"
+ "hstringval: hello fantastic world\n"),
+ doStripFields(*src, repo, "[header]"));
+ CPPUNIT_ASSERT_EQUAL(std::string("content: megafoo megabar\n"
+ "headerval: 5678\n"
+ "hstringval: hello fantastic world\n"),
+ doStripFields(*src, repo, "[all]"));
+ CPPUNIT_ASSERT_EQUAL(std::string("content: megafoo megabar\n"
+ "hstringval: hello fantastic world\n"),
+ doStripFields(*src, repo, "testdoctype1:hstringval,content"));
+}
+
+} // document