diff options
Diffstat (limited to 'searchlib/src/tests/attribute')
3 files changed, 179 insertions, 52 deletions
diff --git a/searchlib/src/tests/attribute/searchcontext/searchcontext_test.cpp b/searchlib/src/tests/attribute/searchcontext/searchcontext_test.cpp index 416ddb5fbc0..ffae7824668 100644 --- a/searchlib/src/tests/attribute/searchcontext/searchcontext_test.cpp +++ b/searchlib/src/tests/attribute/searchcontext/searchcontext_test.cpp @@ -1,12 +1,9 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#include <vespa/searchlib/attribute/attribute.h> #include <vespa/searchlib/attribute/attributefactory.h> #include <vespa/searchlib/attribute/attributeiterators.h> -#include <vespa/searchlib/attribute/attributevector.hpp> -#include <vespa/searchlib/attribute/elementiterator.h> +#include <vespa/searchlib/attribute/searchcontextelementiterator.h> #include <vespa/searchlib/attribute/flagattribute.h> -#include <vespa/searchlib/attribute/multistringattribute.h> #include <vespa/searchlib/attribute/singleboolattribute.h> #include <vespa/searchlib/attribute/singlenumericattribute.h> #include <vespa/searchlib/attribute/singlestringattribute.h> @@ -22,6 +19,7 @@ #include <vespa/searchlib/test/searchiteratorverifier.h> #include <vespa/vespalib/testkit/testapp.h> #include <vespa/vespalib/util/compress.h> +#include <vespa/searchlib/attribute/attributevector.hpp> #include <vespa/log/log.h> LOG_SETUP("searchcontext_test"); @@ -628,29 +626,24 @@ void SearchContextTest::testSearch(const ConfigMap & cfgs) { template<typename T, typename A> class Verifier : public search::test::SearchIteratorVerifier { public: - Verifier(const std::vector<T> & keys, const vespalib::string & keyAsString, const vespalib::string & name, - const Config & cfg, bool withElementId); + Verifier(const std::vector<T> & keys, const vespalib::string & keyAsString, + const vespalib::string & name, const Config & cfg); ~Verifier() override; SearchIterator::UP create(bool strict) const override { _sc->fetchPostings(queryeval::ExecuteInfo::create(strict, 1.0)); - auto search = _sc->createIterator(&_dummy, strict); - if (_withElementId) { - search = std::make_unique<attribute::ElementIterator>(std::move(search), *_sc, _dummy); - } - return search; + return _sc->createIterator(&_dummy, strict); } private: mutable TermFieldMatchData _dummy; - const bool _withElementId; AttributePtr _attribute; SearchContextPtr _sc; }; template<typename T, typename A> -Verifier<T, A>::Verifier(const std::vector<T> & keys, const vespalib::string & keyAsString, const vespalib::string & name, - const Config & cfg, bool withElementId) - : _withElementId(withElementId), +Verifier<T, A>::Verifier(const std::vector<T> & keys, const vespalib::string & keyAsString, + const vespalib::string & name, const Config & cfg) + : _dummy(), _attribute(AttributeFactory::createAttribute(name + "-initrange", cfg)), _sc() { @@ -670,22 +663,18 @@ Verifier<T, A>::~Verifier() = default; template<typename T, typename A> void SearchContextTest::testSearchIterator(const std::vector<T> & keys, const vespalib::string &keyAsString, const ConfigMap &cfgs) { - - for (bool withElementId : {false, true} ) { - for (const auto & cfg : cfgs) { - { - Verifier<T, A> verifier(keys, keyAsString, cfg.first, cfg.second, withElementId); - verifier.verify(); - } - { - Config withFilter(cfg.second); - withFilter.setIsFilter(true); - Verifier<T, A> verifier(keys, keyAsString, cfg.first + "-filter", withFilter, withElementId); - verifier.verify(); - } + for (const auto & cfg : cfgs) { + { + Verifier<T, A> verifier(keys, keyAsString, cfg.first, cfg.second); + verifier.verify(); + } + { + Config withFilter(cfg.second); + withFilter.setIsFilter(true); + Verifier<T, A> verifier(keys, keyAsString, cfg.first + "-filter", withFilter); + verifier.verify(); } } - } void SearchContextTest::testSearchIteratorConformance() { @@ -976,11 +965,13 @@ SearchContextTest::testSearchIteratorUnpacking(const AttributePtr & attr, Search pos.setElementWeight(100); md.appendPosition(pos); - SearchBasePtr sb = sc.createIterator(&md, strict); + SearchBasePtr sbp = sc.createIterator(&md, strict); + SearchIterator & search = *sbp; + queryeval::ElementIterator::UP elemIt; if (withElementId) { - sb = std::make_unique<attribute::ElementIterator>(std::move(sb), sc, md); + elemIt = std::make_unique<attribute::SearchContextElementIterator>(std::move(sbp), sc); } - sb->initFullRange(); + search.initFullRange(); std::vector<int32_t> weights(3); if (attr->getCollectionType() == CollectionType::SINGLE || @@ -1000,41 +991,40 @@ SearchContextTest::testSearchIteratorUnpacking(const AttributePtr & attr, Search } // unpack and check weights - sb->unpack(1); - EXPECT_EQUAL(sb->getDocId(), 1u); + search.unpack(1); + EXPECT_EQUAL(search.getDocId(), 1u); EXPECT_EQUAL(md.getDocId(), 1u); EXPECT_EQUAL(md.getWeight(), weights[0]); - sb->unpack(2); - EXPECT_EQUAL(sb->getDocId(), 2u); + search.unpack(2); + EXPECT_EQUAL(search.getDocId(), 2u); EXPECT_EQUAL(md.getDocId(), 2u); if (withElementId && attr->hasMultiValue() && !attr->hasWeightedSetType()) { - EXPECT_EQUAL(2, md.end()- md.begin()); - EXPECT_EQUAL(md.begin()[0].getElementId(), 0u); - EXPECT_EQUAL(md.begin()[0].getElementWeight(), 1); - EXPECT_EQUAL(md.begin()[1].getElementId(), 1u); - EXPECT_EQUAL(md.begin()[1].getElementWeight(), 1); + std::vector<uint32_t> elems; + elemIt->getElementIds(2, elems); + ASSERT_EQUAL(2u, elems.size()); + EXPECT_EQUAL(0u,elems[0]); + EXPECT_EQUAL(1u,elems[1]); } else { EXPECT_EQUAL(md.getWeight(), weights[1]); } - sb->unpack(3); - EXPECT_EQUAL(sb->getDocId(), 3u); + search.unpack(3); + EXPECT_EQUAL(search.getDocId(), 3u); EXPECT_EQUAL(md.getDocId(), 3u); if (withElementId && attr->hasMultiValue() && !attr->hasWeightedSetType()) { - EXPECT_EQUAL(3, md.end()- md.begin()); - EXPECT_EQUAL(md.begin()[0].getElementId(), 0u); - EXPECT_EQUAL(md.begin()[0].getElementWeight(), 1); - EXPECT_EQUAL(md.begin()[1].getElementId(), 1u); - EXPECT_EQUAL(md.begin()[1].getElementWeight(), 1); - EXPECT_EQUAL(md.begin()[2].getElementId(), 2u); - EXPECT_EQUAL(md.begin()[2].getElementWeight(), 1); + std::vector<uint32_t> elems; + elemIt->getElementIds(3, elems); + ASSERT_EQUAL(3u, elems.size()); + EXPECT_EQUAL(0u,elems[0]); + EXPECT_EQUAL(1u,elems[1]); + EXPECT_EQUAL(2u,elems[2]); } else { EXPECT_EQUAL(md.getWeight(), weights[2]); } if (extra) { - sb->unpack(4); - EXPECT_EQUAL(sb->getDocId(), 4u); + search.unpack(4); + EXPECT_EQUAL(search.getDocId(), 4u); EXPECT_EQUAL(md.getDocId(), 4u); EXPECT_EQUAL(md.getWeight(), 1); } diff --git a/searchlib/src/tests/attribute/searchcontextelementiterator/CMakeLists.txt b/searchlib/src/tests/attribute/searchcontextelementiterator/CMakeLists.txt new file mode 100644 index 00000000000..1a27b446d30 --- /dev/null +++ b/searchlib/src/tests/attribute/searchcontextelementiterator/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +vespa_add_executable(searchlib_attribute_searchcontextelementiterator_test_app TEST + SOURCES + searchcontextelementiterator_test.cpp + DEPENDS + searchlib + gtest +) +vespa_add_test(NAME searchlib_attribute_searchcontextelementiterator_test_app COMMAND searchlib_attribute_searchcontextelementiterator_test_app) diff --git a/searchlib/src/tests/attribute/searchcontextelementiterator/searchcontextelementiterator_test.cpp b/searchlib/src/tests/attribute/searchcontextelementiterator/searchcontextelementiterator_test.cpp new file mode 100644 index 00000000000..400af6860ec --- /dev/null +++ b/searchlib/src/tests/attribute/searchcontextelementiterator/searchcontextelementiterator_test.cpp @@ -0,0 +1,128 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include <vespa/searchlib/attribute/searchcontextelementiterator.h> +#include <vespa/searchlib/attribute/attributevector.h> +#include <vespa/searchlib/attribute/integerbase.h> +#include <vespa/searchlib/attribute/attributefactory.h> +#include <vespa/searchlib/queryeval/fake_search.h> +#include <vespa/searchlib/query/query_term_simple.h> +#include <vespa/searchlib/fef/termfieldmatchdata.h> +# + +#include <vespa/vespalib/gtest/gtest.h> + +#include <vespa/log/log.h> +LOG_SETUP("searchcontextelementiterator_test"); + +using namespace search::attribute; +using namespace search; + +namespace { + +AttributeVector::SP +createAndFillAttribute() { + AttributeFactory factory; + AttributeVector::SP attribute = factory.createAttribute("mva", Config(BasicType::INT32, CollectionType::ARRAY)); + attribute->addDocs(6); + IntegerAttribute & ia = dynamic_cast<IntegerAttribute &>(*attribute); + ia.append(1, 3, 1); + for (int v : {1,2,3,1,2,3}) { + ia.append(2, v, 1); + } + for (int v : {1,2,3,4,5,1,2,3,4,5,6}) { + ia.append(4, v, 1); + } + ia.append(5, 5, 1); + attribute->commit(); + return attribute; +} + +queryeval::FakeResult +createResult() { + queryeval::FakeResult result; + result.doc(2).elem(0).pos(7).pos(9) + .elem(3).pos(1); + result.doc(4).elem(0).pos(2) + .elem(5).pos(1).pos(2).pos(3); + return result; +} + +void +verifySeek(queryeval::ElementIterator & elemIt) { + elemIt.initFullRange(); + EXPECT_FALSE(elemIt.seek(1)); + EXPECT_TRUE(elemIt.seek(2)); + EXPECT_FALSE(elemIt.seek(3)); + EXPECT_TRUE(elemIt.seek(4)); + EXPECT_FALSE(elemIt.seek(5)); +} + +void +verifyGetElementIds(queryeval::ElementIterator & elemIt, const std::vector<std::vector<uint32_t>> & expectedALL) { + elemIt.initFullRange(); + std::vector<uint32_t> elems; + for (uint32_t docId : {1,2,3,4,5}) { + const auto & expected = expectedALL[docId]; + elems.clear(); + EXPECT_EQ(expected.empty(), !elemIt.seek(docId)); + assert(expected.empty() != elemIt.seek(docId)); + if (elemIt.seek(docId)) { + elemIt.getElementIds(docId, elems); + EXPECT_EQ(expected.size(), elems.size()); + EXPECT_EQ(expected, elems); + } + } +} + +void +verifyMergeElementIds(queryeval::ElementIterator & elemIt, std::vector<uint32_t> initial, const std::vector<std::vector<uint32_t>> & expectedALL) { + elemIt.initFullRange(); + std::vector<uint32_t> elems; + for (uint32_t docId : {1,2,3,4,5}) { + const auto & expected = expectedALL[docId]; + elems = initial; + EXPECT_EQ(expected.empty(), !elemIt.seek(docId)); + assert(expected.empty() != elemIt.seek(docId)); + if (elemIt.seek(docId)) { + elemIt.mergeElementIds(docId, elems); + EXPECT_EQ(expected.size(), elems.size()); + EXPECT_EQ(expected, elems); + } + } +} + +void +verifyElementIterator(queryeval::ElementIterator & elemIt) { + verifySeek(elemIt); + std::vector<std::vector<uint32_t>> expectedALL = {{}, {}, {0, 3}, {}, {0, 5}, {}}; + std::vector<std::vector<uint32_t>> expectedNONE = {{}, {}, {}, {}, {}, {}}; + verifyGetElementIds(elemIt, expectedALL); + verifyMergeElementIds(elemIt, {0,1,2,3,4,5}, expectedALL); + //verifyMergeElementIds(elemIt, {}, expectedNONE); +} + +} + +TEST(ElementIteratorTest, require_that_searchcontext) +{ + AttributeVector::SP attribute = createAndFillAttribute(); + fef::TermFieldMatchData tfmd; + + SearchContextParams params; + ISearchContext::UP sc = attribute->createSearchContext(std::make_unique<QueryTermSimple>("1", QueryTermSimple::SearchTerm::WORD), params); + SearchContextElementIterator elemIt(sc->createIterator(&tfmd, false), *sc); + verifyElementIterator(elemIt); +} + +TEST(ElementIteratorTest, require_that_non_searchcontext) +{ + fef::TermFieldMatchData tfmd; + fef::TermFieldMatchDataArray tfmda; + tfmda.add(&tfmd); + queryeval::FakeResult result = createResult(); + auto search = std::make_unique<queryeval::FakeSearch>("","","", result, tfmda); + queryeval::ElementIteratorWrapper wrapper(std::move(search), tfmd); + verifyElementIterator(wrapper); +} + +GTEST_MAIN_RUN_ALL_TESTS() |