diff options
Diffstat (limited to 'searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp')
-rw-r--r-- | searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp | 170 |
1 files changed, 130 insertions, 40 deletions
diff --git a/searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp b/searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp index 1d9f088d170..dd88684dfee 100644 --- a/searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp +++ b/searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp @@ -114,48 +114,52 @@ TEST("test AndNot Blueprint") { // createSearch tested by iterator unit test } +template <typename BP> +void optimize(std::unique_ptr<BP> &ref) { + auto optimized = Blueprint::optimize(std::move(ref)); + ref.reset(dynamic_cast<BP*>(optimized.get())); + ASSERT_TRUE(ref); + optimized.release(); +} + TEST("test And propagates updated histestimate") { - AndBlueprint bp; - bp.setSourceId(2); - bp.addChild(ap(MyLeafSpec(20).create<RememberExecuteInfo>()->setSourceId(2))); - bp.addChild(ap(MyLeafSpec(200).create<RememberExecuteInfo>()->setSourceId(2))); - bp.addChild(ap(MyLeafSpec(2000).create<RememberExecuteInfo>()->setSourceId(2))); - bp.optimize_self(Blueprint::OptimizePass::FIRST); - bp.optimize_self(Blueprint::OptimizePass::SECOND); - bp.optimize_self(Blueprint::OptimizePass::LAST); - bp.setDocIdLimit(5000); - bp.fetchPostings(ExecuteInfo::TRUE); - EXPECT_EQUAL(3u, bp.childCnt()); - for (uint32_t i = 0; i < bp.childCnt(); i++) { - const auto & child = dynamic_cast<const RememberExecuteInfo &>(bp.getChild(i)); + auto bp = std::make_unique<AndBlueprint>(); + bp->setSourceId(2); + bp->addChild(ap(MyLeafSpec(20).create<RememberExecuteInfo>()->setSourceId(2))); + bp->addChild(ap(MyLeafSpec(200).create<RememberExecuteInfo>()->setSourceId(2))); + bp->addChild(ap(MyLeafSpec(2000).create<RememberExecuteInfo>()->setSourceId(2))); + optimize(bp); + bp->setDocIdLimit(5000); + bp->fetchPostings(ExecuteInfo::TRUE); + EXPECT_EQUAL(3u, bp->childCnt()); + for (uint32_t i = 0; i < bp->childCnt(); i++) { + const auto & child = dynamic_cast<const RememberExecuteInfo &>(bp->getChild(i)); EXPECT_EQUAL((i == 0), child.executeInfo.isStrict()); } - EXPECT_EQUAL(1.0f, dynamic_cast<const RememberExecuteInfo &>(bp.getChild(0)).executeInfo.hitRate()); - EXPECT_EQUAL(1.0f/250, dynamic_cast<const RememberExecuteInfo &>(bp.getChild(1)).executeInfo.hitRate()); - EXPECT_EQUAL(1.0f/(250*25), dynamic_cast<const RememberExecuteInfo &>(bp.getChild(2)).executeInfo.hitRate()); + EXPECT_EQUAL(1.0f, dynamic_cast<const RememberExecuteInfo &>(bp->getChild(0)).executeInfo.hitRate()); + EXPECT_EQUAL(1.0f/250, dynamic_cast<const RememberExecuteInfo &>(bp->getChild(1)).executeInfo.hitRate()); + EXPECT_EQUAL(1.0f/(250*25), dynamic_cast<const RememberExecuteInfo &>(bp->getChild(2)).executeInfo.hitRate()); } TEST("test Or propagates updated histestimate") { - OrBlueprint bp; - bp.setSourceId(2); - bp.addChild(ap(MyLeafSpec(5000).create<RememberExecuteInfo>()->setSourceId(2))); - bp.addChild(ap(MyLeafSpec(2000).create<RememberExecuteInfo>()->setSourceId(2))); - bp.addChild(ap(MyLeafSpec(800).create<RememberExecuteInfo>()->setSourceId(2))); - bp.addChild(ap(MyLeafSpec(20).create<RememberExecuteInfo>()->setSourceId(2))); - bp.optimize_self(Blueprint::OptimizePass::FIRST); - bp.optimize_self(Blueprint::OptimizePass::SECOND); - bp.optimize_self(Blueprint::OptimizePass::LAST); - bp.setDocIdLimit(5000); - bp.fetchPostings(ExecuteInfo::TRUE); - EXPECT_EQUAL(4u, bp.childCnt()); - for (uint32_t i = 0; i < bp.childCnt(); i++) { - const auto & child = dynamic_cast<const RememberExecuteInfo &>(bp.getChild(i)); + auto bp = std::make_unique<OrBlueprint>(); + bp->setSourceId(2); + bp->addChild(ap(MyLeafSpec(5000).create<RememberExecuteInfo>()->setSourceId(2))); + bp->addChild(ap(MyLeafSpec(2000).create<RememberExecuteInfo>()->setSourceId(2))); + bp->addChild(ap(MyLeafSpec(800).create<RememberExecuteInfo>()->setSourceId(2))); + bp->addChild(ap(MyLeafSpec(20).create<RememberExecuteInfo>()->setSourceId(2))); + optimize(bp); + bp->setDocIdLimit(5000); + bp->fetchPostings(ExecuteInfo::TRUE); + EXPECT_EQUAL(4u, bp->childCnt()); + for (uint32_t i = 0; i < bp->childCnt(); i++) { + const auto & child = dynamic_cast<const RememberExecuteInfo &>(bp->getChild(i)); EXPECT_TRUE(child.executeInfo.isStrict()); } - EXPECT_EQUAL(1.0f, dynamic_cast<const RememberExecuteInfo &>(bp.getChild(0)).executeInfo.hitRate()); - EXPECT_EQUAL(1.0f, dynamic_cast<const RememberExecuteInfo &>(bp.getChild(1)).executeInfo.hitRate()); - EXPECT_EQUAL(3.0f/5.0f, dynamic_cast<const RememberExecuteInfo &>(bp.getChild(2)).executeInfo.hitRate()); - EXPECT_EQUAL(3.0f*42.0f/(5.0f*50.0f), dynamic_cast<const RememberExecuteInfo &>(bp.getChild(3)).executeInfo.hitRate()); + EXPECT_EQUAL(1.0f, dynamic_cast<const RememberExecuteInfo &>(bp->getChild(0)).executeInfo.hitRate()); + EXPECT_EQUAL(1.0f, dynamic_cast<const RememberExecuteInfo &>(bp->getChild(1)).executeInfo.hitRate()); + EXPECT_EQUAL(3.0f/5.0f, dynamic_cast<const RememberExecuteInfo &>(bp->getChild(2)).executeInfo.hitRate()); + EXPECT_EQUAL(3.0f*42.0f/(5.0f*50.0f), dynamic_cast<const RememberExecuteInfo &>(bp->getChild(3)).executeInfo.hitRate()); } TEST("test And Blueprint") { @@ -469,6 +473,7 @@ struct SourceBlenderTestFixture { InvalidSelector selector_1; // the one InvalidSelector selector_2; // not the one void addChildrenForSBTest(IntermediateBlueprint & parent); + void addChildrenForSimpleSBTest(IntermediateBlueprint & parent); }; void @@ -488,7 +493,13 @@ void SourceBlenderTestFixture::addChildrenForSBTest(IntermediateBlueprint & pare parent.addChild(addLeafsWithSourceId(std::make_unique<SourceBlenderBlueprint>(selector_1), {{2000, 2}, {1000, 1}})); } -TEST_F("test SourceBlender below AND optimization", SourceBlenderTestFixture) { +void SourceBlenderTestFixture::addChildrenForSimpleSBTest(IntermediateBlueprint & parent) { + parent.addChild(addLeafsWithSourceId(std::make_unique<SourceBlenderBlueprint>(selector_1), {{200, 2}, {100, 1}, {300, 3}})); + parent.addChild(addLeafsWithSourceId(std::make_unique<SourceBlenderBlueprint>(selector_1), {{20, 2}, {10, 1}, {30, 3}})); + parent.addChild(addLeafsWithSourceId(std::make_unique<SourceBlenderBlueprint>(selector_1), {{2000, 2}, {1000, 1}})); +} + +TEST_F("test SourceBlender below AND partial optimization", SourceBlenderTestFixture) { auto top = std::make_unique<AndBlueprint>(); f.addChildrenForSBTest(*top); @@ -505,7 +516,19 @@ TEST_F("test SourceBlender below AND optimization", SourceBlenderTestFixture) { optimize_and_compare(std::move(top), std::move(expect)); } -TEST_F("test SourceBlender below OR optimization", SourceBlenderTestFixture) { +TEST_F("test AND replaced by source blender after full optimization", SourceBlenderTestFixture) { + auto top = std::make_unique<AndBlueprint>(); + f.addChildrenForSimpleSBTest(*top); + + auto expect = std::make_unique<SourceBlenderBlueprint>(f.selector_1); + expect->addChild(addLeafsWithSourceId(3, std::make_unique<AndBlueprint>(), {{30, 3}, {300, 3}})); + expect->addChild(addLeafsWithSourceId(2, std::make_unique<AndBlueprint>(), {{20, 2}, {200, 2}, {2000, 2}})); + expect->addChild(addLeafsWithSourceId(1, std::make_unique<AndBlueprint>(), {{10, 1}, {100, 1}, {1000, 1}})); + + optimize_and_compare(std::move(top), std::move(expect)); +} + +TEST_F("test SourceBlender below OR partial optimization", SourceBlenderTestFixture) { auto top = std::make_unique<OrBlueprint>(); f.addChildrenForSBTest(*top); //------------------------------------------------------------------------- @@ -521,6 +544,18 @@ TEST_F("test SourceBlender below OR optimization", SourceBlenderTestFixture) { optimize_and_compare(std::move(top), std::move(expect)); } +TEST_F("test OR replaced by source blender after full optimization", SourceBlenderTestFixture) { + auto top = std::make_unique<OrBlueprint>(); + f.addChildrenForSimpleSBTest(*top); + + auto expect = std::make_unique<SourceBlenderBlueprint>(f.selector_1); + expect->addChild(addLeafsWithSourceId(3, std::make_unique<OrBlueprint>(), {{300, 3}, {30, 3}})); + expect->addChild(addLeafsWithSourceId(2, std::make_unique<OrBlueprint>(), {{2000, 2}, {200, 2}, {20, 2}})); + expect->addChild(addLeafsWithSourceId(1, std::make_unique<OrBlueprint>(), {{1000, 1}, {100, 1}, {10, 1}})); + + optimize_and_compare(std::move(top), std::move(expect)); +} + TEST_F("test SourceBlender below AND_NOT optimization", SourceBlenderTestFixture) { auto top = std::make_unique<AndNotBlueprint>(); top->addChild(addLeafsWithSourceId(std::make_unique<SourceBlenderBlueprint>(f.selector_1), {{42, 1}})); @@ -592,14 +627,69 @@ TEST("and with one empty child is optimized away") { EXPECT_EQUAL(expect_up->asString(), top->asString()); } +TEST("AND AND collapsing") { + auto top = std::make_unique<AndBlueprint>(); + addLeafs(*top, {1,3,5}); + auto sub_and = std::make_unique<AndBlueprint>(); + addLeafs(*sub_and, {2,4}); + top->addChild(std::move(sub_and)); + auto expect = std::make_unique<AndBlueprint>(); + addLeafs(*expect, {1,2,3,4,5}); + optimize_and_compare(std::move(top), std::move(expect)); +} + +TEST("OR OR collapsing") { + auto top = std::make_unique<OrBlueprint>(); + addLeafs(*top, {1,3,5}); + auto sub_and = std::make_unique<OrBlueprint>(); + addLeafs(*sub_and, {2,4}); + top->addChild(std::move(sub_and)); + auto expect = std::make_unique<OrBlueprint>(); + addLeafs(*expect, {5,4,3,2,1}); + optimize_and_compare(std::move(top), std::move(expect)); +} + +TEST("AND_NOT AND_NOT collapsing") { + auto top = std::make_unique<AndNotBlueprint>(); + auto sub_and_not = std::make_unique<AndNotBlueprint>(); + addLeafs(*sub_and_not, {1,3,5}); + top->addChild(std::move(sub_and_not)); + addLeafs(*top, {2,4}); + auto expect = std::make_unique<AndNotBlueprint>(); + addLeafs(*expect, {1,5,4,3,2}); + optimize_and_compare(std::move(top), std::move(expect)); +} + +TEST("AND_NOT AND AND_NOT collapsing") { + auto top = std::make_unique<AndNotBlueprint>(); + auto sub_and = std::make_unique<AndBlueprint>(); + auto sub_and_not = std::make_unique<AndNotBlueprint>(); + addLeafs(*sub_and_not, {1,5,6}); + sub_and->addChild(std::move(sub_and_not)); + addLeafs(*sub_and, {3,2}); + sub_and_not = std::make_unique<AndNotBlueprint>(); + addLeafs(*sub_and_not, {4,8,9}); + sub_and->addChild(std::move(sub_and_not)); + top->addChild(std::move(sub_and)); + addLeafs(*top, {7}); + //------------------------------------------------------------------------- + auto expect = std::make_unique<AndNotBlueprint>(); + auto sub_expect = std::make_unique<AndBlueprint>(); + addLeafs(*sub_expect, {1,2,3,4}); + expect->addChild(std::move(sub_expect)); + addLeafs(*expect, {9,8,7,6,5}); + optimize_and_compare(std::move(top), std::move(expect)); +} + TEST("test single child optimization") { InvalidSelector selector; //------------------------------------------------------------------------- Blueprint::UP top = ap((new AndNotBlueprint())-> - addChild(ap((new AndBlueprint())-> - addChild(ap((new OrBlueprint())-> - addChild(ap((new SourceBlenderBlueprint(selector))-> - addChild(addLeafs(std::make_unique<RankBlueprint>(), {42}))))))))); + addChild(ap((new AndBlueprint())-> + addChild(ap((new RankBlueprint())-> + addChild(ap((new OrBlueprint())-> + addChild(ap((new SourceBlenderBlueprint(selector))-> + addChild(addLeafs(std::make_unique<RankBlueprint>(), {42}))))))))))); //------------------------------------------------------------------------- Blueprint::UP expect = addLeafs(std::make_unique<SourceBlenderBlueprint>(selector), {42}); //------------------------------------------------------------------------- |