summaryrefslogtreecommitdiffstats
path: root/searchlib
diff options
context:
space:
mode:
authorTor Egge <Tor.Egge@broadpark.no>2018-09-13 12:25:15 +0200
committerTor Egge <Tor.Egge@broadpark.no>2018-09-13 12:25:15 +0200
commit009b0ea995f82e164e2892d8cc4ab72973f79acd (patch)
tree2e0be4a638ed2c4df2a0c6b7ebe66d0c7ed1604f /searchlib
parent88a8ed4e3223d761a7943ad646dba25b3b70ed4c (diff)
Test simple grouping with attribute map lookup.
Diffstat (limited to 'searchlib')
-rw-r--r--searchlib/src/tests/expression/attributenode/CMakeLists.txt1
-rw-r--r--searchlib/src/tests/expression/attributenode/attribute_node_test.cpp29
-rw-r--r--searchlib/src/tests/grouping/CMakeLists.txt1
-rw-r--r--searchlib/src/tests/grouping/grouping_test.cpp57
-rw-r--r--searchlib/src/vespa/searchlib/test/CMakeLists.txt1
-rw-r--r--searchlib/src/vespa/searchlib/test/make_attribute_map_lookup_node.cpp38
-rw-r--r--searchlib/src/vespa/searchlib/test/make_attribute_map_lookup_node.h14
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);
+
+}