summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArne Juul <arnej@verizonmedia.com>2020-10-01 08:35:26 +0000
committerArne Juul <arnej@verizonmedia.com>2020-10-02 12:08:37 +0000
commit592fdfa0c1250c5b7533a82db6a40799f5891f17 (patch)
treedbb285d468e1e722f4d68690f0fd3fa03b93ef43
parentc860aff674ea5581ea168ccfb640b535ee625be2 (diff)
add test for GenericMerge instruction
-rw-r--r--eval/CMakeLists.txt1
-rw-r--r--eval/src/tests/instruction/generic_merge/CMakeLists.txt9
-rw-r--r--eval/src/tests/instruction/generic_merge/generic_merge_test.cpp82
3 files changed, 92 insertions, 0 deletions
diff --git a/eval/CMakeLists.txt b/eval/CMakeLists.txt
index 03a19b8c2c4..1872ee1410a 100644
--- a/eval/CMakeLists.txt
+++ b/eval/CMakeLists.txt
@@ -33,6 +33,7 @@ vespa_define_module(
src/tests/eval/value_type
src/tests/gp/ponder_nov2017
src/tests/instruction/generic_join
+ src/tests/instruction/generic_merge
src/tests/instruction/generic_rename
src/tests/tensor/default_value_builder_factory
src/tests/tensor/dense_add_dimension_optimizer
diff --git a/eval/src/tests/instruction/generic_merge/CMakeLists.txt b/eval/src/tests/instruction/generic_merge/CMakeLists.txt
new file mode 100644
index 00000000000..154b04cb32f
--- /dev/null
+++ b/eval/src/tests/instruction/generic_merge/CMakeLists.txt
@@ -0,0 +1,9 @@
+# Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(eval_generic_merge_test_app TEST
+ SOURCES
+ generic_merge_test.cpp
+ DEPENDS
+ vespaeval
+ GTest::GTest
+)
+vespa_add_test(NAME eval_generic_merge_test_app COMMAND eval_generic_merge_test_app)
diff --git a/eval/src/tests/instruction/generic_merge/generic_merge_test.cpp b/eval/src/tests/instruction/generic_merge/generic_merge_test.cpp
new file mode 100644
index 00000000000..501d5410b87
--- /dev/null
+++ b/eval/src/tests/instruction/generic_merge/generic_merge_test.cpp
@@ -0,0 +1,82 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include <vespa/eval/eval/simple_value.h>
+#include <vespa/eval/eval/value_codec.h>
+#include <vespa/eval/instruction/generic_merge.h>
+#include <vespa/eval/eval/interpreted_function.h>
+#include <vespa/eval/eval/test/tensor_model.hpp>
+#include <vespa/vespalib/util/stringfmt.h>
+#include <vespa/vespalib/gtest/gtest.h>
+#include <optional>
+
+using namespace vespalib;
+using namespace vespalib::eval;
+using namespace vespalib::eval::instruction;
+using namespace vespalib::eval::test;
+
+using vespalib::make_string_short::fmt;
+
+std::vector<Layout> merge_layouts = {
+ {}, {},
+ {x(5)}, {x(5)},
+ {x(3),y(5)}, {x(3),y(5)},
+ float_cells({x(3),y(5)}), {x(3),y(5)},
+ {x(3),y(5)}, float_cells({x(3),y(5)}),
+ {x({"a","b","c"})}, {x({"a","b","c"})},
+ {x({"a","b","c"})}, {x({"c","d","e"})},
+ {x({"a","c","e"})}, {x({"b","c","d"})},
+ {x({"b","c","d"})}, {x({"a","c","e"})},
+ {x({"a","b","c"})}, {x({"c","d"})},
+ {x({"a","b"}),y({"foo","bar","baz"})}, {x({"b","c"}),y({"any","foo","bar"})},
+ {x(3),y({"foo", "bar"})}, {x(3),y({"baz", "bar"})},
+ {x({"a","b","c"}),y(5)}, {x({"b","c","d"}),y(5)}
+};
+
+
+TensorSpec reference_merge(const TensorSpec &a, const TensorSpec &b, join_fun_t fun) {
+ ValueType res_type = ValueType::merge(ValueType::from_spec(a.type()),
+ ValueType::from_spec(b.type()));
+ EXPECT_FALSE(res_type.is_error());
+ TensorSpec result(res_type.to_spec());
+ for (const auto &cell: a.cells()) {
+ auto other = b.cells().find(cell.first);
+ if (other == b.cells().end()) {
+ result.add(cell.first, cell.second);
+ } else {
+ result.add(cell.first, fun(cell.second, other->second));
+ }
+ }
+ for (const auto &cell: b.cells()) {
+ auto other = a.cells().find(cell.first);
+ if (other == a.cells().end()) {
+ result.add(cell.first, cell.second);
+ }
+ }
+ return result;
+}
+
+TensorSpec perform_generic_merge(const TensorSpec &a, const TensorSpec &b, join_fun_t fun) {
+ Stash stash;
+ const auto &factory = SimpleValueBuilderFactory::get();
+ auto lhs = value_from_spec(a, factory);
+ auto rhs = value_from_spec(b, factory);
+ auto my_op = GenericMerge::make_instruction(lhs->type(), rhs->type(), fun, factory, stash);
+ InterpretedFunction::EvalSingle single(my_op);
+ return spec_from_value(single.eval(std::vector<Value::CREF>({*lhs, *rhs})));
+}
+
+TEST(GenericMergeTest, generic_merge_works_for_simple_values) {
+ ASSERT_TRUE((merge_layouts.size() % 2) == 0);
+ for (size_t i = 0; i < merge_layouts.size(); i += 2) {
+ TensorSpec lhs = spec(merge_layouts[i], N());
+ TensorSpec rhs = spec(merge_layouts[i + 1], Div16(N()));
+ SCOPED_TRACE(fmt("\n===\nLHS: %s\nRHS: %s\n===\n", lhs.to_string().c_str(), rhs.to_string().c_str()));
+ for (auto fun: {operation::Add::f, operation::Mul::f, operation::Sub::f, operation::Max::f}) {
+ auto expect = reference_merge(lhs, rhs, fun);
+ auto actual = perform_generic_merge(lhs, rhs, fun);
+ EXPECT_EQ(actual, expect);
+ }
+ }
+}
+
+GTEST_MAIN_RUN_ALL_TESTS()