diff options
41 files changed, 1501 insertions, 1442 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 7902f9a017e..f077dd87b9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -143,6 +143,7 @@ add_subdirectory(jdisc-security-filters) add_subdirectory(jrt_test) add_subdirectory(linguistics) add_subdirectory(linguistics-components) +add_subdirectory(lucene-linguistics) add_subdirectory(logd) add_subdirectory(logforwarder) add_subdirectory(logserver) diff --git a/dist/vespa.spec b/dist/vespa.spec index 350db684a02..4424cfd0f8e 100644 --- a/dist/vespa.spec +++ b/dist/vespa.spec @@ -640,6 +640,7 @@ fi %{_prefix}/lib/jars/jdisc-security-filters-jar-with-dependencies.jar %{_prefix}/lib/jars/jna-*.jar %{_prefix}/lib/jars/linguistics-components-jar-with-dependencies.jar +%{_prefix}/lib/jars/lucene-linguistics-jar-with-dependencies.jar %{_prefix}/lib/jars/model-evaluation-jar-with-dependencies.jar %{_prefix}/lib/jars/model-integration-jar-with-dependencies.jar %{_prefix}/lib/jars/security-utils.jar diff --git a/eval/src/vespa/eval/eval/aggr.cpp b/eval/src/vespa/eval/eval/aggr.cpp index a43341dac30..ebb8ab4d6b1 100644 --- a/eval/src/vespa/eval/eval/aggr.cpp +++ b/eval/src/vespa/eval/eval/aggr.cpp @@ -12,12 +12,12 @@ namespace eval { namespace { template <typename T> -struct Wrapper : Aggregator { +struct Wrapper final : Aggregator { T aggr; - virtual void first(double value) final override { aggr = T{value}; } - virtual void next(double value) final override { aggr.sample(value); } - virtual double result() const final override { return aggr.result(); } - virtual Aggr enum_value() const final override { return T::enum_value(); } + void first(double value) override { aggr = T{value}; } + void next(double value) override { aggr.sample(value); } + double result() const override { return aggr.result(); } + Aggr enum_value() const override { return T::enum_value(); } }; } // namespace vespalib::eval::<unnamed> @@ -66,9 +66,7 @@ AggrNames::from_name(const vespalib::string &name) return &(result->second); } -Aggregator::~Aggregator() -{ -} +Aggregator::~Aggregator() = default; Aggregator & Aggregator::create(Aggr aggr, Stash &stash) diff --git a/eval/src/vespa/eval/eval/tensor_nodes.cpp b/eval/src/vespa/eval/eval/tensor_nodes.cpp index ef2718234b2..1143f182f34 100644 --- a/eval/src/vespa/eval/eval/tensor_nodes.cpp +++ b/eval/src/vespa/eval/eval/tensor_nodes.cpp @@ -17,4 +17,175 @@ void TensorCreate ::accept(NodeVisitor &visitor) const { visitor.visit(*thi void TensorLambda ::accept(NodeVisitor &visitor) const { visitor.visit(*this); } void TensorPeek ::accept(NodeVisitor &visitor) const { visitor.visit(*this); } +vespalib::string +TensorMap::dump(DumpContext &ctx) const { + vespalib::string str; + str += "map("; + str += _child->dump(ctx); + str += ","; + str += _lambda->dump_as_lambda(); + str += ")"; + return str; +} + +vespalib::string +TensorMapSubspaces::dump(DumpContext &ctx) const { + vespalib::string str; + str += "map_subspaces("; + str += _child->dump(ctx); + str += ","; + str += _lambda->dump_as_lambda(); + str += ")"; + return str; +} + +vespalib::string +TensorJoin::dump(DumpContext &ctx) const { + vespalib::string str; + str += "join("; + str += _lhs->dump(ctx); + str += ","; + str += _rhs->dump(ctx); + str += ","; + str += _lambda->dump_as_lambda(); + str += ")"; + return str; +} + +vespalib::string +TensorMerge::dump(DumpContext &ctx) const { + vespalib::string str; + str += "join("; + str += _lhs->dump(ctx); + str += ","; + str += _rhs->dump(ctx); + str += ","; + str += _lambda->dump_as_lambda(); + str += ")"; + return str; +} + +vespalib::string +TensorReduce::dump(DumpContext &ctx) const { + vespalib::string str; + str += "reduce("; + str += _child->dump(ctx); + str += ","; + str += *AggrNames::name_of(_aggr); + for (const auto &dimension: _dimensions) { + str += ","; + str += dimension; + } + str += ")"; + return str; +} + +vespalib::string +TensorRename::dump(DumpContext &ctx) const { + vespalib::string str; + str += "rename("; + str += _child->dump(ctx); + str += ","; + str += flatten(_from); + str += ","; + str += flatten(_to); + str += ")"; + return str; +} + +vespalib::string +TensorRename::flatten(const std::vector<vespalib::string> &list) { + if (list.size() == 1) { + return list[0]; + } + vespalib::string str = "("; + for (size_t i = 0; i < list.size(); ++i) { + if (i > 0) { + str += ","; + } + str += list[i]; + } + str += ")"; + return str; +} + +vespalib::string +TensorConcat::dump(DumpContext &ctx) const { + vespalib::string str; + str += "concat("; + str += _lhs->dump(ctx); + str += ","; + str += _rhs->dump(ctx); + str += ","; + str += _dimension; + str += ")"; + return str; +} + +vespalib::string +TensorCellCast::dump(DumpContext &ctx) const { + vespalib::string str; + str += "cell_cast("; + str += _child->dump(ctx); + str += ","; + str += value_type::cell_type_to_name(_cell_type); + str += ")"; + return str; +} + +vespalib::string +TensorCreate::dump(DumpContext &ctx) const { + vespalib::string str = _type.to_spec(); + str += ":{"; + CommaTracker child_list; + for (const Child &child: _cells) { + child_list.maybe_add_comma(str); + str += as_string(child.first); + str += ":"; + str += child.second->dump(ctx); + } + str += "}"; + return str; +} + +vespalib::string +TensorLambda::dump(DumpContext &) const { + vespalib::string str = _type.to_spec(); + vespalib::string expr = _lambda->dump(); + if (starts_with(expr, "(")) { + str += expr; + } else { + str += "("; + str += expr; + str += ")"; + } + return str; +} + +vespalib::string +TensorPeek::dump(DumpContext &ctx) const { + vespalib::string str = _param->dump(ctx); + str += "{"; + CommaTracker dim_list; + for (const auto &dim : _dim_list) { + dim_list.maybe_add_comma(str); + str += dim.first; + str += ":"; + if (dim.second.is_expr()) { + vespalib::string expr = dim.second.expr->dump(ctx); + if (starts_with(expr, "(")) { + str += expr; + } else { + str += "("; + str += expr; + str += ")"; + } + } else { + str += as_quoted_string(dim.second.label); + } + } + str += "}"; + return str; +} + } diff --git a/eval/src/vespa/eval/eval/tensor_nodes.h b/eval/src/vespa/eval/eval/tensor_nodes.h index 6ed19e81712..5de2e4bc80d 100644 --- a/eval/src/vespa/eval/eval/tensor_nodes.h +++ b/eval/src/vespa/eval/eval/tensor_nodes.h @@ -23,15 +23,7 @@ public: : _child(std::move(child)), _lambda(std::move(lambda)) {} const Node &child() const { return *_child; } const Function &lambda() const { return *_lambda; } - vespalib::string dump(DumpContext &ctx) const override { - vespalib::string str; - str += "map("; - str += _child->dump(ctx); - str += ","; - str += _lambda->dump_as_lambda(); - str += ")"; - return str; - } + vespalib::string dump(DumpContext &ctx) const override; void accept(NodeVisitor &visitor) const override; size_t num_children() const override { return 1; } const Node &get_child(size_t idx) const override { @@ -53,15 +45,7 @@ public: : _child(std::move(child)), _lambda(std::move(lambda)) {} const Node &child() const { return *_child; } const Function &lambda() const { return *_lambda; } - vespalib::string dump(DumpContext &ctx) const override { - vespalib::string str; - str += "map_subspaces("; - str += _child->dump(ctx); - str += ","; - str += _lambda->dump_as_lambda(); - str += ")"; - return str; - } + vespalib::string dump(DumpContext &ctx) const override; void accept(NodeVisitor &visitor) const override; size_t num_children() const override { return 1; } const Node &get_child(size_t idx) const override { @@ -85,17 +69,7 @@ public: const Node &lhs() const { return *_lhs; } const Node &rhs() const { return *_rhs; } const Function &lambda() const { return *_lambda; } - vespalib::string dump(DumpContext &ctx) const override { - vespalib::string str; - str += "join("; - str += _lhs->dump(ctx); - str += ","; - str += _rhs->dump(ctx); - str += ","; - str += _lambda->dump_as_lambda(); - str += ")"; - return str; - } + vespalib::string dump(DumpContext &ctx) const override; void accept(NodeVisitor &visitor) const override; size_t num_children() const override { return 2; } const Node &get_child(size_t idx) const override { @@ -119,17 +93,7 @@ public: const Node &lhs() const { return *_lhs; } const Node &rhs() const { return *_rhs; } const Function &lambda() const { return *_lambda; } - vespalib::string dump(DumpContext &ctx) const override { - vespalib::string str; - str += "join("; - str += _lhs->dump(ctx); - str += ","; - str += _rhs->dump(ctx); - str += ","; - str += _lambda->dump_as_lambda(); - str += ")"; - return str; - } + vespalib::string dump(DumpContext &ctx) const override; void accept(NodeVisitor &visitor) const override; size_t num_children() const override { return 2; } const Node &get_child(size_t idx) const override { @@ -153,19 +117,7 @@ public: const Node &child() const { return *_child; } Aggr aggr() const { return _aggr; } const std::vector<vespalib::string> &dimensions() const { return _dimensions; } - vespalib::string dump(DumpContext &ctx) const override { - vespalib::string str; - str += "reduce("; - str += _child->dump(ctx); - str += ","; - str += *AggrNames::name_of(_aggr); - for (const auto &dimension: _dimensions) { - str += ","; - str += dimension; - } - str += ")"; - return str; - } + vespalib::string dump(DumpContext &ctx) const override; void accept(NodeVisitor &visitor) const override; size_t num_children() const override { return 1; } const Node &get_child(size_t idx) const override { @@ -188,17 +140,7 @@ public: const Node &child() const { return *_child; } const std::vector<vespalib::string> &from() const { return _from; } const std::vector<vespalib::string> &to() const { return _to; } - vespalib::string dump(DumpContext &ctx) const override { - vespalib::string str; - str += "rename("; - str += _child->dump(ctx); - str += ","; - str += flatten(_from); - str += ","; - str += flatten(_to); - str += ")"; - return str; - } + vespalib::string dump(DumpContext &ctx) const override; void accept(NodeVisitor &visitor) const override; size_t num_children() const override { return 1; } const Node &get_child(size_t idx) const override { @@ -208,20 +150,7 @@ public: void detach_children(NodeHandler &handler) override { handler.handle(std::move(_child)); } - static vespalib::string flatten(const std::vector<vespalib::string> &list) { - if (list.size() == 1) { - return list[0]; - } - vespalib::string str = "("; - for (size_t i = 0; i < list.size(); ++i) { - if (i > 0) { - str += ","; - } - str += list[i]; - } - str += ")"; - return str; - } + static vespalib::string flatten(const std::vector<vespalib::string> &list); }; class TensorConcat : public Node { @@ -235,17 +164,7 @@ public: const Node &lhs() const { return *_lhs; } const Node &rhs() const { return *_rhs; } const vespalib::string &dimension() const { return _dimension; } - vespalib::string dump(DumpContext &ctx) const override { - vespalib::string str; - str += "concat("; - str += _lhs->dump(ctx); - str += ","; - str += _rhs->dump(ctx); - str += ","; - str += _dimension; - str += ")"; - return str; - } + vespalib::string dump(DumpContext &ctx) const override; void accept(NodeVisitor &visitor) const override; size_t num_children() const override { return 2; } const Node &get_child(size_t idx) const override { @@ -267,15 +186,7 @@ public: : _child(std::move(child)), _cell_type(cell_type) {} const Node &child() const { return *_child; } CellType cell_type() const { return _cell_type; } - vespalib::string dump(DumpContext &ctx) const override { - vespalib::string str; - str += "cell_cast("; - str += _child->dump(ctx); - str += ","; - str += value_type::cell_type_to_name(_cell_type); - str += ")"; - return str; - } + vespalib::string dump(DumpContext &ctx) const override; void accept(NodeVisitor &visitor) const override; size_t num_children() const override { return 1; } const Node &get_child(size_t idx) const override { @@ -305,19 +216,7 @@ public: } } const ValueType &type() const { return _type; } - vespalib::string dump(DumpContext &ctx) const override { - vespalib::string str = _type.to_spec(); - str += ":{"; - CommaTracker child_list; - for (const Child &child: _cells) { - child_list.maybe_add_comma(str); - str += as_string(child.first); - str += ":"; - str += child.second->dump(ctx); - } - str += "}"; - return str; - } + vespalib::string dump(DumpContext &ctx) const override; void accept(NodeVisitor &visitor) const override; size_t num_children() const override { return _cells.size(); } const Node &get_child(size_t idx) const override { @@ -350,18 +249,7 @@ public: const ValueType &type() const { return _type; } const std::vector<size_t> &bindings() const { return _bindings; } const Function &lambda() const { return *_lambda; } - vespalib::string dump(DumpContext &) const override { - vespalib::string str = _type.to_spec(); - vespalib::string expr = _lambda->dump(); - if (starts_with(expr, "(")) { - str += expr; - } else { - str += "("; - str += expr; - str += ")"; - } - return str; - } + vespalib::string dump(DumpContext &) const override; void accept(NodeVisitor &visitor) const override; size_t num_children() const override { return 0; } const Node &get_child(size_t) const override { abort(); } @@ -400,30 +288,7 @@ public: } const Node ¶m() const { return *_param; } const DimList &dim_list() const { return _dim_list; } - vespalib::string dump(DumpContext &ctx) const override { - vespalib::string str = _param->dump(ctx); - str += "{"; - CommaTracker dim_list; - for (const auto &dim: _dim_list) { - dim_list.maybe_add_comma(str); - str += dim.first; - str += ":"; - if (dim.second.is_expr()) { - vespalib::string expr = dim.second.expr->dump(ctx); - if (starts_with(expr, "(")) { - str += expr; - } else { - str += "("; - str += expr; - str += ")"; - } - } else { - str += as_quoted_string(dim.second.label); - } - } - str += "}"; - return str; - } + vespalib::string dump(DumpContext &ctx) const override; void accept(NodeVisitor &visitor) const override; size_t num_children() const override { return (1 + _expr_dims.size()); } const Node &get_child(size_t idx) const override { diff --git a/eval/src/vespa/eval/instruction/generic_reduce.cpp b/eval/src/vespa/eval/instruction/generic_reduce.cpp index 6d845557496..dac8a5ceece 100644 --- a/eval/src/vespa/eval/instruction/generic_reduce.cpp +++ b/eval/src/vespa/eval/instruction/generic_reduce.cpp @@ -8,7 +8,6 @@ #include <vespa/vespalib/util/typify.h> #include <vespa/vespalib/util/overload.h> #include <vespa/vespalib/util/visit_ranges.h> -#include <algorithm> #include <cassert> #include <array> @@ -51,7 +50,7 @@ struct SparseReduceState { SmallVector<string_id*> keep_address; size_t subspace; - SparseReduceState(const SparseReducePlan &plan) + explicit SparseReduceState(const SparseReducePlan &plan) : full_address(plan.keep_dims.size() + plan.num_reduce_dims), fetch_address(full_address.size(), nullptr), keep_address(plan.keep_dims.size(), nullptr), @@ -97,7 +96,8 @@ generic_reduce(const Value &value, const ReduceParam ¶m) { auto zero = builder->add_subspace(); std::fill(zero.begin(), zero.end(), OCT{}); } - return builder->build(std::move(builder)); + auto & builder_ref = *builder; + return builder_ref.build(std::move(builder)); } template <typename ICT, typename OCT, typename AGGR> @@ -311,7 +311,7 @@ GenericReduce::make_instruction(const ValueType &result_type, assert(result_type == param.res_type); assert(result_type.cell_meta().eq(input_type.cell_meta().reduce(result_type.is_double()))); auto fun = typify_invoke<3,ReduceTypify,SelectGenericReduceOp>(input_type.cell_meta(), result_type.cell_meta().is_scalar, aggr, param); - return Instruction(fun, wrap_param<ReduceParam>(param)); + return {fun, wrap_param<ReduceParam>(param)}; } } // namespace diff --git a/lucene-linguistics/CMakeLists.txt b/lucene-linguistics/CMakeLists.txt index efe20451e0f..10ea606798a 100644 --- a/lucene-linguistics/CMakeLists.txt +++ b/lucene-linguistics/CMakeLists.txt @@ -1,2 +1,3 @@ # Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. install_config_definitions() +install_jar(lucene-linguistics-jar-with-dependencies.jar) diff --git a/searchcore/src/vespa/searchcore/proton/matching/termdataextractor.cpp b/searchcore/src/vespa/searchcore/proton/matching/termdataextractor.cpp index ee3c64f3cbb..547c4641fde 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/termdataextractor.cpp +++ b/searchcore/src/vespa/searchcore/proton/matching/termdataextractor.cpp @@ -18,7 +18,7 @@ class TermDataExtractorVisitor vector<const ITermData *> &_term_data; public: - TermDataExtractorVisitor(vector<const ITermData *> &term_data) + explicit TermDataExtractorVisitor(vector<const ITermData *> &term_data) noexcept : _term_data(term_data) { } @@ -29,12 +29,12 @@ public: } } - virtual void visit(ProtonNodeTypes::AndNot &n) override { + void visit(ProtonNodeTypes::AndNot &n) override { assert(n.getChildren().size() > 0); n.getChildren()[0]->accept(*this); } - virtual void visit(ProtonNodeTypes::Equiv &n) override { + void visit(ProtonNodeTypes::Equiv &n) override { // XXX: unranked equiv not supported _term_data.push_back(&n); } diff --git a/searchlib/src/tests/attribute/bitvector/bitvector_test.cpp b/searchlib/src/tests/attribute/bitvector/bitvector_test.cpp index 6e479e1d9db..f9e6340560f 100644 --- a/searchlib/src/tests/attribute/bitvector/bitvector_test.cpp +++ b/searchlib/src/tests/attribute/bitvector/bitvector_test.cpp @@ -9,15 +9,13 @@ #include <vespa/searchlib/parsequery/parse.h> #include <vespa/searchlib/queryeval/docid_with_weight_search_iterator.h> #include <vespa/searchlib/queryeval/executeinfo.h> +#define ENABLE_GTEST_MIGRATION #include <vespa/searchlib/test/searchiteratorverifier.h> #include <vespa/searchlib/util/randomgenerator.h> +#include <vespa/vespalib/gtest/gtest.h> #include <vespa/vespalib/stllike/asciistream.h> -#include <vespa/vespalib/testkit/testapp.h> #include <vespa/vespalib/util/compress.h> -#include <vespa/log/log.h> -LOG_SETUP("bitvector_test"); - using search::AttributeFactory; using search::AttributeVector; using search::BitVector; @@ -37,12 +35,37 @@ using search::queryeval::SearchIterator; using SearchContextPtr = std::unique_ptr<SearchContext>; using SearchBasePtr = std::unique_ptr<search::queryeval::SearchIterator>; -struct BitVectorTest +namespace search::attribute { + +void PrintTo(const BasicType& bt, std::ostream* os) { + *os << bt.asString(); +} + +void PrintTo(const CollectionType& ct, std::ostream* os) { + *os << ct.asString(); +} + +} + +std::string +param_as_string(const testing::TestParamInfo<std::tuple<BasicType, CollectionType, bool, bool>>& info) +{ + std::ostringstream os; + auto& param = info.param; + os << std::get<0>(param).asString() << "_"; + os << std::get<1>(param).asString(); + os << (std::get<2>(param) ? "_fs" : ""); + os << (std::get<3>(param) ? "_filter" : ""); + return os.str(); +} + +class BitVectorTest : public ::testing::TestWithParam<std::tuple<BasicType, CollectionType, bool, bool>> { +public: using AttributePtr = AttributeVector::SP; BitVectorTest(); - ~BitVectorTest(); + ~BitVectorTest() override; template <typename VectorType> VectorType & as(AttributePtr &v); @@ -90,13 +113,9 @@ struct BitVectorTest bool weights, bool checkStride); - template <typename VectorType, typename BufferType> + template <typename VectorType> void test(BasicType bt, CollectionType ct, const vespalib::string &pref, bool fastSearch, bool filter); - - template <typename VectorType, typename BufferType> - void - test(BasicType bt, CollectionType ct, const vespalib::string &pref); }; BitVectorTest::BitVectorTest() = default; @@ -371,29 +390,29 @@ BitVectorTest::checkSearch(AttributePtr v, uint32_t docId = sb->getDocId(); uint32_t lastDocId = 0; uint32_t docFreq = 0; - EXPECT_EQUAL(expFirstDocId, docId); + EXPECT_EQ(expFirstDocId, docId); while (docId != search::endDocId) { lastDocId = docId; ++docFreq, assert(!checkStride || (docId % 5) == 2u); sb->unpack(docId); - EXPECT_EQUAL(md.getDocId(), docId); + EXPECT_EQ(md.getDocId(), docId); if (v->getCollectionType() == CollectionType::SINGLE || !weights) { - EXPECT_EQUAL(1, md.getWeight()); + EXPECT_EQ(1, md.getWeight()); } else if (v->getCollectionType() == CollectionType::ARRAY) { - EXPECT_EQUAL(2, md.getWeight()); + EXPECT_EQ(2, md.getWeight()); } else { if (v->getBasicType() == BasicType::STRING) { - EXPECT_EQUAL(24, md.getWeight()); + EXPECT_EQ(24, md.getWeight()); } else { - EXPECT_EQUAL(-3, md.getWeight()); + EXPECT_EQ(-3, md.getWeight()); } } sb->seek(docId + 1); docId = sb->getDocId(); } - EXPECT_EQUAL(expLastDocId, lastDocId); - EXPECT_EQUAL(expDocFreq, docFreq); + EXPECT_EQ(expLastDocId, lastDocId); + EXPECT_EQ(expDocFreq, docFreq); } @@ -415,7 +434,7 @@ BitVectorTest::checkSearch(AttributePtr v, } -template <typename VectorType, typename BufferType> +template <typename VectorType> void BitVectorTest::test(BasicType bt, CollectionType ct, const vespalib::string &pref, bool fastSearch, bool filter) { @@ -437,7 +456,8 @@ BitVectorTest::test(BasicType bt, CollectionType ct, const vespalib::string &pre TermFieldMatchData md; auto dwsi = std::make_unique<DWSI>(md, *dww, lres); if (!filter) { - TEST_DO(checkSearch(v, std::move(dwsi), md, 2, 1022, 205, !filter, true)); + SCOPED_TRACE("dww without filter"); + checkSearch(v, std::move(dwsi), md, 2, 1022, 205, !filter, true); } else { dwsi->initRange(1, v->getCommittedDocIdLimit()); EXPECT_TRUE(dwsi->isAtEnd()); @@ -457,73 +477,33 @@ BitVectorTest::test(BasicType bt, CollectionType ct, const vespalib::string &pre checkSearch(v, std::move(sc), 2, 14999, 14992, !fastSearch && !filter, false); } - -template <typename VectorType, typename BufferType> -void -BitVectorTest::test(BasicType bt, CollectionType ct, const vespalib::string &pref) -{ - LOG(info, "test run, pref is %s", pref.c_str()); - test<VectorType, BufferType>(bt, ct, pref, false, false); - test<VectorType, BufferType>(bt, ct, pref, false, true); - test<VectorType, BufferType>(bt, ct, pref, true, false); - test<VectorType, BufferType>(bt, ct, pref, true, true); -} - - -TEST_F("Test bitvectors with single value int32", BitVectorTest) -{ - f.template test<IntegerAttribute, - IntegerAttribute::largeint_t>(BasicType::INT32, CollectionType::SINGLE, "int32_sv"); -} - -TEST_F("Test bitvectors with array value int32", BitVectorTest) -{ - f.template test<IntegerAttribute, - IntegerAttribute::largeint_t>(BasicType::INT32, CollectionType::ARRAY, "int32_a"); -} - -TEST_F("Test bitvectors with weighted set value int32", BitVectorTest) -{ - f.template test<IntegerAttribute, - IntegerAttribute::WeightedInt>(BasicType::INT32, CollectionType::WSET, "int32_sv"); -} - -TEST_F("Test bitvectors with single value double", BitVectorTest) -{ - f.template test<FloatingPointAttribute, - double>(BasicType::DOUBLE, CollectionType::SINGLE, "double_sv"); -} - -TEST_F("Test bitvectors with array value double", BitVectorTest) -{ - f.template test<FloatingPointAttribute, - double>(BasicType::DOUBLE, CollectionType::ARRAY, "double_a"); -} - -TEST_F("Test bitvectors with weighted set value double", BitVectorTest) -{ - f.template test<FloatingPointAttribute, - FloatingPointAttribute::WeightedFloat>(BasicType::DOUBLE, CollectionType::WSET, "double_ws"); -} - -TEST_F("Test bitvectors with single value string", BitVectorTest) -{ - f.template test<StringAttribute, - vespalib::string>(BasicType::STRING, CollectionType::SINGLE, "string_sv"); -} - -TEST_F("Test bitvectors with array value string", BitVectorTest) -{ - f.template test<StringAttribute, - vespalib::string>(BasicType::STRING, CollectionType::ARRAY, "string_a"); +TEST_P(BitVectorTest, test_bitvectors) +{ + const auto& param = GetParam(); + auto bt = std::get<0>(param); + auto ct = std::get<1>(param); + auto fast_search = std::get<2>(param); + auto filter = std::get<3>(param); + vespalib::asciistream pref; + pref << bt.asString() << "_" << ct.asString(); + switch (bt.type()) { + case BasicType::INT32: + test<IntegerAttribute>(bt, ct, pref.str(), fast_search, filter); + break; + case BasicType::DOUBLE: + test<FloatingPointAttribute>(bt, ct, pref.str(), fast_search, filter); + break; + case BasicType::STRING: + test<StringAttribute>(bt, ct, pref.str(), fast_search, filter); + break; + default: + FAIL() << "Cannot handle basic type " << bt.asString(); + } } -TEST_F("Test bitvectors with weighted set value string", BitVectorTest) -{ - f.template test<StringAttribute, - StringAttribute::WeightedString>(BasicType::STRING, CollectionType::WSET, "string_ws"); -} +auto test_values = testing::Combine(testing::Values(BasicType::INT32, BasicType::DOUBLE, BasicType::STRING), testing::Values(CollectionType::SINGLE, CollectionType::ARRAY, CollectionType::WSET),testing::Bool(), testing::Bool()); +INSTANTIATE_TEST_SUITE_P(Attributes, BitVectorTest, test_values, param_as_string); class Verifier : public search::test::SearchIteratorVerifier { public: @@ -557,7 +537,8 @@ Verifier::Verifier(bool inverted) } Verifier::~Verifier() = default; -TEST("Test that bitvector iterators adheres to SearchIterator requirements") { +TEST(BitVectorVerifierTest, test_that_bitvector_iterators_adheres_to_SearchIterator_requirements) +{ { Verifier searchIteratorVerifier(false); searchIteratorVerifier.verify(); @@ -568,4 +549,4 @@ TEST("Test that bitvector iterators adheres to SearchIterator requirements") { } } -TEST_MAIN() { TEST_RUN_ALL(); } +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/searchlib/src/tests/attribute/searchcontext/searchcontext_test.cpp b/searchlib/src/tests/attribute/searchcontext/searchcontext_test.cpp index 85b13c20f88..77acbe046ca 100644 --- a/searchlib/src/tests/attribute/searchcontext/searchcontext_test.cpp +++ b/searchlib/src/tests/attribute/searchcontext/searchcontext_test.cpp @@ -18,9 +18,10 @@ #include <vespa/searchlib/queryeval/hitcollector.h> #include <vespa/searchlib/queryeval/simpleresult.h> #include <vespa/searchlib/test/attribute_builder.h> +#define ENABLE_GTEST_MIGRATION #include <vespa/searchlib/test/searchiteratorverifier.h> +#include <vespa/vespalib/gtest/gtest.h> #include <vespa/vespalib/stllike/asciistream.h> -#include <vespa/vespalib/testkit/testapp.h> #include <vespa/vespalib/util/compress.h> #include <vespa/vespalib/util/simple_thread_bundle.h> #include <vespa/vespalib/util/stringfmt.h> @@ -142,7 +143,7 @@ public: DocRange(uint32_t start_, uint32_t end_) : start(start_), end(end_) {} }; -class SearchContextTest : public vespalib::TestApp +class SearchContextTest : public ::testing::Test { public: // helper functions @@ -150,7 +151,7 @@ public: static void addDocs(AttributeVector & ptr, uint32_t numDocs); template <typename V, typename T> static SearchContextPtr getSearch(const V & vec, const T & term, TermType termType=TermType::WORD); -private: +protected: using ConfigMap = std::map<vespalib::string, Config>; // Map of all config objects ConfigMap _integerCfg; @@ -185,7 +186,6 @@ private: template<typename T, typename A> void testSearchIterator(const std::vector<T> & keys, const vespalib::string &keyAsString, const ConfigMap &cfgs); - void testSearchIteratorConformance(); // test search functionality template <typename V, typename T> void testFind(const PostingList<V, T> & first, bool verify_hit_estimate); @@ -198,7 +198,6 @@ private: void testMultiValueSearchHelper(V & vec, const std::vector<T> & values); template <typename V, typename T> void testMultiValueSearch(V& attr, uint32_t num_docs, const std::vector<T> & values); - void testSearch(); class IteratorTester { public: @@ -237,7 +236,6 @@ private: void testNonStrictSearchIterator(SearchContext & threeHits, SearchContext & noHits, const IteratorTester & typeTester); AttributePtr fillForSearchIteratorTest(const vespalib::string& name, const Config& cfg); AttributePtr fillForSemiNibbleSearchIteratorTest(const vespalib::string& name, const Config& cfg); - void testSearchIterator(); // test search iterator unpacking @@ -250,7 +248,6 @@ private: } void testSearchIteratorUnpacking(const AttributePtr & ptr, SearchContext & sc, bool extra, bool strict, bool withElementId); - void testSearchIteratorUnpacking(); // test range search @@ -258,58 +255,41 @@ private: void performRangeSearch(const VectorType & vec, const vespalib::string & term, const DocSet & expected); template <typename VectorType, typename ValueType> void testRangeSearch(const AttributePtr & ptr, uint32_t numDocs, std::vector<ValueType> values); - void testRangeSearch(); - void testRangeSearchLimited(); - void testRangeSearchLimitedHugeDictionary(); // test case insensitive search void performCaseInsensitiveSearch(const StringAttribute & vec, const vespalib::string & term, const DocSet & expected); void testCaseInsensitiveSearch(const AttributePtr & ptr); - void testCaseInsensitiveSearch(); void testRegexSearch(const vespalib::string& name, const Config& cfg); - void testRegexSearch(); // test prefix search void testPrefixSearch(const vespalib::string& name, const Config& cfg); - void testPrefixSearch(); // test fuzzy search void testFuzzySearch(const vespalib::string& name, const Config& cfg); - void testFuzzySearch(); // test that search is working after clear doc template <typename VectorType, typename ValueType> void requireThatSearchIsWorkingAfterClearDoc(const vespalib::string & name, const Config & cfg, ValueType startValue, const vespalib::string & term); - void requireThatSearchIsWorkingAfterClearDoc(); // test that search is working after load and clear doc template <typename VectorType, typename ValueType> void requireThatSearchIsWorkingAfterLoadAndClearDoc(const vespalib::string & name, const Config & cfg, ValueType startValue, ValueType defaultValue, const vespalib::string & term); - void requireThatSearchIsWorkingAfterLoadAndClearDoc(); template <typename VectorType, typename ValueType> void requireThatSearchIsWorkingAfterUpdates(const vespalib::string & name, const Config & cfg, ValueType value1, ValueType value2); - void requireThatSearchIsWorkingAfterUpdates(); - void requireThatFlagAttributeIsWorkingWhenNewDocsAreAdded(); template <typename VectorType, typename ValueType> void requireThatInvalidSearchTermGivesZeroHits(const vespalib::string & name, const Config & cfg, ValueType value); - void requireThatInvalidSearchTermGivesZeroHits(); - void requireThatFlagAttributeHandlesTheByteRange(); void requireThatOutOfBoundsSearchTermGivesZeroHits(const vespalib::string &name, const Config &cfg, int32_t maxValue); - void requireThatOutOfBoundsSearchTermGivesZeroHits(); - - void single_bool_attribute_search_context_handles_true_and_false_queries(); - void single_bool_attribute_search_iterator_handles_true_and_false_queries(); // init maps with config objects void initIntegerConfig(); @@ -319,7 +299,6 @@ private: public: SearchContextTest(); ~SearchContextTest() override; - int Main() override; }; @@ -337,7 +316,7 @@ SearchContextTest::addDocs(AttributeVector & ptr, uint32_t numDocs) addReservedDoc(ptr); for (uint32_t i = 1; i <= numDocs; ++i) { ptr.addDoc(docId); - EXPECT_EQUAL(docId, i); + EXPECT_EQ(docId, i); } ASSERT_TRUE(ptr.getNumDocs() == numDocs + 1); } @@ -531,7 +510,7 @@ SearchContextTest::performSearch(const V & vec, const vespalib::string & term, void SearchContextTest::checkResultSet(const ResultSet & rs, const DocSet & expected, bool bitVector) { - EXPECT_EQUAL(rs.getNumHits(), expected.size()); + EXPECT_EQ(rs.getNumHits(), expected.size()); if (bitVector) { const BitVector * vec = rs.getBitOverflow(); if ( ! expected.empty()) { @@ -546,7 +525,7 @@ SearchContextTest::checkResultSet(const ResultSet & rs, const DocSet & expected, ASSERT_TRUE(array != nullptr); uint32_t i = 0; for (auto iter = expected.begin(); iter != expected.end(); ++iter, ++i) { - EXPECT_EQUAL(array[i].getDocId(), *iter); + EXPECT_EQ(array[i].getDocId(), *iter); } } } @@ -565,8 +544,8 @@ SearchContextTest::testFind(const PostingList<V, T> & pl, bool verify_hit_estima if (verify_hit_estimate) { auto act_est = sc->calc_hit_estimate(); auto exp_est = pl.expected_hit_estimate(); - EXPECT_EQUAL(exp_est.est_hits(), act_est.est_hits()); - EXPECT_EQUAL(exp_est.is_unknown(), act_est.is_unknown()); + EXPECT_EQ(exp_est.est_hits(), act_est.est_hits()); + EXPECT_EQ(exp_est.is_unknown(), act_est.is_unknown()); } sc->fetchPostings(queryeval::ExecuteInfo::TRUE); TermFieldMatchData dummy; @@ -721,7 +700,7 @@ Verifier<T, A>::Verifier(const std::vector<T> & keys, const vespalib::string & k } _attribute->commit(true); _sc = SearchContextTest::getSearch(*_attribute, keyAsString); - ASSERT_TRUE(_sc->valid()); + EXPECT_TRUE(_sc->valid()); } template<typename T, typename A> @@ -743,15 +722,15 @@ void SearchContextTest::testSearchIterator(const std::vector<T> & keys, const ve } } -void SearchContextTest::testSearchIteratorConformance() { +TEST_F(SearchContextTest, test_search_iterator_conformance) +{ testSearchIterator<AttributeVector::largeint_t, IntegerAttribute>({42,45,46}, "[0;100]", _integerCfg); testSearchIterator<AttributeVector::largeint_t, IntegerAttribute>({42}, "42", _integerCfg); testSearchIterator<double, FloatingPointAttribute>({42.42}, "42.42", _floatCfg); testSearchIterator<vespalib::string, StringAttribute>({"any-key"}, "any-key", _stringCfg); } -void -SearchContextTest::testSearch() +TEST_F(SearchContextTest, test_search) { const uint32_t numDocs = 100; const uint32_t numUniques = 20; @@ -812,15 +791,15 @@ SearchContextTest::testStrictSearchIterator(SearchContext & threeHits, EXPECT_TRUE(sb->getDocId() == sb->beginId() || sb->getDocId() == 1u); EXPECT_TRUE(sb->seek(1)); - EXPECT_EQUAL(sb->getDocId(), 1u); + EXPECT_EQ(sb->getDocId(), 1u); EXPECT_TRUE(!sb->seek(2)); - EXPECT_EQUAL(sb->getDocId(), 3u); + EXPECT_EQ(sb->getDocId(), 3u); EXPECT_TRUE(sb->seek(3)); - EXPECT_EQUAL(sb->getDocId(), 3u); + EXPECT_EQ(sb->getDocId(), 3u); EXPECT_TRUE(!sb->seek(4)); - EXPECT_EQUAL(sb->getDocId(), 5u); + EXPECT_EQ(sb->getDocId(), 5u); EXPECT_TRUE(sb->seek(5)); - EXPECT_EQUAL(sb->getDocId(), 5u); + EXPECT_EQ(sb->getDocId(), 5u); EXPECT_TRUE(!sb->seek(6)); EXPECT_TRUE(sb->isAtEnd()); } @@ -849,15 +828,15 @@ SearchContextTest::testNonStrictSearchIterator(SearchContext & threeHits, sb->initRange(1, threeHits.attribute().getCommittedDocIdLimit()); EXPECT_TRUE(typeTester.matches(*sb)); EXPECT_TRUE(sb->seek(1)); - EXPECT_EQUAL(sb->getDocId(), 1u); + EXPECT_EQ(sb->getDocId(), 1u); EXPECT_TRUE(!sb->seek(2)); - EXPECT_EQUAL(sb->getDocId(), 1u); + EXPECT_EQ(sb->getDocId(), 1u); EXPECT_TRUE(sb->seek(3)); - EXPECT_EQUAL(sb->getDocId(), 3u); + EXPECT_EQ(sb->getDocId(), 3u); EXPECT_TRUE(!sb->seek(4)); - EXPECT_EQUAL(sb->getDocId(), 3u); + EXPECT_EQ(sb->getDocId(), 3u); EXPECT_TRUE(sb->seek(5)); - EXPECT_EQUAL(sb->getDocId(), 5u); + EXPECT_EQ(sb->getDocId(), 5u); EXPECT_TRUE(!sb->seek(6)); EXPECT_TRUE(sb->getDocId() == 5u || sb->isAtEnd()); } @@ -870,9 +849,9 @@ SearchContextTest::testNonStrictSearchIterator(SearchContext & threeHits, EXPECT_TRUE(sb->getDocId() == sb->beginId() || sb->isAtEnd()); EXPECT_TRUE(!sb->seek(1)); - EXPECT_NOT_EQUAL(sb->getDocId(), 1u); + EXPECT_NE(sb->getDocId(), 1u); EXPECT_TRUE(!sb->seek(6)); - EXPECT_NOT_EQUAL(sb->getDocId(), 6u); + EXPECT_NE(sb->getDocId(), 6u); } } @@ -888,8 +867,7 @@ SearchContextTest::fillForSemiNibbleSearchIteratorTest(const vespalib::string& n return AttributeBuilder(name, cfg).fill({1, 2, 1, 2, 1}).get(); } -void -SearchContextTest::testSearchIterator() +TEST_F(SearchContextTest, test_search_iterator) { { Config cfg(BasicType::INT32, CollectionType::SINGLE); @@ -1031,46 +1009,45 @@ SearchContextTest::testSearchIteratorUnpacking(const AttributePtr & attr, Search // unpack and check weights search.unpack(1); - EXPECT_EQUAL(search.getDocId(), 1u); - EXPECT_EQUAL(md.getDocId(), 1u); - EXPECT_EQUAL(md.getWeight(), weights[0]); + EXPECT_EQ(search.getDocId(), 1u); + EXPECT_EQ(md.getDocId(), 1u); + EXPECT_EQ(md.getWeight(), weights[0]); search.unpack(2); - EXPECT_EQUAL(search.getDocId(), 2u); - EXPECT_EQUAL(md.getDocId(), 2u); + EXPECT_EQ(search.getDocId(), 2u); + EXPECT_EQ(md.getDocId(), 2u); if (withElementId && attr->hasMultiValue() && !attr->hasWeightedSetType()) { std::vector<uint32_t> elems; elemIt->getElementIds(2, elems); - ASSERT_EQUAL(2u, elems.size()); - EXPECT_EQUAL(0u,elems[0]); - EXPECT_EQUAL(1u,elems[1]); + ASSERT_EQ(2u, elems.size()); + EXPECT_EQ(0u,elems[0]); + EXPECT_EQ(1u,elems[1]); } else { - EXPECT_EQUAL(md.getWeight(), weights[1]); + EXPECT_EQ(md.getWeight(), weights[1]); } search.unpack(3); - EXPECT_EQUAL(search.getDocId(), 3u); - EXPECT_EQUAL(md.getDocId(), 3u); + EXPECT_EQ(search.getDocId(), 3u); + EXPECT_EQ(md.getDocId(), 3u); if (withElementId && attr->hasMultiValue() && !attr->hasWeightedSetType()) { 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]); + ASSERT_EQ(3u, elems.size()); + EXPECT_EQ(0u,elems[0]); + EXPECT_EQ(1u,elems[1]); + EXPECT_EQ(2u,elems[2]); } else { - EXPECT_EQUAL(md.getWeight(), weights[2]); + EXPECT_EQ(md.getWeight(), weights[2]); } if (extra) { search.unpack(4); - EXPECT_EQUAL(search.getDocId(), 4u); - EXPECT_EQUAL(md.getDocId(), 4u); - EXPECT_EQUAL(md.getWeight(), 1); + EXPECT_EQ(search.getDocId(), 4u); + EXPECT_EQ(md.getDocId(), 4u); + EXPECT_EQ(md.getWeight(), 1); } } -void -SearchContextTest::testSearchIteratorUnpacking() +TEST_F(SearchContextTest, test_search_iterator_unpacking) { std::vector<std::pair<vespalib::string, Config> > config; @@ -1242,8 +1219,8 @@ createDocs(uint32_t from, int32_t count) { return docs; } -void -SearchContextTest::testRangeSearchLimitedHugeDictionary() { +TEST_F(SearchContextTest, test_range_search_limited_huge_dictionary) +{ Config cfg(BasicType::INT32, CollectionType::SINGLE); cfg.setFastSearch(true); std::vector<int32_t> v; @@ -1263,8 +1240,7 @@ SearchContextTest::testRangeSearchLimitedHugeDictionary() { performRangeSearch(vec, "[1;3009;-1200]", createDocs(2000, -1200)); } -void -SearchContextTest::testRangeSearchLimited() +TEST_F(SearchContextTest, test_range_search_limited) { Config cfg(BasicType::INT32, CollectionType::SINGLE); cfg.setFastSearch(true); @@ -1317,8 +1293,7 @@ SearchContextTest::testRangeSearchLimited() performRangeSearch(vec, "[;;-1]", expected); } -void -SearchContextTest::testRangeSearch() +TEST_F(SearchContextTest, test_range_search) { const uint32_t numDocs = 100; const uint32_t numValues = 20; @@ -1412,8 +1387,8 @@ SearchContextTest::testCaseInsensitiveSearch(const AttributePtr & ptr) doc = 1; for (uint32_t j = 0; j < 5; ++j) { for (uint32_t i = 0; i < 5; ++i) { - EXPECT_EQUAL(ptr->get(doc++, buffer, 1), uint32_t(1)); - EXPECT_EQUAL(vespalib::string(buffer[0]), vespalib::string(terms[i][j])); + EXPECT_EQ(ptr->get(doc++, buffer, 1), uint32_t(1)); + EXPECT_EQ(vespalib::string(buffer[0]), vespalib::string(terms[i][j])); } } @@ -1462,16 +1437,14 @@ SearchContextTest::testRegexSearch(const vespalib::string& name, const Config& c } -void -SearchContextTest::testCaseInsensitiveSearch() +TEST_F(SearchContextTest, test_case_insensitive_search) { for (const auto & cfg : _stringCfg) { testCaseInsensitiveSearch(AttributeFactory::createAttribute(cfg.first, cfg.second)); } } -void -SearchContextTest::testRegexSearch() +TEST_F(SearchContextTest, test_regex_search) { for (const auto & cfg : _stringCfg) { testRegexSearch(cfg.first, cfg.second); @@ -1534,8 +1507,7 @@ SearchContextTest::testPrefixSearch(const vespalib::string& name, const Config& } -void -SearchContextTest::testPrefixSearch() +TEST_F(SearchContextTest, test_prefix_search) { for (const auto & cfg : _stringCfg) { testPrefixSearch(cfg.first, cfg.second); @@ -1570,8 +1542,7 @@ SearchContextTest::testFuzzySearch(const vespalib::string& name, const Config& c } } -void -SearchContextTest::testFuzzySearch() +TEST_F(SearchContextTest, test_fuzzy_search) { for (const auto & cfg : _stringCfg) { testFuzzySearch(cfg.first, cfg.second); @@ -1595,28 +1566,27 @@ SearchContextTest::requireThatSearchIsWorkingAfterClearDoc(const vespalib::strin resetAttribute(v, startValue); { ResultSetPtr rs = performSearch(v, term); - EXPECT_EQUAL(4u, rs->getNumHits()); + EXPECT_EQ(4u, rs->getNumHits()); ASSERT_TRUE(4u == rs->getNumHits()); const RankedHit * array = rs->getArray(); - EXPECT_EQUAL(1u, array[0].getDocId()); - EXPECT_EQUAL(2u, array[1].getDocId()); - EXPECT_EQUAL(3u, array[2].getDocId()); - EXPECT_EQUAL(4u, array[3].getDocId()); + EXPECT_EQ(1u, array[0].getDocId()); + EXPECT_EQ(2u, array[1].getDocId()); + EXPECT_EQ(3u, array[2].getDocId()); + EXPECT_EQ(4u, array[3].getDocId()); } a->clearDoc(1); a->clearDoc(3); a->commit(true); { ResultSetPtr rs = performSearch(v, term); - EXPECT_EQUAL(2u, rs->getNumHits()); + EXPECT_EQ(2u, rs->getNumHits()); const RankedHit * array = rs->getArray(); - EXPECT_EQUAL(2u, array[0].getDocId()); - EXPECT_EQUAL(4u, array[1].getDocId()); + EXPECT_EQ(2u, array[0].getDocId()); + EXPECT_EQ(4u, array[1].getDocId()); } } -void -SearchContextTest::requireThatSearchIsWorkingAfterClearDoc() +TEST_F(SearchContextTest, require_that_search_is_working_after_clear_doc) { for (const auto & cfg : _integerCfg) { requireThatSearchIsWorkingAfterClearDoc<IntegerAttribute>(cfg.first, cfg.second, 10, "10"); @@ -1655,26 +1625,25 @@ SearchContextTest::requireThatSearchIsWorkingAfterLoadAndClearDoc(const vespalib b->commit(true); { ResultSetPtr rs = performSearch(dynamic_cast<VectorType &>(*b), term); - EXPECT_EQUAL(14u, rs->getNumHits()); + EXPECT_EQ(14u, rs->getNumHits()); const RankedHit * array = rs->getArray(); for (uint32_t i = 0; i < 14; ++i) { if (i < 5) { - EXPECT_EQUAL(i + 1, array[i].getDocId()); + EXPECT_EQ(i + 1, array[i].getDocId()); } else - EXPECT_EQUAL(i + 2, array[i].getDocId()); + EXPECT_EQ(i + 2, array[i].getDocId()); } } ValueType buf; if (cfg.collectionType().isMultiValue()) { - EXPECT_EQUAL(0u, b->get(6, &buf, 1)); + EXPECT_EQ(0u, b->get(6, &buf, 1)); } else { - EXPECT_EQUAL(1u, b->get(6, &buf, 1)); - EXPECT_EQUAL(defaultValue, buf); + EXPECT_EQ(1u, b->get(6, &buf, 1)); + EXPECT_EQ(defaultValue, buf); } } -void -SearchContextTest::requireThatSearchIsWorkingAfterLoadAndClearDoc() +TEST_F(SearchContextTest, require_that_search_is_working_after_load_and_clear_doc) { { int64_t value = 10; @@ -1713,16 +1682,15 @@ SearchContextTest::requireThatSearchIsWorkingAfterUpdates(const vespalib::string va.commit(true); { ResultSetPtr rs = performSearch(va, value1); - EXPECT_EQUAL(1u, rs->getNumHits()); // doc 1 should not have this value + EXPECT_EQ(1u, rs->getNumHits()); // doc 1 should not have this value } { ResultSetPtr rs = performSearch(va, value2); - EXPECT_EQUAL(1u, rs->getNumHits()); + EXPECT_EQ(1u, rs->getNumHits()); } } -void -SearchContextTest::requireThatSearchIsWorkingAfterUpdates() +TEST_F(SearchContextTest, require_that_search_is_working_after_updates) { for (const auto & cfg : _integerCfg) { requireThatSearchIsWorkingAfterUpdates<IntegerAttribute>(cfg.first, cfg.second, 10, 20); @@ -1733,8 +1701,7 @@ SearchContextTest::requireThatSearchIsWorkingAfterUpdates() } } -void -SearchContextTest::requireThatFlagAttributeIsWorkingWhenNewDocsAreAdded() +TEST_F(SearchContextTest, require_that_flag_attribute_is_working_when_new_docs_are_added) { LOG(info, "requireThatFlagAttributeIsWorkingWhenNewDocsAreAdded()"); Config cfg(BasicType::INT8, CollectionType::ARRAY); @@ -1746,16 +1713,16 @@ SearchContextTest::requireThatFlagAttributeIsWorkingWhenNewDocsAreAdded() fill_array({IL{10, 24}, {20, 24}, {30, 26}, {40, 24}}).get(); { ResultSetPtr rs = performSearch(*a, "<24"); - EXPECT_EQUAL(2u, rs->getNumHits()); - EXPECT_EQUAL(1u, rs->getArray()[0].getDocId()); - EXPECT_EQUAL(2u, rs->getArray()[1].getDocId()); + EXPECT_EQ(2u, rs->getNumHits()); + EXPECT_EQ(1u, rs->getArray()[0].getDocId()); + EXPECT_EQ(2u, rs->getArray()[1].getDocId()); } { ResultSetPtr rs = performSearch(*a, "24"); - EXPECT_EQUAL(3u, rs->getNumHits()); - EXPECT_EQUAL(1u, rs->getArray()[0].getDocId()); - EXPECT_EQUAL(2u, rs->getArray()[1].getDocId()); - EXPECT_EQUAL(4u, rs->getArray()[2].getDocId()); + EXPECT_EQ(3u, rs->getNumHits()); + EXPECT_EQ(1u, rs->getArray()[0].getDocId()); + EXPECT_EQ(2u, rs->getArray()[1].getDocId()); + EXPECT_EQ(4u, rs->getArray()[2].getDocId()); } } { @@ -1779,18 +1746,18 @@ SearchContextTest::requireThatFlagAttributeIsWorkingWhenNewDocsAreAdded() { ResultSetPtr rs1 = performSearch(fa, "50"); ResultSetPtr rs2 = performSearch(fa, "<51"); - EXPECT_EQUAL(exp50.size(), rs1->getNumHits()); - EXPECT_EQUAL(exp50.size(), rs2->getNumHits()); + EXPECT_EQ(exp50.size(), rs1->getNumHits()); + EXPECT_EQ(exp50.size(), rs2->getNumHits()); for (size_t j = 0; j < exp50.size(); ++j) { - EXPECT_EQUAL(exp50[j], rs1->getArray()[j].getDocId()); - EXPECT_EQUAL(exp50[j], rs2->getArray()[j].getDocId()); + EXPECT_EQ(exp50[j], rs1->getArray()[j].getDocId()); + EXPECT_EQ(exp50[j], rs2->getArray()[j].getDocId()); } } { ResultSetPtr rs = performSearch(fa, "60"); - EXPECT_EQUAL(exp60.size(), rs->getNumHits()); + EXPECT_EQ(exp60.size(), rs->getNumHits()); for (size_t j = 0; j < exp60.size(); ++j) { - EXPECT_EQUAL(exp60[j], rs->getArray()[j].getDocId()); + EXPECT_EQ(exp60[j], rs->getArray()[j].getDocId()); } } } @@ -1806,11 +1773,10 @@ SearchContextTest::requireThatInvalidSearchTermGivesZeroHits(const vespalib::str auto a = AttributeBuilder(name, cfg).fill({value}).get(); LOG(info, "requireThatInvalidSearchTermGivesZeroHits: vector '%s'", a->getName().c_str()); ResultSetPtr rs = performSearch(*a, "foo"); - EXPECT_EQUAL(0u, rs->getNumHits()); + EXPECT_EQ(0u, rs->getNumHits()); } -void -SearchContextTest::requireThatInvalidSearchTermGivesZeroHits() +TEST_F(SearchContextTest, require_that_invalid_search_term_gives_zero_hits) { for (const auto & cfg : _integerCfg) { requireThatInvalidSearchTermGivesZeroHits<IntegerAttribute, int32_t>(cfg.first, cfg.second, 10); @@ -1820,8 +1786,7 @@ SearchContextTest::requireThatInvalidSearchTermGivesZeroHits() } } -void -SearchContextTest::requireThatFlagAttributeHandlesTheByteRange() +TEST_F(SearchContextTest, require_that_flag_attribute_handles_the_byte_range) { LOG(info, "requireThatFlagAttributeHandlesTheByteRange()"); Config cfg(BasicType::INT8, CollectionType::ARRAY); @@ -1850,11 +1815,10 @@ SearchContextTest::requireThatOutOfBoundsSearchTermGivesZeroHits(const vespalib: vespalib::string term = vespalib::make_string("%" PRIu64 "", (int64_t) maxValue + 1); LOG(info, "requireThatOutOfBoundsSearchTermGivesZeroHits: vector '%s', term '%s'", a->getName().c_str(), term.c_str()); ResultSetPtr rs = performSearch(*a, term); - EXPECT_EQUAL(0u, rs->getNumHits()); + EXPECT_EQ(0u, rs->getNumHits()); } -void -SearchContextTest::requireThatOutOfBoundsSearchTermGivesZeroHits() +TEST_F(SearchContextTest, require_that_out_of_bounds_search_term_gives_zero_hits) { for (const auto & cfg : _integerCfg) { int32_t maxValue = std::numeric_limits<int32_t>::max(); @@ -1894,8 +1858,8 @@ public: for (uint32_t docid = 1; docid < _attr.getNumDocs(); ++docid) { bool match_1 = search_ctx->matches(docid); bool match_2 = search_ctx->matches(docid, weight); - EXPECT_EQUAL(match_1, match_2); - EXPECT_EQUAL(match_2 ? 1 : 0, weight); + EXPECT_EQ(match_1, match_2); + EXPECT_EQ(match_2 ? 1 : 0, weight); if (match_1) { result.addHit(docid); } @@ -1917,36 +1881,34 @@ public: } }; -void -SearchContextTest::single_bool_attribute_search_context_handles_true_and_false_queries() +TEST_F(SearchContextTest, single_bool_attribute_search_context_handles_true_and_false_queries) { BoolAttributeFixture f(SimpleResult().addHit(3).addHit(5).addHit(7), 9); auto true_exp = SimpleResult().addHit(3).addHit(5).addHit(7); - EXPECT_EQUAL(true_exp, f.search_context("true")); - EXPECT_EQUAL(true_exp, f.search_context("1")); + EXPECT_EQ(true_exp, f.search_context("true")); + EXPECT_EQ(true_exp, f.search_context("1")); auto false_exp = SimpleResult().addHit(1).addHit(2).addHit(4).addHit(6).addHit(8); - EXPECT_EQUAL(false_exp, f.search_context("false")); - EXPECT_EQUAL(false_exp, f.search_context("0")); + EXPECT_EQ(false_exp, f.search_context("false")); + EXPECT_EQ(false_exp, f.search_context("0")); } -void -SearchContextTest::single_bool_attribute_search_iterator_handles_true_and_false_queries() +TEST_F(SearchContextTest, single_bool_attribute_search_iterator_handles_true_and_false_queries) { BoolAttributeFixture f(SimpleResult().addHit(3).addHit(5).addHit(7), 9); auto true_exp = SimpleResult().addHit(3).addHit(5).addHit(7); - EXPECT_EQUAL(true_exp, f.search_iterator("true", false)); - EXPECT_EQUAL(true_exp, f.search_iterator("1", false)); - EXPECT_EQUAL(true_exp, f.search_iterator("true", true)); - EXPECT_EQUAL(true_exp, f.search_iterator("1", true)); + EXPECT_EQ(true_exp, f.search_iterator("true", false)); + EXPECT_EQ(true_exp, f.search_iterator("1", false)); + EXPECT_EQ(true_exp, f.search_iterator("true", true)); + EXPECT_EQ(true_exp, f.search_iterator("1", true)); auto false_exp = SimpleResult().addHit(1).addHit(2).addHit(4).addHit(6).addHit(8); - EXPECT_EQUAL(false_exp, f.search_iterator("false", false)); - EXPECT_EQUAL(false_exp, f.search_iterator("0", false)); - EXPECT_EQUAL(false_exp, f.search_iterator("false", true)); - EXPECT_EQUAL(false_exp, f.search_iterator("0", true)); + EXPECT_EQ(false_exp, f.search_iterator("false", false)); + EXPECT_EQ(false_exp, f.search_iterator("0", false)); + EXPECT_EQ(false_exp, f.search_iterator("false", true)); + EXPECT_EQ(false_exp, f.search_iterator("0", true)); } void @@ -2057,36 +2019,6 @@ SearchContextTest::SearchContextTest() : SearchContextTest::~SearchContextTest() = default; -int -SearchContextTest::Main() -{ - TEST_INIT("searchcontext_test"); - EXPECT_TRUE(true); - - testSearch(); - testSearchIterator(); - testRangeSearch(); - testRangeSearchLimited(); - testRangeSearchLimitedHugeDictionary(); - testCaseInsensitiveSearch(); - testRegexSearch(); - testPrefixSearch(); - testSearchIteratorConformance(); - testSearchIteratorUnpacking(); - testFuzzySearch(); - TEST_DO(requireThatSearchIsWorkingAfterClearDoc()); - TEST_DO(requireThatSearchIsWorkingAfterLoadAndClearDoc()); - TEST_DO(requireThatSearchIsWorkingAfterUpdates()); - TEST_DO(requireThatFlagAttributeIsWorkingWhenNewDocsAreAdded()); - TEST_DO(requireThatInvalidSearchTermGivesZeroHits()); - TEST_DO(requireThatFlagAttributeHandlesTheByteRange()); - TEST_DO(requireThatOutOfBoundsSearchTermGivesZeroHits()); - TEST_DO(single_bool_attribute_search_context_handles_true_and_false_queries()); - TEST_DO(single_bool_attribute_search_iterator_handles_true_and_false_queries()); - - TEST_DONE(); -} - } -TEST_APPHOOK(search::SearchContextTest); +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/searchlib/src/tests/features/beta/beta_features_test.cpp b/searchlib/src/tests/features/beta/beta_features_test.cpp index 8413cfde47f..3a476b3682b 100644 --- a/searchlib/src/tests/features/beta/beta_features_test.cpp +++ b/searchlib/src/tests/features/beta/beta_features_test.cpp @@ -13,8 +13,10 @@ #include <vespa/searchlib/features/termeditdistancefeature.h> #include <vespa/searchlib/features/utils.h> #include <vespa/searchlib/fef/test/plugin/setup.h> +#define ENABLE_GTEST_MIGRATION +#include <vespa/searchlib/test/ft_test_app_base.h> +#include <vespa/vespalib/gtest/gtest.h> #include <vespa/vespalib/util/rand48.h> -#include <vespa/searchlib/test/ft_test_app.h> #include <vespa/vespalib/util/stringfmt.h> using namespace search::features; @@ -25,56 +27,33 @@ using CollectionType = FieldInfo::CollectionType; //--------------------------------------------------------------------------------------------------------------------- // Test //--------------------------------------------------------------------------------------------------------------------- -class Test : public FtTestApp { -public: - Test(); - ~Test() override; - int Main() override; - void testJaroWinklerDistance(); - void testProximity(); - void testFlowCompleteness(); - void testQueryCompleteness(); - void testReverseProximity(); - void testTermEditDistance(); - -private: +class BetaFeaturesTest : public ::testing::Test, + public FtTestAppBase +{ +protected: + search::fef::BlueprintFactory _factory; + + BetaFeaturesTest(); + ~BetaFeaturesTest() override; + void assertJaroWinklerDistance(const vespalib::string &query, const vespalib::string &field, feature_t expected); void assertQueryCompleteness(FtFeatureTest & ft, uint32_t firstOcc, uint32_t hits, uint32_t miss); void assertTermEditDistance(const vespalib::string &query, const vespalib::string &field, uint32_t expectedDel, uint32_t expectedIns, uint32_t expectedSub); - -private: - search::fef::BlueprintFactory _factory; }; -TEST_APPHOOK(Test); - -Test::Test() = default; -Test::~Test() = default; - -int -Test::Main() +BetaFeaturesTest::BetaFeaturesTest() + : Test(), + _factory() { - TEST_INIT("beta_features_test"); - // Configure factory with all known blueprints. setup_fef_test_plugin(_factory); setup_search_features(_factory); - - // Test all features. - testJaroWinklerDistance(); TEST_FLUSH(); - testProximity(); TEST_FLUSH(); - testFlowCompleteness(); TEST_FLUSH(); - testQueryCompleteness(); TEST_FLUSH(); - testReverseProximity(); TEST_FLUSH(); - testTermEditDistance(); TEST_FLUSH(); - - TEST_DONE(); - return 0; } -void -Test::testJaroWinklerDistance() +BetaFeaturesTest::~BetaFeaturesTest() = default; + +TEST_F(BetaFeaturesTest, test_jaro_winkler_distance) { { // Test blueprint. @@ -141,7 +120,7 @@ Test::testJaroWinklerDistance() } void -Test::assertJaroWinklerDistance(const vespalib::string &query, const vespalib::string &field, feature_t expected) +BetaFeaturesTest::assertJaroWinklerDistance(const vespalib::string &query, const vespalib::string &field, feature_t expected) { FtFeatureTest ft(_factory, "jaroWinklerDistance(foo)"); ft.getIndexEnv().getBuilder().addField(FieldType::INDEX, CollectionType::SINGLE, "foo"); @@ -151,8 +130,7 @@ Test::assertJaroWinklerDistance(const vespalib::string &query, const vespalib::s ASSERT_TRUE(ft.execute(res.setEpsilon(0.001).addScore("jaroWinklerDistance(foo).out", expected))); } -void -Test::testProximity() +TEST_F(BetaFeaturesTest, test_proximity) { { // Test blueprint. @@ -260,7 +238,7 @@ Test::testProximity() exp .addScore("proximity(foo,0,1).out", a < b ? b - a : util::FEATURE_MAX) .addScore("proximity(foo,0,1).posA", a < b ? a : util::FEATURE_MAX) .addScore("proximity(foo,0,1).posB", a < b ? b : util::FEATURE_MIN); - TEST_STATE(vespalib::make_string("a=%u, b=%u", a, b).c_str()); + SCOPED_TRACE(vespalib::make_string("a=%u, b=%u", a, b).c_str()); { // reset lazy evaluation RankResult dummy; ft.executeOnly(dummy, 0); @@ -271,8 +249,7 @@ Test::testProximity() } } -void -Test::testQueryCompleteness() +TEST_F(BetaFeaturesTest, test_query_completeness) { { // Test blueprint. QueryCompletenessBlueprint prototype; @@ -342,7 +319,7 @@ Test::testQueryCompleteness() } void -Test::assertQueryCompleteness(FtFeatureTest & ft, uint32_t firstOcc, uint32_t hits, uint32_t miss) +BetaFeaturesTest::assertQueryCompleteness(FtFeatureTest & ft, uint32_t firstOcc, uint32_t hits, uint32_t miss) { MatchDataBuilder::UP mdb = ft.createMatchDataBuilder(); mdb->setFieldLength("foo", 20); @@ -385,19 +362,18 @@ int cntFlow(int m1, int m2, int m3, int m4) return flow; } -void -Test::testFlowCompleteness() +TEST_F(BetaFeaturesTest, test_flow_completeness) { { // Test blueprint. - TEST_STATE("test flow completeness blueprint"); + SCOPED_TRACE("test flow completeness blueprint"); FlowCompletenessBlueprint prototype; EXPECT_TRUE(assertCreateInstance(prototype, "flowCompleteness")); StringList params, in, out; - TEST_DO(FT_SETUP_FAIL(prototype, params)); - TEST_DO(FT_SETUP_FAIL(prototype, params.add("foo"))); - TEST_DO(FT_SETUP_FAIL(prototype, params.add("0"))); + FT_SETUP_FAIL(prototype, params); + FT_SETUP_FAIL(prototype, params.add("foo")); + FT_SETUP_FAIL(prototype, params.add("0")); FtIndexEnvironment ie; ie.getBuilder().addField(FieldType::INDEX, CollectionType::SINGLE, "foo"); @@ -416,16 +392,16 @@ Test::testFlowCompleteness() expDump.push_back(fn); } - TEST_DO(FT_SETUP_OK(prototype, ie, params, in, out)); - TEST_DO(FT_SETUP_FAIL(prototype, ie, params.add("2"))); - TEST_DO(FT_DUMP_EMPTY(_factory, "flowCompleteness")); + FT_SETUP_OK(prototype, ie, params, in, out); + FT_SETUP_FAIL(prototype, ie, params.add("2")); + FT_DUMP_EMPTY(_factory, "flowCompleteness"); #ifdef notyet - TEST_DO(FT_DUMP(_factory, "flowCompleteness", ie, expDump)); + FT_DUMP(_factory, "flowCompleteness", ie, expDump); #endif } { // Test executor. - TEST_STATE("test flow completeness executor"); + SCOPED_TRACE("test flow completeness executor"); FtFeatureTest ft(_factory, "flowCompleteness(foo)"); ft.getIndexEnv().getBuilder().addField(FieldType::INDEX, CollectionType::SINGLE, "foo"); @@ -453,7 +429,7 @@ Test::testFlowCompleteness() exp.addScore("flowCompleteness(foo).elementWeight", i > 0 ? 1 : 0); exp.addScore("flowCompleteness(foo).weight", 100.0); exp.addScore("flowCompleteness(foo).flow", i); - TEST_STATE("run execute"); + SCOPED_TRACE("run execute"); { // reset lazy evaluation RankResult dummy; ft.executeOnly(dummy, 0); @@ -464,7 +440,7 @@ Test::testFlowCompleteness() { // Test executor, pass 2 - TEST_STATE("test flow completeness executor (pass 2)"); + SCOPED_TRACE("test flow completeness executor (pass 2)"); FtFeatureTest ft(_factory, "flowCompleteness(foo)"); ft.getIndexEnv().getBuilder().addField(FieldType::INDEX, CollectionType::SINGLE, "foo"); @@ -507,7 +483,7 @@ Test::testFlowCompleteness() exp.addScore("flowCompleteness(foo).elementWeight", 1); exp.addScore("flowCompleteness(foo).weight", 100.0); exp.addScore("flowCompleteness(foo).flow", flow); - TEST_STATE(vespalib::make_string("execute t0m=%u t1m=%u t2m=%u t3m=%u flow=%u", + SCOPED_TRACE(vespalib::make_string("execute t0m=%u t1m=%u t2m=%u t3m=%u flow=%u", t0m, t1m, t2m, t3m, flow).c_str()); { // reset lazy evaluation RankResult dummy; @@ -522,8 +498,7 @@ Test::testFlowCompleteness() } -void -Test::testReverseProximity() +TEST_F(BetaFeaturesTest, test_reverse_proximity) { { // Test blueprint. ReverseProximityBlueprint prototype; @@ -632,8 +607,7 @@ Test::testReverseProximity() } } -void -Test::testTermEditDistance() +TEST_F(BetaFeaturesTest, test_term_edit_distance) { { // Test blueprint. TermEditDistanceBlueprint prototype; @@ -691,7 +665,7 @@ Test::testTermEditDistance() } void -Test::assertTermEditDistance(const vespalib::string &query, const vespalib::string &field, +BetaFeaturesTest::assertTermEditDistance(const vespalib::string &query, const vespalib::string &field, uint32_t expectedDel, uint32_t expectedIns, uint32_t expectedSub) { // Setup feature test. @@ -710,3 +684,5 @@ Test::assertTermEditDistance(const vespalib::string &query, const vespalib::stri .addScore(feature + ".sub", (feature_t)expectedSub); ASSERT_TRUE(ft.execute(exp)); } + +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/searchlib/src/tests/features/bm25/bm25_test.cpp b/searchlib/src/tests/features/bm25/bm25_test.cpp index 233c0ec09f3..f175d21c001 100644 --- a/searchlib/src/tests/features/bm25/bm25_test.cpp +++ b/searchlib/src/tests/features/bm25/bm25_test.cpp @@ -6,8 +6,10 @@ #include <vespa/searchlib/fef/test/dummy_dependency_handler.h> #include <vespa/searchlib/fef/test/indexenvironment.h> #include <vespa/searchlib/fef/test/indexenvironmentbuilder.h> -#include <vespa/searchlib/test/ft_test_app.h> +#define ENABLE_GTEST_MIGRATION +#include <vespa/searchlib/test/ft_test_app_base.h> #include <vespa/vespalib/gtest/gtest.h> +#include <cmath> using namespace search::features; using namespace search::fef; @@ -102,8 +104,8 @@ TEST_F(Bm25BlueprintTest, blueprint_can_prepare_shared_state_with_average_field_ TEST_F(Bm25BlueprintTest, dump_features_for_all_index_fields) { - FtTestApp::FT_DUMP(factory, "bm25", index_env, - StringList().add("bm25(is)").add("bm25(ia)").add("bm25(iws)")); + FtTestAppBase::FT_DUMP(factory, "bm25", index_env, + StringList().add("bm25(is)").add("bm25(ia)").add("bm25(iws)")); } struct Scorer { diff --git a/searchlib/src/tests/features/featurebenchmark.cpp b/searchlib/src/tests/features/featurebenchmark.cpp index 9c3d4943d65..1c208cb0537 100644 --- a/searchlib/src/tests/features/featurebenchmark.cpp +++ b/searchlib/src/tests/features/featurebenchmark.cpp @@ -11,8 +11,10 @@ #include <vespa/searchlib/fef/functiontablefactory.h> #include <vespa/searchlib/fef/test/plugin/setup.h> #include <vespa/vespalib/util/stringfmt.h> -#include <vespa/searchlib/test/ft_test_app.h> +#define ENABLE_GTEST_MIGRATION +#include <vespa/searchlib/test/ft_test_app_base.h> #include <vespa/searchcommon/attribute/config.h> +#include <vespa/vespalib/gtest/gtest.h> #include <fstream> #include <iomanip> @@ -37,7 +39,8 @@ using AttributePtr = AttributeVector::SP; using CollectionType = FieldInfo::CollectionType; -class Benchmark : public FtTestApp { +class Benchmark : public ::testing::Test, + public FtTestAppBase { public: using KeyValueVector = std::vector<std::pair<vespalib::string, vespalib::string> >; @@ -106,6 +109,8 @@ public: }; private: + int _argc; + char **_argv; search::fef::BlueprintFactory _factory; vespalib::Timer _timer; vespalib::duration _sample; @@ -130,16 +135,24 @@ private: void runNativeProximity(Config & cfg); public: - Benchmark(); - ~Benchmark(); - int Main() override; + Benchmark(int argc, char **argv); + ~Benchmark() override; + void TestBody() override; }; -TEST_APPHOOK(Benchmark); +Benchmark::Benchmark(int argc, char **argv) + : ::testing::Test(), + FtTestAppBase(), + _argc(argc), + _argv(argv), + _factory(), + _timer(), + _sample() +{ +} -Benchmark::Benchmark() : _factory(), _timer(), _sample() {} -Benchmark::~Benchmark() {} +Benchmark::~Benchmark() = default; bool Benchmark::Config::isKnown(const vespalib::string & key) const @@ -589,11 +602,9 @@ Benchmark::runNativeProximity(Config & cfg) sample(); } -int -Benchmark::Main() +void +Benchmark::TestBody() { - TEST_INIT("featurebenchmark"); - // Configure factory with all known blueprints. setup_fef_test_plugin(_factory); setup_search_features(_factory); @@ -617,8 +628,8 @@ Benchmark::Main() } if (_argc != optind || optError) { - //usage(); - return -1; + FAIL() << "Bad options"; + return; } Config cfg; @@ -651,8 +662,12 @@ Benchmark::Main() std::cout << "TET: " << vespalib::count_ms(_sample) << " (ms)" << std::endl; std::cout << "ETPD: " << std::fixed << std::setprecision(10) << double(vespalib::count_ms(_sample)) / cfg.getNumRuns() << " (ms)" << std::endl; std::cout << "**** '" << cfg.getFeature() << "' ****" << std::endl; - - TEST_DONE(); - return 0; } +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ::testing::RegisterTest("Benchmark", "benchmark", nullptr, "", + __FILE__, __LINE__, + [=]() -> Benchmark* { return new Benchmark(argc, argv); }); + return RUN_ALL_TESTS(); +} diff --git a/searchlib/src/tests/features/prod_features_attributematch.cpp b/searchlib/src/tests/features/prod_features_attributematch.cpp index aac15801b8c..7db5d352448 100644 --- a/searchlib/src/tests/features/prod_features_attributematch.cpp +++ b/searchlib/src/tests/features/prod_features_attributematch.cpp @@ -6,9 +6,6 @@ #include <vespa/searchlib/attribute/attributevector.h> #include <vespa/searchcommon/attribute/config.h> -#include <vespa/log/log.h> -LOG_SETUP(".prod_features_attributematch"); - using namespace search::features; using namespace search::fef; using namespace search::fef::test; @@ -23,8 +20,7 @@ using AVCT = search::attribute::CollectionType; using CollectionType = FieldInfo::CollectionType; using DataType = FieldInfo::DataType; -void -Test::testAttributeMatch() +TEST_F(ProdFeaturesTest, test_attribute_match) { AttributeMatchBlueprint pt; { diff --git a/searchlib/src/tests/features/prod_features_fieldmatch.cpp b/searchlib/src/tests/features/prod_features_fieldmatch.cpp index 38e74f9ae5b..66815247344 100644 --- a/searchlib/src/tests/features/prod_features_fieldmatch.cpp +++ b/searchlib/src/tests/features/prod_features_fieldmatch.cpp @@ -12,11 +12,7 @@ using namespace search::fef::test; using search::AttributeVector; using CollectionType = FieldInfo::CollectionType; -Test::Test() {} -Test::~Test() {} - -void -Test::testFieldMatch() +TEST_F(ProdFeaturesTest, test_field_match) { testFieldMatchBluePrint(); testFieldMatchExecutor(); diff --git a/searchlib/src/tests/features/prod_features_fieldtermmatch.cpp b/searchlib/src/tests/features/prod_features_fieldtermmatch.cpp index 397f2597390..921b690bf6f 100644 --- a/searchlib/src/tests/features/prod_features_fieldtermmatch.cpp +++ b/searchlib/src/tests/features/prod_features_fieldtermmatch.cpp @@ -3,16 +3,13 @@ #include "prod_features_test.h" #include <vespa/searchlib/features/fieldtermmatchfeature.h> #include <vespa/vespalib/util/stringfmt.h> -#include <vespa/log/log.h> -LOG_SETUP(".prod_features_fieldtermmatch"); using namespace search::features; using namespace search::fef; using namespace search::fef::test; using CollectionType = FieldInfo::CollectionType; -void -Test::testFieldTermMatch() +TEST_F(ProdFeaturesTest, test_field_term_match) { { // Test blueprint. diff --git a/searchlib/src/tests/features/prod_features_framework.cpp b/searchlib/src/tests/features/prod_features_framework.cpp index 0f78182817b..46d509b31b1 100644 --- a/searchlib/src/tests/features/prod_features_framework.cpp +++ b/searchlib/src/tests/features/prod_features_framework.cpp @@ -1,6 +1,4 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#include <vespa/log/log.h> -LOG_SETUP(".prod_features_framework"); #include "prod_features_test.h" #include <vespa/searchlib/features/valuefeature.h> @@ -10,10 +8,8 @@ using namespace search::fef; using namespace search::fef::test; using CollectionType = FieldInfo::CollectionType; -void -Test::testFramework() +TEST_F(ProdFeaturesTest, test_framework) { - LOG(info, "testFramework()"); IndexEnvironment indexEnv; { // test index environment builder IndexEnvironmentBuilder ieb(indexEnv); @@ -23,21 +19,21 @@ Test::testFramework() { const FieldInfo * info = indexEnv.getFieldByName("foo"); ASSERT_TRUE(info != NULL); - EXPECT_EQUAL(info->id(), 0u); + EXPECT_EQ(info->id(), 0u); EXPECT_TRUE(info->type() == FieldType::INDEX); EXPECT_TRUE(info->collection() == CollectionType::SINGLE); } { const FieldInfo * info = indexEnv.getFieldByName("bar"); ASSERT_TRUE(info != NULL); - EXPECT_EQUAL(info->id(), 1u); + EXPECT_EQ(info->id(), 1u); EXPECT_TRUE(info->type() == FieldType::ATTRIBUTE); EXPECT_TRUE(info->collection() == CollectionType::WEIGHTEDSET); } { const FieldInfo * info = indexEnv.getFieldByName("baz"); ASSERT_TRUE(info != NULL); - EXPECT_EQUAL(info->id(), 2u); + EXPECT_EQ(info->id(), 2u); EXPECT_TRUE(info->type() == FieldType::INDEX); EXPECT_TRUE(info->collection() == CollectionType::ARRAY); } @@ -59,7 +55,7 @@ Test::testFramework() EXPECT_TRUE(tr.lookupField(2)->getHandle() == 2u); const ITermData *tp = queryEnv.getTerm(0); ASSERT_TRUE(tp != NULL); - EXPECT_EQUAL(tp, &tr); + EXPECT_EQ(tp, &tr); } { SimpleTermData *tr = qeb.addAttributeNode("bar"); @@ -71,12 +67,12 @@ Test::testFramework() EXPECT_TRUE(tr->lookupField(1)->getHandle() == 3u); const ITermData *tp = queryEnv.getTerm(1); ASSERT_TRUE(tp != NULL); - EXPECT_EQUAL(tp, tr); + EXPECT_EQ(tp, tr); } } MatchData::UP data = layout.createMatchData(); - EXPECT_EQUAL(data->getNumTermFields(), 4u); + EXPECT_EQ(data->getNumTermFields(), 4u); { // check match data access MatchDataBuilder mdb(queryEnv, *data); @@ -97,11 +93,11 @@ Test::testFramework() FieldPositionsIterator itr = tfmd->getIterator(); // foo (index) ASSERT_TRUE(itr.valid()); - EXPECT_EQUAL(itr.getFieldLength(), 50u); - EXPECT_EQUAL(itr.getPosition(), 10u); + EXPECT_EQ(itr.getFieldLength(), 50u); + EXPECT_EQ(itr.getPosition(), 10u); itr.next(); ASSERT_TRUE(itr.valid()); - EXPECT_EQUAL(itr.getPosition(), 20u); + EXPECT_EQ(itr.getPosition(), 20u); itr.next(); ASSERT_TRUE(!itr.valid()); } @@ -118,11 +114,11 @@ Test::testFramework() FieldPositionsIterator itr = tfmd->getIterator(); // baz (index) ASSERT_TRUE(itr.valid()); - EXPECT_EQUAL(itr.getFieldLength(), 100u); - EXPECT_EQUAL(itr.getPosition(), 5u); + EXPECT_EQ(itr.getFieldLength(), 100u); + EXPECT_EQ(itr.getPosition(), 5u); itr.next(); ASSERT_TRUE(itr.valid()); - EXPECT_EQUAL(itr.getPosition(), 15u); + EXPECT_EQ(itr.getPosition(), 15u); itr.next(); ASSERT_TRUE(!itr.valid()); } @@ -137,10 +133,10 @@ Test::testFramework() } { // check that data is cleared MatchDataBuilder mdb(queryEnv, *data); - EXPECT_EQUAL(mdb.getTermFieldMatchData(0, 0)->getDocId(), TermFieldMatchData::invalidId()); - EXPECT_EQUAL(mdb.getTermFieldMatchData(0, 1)->getDocId(), TermFieldMatchData::invalidId()); - EXPECT_EQUAL(mdb.getTermFieldMatchData(0, 2)->getDocId(), TermFieldMatchData::invalidId()); - EXPECT_EQUAL(mdb.getTermFieldMatchData(1, 1)->getDocId(), TermFieldMatchData::invalidId()); + EXPECT_EQ(mdb.getTermFieldMatchData(0, 0)->getDocId(), TermFieldMatchData::invalidId()); + EXPECT_EQ(mdb.getTermFieldMatchData(0, 1)->getDocId(), TermFieldMatchData::invalidId()); + EXPECT_EQ(mdb.getTermFieldMatchData(0, 2)->getDocId(), TermFieldMatchData::invalidId()); + EXPECT_EQ(mdb.getTermFieldMatchData(1, 1)->getDocId(), TermFieldMatchData::invalidId()); // test illegal things ASSERT_TRUE(!mdb.addOccurence("foo", 1, 10)); // invalid term/field combination diff --git a/searchlib/src/tests/features/prod_features_test.cpp b/searchlib/src/tests/features/prod_features_test.cpp index 472bb545f33..22105533895 100644 --- a/searchlib/src/tests/features/prod_features_test.cpp +++ b/searchlib/src/tests/features/prod_features_test.cpp @@ -79,103 +79,65 @@ using DataType = FieldInfo::DataType; const double EPS = 10e-6; -TEST_APPHOOK(Test); - -int -Test::Main() +Test::Test() { - TEST_INIT("prod_features_test"); - // Configure factory with all known blueprints. setup_fef_test_plugin(_factory); setup_search_features(_factory); - - // Test all features. - TEST_DO(testFramework()); TEST_FLUSH(); - TEST_DO(testFtLib()); TEST_FLUSH(); - TEST_DO(testAge()); TEST_FLUSH(); - TEST_DO(testAttribute()); TEST_FLUSH(); - TEST_DO(testAttributeMatch()); TEST_FLUSH(); - TEST_DO(testCloseness()); TEST_FLUSH(); - TEST_DO(testMatchCount()); TEST_FLUSH(); - TEST_DO(testGreatCircleDistance()); TEST_FLUSH(); - TEST_DO(testDistance()); TEST_FLUSH(); - TEST_DO(testDistanceToPath()); TEST_FLUSH(); - TEST_DO(testDotProduct()); TEST_FLUSH(); - TEST_DO(testFieldLength()); TEST_FLUSH(); - TEST_DO(testFieldMatch()); TEST_FLUSH(); - TEST_DO(testFieldTermMatch()); TEST_FLUSH(); - TEST_DO(testFirstPhase()); TEST_FLUSH(); - TEST_DO(testForeach()); TEST_FLUSH(); - TEST_DO(testFreshness()); TEST_FLUSH(); - TEST_DO(testMatch()); TEST_FLUSH(); - TEST_DO(testMatches()); TEST_FLUSH(); - TEST_DO(testNow()); TEST_FLUSH(); - TEST_DO(testQuery()); TEST_FLUSH(); - TEST_DO(testQueryTermCount()); TEST_FLUSH(); - TEST_DO(testRandom()); TEST_FLUSH(); - TEST_DO(testRandomNormal()); TEST_FLUSH(); - TEST_DO(testRandomNormalStable()); TEST_FLUSH(); - TEST_DO(testRankingExpression()); TEST_FLUSH(); - TEST_DO(testTerm()); TEST_FLUSH(); - TEST_DO(testTermDistance()); TEST_FLUSH(); - TEST_DO(testUtils()); TEST_FLUSH(); - TEST_DO(testUnique()); TEST_FLUSH(); - - TEST_DONE(); - return 0; } +Test::~Test() = default; -void -Test::testFtLib() +ProdFeaturesTest::ProdFeaturesTest() = default; +ProdFeaturesTest::~ProdFeaturesTest() = default; + +TEST_F(ProdFeaturesTest, test_ft_lib) { { // toQuery FtQuery q = FtUtil::toQuery("a b!50 0.5:c!200%0.5 d%0.3 e!300 0.3:f "); ASSERT_TRUE(q.size() == 6); - EXPECT_EQUAL(q[0].term, vespalib::string("a")); - EXPECT_EQUAL(q[0].termWeight.percent(), 100); - EXPECT_APPROX(q[0].connexity, 0.1f, EPS); - EXPECT_APPROX(q[0].significance, 0.1f, EPS); - EXPECT_EQUAL(q[1].term, vespalib::string("b")); - EXPECT_EQUAL(q[1].termWeight.percent(), 50); - EXPECT_APPROX(q[1].connexity, 0.1f, EPS); - EXPECT_APPROX(q[1].significance, 0.1f, EPS); - EXPECT_EQUAL(q[2].term, vespalib::string("c")); - EXPECT_EQUAL(q[2].termWeight.percent(), 200); - EXPECT_APPROX(q[2].connexity, 0.5f, EPS); - EXPECT_APPROX(q[2].significance, 0.5f, EPS); - EXPECT_EQUAL(q[3].term, vespalib::string("d")); - EXPECT_EQUAL(q[3].termWeight.percent(), 100); - EXPECT_APPROX(q[3].connexity, 0.1f, EPS); - EXPECT_APPROX(q[3].significance, 0.3f, EPS); - EXPECT_EQUAL(q[4].term, vespalib::string("e")); - EXPECT_EQUAL(q[4].termWeight.percent(), 300); - EXPECT_APPROX(q[4].connexity, 0.1f, EPS); - EXPECT_APPROX(q[4].significance, 0.1f, EPS); - EXPECT_EQUAL(q[5].term, vespalib::string("f")); - EXPECT_EQUAL(q[5].termWeight.percent(), 100); - EXPECT_APPROX(q[5].connexity, 0.3f, EPS); - EXPECT_APPROX(q[5].significance, 0.1f, EPS); + EXPECT_EQ(q[0].term, vespalib::string("a")); + EXPECT_EQ(q[0].termWeight.percent(), 100); + EXPECT_NEAR(q[0].connexity, 0.1f, EPS); + EXPECT_NEAR(q[0].significance, 0.1f, EPS); + EXPECT_EQ(q[1].term, vespalib::string("b")); + EXPECT_EQ(q[1].termWeight.percent(), 50); + EXPECT_NEAR(q[1].connexity, 0.1f, EPS); + EXPECT_NEAR(q[1].significance, 0.1f, EPS); + EXPECT_EQ(q[2].term, vespalib::string("c")); + EXPECT_EQ(q[2].termWeight.percent(), 200); + EXPECT_NEAR(q[2].connexity, 0.5f, EPS); + EXPECT_NEAR(q[2].significance, 0.5f, EPS); + EXPECT_EQ(q[3].term, vespalib::string("d")); + EXPECT_EQ(q[3].termWeight.percent(), 100); + EXPECT_NEAR(q[3].connexity, 0.1f, EPS); + EXPECT_NEAR(q[3].significance, 0.3f, EPS); + EXPECT_EQ(q[4].term, vespalib::string("e")); + EXPECT_EQ(q[4].termWeight.percent(), 300); + EXPECT_NEAR(q[4].connexity, 0.1f, EPS); + EXPECT_NEAR(q[4].significance, 0.1f, EPS); + EXPECT_EQ(q[5].term, vespalib::string("f")); + EXPECT_EQ(q[5].termWeight.percent(), 100); + EXPECT_NEAR(q[5].connexity, 0.3f, EPS); + EXPECT_NEAR(q[5].significance, 0.1f, EPS); } { // toRankResult RankResult rr = toRankResult("foo", "a:0.5 b:-0.5 c:2 d:3 "); std::vector<vespalib::string> keys = rr.getKeys(); ASSERT_TRUE(keys.size() == 4); - EXPECT_EQUAL(keys[0], vespalib::string("foo.a")); - EXPECT_EQUAL(keys[1], vespalib::string("foo.b")); - EXPECT_EQUAL(keys[2], vespalib::string("foo.c")); - EXPECT_EQUAL(keys[3], vespalib::string("foo.d")); - EXPECT_APPROX(rr.getScore("foo.a"), 0.5f, EPS); - EXPECT_APPROX(rr.getScore("foo.b"), -0.5f, EPS); - EXPECT_APPROX(rr.getScore("foo.c"), 2.0f, EPS); - EXPECT_APPROX(rr.getScore("foo.d"), 3.0f, EPS); + EXPECT_EQ(keys[0], vespalib::string("foo.a")); + EXPECT_EQ(keys[1], vespalib::string("foo.b")); + EXPECT_EQ(keys[2], vespalib::string("foo.c")); + EXPECT_EQ(keys[3], vespalib::string("foo.d")); + EXPECT_NEAR(rr.getScore("foo.a"), 0.5f, EPS); + EXPECT_NEAR(rr.getScore("foo.b"), -0.5f, EPS); + EXPECT_NEAR(rr.getScore("foo.c"), 2.0f, EPS); + EXPECT_NEAR(rr.getScore("foo.d"), 3.0f, EPS); } } -void -Test::testAge() +TEST_F(ProdFeaturesTest, test_age) { { // Test blueprint FtIndexEnvironment idx_env; @@ -222,8 +184,7 @@ Test::setupForAgeTest(FtFeatureTest & ft, int64_t docTime) ft.getIndexEnv().getAttributeMap().add(doctime); } -void -Test::testAttribute() +TEST_F(ProdFeaturesTest, test_attribute) { AttributeBlueprint prototype; { @@ -476,8 +437,7 @@ Test::setupForAttributeTest(FtFeatureTest &ft, bool setup_env) ASSERT_TRUE(avs[9]->load()); } -void -Test::testCloseness() +TEST_F(ProdFeaturesTest, test_closeness) { { // Test blueprint. ClosenessBlueprint pt; @@ -492,11 +452,11 @@ Test::testCloseness() } { // Test executor. - TEST_DO(assertCloseness(1, "pos", 0)); + assertCloseness(1, "pos", 0); assertCloseness(0.8, "pos", 1802661); assertCloseness(0, "pos", 9013306); // two-argument version - TEST_DO(assertCloseness(0.8, "field,pos", 1802661)); + assertCloseness(0.8, "field,pos", 1802661); // use non-default maxDistance assertCloseness(1, "pos", 0, 100); @@ -536,8 +496,7 @@ Test::assertCloseness(feature_t exp, const vespalib::string & attr, double dista ASSERT_TRUE(ft.execute(RankResult().addScore(feature, exp))); } -void -Test::testFieldLength() +TEST_F(ProdFeaturesTest, test_field_length) { FieldLengthBlueprint pt; @@ -629,8 +588,7 @@ Test::assertFieldMatchTS(const vespalib::string & spec, } -void -Test::testFirstPhase() +TEST_F(ProdFeaturesTest, test_first_phase) { { // Test blueprint. FirstPhaseBlueprint pt; @@ -656,8 +614,7 @@ Test::testFirstPhase() } } -void -Test::testForeach() +TEST_F(ProdFeaturesTest, test_foreach) { { // Test blueprint. ForeachBlueprint pt; @@ -764,8 +721,7 @@ Test::assertForeachOperation(feature_t exp, const vespalib::string & cond, const } -void -Test::testFreshness() +TEST_F(ProdFeaturesTest, test_freshness) { { // Test blueprint. FtIndexEnvironment idx_env; @@ -853,8 +809,7 @@ GeoLocation toGL(const AirPort &p) { } -void -Test::testGreatCircleDistance() +TEST_F(ProdFeaturesTest, test_great_circle_distance) { { // Test blueprint. GreatCircleDistanceBlueprint pt; @@ -892,8 +847,7 @@ Test::testGreatCircleDistance() } } -void -Test::testDistance() +TEST_F(ProdFeaturesTest, test_distance) { { // Test blueprint. DistanceBlueprint pt; @@ -924,34 +878,34 @@ Test::testDistance() { // test 2D multi location (zcurve) // note: "aspect" is ignored now, computed from "y", and cos(60 degrees) = 0.5 vespalib::string positions = "5:59999995," "35:60000000," "5:60000040," "35:59999960"; - TEST_DO(assert2DZDistance(static_cast<feature_t>(0.0f), positions, 5, 59999995, 0, 0)); - TEST_DO(assert2DZDistance(static_cast<feature_t>(0.0f), positions, 35, 60000000, 0x10000000, 1)); - TEST_DO(assert2DZDistance(static_cast<feature_t>(0.0f), positions, 5, 60000040, 0x20000000, 2)); - TEST_DO(assert2DZDistance(static_cast<feature_t>(0.0f), positions, 35, 59999960, 0x30000000, 3)); - TEST_DO(assert2DZDistance(static_cast<feature_t>(std::sqrt(250.0f)), positions, 15, 59999980, 0x40000000, 0)); - TEST_DO(assert2DZDistance(static_cast<feature_t>(std::sqrt(250.0f)), positions, -5, 59999980, 0x50000000, 0)); - TEST_DO(assert2DZDistance(static_cast<feature_t>(std::sqrt(250.0f)), positions, 45, 59999985, 0x60000000, 1)); - TEST_DO(assert2DZDistance(static_cast<feature_t>(std::sqrt(250.0f)), positions, 45, 60000015, 0x70000000, 1)); - TEST_DO(assert2DZDistance(static_cast<feature_t>(std::sqrt(425.0f)), positions, 15, 60000020, 0x80000000, 2)); - TEST_DO(assert2DZDistance(static_cast<feature_t>(std::sqrt(425.0f)), positions, -5, 60000020, 0x90000000, 2)); - TEST_DO(assert2DZDistance(static_cast<feature_t>(std::sqrt(50.0f)), positions, 45, 59999955, 0xa0000000, 3)); - TEST_DO(assert2DZDistance(static_cast<feature_t>(std::sqrt(50.0f)), positions, 45, 59999965, 0xb0000000, 3)); - - TEST_DO(assert2DZDistance(static_cast<feature_t>(std::sqrt(450.0f)), positions, -25, 59999980, 0xc0000000, 0)); - TEST_DO(assert2DZDistance(static_cast<feature_t>(std::sqrt(625.0f)), positions, -25, 60000060, 0xd0000000, 2)); - TEST_DO(assert2DZDistance(static_cast<feature_t>(std::sqrt(250.0f)), positions, 15, 59999980, 0xe0000000, 0)); - TEST_DO(assert2DZDistance(static_cast<feature_t>(std::sqrt(425.0f)), positions, 45, 59999980, 0xf0000000, 1)); + assert2DZDistance(static_cast<feature_t>(0.0f), positions, 5, 59999995, 0, 0); + assert2DZDistance(static_cast<feature_t>(0.0f), positions, 35, 60000000, 0x10000000, 1); + assert2DZDistance(static_cast<feature_t>(0.0f), positions, 5, 60000040, 0x20000000, 2); + assert2DZDistance(static_cast<feature_t>(0.0f), positions, 35, 59999960, 0x30000000, 3); + assert2DZDistance(static_cast<feature_t>(std::sqrt(250.0f)), positions, 15, 59999980, 0x40000000, 0); + assert2DZDistance(static_cast<feature_t>(std::sqrt(250.0f)), positions, -5, 59999980, 0x50000000, 0); + assert2DZDistance(static_cast<feature_t>(std::sqrt(250.0f)), positions, 45, 59999985, 0x60000000, 1); + assert2DZDistance(static_cast<feature_t>(std::sqrt(250.0f)), positions, 45, 60000015, 0x70000000, 1); + assert2DZDistance(static_cast<feature_t>(std::sqrt(425.0f)), positions, 15, 60000020, 0x80000000, 2); + assert2DZDistance(static_cast<feature_t>(std::sqrt(425.0f)), positions, -5, 60000020, 0x90000000, 2); + assert2DZDistance(static_cast<feature_t>(std::sqrt(50.0f)), positions, 45, 59999955, 0xa0000000, 3); + assert2DZDistance(static_cast<feature_t>(std::sqrt(50.0f)), positions, 45, 59999965, 0xb0000000, 3); + + assert2DZDistance(static_cast<feature_t>(std::sqrt(450.0f)), positions, -25, 59999980, 0xc0000000, 0); + assert2DZDistance(static_cast<feature_t>(std::sqrt(625.0f)), positions, -25, 60000060, 0xd0000000, 2); + assert2DZDistance(static_cast<feature_t>(std::sqrt(250.0f)), positions, 15, 59999980, 0xe0000000, 0); + assert2DZDistance(static_cast<feature_t>(std::sqrt(425.0f)), positions, 45, 59999980, 0xf0000000, 1); } { // test geo multi location (zcurve) // note: cos(70.528779 degrees) = 1/3 vespalib::string positions = "0:70528779," "100:70528879," "-200:70528979," "-300:70528479," "400:70528379"; - TEST_DO(assert2DZDistance(static_cast<feature_t>(0.0f), positions, 0, 70528779 + 0, 0, 0)); - TEST_DO(assert2DZDistance(static_cast<feature_t>(1.0f), positions, 100, 70528779 + 101, 0x20000000, 1)); - TEST_DO(assert2DZDistance(static_cast<feature_t>(0.0f), positions, -200, 70528779 + 200, 0x40000000, 2)); - TEST_DO(assert2DZDistance(static_cast<feature_t>(13.0f), positions, -315, 70528779 -312, 0x80000000, 3)); - TEST_DO(assert2DZDistance(static_cast<feature_t>(5.0f), positions, 412, 70528779 -403, 0xB0000000, 4)); - TEST_DO(assert2DZDistance(static_cast<feature_t>(5.0f), positions, 109, 70528779 + 104, 0xF0000000, 1)); + assert2DZDistance(static_cast<feature_t>(0.0f), positions, 0, 70528779 + 0, 0, 0); + assert2DZDistance(static_cast<feature_t>(1.0f), positions, 100, 70528779 + 101, 0x20000000, 1); + assert2DZDistance(static_cast<feature_t>(0.0f), positions, -200, 70528779 + 200, 0x40000000, 2); + assert2DZDistance(static_cast<feature_t>(13.0f), positions, -315, 70528779 -312, 0x80000000, 3); + assert2DZDistance(static_cast<feature_t>(5.0f), positions, 412, 70528779 -403, 0xB0000000, 4); + assert2DZDistance(static_cast<feature_t>(5.0f), positions, 109, 70528779 + 104, 0xF0000000, 1); } { // test default distance @@ -1056,8 +1010,7 @@ Test::assert2DZDistance(feature_t exp, const vespalib::string & positions, addScore("distance(pos).longitude", pos[hit_index].first * 1e-6))); } -void -Test::testDistanceToPath() +TEST_F(ProdFeaturesTest, test_distance_to_path) { { // Test blueprint. @@ -1197,8 +1150,8 @@ verifyCorrectDotProductExecutor(BlueprintFactory & factory, vespalib::stringref vespalib::Stash stash; FeatureExecutor &exc = bp.createExecutor(ft.getQueryEnv(), stash); // check that we have the optimized enum version - EXPECT_EQUAL(expected, exc.getClassName()); - EXPECT_EQUAL(1u, deps.output.size()); + EXPECT_EQ(expected, exc.getClassName()); + EXPECT_EQ(1u, deps.output.size()); } template<typename T> @@ -1208,22 +1161,21 @@ void verifyArrayParser() for(const vespalib::string & s : v) { std::vector<T> out; ArrayParser::parse(s, out); - EXPECT_EQUAL(8u, out.size()); - EXPECT_EQUAL(2, out[0]); - EXPECT_EQUAL(-3, out[1]); - EXPECT_EQUAL(0, out[2]); - EXPECT_EQUAL(0, out[3]); - EXPECT_EQUAL(0, out[4]); - EXPECT_EQUAL(0, out[5]); - EXPECT_EQUAL(0, out[6]); - EXPECT_EQUAL(-3, out[7]); + EXPECT_EQ(8u, out.size()); + EXPECT_EQ(2, out[0]); + EXPECT_EQ(-3, out[1]); + EXPECT_EQ(0, out[2]); + EXPECT_EQ(0, out[3]); + EXPECT_EQ(0, out[4]); + EXPECT_EQ(0, out[5]); + EXPECT_EQ(0, out[6]); + EXPECT_EQ(-3, out[7]); } } } -void -Test::testDotProduct() +TEST_F(ProdFeaturesTest, test_dot_product) { { // Test blueprint. FtIndexEnvironment idx_env; @@ -1252,69 +1204,69 @@ Test::testDotProduct() { dotproduct::wset::EnumVector out(sv); WeightedSetParser::parse("", out); - EXPECT_EQUAL(out.getVector().size(), 0u); + EXPECT_EQ(out.getVector().size(), 0u); WeightedSetParser::parse("()", out); - EXPECT_EQUAL(out.getVector().size(), 0u); + EXPECT_EQ(out.getVector().size(), 0u); WeightedSetParser::parse("(a;1)", out); - EXPECT_EQUAL(out.getVector().size(), 0u); + EXPECT_EQ(out.getVector().size(), 0u); WeightedSetParser::parse("(a:1)", out); - EXPECT_EQUAL(out.getVector().size(), 1u); + EXPECT_EQ(out.getVector().size(), 1u); EXPECT_TRUE(sv->findEnum("a", e)); - EXPECT_EQUAL(out.getVector()[0].first, e); - EXPECT_EQUAL(out.getVector()[0].second, 1.0); + EXPECT_EQ(out.getVector()[0].first, e); + EXPECT_EQ(out.getVector()[0].second, 1.0); } std::vector<vespalib::string> v = {"(b:2.5,c:-3.5)", "{b:2.5,c:-3.5}"}; for(const vespalib::string & s : v) { dotproduct::wset::EnumVector out(sv); WeightedSetParser::parse(s, out); - EXPECT_EQUAL(out.getVector().size(), 2u); + EXPECT_EQ(out.getVector().size(), 2u); EXPECT_TRUE(sv->findEnum("b", e)); - EXPECT_EQUAL(out.getVector()[0].first, e); - EXPECT_EQUAL(out.getVector()[0].second, 2.5); + EXPECT_EQ(out.getVector()[0].first, e); + EXPECT_EQ(out.getVector()[0].second, 2.5); EXPECT_TRUE(sv->findEnum("c", e)); - EXPECT_EQUAL(out.getVector()[1].first, e); - EXPECT_EQUAL(out.getVector()[1].second, -3.5); + EXPECT_EQ(out.getVector()[1].first, e); + EXPECT_EQ(out.getVector()[1].second, -3.5); } { // test funky syntax dotproduct::wset::EnumVector out(sv); WeightedSetParser::parse("( a: 1, b:2 ,c: , :3)", out); - EXPECT_EQUAL(out.getVector().size(), 4u); + EXPECT_EQ(out.getVector().size(), 4u); EXPECT_TRUE(sv->findEnum("a", e)); - EXPECT_EQUAL(out.getVector()[0].first, e); - EXPECT_EQUAL(out.getVector()[0].second, 1); + EXPECT_EQ(out.getVector()[0].first, e); + EXPECT_EQ(out.getVector()[0].second, 1); EXPECT_TRUE(sv->findEnum("b", e)); - EXPECT_EQUAL(out.getVector()[1].first, e); - EXPECT_EQUAL(out.getVector()[1].second, 2); + EXPECT_EQ(out.getVector()[1].first, e); + EXPECT_EQ(out.getVector()[1].second, 2); EXPECT_TRUE(sv->findEnum("c", e)); - EXPECT_EQUAL(out.getVector()[2].first, e); - EXPECT_EQUAL(out.getVector()[2].second, 0); + EXPECT_EQ(out.getVector()[2].first, e); + EXPECT_EQ(out.getVector()[2].second, 0); EXPECT_TRUE(sv->findEnum("", e)); - EXPECT_EQUAL(out.getVector()[3].first, e); - EXPECT_EQUAL(out.getVector()[3].second, 3); + EXPECT_EQ(out.getVector()[3].first, e); + EXPECT_EQ(out.getVector()[3].second, 3); } { // strings not in attribute vector dotproduct::wset::EnumVector out(sv); WeightedSetParser::parse("(not:1)", out); - EXPECT_EQUAL(out.getVector().size(), 0u); + EXPECT_EQ(out.getVector().size(), 0u); } } { // string vector dotproduct::wset::StringVector out; WeightedSetParser::parse("(b:2.5,c:-3.5)", out); - EXPECT_EQUAL(out.getVector().size(), 2u); - EXPECT_EQUAL(out.getVector()[0].first, "b"); - EXPECT_EQUAL(out.getVector()[0].second, 2.5); - EXPECT_EQUAL(out.getVector()[1].first, "c"); - EXPECT_EQUAL(out.getVector()[1].second, -3.5); + EXPECT_EQ(out.getVector().size(), 2u); + EXPECT_EQ(out.getVector()[0].first, "b"); + EXPECT_EQ(out.getVector()[0].second, 2.5); + EXPECT_EQ(out.getVector()[1].first, "c"); + EXPECT_EQ(out.getVector()[1].second, -3.5); } { // integer vector dotproduct::wset::IntegerVector out; WeightedSetParser::parse("(20:2.5,30:-3.5)", out); - EXPECT_EQUAL(out.getVector().size(), 2u); - EXPECT_EQUAL(out.getVector()[0].first, 20); - EXPECT_EQUAL(out.getVector()[0].second, 2.5); - EXPECT_EQUAL(out.getVector()[1].first, 30); - EXPECT_EQUAL(out.getVector()[1].second, -3.5); + EXPECT_EQ(out.getVector().size(), 2u); + EXPECT_EQ(out.getVector()[0].first, 20); + EXPECT_EQ(out.getVector()[0].second, 2.5); + EXPECT_EQ(out.getVector()[1].first, 30); + EXPECT_EQ(out.getVector()[1].second, -3.5); } } verifyArrayParser<int8_t>(); @@ -1327,7 +1279,7 @@ Test::testDotProduct() vespalib::string s = "[[1:3]]"; std::vector<int32_t> out; ArrayParser::parse(s, out); - EXPECT_EQUAL(0u, out.size()); + EXPECT_EQ(0u, out.size()); } { // Test executor. @@ -1351,10 +1303,10 @@ Test::testDotProduct() assertDotProduct(550, "(a:1,b:2,c:3,d:4,e:5)", 1, "wsextstr"); } for (const char * name : {"wsbyte", "wsint", "wsint_fast"}) { - TEST_DO(assertDotProduct(0, "()", 1, name)); - TEST_DO(assertDotProduct(0, "(6:5,7:5)", 1, name)); - TEST_DO(assertDotProduct(18, "(4:4.5)", 1, name)); - TEST_DO(assertDotProduct(57, "(1:1,2:2,3:3,4:4.5,5:5)", 1, name)); + assertDotProduct(0, "()", 1, name); + assertDotProduct(0, "(6:5,7:5)", 1, name); + assertDotProduct(18, "(4:4.5)", 1, name); + assertDotProduct(57, "(1:1,2:2,3:3,4:4.5,5:5)", 1, name); } for (const char * name : {"arrbyte", "arrint", "arrfloat", "arrint_fast", "arrfloat_fast"}) { assertDotProduct(0, "()", 1, name); @@ -1375,12 +1327,12 @@ Test::testDotProduct() assertDotProduct(17, "(0:1,3:4,50:97)", 1, "sint", "arrfloat"); // attribute override assertDotProduct(0, "(0:1,3:4,50:97)", 1, "sint", "arrfloat_non_existing"); // incorrect attribute override } - TEST_DO(verifyCorrectDotProductExecutor(_factory, "wsstr", "{a:1,b:2}", "search::features::dotproduct::wset::(anonymous namespace)::DotProductExecutorByEnum")); - TEST_DO(verifyCorrectDotProductExecutor(_factory, "wsstr", "{a:1}", "search::features::dotproduct::wset::(anonymous namespace)::SingleDotProductExecutorByEnum")); - TEST_DO(verifyCorrectDotProductExecutor(_factory, "wsstr", "{unknown:1}", "search::features::SingleZeroValueExecutor")); - TEST_DO(verifyCorrectDotProductExecutor(_factory, "wsint", "{1:1, 2:3}", "search::features::dotproduct::wset::DotProductByWeightedSetReadViewExecutor<int>")); - TEST_DO(verifyCorrectDotProductExecutor(_factory, "wsint", "{1:1}", "search::features::dotproduct::wset::(anonymous namespace)::SingleDotProductByWeightedValueExecutor<int>")); - TEST_DO(verifyCorrectDotProductExecutor(_factory, "wsint", "{}", "search::features::SingleZeroValueExecutor")); + verifyCorrectDotProductExecutor(_factory, "wsstr", "{a:1,b:2}", "search::features::dotproduct::wset::(anonymous namespace)::DotProductExecutorByEnum"); + verifyCorrectDotProductExecutor(_factory, "wsstr", "{a:1}", "search::features::dotproduct::wset::(anonymous namespace)::SingleDotProductExecutorByEnum"); + verifyCorrectDotProductExecutor(_factory, "wsstr", "{unknown:1}", "search::features::SingleZeroValueExecutor"); + verifyCorrectDotProductExecutor(_factory, "wsint", "{1:1, 2:3}", "search::features::dotproduct::wset::DotProductByWeightedSetReadViewExecutor<int>"); + verifyCorrectDotProductExecutor(_factory, "wsint", "{1:1}", "search::features::dotproduct::wset::(anonymous namespace)::SingleDotProductByWeightedValueExecutor<int>"); + verifyCorrectDotProductExecutor(_factory, "wsint", "{}", "search::features::SingleZeroValueExecutor"); } @@ -1463,8 +1415,7 @@ Test::setupForDotProductTest(FtFeatureTest & ft) d->addDoc(docId); } -void -Test::testNow() +TEST_F(ProdFeaturesTest, test_now) { { // Test blueprint. @@ -1503,13 +1454,12 @@ Test::testNow() RankResult res; ASSERT_TRUE(ft.executeOnly(res, 1)); feature_t now = 15000000000; - ASSERT_EQUAL(now, res.getScore("now")); + ASSERT_EQ(now, res.getScore("now")); } } -void -Test::testMatch() +TEST_F(ProdFeaturesTest, test_match) { { // Test blueprint. MatchBlueprint pt; @@ -1617,8 +1567,7 @@ Test::testMatch() } } -void -Test::testMatchCount() +TEST_F(ProdFeaturesTest, test_match_count) { { // Test blueprint. MatchCountBlueprint pt; @@ -1666,12 +1615,11 @@ Test::testMatchCount() } void verifySequence(uint64_t first, uint64_t second) { - ASSERT_GREATER(first, second); - ASSERT_GREATER(double(first), double(second)); + ASSERT_GT(first, second); + ASSERT_GT(double(first), double(second)); } -void -Test::testUnique() +TEST_F(ProdFeaturesTest, test_unique) { { GlobalSequenceBlueprint bp; @@ -1683,19 +1631,18 @@ Test::testUnique() } FtFeatureTest ft(_factory, "globalSequence"); ASSERT_TRUE(ft.setup()); - TEST_DO(verifySequence(GlobalSequenceBlueprint::globalSequence(1, 0), GlobalSequenceBlueprint::globalSequence(1,1))); - TEST_DO(verifySequence(GlobalSequenceBlueprint::globalSequence(1, 1), GlobalSequenceBlueprint::globalSequence(1,2))); - TEST_DO(verifySequence(GlobalSequenceBlueprint::globalSequence(1, 1), GlobalSequenceBlueprint::globalSequence(2,1))); - TEST_DO(verifySequence(GlobalSequenceBlueprint::globalSequence(2, 1), GlobalSequenceBlueprint::globalSequence(2,2))); - TEST_DO(verifySequence(GlobalSequenceBlueprint::globalSequence(2, 2), GlobalSequenceBlueprint::globalSequence(2,3))); - TEST_DO(verifySequence(GlobalSequenceBlueprint::globalSequence(2, 2), GlobalSequenceBlueprint::globalSequence(3,0))); - ASSERT_EQUAL(0xfffffffefffdul, (1ul << 48) - 0x10003l); + verifySequence(GlobalSequenceBlueprint::globalSequence(1, 0), GlobalSequenceBlueprint::globalSequence(1,1)); + verifySequence(GlobalSequenceBlueprint::globalSequence(1, 1), GlobalSequenceBlueprint::globalSequence(1,2)); + verifySequence(GlobalSequenceBlueprint::globalSequence(1, 1), GlobalSequenceBlueprint::globalSequence(2,1)); + verifySequence(GlobalSequenceBlueprint::globalSequence(2, 1), GlobalSequenceBlueprint::globalSequence(2,2)); + verifySequence(GlobalSequenceBlueprint::globalSequence(2, 2), GlobalSequenceBlueprint::globalSequence(2,3)); + verifySequence(GlobalSequenceBlueprint::globalSequence(2, 2), GlobalSequenceBlueprint::globalSequence(3,0)); + ASSERT_EQ(0xfffffffefffdul, (1ul << 48) - 0x10003l); EXPECT_TRUE(ft.execute(0xfffffffefffdul, 0, 1)); EXPECT_TRUE(ft.execute(0xfffffff8fffdul, 0, 7)); } -void -Test::testMatches() +TEST_F(ProdFeaturesTest, test_matches) { { // Test blueprint. MatchesBlueprint pt; @@ -1784,13 +1731,14 @@ Test::assertMatches(uint32_t output, index["foo"] = FtUtil::tokenize(field); FT_SETUP(ft, FtUtil::toQuery(query), index, 1); - ASSERT_TRUE(ft.execute(output, EPS, docId)); + EXPECT_TRUE(ft.execute(output, EPS, docId)); // Execute and compare results. - return EXPECT_TRUE(ft.execute(output, EPS, docId)); + bool failed = false; + EXPECT_TRUE(ft.execute(output, EPS, docId)) << (failed = true, ""); + return !failed; } -void -Test::testQuery() +TEST_F(ProdFeaturesTest, test_query) { { // Test blueprint. QueryBlueprint pt; @@ -1831,8 +1779,7 @@ Test::testQuery() } } -void -Test::testQueryTermCount() +TEST_F(ProdFeaturesTest, test_query_term_count) { { // Test blueprint. QueryTermCountBlueprint pt; @@ -1869,8 +1816,7 @@ Test::testQueryTermCount() } } -void -Test::testRandom() +TEST_F(ProdFeaturesTest, test_random) { { // Test blueprint. RandomBlueprint pt; @@ -1921,8 +1867,8 @@ Test::testRandom() } } -void -Test::testRandomNormal() { +TEST_F(ProdFeaturesTest, test_random_normal) +{ { // Test blueprint. RandomNormalBlueprint pt; @@ -1965,8 +1911,8 @@ Test::testRandomNormal() { } } -void -Test::testRandomNormalStable() { +TEST_F(ProdFeaturesTest, test_random_normal_stable) +{ { // Test blueprint. RandomNormalStableBlueprint pt; @@ -2008,8 +1954,7 @@ Test::testRandomNormalStable() { } } -void -Test::testRankingExpression() +TEST_F(ProdFeaturesTest, test_ranking_expression) { { // Test blueprint. RankingExpressionBlueprint prototype; @@ -2090,8 +2035,7 @@ Test::getExpression(const vespalib::string ¶meter) const return FNB().baseName("rankingExpression").parameter(parameter).buildName(); } -void -Test::testTerm() +TEST_F(ProdFeaturesTest, test_term) { { // Test blueprint. @@ -2171,8 +2115,7 @@ Test::testTerm() } } -void -Test::testTermDistance() +TEST_F(ProdFeaturesTest, test_term_distance) { { // test blueprint TermDistanceBlueprint pt; @@ -2238,32 +2181,34 @@ Test::assertTermDistance(const TermDistanceCalculator::Result & exp, rr.addScore(feature + ".forwardTermPosition", exp.forwardTermPos); rr.addScore(feature + ".reverse", exp.reverseDist); rr.addScore(feature + ".reverseTermPosition", exp.reverseTermPos); - return EXPECT_TRUE(ft.execute(rr, docId)); + bool failed = false; + EXPECT_TRUE(ft.execute(rr, docId)) << (failed = true, ""); + return !failed; } -void -Test::testUtils() +TEST_F(ProdFeaturesTest, test_utils) { { // getSignificance - EXPECT_APPROX(util::getSignificance(0.0), 1, EPS); - EXPECT_APPROX(util::getSignificance(0.0 + 1.0e-7), 1, EPS); - EXPECT_APPROX(util::getSignificance(1.0), 0.5, EPS); - EXPECT_APPROX(util::getSignificance(1.0 + 1.0e-7), 0.5, EPS); + EXPECT_NEAR(util::getSignificance(0.0), 1, EPS); + EXPECT_NEAR(util::getSignificance(0.0 + 1.0e-7), 1, EPS); + EXPECT_NEAR(util::getSignificance(1.0), 0.5, EPS); + EXPECT_NEAR(util::getSignificance(1.0 + 1.0e-7), 0.5, EPS); feature_t last = 1; for (uint32_t i = 2; i <= 100; i = i + 1) { feature_t s = util::getSignificance(i * 1.0e-6); - EXPECT_GREATER(s, 0); - EXPECT_LESS(s, 1); - EXPECT_LESS(s, last); + EXPECT_GT(s, 0); + EXPECT_LT(s, 1); + EXPECT_LT(s, last); last = s; } for (uint32_t i = 999900; i <= 1000000; i = i + 1) { feature_t s = util::getSignificance(i * 1.0e-6); - EXPECT_GREATER(s, 0); - EXPECT_LESS(s, 1); - EXPECT_LESS(s, last); + EXPECT_GT(s, 0); + EXPECT_LT(s, 1); + EXPECT_LT(s, last); last = s; } } } +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/searchlib/src/tests/features/prod_features_test.h b/searchlib/src/tests/features/prod_features_test.h index aeadf23be80..9cd3df7a2ec 100644 --- a/searchlib/src/tests/features/prod_features_test.h +++ b/searchlib/src/tests/features/prod_features_test.h @@ -4,48 +4,18 @@ #include <vespa/searchlib/features/distancetopathfeature.h> #include <vespa/searchlib/features/termdistancefeature.h> -#include <vespa/searchlib/test/ft_test_app.h> +#define ENABLE_GTEST_MIGRATION +#include <vespa/searchlib/test/ft_test_app_base.h> -class Test : public FtTestApp +class Test : public FtTestAppBase { public: Test(); - ~Test() override; - int Main() override; - void testFramework(); - static void testFtLib(); - void testAge(); - void testAttribute(); - void testAttributeMatch(); - void testCloseness(); - void testMatchCount(); - void testGreatCircleDistance(); - void testDistance(); - void testDistanceToPath(); - void testDotProduct(); - void testFieldLength(); - void testFieldMatch(); - void testFieldTermMatch(); - void testFirstPhase(); - void testForeach(); - void testFreshness(); - void testMatch(); - void testMatches(); - void testNow(); - void testQuery(); - void testQueryTermCount(); - void testRandom(); - void testRandomNormal(); - void testRandomNormalStable(); - void testRankingExpression(); - void testTerm(); - void testTermDistance(); - void testUnique(); - static void testUtils(); + ~Test(); static void setupForDotProductTest(FtFeatureTest & ft); -private: +protected: void testFieldMatchBluePrint(); void testFieldMatchExecutor(); void testFieldMatchExecutorOutOfOrder(); @@ -109,7 +79,13 @@ private: bool assertMatches(uint32_t output, const vespalib::string & query, const vespalib::string & field, const vespalib::string & feature = "matches(foo)", uint32_t docId = 1); -private: search::fef::BlueprintFactory _factory; }; +class ProdFeaturesTest : public ::testing::Test, + public Test +{ +protected: + ProdFeaturesTest(); + ~ProdFeaturesTest(); +}; diff --git a/searchlib/src/tests/memoryindex/field_index/field_index_iterator_test.cpp b/searchlib/src/tests/memoryindex/field_index/field_index_iterator_test.cpp index e250cc9487b..1cf8a2ab91f 100644 --- a/searchlib/src/tests/memoryindex/field_index/field_index_iterator_test.cpp +++ b/searchlib/src/tests/memoryindex/field_index/field_index_iterator_test.cpp @@ -3,12 +3,10 @@ #include <vespa/searchcommon/common/schema.h> #include <vespa/searchlib/memoryindex/field_index.h> #include <vespa/searchlib/test/memoryindex/wrap_inserter.h> +#define ENABLE_GTEST_MIGRATION #include <vespa/searchlib/test/searchiteratorverifier.h> #include <vespa/searchlib/fef/termfieldmatchdataarray.h> -#include <vespa/vespalib/testkit/testapp.h> - -#include <vespa/log/log.h> -LOG_SETUP("field_index_iterator_test"); +#include <vespa/vespalib/gtest/gtest.h> using namespace search::fef; using namespace search::index; @@ -65,15 +63,16 @@ struct Fixture { } }; -TEST_F("require that normal posting iterator conforms", Fixture<FieldIndex<false>>) +TEST(FieldIndexIteratorTest, require_that_normal_posting_iterator_conforms) { + Fixture<FieldIndex<false>> f; f.verifier.verify(); } -TEST_F("require that interleaved posting iterator conforms", Fixture<FieldIndex<true>>) +TEST(FieldIndexIteratorTest, require_that_interleaved_posting_iterator_conforms) { + Fixture<FieldIndex<true>> f; f.verifier.verify(); } -TEST_MAIN() { TEST_RUN_ALL(); } - +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/searchlib/src/tests/nativerank/nativerank_test.cpp b/searchlib/src/tests/nativerank/nativerank_test.cpp index 69234071a34..d9f0782008a 100644 --- a/searchlib/src/tests/nativerank/nativerank_test.cpp +++ b/searchlib/src/tests/nativerank/nativerank_test.cpp @@ -9,9 +9,11 @@ #include <vespa/searchlib/fef/fef.h> #include <vespa/searchlib/fef/functiontablefactory.h> #include <vespa/searchlib/fef/test/plugin/setup.h> -#include <vespa/vespalib/util/stringfmt.h> #include <vespa/searchlib/fef/test/dummy_dependency_handler.h> -#include <vespa/searchlib/test/ft_test_app.h> +#define ENABLE_GTEST_MIGRATION +#include <vespa/searchlib/test/ft_test_app_base.h> +#include <vespa/vespalib/gtest/gtest.h> +#include <vespa/vespalib/util/stringfmt.h> #include <vespa/log/log.h> LOG_SETUP("nativerank_test"); @@ -22,13 +24,16 @@ using CollectionType = FieldInfo::CollectionType; const double EPS = 10e-4; -namespace search { -namespace features { +namespace search::features { -class Test : public FtTestApp { -private: +class NativeRankTest : public ::testing::Test, + public FtTestAppBase { +protected: BlueprintFactory _factory; + NativeRankTest(); + ~NativeRankTest() override; + struct ANAM { int32_t attributeWeight; search::query::Weight termWeight; @@ -49,21 +54,20 @@ private: bool assertNativeProximity(feature_t score, const vespalib::string & query, const vespalib::string & field, const Properties & props = Properties(), uint32_t docId = 1); bool assertNativeRank(feature_t score, feature_t fieldMatchWeight, feature_t attributeMatchWeight, feature_t proximityWeight); - - void testNativeFieldMatch(); - void testNativeAttributeMatch(); - void testNativeProximity(); - void testNativeRank(); - -public: - ~Test(); - int Main() override; }; -Test::~Test() {} +NativeRankTest::NativeRankTest() + : ::testing::Test(), + FtTestAppBase() +{ + // Configure factory with all known blueprints. + setup_fef_test_plugin(_factory); + setup_search_features(_factory); +} -void -Test::testNativeFieldMatch() +NativeRankTest::~NativeRankTest() = default; + +TEST_F(NativeRankTest, test_native_field_match) { { // test blueprint NativeFieldMatchBlueprint pt; @@ -100,18 +104,18 @@ Test::testNativeFieldMatch() EXPECT_TRUE(pas.vector[1].firstOccTable == tm.getTable("expdecay(8000,12.50)")); EXPECT_TRUE(pas.vector[0].numOccTable == tm.getTable("loggrowth(1500,4000,19)")); EXPECT_TRUE(pas.vector[1].numOccTable == tm.getTable("loggrowth(1500,4000,19)")); - EXPECT_EQUAL(pas.vector[0].maxTableSum, 1); - EXPECT_EQUAL(pas.vector[1].maxTableSum, 1); - EXPECT_EQUAL(pas.vector[0].fieldWeight, 100u); - EXPECT_EQUAL(pas.vector[1].fieldWeight, 100u); - EXPECT_EQUAL(pas.vector[0].field, true); - EXPECT_EQUAL(pas.vector[1].field, true); - EXPECT_EQUAL(pas.vector[2].field, false); - EXPECT_EQUAL(pas.vector[0].averageFieldLength, NativeFieldMatchParam::NOT_DEF_FIELD_LENGTH); - EXPECT_EQUAL(pas.vector[1].averageFieldLength, NativeFieldMatchParam::NOT_DEF_FIELD_LENGTH); - EXPECT_EQUAL(pas.minFieldLength, 6u); - EXPECT_EQUAL(pas.vector[0].firstOccImportance, 0.5); - EXPECT_EQUAL(pas.vector[1].firstOccImportance, 0.5); + EXPECT_EQ(pas.vector[0].maxTableSum, 1); + EXPECT_EQ(pas.vector[1].maxTableSum, 1); + EXPECT_EQ(pas.vector[0].fieldWeight, 100u); + EXPECT_EQ(pas.vector[1].fieldWeight, 100u); + EXPECT_EQ(pas.vector[0].field, true); + EXPECT_EQ(pas.vector[1].field, true); + EXPECT_EQ(pas.vector[2].field, false); + EXPECT_EQ(pas.vector[0].averageFieldLength, NativeFieldMatchParam::NOT_DEF_FIELD_LENGTH); + EXPECT_EQ(pas.vector[1].averageFieldLength, NativeFieldMatchParam::NOT_DEF_FIELD_LENGTH); + EXPECT_EQ(pas.minFieldLength, 6u); + EXPECT_EQ(pas.vector[0].firstOccImportance, 0.5); + EXPECT_EQ(pas.vector[1].firstOccImportance, 0.5); } { p.clear(); @@ -139,21 +143,21 @@ Test::testNativeFieldMatch() EXPECT_TRUE(pas.vector[3].firstOccTable == tm.getTable("linear(0,1)")); EXPECT_TRUE(pas.vector[0].numOccTable == tm.getTable("linear(0,3)")); EXPECT_TRUE(pas.vector[3].numOccTable == tm.getTable("linear(0,4)")); - EXPECT_APPROX(pas.vector[0].maxTableSum, 2.4, 10e-6); - EXPECT_APPROX(pas.vector[3].maxTableSum, 1.6, 10e-6); - EXPECT_EQUAL(pas.vector[0].fieldWeight, 200u); - EXPECT_EQUAL(pas.vector[1].fieldWeight, 100u); - EXPECT_EQUAL(pas.vector[3].fieldWeight, 0u); - EXPECT_EQUAL(pas.vector[0].field, true); - EXPECT_EQUAL(pas.vector[1].field, false); // only 'foo' and 'baz' are specified explicit - EXPECT_EQUAL(pas.vector[2].field, false); // 'qux' is an attribute - EXPECT_EQUAL(pas.vector[3].field, false); // fieldWeight == 0 -> do not consider this field - EXPECT_EQUAL(pas.vector[4].field, false); // filter field - EXPECT_EQUAL(pas.vector[0].averageFieldLength, 400u); - EXPECT_EQUAL(pas.vector[3].averageFieldLength, 500u); - EXPECT_EQUAL(pas.minFieldLength, 12u); - EXPECT_EQUAL(pas.vector[0].firstOccImportance, 0.6); - EXPECT_EQUAL(pas.vector[3].firstOccImportance, 0.8); + EXPECT_NEAR(pas.vector[0].maxTableSum, 2.4, 10e-6); + EXPECT_NEAR(pas.vector[3].maxTableSum, 1.6, 10e-6); + EXPECT_EQ(pas.vector[0].fieldWeight, 200u); + EXPECT_EQ(pas.vector[1].fieldWeight, 100u); + EXPECT_EQ(pas.vector[3].fieldWeight, 0u); + EXPECT_EQ(pas.vector[0].field, true); + EXPECT_EQ(pas.vector[1].field, false); // only 'foo' and 'baz' are specified explicit + EXPECT_EQ(pas.vector[2].field, false); // 'qux' is an attribute + EXPECT_EQ(pas.vector[3].field, false); // fieldWeight == 0 -> do not consider this field + EXPECT_EQ(pas.vector[4].field, false); // filter field + EXPECT_EQ(pas.vector[0].averageFieldLength, 400u); + EXPECT_EQ(pas.vector[3].averageFieldLength, 500u); + EXPECT_EQ(pas.minFieldLength, 12u); + EXPECT_EQ(pas.vector[0].firstOccImportance, 0.6); + EXPECT_EQ(pas.vector[3].firstOccImportance, 0.8); } { FtIndexEnvironment ie; @@ -172,32 +176,32 @@ Test::testNativeFieldMatch() p.vector.push_back(f); NativeFieldMatchExecutorSharedState nfmess(ft.getQueryEnv(), p); NativeFieldMatchExecutor nfme(nfmess); - EXPECT_EQUAL(p.minFieldLength, 6u); - EXPECT_EQUAL(nfme.getFirstOccBoost(0, 0, 4), 0); - EXPECT_EQUAL(nfme.getFirstOccBoost(0, 1, 4), 1); - EXPECT_EQUAL(nfme.getFirstOccBoost(0, 2, 4), 2); - EXPECT_EQUAL(nfme.getFirstOccBoost(0, 3, 4), 4); - EXPECT_EQUAL(nfme.getFirstOccBoost(0, 3, 6), 4); - EXPECT_EQUAL(nfme.getFirstOccBoost(0, 4, 6), 5); - EXPECT_EQUAL(nfme.getFirstOccBoost(0, 5, 6), 7); - EXPECT_EQUAL(nfme.getFirstOccBoost(0, 0, 12), 0); - EXPECT_EQUAL(nfme.getFirstOccBoost(0, 4, 12), 2); - EXPECT_EQUAL(nfme.getFirstOccBoost(0, 11, 12), 7); - EXPECT_EQUAL(nfme.getNumOccBoost(0, 0, 4), 0); - EXPECT_EQUAL(nfme.getNumOccBoost(0, 2, 4), 2); - EXPECT_EQUAL(nfme.getNumOccBoost(0, 4, 4), 4); - EXPECT_EQUAL(nfme.getNumOccBoost(0, 4, 6), 4); - EXPECT_EQUAL(nfme.getNumOccBoost(0, 5, 6), 5); - EXPECT_EQUAL(nfme.getNumOccBoost(0, 6, 6), 7); - EXPECT_EQUAL(nfme.getNumOccBoost(0, 0, 12), 0); - EXPECT_EQUAL(nfme.getNumOccBoost(0, 6, 12), 3); - EXPECT_EQUAL(nfme.getNumOccBoost(0, 12, 12), 7); + EXPECT_EQ(p.minFieldLength, 6u); + EXPECT_EQ(nfme.getFirstOccBoost(0, 0, 4), 0); + EXPECT_EQ(nfme.getFirstOccBoost(0, 1, 4), 1); + EXPECT_EQ(nfme.getFirstOccBoost(0, 2, 4), 2); + EXPECT_EQ(nfme.getFirstOccBoost(0, 3, 4), 4); + EXPECT_EQ(nfme.getFirstOccBoost(0, 3, 6), 4); + EXPECT_EQ(nfme.getFirstOccBoost(0, 4, 6), 5); + EXPECT_EQ(nfme.getFirstOccBoost(0, 5, 6), 7); + EXPECT_EQ(nfme.getFirstOccBoost(0, 0, 12), 0); + EXPECT_EQ(nfme.getFirstOccBoost(0, 4, 12), 2); + EXPECT_EQ(nfme.getFirstOccBoost(0, 11, 12), 7); + EXPECT_EQ(nfme.getNumOccBoost(0, 0, 4), 0); + EXPECT_EQ(nfme.getNumOccBoost(0, 2, 4), 2); + EXPECT_EQ(nfme.getNumOccBoost(0, 4, 4), 4); + EXPECT_EQ(nfme.getNumOccBoost(0, 4, 6), 4); + EXPECT_EQ(nfme.getNumOccBoost(0, 5, 6), 5); + EXPECT_EQ(nfme.getNumOccBoost(0, 6, 6), 7); + EXPECT_EQ(nfme.getNumOccBoost(0, 0, 12), 0); + EXPECT_EQ(nfme.getNumOccBoost(0, 6, 12), 3); + EXPECT_EQ(nfme.getNumOccBoost(0, 12, 12), 7); } { // test params object NativeFieldMatchParams p; p.resize(1); p.setMaxTableSums(0, 0); // test reset to 1 - EXPECT_EQUAL(p.vector[0].maxTableSum, 1); + EXPECT_EQ(p.vector[0].maxTableSum, 1); } { // test executor @@ -259,11 +263,11 @@ Test::testNativeFieldMatch() } bool -Test::assertNativeFieldMatch(feature_t score, - const vespalib::string & query, - const vespalib::string & field, - const Properties & props, - uint32_t docId) +NativeRankTest::assertNativeFieldMatch(feature_t score, + const vespalib::string & query, + const vespalib::string & field, + const Properties & props, + uint32_t docId) { LOG(info, "assertNativeFieldMatch(%f, '%s', '%s')", score, query.c_str(), field.c_str()); @@ -284,14 +288,12 @@ Test::assertNativeFieldMatch(feature_t score, FT_SETUP(ft, FtUtil::toQuery(query), index, 1); // Execute and compare results. - if (!EXPECT_TRUE(ft.execute(score, EPS, docId))) { - return false; - } - return true; + bool failure = false; + EXPECT_TRUE(ft.execute(score, EPS, docId)) << (failure = true, ""); + return !failure; } -void -Test::testNativeAttributeMatch() +TEST_F(NativeRankTest, test_native_attribute_match) { { // test blueprint NativeAttributeMatchBlueprint pt; @@ -324,13 +326,13 @@ Test::testNativeAttributeMatch() ASSERT_TRUE(pas.vector.size() == 3); // EXPECT_TRUE(pas.vector[0].weightBoostTable == tm.getTable("linear(1,0)")); // EXPECT_TRUE(pas.vector[1].weightBoostTable == tm.getTable("linear(1,0)")); - EXPECT_EQUAL(pas.vector[0].maxTableSum, 1); - EXPECT_EQUAL(pas.vector[1].maxTableSum, 1); - EXPECT_EQUAL(pas.vector[0].fieldWeight, 100u); - EXPECT_EQUAL(pas.vector[1].fieldWeight, 100u); - EXPECT_EQUAL(pas.vector[0].field, true); - EXPECT_EQUAL(pas.vector[1].field, true); - EXPECT_EQUAL(pas.vector[2].field, false); + EXPECT_EQ(pas.vector[0].maxTableSum, 1); + EXPECT_EQ(pas.vector[1].maxTableSum, 1); + EXPECT_EQ(pas.vector[0].fieldWeight, 100u); + EXPECT_EQ(pas.vector[1].fieldWeight, 100u); + EXPECT_EQ(pas.vector[0].field, true); + EXPECT_EQ(pas.vector[1].field, true); + EXPECT_EQ(pas.vector[2].field, false); } { p.clear(); @@ -347,15 +349,15 @@ Test::testNativeAttributeMatch() ASSERT_TRUE(pas.vector.size() == 4); // EXPECT_TRUE(pas.vector[0].weightBoostTable == tm.getTable("linear(0,2)")); // EXPECT_TRUE(pas.vector[3].weightBoostTable == tm.getTable("linear(0,3)")); - EXPECT_EQUAL(pas.vector[0].maxTableSum, 2); - EXPECT_EQUAL(pas.vector[3].maxTableSum, 3); - EXPECT_EQUAL(pas.vector[0].fieldWeight, 200u); - EXPECT_EQUAL(pas.vector[1].fieldWeight, 100u); - EXPECT_EQUAL(pas.vector[3].fieldWeight, 0u); - EXPECT_EQUAL(pas.vector[0].field, true); - EXPECT_EQUAL(pas.vector[1].field, false); // only 'foo' and 'baz' are specified explicit - EXPECT_EQUAL(pas.vector[2].field, false); // 'qux' is an index - EXPECT_EQUAL(pas.vector[3].field, false); // fieldWeight == 0 -> do not consider this field + EXPECT_EQ(pas.vector[0].maxTableSum, 2); + EXPECT_EQ(pas.vector[3].maxTableSum, 3); + EXPECT_EQ(pas.vector[0].fieldWeight, 200u); + EXPECT_EQ(pas.vector[1].fieldWeight, 100u); + EXPECT_EQ(pas.vector[3].fieldWeight, 0u); + EXPECT_EQ(pas.vector[0].field, true); + EXPECT_EQ(pas.vector[1].field, false); // only 'foo' and 'baz' are specified explicit + EXPECT_EQ(pas.vector[2].field, false); // 'qux' is an index + EXPECT_EQ(pas.vector[3].field, false); // fieldWeight == 0 -> do not consider this field } { @@ -388,7 +390,7 @@ Test::testNativeAttributeMatch() } bool -Test::assertNativeAttributeMatch(feature_t score, const ANAM & t1, const ANAM & t2, const Properties & props) +NativeRankTest::assertNativeAttributeMatch(feature_t score, const ANAM & t1, const ANAM & t2, const Properties & props) { LOG(info, "assertNativeAttributeMatch(%f, '%s', '%s')", score, t1.toString().c_str(), t2.toString().c_str()); vespalib::string feature = "nativeAttributeMatch"; @@ -402,15 +404,21 @@ Test::assertNativeAttributeMatch(feature_t score, const ANAM & t1, const ANAM & ft.getIndexEnv().getProperties().add("vespa.fieldweight.bar", vespalib::make_string("%u", t2.fieldWeight)); ft.getIndexEnv().getProperties().add("nativeRank.useTableNormalization", "false"); // make it easier to test ft.getIndexEnv().getProperties().import(props); - if (!EXPECT_TRUE(ft.getQueryEnv().getBuilder().addAttributeNode("foo") != NULL)) { // t1 + bool failure = false; + EXPECT_TRUE(ft.getQueryEnv().getBuilder().addAttributeNode("foo") != NULL) << (failure = true, ""); + if (failure) { return false; } - if (!EXPECT_TRUE(ft.getQueryEnv().getBuilder().addAttributeNode("bar") != NULL)) { // t2 + EXPECT_TRUE(ft.getQueryEnv().getBuilder().addAttributeNode("bar") != NULL) << (failure = true, ""); + if (failure) { return false; } ft.getQueryEnv().getTerms()[0].setWeight(t1.termWeight); ft.getQueryEnv().getTerms()[1].setWeight(t2.termWeight); - ASSERT_TRUE(ft.setup()); + EXPECT_TRUE(ft.setup()) << (failure = true, ""); + if (failure) { + return false; + } MatchDataBuilder::UP mdb = ft.createMatchDataBuilder(); { @@ -427,14 +435,14 @@ Test::assertNativeAttributeMatch(feature_t score, const ANAM & t1, const ANAM & pos.setElementWeight(t2.attributeWeight); tfmd->appendPosition(pos); } - if (!EXPECT_TRUE(ft.execute(score, EPS))) { + EXPECT_TRUE(ft.execute(score, EPS)) << (failure = true, ""); + if (failure) { return false; } return true; } -void -Test::testNativeProximity() +TEST_F(NativeRankTest, test_native_proximity) { { // test blueprint NativeProximityBlueprint pt; @@ -471,16 +479,16 @@ Test::testNativeProximity() EXPECT_TRUE(pas.vector[1].proximityTable == tm.getTable("expdecay(500,3)")); EXPECT_TRUE(pas.vector[0].revProximityTable == tm.getTable("expdecay(400,3)")); EXPECT_TRUE(pas.vector[1].revProximityTable == tm.getTable("expdecay(400,3)")); - EXPECT_EQUAL(pas.vector[0].maxTableSum, 1); - EXPECT_EQUAL(pas.vector[1].maxTableSum, 1); - EXPECT_EQUAL(pas.vector[0].fieldWeight, 100u); - EXPECT_EQUAL(pas.vector[1].fieldWeight, 100u); - EXPECT_EQUAL(pas.vector[0].field, true); - EXPECT_EQUAL(pas.vector[1].field, true); - EXPECT_EQUAL(pas.vector[2].field, false); - EXPECT_EQUAL(pas.slidingWindow, 4u); - EXPECT_EQUAL(pas.vector[0].proximityImportance, 0.5); - EXPECT_EQUAL(pas.vector[1].proximityImportance, 0.5); + EXPECT_EQ(pas.vector[0].maxTableSum, 1); + EXPECT_EQ(pas.vector[1].maxTableSum, 1); + EXPECT_EQ(pas.vector[0].fieldWeight, 100u); + EXPECT_EQ(pas.vector[1].fieldWeight, 100u); + EXPECT_EQ(pas.vector[0].field, true); + EXPECT_EQ(pas.vector[1].field, true); + EXPECT_EQ(pas.vector[2].field, false); + EXPECT_EQ(pas.slidingWindow, 4u); + EXPECT_EQ(pas.vector[0].proximityImportance, 0.5); + EXPECT_EQ(pas.vector[1].proximityImportance, 0.5); } { p.clear(); @@ -506,19 +514,19 @@ Test::testNativeProximity() EXPECT_TRUE(pas.vector[3].proximityTable == tm.getTable("linear(0,1)")); EXPECT_TRUE(pas.vector[0].revProximityTable == tm.getTable("linear(0,3)")); EXPECT_TRUE(pas.vector[3].revProximityTable == tm.getTable("linear(0,4)")); - EXPECT_APPROX(pas.vector[0].maxTableSum, 2.4, 10e-6); - EXPECT_APPROX(pas.vector[3].maxTableSum, 1.6, 10e-6); - EXPECT_EQUAL(pas.vector[0].fieldWeight, 200u); - EXPECT_EQUAL(pas.vector[1].fieldWeight, 100u); - EXPECT_EQUAL(pas.vector[3].fieldWeight, 0u); - EXPECT_EQUAL(pas.vector[0].field, true); - EXPECT_EQUAL(pas.vector[1].field, false); // only 'foo' and 'baz' are specified explicit - EXPECT_EQUAL(pas.vector[2].field, false); // 'qux' is an attribute - EXPECT_EQUAL(pas.vector[3].field, false); // fieldWeight == 0 -> do not consider this field - EXPECT_EQUAL(pas.vector[4].field, false); // filter field - EXPECT_EQUAL(pas.slidingWindow, 2u); - EXPECT_EQUAL(pas.vector[0].proximityImportance, 0.6); - EXPECT_EQUAL(pas.vector[3].proximityImportance, 0.8); + EXPECT_NEAR(pas.vector[0].maxTableSum, 2.4, 10e-6); + EXPECT_NEAR(pas.vector[3].maxTableSum, 1.6, 10e-6); + EXPECT_EQ(pas.vector[0].fieldWeight, 200u); + EXPECT_EQ(pas.vector[1].fieldWeight, 100u); + EXPECT_EQ(pas.vector[3].fieldWeight, 0u); + EXPECT_EQ(pas.vector[0].field, true); + EXPECT_EQ(pas.vector[1].field, false); // only 'foo' and 'baz' are specified explicit + EXPECT_EQ(pas.vector[2].field, false); // 'qux' is an attribute + EXPECT_EQ(pas.vector[3].field, false); // fieldWeight == 0 -> do not consider this field + EXPECT_EQ(pas.vector[4].field, false); // filter field + EXPECT_EQ(pas.slidingWindow, 2u); + EXPECT_EQ(pas.vector[0].proximityImportance, 0.6); + EXPECT_EQ(pas.vector[3].proximityImportance, 0.8); } { @@ -549,34 +557,34 @@ Test::testNativeProximity() NativeProximityExecutor::FieldSetup setup(0); NativeProximityExecutorSharedState::TermPairVector & pairs = setup.pairs; NativeProximityExecutorSharedState::generateTermPairs(env, terms, 0, setup); - EXPECT_EQUAL(pairs.size(), 0u); + EXPECT_EQ(pairs.size(), 0u); NativeProximityExecutorSharedState::generateTermPairs(env, terms, 1, setup); - EXPECT_EQUAL(pairs.size(), 0u); + EXPECT_EQ(pairs.size(), 0u); NativeProximityExecutorSharedState::generateTermPairs(env, terms, 2, setup); - EXPECT_EQUAL(pairs.size(), 2u); + EXPECT_EQ(pairs.size(), 2u); EXPECT_TRUE(pairs[0].first.termData() == &a); EXPECT_TRUE(pairs[0].second.termData() == &b); - EXPECT_EQUAL(pairs[0].connectedness, 0.8); + EXPECT_EQ(pairs[0].connectedness, 0.8); EXPECT_TRUE(pairs[1].first.termData() == &b); EXPECT_TRUE(pairs[1].second.termData() == &c); - EXPECT_EQUAL(pairs[1].connectedness, 0.6); - EXPECT_EQUAL(setup.divisor, 118); // (10 + 40)*0.8 + (40 + 90)*0.6 + EXPECT_EQ(pairs[1].connectedness, 0.6); + EXPECT_EQ(setup.divisor, 118); // (10 + 40)*0.8 + (40 + 90)*0.6 pairs.clear(); setup.divisor = 0; NativeProximityExecutorSharedState::generateTermPairs(env, terms, 3, setup); - EXPECT_EQUAL(pairs.size(), 3u); + EXPECT_EQ(pairs.size(), 3u); EXPECT_TRUE(pairs[0].first.termData() == &a); EXPECT_TRUE(pairs[0].second.termData() == &b); - EXPECT_EQUAL(pairs[0].connectedness, 0.8); + EXPECT_EQ(pairs[0].connectedness, 0.8); EXPECT_TRUE(pairs[1].first.termData() == &a); EXPECT_TRUE(pairs[1].second.termData() == &c); - EXPECT_EQUAL(pairs[1].connectedness, 0.3); + EXPECT_EQ(pairs[1].connectedness, 0.3); EXPECT_TRUE(pairs[2].first.termData() == &b); EXPECT_TRUE(pairs[2].second.termData() == &c); - EXPECT_EQUAL(pairs[2].connectedness, 0.6); - EXPECT_EQUAL(setup.divisor, 148); // (10 + 40)*0.8 + (10 + 90)*0.3 + (40 + 90)*0.6 + EXPECT_EQ(pairs[2].connectedness, 0.6); + EXPECT_EQ(setup.divisor, 148); // (10 + 40)*0.8 + (10 + 90)*0.3 + (40 + 90)*0.6 pairs.clear(); setup.divisor = 0; @@ -585,10 +593,10 @@ Test::testNativeProximity() // test that (ab) is filtered away NativeProximityExecutorSharedState::generateTermPairs(env, terms, 2, setup); - EXPECT_EQUAL(pairs.size(), 1u); + EXPECT_EQ(pairs.size(), 1u); EXPECT_TRUE(pairs[0].first.termData() == &b); EXPECT_TRUE(pairs[0].second.termData() == &c); - EXPECT_EQUAL(pairs[0].connectedness, 0.6); + EXPECT_EQ(pairs[0].connectedness, 0.6); } } @@ -659,11 +667,11 @@ Test::testNativeProximity() } bool -Test::assertNativeProximity(feature_t score, - const vespalib::string & query, - const vespalib::string & field, - const Properties & props, - uint32_t docId) +NativeRankTest::assertNativeProximity(feature_t score, + const vespalib::string & query, + const vespalib::string & field, + const Properties & props, + uint32_t docId) { LOG(info, "assertNativeProximity(%f, '%s', '%s')", score, query.c_str(), field.c_str()); @@ -683,14 +691,15 @@ Test::assertNativeProximity(feature_t score, FT_SETUP(ft, FtUtil::toQuery(query), index, 1); // Execute and compare results. - if (!EXPECT_TRUE(ft.execute(score, EPS, docId))) { + bool failure = false; + EXPECT_TRUE(ft.execute(score, EPS, docId)) << (failure = true, ""); + if (failure) { return false; } return true; } -void -Test::testNativeRank() +TEST_F(NativeRankTest, test_native_rank) { { // test blueprint NativeRankBlueprint pt; @@ -710,9 +719,9 @@ Test::testNativeRank() DummyDependencyHandler deps(*bp); bp->setup(ft.getIndexEnv(), params); const NativeRankParams & pas = (dynamic_cast<NativeRankBlueprint *>(bp.get()))->getParams(); - EXPECT_EQUAL(pas.fieldMatchWeight, 100u); - EXPECT_EQUAL(pas.attributeMatchWeight, 100u); - EXPECT_EQUAL(pas.proximityWeight, 25u); + EXPECT_EQ(pas.fieldMatchWeight, 100u); + EXPECT_EQ(pas.attributeMatchWeight, 100u); + EXPECT_EQ(pas.proximityWeight, 25u); } { Properties & p = ft.getIndexEnv().getProperties(); @@ -721,7 +730,7 @@ Test::testNativeRank() DummyDependencyHandler deps(*bp); bp->setup(ft.getIndexEnv(), params); const NativeRankParams & pas = (dynamic_cast<NativeRankBlueprint *>(bp.get()))->getParams(); - EXPECT_EQUAL(pas.proximityWeight, 100u); + EXPECT_EQ(pas.proximityWeight, 100u); p.clear(); } { @@ -734,9 +743,9 @@ Test::testNativeRank() DummyDependencyHandler deps(*bp); bp->setup(ft.getIndexEnv(), params); const NativeRankParams & pas = (dynamic_cast<NativeRankBlueprint *>(bp.get()))->getParams(); - EXPECT_EQUAL(pas.fieldMatchWeight, 200u); - EXPECT_EQUAL(pas.attributeMatchWeight, 300u); - EXPECT_EQUAL(pas.proximityWeight, 400u); + EXPECT_EQ(pas.fieldMatchWeight, 200u); + EXPECT_EQ(pas.attributeMatchWeight, 300u); + EXPECT_EQ(pas.proximityWeight, 400u); } FT_DUMP(_factory, "nativeRank", ft.getIndexEnv(), StringList().add("nativeRank")); @@ -776,10 +785,10 @@ Test::testNativeRank() } bool -Test::assertNativeRank(feature_t score, - feature_t fieldMatchWeight, - feature_t attributeMatchWeight, - feature_t proximityWeight) +NativeRankTest::assertNativeRank(feature_t score, + feature_t fieldMatchWeight, + feature_t attributeMatchWeight, + feature_t proximityWeight) { LOG(info, "assertNativeRank(%f, %f, %f, %f)", score, fieldMatchWeight, attributeMatchWeight, proximityWeight); @@ -798,39 +807,20 @@ Test::assertNativeRank(feature_t score, ft.getOverrides().add("nativeAttributeMatch", "60"); ft.getOverrides().add("nativeProximity", "30"); - if (!EXPECT_TRUE(ft.setup())) { + bool failure = false; + EXPECT_TRUE(ft.setup()) << (failure = true, ""); + if (failure) { return false; } // Execute and compare results. - if (!EXPECT_TRUE(ft.execute(score, EPS))) { + EXPECT_TRUE(ft.execute(score, EPS)) << (failure = true, ""); + if (failure) { return false; } return true; } - - -int -Test::Main() -{ - TEST_INIT("nativerank_test"); - - // Configure factory with all known blueprints. - setup_fef_test_plugin(_factory); - setup_search_features(_factory); - - testNativeFieldMatch(); - testNativeAttributeMatch(); - testNativeProximity(); - testNativeRank(); - - TEST_DONE(); - return 0; -} - -} } -TEST_APPHOOK(search::features::Test); - +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/searchlib/src/tests/queryeval/blueprint/blueprint_test.cpp b/searchlib/src/tests/queryeval/blueprint/blueprint_test.cpp index d739151a2c4..2a21d66c090 100644 --- a/searchlib/src/tests/queryeval/blueprint/blueprint_test.cpp +++ b/searchlib/src/tests/queryeval/blueprint/blueprint_test.cpp @@ -22,6 +22,9 @@ namespace { class MyOr : public IntermediateBlueprint { private: + FlowCalc make_flow_calc(bool strict, double flow) const override { + return flow_calc<OrFlow>(strict, flow); + } public: FlowStats calculate_flow_stats(uint32_t) const final { return {OrFlow::estimate_of(get_children()), diff --git a/searchlib/src/tests/queryeval/dot_product/dot_product_test.cpp b/searchlib/src/tests/queryeval/dot_product/dot_product_test.cpp index 357065d8667..d160b513534 100644 --- a/searchlib/src/tests/queryeval/dot_product/dot_product_test.cpp +++ b/searchlib/src/tests/queryeval/dot_product/dot_product_test.cpp @@ -1,6 +1,5 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#include <vespa/vespalib/testkit/testapp.h> #include <vespa/searchlib/queryeval/dot_product_search.h> #include <vespa/searchlib/fef/fef.h> #include <vespa/searchlib/query/tree/simplequery.h> @@ -10,7 +9,9 @@ #include <vespa/searchlib/queryeval/fake_result.h> #include <vespa/searchlib/queryeval/fake_searchable.h> #include <vespa/searchlib/queryeval/fake_requestcontext.h> +#define ENABLE_GTEST_MIGRATION #include <vespa/searchlib/test/weightedchildrenverifiers.h> +#include <vespa/vespalib/gtest/gtest.h> using namespace search; using namespace search::query; @@ -83,7 +84,7 @@ struct DP { sb->unpack(docId); result.doc(docId); double score = md->resolveTermField(handle)->getRawScore(); - EXPECT_EQUAL((int)score, score); + EXPECT_EQ((int)score, score); result.score(score); } } @@ -113,6 +114,7 @@ struct MockFixture { MockFixture(uint32_t initial) : MockFixture(initial, {new EmptySearch()}) { } + ~MockFixture(); MockFixture(uint32_t initial, std::vector<SearchIterator *> children) : mock(0), tfmd(), search() { std::vector<TermFieldMatchData*> childMatch; std::vector<int32_t> weights; @@ -130,13 +132,15 @@ struct MockFixture { } }; +MockFixture::~MockFixture() = default; + void verifySimple(const FakeResult & expect, DP & ws) { FakeSearchable index; setupFakeSearchable(index); - EXPECT_EQUAL(expect, ws.search(index, "field", true)); - EXPECT_EQUAL(expect, ws.search(index, "field", false)); - EXPECT_EQUAL(expect, ws.search(index, "multi-field", true)); - EXPECT_EQUAL(expect, ws.search(index, "multi-field", false)); + EXPECT_EQ(expect, ws.search(index, "field", true)); + EXPECT_EQ(expect, ws.search(index, "field", false)); + EXPECT_EQ(expect, ws.search(index, "multi-field", true)); + EXPECT_EQ(expect, ws.search(index, "multi-field", false)); } } // namespace <unnamed> @@ -162,27 +166,31 @@ void run_simple(bool field_is_filter, bool term_is_not_needed) .set_field_is_filter(field_is_filter) .set_term_is_not_needed(term_is_not_needed); - TEST_DO(verifySimple(expect, ws)); + verifySimple(expect, ws); } -TEST("test Simple") { - TEST_DO(run_simple(false, false)); +TEST(DotProductTest, test_simple) +{ + run_simple(false, false); } -TEST("test Simple filter field") { - TEST_DO(run_simple(true, false)); +TEST(DotProductTest, test_simple_filter_field) +{ + run_simple(true, false); } -TEST("test Simple unranked") { - TEST_DO(run_simple(false, true)); +TEST(DotProductTest, test_simple_unranked) +{ + run_simple(false, true); } -TEST("test Simple Single") { +TEST(DotProductTest, test_simple_single) +{ FakeResult expect = FakeResult() .doc(7).score(70 * 7); DP ws = DP().add("7", 70); - TEST_DO(verifySimple(expect, ws)); + verifySimple(expect, ws); } void run_multi(bool field_is_filter, bool term_is_not_needed) @@ -200,65 +208,77 @@ void run_multi(bool field_is_filter, bool term_is_not_needed) .set_field_is_filter(field_is_filter) .set_term_is_not_needed(term_is_not_needed); - EXPECT_EQUAL(expect, ws.search(index, "multi-field", true)); - EXPECT_EQUAL(expect, ws.search(index, "multi-field", false)); + EXPECT_EQ(expect, ws.search(index, "multi-field", true)); + EXPECT_EQ(expect, ws.search(index, "multi-field", false)); } -TEST("test Multi") { - TEST_DO(run_multi(false, false)); +TEST(DotProductTest, test_multi) +{ + run_multi(false, false); } -TEST("test Multi filter field") { - TEST_DO(run_multi(true, false)); +TEST(DotProductTest, test_multi_filter_field) +{ + run_multi(true, false); } -TEST("test Multi unranked") { - TEST_DO(run_multi(false, true)); + +TEST(DotProductTest, test_multi_unranked) +{ + run_multi(false, true); } -TEST_F("test Eager Empty Child", MockFixture(search::endDocId, {})) { +TEST(DotProductTest, test_eager_empty_child) +{ + MockFixture f1(search::endDocId, {}); MockSearch *mock = f1.mock; SearchIterator &search = *f1.search; search.initFullRange(); EXPECT_TRUE(search.isAtEnd()); - EXPECT_EQUAL(0, mock->seekCnt); + EXPECT_EQ(0, mock->seekCnt); } -TEST_F("test Eager Empty Children", MockFixture(search::endDocId)) { +TEST(DotProductTest, test_eager_empty_cildren) +{ + MockFixture f1(search::endDocId); MockSearch *mock = f1.mock; SearchIterator &search = *f1.search; search.initFullRange(); - EXPECT_EQUAL(search.beginId(), search.getDocId()); + EXPECT_EQ(search.beginId(), search.getDocId()); EXPECT_TRUE(!search.seek(1)); EXPECT_TRUE(search.isAtEnd()); - EXPECT_EQUAL(0, mock->seekCnt); + EXPECT_EQ(0, mock->seekCnt); } void verifyEagerMatching(SearchIterator & search, MockSearch * mock) { EXPECT_TRUE(!search.seek(3)); - EXPECT_EQUAL(5u, search.getDocId()); - EXPECT_EQUAL(0, mock->seekCnt); + EXPECT_EQ(5u, search.getDocId()); + EXPECT_EQ(0, mock->seekCnt); EXPECT_TRUE(search.seek(5)); - EXPECT_EQUAL(5u, search.getDocId()); - EXPECT_EQUAL(0, mock->seekCnt); + EXPECT_EQ(5u, search.getDocId()); + EXPECT_EQ(0, mock->seekCnt); EXPECT_TRUE(!search.seek(7)); EXPECT_TRUE(search.isAtEnd()); - EXPECT_EQUAL(1, mock->seekCnt); + EXPECT_EQ(1, mock->seekCnt); } -TEST_F("test Eager Matching Child", MockFixture(5, {})) { +TEST(DotProductTest, test_eager_matching_child) +{ + MockFixture f1(5, {}); MockSearch *mock = f1.mock; SearchIterator &search = *f1.search; search.initFullRange(); - EXPECT_EQUAL(5u, search.getDocId()); + EXPECT_EQ(5u, search.getDocId()); verifyEagerMatching(search, mock); } -TEST_F("test Eager Matching Children", MockFixture(5)) { +TEST(DotProductTest, test_eager_matching_children) +{ + MockFixture f1(5); MockSearch *mock = f1.mock; SearchIterator &search = *f1.search; search.initFullRange(); - EXPECT_EQUAL(search.beginId(), search.getDocId()); + EXPECT_EQ(search.beginId(), search.getDocId()); verifyEagerMatching(search, mock); } @@ -282,14 +302,16 @@ private: } }; -TEST("verify search iterator conformance with search iterator children") { +TEST(DotProductTest, verify_search_iterator_conformance_with_search_iterator_children) +{ IteratorChildrenVerifier verifier; verifier.verify(); } -TEST("verify search iterator conformance with document weight iterator children") { +TEST(DotProductTest, verify_search_iterator_conformance_with_document_weight_iterator_children) +{ WeightIteratorChildrenVerifier verifier; verifier.verify(); } -TEST_MAIN() { TEST_RUN_ALL(); } +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/searchlib/src/tests/queryeval/iterator_benchmark/iterator_benchmark_test.cpp b/searchlib/src/tests/queryeval/iterator_benchmark/iterator_benchmark_test.cpp index 9c084db4a5d..2721f135cfb 100644 --- a/searchlib/src/tests/queryeval/iterator_benchmark/iterator_benchmark_test.cpp +++ b/searchlib/src/tests/queryeval/iterator_benchmark/iterator_benchmark_test.cpp @@ -36,7 +36,6 @@ constexpr uint32_t default_seed = 1234; std::mt19937 gen(default_seed); const vespalib::string field = "myfield"; double budget_sec = 1.0; -using DocidVector = std::vector<uint32_t>; BitVector::UP random_docids(uint32_t docid_limit, uint32_t count) @@ -163,9 +162,18 @@ struct BenchmarkResult { double estimate; double cost; vespalib::string iterator_name; - BenchmarkResult() : BenchmarkResult(0, 0, 0, 0, 0, "") {} - BenchmarkResult(double time_ms_in, uint32_t seeks_in, uint32_t hits_in, double estimate_in, double cost_in, const vespalib::string& iterator_name_in) - : time_ms(time_ms_in), seeks(seeks_in), hits(hits_in), estimate(estimate_in), cost(cost_in), iterator_name(iterator_name_in) {} + vespalib::string blueprint_name; + BenchmarkResult() : BenchmarkResult(0, 0, 0, 0, 0, "", "") {} + BenchmarkResult(double time_ms_in, uint32_t seeks_in, uint32_t hits_in, double estimate_in, double cost_in, + const vespalib::string& iterator_name_in, const vespalib::string& blueprint_name_in) + : time_ms(time_ms_in), + seeks(seeks_in), + hits(hits_in), + estimate(estimate_in), + cost(cost_in), + iterator_name(iterator_name_in), + blueprint_name(blueprint_name_in) + {} double ns_per_seek() const { return (time_ms / seeks) * 1000.0 * 1000.0; } double ms_per_cost() const { return (time_ms / cost); } }; @@ -186,12 +194,35 @@ struct Stats { } }; -class BenchmarkResults { +double +calc_median(const std::vector<double>& sorted_values) +{ + size_t middle = sorted_values.size() / 2; + if (sorted_values.size() % 2 == 0) { + return (sorted_values[middle - 1] + sorted_values[middle]) / 2; + } else { + return sorted_values[middle]; + } +} + +double +calc_standard_deviation(const std::vector<double>& values, double average) +{ + double deviations = 0.0; + for (double val : values) { + double diff = val - average; + deviations += (diff * diff); + } + // Bessel's correction (dividing by N-1, instead of N). + double variance = deviations / (values.size() - 1); + return std::sqrt(variance); +} + +class BenchmarkCaseResult { private: std::vector<BenchmarkResult> _results; - template <typename F> - std::vector<double> extract_sorted_values(F func) const { + std::vector<double> extract_sorted_values(auto func) const { std::vector<double> values; for (const auto& res: _results) { values.push_back(func(res)); @@ -200,27 +231,7 @@ private: return values; } - double calc_median(const std::vector<double>& values) const { - size_t middle = values.size() / 2; - if (values.size() % 2 == 0) { - return (values[middle - 1] + values[middle]) / 2; - } else { - return values[middle]; - } - } - - double calc_standard_deviation(const std::vector<double>& values, double average) const { - double deviations = 0.0; - for (double val : values) { - double diff = val - average; - deviations += (diff * diff); - } - double variance = deviations / values.size(); - return std::sqrt(variance); - } - - template <typename F> - Stats calc_stats(F func) const { + Stats calc_stats(auto func) const { auto values = extract_sorted_values(func); double average = std::accumulate(values.begin(), values.end(), 0.0) / values.size(); double median = calc_median(values); @@ -229,7 +240,7 @@ private: } public: - BenchmarkResults(): _results() {} + BenchmarkCaseResult(): _results() {} void add(const BenchmarkResult& res) { _results.push_back(res); } @@ -244,28 +255,57 @@ public: } }; +std::string +delete_substr_from(const std::string& source, const std::string& substr) +{ + std::string res = source; + auto i = res.find(substr); + while (i != std::string::npos) { + res.erase(i, substr.length()); + i = res.find(substr, i); + } + return res; +} + +vespalib::string +get_class_name(const auto& obj) +{ + auto res = obj.getClassName(); + res = delete_substr_from(res, "search::attribute::"); + res = delete_substr_from(res, "search::queryeval::"); + res = delete_substr_from(res, "vespalib::btree::"); + res = delete_substr_from(res, "search::"); + res = delete_substr_from(res, "vespalib::"); + res = delete_substr_from(res, "anonymous namespace"); + return res; +} + BenchmarkResult -strict_search(SearchIterator& itr, uint32_t docid_limit, double estimate, double strict_cost) +strict_search(Blueprint& blueprint, MatchData& md, uint32_t docid_limit) { + auto itr = blueprint.createSearch(md, true); + assert(itr.get()); BenchmarkTimer timer(budget_sec); uint32_t hits = 0; while (timer.has_budget()) { timer.before(); hits = 0; - itr.initRange(1, docid_limit); - uint32_t docid = itr.seekFirst(1); + itr->initRange(1, docid_limit); + uint32_t docid = itr->seekFirst(1); while (docid < docid_limit) { ++hits; - docid = itr.seekNext(docid + 1); + docid = itr->seekNext(docid + 1); } timer.after(); } - return {timer.min_time() * 1000.0, hits + 1, hits, estimate, strict_cost, itr.getClassName()}; + return {timer.min_time() * 1000.0, hits + 1, hits, blueprint.estimate(), blueprint.strict_cost(), get_class_name(*itr), get_class_name(blueprint)}; } BenchmarkResult -non_strict_search(SearchIterator& itr, uint32_t docid_limit, double estimate, double non_strict_cost) +non_strict_search(Blueprint& blueprint, MatchData& md, uint32_t docid_limit) { + auto itr = blueprint.createSearch(md, false); + assert(itr.get()); BenchmarkTimer timer(budget_sec); uint32_t seeks = 0; uint32_t hits = 0; @@ -273,16 +313,16 @@ non_strict_search(SearchIterator& itr, uint32_t docid_limit, double estimate, do timer.before(); seeks = 0; hits = 0; - itr.initRange(1, docid_limit); - for (uint32_t docid = 1; !itr.isAtEnd(docid); ++docid) { + itr->initRange(1, docid_limit); + for (uint32_t docid = 1; !itr->isAtEnd(docid); ++docid) { ++seeks; - if (itr.seek(docid)) { + if (itr->seek(docid)) { ++hits; } } timer.after(); } - return {timer.min_time() * 1000.0, seeks, hits, estimate, non_strict_cost, itr.getClassName()}; + return {timer.min_time() * 1000.0, seeks, hits, blueprint.estimate(), blueprint.cost(), get_class_name(*itr), get_class_name(blueprint)}; } BenchmarkResult @@ -294,13 +334,9 @@ benchmark_search(Blueprint::UP blueprint, uint32_t docid_limit, bool strict) // This is OK as long as we don't do unpacking and only use 1 thread. auto md = MatchData::makeTestInstance(1, 1); if (strict) { - auto iterator = blueprint->createSearch(*md, true); - assert(iterator.get()); - return strict_search(*iterator, docid_limit, blueprint->estimate(), blueprint->strict_cost()); + return strict_search(*blueprint, *md, docid_limit); } else { - auto iterator = blueprint->createSearch(*md, false); - assert(iterator.get()); - return non_strict_search(*iterator, docid_limit, blueprint->estimate(), blueprint->cost()); + return non_strict_search(*blueprint, *md, docid_limit); } } @@ -342,12 +378,18 @@ to_string(QueryOperator query_op) vespalib::string to_string(const Config& attr_config) { + std::ostringstream oss; auto col_type = attr_config.collectionType(); auto basic_type = attr_config.basicType(); if (col_type == CollectionType::SINGLE) { - return basic_type.asString(); + oss << basic_type.asString(); + } else { + oss << col_type.asString() << "<" << basic_type.asString() << ">"; + } + if (attr_config.fastSearch()) { + oss << "(fs)"; } - return vespalib::string(col_type.asString()) + "<" + vespalib::string(basic_type.asString()) + ">"; + return oss.str(); } std::unique_ptr<Node> @@ -408,124 +450,167 @@ run_benchmark(IAttributeContext& attr_ctx, QueryOperator query_op, const benchma } void +print_result_header() +{ + std::cout << "| children | t_ratio | a_ratio | est | hits | seeks | time_ms | cost | ns_per_seek | ms_per_cost | iterator | blueprint |" << std::endl; +} + +void print_result(const BenchmarkResult& res, const benchmark::TermVector& terms, double hit_ratio, uint32_t num_docs) { std::cout << std::fixed << std::setprecision(3) - << "children=" << std::setw(4) << terms.size() - << ", t_ratio=" << std::setw(5) << hit_ratio - << ", a_ratio=" << std::setw(5) << ((double) res.hits / (double) num_docs) - << ", est=" << std::setw(5) << res.estimate - << ", hits=" << std::setw(7) << res.hits - << ", seeks=" << std::setw(8) << res.seeks + << "| " << std::setw(8) << terms.size() + << " | " << std::setw(7) << hit_ratio + << " | " << std::setw(7) << ((double) res.hits / (double) num_docs) + << " | " << std::setw(5) << res.estimate + << " | " << std::setw(8) << res.hits + << " | " << std::setw(8) << res.seeks << std::setprecision(2) - << ", time_ms=" << std::setw(8) << res.time_ms + << " | " << std::setw(8) << res.time_ms << std::setprecision(3) - << ", cost=" << std::setw(8) << res.cost + << " | " << std::setw(8) << res.cost << std::setprecision(2) - << ", ns_per_seek=" << std::setw(8) << res.ns_per_seek() - << ", ms_per_cost=" << std::setw(7) << res.ms_per_cost() - << ", itr=" << res.iterator_name << std::endl; + << " | " << std::setw(11) << res.ns_per_seek() + << " | " << std::setw(11) << res.ms_per_cost() + << " | " << res.iterator_name + << " | " << res.blueprint_name << " |" << std::endl; } void -print_results(const BenchmarkResults& results) +print_result(const BenchmarkCaseResult& result) { std::cout << std::fixed << std::setprecision(3) - << "statistics summary: time_ms=" << results.time_ms_stats().to_string() - << ", ns_per_seek=" << results.ns_per_seek_stats().to_string() - << ", ms_per_cost=" << results.ms_per_cost_stats().to_string() << std::endl << std::endl; + << "summary: time_ms=" << result.time_ms_stats().to_string() + << ", ns_per_seek=" << result.ns_per_seek_stats().to_string() + << ", ms_per_cost=" << result.ms_per_cost_stats().to_string() << std::endl << std::endl; } struct BenchmarkCase { Config attr_cfg; QueryOperator query_op; bool strict; - BenchmarkResults results; - double scaled_cost; - BenchmarkCase(const Config& attr_cfg_in, QueryOperator query_op_in, bool strict_in, const BenchmarkResults& results_in) + BenchmarkCase(const Config& attr_cfg_in, QueryOperator query_op_in, bool strict_in) : attr_cfg(attr_cfg_in), query_op(query_op_in), - strict(strict_in), - results(results_in), + strict(strict_in) + {} + vespalib::string to_string() const { + return "op=" + ::to_string(query_op) + ", cfg=" + ::to_string(attr_cfg) + ", strict=" + (strict ? "true" : "false"); + } +}; + +struct BenchmarkCaseSummary { + BenchmarkCase bcase; + BenchmarkCaseResult result; + double scaled_cost; + BenchmarkCaseSummary(const BenchmarkCase& bcase_in, const BenchmarkCaseResult& result_in) + : bcase(bcase_in), + result(result_in), scaled_cost(1.0) {} - BenchmarkCase(const BenchmarkCase&); - BenchmarkCase& operator=(const BenchmarkCase&); - ~BenchmarkCase(); + BenchmarkCaseSummary(const BenchmarkCaseSummary&); + BenchmarkCaseSummary& operator=(const BenchmarkCaseSummary&); + ~BenchmarkCaseSummary(); }; -BenchmarkCase::BenchmarkCase(const BenchmarkCase&) = default; -BenchmarkCase& BenchmarkCase::operator=(const BenchmarkCase&) = default; -BenchmarkCase::~BenchmarkCase() = default; +BenchmarkCaseSummary::BenchmarkCaseSummary(const BenchmarkCaseSummary&) = default; +BenchmarkCaseSummary& BenchmarkCaseSummary::operator=(const BenchmarkCaseSummary&) = default; +BenchmarkCaseSummary::~BenchmarkCaseSummary() = default; class BenchmarkSummary { private: - std::vector<BenchmarkCase> _cases; - double _baseline_ms_per_cost; + std::vector<BenchmarkCaseSummary> _cases; public: - BenchmarkSummary(double baseline_ms_per_cost_in) - : _cases(), - _baseline_ms_per_cost(baseline_ms_per_cost_in) + BenchmarkSummary() + : _cases() {} - double baseline_ms_per_cost() const { return _baseline_ms_per_cost; } - void add(const Config& attr_cfg, QueryOperator query_op, bool strict, const BenchmarkResults& results) { - _cases.emplace_back(attr_cfg, query_op, strict, results); + void add(const BenchmarkCase& bcase, const BenchmarkCaseResult& result) { + _cases.emplace_back(bcase, result); } void calc_scaled_costs() { std::sort(_cases.begin(), _cases.end(), [](const auto& lhs, const auto& rhs) { - return lhs.results.ms_per_cost_stats().average < rhs.results.ms_per_cost_stats().average; + return lhs.result.ms_per_cost_stats().average < rhs.result.ms_per_cost_stats().average; }); - for (auto& c : _cases) { - c.scaled_cost = c.results.ms_per_cost_stats().average / _baseline_ms_per_cost; + double baseline_ms_per_cost = _cases[0].result.ms_per_cost_stats().average; + for (size_t i = 1; i < _cases.size(); ++i) { + auto& c = _cases[i]; + c.scaled_cost = c.result.ms_per_cost_stats().average / baseline_ms_per_cost; } } - const std::vector<BenchmarkCase>& cases() const { return _cases; } + const std::vector<BenchmarkCaseSummary>& cases() const { return _cases; } }; -vespalib::string -to_string(QueryOperator query_op, const Config& attr_cfg, bool strict) -{ - return "op=" + to_string(query_op) + ", cfg=" + to_string(attr_cfg) + ", strict=" + (strict ? "true" : "false"); -} - void print_summary(const BenchmarkSummary& summary) { - std::cout << "-------- benchmark summary (baseline_ms_per_cost=" << summary.baseline_ms_per_cost() << ") --------" << std::endl; + std::cout << "-------- benchmark summary --------" << std::endl; for (const auto& c : summary.cases()) { std::cout << std::fixed << std::setprecision(3) << "" - << std::setw(40) << std::left << to_string(c.query_op, c.attr_cfg, c.strict) << ": " - << "ms_per_cost=" << std::setw(7) << std::right << c.results.ms_per_cost_stats().to_string() + << std::setw(50) << std::left << c.bcase.to_string() << ": " + << "ms_per_cost=" << std::setw(7) << std::right << c.result.ms_per_cost_stats().to_string() << ", scaled_cost=" << std::setw(7) << c.scaled_cost << std::endl; } } -struct BenchmarkSetup { +struct BenchmarkCaseSetup { uint32_t num_docs; - Config attr_cfg; - QueryOperator query_op; + BenchmarkCase bcase; std::vector<double> hit_ratios; std::vector<uint32_t> child_counts; + uint32_t default_values_per_document; + BenchmarkCaseSetup(uint32_t num_docs_in, + const BenchmarkCase& bcase_in, + const std::vector<double>& hit_ratios_in, + const std::vector<uint32_t>& child_counts_in) + : num_docs(num_docs_in), + bcase(bcase_in), + hit_ratios(hit_ratios_in), + child_counts(child_counts_in), + default_values_per_document(0) + {} + ~BenchmarkCaseSetup() {} +}; + +struct BenchmarkSetup { + uint32_t num_docs; + std::vector<Config> attr_cfgs; + std::vector<QueryOperator> query_ops; std::vector<bool> strictness; + std::vector<double> hit_ratios; + std::vector<uint32_t> child_counts; uint32_t default_values_per_document; BenchmarkSetup(uint32_t num_docs_in, - Config attr_cfg_in, - QueryOperator query_op_in, + const std::vector<Config>& attr_cfgs_in, + const std::vector<QueryOperator>& query_ops_in, + const std::vector<bool>& strictness_in, const std::vector<double>& hit_ratios_in, - const std::vector<uint32_t>& child_counts_in, - const std::vector<bool>& strictness_in) + const std::vector<uint32_t>& child_counts_in) : num_docs(num_docs_in), - attr_cfg(attr_cfg_in), - query_op(query_op_in), + attr_cfgs(attr_cfgs_in), + query_ops(query_ops_in), + strictness(strictness_in), hit_ratios(hit_ratios_in), child_counts(child_counts_in), - strictness(strictness_in), default_values_per_document(0) {} - ~BenchmarkSetup() {} + BenchmarkSetup(uint32_t num_docs_in, + const std::vector<Config>& attr_cfgs_in, + const std::vector<QueryOperator>& query_ops_in, + const std::vector<bool>& strictness_in, + const std::vector<double>& hit_ratios_in) + : BenchmarkSetup(num_docs_in, attr_cfgs_in, query_ops_in, strictness_in, hit_ratios_in, {1}) + {} + BenchmarkCaseSetup make_case_setup(const BenchmarkCase& bcase) const { + BenchmarkCaseSetup res(num_docs, bcase, hit_ratios, child_counts); + res.default_values_per_document = default_values_per_document; + return res; + } + ~BenchmarkSetup(); }; +BenchmarkSetup::~BenchmarkSetup() = default; + uint32_t calc_hits_per_term(uint32_t num_docs, double target_hit_ratio, uint32_t children, QueryOperator query_op) { @@ -538,27 +623,44 @@ calc_hits_per_term(uint32_t num_docs, double target_hit_ratio, uint32_t children } } -BenchmarkResults +BenchmarkCaseResult +run_benchmark_case(const BenchmarkCaseSetup& setup) +{ + BenchmarkCaseResult result; + std::cout << "-------- run_benchmark_case: " << setup.bcase.to_string() << " --------" << std::endl; + print_result_header(); + for (double hit_ratio : setup.hit_ratios) { + for (uint32_t children : setup.child_counts) { + uint32_t hits_per_term = calc_hits_per_term(setup.num_docs, hit_ratio, children, setup.bcase.query_op); + HitSpecs hit_specs(55555); + hit_specs.add(setup.default_values_per_document, setup.num_docs); + auto terms = hit_specs.add(children, hits_per_term); + auto attr_ctx = make_attribute_context(setup.bcase.attr_cfg, setup.num_docs, hit_specs); + auto res = run_benchmark(*attr_ctx, setup.bcase.query_op, terms, setup.num_docs + 1, setup.bcase.strict); + print_result(res, terms, hit_ratio, setup.num_docs); + result.add(res); + } + } + print_result(result); + return result; +} + +void run_benchmarks(const BenchmarkSetup& setup) { - BenchmarkResults results; - for (bool strict : setup.strictness) { - std::cout << "-------- run_benchmarks: " << to_string(setup.query_op, setup.attr_cfg, strict) << " --------" << std::endl; - for (double hit_ratio : setup.hit_ratios) { - for (uint32_t children : setup.child_counts) { - uint32_t hits_per_term = calc_hits_per_term(setup.num_docs, hit_ratio, children, setup.query_op); - HitSpecs hit_specs(55555); - hit_specs.add(setup.default_values_per_document, setup.num_docs); - auto terms = hit_specs.add(children, hits_per_term); - auto attr_ctx = make_attribute_context(setup.attr_cfg, setup.num_docs, hit_specs); - auto res = run_benchmark(*attr_ctx, setup.query_op, terms, setup.num_docs + 1, strict); - print_result(res, terms, hit_ratio, setup.num_docs); - results.add(res); + BenchmarkSummary summary; + for (const auto& attr_cfg : setup.attr_cfgs) { + for (auto query_op : setup.query_ops) { + for (bool strict : setup.strictness) { + BenchmarkCase bcase(attr_cfg, query_op, strict); + auto case_setup = setup.make_case_setup(bcase); + auto results = run_benchmark_case(case_setup); + summary.add(bcase, results); } } } - print_results(results); - return results; + summary.calc_scaled_costs(); + print_summary(summary); } Config @@ -570,67 +672,60 @@ make_config(BasicType basic_type, CollectionType col_type, bool fast_search) } constexpr uint32_t num_docs = 10'000'000; -const std::vector<double> hit_ratios = {0.001, 0.01, 0.1, 0.5}; -const std::vector<uint32_t> child_counts = {1, 10, 100, 1000}; +const std::vector<double> base_hit_ratios = {0.001, 0.01, 0.1, 0.5}; const Config int32 = make_config(BasicType::INT32, CollectionType::SINGLE, false); const Config int32_fs = make_config(BasicType::INT32, CollectionType::SINGLE, true); const Config int32_array = make_config(BasicType::INT32, CollectionType::ARRAY, false); const Config int32_array_fs = make_config(BasicType::INT32, CollectionType::ARRAY, true); const Config int32_wset_fs = make_config(BasicType::INT32, CollectionType::WSET, true); const Config str = make_config(BasicType::STRING, CollectionType::SINGLE, false); +const Config str_fs = make_config(BasicType::STRING, CollectionType::SINGLE, true); const Config str_array = make_config(BasicType::STRING, CollectionType::ARRAY, false); +const Config str_array_fs = make_config(BasicType::STRING, CollectionType::ARRAY, true); TEST(IteratorBenchmark, analyze_term_search_in_attributes_without_fast_search) { std::vector<Config> attr_cfgs = {int32, int32_array, str, str_array}; - const std::vector<double> my_hit_ratios = {0.001, 0.005, 0.01, 0.05, 0.1, 0.3, 0.5, 0.7, 0.9}; - BenchmarkSummary summary(25.0); - for (const auto& attr_cfg : attr_cfgs) { - for (bool strict : {true, false}) { - BenchmarkSetup setup(num_docs, attr_cfg, QueryOperator::Term, my_hit_ratios, {1}, {strict}); - setup.default_values_per_document = 1; - auto results = run_benchmarks(setup); - summary.add(attr_cfg, QueryOperator::Term, strict, results); - } - } - summary.calc_scaled_costs(); - print_summary(summary); -} - -TEST(IteratorBenchmark, term_benchmark) -{ - BenchmarkSetup setup(num_docs, int32_fs, QueryOperator::Term, hit_ratios, {1}, {true, false}); + const std::vector<double> hit_ratios = {0.001, 0.005, 0.01, 0.05, 0.1, 0.3, 0.5, 0.7, 0.9}; + BenchmarkSetup setup(num_docs, attr_cfgs, {QueryOperator::Term}, {true, false}, hit_ratios); + setup.default_values_per_document = 1; run_benchmarks(setup); } -TEST(IteratorBenchmark, in_benchmark) +TEST(IteratorBenchmark, analyze_term_search_in_attributes_with_fast_search) { - BenchmarkSetup setup(num_docs, int32_array_fs, QueryOperator::In, hit_ratios, child_counts, {true, false}); + std::vector<Config> attr_cfgs = {int32_array, int32_fs}; //, int32_array_fs, str_fs, str_array_fs}; + const std::vector<double> hit_ratios = {0.001, 0.01, 0.1, 0.2, 0.4, 0.6, 0.8, 1.0}; + BenchmarkSetup setup(num_docs, attr_cfgs, {QueryOperator::Term}, {true, false}, hit_ratios); + setup.default_values_per_document = 1; run_benchmarks(setup); } -TEST(IteratorBenchmark, weighted_set_benchmark) +TEST(IteratorBenchmark, analyze_complex_leaf_operators) { - BenchmarkSetup setup(num_docs, int32_array_fs, QueryOperator::WeightedSet, hit_ratios, child_counts, {true, false}); + std::vector<Config> attr_cfgs = {int32_array_fs}; + std::vector<QueryOperator> query_ops = {QueryOperator::In, QueryOperator::DotProduct}; + const std::vector<double> hit_ratios = {0.001, 0.01, 0.1, 0.2, 0.4, 0.6, 0.8}; + BenchmarkSetup setup(num_docs, attr_cfgs, query_ops, {true, false}, hit_ratios, {1, 2, 10, 100}); run_benchmarks(setup); } -TEST(IteratorBenchmark, dot_product_benchmark) +TEST(IteratorBenchmark, term_benchmark) { - BenchmarkSetup setup(num_docs, int32_wset_fs, QueryOperator::DotProduct, hit_ratios, child_counts, {true, false}); + BenchmarkSetup setup(num_docs, {int32_fs}, {QueryOperator::Term}, {true, false}, base_hit_ratios); run_benchmarks(setup); } TEST(IteratorBenchmark, and_benchmark) { - BenchmarkSetup setup(num_docs, int32_array_fs, QueryOperator::And, hit_ratios, {1, 2, 4, 8}, {true, false}); + BenchmarkSetup setup(num_docs, {int32_array_fs}, {QueryOperator::And}, {true, false}, base_hit_ratios, {1, 2, 4, 8}); run_benchmarks(setup); } TEST(IteratorBenchmark, or_benchmark) { - BenchmarkSetup setup(num_docs, int32_array_fs, QueryOperator::Or, hit_ratios, child_counts, {true, false}); + BenchmarkSetup setup(num_docs, {int32_array_fs}, {QueryOperator::Or}, {true, false}, base_hit_ratios, {1, 10, 100, 1000}); run_benchmarks(setup); } diff --git a/searchlib/src/tests/queryeval/monitoring_search_iterator/monitoring_search_iterator_test.cpp b/searchlib/src/tests/queryeval/monitoring_search_iterator/monitoring_search_iterator_test.cpp index f5b90fd862c..c20c7091355 100644 --- a/searchlib/src/tests/queryeval/monitoring_search_iterator/monitoring_search_iterator_test.cpp +++ b/searchlib/src/tests/queryeval/monitoring_search_iterator/monitoring_search_iterator_test.cpp @@ -1,5 +1,4 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#include <vespa/vespalib/testkit/test_kit.h> #include <vespa/searchlib/queryeval/andsearch.h> #include <vespa/searchlib/queryeval/monitoring_search_iterator.h> #include <vespa/searchlib/queryeval/monitoring_dump_iterator.h> @@ -7,9 +6,11 @@ #include <vespa/searchlib/queryeval/simplesearch.h> #include <vespa/searchlib/queryeval/test/searchhistory.h> #include <vespa/vespalib/objects/objectdumper.h> +#define ENABLE_GTEST_MIGRATION #include <vespa/searchlib/test/searchiteratorverifier.h> #include <vespa/searchlib/common/bitvectoriterator.h> #include <vespa/searchlib/fef/termfieldmatchdata.h> +#include <vespa/vespalib/gtest/gtest.h> using namespace search::queryeval; using namespace search::queryeval::test; @@ -92,71 +93,81 @@ struct TreeFixture false)); _res.search(*_itr); } + ~TreeFixture(); }; -TEST_F("require that number of seeks is collected", SimpleFixture) +TreeFixture::~TreeFixture() = default; + +TEST(MonitoringSearchIteratorTest, require_that_number_of_seeks_is_collected) { - EXPECT_EQUAL(4u, f._itr.getStats().getNumSeeks()); - EXPECT_EQUAL(4.0 / 3.0, f._itr.getStats().getNumSeeksPerUnpack()); + SimpleFixture f; + EXPECT_EQ(4u, f._itr.getStats().getNumSeeks()); + EXPECT_EQ(4.0 / 3.0, f._itr.getStats().getNumSeeksPerUnpack()); } -TEST_F("require that number of unpacks is collected", SimpleFixture) +TEST(MonitoringSearchIteratorTest, require_that_number_of_unpacks_is_collected) { - EXPECT_EQUAL(3u, f._itr.getStats().getNumUnpacks()); + SimpleFixture f; + EXPECT_EQ(3u, f._itr.getStats().getNumUnpacks()); } -TEST_F("require that docId stepping is collected (root iterator)", SimpleFixture) +TEST(MonitoringSearchIteratorTest, require_that_docid_stepping_is_collected_for_root_iterator) { - EXPECT_EQUAL(4u, f._itr.getStats().getNumDocIdSteps()); - EXPECT_EQUAL(1, f._itr.getStats().getAvgDocIdSteps()); + SimpleFixture f; + EXPECT_EQ(4u, f._itr.getStats().getNumDocIdSteps()); + EXPECT_EQ(1, f._itr.getStats().getAvgDocIdSteps()); } -TEST_F("require that docId stepping is collected (child iterator)", AdvancedFixture) +TEST(MonitoringSearchIteratorTest, require_that_docid_stepping_is_collected_for_child_iterator) { + AdvancedFixture f; f._itr.seek(1); // 2 - 1 - EXPECT_EQUAL(1u, f._itr.getStats().getNumDocIdSteps()); + EXPECT_EQ(1u, f._itr.getStats().getNumDocIdSteps()); f._itr.seek(19); // 19 - 2 - EXPECT_EQUAL(18u, f._itr.getStats().getNumDocIdSteps()); + EXPECT_EQ(18u, f._itr.getStats().getNumDocIdSteps()); f._itr.seek(64); // 64 - 32 - EXPECT_EQUAL(50u, f._itr.getStats().getNumDocIdSteps()); + EXPECT_EQ(50u, f._itr.getStats().getNumDocIdSteps()); f._itr.seek(74); // 74 - 64 - EXPECT_EQUAL(60u, f._itr.getStats().getNumDocIdSteps()); - EXPECT_EQUAL(60 / 4, f._itr.getStats().getAvgDocIdSteps()); + EXPECT_EQ(60u, f._itr.getStats().getNumDocIdSteps()); + EXPECT_EQ(60 / 4, f._itr.getStats().getAvgDocIdSteps()); } -TEST_F("require that hit skipping is collected ", AdvancedFixture) +TEST(MonitoringSearchIteratorTest, require_that_hit_skipping_is_collected) { + AdvancedFixture f; f._itr.seek(1); - EXPECT_EQUAL(0u, f._itr.getStats().getNumHitSkips()); + EXPECT_EQ(0u, f._itr.getStats().getNumHitSkips()); f._itr.seek(4); - EXPECT_EQUAL(0u, f._itr.getStats().getNumHitSkips()); + EXPECT_EQ(0u, f._itr.getStats().getNumHitSkips()); f._itr.seek(16); - EXPECT_EQUAL(1u, f._itr.getStats().getNumHitSkips()); + EXPECT_EQ(1u, f._itr.getStats().getNumHitSkips()); f._itr.seek(120); - EXPECT_EQUAL(3u, f._itr.getStats().getNumHitSkips()); - EXPECT_EQUAL(3.0 / 4.0, f._itr.getStats().getAvgHitSkips()); + EXPECT_EQ(3u, f._itr.getStats().getNumHitSkips()); + EXPECT_EQ(3.0 / 4.0, f._itr.getStats().getAvgHitSkips()); } -TEST_F("require that results from underlying iterator is exposed through monitoring iterator", SimpleFixture) +TEST(MonitoringSearchIteratorTest, require_that_results_from_underlying_iterator_is_exposed_through_monitoring_iterator) { - EXPECT_EQUAL(SimpleResult().addHit(2).addHit(4).addHit(8), f._res); + SimpleFixture f; + EXPECT_EQ(SimpleResult().addHit(2).addHit(4).addHit(8), f._res); } -TEST_F("require that calls are forwarded to underlying iterator", HistoryFixture) +TEST(MonitoringSearchIteratorTest, require_that_calls_are_forwarded_to_underlying_iterator) { + HistoryFixture f; f._itr.seek(2); - EXPECT_EQUAL(2u, f._itr.getDocId()); + EXPECT_EQ(2u, f._itr.getDocId()); f._itr.unpack(2); f._itr.seek(4); - EXPECT_EQUAL(4u, f._itr.getDocId()); + EXPECT_EQ(4u, f._itr.getDocId()); f._itr.unpack(4); f._itr.seek(8); - EXPECT_EQUAL(8u, f._itr.getDocId()); + EXPECT_EQ(8u, f._itr.getDocId()); f._itr.unpack(8); f._itr.getPostingInfo(); const HistorySearchIterator &hsi = dynamic_cast<const HistorySearchIterator &>(f._itr.getIterator()); - EXPECT_EQUAL(SearchHistory().seek("x", 2).unpack("x", 2).seek("x", 4).unpack("x", 4).seek("x", 8).unpack("x", 8), - hsi._history); + EXPECT_EQ(SearchHistory().seek("x", 2).unpack("x", 2).seek("x", 4).unpack("x", 4).seek("x", 8).unpack("x", 8), + hsi._history); EXPECT_TRUE(hsi._getPostingInfoCalled); } @@ -183,7 +194,7 @@ addIterator(MonitoringSearchIterator::Dumper &d, d.closeStruct(); } -TEST("require that dumper can handle formatting on several levels") +TEST(MonitoringSearchIteratorTest, require_that_dumper_can_handle_formatting_on_several_levels) { MonitoringSearchIterator::Dumper d(2, 6, 6, 10, 3); addIterator(d, "root", 1, 1.1, 11.22, 11, 111.3); @@ -205,7 +216,7 @@ TEST("require that dumper can handle formatting on several levels") } d.closeStruct(); } - EXPECT_EQUAL( + EXPECT_EQ( "root: 1 seeks, 1.100 steps/seek, 11.220 skips/seek, 11 unpacks, 111.300 seeks/unpack\n" " c.1: 222222 seeks, 2.111 steps/seek, 22.222 skips/seek, 222000 unpacks, 222.444 seeks/unpack\n" " c.1.1: 333333 seeks, 3.111 steps/seek, 33.222 skips/seek, 333000 unpacks, 333333.444 seeks/unpack\n" @@ -216,99 +227,103 @@ TEST("require that dumper can handle formatting on several levels") d.toString()); } -TEST_F("require that single iterator can be dumped compact", AdvancedFixture) +TEST(MonitoringSearchIteratorTest, require_that_single_iterator_can_be_dumped_compact) { + AdvancedFixture f; f._itr.seek(6); f._itr.seek(16); f._itr.unpack(16); MonitoringSearchIterator::Dumper dumper; visit(dumper, "", f._itr); - EXPECT_EQUAL("AdvancedIterator: 2 seeks, 7.00 steps/seek, 1.00 skips/seek, 1 unpacks, 2.00 seeks/unpack\n", - dumper.toString()); + EXPECT_EQ("AdvancedIterator: 2 seeks, 7.00 steps/seek, 1.00 skips/seek, 1 unpacks, 2.00 seeks/unpack\n", + dumper.toString()); } -TEST_F("require that iterator tree can be dumped compact", TreeFixture) +TEST(MonitoringSearchIteratorTest, require_that_iterator_tree_can_be_dumped_compact) { + TreeFixture f; MonitoringSearchIterator::Dumper dumper; visit(dumper, "", f._itr.get()); - EXPECT_EQUAL("and: 2 seeks, 1.00 steps/seek, 0.00 skips/seek, 1 unpacks, 2.00 seeks/unpack\n" - " child1: 3 seeks, 1.00 steps/seek, 0.00 skips/seek, 1 unpacks, 3.00 seeks/unpack\n" - " child2: 3 seeks, 1.67 steps/seek, 0.00 skips/seek, 1 unpacks, 3.00 seeks/unpack\n", - dumper.toString()); + EXPECT_EQ("and: 2 seeks, 1.00 steps/seek, 0.00 skips/seek, 1 unpacks, 2.00 seeks/unpack\n" + " child1: 3 seeks, 1.00 steps/seek, 0.00 skips/seek, 1 unpacks, 3.00 seeks/unpack\n" + " child2: 3 seeks, 1.67 steps/seek, 0.00 skips/seek, 1 unpacks, 3.00 seeks/unpack\n", + dumper.toString()); } -TEST_F("require that single iterator can be dumped verbosely", AdvancedFixture) +TEST(MonitoringSearchIteratorTest, require_that_single_iterator_can_be_dumped_verbosely) { + AdvancedFixture f; f._itr.seek(6); f._itr.seek(16); f._itr.unpack(16); vespalib::ObjectDumper dumper; visit(dumper, "", &f._itr); - EXPECT_EQUAL("search::queryeval::MonitoringSearchIterator {\n" - " iteratorName: 'AdvancedIterator'\n" - " iteratorType: 'search::queryeval::SimpleSearch'\n" - " stats: MonitoringSearchIterator::Stats {\n" - " numSeeks: 2\n" - " numDocIdSteps: 14\n" - " avgDocIdSteps: 7\n" - " numHitSkips: 2\n" - " avgHitSkips: 1\n" - " numUnpacks: 1\n" - " numSeeksPerUnpack: 2\n" - " }\n" - " tag: '<null>'\n" - "}\n", - dumper.toString()); + EXPECT_EQ("search::queryeval::MonitoringSearchIterator {\n" + " iteratorName: 'AdvancedIterator'\n" + " iteratorType: 'search::queryeval::SimpleSearch'\n" + " stats: MonitoringSearchIterator::Stats {\n" + " numSeeks: 2\n" + " numDocIdSteps: 14\n" + " avgDocIdSteps: 7\n" + " numHitSkips: 2\n" + " avgHitSkips: 1\n" + " numUnpacks: 1\n" + " numSeeksPerUnpack: 2\n" + " }\n" + " tag: '<null>'\n" + "}\n", + dumper.toString()); } -TEST_F("require that iterator tree can be dumped verbosely", TreeFixture) +TEST(MonitoringSearchIteratorTest, require_that_iterator_tree_can_be_dumped_verbosely) { + TreeFixture f; vespalib::ObjectDumper dumper; visit(dumper, "", f._itr.get()); - EXPECT_EQUAL("search::queryeval::MonitoringSearchIterator {\n" - " iteratorName: 'and'\n" - " iteratorType: 'search::queryeval::AndSearchStrict<search::queryeval::(anonymous namespace)::FullUnpack>'\n" - " stats: MonitoringSearchIterator::Stats {\n" - " numSeeks: 2\n" - " numDocIdSteps: 2\n" - " avgDocIdSteps: 1\n" - " numHitSkips: 0\n" - " avgHitSkips: 0\n" - " numUnpacks: 1\n" - " numSeeksPerUnpack: 2\n" - " }\n" - " children: std::vector {\n" - " [0]: search::queryeval::MonitoringSearchIterator {\n" - " iteratorName: 'child1'\n" - " iteratorType: 'search::queryeval::SimpleSearch'\n" - " stats: MonitoringSearchIterator::Stats {\n" - " numSeeks: 3\n" - " numDocIdSteps: 3\n" - " avgDocIdSteps: 1\n" - " numHitSkips: 0\n" - " avgHitSkips: 0\n" - " numUnpacks: 1\n" - " numSeeksPerUnpack: 3\n" - " }\n" - " tag: '<null>'\n" - " }\n" - " [1]: search::queryeval::MonitoringSearchIterator {\n" - " iteratorName: 'child2'\n" - " iteratorType: 'search::queryeval::SimpleSearch'\n" - " stats: MonitoringSearchIterator::Stats {\n" - " numSeeks: 3\n" - " numDocIdSteps: 5\n" - " avgDocIdSteps: 1.66667\n" - " numHitSkips: 0\n" - " avgHitSkips: 0\n" - " numUnpacks: 1\n" - " numSeeksPerUnpack: 3\n" - " }\n" - " tag: '<null>'\n" - " }\n" - " }\n" - "}\n", - dumper.toString()); + EXPECT_EQ("search::queryeval::MonitoringSearchIterator {\n" + " iteratorName: 'and'\n" + " iteratorType: 'search::queryeval::AndSearchStrict<search::queryeval::(anonymous namespace)::FullUnpack>'\n" + " stats: MonitoringSearchIterator::Stats {\n" + " numSeeks: 2\n" + " numDocIdSteps: 2\n" + " avgDocIdSteps: 1\n" + " numHitSkips: 0\n" + " avgHitSkips: 0\n" + " numUnpacks: 1\n" + " numSeeksPerUnpack: 2\n" + " }\n" + " children: std::vector {\n" + " [0]: search::queryeval::MonitoringSearchIterator {\n" + " iteratorName: 'child1'\n" + " iteratorType: 'search::queryeval::SimpleSearch'\n" + " stats: MonitoringSearchIterator::Stats {\n" + " numSeeks: 3\n" + " numDocIdSteps: 3\n" + " avgDocIdSteps: 1\n" + " numHitSkips: 0\n" + " avgHitSkips: 0\n" + " numUnpacks: 1\n" + " numSeeksPerUnpack: 3\n" + " }\n" + " tag: '<null>'\n" + " }\n" + " [1]: search::queryeval::MonitoringSearchIterator {\n" + " iteratorName: 'child2'\n" + " iteratorType: 'search::queryeval::SimpleSearch'\n" + " stats: MonitoringSearchIterator::Stats {\n" + " numSeeks: 3\n" + " numDocIdSteps: 5\n" + " avgDocIdSteps: 1.66667\n" + " numHitSkips: 0\n" + " avgHitSkips: 0\n" + " numUnpacks: 1\n" + " numSeeksPerUnpack: 3\n" + " }\n" + " tag: '<null>'\n" + " }\n" + " }\n" + "}\n", + dumper.toString()); } class MonitoringSearchIteratorVerifier : public search::test::SearchIteratorVerifier { @@ -331,7 +346,8 @@ public: } }; -TEST("test monitoring search iterator adheres to search iterator requirements") { +TEST(MonitoringSearchIteratorTest, test_monitoring_search_iterator_adheres_to_search_iterator_requirements) +{ MonitoringSearchIteratorVerifier searchVerifier; searchVerifier.verify(); MonitoringDumpIteratorVerifier dumpVerifier; @@ -339,4 +355,4 @@ TEST("test monitoring search iterator adheres to search iterator requirements") } -TEST_MAIN() { TEST_RUN_ALL(); } +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/searchlib/src/tests/queryeval/multibitvectoriterator/multibitvectoriterator_test.cpp b/searchlib/src/tests/queryeval/multibitvectoriterator/multibitvectoriterator_test.cpp index 901d8371bc9..ff8f6415284 100644 --- a/searchlib/src/tests/queryeval/multibitvectoriterator/multibitvectoriterator_test.cpp +++ b/searchlib/src/tests/queryeval/multibitvectoriterator/multibitvectoriterator_test.cpp @@ -1,5 +1,4 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#include <vespa/vespalib/testkit/testapp.h> #include <vespa/searchlib/queryeval/multibitvectoriterator.h> #include <vespa/searchlib/queryeval/emptysearch.h> #include <vespa/searchlib/queryeval/truesearch.h> @@ -9,12 +8,11 @@ #include <vespa/searchlib/queryeval/orsearch.h> #include <vespa/searchlib/fef/termfieldmatchdata.h> #include <vespa/searchlib/fef/termfieldmatchdataarray.h> +#define ENABLE_GTEST_MIGRATION #include <vespa/searchlib/test/searchiteratorverifier.h> +#include <vespa/vespalib/gtest/gtest.h> #include <random> -#include <vespa/log/log.h> -LOG_SETUP("multibitvectoriterator_test"); - using namespace search::queryeval; using namespace search::fef; using namespace search; @@ -74,6 +72,18 @@ Fixture::Fixture() } } +class MultiBitVectorIteratorTest : public ::testing::Test, + protected Fixture +{ +protected: + MultiBitVectorIteratorTest(); + ~MultiBitVectorIteratorTest() override; +}; + +MultiBitVectorIteratorTest::MultiBitVectorIteratorTest() = default; + +MultiBitVectorIteratorTest::~MultiBitVectorIteratorTest() = default; + using H = std::vector<uint32_t>; H @@ -130,68 +140,69 @@ Fixture::testAndWith(bool invert) H firstHits3 = seekNoReset(*s, 1, 130); H lastHits3 = seekNoReset(*s, 130, _bvs[0]->size()); //These constants will change if rnd(341) is changed. - EXPECT_EQUAL(30u, firstHits2.size()); - EXPECT_EQUAL(19u, firstHits3.size()); - EXPECT_EQUAL(1234u, lastHits2F.size()); - ASSERT_EQUAL(lastHits3.size(), lastHits2F.size()); + EXPECT_EQ(30u, firstHits2.size()); + EXPECT_EQ(19u, firstHits3.size()); + EXPECT_EQ(1234u, lastHits2F.size()); + ASSERT_EQ(lastHits3.size(), lastHits2F.size()); for (size_t i(0); i < lastHits3.size(); i++) { - EXPECT_EQUAL(lastHits3[i], lastHits2F[i]); + EXPECT_EQ(lastHits3[i], lastHits2F[i]); } } } -TEST_F("testAndNot", Fixture) +TEST_F(MultiBitVectorIteratorTest, test_and_not) { for (bool invert : {false, true}) { - f.template testOptimizeCommon<AndNotSearch>(false, invert); - f.template testSearch<AndNotSearch>(false, invert); - f.template testSearch<AndNotSearch>(true, invert); + testOptimizeCommon<AndNotSearch>(false, invert); + testSearch<AndNotSearch>(false, invert); + testSearch<AndNotSearch>(true, invert); } } -TEST_F("testAnd", Fixture) +TEST_F(MultiBitVectorIteratorTest, test_and) { for (bool invert : {false, true}) { - f.template testOptimizeCommon<AndSearch>(true, invert); - f.template testOptimizeAndOr<AndSearch>(invert); - f.template testSearch<AndSearch>(false, invert); - f.template testSearch<AndSearch>(true, invert); + testOptimizeCommon<AndSearch>(true, invert); + testOptimizeAndOr<AndSearch>(invert); + testSearch<AndSearch>(false, invert); + testSearch<AndSearch>(true, invert); } } -TEST_F("testOr", Fixture) +TEST_F(MultiBitVectorIteratorTest, test_or) { for (bool invert : {false, true}) { - f.template testOptimizeCommon< OrSearch >(false, invert); - f.template testOptimizeAndOr< OrSearch >(invert); - f.template testSearch<OrSearch>(false, invert); - f.template testSearch<OrSearch>(true, invert); + testOptimizeCommon< OrSearch >(false, invert); + testOptimizeAndOr< OrSearch >(invert); + testSearch<OrSearch>(false, invert); + testSearch<OrSearch>(true, invert); } } -TEST_F("testAndWith", Fixture) { - f.testAndWith(false); - f.testAndWith(true); +TEST_F(MultiBitVectorIteratorTest, test_and_with) +{ + testAndWith(false); + testAndWith(true); } -TEST_F("testBug7163266", Fixture) +TEST_F(MultiBitVectorIteratorTest, test_bug_7163266) { TermFieldMatchData tfmd[30]; - f._bvs[0]->setBit(1); - f._bvs[1]->setBit(1); + _bvs[0]->setBit(1); + _bvs[1]->setBit(1); MultiSearch::Children children; UnpackInfo unpackInfo; for (size_t i(0); i < 28; i++) { children.emplace_back(new TrueSearch(tfmd[2])); unpackInfo.add(i); } - children.push_back(f.createIter(0, false, tfmd[0], false)); - children.push_back(f.createIter(1, false, tfmd[1], false)); + children.push_back(createIter(0, false, tfmd[0], false)); + children.push_back(createIter(1, false, tfmd[1], false)); SearchIterator::UP s = AndSearch::create(std::move(children), false, unpackInfo); const auto * ms = dynamic_cast<const MultiSearch *>(s.get()); EXPECT_TRUE(ms != nullptr); - EXPECT_EQUAL(30u, ms->getChildren().size()); - EXPECT_EQUAL("search::queryeval::AndSearchNoStrict<search::queryeval::(anonymous namespace)::SelectiveUnpack>", s->getClassName()); + EXPECT_EQ(30u, ms->getChildren().size()); + EXPECT_EQ("search::queryeval::AndSearchNoStrict<search::queryeval::(anonymous namespace)::SelectiveUnpack>", s->getClassName()); for (size_t i(0); i < 28; i++) { EXPECT_TRUE(ms->needUnpack(i)); } @@ -200,8 +211,8 @@ TEST_F("testBug7163266", Fixture) s = MultiBitVectorIteratorBase::optimize(std::move(s)); ms = dynamic_cast<const MultiSearch *>(s.get()); EXPECT_TRUE(ms != nullptr); - EXPECT_EQUAL(29u, ms->getChildren().size()); - EXPECT_EQUAL("search::queryeval::AndSearchNoStrict<search::queryeval::(anonymous namespace)::SelectiveUnpack>", s->getClassName()); + EXPECT_EQ(29u, ms->getChildren().size()); + EXPECT_EQ("search::queryeval::AndSearchNoStrict<search::queryeval::(anonymous namespace)::SelectiveUnpack>", s->getClassName()); for (size_t i(0); i < 28; i++) { EXPECT_TRUE(ms->needUnpack(i)); } @@ -212,15 +223,15 @@ void verifySelectiveUnpack(SearchIterator & s, const TermFieldMatchData * tfmd) { s.seek(1); - EXPECT_EQUAL(0u, tfmd[0].getDocId()); - EXPECT_EQUAL(0u, tfmd[1].getDocId()); - EXPECT_EQUAL(0u, tfmd[2].getDocId()); - EXPECT_EQUAL(0u, tfmd[3].getDocId()); + EXPECT_EQ(0u, tfmd[0].getDocId()); + EXPECT_EQ(0u, tfmd[1].getDocId()); + EXPECT_EQ(0u, tfmd[2].getDocId()); + EXPECT_EQ(0u, tfmd[3].getDocId()); s.unpack(1); - EXPECT_EQUAL(0u, tfmd[0].getDocId()); - EXPECT_EQUAL(1u, tfmd[1].getDocId()); - EXPECT_EQUAL(1u, tfmd[2].getDocId()); - EXPECT_EQUAL(0u, tfmd[3].getDocId()); + EXPECT_EQ(0u, tfmd[0].getDocId()); + EXPECT_EQ(1u, tfmd[1].getDocId()); + EXPECT_EQ(1u, tfmd[2].getDocId()); + EXPECT_EQ(0u, tfmd[3].getDocId()); } template<typename T> @@ -243,7 +254,7 @@ Fixture::testThatOptimizePreservesUnpack() s->initFullRange(); const auto * ms = dynamic_cast<const MultiSearch *>(s.get()); EXPECT_TRUE(ms != nullptr); - EXPECT_EQUAL(4u, ms->getChildren().size()); + EXPECT_EQ(4u, ms->getChildren().size()); verifySelectiveUnpack(*s, tfmd); tfmd[1].resetOnlyDocId(0); tfmd[2].resetOnlyDocId(0); @@ -251,7 +262,7 @@ Fixture::testThatOptimizePreservesUnpack() s->initFullRange(); ms = dynamic_cast<const MultiSearch *>(s.get()); EXPECT_TRUE(ms != nullptr); - EXPECT_EQUAL(2u, ms->getChildren().size()); + EXPECT_EQ(2u, ms->getChildren().size()); verifySelectiveUnpack(*s, tfmd); fixup_bitvectors(); } @@ -260,26 +271,27 @@ void verifyOrUnpack(SearchIterator & s, TermFieldMatchData tfmd[3]) { s.initFullRange(); s.seek(1); for (size_t i = 0; i < 3; i++) { - EXPECT_EQUAL(0u, tfmd[i].getDocId()); + EXPECT_EQ(0u, tfmd[i].getDocId()); } s.unpack(1); - EXPECT_EQUAL(0u, tfmd[0].getDocId()); - EXPECT_EQUAL(1u, tfmd[1].getDocId()); - EXPECT_EQUAL(0u, tfmd[2].getDocId()); + EXPECT_EQ(0u, tfmd[0].getDocId()); + EXPECT_EQ(1u, tfmd[1].getDocId()); + EXPECT_EQ(0u, tfmd[2].getDocId()); } -TEST_F("testUnpackOfOr", Fixture) { - f._bvs[0]->clearBit(1); - f._bvs[1]->setBit(1); - f._bvs[2]->clearBit(1); +TEST_F(MultiBitVectorIteratorTest, test_unpack_of_Or) +{ + _bvs[0]->clearBit(1); + _bvs[1]->setBit(1); + _bvs[2]->clearBit(1); UnpackInfo all; all.forceAll(); - f.verifyUnpackOfOr(all); + verifyUnpackOfOr(all); UnpackInfo unpackInfo; unpackInfo.add(1); unpackInfo.add(2); - f.verifyUnpackOfOr(unpackInfo); + verifyUnpackOfOr(unpackInfo); } void @@ -299,13 +311,13 @@ Fixture::verifyUnpackOfOr(const UnpackInfo &unpackInfo) const auto * ms = dynamic_cast<const MultiSearch *>(s.get()); EXPECT_TRUE(ms != nullptr); - EXPECT_EQUAL(3u, ms->getChildren().size()); + EXPECT_EQ(3u, ms->getChildren().size()); s = MultiBitVectorIteratorBase::optimize(std::move(s)); s->initFullRange(); ms = dynamic_cast<const MultiBitVectorIteratorBase *>(s.get()); EXPECT_TRUE(ms != nullptr); - EXPECT_EQUAL(3u, ms->getChildren().size()); + EXPECT_EQ(3u, ms->getChildren().size()); verifyOrUnpack(*s, tfmdA); } @@ -319,9 +331,9 @@ searchAndCompare(SearchIterator::UP s, uint32_t docIdLimit) if (s.get() != p) { H b = seek(*s, docIdLimit); EXPECT_FALSE(a.empty()); - EXPECT_EQUAL(a.size(), b.size()); + EXPECT_EQ(a.size(), b.size()); for (size_t i(0); i < a.size(); i++) { - EXPECT_EQUAL(a[i], b[i]); + EXPECT_EQ(a[i], b[i]); } } } @@ -369,7 +381,7 @@ Fixture::testOptimizeCommon(bool isAnd, bool invert) s = MultiBitVectorIteratorBase::optimize(std::move(s)); EXPECT_TRUE(dynamic_cast<const T *>(s.get()) != nullptr); const auto & m(dynamic_cast<const MultiSearch &>(*s)); - EXPECT_EQUAL(1u, m.getChildren().size()); + EXPECT_EQ(1u, m.getChildren().size()); EXPECT_TRUE(dynamic_cast<const BitVectorIterator *>(m.getChildren()[0].get()) != nullptr); } { @@ -381,7 +393,7 @@ Fixture::testOptimizeCommon(bool isAnd, bool invert) s = MultiBitVectorIteratorBase::optimize(std::move(s)); EXPECT_TRUE(dynamic_cast<const T *>(s.get()) != nullptr); const auto & m(dynamic_cast<const MultiSearch &>(*s)); - EXPECT_EQUAL(2u, m.getChildren().size()); + EXPECT_EQ(2u, m.getChildren().size()); EXPECT_TRUE(dynamic_cast<const BitVectorIterator *>(m.getChildren()[0].get()) != nullptr); EXPECT_TRUE(dynamic_cast<const EmptySearch *>(m.getChildren()[1].get()) != nullptr); } @@ -394,7 +406,7 @@ Fixture::testOptimizeCommon(bool isAnd, bool invert) s = MultiBitVectorIteratorBase::optimize(std::move(s)); EXPECT_TRUE(dynamic_cast<const T *>(s.get()) != nullptr); const auto & m(dynamic_cast<const MultiSearch &>(*s)); - EXPECT_EQUAL(2u, m.getChildren().size()); + EXPECT_EQ(2u, m.getChildren().size()); EXPECT_TRUE(dynamic_cast<const EmptySearch *>(m.getChildren()[0].get()) != nullptr); EXPECT_TRUE(dynamic_cast<const BitVectorIterator *>(m.getChildren()[1].get()) != nullptr); } @@ -409,7 +421,7 @@ Fixture::testOptimizeCommon(bool isAnd, bool invert) EXPECT_TRUE(s); EXPECT_TRUE(dynamic_cast<const T *>(s.get()) != nullptr); const auto & m(dynamic_cast<const MultiSearch &>(*s)); - EXPECT_EQUAL(2u, m.getChildren().size()); + EXPECT_EQ(2u, m.getChildren().size()); EXPECT_TRUE(dynamic_cast<const EmptySearch *>(m.getChildren()[0].get()) != nullptr); EXPECT_TRUE(dynamic_cast<const MultiBitVectorIteratorBase *>(m.getChildren()[1].get()) != nullptr); EXPECT_TRUE(Trinary::False == m.getChildren()[1]->is_strict()); @@ -425,7 +437,7 @@ Fixture::testOptimizeCommon(bool isAnd, bool invert) EXPECT_TRUE(s); EXPECT_TRUE(dynamic_cast<const T *>(s.get()) != nullptr); const auto & m(dynamic_cast<const MultiSearch &>(*s)); - EXPECT_EQUAL(2u, m.getChildren().size()); + EXPECT_EQ(2u, m.getChildren().size()); EXPECT_TRUE(dynamic_cast<const EmptySearch *>(m.getChildren()[0].get()) != nullptr); EXPECT_TRUE(dynamic_cast<const MultiBitVectorIteratorBase *>(m.getChildren()[1].get()) != nullptr); EXPECT_TRUE(Trinary::True == m.getChildren()[1]->is_strict()); @@ -488,7 +500,7 @@ Fixture::testOptimizeAndOr(bool invert) EXPECT_TRUE(s); EXPECT_TRUE(dynamic_cast<const T *>(s.get()) != nullptr); const auto & m(dynamic_cast<const MultiSearch &>(*s)); - EXPECT_EQUAL(2u, m.getChildren().size()); + EXPECT_EQ(2u, m.getChildren().size()); EXPECT_TRUE(dynamic_cast<const MultiBitVectorIteratorBase *>(m.getChildren()[0].get()) != nullptr); EXPECT_TRUE(Trinary::False == m.getChildren()[0]->is_strict()); EXPECT_TRUE(dynamic_cast<const EmptySearch *>(m.getChildren()[1].get()) != nullptr); @@ -504,7 +516,7 @@ Fixture::testOptimizeAndOr(bool invert) EXPECT_TRUE(s); EXPECT_TRUE(dynamic_cast<const T *>(s.get()) != nullptr); const auto & m(dynamic_cast<const MultiSearch &>(*s)); - EXPECT_EQUAL(2u, m.getChildren().size()); + EXPECT_EQ(2u, m.getChildren().size()); EXPECT_TRUE(dynamic_cast<const MultiBitVectorIteratorBase *>(m.getChildren()[0].get()) != nullptr); EXPECT_TRUE(Trinary::False == m.getChildren()[0]->is_strict()); EXPECT_TRUE(dynamic_cast<const EmptySearch *>(m.getChildren()[1].get()) != nullptr); @@ -520,7 +532,7 @@ Fixture::testOptimizeAndOr(bool invert) EXPECT_TRUE(s); EXPECT_TRUE(dynamic_cast<const T *>(s.get()) != nullptr); const auto & m(dynamic_cast<const MultiSearch &>(*s)); - EXPECT_EQUAL(2u, m.getChildren().size()); + EXPECT_EQ(2u, m.getChildren().size()); EXPECT_TRUE(dynamic_cast<const MultiBitVectorIteratorBase *>(m.getChildren()[0].get()) != nullptr); EXPECT_TRUE(Trinary::True == m.getChildren()[0]->is_strict()); EXPECT_TRUE(dynamic_cast<const EmptySearch *>(m.getChildren()[1].get()) != nullptr); @@ -536,7 +548,7 @@ Fixture::testOptimizeAndOr(bool invert) EXPECT_TRUE(s); EXPECT_TRUE(dynamic_cast<const T *>(s.get()) != nullptr); const auto & m(dynamic_cast<const MultiSearch &>(*s)); - EXPECT_EQUAL(2u, m.getChildren().size()); + EXPECT_EQ(2u, m.getChildren().size()); EXPECT_TRUE(dynamic_cast<const MultiBitVectorIteratorBase *>(m.getChildren()[0].get()) != nullptr); EXPECT_TRUE(Trinary::True == m.getChildren()[0]->is_strict()); EXPECT_TRUE(dynamic_cast<const EmptySearch *>(m.getChildren()[1].get()) != nullptr); @@ -563,14 +575,16 @@ Fixture::testEndGuard(bool invert) EXPECT_FALSE(m.seek(_bvs[0]->size()+987)); } -TEST_F("testEndGuard", Fixture) { - f.testEndGuard(false); - f.testEndGuard(true); +TEST_F(MultiBitVectorIteratorTest, test_end_guard) +{ + testEndGuard(false); + testEndGuard(true); } -TEST_F("testThatOptimizePreservesUnpack", Fixture) { - f.template testThatOptimizePreservesUnpack<OrSearch>(); - f.template testThatOptimizePreservesUnpack<AndSearch>(); +TEST_F(MultiBitVectorIteratorTest, test_that_optimize_preserves_unpack) +{ + testThatOptimizePreservesUnpack<OrSearch>(); + testThatOptimizePreservesUnpack<AndSearch>(); } SearchIterator::UP @@ -595,7 +609,7 @@ countUntilEnd(SearchIterator & s) { for (uint32_t docId = s.seekFirst(1); !s.isAtEnd(); docId = s.seekNext(docId+1)) { seekCount++; } - EXPECT_EQUAL(2459u, seekCount); + EXPECT_EQ(2459u, seekCount); } void @@ -604,19 +618,20 @@ countUntilDocId(SearchIterator & s) { for (uint32_t docId = s.seekFirst(1), endId = s.getEndId(); docId < endId; docId = s.seekNext(docId+1)) { seekCount++; } - EXPECT_EQUAL(2459u, seekCount); + EXPECT_EQ(2459u, seekCount); } -TEST_F("test that short vectors don't spin at end", Fixture) { +TEST_F(MultiBitVectorIteratorTest, test_that_short_vectors_dont_spin_at_end) +{ TermFieldMatchData tfmd; - countUntilEnd(*createDual(f, tfmd, f._bvs[0]->size())); - countUntilDocId(*createDual(f, tfmd, f._bvs[0]->size())); + countUntilEnd(*createDual(*this, tfmd, _bvs[0]->size())); + countUntilDocId(*createDual(*this, tfmd, _bvs[0]->size())); - countUntilDocId(*createDual(f, tfmd, f._bvs[0]->size() + 1)); - countUntilEnd(*createDual(f, tfmd, f._bvs[0]->size() + 1)); + countUntilDocId(*createDual(*this, tfmd, _bvs[0]->size() + 1)); + countUntilEnd(*createDual(*this, tfmd, _bvs[0]->size() + 1)); - countUntilDocId(*createDual(f, tfmd, -1)); - countUntilEnd(*createDual(f, tfmd, -1)); + countUntilDocId(*createDual(*this, tfmd, -1)); + countUntilEnd(*createDual(*this, tfmd, -1)); } class Verifier : public search::test::SearchIteratorVerifier { @@ -660,11 +675,12 @@ Verifier::create(bool strict) const { SearchIterator::UP iter(_is_and ? AndSearch::create(std::move(bvs), strict) : OrSearch::create(std::move(bvs), strict)); auto mbvit = MultiBitVectorIteratorBase::optimize(std::move(iter)); EXPECT_TRUE((_bvs.size() < 2) || (dynamic_cast<const MultiBitVectorIteratorBase *>(mbvit.get()) != nullptr)); - EXPECT_EQUAL(strict, Trinary::True == mbvit->is_strict()); + EXPECT_EQ(strict, Trinary::True == mbvit->is_strict()); return mbvit; } -TEST("testIteratorConformance") { +TEST_F(MultiBitVectorIteratorTest, test_iterator_conformance) +{ for (bool is_and : {false, true}) { for (size_t i(1); i < 6; i++) { Verifier searchIteratorVerifier(i, is_and); @@ -673,4 +689,4 @@ TEST("testIteratorConformance") { } } -TEST_MAIN() { TEST_RUN_ALL(); } +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/searchlib/src/tests/queryeval/sourceblender/sourceblender_test.cpp b/searchlib/src/tests/queryeval/sourceblender/sourceblender_test.cpp index bb2e559106f..a266902445b 100644 --- a/searchlib/src/tests/queryeval/sourceblender/sourceblender_test.cpp +++ b/searchlib/src/tests/queryeval/sourceblender/sourceblender_test.cpp @@ -1,15 +1,16 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#include <vespa/vespalib/testkit/testapp.h> #include <vespa/searchlib/queryeval/sourceblendersearch.h> #include <vespa/searchlib/queryeval/simplesearch.h> #include <vespa/searchlib/queryeval/simpleresult.h> #include <vespa/searchlib/queryeval/intermediate_blueprints.h> #include <vespa/searchlib/queryeval/leaf_blueprints.h> +#define ENABLE_GTEST_MIGRATION #include <vespa/searchlib/test/searchiteratorverifier.h> #include <vespa/searchlib/common/bitvectoriterator.h> #include <vespa/searchlib/attribute/fixedsourceselector.h> #include <vespa/searchlib/fef/matchdata.h> +#include <vespa/vespalib/gtest/gtest.h> using namespace search::queryeval; using namespace search::fef; @@ -52,7 +53,8 @@ public: //----------------------------------------------------------------------------- -TEST("test strictness") { +TEST(SourceBlenderTest, test_strictness) +{ MatchData::UP md(MatchData::makeTestInstance(100, 10)); for (uint32_t i = 0; i < 2; ++i) { bool strict = (i == 0); @@ -81,23 +83,24 @@ TEST("test strictness") { EXPECT_TRUE(!blend.seek(1u)); if (strict) { - EXPECT_EQUAL(2u, blend.getDocId()); + EXPECT_EQ(2u, blend.getDocId()); } else { - EXPECT_EQUAL(blend.beginId(), blend.getDocId()); + EXPECT_EQ(blend.beginId(), blend.getDocId()); } EXPECT_TRUE(blend.seek(5)); - EXPECT_EQUAL(5u, blend.getDocId()); + EXPECT_EQ(5u, blend.getDocId()); EXPECT_TRUE(!blend.seek(6)); if (strict) { EXPECT_TRUE(blend.isAtEnd()); } else { - EXPECT_EQUAL(5u, blend.getDocId()); + EXPECT_EQ(5u, blend.getDocId()); } delete sel; } } -TEST("test full sourceblender search") { +TEST(SourceBlenderTest, test_full_sourceblender_search) +{ SimpleResult a; SimpleResult b; SimpleResult c; @@ -134,10 +137,10 @@ TEST("test full sourceblender search") { SimpleResult expect_unpacked_c; expect_unpacked_c.addHit(21); - EXPECT_EQUAL(expect_result, result); - EXPECT_EQUAL(expect_unpacked_a, ua->getUnpacked()); - EXPECT_EQUAL(expect_unpacked_b, ub->getUnpacked()); - EXPECT_EQUAL(expect_unpacked_c, uc->getUnpacked()); + EXPECT_EQ(expect_result, result); + EXPECT_EQ(expect_unpacked_a, ua->getUnpacked()); + EXPECT_EQ(expect_unpacked_b, ub->getUnpacked()); + EXPECT_EQ(expect_unpacked_c, uc->getUnpacked()); } using search::test::SearchIteratorVerifier; @@ -176,9 +179,10 @@ Verifier::Verifier() : } Verifier::~Verifier() {} -TEST("Test that source blender iterator adheres to SearchIterator requirements") { +TEST(SourceBlenderTest, test_that_source_blender_iterator_adheres_to_search_terator_requirements) +{ Verifier searchIteratorVerifier; searchIteratorVerifier.verify(); } -TEST_MAIN() { TEST_RUN_ALL(); } +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/searchlib/src/vespa/searchlib/fef/test/featuretest.cpp b/searchlib/src/vespa/searchlib/fef/test/featuretest.cpp index 5313fcc3eb4..b83293c6ad8 100644 --- a/searchlib/src/vespa/searchlib/fef/test/featuretest.cpp +++ b/searchlib/src/vespa/searchlib/fef/test/featuretest.cpp @@ -3,7 +3,7 @@ #include "featuretest.h" #include <vespa/searchlib/fef/utils.h> #include <vespa/searchlib/fef/blueprint.h> -#include <vespa/vespalib/testkit/test_kit.h> +#include <sstream> #include <vespa/log/log.h> LOG_SETUP(".fef.featuretest"); diff --git a/searchlib/src/vespa/searchlib/parsequery/stackdumpiterator.h b/searchlib/src/vespa/searchlib/parsequery/stackdumpiterator.h index 0f80661bf38..d15e1ca0512 100644 --- a/searchlib/src/vespa/searchlib/parsequery/stackdumpiterator.h +++ b/searchlib/src/vespa/searchlib/parsequery/stackdumpiterator.h @@ -77,7 +77,7 @@ public: ~SimpleQueryStackDumpIterator(); vespalib::stringref getStack() const noexcept { return vespalib::stringref(_buf, _bufEnd - _buf); } - size_t getPosition() const { return _currPos; } + size_t getPosition() const noexcept { return _currPos; } /** * Moves to the next item in the buffer. @@ -91,7 +91,7 @@ public: * Get the type of the current item. * @return the type. */ - ParseItem::ItemType getType() const { return _currType; } + ParseItem::ItemType getType() const noexcept { return _currType; } /** * Get the type of the current item. * @return the type. @@ -103,40 +103,40 @@ public: * * @return rank weight. **/ - query::Weight GetWeight() const { return _currWeight; } + query::Weight GetWeight() const noexcept { return _currWeight; } /** * Get the unique id of the current item. * * @return unique id of current item **/ - uint32_t getUniqueId() const { return _currUniqueId; } + uint32_t getUniqueId() const noexcept { return _currUniqueId; } // Get the flags of the current item. - bool hasNoRankFlag() const { return (_currFlags & ParseItem::IFLAG_NORANK) != 0; } - bool hasSpecialTokenFlag() const { return (_currFlags & ParseItem::IFLAG_SPECIALTOKEN) != 0; } - bool hasNoPositionDataFlag() const { return (_currFlags & ParseItem::IFLAG_NOPOSITIONDATA) != 0; } + bool hasNoRankFlag() const noexcept { return (_currFlags & ParseItem::IFLAG_NORANK) != 0; } + bool hasSpecialTokenFlag() const noexcept { return (_currFlags & ParseItem::IFLAG_SPECIALTOKEN) != 0; } + bool hasNoPositionDataFlag() const noexcept { return (_currFlags & ParseItem::IFLAG_NOPOSITIONDATA) != 0; } - uint32_t getArity() const { return _currArity; } + uint32_t getArity() const noexcept { return _currArity; } - uint32_t getNearDistance() const { return _extraIntArg1; } - uint32_t getTargetHits() const { return _extraIntArg1; } - double getDistanceThreshold() const { return _extraDoubleArg4; } - double getScoreThreshold() const { return _extraDoubleArg4; } - double getThresholdBoostFactor() const { return _extraDoubleArg5; } - bool getAllowApproximate() const { return (_extraIntArg2 != 0); } - uint32_t getExploreAdditionalHits() const { return _extraIntArg3; } + uint32_t getNearDistance() const noexcept { return _extraIntArg1; } + uint32_t getTargetHits() const noexcept { return _extraIntArg1; } + double getDistanceThreshold() const noexcept { return _extraDoubleArg4; } + double getScoreThreshold() const noexcept { return _extraDoubleArg4; } + double getThresholdBoostFactor() const noexcept { return _extraDoubleArg5; } + bool getAllowApproximate() const noexcept { return (_extraIntArg2 != 0); } + uint32_t getExploreAdditionalHits() const noexcept { return _extraIntArg3; } // fuzzy match arguments - uint32_t getFuzzyMaxEditDistance() const { return _extraIntArg1; } - uint32_t getFuzzyPrefixLength() const { return _extraIntArg2; } + uint32_t getFuzzyMaxEditDistance() const noexcept { return _extraIntArg1; } + uint32_t getFuzzyPrefixLength() const noexcept { return _extraIntArg2; } std::unique_ptr<query::PredicateQueryTerm> getPredicateQueryTerm(); std::unique_ptr<query::TermVector> get_terms(); - vespalib::stringref getIndexName() const { return _curr_index_name; } - vespalib::stringref getTerm() const { return _curr_term; } - int64_t getIntergerTerm() const { return _curr_integer_term; } + vespalib::stringref getIndexName() const noexcept { return _curr_index_name; } + vespalib::stringref getTerm() const noexcept { return _curr_term; } + int64_t getIntergerTerm() const noexcept { return _curr_integer_term; } static vespalib::stringref DEFAULT_INDEX; }; diff --git a/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp b/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp index dd3b1f84ad9..16406bffd3d 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp +++ b/searchlib/src/vespa/searchlib/query/streaming/querynode.cpp @@ -137,6 +137,7 @@ QueryNode::Build(const QueryNode * parent, const QueryNodeResultFactory & factor } qt->setWeight(queryRep.GetWeight()); qt->setUniqueId(queryRep.getUniqueId()); + qt->setRanked( ! queryRep.hasNoRankFlag()); if (allowRewrite && possibleFloat(*qt, ssTerm) && factory.allow_float_terms_rewrite(ssIndex)) { auto phrase = std::make_unique<PhraseQueryNode>(factory.create(), ssIndex, arity); auto dotPos = ssTerm.find('.'); diff --git a/searchlib/src/vespa/searchlib/query/streaming/queryterm.cpp b/searchlib/src/vespa/searchlib/query/streaming/queryterm.cpp index 0d0f5a7c4ad..a9516d8aee4 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/queryterm.cpp +++ b/searchlib/src/vespa/searchlib/query/streaming/queryterm.cpp @@ -69,10 +69,11 @@ QueryTerm::visitMembers(vespalib::ObjectVisitor & visitor) const QueryTerm::QueryTerm(std::unique_ptr<QueryNodeResultBase> org, stringref termS, const string & indexS, Type type, Normalizing normalizing) : QueryTermUCS4(QueryNormalization::optional_fold(termS, type, normalizing), type), + _hitList(), _index(indexS), - _encoding(0x01), _result(org.release()), - _hitList(), + _encoding(0x01), + _isRanked(true), _weight(100), _uniqueId(0), _fieldInfo() diff --git a/searchlib/src/vespa/searchlib/query/streaming/queryterm.h b/searchlib/src/vespa/searchlib/query/streaming/queryterm.h index 2cb4f2d2ebb..1d0454f3b63 100644 --- a/searchlib/src/vespa/searchlib/query/streaming/queryterm.h +++ b/searchlib/src/vespa/searchlib/query/streaming/queryterm.h @@ -83,6 +83,8 @@ public: size_t termLen() const { return getTermLen(); } const string & index() const { return _index; } void setWeight(query::Weight v) { _weight = v; } + void setRanked(bool ranked) { _isRanked = ranked; } + bool isRanked() const { return _isRanked; } void setUniqueId(uint32_t u) { _uniqueId = u; } query::Weight weight() const { return _weight; } uint32_t uniqueId() const { return _uniqueId; } @@ -108,11 +110,12 @@ protected: template <typename HitListType> static void unpack_match_data_helper(uint32_t docid, const fef::ITermData& td, fef::MatchData& match_data, const HitListType& hit_list, const QueryTerm& fl_term); using QueryNodeResultBaseContainer = std::unique_ptr<QueryNodeResultBase>; - string _index; - EncodingBitMap _encoding; - QueryNodeResultBaseContainer _result; HitList _hitList; private: + string _index; + QueryNodeResultBaseContainer _result; + EncodingBitMap _encoding; + bool _isRanked; query::Weight _weight; uint32_t _uniqueId; std::vector<FieldInfo> _fieldInfo; diff --git a/searchlib/src/vespa/searchlib/query/tree/term.h b/searchlib/src/vespa/searchlib/query/tree/term.h index bcecaa37870..2f57c3cb06d 100644 --- a/searchlib/src/vespa/searchlib/query/tree/term.h +++ b/searchlib/src/vespa/searchlib/query/tree/term.h @@ -23,16 +23,16 @@ public: virtual ~Term() = 0; void setView(const vespalib::string & view) { _view = view; } - void setRanked(bool ranked) { _ranked = ranked; } - void setPositionData(bool position_data) { _position_data = position_data; } + void setRanked(bool ranked) noexcept { _ranked = ranked; } + void setPositionData(bool position_data) noexcept { _position_data = position_data; } void setStateFrom(const Term& other); - const vespalib::string & getView() const { return _view; } - Weight getWeight() const { return _weight; } - int32_t getId() const { return _id; } - bool isRanked() const { return _ranked; } - bool usePositionData() const { return _position_data; } + const vespalib::string & getView() const noexcept { return _view; } + Weight getWeight() const noexcept { return _weight; } + int32_t getId() const noexcept { return _id; } + bool isRanked() const noexcept { return _ranked; } + bool usePositionData() const noexcept { return _position_data; } static bool isPossibleRangeTerm(vespalib::stringref term) noexcept { return (term[0] == '[' || term[0] == '<' || term[0] == '>'); diff --git a/searchlib/src/vespa/searchlib/queryeval/blueprint.h b/searchlib/src/vespa/searchlib/queryeval/blueprint.h index 395512d84cc..c24790ddcf1 100644 --- a/searchlib/src/vespa/searchlib/queryeval/blueprint.h +++ b/searchlib/src/vespa/searchlib/queryeval/blueprint.h @@ -362,7 +362,7 @@ private: bool infer_want_global_filter() const; size_t count_termwise_nodes(const UnpackInfo &unpack) const; - virtual FlowCalc make_flow_calc(bool strict, double flow) const; + virtual FlowCalc make_flow_calc(bool strict, double flow) const = 0; protected: // returns an empty collection if children have empty or diff --git a/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp b/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp index 6faa4ddf147..b8bf7d40655 100644 --- a/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp @@ -206,6 +206,13 @@ AndNotBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) co return create_andnot_filter(get_children(), strict, constraint); } + +FlowCalc +AndNotBlueprint::make_flow_calc(bool strict, double flow) const +{ + return flow_calc<AndNotFlow>(strict, flow); +} + //----------------------------------------------------------------------------- FlowStats @@ -417,6 +424,13 @@ OrBlueprint::calculate_cost_tier() const } //----------------------------------------------------------------------------- + +FlowCalc +WeakAndBlueprint::make_flow_calc(bool strict, double flow) const +{ + return flow_calc<OrFlow>(strict, flow); +} + WeakAndBlueprint::~WeakAndBlueprint() = default; FlowStats @@ -488,6 +502,12 @@ WeakAndBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) c //----------------------------------------------------------------------------- +FlowCalc +NearBlueprint::make_flow_calc(bool strict, double flow) const +{ + return flow_calc<AndFlow>(strict, flow); +} + FlowStats NearBlueprint::calculate_flow_stats(uint32_t) const { double est = AndFlow::estimate_of(get_children()); @@ -553,6 +573,12 @@ NearBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) cons //----------------------------------------------------------------------------- +FlowCalc +ONearBlueprint::make_flow_calc(bool strict, double flow) const +{ + return flow_calc<AndFlow>(strict, flow); +} + FlowStats ONearBlueprint::calculate_flow_stats(uint32_t) const { double est = AndFlow::estimate_of(get_children()); @@ -708,8 +734,20 @@ RankBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) cons return create_first_child_filter(get_children(), strict, constraint); } +FlowCalc +RankBlueprint::make_flow_calc(bool strict, double flow) const +{ + return first_flow_calc(strict, flow); +} + //----------------------------------------------------------------------------- +FlowCalc +SourceBlenderBlueprint::make_flow_calc(bool strict, double flow) const +{ + return full_flow_calc(strict, flow); +} + SourceBlenderBlueprint::SourceBlenderBlueprint(const ISourceSelector &selector) noexcept : _selector(selector) { diff --git a/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.h b/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.h index 25586022535..0095095dfe8 100644 --- a/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.h +++ b/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.h @@ -29,6 +29,7 @@ public: SearchIterator::UP createFilterSearch(bool strict, FilterConstraint constraint) const override; private: + FlowCalc make_flow_calc(bool strict, double flow) const override; uint8_t calculate_cost_tier() const override { return (childCnt() > 0) ? get_children()[0]->getState().cost_tier() : State::COST_TIER_NORMAL; } @@ -56,7 +57,7 @@ public: SearchIterator::UP createFilterSearch(bool strict, FilterConstraint constraint) const override; private: - virtual FlowCalc make_flow_calc(bool strict, double flow) const override; + FlowCalc make_flow_calc(bool strict, double flow) const override; }; //----------------------------------------------------------------------------- @@ -93,6 +94,7 @@ private: uint32_t _n; std::vector<uint32_t> _weights; + FlowCalc make_flow_calc(bool strict, double flow) const override; public: FlowStats calculate_flow_stats(uint32_t docid_limit) const final; HitEstimate combine(const std::vector<HitEstimate> &data) const override; @@ -123,6 +125,7 @@ class NearBlueprint : public IntermediateBlueprint private: uint32_t _window; + FlowCalc make_flow_calc(bool strict, double flow) const override; public: FlowStats calculate_flow_stats(uint32_t docid_limit) const final; HitEstimate combine(const std::vector<HitEstimate> &data) const override; @@ -145,6 +148,7 @@ class ONearBlueprint : public IntermediateBlueprint private: uint32_t _window; + FlowCalc make_flow_calc(bool strict, double flow) const override; public: FlowStats calculate_flow_stats(uint32_t docid_limit) const final; HitEstimate combine(const std::vector<HitEstimate> &data) const override; @@ -181,6 +185,8 @@ public: uint8_t calculate_cost_tier() const override { return (childCnt() > 0) ? get_children()[0]->getState().cost_tier() : State::COST_TIER_NORMAL; } +private: + FlowCalc make_flow_calc(bool strict, double flow) const override; }; //----------------------------------------------------------------------------- @@ -190,6 +196,7 @@ class SourceBlenderBlueprint final : public IntermediateBlueprint private: const ISourceSelector &_selector; + FlowCalc make_flow_calc(bool strict, double flow) const override; public: explicit SourceBlenderBlueprint(const ISourceSelector &selector) noexcept; ~SourceBlenderBlueprint() override; diff --git a/searchlib/src/vespa/searchlib/test/CMakeLists.txt b/searchlib/src/vespa/searchlib/test/CMakeLists.txt index a4db57a44cd..c43f4eb0cef 100644 --- a/searchlib/src/vespa/searchlib/test/CMakeLists.txt +++ b/searchlib/src/vespa/searchlib/test/CMakeLists.txt @@ -27,6 +27,7 @@ vespa_add_library(searchlib_test vespa_add_library(searchlib_test_gtest_migration OBJECT SOURCES + ft_test_app_base.cpp initrange.cpp searchiteratorverifier.cpp ) diff --git a/searchlib/src/vespa/searchlib/test/ft_test_app_base.cpp b/searchlib/src/vespa/searchlib/test/ft_test_app_base.cpp index eee5631dcc5..1b60ca2cd33 100644 --- a/searchlib/src/vespa/searchlib/test/ft_test_app_base.cpp +++ b/searchlib/src/vespa/searchlib/test/ft_test_app_base.cpp @@ -1,12 +1,16 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#include "ft_test_app.h" +#include "ft_test_app_base.h" #include <vespa/searchlib/fef/test/dummy_dependency_handler.h> #include <vespa/vespalib/util/stringfmt.h> #include <vespa/log/log.h> LOG_SETUP(".ft_test_app_base"); +#ifdef ENABLE_GTEST_MIGRATION +#define EXPECT_EQUAL EXPECT_EQ +#endif + namespace fieldmatch = search::features::fieldmatch; using search::fef::test::DummyDependencyHandler; using search::fef::FieldInfo; diff --git a/searchlib/src/vespa/searchlib/test/ft_test_app_base.h b/searchlib/src/vespa/searchlib/test/ft_test_app_base.h index 329d93e4c47..f4fc1c11b76 100644 --- a/searchlib/src/vespa/searchlib/test/ft_test_app_base.h +++ b/searchlib/src/vespa/searchlib/test/ft_test_app_base.h @@ -4,7 +4,15 @@ #include <vespa/searchlib/features/fieldmatch/params.h> #include <vespa/searchlib/fef/test/ftlib.h> +#ifdef ENABLE_GTEST_MIGRATION +#include <vespa/vespalib/gtest/gtest.h> +#else #include <vespa/vespalib/testkit/test_macros.h> +#endif + +#ifdef ENABLE_GTEST_MIGRATION +#define FtTestAppBase FtTestAppBaseForGTest +#endif /* * Base class for test application used by feature unit tests. @@ -54,8 +62,20 @@ struct FtTestAppBase { template <typename T> static bool assertCreateInstance(const T & prototype, const vespalib::string & baseName) { search::fef::Blueprint::UP bp = prototype.createInstance(); +#ifdef ENABLE_GTEST_MIGRATION + bool failed = false; + EXPECT_TRUE(dynamic_cast<T*>(bp.get()) != NULL) << (failed = true, ""); + if (failed) { + return false; + } + EXPECT_EQ(bp->getBaseName(), baseName) << (failed = true, ""); + if (failed) { + return false; + } +#else if (!EXPECT_TRUE(dynamic_cast<T*>(bp.get()) != NULL)) return false; if (!EXPECT_EQUAL(bp->getBaseName(), baseName)) return false; +#endif return true; } }; diff --git a/streamingvisitors/src/vespa/searchvisitor/queryenvironment.h b/streamingvisitors/src/vespa/searchvisitor/queryenvironment.h index efd5c93d267..734394c86ad 100644 --- a/streamingvisitors/src/vespa/searchvisitor/queryenvironment.h +++ b/streamingvisitors/src/vespa/searchvisitor/queryenvironment.h @@ -30,36 +30,24 @@ public: QueryEnvironment(const vespalib::string & location, const IndexEnvironment & indexEnv, const search::fef::Properties & properties, - const search::IAttributeManager * attrMgr = nullptr); - ~QueryEnvironment(); + const search::IAttributeManager * attrMgr); + ~QueryEnvironment() override; void addGeoLocation(const vespalib::string &field, const vespalib::string &location); + const search::fef::Properties & getProperties() const override { return _properties; } + uint32_t getNumTerms() const override { return _queryTerms.size(); } - // inherit documentation - virtual const search::fef::Properties & getProperties() const override { return _properties; } - - // inherit documentation - virtual uint32_t getNumTerms() const override { return _queryTerms.size(); } - - // inherit documentation - virtual const search::fef::ITermData *getTerm(uint32_t idx) const override { + const search::fef::ITermData *getTerm(uint32_t idx) const override { if (idx >= _queryTerms.size()) { return nullptr; } return _queryTerms[idx]; } - // inherit documentation GeoLocationSpecPtrs getAllLocations() const override; - - // inherit documentation - virtual const search::attribute::IAttributeContext & getAttributeContext() const override { return *_attrCtx; } - + const search::attribute::IAttributeContext & getAttributeContext() const override { return *_attrCtx; } double get_average_field_length(const vespalib::string &) const override { return 100.0; } - - // inherit documentation - virtual const search::fef::IIndexEnvironment & getIndexEnvironment() const override { return _indexEnv; } - + const search::fef::IIndexEnvironment & getIndexEnvironment() const override { return _indexEnv; } void addTerm(const search::fef::ITermData *term) { _queryTerms.push_back(term); } std::vector<vespalib::string> get_accessed_attributes() const { return _attrCtx->get_accessed_attributes(); } diff --git a/streamingvisitors/src/vespa/searchvisitor/rankprocessor.cpp b/streamingvisitors/src/vespa/searchvisitor/rankprocessor.cpp index ac7a61e5888..825630f057b 100644 --- a/streamingvisitors/src/vespa/searchvisitor/rankprocessor.cpp +++ b/streamingvisitors/src/vespa/searchvisitor/rankprocessor.cpp @@ -106,6 +106,8 @@ RankProcessor::initQueryEnvironment() QueryWrapper::TermList & terms = _query.getTermList(); for (auto& term : terms) { + if (!term->isRanked()) continue; + if (term->isGeoLoc()) { const vespalib::string & fieldName = term->index(); const vespalib::string & locStr = term->getTermString(); |