diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2018-09-13 13:50:23 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-13 13:50:23 +0200 |
commit | de560e27f9cabc3aa92b0f173045f2e572513fbe (patch) | |
tree | 811569ee866ddeea2aec0199c08c994c8e1f3ab0 | |
parent | 023e9c25224a7e13b35f5c52e85c143c5dd9d249 (diff) | |
parent | 009b0ea995f82e164e2892d8cc4ab72973f79acd (diff) |
Merge pull request #6941 from vespa-engine/toregge/extend-grouping-test-to-use-attribute-map-lookup
Test simple grouping with attribute map lookup.
7 files changed, 114 insertions, 27 deletions
diff --git a/searchlib/src/tests/expression/attributenode/CMakeLists.txt b/searchlib/src/tests/expression/attributenode/CMakeLists.txt index c7df5458bb7..3006c27dd0d 100644 --- a/searchlib/src/tests/expression/attributenode/CMakeLists.txt +++ b/searchlib/src/tests/expression/attributenode/CMakeLists.txt @@ -4,5 +4,6 @@ vespa_add_executable(searchlib_attribute_node_test_app TEST attribute_node_test.cpp DEPENDS searchlib + searchlib_test ) vespa_add_test(NAME searchlib_attribute_node_test_app COMMAND searchlib_attribute_node_test_app) diff --git a/searchlib/src/tests/expression/attributenode/attribute_node_test.cpp b/searchlib/src/tests/expression/attributenode/attribute_node_test.cpp index ec1a86bca69..7490b0699be 100644 --- a/searchlib/src/tests/expression/attributenode/attribute_node_test.cpp +++ b/searchlib/src/tests/expression/attributenode/attribute_node_test.cpp @@ -10,8 +10,8 @@ #include <vespa/searchlib/attribute/integerbase.h> #include <vespa/searchlib/attribute/stringbase.h> #include <vespa/searchlib/expression/attributenode.h> -#include <vespa/searchlib/expression/attribute_map_lookup_node.h> #include <vespa/searchlib/expression/resultvector.h> +#include <vespa/searchlib/test/make_attribute_map_lookup_node.h> #include <vespa/vespalib/test/insertion_operators.h> #include <vespa/vespalib/testkit/testapp.h> @@ -31,7 +31,6 @@ using search::attribute::Config; using search::attribute::IAttributeVector; using search::attribute::getUndefined; using search::expression::AttributeNode; -using search::expression::AttributeMapLookupNode; using search::expression::EnumResultNode; using search::expression::EnumResultNodeVector; using search::expression::FloatResultNode; @@ -44,6 +43,7 @@ using search::expression::ResultNode; using search::expression::ResultNodeVector; using search::expression::StringResultNode; using search::expression::StringResultNodeVector; +using search::expression::test::makeAttributeMapLookupNode; using vespalib::BufferRef; namespace { @@ -60,31 +60,6 @@ vespalib::string stringValue(const ResultNode &result, const IAttributeVector &a return vespalib::string(sbuf.c_str(), sbuf.c_str() + sbuf.size()); } -vespalib::string indirectKeyMarker("attribute("); - -std::unique_ptr<AttributeNode> -makeAttributeMapLookupNode(const vespalib::string attributeName) -{ - vespalib::asciistream keyName; - vespalib::asciistream valueName; - auto leftBracePos = attributeName.find('{'); - auto baseName = attributeName.substr(0, leftBracePos); - auto rightBracePos = attributeName.rfind('}'); - keyName << baseName << ".key"; - valueName << baseName << ".value" << attributeName.substr(rightBracePos + 1); - if (rightBracePos != vespalib::string::npos && rightBracePos > leftBracePos) { - if (attributeName[leftBracePos + 1] == '"' && attributeName[rightBracePos - 1] == '"') { - vespalib::string key = attributeName.substr(leftBracePos + 2, rightBracePos - leftBracePos - 3); - return std::make_unique<AttributeMapLookupNode>(attributeName, keyName.str(), valueName.str(), key, ""); - } else if (attributeName.substr(leftBracePos + 1, indirectKeyMarker.size()) == indirectKeyMarker && attributeName[rightBracePos - 1] == ')') { - auto startPos = leftBracePos + 1 + indirectKeyMarker.size(); - vespalib::string keySourceAttributeName = attributeName.substr(startPos, rightBracePos - 1 - startPos); - return std::make_unique<AttributeMapLookupNode>(attributeName, keyName.str(), valueName.str(), "", keySourceAttributeName); - } - } - return std::unique_ptr<AttributeNode>(); -} - struct AttributeManagerFixture { AttributeManager mgr; diff --git a/searchlib/src/tests/grouping/CMakeLists.txt b/searchlib/src/tests/grouping/CMakeLists.txt index ea90f27d9f6..e2bb73c57a4 100644 --- a/searchlib/src/tests/grouping/CMakeLists.txt +++ b/searchlib/src/tests/grouping/CMakeLists.txt @@ -4,6 +4,7 @@ vespa_add_executable(searchlib_grouping_test_app TEST grouping_test.cpp DEPENDS searchlib + searchlib_test ) vespa_add_test(NAME searchlib_grouping_test_app COMMAND searchlib_grouping_test_app) vespa_add_executable(searchlib_hyperloglog_test_app TEST diff --git a/searchlib/src/tests/grouping/grouping_test.cpp b/searchlib/src/tests/grouping/grouping_test.cpp index 4cf9eb6f5c6..084f13795f7 100644 --- a/searchlib/src/tests/grouping/grouping_test.cpp +++ b/searchlib/src/tests/grouping/grouping_test.cpp @@ -9,6 +9,8 @@ #include <vespa/searchlib/aggregation/fs4hit.h> #include <vespa/searchlib/aggregation/predicates.h> #include <vespa/searchlib/expression/fixedwidthbucketfunctionnode.h> +#include <vespa/searchlib/test/make_attribute_map_lookup_node.h> +#include <vespa/searchcommon/common/undefinedvalues.h> #include <algorithm> #include <cmath> #include <iostream> @@ -21,6 +23,13 @@ using namespace search; using namespace search::aggregation; using namespace search::attribute; using namespace search::expression; +using search::expression::test::makeAttributeMapLookupNode; + +namespace { + +const int64_t undefinedInteger = getUndefined<int64_t>(); + +} //----------------------------------------------------------------------------- @@ -61,6 +70,14 @@ public: _attr->add(value); return *this; } + AttrBuilder &add(std::vector<T> values) { + DocId ignore; + _attr->addDoc(ignore); + for (T value : values) { + _attr->add(value); + } + return *this; + } AttributeVector::SP sp() const { return _attrSP; } @@ -70,6 +87,9 @@ typedef AttrBuilder<SingleIntegerExtAttribute, int64_t> IntAttrBuilder; typedef AttrBuilder<SingleFloatExtAttribute, double> FloatAttrBuilder; typedef AttrBuilder<SingleStringExtAttribute, const char *> StringAttrBuilder; +using StringArrayAttrBuilder = AttrBuilder<MultiStringExtAttribute, const char *>; +using IntArrayAttrBuilder = AttrBuilder<MultiIntegerExtAttribute, int64_t>; + //----------------------------------------------------------------------------- class ResultBuilder @@ -164,8 +184,10 @@ public: void testFixedWidthBuckets(); void testThatNanIsConverted(); void testNanSorting(); + void testAttributeMapLookup(); int Main() override; private: + void testAggregationSimple(AggregationContext & ctx, const AggregationResult & aggr, const ResultNode & ir, const vespalib::string &name); void testAggregationSimpleSum(AggregationContext & ctx, const AggregationResult & aggr, const ResultNode & ir, const ResultNode & fr, const ResultNode & sr); class CheckAttributeReferences : public vespalib::ObjectOperation, public vespalib::ObjectPredicate { @@ -313,6 +335,18 @@ prepareAggr(const AggregationResult & aggr, ExpressionNode::UP expr, const Resul prepared->setResult(r); return prepared; } + +void Test::testAggregationSimple(AggregationContext & ctx, const AggregationResult & aggr, const ResultNode & ir, const vespalib::string &name) +{ + ExpressionNode::CP clone(aggr); + Grouping request; + request.setRoot(Group().addResult(prepareAggr(aggr, makeAttributeMapLookupNode(name)))); + + Group expect; + expect.addResult(prepareAggr(aggr, makeAttributeMapLookupNode(name), ir)); + EXPECT_TRUE(testAggregation(ctx, request, expect)); +} + void Test::testAggregationSimpleSum(AggregationContext & ctx, const AggregationResult & aggr, const ResultNode & ir, const ResultNode & fr, const ResultNode & sr) { ExpressionNode::CP clone(aggr); @@ -1884,6 +1918,28 @@ Test::testThatNanIsConverted() ASSERT_EQUAL(g.getRank(), g.getRank()); } +void +Test::testAttributeMapLookup() +{ + AggregationContext ctx; + ctx.result().add(0).add(1); + ctx.add(StringArrayAttrBuilder("smap.key").add({"k1", "k2"}).add({"k3", "k4"}).sp()); + ctx.add(IntArrayAttrBuilder("smap.value.weight").add({10, 20}).add({100, 200}).sp()); + ctx.add(StringAttrBuilder("key1").add("k1").add("k4").sp()); + ctx.add(StringAttrBuilder("key2").add("k2").add("k3").sp()); + ctx.add(StringAttrBuilder("key3").add("k3").add("k2").sp()); + testAggregationSimple(ctx, SumAggregationResult(), Int64ResultNode(10 + undefinedInteger), "smap{\"k1\"}.weight"); + testAggregationSimple(ctx, SumAggregationResult(), Int64ResultNode(20 + undefinedInteger), "smap{\"k2\"}.weight"); + testAggregationSimple(ctx, SumAggregationResult(), Int64ResultNode(2 * undefinedInteger), "smap{\"k5\"}.weight"); + testAggregationSimple(ctx, SumAggregationResult(), Int64ResultNode(210), "smap{attribute(key1)}.weight"); + testAggregationSimple(ctx, SumAggregationResult(), Int64ResultNode(120), "smap{attribute(key2)}.weight"); + testAggregationSimple(ctx, SumAggregationResult(), Int64ResultNode(2 * undefinedInteger), "smap{attribute(key3)}.weight"); + testAggregationSimple(ctx, MinAggregationResult(), Int64ResultNode(10), "smap{attribute(key1)}.weight"); + testAggregationSimple(ctx, MinAggregationResult(), Int64ResultNode(20), "smap{attribute(key2)}.weight"); + testAggregationSimple(ctx, MaxAggregationResult(), Int64ResultNode(200), "smap{attribute(key1)}.weight"); + testAggregationSimple(ctx, MaxAggregationResult(), Int64ResultNode(100), "smap{attribute(key2)}.weight"); +} + //----------------------------------------------------------------------------- struct RunDiff { ~RunDiff() { system("diff -u lhs.out rhs.out > diff.txt"); }}; @@ -1916,6 +1972,7 @@ Test::Main() testTopN(); testThatNanIsConverted(); testNanSorting(); + testAttributeMapLookup(); TEST_DONE(); } diff --git a/searchlib/src/vespa/searchlib/test/CMakeLists.txt b/searchlib/src/vespa/searchlib/test/CMakeLists.txt index b4fb895c0e2..1231a99920e 100644 --- a/searchlib/src/vespa/searchlib/test/CMakeLists.txt +++ b/searchlib/src/vespa/searchlib/test/CMakeLists.txt @@ -3,6 +3,7 @@ vespa_add_library(searchlib_test SOURCES document_weight_attribute_helper.cpp initrange.cpp + make_attribute_map_lookup_node.cpp mock_attribute_context.cpp mock_attribute_manager.cpp searchiteratorverifier.cpp diff --git a/searchlib/src/vespa/searchlib/test/make_attribute_map_lookup_node.cpp b/searchlib/src/vespa/searchlib/test/make_attribute_map_lookup_node.cpp new file mode 100644 index 00000000000..6f717d99d2c --- /dev/null +++ b/searchlib/src/vespa/searchlib/test/make_attribute_map_lookup_node.cpp @@ -0,0 +1,38 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "make_attribute_map_lookup_node.h" +#include <vespa/searchlib/expression/attribute_map_lookup_node.h> +#include <vespa/vespalib/stllike/asciistream.h> + +namespace search::expression::test { + +namespace { + +vespalib::string indirectKeyMarker("attribute("); + +} + +std::unique_ptr<AttributeNode> +makeAttributeMapLookupNode(const vespalib::string attributeName) +{ + vespalib::asciistream keyName; + vespalib::asciistream valueName; + auto leftBracePos = attributeName.find('{'); + auto baseName = attributeName.substr(0, leftBracePos); + auto rightBracePos = attributeName.rfind('}'); + keyName << baseName << ".key"; + valueName << baseName << ".value" << attributeName.substr(rightBracePos + 1); + if (rightBracePos != vespalib::string::npos && rightBracePos > leftBracePos) { + if (attributeName[leftBracePos + 1] == '"' && attributeName[rightBracePos - 1] == '"') { + vespalib::string key = attributeName.substr(leftBracePos + 2, rightBracePos - leftBracePos - 3); + return std::make_unique<AttributeMapLookupNode>(attributeName, keyName.str(), valueName.str(), key, ""); + } else if (attributeName.substr(leftBracePos + 1, indirectKeyMarker.size()) == indirectKeyMarker && attributeName[rightBracePos - 1] == ')') { + auto startPos = leftBracePos + 1 + indirectKeyMarker.size(); + vespalib::string keySourceAttributeName = attributeName.substr(startPos, rightBracePos - 1 - startPos); + return std::make_unique<AttributeMapLookupNode>(attributeName, keyName.str(), valueName.str(), "", keySourceAttributeName); + } + } + return std::unique_ptr<AttributeNode>(); +} + +} diff --git a/searchlib/src/vespa/searchlib/test/make_attribute_map_lookup_node.h b/searchlib/src/vespa/searchlib/test/make_attribute_map_lookup_node.h new file mode 100644 index 00000000000..3434c8f2ae3 --- /dev/null +++ b/searchlib/src/vespa/searchlib/test/make_attribute_map_lookup_node.h @@ -0,0 +1,14 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#pragma once + +#include <vespa/vespalib/stllike/string.h> +#include <memory> + +namespace search::expression { class AttributeNode; } + +namespace search::expression::test { + +std::unique_ptr<AttributeNode> +makeAttributeMapLookupNode(const vespalib::string attributeName); + +} |