summaryrefslogtreecommitdiffstats
path: root/searchlib
diff options
context:
space:
mode:
authorGeir Storli <geirstorli@yahoo.no>2016-08-31 13:44:51 +0200
committerGitHub <noreply@github.com>2016-08-31 13:44:51 +0200
commit431961a4f99cfbb394bae5478818333cb8c6f7df (patch)
tree5097d52d259d8707dc6ff3cf07dec7a1123291d8 /searchlib
parent179b2b164317d2c6d51d6a7fe881cea6d3fbe8fa (diff)
parent9a8ec2228b0f4300fc2cefb7cbe05ddbc2636e2f (diff)
Merge pull request #501 from yahoo/toregge/add-constant-feature
Add constant feature blueprint and constant feature executor.
Diffstat (limited to 'searchlib')
-rw-r--r--searchlib/CMakeLists.txt1
-rw-r--r--searchlib/src/tests/features/constant/.gitignore1
-rw-r--r--searchlib/src/tests/features/constant/CMakeLists.txt8
-rw-r--r--searchlib/src/tests/features/constant/FILES1
-rw-r--r--searchlib/src/tests/features/constant/constant_test.cpp119
-rw-r--r--searchlib/src/tests/features/tensor/tensor_test.cpp42
-rw-r--r--searchlib/src/tests/features/tensor_from_labels/tensor_from_labels_test.cpp22
-rw-r--r--searchlib/src/tests/features/tensor_from_weighted_set/tensor_from_weighted_set_test.cpp22
-rw-r--r--searchlib/src/vespa/searchlib/features/CMakeLists.txt1
-rw-r--r--searchlib/src/vespa/searchlib/features/constant_feature.cpp91
-rw-r--r--searchlib/src/vespa/searchlib/features/constant_feature.h48
-rw-r--r--searchlib/src/vespa/searchlib/features/setup.cpp2
-rw-r--r--searchlib/src/vespa/searchlib/fef/test/CMakeLists.txt1
-rw-r--r--searchlib/src/vespa/searchlib/fef/test/as_tensor.cpp57
-rw-r--r--searchlib/src/vespa/searchlib/fef/test/as_tensor.h40
-rw-r--r--searchlib/src/vespa/searchlib/fef/test/indexenvironment.cpp36
-rw-r--r--searchlib/src/vespa/searchlib/fef/test/indexenvironment.h37
17 files changed, 442 insertions, 87 deletions
diff --git a/searchlib/CMakeLists.txt b/searchlib/CMakeLists.txt
index 0ef3b0bac18..c99c3c36bd1 100644
--- a/searchlib/CMakeLists.txt
+++ b/searchlib/CMakeLists.txt
@@ -111,6 +111,7 @@ vespa_define_module(
src/tests/engine/transportserver
src/tests/features
src/tests/features/beta
+ src/tests/features/constant
src/tests/features/element_completeness
src/tests/features/element_similarity_feature
src/tests/features/euclidean_distance
diff --git a/searchlib/src/tests/features/constant/.gitignore b/searchlib/src/tests/features/constant/.gitignore
new file mode 100644
index 00000000000..ec1ff674d9e
--- /dev/null
+++ b/searchlib/src/tests/features/constant/.gitignore
@@ -0,0 +1 @@
+searchlib_constant_test_app
diff --git a/searchlib/src/tests/features/constant/CMakeLists.txt b/searchlib/src/tests/features/constant/CMakeLists.txt
new file mode 100644
index 00000000000..9a653234a0a
--- /dev/null
+++ b/searchlib/src/tests/features/constant/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(searchlib_constant_test_app TEST
+ SOURCES
+ constant_test.cpp
+ DEPENDS
+ searchlib
+)
+vespa_add_test(NAME searchlib_constant_test_app COMMAND searchlib_constant_test_app)
diff --git a/searchlib/src/tests/features/constant/FILES b/searchlib/src/tests/features/constant/FILES
new file mode 100644
index 00000000000..5ff67b0b742
--- /dev/null
+++ b/searchlib/src/tests/features/constant/FILES
@@ -0,0 +1 @@
+constant_test.cpp
diff --git a/searchlib/src/tests/features/constant/constant_test.cpp b/searchlib/src/tests/features/constant/constant_test.cpp
new file mode 100644
index 00000000000..3fae07f908a
--- /dev/null
+++ b/searchlib/src/tests/features/constant/constant_test.cpp
@@ -0,0 +1,119 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/fastos/fastos.h>
+#include <vespa/vespalib/testkit/test_kit.h>
+#include <vespa/vespalib/eval/function.h>
+
+#include <vespa/searchlib/features/setup.h>
+#include <vespa/searchlib/fef/fef.h>
+#include <vespa/searchlib/fef/test/as_tensor.h>
+#include <vespa/searchlib/fef/test/ftlib.h>
+#include <vespa/searchlib/fef/test/indexenvironment.h>
+#include <vespa/vespalib/tensor/default_tensor.h>
+#include <vespa/vespalib/tensor/tensor_factory.h>
+
+using search::feature_t;
+using namespace search::fef;
+using namespace search::fef::indexproperties;
+using namespace search::fef::test;
+using namespace search::features;
+using vespalib::eval::Function;
+using vespalib::eval::Value;
+using vespalib::eval::DoubleValue;
+using vespalib::eval::TensorValue;
+using vespalib::eval::ValueType;
+using vespalib::tensor::DenseTensorCells;
+using vespalib::tensor::Tensor;
+using vespalib::tensor::TensorCells;
+using vespalib::tensor::TensorDimensions;
+using vespalib::tensor::TensorFactory;
+
+namespace
+{
+
+Tensor::UP createTensor(const TensorCells &cells,
+ const TensorDimensions &dimensions) {
+ vespalib::tensor::DefaultTensor::builder builder;
+ return TensorFactory::create(cells, dimensions, builder);
+}
+
+}
+
+struct ExecFixture
+{
+ BlueprintFactory factory;
+ FtFeatureTest test;
+ ExecFixture(const vespalib::string &feature)
+ : factory(),
+ test(factory, feature)
+ {
+ setup_search_features(factory);
+ }
+ bool setup() { return test.setup(); }
+ const Tensor &extractTensor() {
+ const Value::CREF *value = test.resolveObjectFeature();
+ ASSERT_TRUE(value != nullptr);
+ ASSERT_TRUE(value->get().is_tensor());
+ return static_cast<const Tensor &>(*value->get().as_tensor());
+ }
+ const Tensor &executeTensor(uint32_t docId = 1) {
+ test.executeOnly(docId);
+ return extractTensor();
+ }
+ double extractDouble() {
+ const Value::CREF *value = test.resolveObjectFeature();
+ ASSERT_TRUE(value != nullptr);
+ ASSERT_TRUE(value->get().is_double());
+ return value->get().as_double();
+ }
+ double executeDouble(uint32_t docId = 1) {
+ test.executeOnly(docId);
+ return extractDouble();
+ }
+ void addTensor(const vespalib::string &name,
+ const TensorCells &cells,
+ const TensorDimensions &dimensions)
+ {
+ Tensor::UP tensor = createTensor(cells, dimensions);
+ ValueType type(tensor->getType().as_value_type());
+ test.getIndexEnv().addConstantValue(name,
+ std::move(type),
+ std::make_unique<TensorValue>(std::move(tensor)));
+ }
+
+ void addDouble(const vespalib::string &name, const double value) {
+ test.getIndexEnv().addConstantValue(name,
+ ValueType::double_type(),
+ std::make_unique<DoubleValue>(value));
+ }
+};
+
+TEST_F("require that missing constant is detected",
+ ExecFixture("constant(foo)"))
+{
+ EXPECT_TRUE(!f.setup());
+}
+
+
+TEST_F("require that existing tensor constant is detected",
+ ExecFixture("constant(foo)"))
+{
+ f.addTensor("foo",
+ { {{{"x", "a"}}, 3},
+ {{{"x", "b"}}, 5},
+ {{{"x", "c"}}, 7} },
+ { "x" });
+ EXPECT_TRUE(f.setup());
+ EXPECT_EQUAL(AsTensor("{ {x:b}:5, {x:c}:7, {x:a}:3 }"), f.executeTensor());
+}
+
+
+TEST_F("require that existing double constant is detected",
+ ExecFixture("constant(foo)"))
+{
+ f.addDouble("foo", 42.0);
+ EXPECT_TRUE(f.setup());
+ EXPECT_EQUAL(42.0, f.executeDouble());
+}
+
+
+TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/searchlib/src/tests/features/tensor/tensor_test.cpp b/searchlib/src/tests/features/tensor/tensor_test.cpp
index 8bcbb5954ff..bcb984c692b 100644
--- a/searchlib/src/tests/features/tensor/tensor_test.cpp
+++ b/searchlib/src/tests/features/tensor/tensor_test.cpp
@@ -9,16 +9,14 @@
#include <vespa/searchlib/attribute/tensorattribute.h>
#include <vespa/searchlib/features/setup.h>
#include <vespa/searchlib/fef/fef.h>
+#include <vespa/searchlib/fef/test/as_tensor.h>
#include <vespa/searchlib/fef/test/ftlib.h>
#include <vespa/searchlib/fef/test/indexenvironment.h>
#include <vespa/searchlib/fef/test/indexenvironmentbuilder.h>
#include <vespa/searchlib/fef/test/queryenvironment.h>
-#include <vespa/vespalib/eval/interpreted_function.h>
#include <vespa/vespalib/tensor/default_tensor.h>
-#include <vespa/vespalib/tensor/default_tensor_engine.h>
#include <vespa/vespalib/tensor/serialization/typed_binary_format.h>
#include <vespa/vespalib/tensor/tensor_factory.h>
-#include <vespa/vespalib/tensor/tensor_mapper.h>
using search::feature_t;
using namespace search::fef;
@@ -29,15 +27,12 @@ using search::AttributeFactory;
using search::attribute::TensorAttribute;
using search::AttributeVector;
using vespalib::eval::Function;
-using vespalib::eval::InterpretedFunction;
using vespalib::eval::Value;
-using vespalib::tensor::DefaultTensorEngine;
using vespalib::tensor::DenseTensorCells;
using vespalib::tensor::Tensor;
using vespalib::tensor::TensorCells;
using vespalib::tensor::TensorDimensions;
using vespalib::tensor::TensorFactory;
-using vespalib::tensor::TensorMapper;
using vespalib::tensor::TensorType;
typedef search::attribute::Config AVC;
@@ -160,41 +155,6 @@ struct ExecFixture
}
};
-struct AsTensor {
- InterpretedFunction ifun;
- InterpretedFunction::Context ctx;
- const Value *result;
- const Tensor *tensor;
- explicit AsTensor(const vespalib::string &expr)
- : ifun(DefaultTensorEngine::ref(), Function::parse(expr)), ctx(), result(&ifun.eval(ctx))
- {
- ASSERT_TRUE(result->is_tensor());
- tensor = static_cast<const Tensor *>(result->as_tensor());
- }
- bool operator==(const Tensor &rhs) const {
- return tensor->equals(rhs);
- }
-};
-
-struct AsEmptyTensor : public AsTensor {
- TensorMapper mapper;
- Tensor::UP mappedTensor;
- AsEmptyTensor(const vespalib::string &type)
- : AsTensor("{ }"),
- mapper(TensorType::fromSpec(type)),
- mappedTensor(mapper.map(*tensor))
- {}
- bool operator==(const Tensor &rhs) const {
- return mappedTensor->equals(rhs);
- }
-
-};
-
-std::ostream &operator<<(std::ostream &os, const AsTensor &my_tensor) {
- os << my_tensor.result->as_tensor();
- return os;
-}
-
TEST_F("require that tensor attribute can be extracted as tensor in attribute feature",
ExecFixture("attribute(tensorattr)"))
{
diff --git a/searchlib/src/tests/features/tensor_from_labels/tensor_from_labels_test.cpp b/searchlib/src/tests/features/tensor_from_labels/tensor_from_labels_test.cpp
index b15ffb956ce..8d67ed99fdf 100644
--- a/searchlib/src/tests/features/tensor_from_labels/tensor_from_labels_test.cpp
+++ b/searchlib/src/tests/features/tensor_from_labels/tensor_from_labels_test.cpp
@@ -2,15 +2,14 @@
#include <vespa/fastos/fastos.h>
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/vespalib/eval/function.h>
-#include <vespa/vespalib/eval/interpreted_function.h>
#include <vespa/vespalib/tensor/tensor.h>
-#include <vespa/vespalib/tensor/default_tensor_engine.h>
#include <vespa/searchlib/attribute/attributefactory.h>
#include <vespa/searchlib/attribute/attributevector.h>
#include <vespa/searchlib/attribute/integerbase.h>
#include <vespa/searchlib/attribute/stringbase.h>
#include <vespa/searchlib/features/setup.h>
+#include <vespa/searchlib/fef/test/as_tensor.h>
#include <vespa/searchlib/fef/test/indexenvironment.h>
#include <vespa/searchlib/fef/test/indexenvironmentbuilder.h>
#include <vespa/searchlib/fef/test/queryenvironment.h>
@@ -27,9 +26,7 @@ using search::IntegerAttribute;
using search::StringAttribute;
using vespalib::eval::Value;
using vespalib::eval::Function;
-using vespalib::eval::InterpretedFunction;
using vespalib::tensor::Tensor;
-using vespalib::tensor::DefaultTensorEngine;
typedef search::attribute::Config AVC;
typedef search::attribute::BasicType AVBT;
@@ -126,23 +123,6 @@ struct ExecFixture
}
};
-struct AsTensor {
- InterpretedFunction ifun;
- InterpretedFunction::Context ctx;
- const Value *result;
- explicit AsTensor(const vespalib::string &expr)
- : ifun(DefaultTensorEngine::ref(), Function::parse(expr)), ctx(), result(&ifun.eval(ctx))
- {
- ASSERT_TRUE(result->is_tensor());
- }
- bool operator==(const Tensor &rhs) const { return static_cast<const Tensor &>(*result->as_tensor()).equals(rhs); }
-};
-
-std::ostream &operator<<(std::ostream &os, const AsTensor &my_tensor) {
- os << my_tensor.result->as_tensor();
- return os;
-}
-
// Tests for attribute source:
TEST_F("require that array string attribute can be converted to tensor (default dimension)",
diff --git a/searchlib/src/tests/features/tensor_from_weighted_set/tensor_from_weighted_set_test.cpp b/searchlib/src/tests/features/tensor_from_weighted_set/tensor_from_weighted_set_test.cpp
index 163fd5b5389..a44a0d9fa8f 100644
--- a/searchlib/src/tests/features/tensor_from_weighted_set/tensor_from_weighted_set_test.cpp
+++ b/searchlib/src/tests/features/tensor_from_weighted_set/tensor_from_weighted_set_test.cpp
@@ -2,15 +2,14 @@
#include <vespa/fastos/fastos.h>
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/vespalib/eval/function.h>
-#include <vespa/vespalib/eval/interpreted_function.h>
#include <vespa/vespalib/tensor/tensor.h>
-#include <vespa/vespalib/tensor/default_tensor_engine.h>
#include <vespa/searchlib/attribute/attributefactory.h>
#include <vespa/searchlib/attribute/attributevector.h>
#include <vespa/searchlib/attribute/integerbase.h>
#include <vespa/searchlib/attribute/stringbase.h>
#include <vespa/searchlib/features/setup.h>
+#include <vespa/searchlib/fef/test/as_tensor.h>
#include <vespa/searchlib/fef/test/indexenvironment.h>
#include <vespa/searchlib/fef/test/indexenvironmentbuilder.h>
#include <vespa/searchlib/fef/test/queryenvironment.h>
@@ -27,9 +26,7 @@ using search::IntegerAttribute;
using search::StringAttribute;
using vespalib::eval::Value;
using vespalib::eval::Function;
-using vespalib::eval::InterpretedFunction;
using vespalib::tensor::Tensor;
-using vespalib::tensor::DefaultTensorEngine;
typedef search::attribute::Config AVC;
typedef search::attribute::BasicType AVBT;
@@ -124,23 +121,6 @@ struct ExecFixture
}
};
-struct AsTensor {
- InterpretedFunction ifun;
- InterpretedFunction::Context ctx;
- const Value *result;
- explicit AsTensor(const vespalib::string &expr)
- : ifun(DefaultTensorEngine::ref(), Function::parse(expr)), ctx(), result(&ifun.eval(ctx))
- {
- ASSERT_TRUE(result->is_tensor());
- }
- bool operator==(const Tensor &rhs) const { return static_cast<const Tensor &>(*result->as_tensor()).equals(rhs); }
-};
-
-std::ostream &operator<<(std::ostream &os, const AsTensor &my_tensor) {
- os << my_tensor.result->as_tensor();
- return os;
-}
-
TEST_F("require that weighted set string attribute can be converted to tensor (default dimension)",
ExecFixture("tensorFromWeightedSet(attribute(wsstr))"))
{
diff --git a/searchlib/src/vespa/searchlib/features/CMakeLists.txt b/searchlib/src/vespa/searchlib/features/CMakeLists.txt
index c69486505a0..eb8e3ac39d5 100644
--- a/searchlib/src/vespa/searchlib/features/CMakeLists.txt
+++ b/searchlib/src/vespa/searchlib/features/CMakeLists.txt
@@ -6,6 +6,7 @@ vespa_add_library(searchlib_features OBJECT
attributefeature.cpp
attributematchfeature.cpp
closenessfeature.cpp
+ constant_feature.cpp
debug_attribute_wait.cpp
debug_wait.cpp
distancefeature.cpp
diff --git a/searchlib/src/vespa/searchlib/features/constant_feature.cpp b/searchlib/src/vespa/searchlib/features/constant_feature.cpp
new file mode 100644
index 00000000000..e0237587470
--- /dev/null
+++ b/searchlib/src/vespa/searchlib/features/constant_feature.cpp
@@ -0,0 +1,91 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include <vespa/fastos/fastos.h>
+#include <vespa/log/log.h>
+LOG_SETUP(".features.constant_feature");
+#include "constant_feature.h"
+
+#include <vespa/searchlib/fef/featureexecutor.h>
+#include "valuefeature.h"
+#include <vespa/vespalib/eval/value_cache/constant_value.h>
+
+using namespace search::fef;
+
+namespace search {
+namespace features {
+
+/**
+ * Feature executor that returns a constant value.
+ */
+class ConstantFeatureExecutor : public fef::FeatureExecutor
+{
+private:
+ const vespalib::eval::Value &_value;
+
+public:
+ ConstantFeatureExecutor(const vespalib::eval::Value &value)
+ : _value(value)
+ {}
+ virtual bool isPure() override { return true; }
+ virtual void execute(fef::MatchData &data) override {
+ *data.resolve_object_feature(outputs()[0]) = _value;
+ }
+ static FeatureExecutor::LP create(const vespalib::eval::Value &value) {
+ return FeatureExecutor::LP(new ConstantFeatureExecutor(value));
+ }
+};
+
+ConstantBlueprint::ConstantBlueprint()
+ : Blueprint("constant"),
+ _key(),
+ _value()
+{
+}
+
+ConstantBlueprint::~ConstantBlueprint()
+{
+}
+
+void
+ConstantBlueprint::visitDumpFeatures(const IIndexEnvironment &,
+ IDumpFeatureVisitor &) const
+{
+}
+
+Blueprint::UP
+ConstantBlueprint::createInstance() const
+{
+ return Blueprint::UP(new ConstantBlueprint());
+}
+
+bool
+ConstantBlueprint::setup(const IIndexEnvironment &env,
+ const ParameterList &params)
+{
+ _key = params[0].getValue();
+ _value = env.getConstantValue(_key);
+ if (!_value || _value->type().is_error()) {
+ LOG(error, "Constant '%s' not found", _key.c_str());
+ }
+ FeatureType output_type = _value ?
+ FeatureType::object(_value->type()) :
+ FeatureType::number();
+ describeOutput("out", "The constant looked up in index environment using the given key.",
+ output_type);
+ return (_value && !_value->type().is_error());
+}
+
+FeatureExecutor::LP
+ConstantBlueprint::createExecutor(const IQueryEnvironment &env) const
+{
+ (void) env;
+ if (_value) {
+ return ConstantFeatureExecutor::create(_value->value());
+ } else {
+ // Note: Should not happen, setup() has already failed
+ return FeatureExecutor::LP(new SingleZeroValueExecutor());
+ }
+}
+
+} // namespace features
+} // namespace search
diff --git a/searchlib/src/vespa/searchlib/features/constant_feature.h b/searchlib/src/vespa/searchlib/features/constant_feature.h
new file mode 100644
index 00000000000..3360b072fe3
--- /dev/null
+++ b/searchlib/src/vespa/searchlib/features/constant_feature.h
@@ -0,0 +1,48 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#pragma once
+
+#include <vespa/searchlib/fef/blueprint.h>
+
+namespace vespalib { namespace eval { struct ConstantValue; } }
+
+namespace search {
+namespace features {
+
+/**
+ * Implements the blueprint for the constant feature.
+ *
+ * An executor of this outputs the value of a named constant.
+ * This can either be a number or a tensor value.
+ */
+class ConstantBlueprint : public search::fef::Blueprint {
+private:
+ vespalib::string _key; // 'foo'
+ std::unique_ptr<vespalib::eval::ConstantValue> _value;
+
+public:
+ /**
+ * Constructs a constant blueprint.
+ */
+ ConstantBlueprint();
+
+ ~ConstantBlueprint();
+
+ virtual void visitDumpFeatures(const search::fef::IIndexEnvironment &env,
+ search::fef::IDumpFeatureVisitor &visitor) const override;
+
+ virtual search::fef::Blueprint::UP createInstance() const override;
+
+ virtual search::fef::ParameterDescriptions getDescriptions() const override {
+ return search::fef::ParameterDescriptions().desc().string();
+ }
+
+ virtual bool setup(const search::fef::IIndexEnvironment &env,
+ const search::fef::ParameterList &params) override;
+
+ virtual search::fef::FeatureExecutor::LP createExecutor(const search::fef::IQueryEnvironment &env) const override;
+};
+
+} // namespace features
+} // namespace search
+
diff --git a/searchlib/src/vespa/searchlib/features/setup.cpp b/searchlib/src/vespa/searchlib/features/setup.cpp
index 7c98fc8c1ea..f3f99817932 100644
--- a/searchlib/src/vespa/searchlib/features/setup.cpp
+++ b/searchlib/src/vespa/searchlib/features/setup.cpp
@@ -51,6 +51,7 @@
#include "terminfofeature.h"
#include "text_similarity_feature.h"
#include "valuefeature.h"
+#include "constant_feature.h"
using search::fef::Blueprint;
@@ -111,6 +112,7 @@ void setup_search_features(fef::IBlueprintRegistry & registry)
registry.addPrototype(Blueprint::SP(new ReverseProximityBlueprint()));
registry.addPrototype(Blueprint::SP(new TermEditDistanceBlueprint()));
registry.addPrototype(Blueprint::SP(new TermFieldMdBlueprint()));
+ registry.addPrototype(std::make_shared<ConstantBlueprint>());
}
} // namespace features
diff --git a/searchlib/src/vespa/searchlib/fef/test/CMakeLists.txt b/searchlib/src/vespa/searchlib/fef/test/CMakeLists.txt
index dd9ea8828c9..c24d1906873 100644
--- a/searchlib/src/vespa/searchlib/fef/test/CMakeLists.txt
+++ b/searchlib/src/vespa/searchlib/fef/test/CMakeLists.txt
@@ -1,6 +1,7 @@
# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
vespa_add_library(searchlib_fef_test OBJECT
SOURCES
+ as_tensor.cpp
dummy_dependency_handler.cpp
featuretest.cpp
ftlib.cpp
diff --git a/searchlib/src/vespa/searchlib/fef/test/as_tensor.cpp b/searchlib/src/vespa/searchlib/fef/test/as_tensor.cpp
new file mode 100644
index 00000000000..f71973469fb
--- /dev/null
+++ b/searchlib/src/vespa/searchlib/fef/test/as_tensor.cpp
@@ -0,0 +1,57 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include <vespa/fastos/fastos.h>
+#include "as_tensor.h"
+#include <vespa/vespalib/testkit/test_kit.h>
+#include <vespa/vespalib/tensor/default_tensor_engine.h>
+#include <vespa/vespalib/tensor/tensor.h>
+#include <vespa/vespalib/tensor/tensor_mapper.h>
+#include <vespa/vespalib/eval/function.h>
+#include <iostream>
+
+using vespalib::eval::Function;
+using vespalib::tensor::DefaultTensorEngine;
+using vespalib::tensor::TensorType;
+using vespalib::tensor::TensorMapper;
+
+namespace search {
+namespace fef {
+namespace test {
+
+AsTensor::AsTensor(const vespalib::string &expr)
+ : ifun(DefaultTensorEngine::ref(), Function::parse(expr)), ctx(), result(&ifun.eval(ctx))
+{
+ ASSERT_TRUE(result->is_tensor());
+ tensor = static_cast<const Tensor *>(result->as_tensor());
+}
+
+AsTensor::~AsTensor()
+{
+}
+
+bool AsTensor::operator==(const Tensor &rhs) const {
+ return tensor->equals(rhs);
+};
+
+AsEmptyTensor::AsEmptyTensor(const vespalib::string &type)
+ : AsTensor("{ }"),
+ mappedTensor(TensorMapper(TensorType::fromSpec(type)).map(*tensor))
+{
+}
+
+AsEmptyTensor::~AsEmptyTensor()
+{
+}
+
+bool AsEmptyTensor::operator==(const Tensor &rhs) const {
+ return mappedTensor->equals(rhs);
+}
+
+std::ostream &operator<<(std::ostream &os, const AsTensor &my_tensor) {
+ os << my_tensor.result->as_tensor();
+ return os;
+}
+
+} // search::fef::test
+} // search::fef
+} // search
diff --git a/searchlib/src/vespa/searchlib/fef/test/as_tensor.h b/searchlib/src/vespa/searchlib/fef/test/as_tensor.h
new file mode 100644
index 00000000000..3ce930ca5c0
--- /dev/null
+++ b/searchlib/src/vespa/searchlib/fef/test/as_tensor.h
@@ -0,0 +1,40 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#pragma once
+
+#include <iosfwd>
+#include <vespa/vespalib/eval/interpreted_function.h>
+
+namespace vespalib {
+namespace eval { struct Value; }
+namespace tensor { struct Tensor; }
+}
+
+namespace search {
+namespace fef {
+namespace test {
+
+struct AsTensor {
+ using InterpretedFunction = vespalib::eval::InterpretedFunction;
+ using Value = vespalib::eval::Value;
+ using Tensor = vespalib::tensor::Tensor;
+ InterpretedFunction ifun;
+ InterpretedFunction::Context ctx;
+ const Value *result;
+ const Tensor *tensor;
+ explicit AsTensor(const vespalib::string &expr);
+ ~AsTensor();
+ bool operator==(const Tensor &rhs) const;
+};
+
+struct AsEmptyTensor : public AsTensor {
+ std::unique_ptr<Tensor> mappedTensor;
+ AsEmptyTensor(const vespalib::string &type);
+ ~AsEmptyTensor();
+ bool operator==(const Tensor &rhs) const;
+};
+
+std::ostream &operator<<(std::ostream &os, const AsTensor &my_tensor);
+
+} // search::fef::test
+} // search::fef
+} // search
diff --git a/searchlib/src/vespa/searchlib/fef/test/indexenvironment.cpp b/searchlib/src/vespa/searchlib/fef/test/indexenvironment.cpp
index fa2e2102311..59903668fdb 100644
--- a/searchlib/src/vespa/searchlib/fef/test/indexenvironment.cpp
+++ b/searchlib/src/vespa/searchlib/fef/test/indexenvironment.cpp
@@ -11,11 +11,22 @@ namespace search {
namespace fef {
namespace test {
+using vespalib::eval::ValueType;
+using vespalib::eval::ErrorValue;
+
+namespace {
+
+IndexEnvironment::Constant notFoundError(ValueType::error_type(),
+ std::make_unique<ErrorValue>());
+
+}
+
IndexEnvironment::IndexEnvironment() :
_properties(),
_fields(),
_attrMan(),
- _tableMan()
+ _tableMan(),
+ _constants()
{
}
@@ -37,6 +48,29 @@ IndexEnvironment::getFieldByName(const string &name) const
return NULL;
}
+
+vespalib::eval::ConstantValue::UP
+IndexEnvironment::getConstantValue(const vespalib::string &name) const
+{
+ auto it = _constants.find(name);
+ if (it != _constants.end()) {
+ return std::make_unique<ConstantRef>(it->second);
+ } else {
+ return std::make_unique<ConstantRef>(notFoundError);
+ }
+}
+
+void
+IndexEnvironment::addConstantValue(const vespalib::string &name,
+ vespalib::eval::ValueType type,
+ std::unique_ptr<vespalib::eval::Value> value)
+{
+ auto insertRes = _constants.emplace(name,
+ Constant(std::move(type),
+ std::move(value)));
+ assert(insertRes.second); // successful insert
+}
+
} // namespace test
} // namespace fef
} // namespace search
diff --git a/searchlib/src/vespa/searchlib/fef/test/indexenvironment.h b/searchlib/src/vespa/searchlib/fef/test/indexenvironment.h
index 98a8349ebef..4edf07b9525 100644
--- a/searchlib/src/vespa/searchlib/fef/test/indexenvironment.h
+++ b/searchlib/src/vespa/searchlib/fef/test/indexenvironment.h
@@ -20,6 +20,34 @@ namespace test {
class IndexEnvironment : public IIndexEnvironment
{
public:
+ struct Constant : vespalib::eval::ConstantValue {
+ vespalib::eval::ValueType _type;
+ std::unique_ptr<vespalib::eval::Value> _value;
+ Constant(vespalib::eval::ValueType type,
+ std::unique_ptr<vespalib::eval::Value> value)
+ : _type(std::move(type)), _value(std::move(value))
+ { }
+ Constant(Constant &&rhs)
+ : _type(std::move(rhs._type)),
+ _value(std::move(rhs._value))
+ {
+ }
+ const vespalib::eval::ValueType &type() const override { return _type; }
+ const vespalib::eval::Value &value() const override { return *_value; }
+ ~Constant() { }
+ };
+
+ struct ConstantRef : vespalib::eval::ConstantValue {
+ const Constant &_value;
+ ConstantRef(const Constant &value)
+ : _value(value)
+ { }
+ const vespalib::eval::ValueType &type() const override { return _value.type(); }
+ const vespalib::eval::Value &value() const override { return _value.value(); }
+ ~ConstantRef() { }
+ };
+
+ using ConstantsMap = std::map<vespalib::string, Constant>;
/**
* Constructs a new index environment.
*/
@@ -67,9 +95,11 @@ public:
/** Returns a reference to the table manager of this. */
TableManager &getTableManager() { return _tableMan; }
- virtual vespalib::eval::ConstantValue::UP getConstantValue(const vespalib::string &) const override {
- return vespalib::eval::ConstantValue::UP();
- }
+ virtual vespalib::eval::ConstantValue::UP getConstantValue(const vespalib::string &name) const override;
+
+ void addConstantValue(const vespalib::string &name,
+ vespalib::eval::ValueType type,
+ std::unique_ptr<vespalib::eval::Value> value);
private:
IndexEnvironment(const IndexEnvironment &); // hide
@@ -80,6 +110,7 @@ private:
std::vector<FieldInfo> _fields;
AttributeManager _attrMan;
TableManager _tableMan;
+ ConstantsMap _constants;
};
} // namespace test