aboutsummaryrefslogtreecommitdiffstats
path: root/document/src/tests/annotation/annotation_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'document/src/tests/annotation/annotation_test.cpp')
-rw-r--r--document/src/tests/annotation/annotation_test.cpp295
1 files changed, 295 insertions, 0 deletions
diff --git a/document/src/tests/annotation/annotation_test.cpp b/document/src/tests/annotation/annotation_test.cpp
new file mode 100644
index 00000000000..c4976485b8b
--- /dev/null
+++ b/document/src/tests/annotation/annotation_test.cpp
@@ -0,0 +1,295 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Unit tests for annotation.
+
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP("annotation_test");
+
+#include <stdlib.h>
+#include <vespa/document/annotation/alternatespanlist.h>
+#include <vespa/document/annotation/annotation.h>
+#include <vespa/document/annotation/span.h>
+#include <vespa/document/annotation/spanlist.h>
+#include <vespa/document/annotation/spantree.h>
+#include <vespa/document/datatype/annotationreferencedatatype.h>
+#include <vespa/document/datatype/annotationtype.h>
+#include <vespa/document/datatype/arraydatatype.h>
+#include <vespa/document/datatype/primitivedatatype.h>
+#include <vespa/document/datatype/structdatatype.h>
+#include <vespa/document/fieldvalue/annotationreferencefieldvalue.h>
+#include <vespa/document/fieldvalue/arrayfieldvalue.h>
+#include <vespa/document/fieldvalue/doublefieldvalue.h>
+#include <vespa/document/fieldvalue/structfieldvalue.h>
+#include <vespa/vespalib/testkit/testapp.h>
+#include <memory>
+
+using std::unique_ptr;
+using namespace document;
+
+namespace {
+
+AnnotationType text_type(1, "text");
+AnnotationType begin_tag(2, "begintag");
+AnnotationType end_tag(3, "endtag");
+AnnotationType body_type(4, "body");
+AnnotationType header_type(5, "header");
+AnnotationType city_type(6, "city");
+AnnotationType markup_type(7, "markup");
+
+template <typename T>
+unique_ptr<T> makeUP(T *p) { return unique_ptr<T>(p); }
+
+TEST("requireThatSpansHaveOrder") {
+ Span span(10, 10);
+ Span before(5, 3);
+ Span overlap_start(8, 10);
+ Span contained(12, 3);
+ Span overlap_end(15, 10);
+ Span after(21, 10);
+ Span overlap_complete(5, 20);
+ Span shorter(10, 5);
+ Span longer(10, 15);
+ EXPECT_TRUE(span > before);
+ EXPECT_TRUE(span > overlap_start);
+ EXPECT_TRUE(span < contained);
+ EXPECT_TRUE(span < overlap_end);
+ EXPECT_TRUE(span < after);
+ EXPECT_TRUE(span > overlap_complete);
+ EXPECT_TRUE(span > shorter);
+ EXPECT_TRUE(span < longer);
+ EXPECT_TRUE(!(span < span));
+}
+
+TEST("requireThatSimpleSpanTreeCanBeBuilt") {
+ SpanList::UP root(new SpanList);
+ root->add(makeUP(new Span(0, 19)));
+ root->add(makeUP(new Span(19, 5)));
+ root->add(makeUP(new Span(24, 21)));
+ root->add(makeUP(new Span(45, 23)));
+ root->add(makeUP(new Span(68, 14)));
+
+ EXPECT_EQUAL(5u, root->size());
+ SpanList::const_iterator it = root->begin();
+ EXPECT_EQUAL(Span(0, 19), *(static_cast<Span *>(*it++)));
+ EXPECT_EQUAL(Span(19, 5), *(static_cast<Span *>(*it++)));
+ EXPECT_EQUAL(Span(24, 21), *(static_cast<Span *>(*it++)));
+ EXPECT_EQUAL(Span(45, 23), *(static_cast<Span *>(*it++)));
+ EXPECT_EQUAL(Span(68, 14), *(static_cast<Span *>(*it++)));
+ EXPECT_TRUE(it == root->end());
+
+ SpanTree tree("html", std::move(root));
+}
+
+TEST("requireThatSpanTreeCanHaveAnnotations") {
+ SpanList::UP root_owner(new SpanList);
+ SpanList *root = root_owner.get();
+ SpanTree tree("html", std::move(root_owner));
+
+ Span &span1 = root->add(makeUP(new Span(0, 19)));
+ tree.annotate(span1, markup_type);
+
+ Span &span2 = root->add(makeUP(new Span(19, 5)));
+ tree.annotate(span2, text_type);
+
+ EXPECT_EQUAL(2u, tree.numAnnotations());
+ SpanTree::const_iterator it = tree.begin();
+
+ EXPECT_EQUAL(Annotation(markup_type), *it++);
+ EXPECT_EQUAL(Annotation(text_type), *it++);
+ EXPECT_TRUE(it == tree.end());
+}
+
+TEST("requireThatSpanTreeCanHaveMultipleLevels") {
+ SpanList::UP root_owner(new SpanList);
+ SpanList *root = root_owner.get();
+ SpanTree tree("html", std::move(root_owner));
+
+ SpanList::UP header(new SpanList);
+ tree.annotate(header->add(makeUP(new Span(6, 6))), begin_tag);
+ tree.annotate(header->add(makeUP(new Span(12, 7))), begin_tag);
+ tree.annotate(header->add(makeUP(new Span(19, 5))), text_type);
+ tree.annotate(header->add(makeUP(new Span(24, 8))), end_tag);
+ tree.annotate(header->add(makeUP(new Span(32, 7))), end_tag);
+ tree.annotate(*header, header_type);
+
+ SpanList::UP body(new SpanList);
+ tree.annotate(body->add(makeUP(new Span(39, 6))), begin_tag);
+ tree.annotate(body->add(makeUP(new Span(45, 23))), text_type);
+ tree.annotate(body->add(makeUP(new Span(68, 7))), end_tag);
+ tree.annotate(*body, body_type);
+
+ tree.annotate(root->add(makeUP(new Span(0, 6))), begin_tag);
+ root->add(std::move(std::move(header)));
+ root->add(std::move(std::move(body)));
+ tree.annotate(root->add(makeUP(new Span(75, 7))), end_tag);
+
+ EXPECT_EQUAL(12u, tree.numAnnotations());
+ SpanTree::const_iterator it = tree.begin();
+ EXPECT_EQUAL(Annotation(begin_tag), *it++);
+ EXPECT_EQUAL(Annotation(begin_tag), *it++);
+ EXPECT_EQUAL(Annotation(text_type), *it++);
+ EXPECT_EQUAL(Annotation(end_tag), *it++);
+ EXPECT_EQUAL(Annotation(end_tag), *it++);
+ EXPECT_EQUAL(Annotation(header_type), *it++);
+ EXPECT_EQUAL(Annotation(begin_tag), *it++);
+ EXPECT_EQUAL(Annotation(text_type), *it++);
+ EXPECT_EQUAL(Annotation(end_tag), *it++);
+ EXPECT_EQUAL(Annotation(body_type), *it++);
+ EXPECT_EQUAL(Annotation(begin_tag), *it++);
+ EXPECT_EQUAL(Annotation(end_tag), *it++);
+ EXPECT_TRUE(it == tree.end());
+}
+
+TEST("requireThatAnnotationsCanHaveValues") {
+ PrimitiveDataType double_type(DataType::T_DOUBLE);
+ StructDataType city_data_type;
+ city_data_type.addField(Field("latitude", 0, double_type, false));
+ city_data_type.addField(Field("longitude", 1, double_type, false));
+
+ StructFieldValue::UP position(new StructFieldValue(city_data_type));
+ position->setValue("latitude", DoubleFieldValue(37.774929));
+ position->setValue("longitude", DoubleFieldValue(-122.419415));
+ StructFieldValue original(*position);
+
+ Annotation city(city_type, std::move(position));
+
+ EXPECT_TRUE(*city.getFieldValue() == original);
+}
+
+TEST("requireThatAnnotationsCanReferenceAnnotations") {
+ SpanList::UP root(new SpanList);
+ SpanTree tree("html", std::move(root));
+ size_t san_index = tree.annotate(makeUP(new Annotation(text_type)));
+ size_t fran_index = tree.annotate(makeUP(new Annotation(text_type)));
+
+ AnnotationReferenceDataType annotation_ref_type(text_type, 101);
+ ArrayDataType array_type(annotation_ref_type);
+ StructDataType city_data_type("name", 42);
+ city_data_type.addField(Field("references", 0, array_type, false));
+
+ StructFieldValue::UP city_data(new StructFieldValue(city_data_type));
+ ArrayFieldValue ref_list(array_type);
+ ref_list.add(AnnotationReferenceFieldValue(annotation_ref_type,
+ san_index));
+ ref_list.add(AnnotationReferenceFieldValue(annotation_ref_type,
+ fran_index));
+ city_data->setValue("references", ref_list);
+ StructFieldValue original(*city_data);
+
+ Annotation city(city_type, std::move(city_data));
+
+ ASSERT_TRUE(city.getFieldValue());
+ EXPECT_TRUE(city.getFieldValue()->isA(original));
+ EXPECT_EQUAL(original, *city.getFieldValue());
+}
+
+const double prob0 = 0.6;
+const double prob1 = 0.4;
+
+TEST("requireThatAlternateSpanListHoldsMultipleLists") {
+ AlternateSpanList span_list;
+ span_list.add(0, makeUP(new Span(0, 19)));
+ span_list.add(0, makeUP(new Span(19, 5)));
+ span_list.add(1, makeUP(new Span(0, 5)));
+ span_list.add(1, makeUP(new Span(5, 19)));
+ span_list.setProbability(0, prob0);
+ span_list.setProbability(1, prob1);
+
+ EXPECT_EQUAL(2u, span_list.getNumSubtrees());
+ EXPECT_EQUAL(2u, span_list.getSubtree(0).size());
+ EXPECT_EQUAL(2u, span_list.getSubtree(1).size());
+ EXPECT_EQUAL(prob0, span_list.getProbability(0));
+ EXPECT_EQUAL(prob1, span_list.getProbability(1));
+
+ SpanList::const_iterator it = span_list.getSubtree(0).begin();
+ EXPECT_EQUAL(Span(0, 19), *(static_cast<Span *>(*it++)));
+ EXPECT_EQUAL(Span(19, 5), *(static_cast<Span *>(*it++)));
+ EXPECT_TRUE(it == span_list.getSubtree(0).end());
+
+ it = span_list.getSubtree(1).begin();
+ EXPECT_EQUAL(Span(0, 5), *(static_cast<Span *>(*it++)));
+ EXPECT_EQUAL(Span(5, 19), *(static_cast<Span *>(*it++)));
+ EXPECT_TRUE(it == span_list.getSubtree(1).end());
+}
+
+struct MySpanTreeVisitor : SpanTreeVisitor {
+ int span_count;
+ int span_list_count;
+ int alt_span_list_count;
+
+ MySpanTreeVisitor()
+ : span_count(0), span_list_count(0), alt_span_list_count(0) {}
+
+ void visitChildren(const SpanList &node) {
+ for (SpanList::const_iterator
+ it = node.begin(); it != node.end(); ++it) {
+ (*it)->accept(*this);
+ }
+ }
+
+ void visitChildren(const SimpleSpanList &node) {
+ for (SimpleSpanList::const_iterator
+ it = node.begin(); it != node.end(); ++it) {
+ (*it).accept(*this);
+ }
+ }
+
+ void visit(const Span &) override { ++span_count; }
+ void visit(const SpanList &node) override {
+ ++span_list_count;
+ visitChildren(node);
+ }
+ void visit(const SimpleSpanList &node) override {
+ ++span_list_count;
+ visitChildren(node);
+ }
+ void visit(const AlternateSpanList &node) override {
+ ++alt_span_list_count;
+ for (size_t i = 0; i < node.getNumSubtrees(); ++i) {
+ visitChildren(node.getSubtree(i));
+ }
+ }
+};
+
+TEST("requireThatSpanTreeCanBeVisited") {
+ SpanList::UP root(new SpanList);
+ root->add(makeUP(new Span(0, 19)));
+ AlternateSpanList::UP alt_list(new AlternateSpanList);
+ alt_list->add(0, makeUP(new Span(19, 5)));
+ alt_list->add(1, makeUP(new Span(24, 21)));
+ root->add(std::move(alt_list));
+
+ SpanTree tree("html", std::move(root));
+
+ MySpanTreeVisitor visitor;
+ tree.accept(visitor);
+
+ EXPECT_EQUAL(3, visitor.span_count);
+ EXPECT_EQUAL(1, visitor.span_list_count);
+ EXPECT_EQUAL(1, visitor.alt_span_list_count);
+}
+
+TEST("requireThatDefaultAnnotationTypesHaveDefaultDataTypes") {
+ ASSERT_TRUE(AnnotationType::TERM->getDataType());
+ EXPECT_EQUAL(*DataType::STRING, *AnnotationType::TERM->getDataType());
+ ASSERT_TRUE(AnnotationType::TOKEN_TYPE->getDataType());
+ EXPECT_EQUAL(*DataType::INT, *AnnotationType::TOKEN_TYPE->getDataType());
+}
+
+TEST("require that SpanTrees can be compared") {
+ SpanList::UP root(new SpanList);
+ root->add(makeUP(new Span(0, 19)));
+ SpanTree tree1("html", std::move(root));
+
+ root.reset(new SpanList);
+ root->add(makeUP(new Span(0, 18)));
+ SpanTree tree2("html", std::move(root));
+
+ EXPECT_EQUAL(0, tree1.compare(tree1));
+ EXPECT_LESS(0, tree1.compare(tree2));
+ EXPECT_GREATER(0, tree2.compare(tree1));
+}
+
+} // namespace
+
+TEST_MAIN() { TEST_RUN_ALL(); }