diff options
author | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
---|---|---|
committer | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
commit | 72231250ed81e10d66bfe70701e64fa5fe50f712 (patch) | |
tree | 2728bba1131a6f6e5bdf95afec7d7ff9358dac50 /searchlib/src/tests/queryeval/blueprint/blueprint_test.cpp |
Publish
Diffstat (limited to 'searchlib/src/tests/queryeval/blueprint/blueprint_test.cpp')
-rw-r--r-- | searchlib/src/tests/queryeval/blueprint/blueprint_test.cpp | 766 |
1 files changed, 766 insertions, 0 deletions
diff --git a/searchlib/src/tests/queryeval/blueprint/blueprint_test.cpp b/searchlib/src/tests/queryeval/blueprint/blueprint_test.cpp new file mode 100644 index 00000000000..79fec3770b3 --- /dev/null +++ b/searchlib/src/tests/queryeval/blueprint/blueprint_test.cpp @@ -0,0 +1,766 @@ +// 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/log/log.h> +LOG_SETUP("blueprint_test"); +#include <vespa/vespalib/testkit/testapp.h> +#include <vespa/searchlib/queryeval/blueprint.h> +#include <vespa/searchlib/queryeval/intermediate_blueprints.h> +#include <vespa/vespalib/objects/objectdumper.h> +#include <vespa/vespalib/objects/visit.h> + +#include "mysearch.h" + +using namespace search::queryeval; +using namespace search::fef; + +namespace { + +//----------------------------------------------------------------------------- + +class MyOr : public IntermediateBlueprint +{ +private: +public: + virtual HitEstimate combine(const std::vector<HitEstimate> &data) const { + return max(data); + } + + virtual FieldSpecBaseList exposeFields() const { + return mixChildrenFields(); + } + + virtual void sort(std::vector<Blueprint*> &children) const { + std::sort(children.begin(), children.end(), GreaterEstimate()); + } + + virtual bool inheritStrict(size_t i) const { + (void)i; + return true; + } + + virtual SearchIterator::UP + createIntermediateSearch(const MultiSearch::Children &subSearches, + bool strict, MatchData &md) const + { + return SearchIterator::UP(new MySearch("or", subSearches, &md, strict)); + } + + static MyOr& create() { return *(new MyOr()); } + MyOr& add(Blueprint *n) { addChild(UP(n)); return *this; } + MyOr& add(Blueprint &n) { addChild(UP(&n)); return *this; } +}; + + +class OtherOr : public OrBlueprint +{ +private: +public: + virtual SearchIterator::UP + createIntermediateSearch(const MultiSearch::Children &subSearches, + bool strict, MatchData &md) const + { + return SearchIterator::UP(new MySearch("or", subSearches, &md, strict)); + } + + static OtherOr& create() { return *(new OtherOr()); } + OtherOr& add(Blueprint *n) { addChild(UP(n)); return *this; } + OtherOr& add(Blueprint &n) { addChild(UP(&n)); return *this; } +}; + +//----------------------------------------------------------------------------- + +class MyAnd : public AndBlueprint +{ +private: +public: + virtual HitEstimate combine(const std::vector<HitEstimate> &data) const { + return min(data); + } + + virtual FieldSpecBaseList exposeFields() const { + return FieldSpecBaseList(); + } + + virtual bool inheritStrict(size_t i) const { + return (i == 0); + } + + virtual SearchIterator::UP + createIntermediateSearch(const MultiSearch::Children &subSearches, + bool strict, MatchData &md) const + { + return SearchIterator::UP(new MySearch("and", subSearches, &md, strict)); + } + + static MyAnd& create() { return *(new MyAnd()); } + MyAnd& add(Blueprint *n) { addChild(UP(n)); return *this; } + MyAnd& add(Blueprint &n) { addChild(UP(&n)); return *this; } +}; + + +class OtherAnd : public AndBlueprint +{ +private: +public: + virtual SearchIterator::UP + createIntermediateSearch(const MultiSearch::Children &subSearches, + bool strict, MatchData &md) const + { + return SearchIterator::UP(new MySearch("and", subSearches, &md, strict)); + } + + static OtherAnd& create() { return *(new OtherAnd()); } + OtherAnd& add(Blueprint *n) { addChild(UP(n)); return *this; } + OtherAnd& add(Blueprint &n) { addChild(UP(&n)); return *this; } +}; + +class OtherAndNot : public AndNotBlueprint +{ +public: + virtual SearchIterator::UP + createIntermediateSearch(const MultiSearch::Children &subSearches, + bool strict, MatchData &md) const + { + return SearchIterator::UP(new MySearch("andnot", subSearches, &md, strict)); + } + + static OtherAndNot& create() { return *(new OtherAndNot()); } + OtherAndNot& add(Blueprint *n) { addChild(UP(n)); return *this; } + OtherAndNot& add(Blueprint &n) { addChild(UP(&n)); return *this; } + +}; + +//----------------------------------------------------------------------------- + +struct MyTerm : SimpleLeafBlueprint { + MyTerm(const FieldSpecBaseList &fields, uint32_t hitEstimate) : SimpleLeafBlueprint(fields) { + setEstimate(HitEstimate(hitEstimate, false)); + } + virtual SearchIterator::UP createLeafSearch(const search::fef::TermFieldMatchDataArray &, bool) const { + return SearchIterator::UP(); + } +}; + +//----------------------------------------------------------------------------- + +} // namespace <unnamed> + +class Test : public vespalib::TestApp +{ +private: + MatchData::UP _md; + + static Blueprint::UP ap(Blueprint *b) { return Blueprint::UP(b); } + static Blueprint::UP ap(Blueprint &b) { return Blueprint::UP(&b); } + + SearchIterator::UP create(const Blueprint &blueprint); + bool check_equal(const SearchIterator &a, const SearchIterator &b); + bool check_equal(const Blueprint &a, const Blueprint &b); + bool check_not_equal(const SearchIterator &a, const SearchIterator &b); + bool check_not_equal(const Blueprint &a, const Blueprint &b); + +public: + Test() + : vespalib::TestApp(), + _md(MatchData::makeTestInstance(0, 100, 10)) + { + } + Blueprint::UP buildBlueprint1(); + Blueprint::UP buildBlueprint2(); + void testBlueprintBuilding(); + void testHitEstimateCalculation(); + void testHitEstimatePropagation(); + void testMatchDataPropagation(); + void testChildSorting(); + void testChildAndNotCollapsing(); + void testChildAndCollapsing(); + void testChildOrCollapsing(); + void testSearchCreation(); + void testBlueprintMakeNew(); + void requireThatAsStringWorks(); + void requireThatVisitMembersWorks(); + void requireThatDocIdLimitInjectionWorks(); + int Main(); +}; + +SearchIterator::UP +Test::create(const Blueprint &blueprint) +{ + const_cast<Blueprint &>(blueprint).fetchPostings(true); + SearchIterator::UP search = blueprint.createSearch(*_md, true); + MySearch::verifyAndInfer(search.get(), *_md); + return search; +} + +bool +Test::check_equal(const SearchIterator &a, const SearchIterator &b) +{ + return EXPECT_EQUAL(a.asString(), b.asString()); +} + +bool +Test::check_equal(const Blueprint &a, const Blueprint &b) +{ + SearchIterator::UP searchA = create(a); + SearchIterator::UP searchB = create(b); + TEST_STATE("check_equal"); + bool ok = check_equal(*searchA, *searchB); + return ok; +} + +bool +Test::check_not_equal(const SearchIterator &a, const SearchIterator &b) +{ + return EXPECT_NOT_EQUAL(a.asString(), b.asString()); +} + +bool +Test::check_not_equal(const Blueprint &a, const Blueprint &b) +{ + SearchIterator::UP searchA = create(a); + SearchIterator::UP searchB = create(b); + TEST_STATE("check_not_equal"); + bool ok = check_not_equal(*searchA, *searchB); + return ok; +} + +Blueprint::UP +Test::buildBlueprint1() +{ + return ap(MyAnd::create() + .add(MyOr::create() + .add(MyLeafSpec(10).addField(1, 11).create()) + .add(MyLeafSpec(20).addField(1, 21).create()) + .add(MyLeafSpec(30).addField(1, 31).create()) + ) + .add(MyOr::create() + .add(MyLeafSpec(100).addField(2, 22).create()) + .add(MyLeafSpec(200).addField(2, 42).create()) + ) + ); +} + +Blueprint::UP +Test::buildBlueprint2() +{ + return ap(MyAnd::create() + .add(MyOr::create() + .add(MyLeafSpec(10).addField(1, 11).create()) + .add(MyLeafSpec(20).addField(1, 21).create()) + ) + .add(MyOr::create() + .add(MyLeafSpec(100).addField(2, 22).create()) + .add(MyLeafSpec(200).addField(2, 32).create()) + .add(MyLeafSpec(300).addField(2, 42).create()) + ) + ); +} + +void +Test::testBlueprintBuilding() +{ + Blueprint::UP root1 = buildBlueprint1(); + Blueprint::UP root2 = buildBlueprint2(); + SearchIterator::UP search1 = create(*root1); + SearchIterator::UP search2 = create(*root2); + // fprintf(stderr, "%s\n", search1->asString().c_str()); + // fprintf(stderr, "%s\n", search2->asString().c_str()); +} + +void +Test::testHitEstimateCalculation() +{ + { + Blueprint::UP leaf = ap(MyLeafSpec(37).create()); + EXPECT_EQUAL(37u, leaf->getState().estimate().estHits); + EXPECT_EQUAL(0u, leaf->getState().numFields()); + } + { + Blueprint::UP a1 = ap(MyAnd::create() + .add(MyLeafSpec(7).addField(1, 11).create()) + .add(MyLeafSpec(4).addField(1, 21).create()) + .add(MyLeafSpec(6).addField(1, 31).create())); + EXPECT_EQUAL(4u, a1->getState().estimate().estHits); + } + { + Blueprint::UP a2 = ap(MyAnd::create() + .add(MyLeafSpec(4).addField(1, 1).create()) + .add(MyLeafSpec(7).addField(2, 2).create()) + .add(MyLeafSpec(6).addField(3, 3).create())); + EXPECT_EQUAL(4u, a2->getState().estimate().estHits); + } + { + Blueprint::UP o1 = ap(MyOr::create() + .add(MyLeafSpec(7).addField(1, 11).create()) + .add(MyLeafSpec(4).addField(1, 21).create()) + .add(MyLeafSpec(6).addField(1, 31).create())); + EXPECT_EQUAL(7u, o1->getState().estimate().estHits); + } + { + Blueprint::UP o2 = ap(MyOr::create() + .add(MyLeafSpec(4).addField(1, 1).create()) + .add(MyLeafSpec(7).addField(2, 2).create()) + .add(MyLeafSpec(6).addField(3, 3).create())); + EXPECT_EQUAL(7u, o2->getState().estimate().estHits); + } + { + Blueprint::UP a = ap(MyAnd::create() + .add(MyLeafSpec(0).create()) + .add(MyLeafSpec(0, true).create())); + EXPECT_EQUAL(0u, a->getState().estimate().estHits); + EXPECT_EQUAL(true, a->getState().estimate().empty); + } + { + Blueprint::UP o = ap(MyOr::create() + .add(MyLeafSpec(0).create()) + .add(MyLeafSpec(0, true).create())); + EXPECT_EQUAL(0u, o->getState().estimate().estHits); + EXPECT_EQUAL(false, o->getState().estimate().empty); + } + { + Blueprint::UP tree1 = buildBlueprint1(); + EXPECT_EQUAL(30u, tree1->getState().estimate().estHits); + + Blueprint::UP tree2 = buildBlueprint2(); + EXPECT_EQUAL(20u, tree2->getState().estimate().estHits); + } +} + +void +Test::testHitEstimatePropagation() +{ + MyLeaf *leaf1 = new MyLeaf(FieldSpecBaseList()); + leaf1->estimate(10); + + MyLeaf *leaf2 = new MyLeaf(FieldSpecBaseList()); + leaf2->estimate(20); + + MyLeaf *leaf3 = new MyLeaf(FieldSpecBaseList()); + leaf3->estimate(30); + + MyOr *parent = new MyOr(); + MyOr *grandparent = new MyOr(); + + Blueprint::UP root(grandparent); + + parent->addChild(ap(leaf1)); + parent->addChild(ap(leaf3)); + grandparent->addChild(ap(leaf2)); + grandparent->addChild(ap(parent)); + EXPECT_EQUAL(30u, root->getState().estimate().estHits); + + // edit + leaf3->estimate(50); + EXPECT_EQUAL(50u, root->getState().estimate().estHits); + + // remove + ASSERT_TRUE(parent->childCnt() == 2); + Blueprint::UP tmp = parent->removeChild(1); + ASSERT_TRUE(tmp.get() == leaf3); + EXPECT_EQUAL(1u, parent->childCnt()); + EXPECT_EQUAL(20u, root->getState().estimate().estHits); + + // add + leaf3->estimate(25); + EXPECT_EQUAL(20u, root->getState().estimate().estHits); + parent->addChild(std::move(tmp)); + EXPECT_TRUE(tmp.get() == 0); + EXPECT_EQUAL(25u, root->getState().estimate().estHits); +} + +void +Test::testMatchDataPropagation() +{ + { + Blueprint::UP leaf = ap(MyLeafSpec(0, true).create()); + EXPECT_EQUAL(0u, leaf->getState().numFields()); + } + { + Blueprint::UP leaf = ap(MyLeafSpec(42) + .addField(1, 41) + .addField(2, 72).create()); + EXPECT_EQUAL(42u, leaf->getState().estimate().estHits); + ASSERT_TRUE(leaf->getState().numFields() == 2); + EXPECT_EQUAL(1u, leaf->getState().field(0).getFieldId()); + EXPECT_EQUAL(2u, leaf->getState().field(1).getFieldId()); + EXPECT_EQUAL(41u, leaf->getState().field(0).getHandle()); + EXPECT_EQUAL(72u, leaf->getState().field(1).getHandle()); + } + { + Blueprint::UP a = ap(MyAnd::create() + .add(MyLeafSpec(7).addField(1, 11).create()) + .add(MyLeafSpec(4).addField(1, 21).create()) + .add(MyLeafSpec(6).addField(1, 31).create())); + EXPECT_EQUAL(0u, a->getState().numFields()); + } + { + MyOr &o = MyOr::create() + .add(MyLeafSpec(1).addField(1, 1).create()) + .add(MyLeafSpec(2).addField(2, 2).create()); + + Blueprint::UP a = ap(o); + ASSERT_TRUE(a->getState().numFields() == 2); + EXPECT_EQUAL(1u, a->getState().field(0).getFieldId()); + EXPECT_EQUAL(2u, a->getState().field(1).getFieldId()); + EXPECT_EQUAL(1u, a->getState().field(0).getHandle()); + EXPECT_EQUAL(2u, a->getState().field(1).getHandle()); + EXPECT_EQUAL(2u, a->getState().estimate().estHits); + + o.add(MyLeafSpec(5).addField(2, 2).create()); + ASSERT_TRUE(a->getState().numFields() == 2); + EXPECT_EQUAL(1u, a->getState().field(0).getFieldId()); + EXPECT_EQUAL(2u, a->getState().field(1).getFieldId()); + EXPECT_EQUAL(1u, a->getState().field(0).getHandle()); + EXPECT_EQUAL(2u, a->getState().field(1).getHandle()); + EXPECT_EQUAL(5u, a->getState().estimate().estHits); + + o.add(MyLeafSpec(5).addField(2, 32).create()); + EXPECT_EQUAL(0u, a->getState().numFields()); + o.removeChild(3); + EXPECT_EQUAL(2u, a->getState().numFields()); + o.add(MyLeafSpec(0, true).create()); + EXPECT_EQUAL(0u, a->getState().numFields()); + } +} + +void +Test::testChildAndNotCollapsing() +{ + Blueprint::UP unsorted = ap(OtherAndNot::create() + .add(OtherAndNot::create() + .add(OtherAndNot::create() + .add(MyLeafSpec(200).addField(1, 11).create()) + .add(MyLeafSpec(100).addField(1, 21).create()) + .add(MyLeafSpec(300).addField(1, 31).create()) + ) + .add(OtherAnd::create() + .add(MyLeafSpec(1).addField(2, 42).create()) + .add(MyLeafSpec(2).addField(2, 52).create()) + .add(MyLeafSpec(3).addField(2, 62).create()) + ) + ) + .add(MyLeafSpec(30).addField(3, 73).create()) + .add(MyLeafSpec(20).addField(3, 83).create()) + .add(MyLeafSpec(10).addField(3, 93).create()) + ); + + Blueprint::UP sorted = ap(OtherAndNot::create() + .add(MyLeafSpec(200).addField(1, 11).create()) + .add(MyLeafSpec(300).addField(1, 31).create()) + .add(MyLeafSpec(100).addField(1, 21).create()) + .add(MyLeafSpec(30).addField(3, 73).create()) + .add(MyLeafSpec(20).addField(3, 83).create()) + .add(MyLeafSpec(10).addField(3, 93).create()) + .add(OtherAnd::create() + .add(MyLeafSpec(1).addField(2, 42).create()) + .add(MyLeafSpec(2).addField(2, 52).create()) + .add(MyLeafSpec(3).addField(2, 62).create()) + ) + ); + TEST_DO(check_not_equal(*sorted, *unsorted)); + unsorted = Blueprint::optimize(std::move(unsorted)); + TEST_DO(check_equal(*sorted, *unsorted)); +} + +void +Test::testChildAndCollapsing() +{ + Blueprint::UP unsorted = ap(OtherAnd::create() + .add(OtherAnd::create() + .add(OtherAnd::create() + .add(MyLeafSpec(200).addField(1, 11).create()) + .add(MyLeafSpec(100).addField(1, 21).create()) + .add(MyLeafSpec(300).addField(1, 31).create()) + ) + .add(OtherAnd::create() + .add(MyLeafSpec(1).addField(2, 42).create()) + .add(MyLeafSpec(2).addField(2, 52).create()) + .add(MyLeafSpec(3).addField(2, 62).create()) + ) + ) + .add(OtherAnd::create() + .add(MyLeafSpec(30).addField(3, 73).create()) + .add(MyLeafSpec(20).addField(3, 83).create()) + .add(MyLeafSpec(10).addField(3, 93).create()) + ) + ); + + Blueprint::UP sorted = ap(OtherAnd::create() + .add(MyLeafSpec(1).addField(2, 42).create()) + .add(MyLeafSpec(2).addField(2, 52).create()) + .add(MyLeafSpec(3).addField(2, 62).create()) + .add(MyLeafSpec(10).addField(3, 93).create()) + .add(MyLeafSpec(20).addField(3, 83).create()) + .add(MyLeafSpec(30).addField(3, 73).create()) + .add(MyLeafSpec(100).addField(1, 21).create()) + .add(MyLeafSpec(200).addField(1, 11).create()) + .add(MyLeafSpec(300).addField(1, 31).create()) + ); + + TEST_DO(check_not_equal(*sorted, *unsorted)); + unsorted = Blueprint::optimize(std::move(unsorted)); + TEST_DO(check_equal(*sorted, *unsorted)); +} + +void +Test::testChildOrCollapsing() +{ + Blueprint::UP unsorted = ap(OtherOr::create() + .add(OtherOr::create() + .add(OtherOr::create() + .add(MyLeafSpec(200).addField(1, 11).create()) + .add(MyLeafSpec(100).addField(1, 21).create()) + .add(MyLeafSpec(300).addField(1, 31).create()) + ) + .add(OtherOr::create() + .add(MyLeafSpec(1).addField(2, 42).create()) + .add(MyLeafSpec(2).addField(2, 52).create()) + .add(MyLeafSpec(3).addField(2, 62).create()) + ) + ) + .add(OtherOr::create() + .add(MyLeafSpec(30).addField(3, 73).create()) + .add(MyLeafSpec(20).addField(3, 83).create()) + .add(MyLeafSpec(10).addField(3, 93).create()) + ) + ); + + Blueprint::UP sorted = ap(OtherOr::create() + .add(MyLeafSpec(300).addField(1, 31).create()) + .add(MyLeafSpec(200).addField(1, 11).create()) + .add(MyLeafSpec(100).addField(1, 21).create()) + .add(MyLeafSpec(30).addField(3, 73).create()) + .add(MyLeafSpec(20).addField(3, 83).create()) + .add(MyLeafSpec(10).addField(3, 93).create()) + .add(MyLeafSpec(3).addField(2, 62).create()) + .add(MyLeafSpec(2).addField(2, 52).create()) + .add(MyLeafSpec(1).addField(2, 42).create()) + ); + TEST_DO(check_not_equal(*sorted, *unsorted)); + unsorted = Blueprint::optimize(std::move(unsorted)); + TEST_DO(check_equal(*sorted, *unsorted)); +} + +void +Test::testChildSorting() +{ + Blueprint::UP unsorted = ap(MyAnd::create() + .add(MyOr::create() + .add(MyLeafSpec(200).addField(1, 11).create()) + .add(MyLeafSpec(100).addField(1, 21).create()) + .add(MyLeafSpec(300).addField(1, 31).create()) + ) + .add(MyOr::create() + .add(MyLeafSpec(1).addField(2, 42).create()) + .add(MyLeafSpec(2).addField(2, 52).create()) + .add(MyLeafSpec(3).addField(2, 62).create()) + ) + .add(MyOr::create() + .add(MyLeafSpec(30).addField(3, 73).create()) + .add(MyLeafSpec(20).addField(3, 83).create()) + .add(MyLeafSpec(10).addField(3, 93).create()) + ) + ); + + Blueprint::UP sorted = ap(MyAnd::create() + .add(MyOr::create() + .add(MyLeafSpec(3).addField(2, 62).create()) + .add(MyLeafSpec(2).addField(2, 52).create()) + .add(MyLeafSpec(1).addField(2, 42).create()) + ) + .add(MyOr::create() + .add(MyLeafSpec(30).addField(3, 73).create()) + .add(MyLeafSpec(20).addField(3, 83).create()) + .add(MyLeafSpec(10).addField(3, 93).create()) + ) + .add(MyOr::create() + .add(MyLeafSpec(300).addField(1, 31).create()) + .add(MyLeafSpec(200).addField(1, 11).create()) + .add(MyLeafSpec(100).addField(1, 21).create()) + ) + ); + + TEST_DO(check_not_equal(*sorted, *unsorted)); + unsorted = Blueprint::optimize(std::move(unsorted)); + TEST_DO(check_equal(*sorted, *unsorted)); +} + + +void +Test::testSearchCreation() +{ + { + Blueprint::UP l = ap(MyLeafSpec(3) + .addField(1, 1) + .addField(2, 2) + .addField(3, 3).create()); + SearchIterator::UP leafsearch = create(*l); + + MySearch *lw = new MySearch("leaf", true, true); + lw->addHandle(1).addHandle(2).addHandle(3); + SearchIterator::UP wantleaf(lw); + + TEST_DO(check_equal(*wantleaf, *leafsearch)); + } + { + Blueprint::UP a = ap(MyAnd::create() + .add(MyLeafSpec(1).addField(1, 1).create()) + .add(MyLeafSpec(2).addField(2, 2).create())); + SearchIterator::UP andsearch = create(*a); + + MySearch *l1 = new MySearch("leaf", true, true); + MySearch *l2 = new MySearch("leaf", true, false); + l1->addHandle(1); + l2->addHandle(2); + MySearch *aw = new MySearch("and", false, true); + aw->add(l1); + aw->add(l2); + SearchIterator::UP wanted(aw); + TEST_DO(check_equal(*wanted, *andsearch)); + } + { + Blueprint::UP o = ap(MyOr::create() + .add(MyLeafSpec(1).addField(1, 11).create()) + .add(MyLeafSpec(2).addField(2, 22).create())); + SearchIterator::UP orsearch = create(*o); + + MySearch *l1 = new MySearch("leaf", true, true); + MySearch *l2 = new MySearch("leaf", true, true); + l1->addHandle(11); + l2->addHandle(22); + MySearch *ow = new MySearch("or", false, true); + ow->add(l1); + ow->add(l2); + SearchIterator::UP wanted(ow); + TEST_DO(check_equal(*wanted, *orsearch)); + } +} + +template<typename T> +Blueprint::UP makeNew(T *orig) +{ + return Blueprint::UP(new T(*orig)); +} + +void +Test::testBlueprintMakeNew() +{ + Blueprint::UP orig = ap(MyOr::create() + .add(MyLeafSpec(1).addField(1, 11).create()) + .add(MyLeafSpec(2).addField(2, 22).create())); + orig->setSourceId(42); + MyOr *myOr = dynamic_cast<MyOr*>(orig.get()); + ASSERT_TRUE(myOr != 0); + Blueprint::UP copy1 = makeNew(myOr); + Blueprint::UP copy2 = makeNew(myOr); + TEST_DO(check_equal(*copy1, *copy2)); + TEST_DO(check_not_equal(*orig, *copy1)); + TEST_DO(check_not_equal(*orig, *copy2)); + EXPECT_TRUE(dynamic_cast<MyOr*>(copy1.get()) != 0); + EXPECT_TRUE(dynamic_cast<MyOr*>(copy2.get()) != 0); + EXPECT_EQUAL(42u, orig->getSourceId()); + EXPECT_EQUAL(42u, copy1->getSourceId()); + EXPECT_EQUAL(2u, orig->getState().numFields()); + EXPECT_EQUAL(0u, copy1->getState().numFields()); +} + +vespalib::string +getExpectedBlueprint() +{ + return "(anonymous namespace)::MyOr {\n" + " isTermLike: true\n" + " fields: FieldList {\n" + " [0]: Field {\n" + " fieldId: 5\n" + " handle: 7\n" + " isFilter: false\n" + " }\n" + " }\n" + " estimate: HitEstimate {\n" + " empty: false\n" + " estHits: 9\n" + " tree_size: 2\n" + " allow_termwise_eval: 0\n" + " }\n" + " sourceId: 4294967295\n" + " docid_limit: 0\n" + " children: std::vector {\n" + " [0]: (anonymous namespace)::MyTerm {\n" + " isTermLike: true\n" + " fields: FieldList {\n" + " [0]: Field {\n" + " fieldId: 5\n" + " handle: 7\n" + " isFilter: false\n" + " }\n" + " }\n" + " estimate: HitEstimate {\n" + " empty: false\n" + " estHits: 9\n" + " tree_size: 1\n" + " allow_termwise_eval: 1\n" + " }\n" + " sourceId: 4294967295\n" + " docid_limit: 0\n" + " }\n" + " }\n" + "}\n"; +} + +struct BlueprintFixture +{ + MyOr _blueprint; + BlueprintFixture() : _blueprint() { + _blueprint.add(new MyTerm(FieldSpecBaseList().add(FieldSpecBase(5, 7)), 9)); + } +}; + +void +Test::requireThatAsStringWorks() +{ + BlueprintFixture f; + EXPECT_EQUAL(getExpectedBlueprint(), f._blueprint.asString()); +} + +void +Test::requireThatVisitMembersWorks() +{ + BlueprintFixture f; + vespalib::ObjectDumper dumper; + visit(dumper, "", &f._blueprint); + EXPECT_EQUAL(getExpectedBlueprint(), dumper.toString()); +} + +void +Test::requireThatDocIdLimitInjectionWorks() +{ + BlueprintFixture f; + ASSERT_GREATER(f._blueprint.childCnt(), 0u); + const MyTerm &term = dynamic_cast<MyTerm&>(f._blueprint.getChild(0)); + EXPECT_EQUAL(0u, term.get_docid_limit()); + f._blueprint.setDocIdLimit(1000); + EXPECT_EQUAL(1000u, term.get_docid_limit()); +} + +int +Test::Main() +{ + TEST_DEBUG("lhs.out", "rhs.out"); + TEST_INIT("blueprint_test"); + testBlueprintBuilding(); + testHitEstimateCalculation(); + testHitEstimatePropagation(); + testMatchDataPropagation(); + testChildSorting(); + testChildAndNotCollapsing(); + testChildAndCollapsing(); + testChildOrCollapsing(); + testSearchCreation(); + testBlueprintMakeNew(); + requireThatAsStringWorks(); + requireThatVisitMembersWorks(); + requireThatDocIdLimitInjectionWorks(); + TEST_DONE(); +} + +TEST_APPHOOK(Test); |