summaryrefslogtreecommitdiffstats
path: root/eval/src/tests/tensor/tensor_mapper/tensor_mapper_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'eval/src/tests/tensor/tensor_mapper/tensor_mapper_test.cpp')
-rw-r--r--eval/src/tests/tensor/tensor_mapper/tensor_mapper_test.cpp441
1 files changed, 216 insertions, 225 deletions
diff --git a/eval/src/tests/tensor/tensor_mapper/tensor_mapper_test.cpp b/eval/src/tests/tensor/tensor_mapper/tensor_mapper_test.cpp
index 8fede7e3d0b..6572ab1ed92 100644
--- a/eval/src/tests/tensor/tensor_mapper/tensor_mapper_test.cpp
+++ b/eval/src/tests/tensor/tensor_mapper/tensor_mapper_test.cpp
@@ -2,244 +2,235 @@
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/vespalib/util/stringfmt.h>
-#include <vespa/eval/tensor/sparse/sparse_tensor.h>
-#include <vespa/eval/tensor/sparse/sparse_tensor_builder.h>
-#include <vespa/eval/tensor/dense/dense_tensor.h>
-#include <vespa/eval/tensor/dense/dense_tensor_builder.h>
-#include <vespa/eval/tensor/types.h>
-#include <vespa/eval/tensor/tensor_factory.h>
#include <vespa/eval/tensor/tensor_mapper.h>
-#include <vespa/eval/tensor/default_tensor.h>
-#include <ostream>
+#include <vespa/eval/tensor/wrapped_simple_tensor.h>
+#include <vespa/eval/tensor/default_tensor_engine.h>
+#include <vespa/eval/eval/tensor_spec.h>
+#include <vespa/eval/eval/simple_tensor.h>
using vespalib::eval::ValueType;
+using vespalib::eval::TensorSpec;
+using vespalib::eval::SimpleTensor;
using namespace vespalib::tensor;
-namespace vespalib {
-namespace tensor {
+void verify_wrapped(const TensorSpec &source, const vespalib::string &type, const TensorSpec &expect) {
+ auto tensor = std::make_unique<WrappedSimpleTensor>(SimpleTensor::create(source));
+ auto mapped = TensorMapper::mapToWrapped(*tensor, ValueType::from_spec(type));
+ TensorSpec actual = mapped->toSpec();
+ EXPECT_EQUAL(actual, expect);
+}
+
+void verify(const TensorSpec &source, const vespalib::string &type, const TensorSpec &expect) {
+ auto tensor = DefaultTensorEngine::ref().create(source);
+ const Tensor *tensor_impl = dynamic_cast<const Tensor *>(tensor.get());
+ ASSERT_TRUE(tensor_impl);
+ TensorMapper mapper(ValueType::from_spec(type));
+ auto mapped = mapper.map(*tensor_impl);
+ TensorSpec actual = mapped->toSpec();
+ EXPECT_EQUAL(actual, expect);
+ TEST_DO(verify_wrapped(source, type, expect));
+}
+
+TEST("require that sparse tensors can be mapped to sparse type") {
+ TEST_DO(verify(TensorSpec("tensor(x{},y{})")
+ .add({{"x","1"},{"y","1"}}, 1)
+ .add({{"x","2"},{"y","1"}}, 3)
+ .add({{"x","1"},{"y","2"}}, 5)
+ .add({{"x","2"},{"y","2"}}, 7),
+ "tensor(y{})",
+ TensorSpec("tensor(y{})")
+ .add({{"y","1"}}, 4)
+ .add({{"y","2"}}, 12)));
+
+ TEST_DO(verify(TensorSpec("tensor(x{},y{})")
+ .add({{"x","1"},{"y","1"}}, 1)
+ .add({{"x","2"},{"y","1"}}, 3)
+ .add({{"x","1"},{"y","2"}}, 5)
+ .add({{"x","2"},{"y","2"}}, 7),
+ "tensor(x{})",
+ TensorSpec("tensor(x{})")
+ .add({{"x","1"}}, 6)
+ .add({{"x","2"}}, 10)));
+}
+
+TEST("require that sparse tensors can be mapped to dense type") {
+ TEST_DO(verify(TensorSpec("tensor(x{},y{})")
+ .add({{"x","1"},{"y","0"}}, 1)
+ .add({{"x","2"},{"y","0"}}, 3)
+ .add({{"x","1"},{"y","1"}}, 5)
+ .add({{"x","2"},{"y","1"}}, 7),
+ "tensor(y[3])",
+ TensorSpec("tensor(y[3])")
+ .add({{"y",0}}, 4)
+ .add({{"y",1}}, 12)
+ .add({{"y",2}}, 0)));
+
+ TEST_DO(verify(TensorSpec("tensor(x{},y{})")
+ .add({{"x","1"},{"y","0x"}}, 1)
+ .add({{"x","2"},{"y",""}}, 3)
+ .add({{"x","1"},{"y","1"}}, 5)
+ .add({{"x","2"},{"y","10"}}, 7),
+ "tensor(y[3])",
+ TensorSpec("tensor(y[3])")
+ .add({{"y",0}}, 3)
+ .add({{"y",1}}, 5)
+ .add({{"y",2}}, 0)));
+
+ TEST_DO(verify(TensorSpec("tensor(x{},y{})")
+ .add({{"x","0"},{"y","0"}}, 1)
+ .add({{"x","1"},{"y","0"}}, 3)
+ .add({{"x","0"},{"y","1"}}, 5)
+ .add({{"x","10"},{"y","1"}}, 7),
+ "tensor(x[2],y[3])",
+ TensorSpec("tensor(x[2],y[3])")
+ .add({{"x",0},{"y",0}}, 1)
+ .add({{"x",0},{"y",1}}, 5)
+ .add({{"x",0},{"y",2}}, 0)
+ .add({{"x",1},{"y",0}}, 3)
+ .add({{"x",1},{"y",1}}, 0)
+ .add({{"x",1},{"y",2}}, 0)));
+}
-static bool operator==(const Tensor &lhs, const Tensor &rhs)
-{
- return lhs.equals(rhs);
+TEST("require that sparse tensors can be mapped to abstract dense type") {
+ TEST_DO(verify(TensorSpec("tensor(x{},y{})")
+ .add({{"x","0"},{"y","0"}}, 1)
+ .add({{"x","1"},{"y","0"}}, 3)
+ .add({{"x","0"},{"y","1"}}, 5)
+ .add({{"x","10"},{"y","1"}}, 7),
+ "tensor(x[2],y[])",
+ TensorSpec("tensor(x[2],y[2])")
+ .add({{"x",0},{"y",0}}, 1)
+ .add({{"x",0},{"y",1}}, 5)
+ .add({{"x",1},{"y",0}}, 3)
+ .add({{"x",1},{"y",1}}, 0)));
+
+ TEST_DO(verify(TensorSpec("tensor(x{},y{})")
+ .add({{"x","0"},{"y","0"}}, 1)
+ .add({{"x","1"},{"y","0"}}, 3)
+ .add({{"x","0"},{"y","1"}}, 5)
+ .add({{"x","2"},{"y","0"}}, 7),
+ "tensor(x[],y[])",
+ TensorSpec("tensor(x[3],y[2])")
+ .add({{"x",0},{"y",0}}, 1)
+ .add({{"x",0},{"y",1}}, 5)
+ .add({{"x",1},{"y",0}}, 3)
+ .add({{"x",1},{"y",1}}, 0)
+ .add({{"x",2},{"y",0}}, 7)
+ .add({{"x",2},{"y",1}}, 0)));
+
+ TEST_DO(verify(TensorSpec("tensor(x{},y{})")
+ .add({{"x","0"},{"y","0"}}, 1)
+ .add({{"x","1"},{"y","0"}}, 3)
+ .add({{"x","0"},{"y","1"}}, 5)
+ .add({{"x","10"},{"y","3"}}, 7),
+ "tensor(x[],y[3])",
+ TensorSpec("tensor(x[2],y[3])")
+ .add({{"x",0},{"y",0}}, 1)
+ .add({{"x",0},{"y",1}}, 5)
+ .add({{"x",0},{"y",2}}, 0)
+ .add({{"x",1},{"y",0}}, 3)
+ .add({{"x",1},{"y",1}}, 0)
+ .add({{"x",1},{"y",2}}, 0)));
}
+TEST("require that dense tensors can be mapped to sparse type") {
+ TEST_DO(verify(TensorSpec("tensor(x[2],y[2])")
+ .add({{"x",0},{"y",0}}, 1)
+ .add({{"x",0},{"y",1}}, 3)
+ .add({{"x",1},{"y",0}}, 5)
+ .add({{"x",1},{"y",1}}, 7),
+ "tensor(x{})",
+ TensorSpec("tensor(x{})")
+ .add({{"x","0"}}, 4)
+ .add({{"x","1"}}, 12)));
}
+
+TEST("require that mixed tensors can be mapped to sparse type") {
+ TEST_DO(verify(TensorSpec("tensor(x[2],y{})")
+ .add({{"x",0},{"y","0"}}, 1)
+ .add({{"x",0},{"y","1"}}, 3)
+ .add({{"x",1},{"y","0"}}, 5)
+ .add({{"x",1},{"y","1"}}, 7),
+ "tensor(x{})",
+ TensorSpec("tensor(x{})")
+ .add({{"x","0"}}, 4)
+ .add({{"x","1"}}, 12)));
+}
+
+TEST("require that mixed tensors can be mapped to dense type") {
+ TEST_DO(verify(TensorSpec("tensor(x[2],y{})")
+ .add({{"x",0},{"y","0"}}, 1)
+ .add({{"x",0},{"y","1"}}, 3)
+ .add({{"x",1},{"y","0"}}, 5)
+ .add({{"x",1},{"y","1"}}, 7),
+ "tensor(y[])",
+ TensorSpec("tensor(y[2])")
+ .add({{"y",0}}, 6)
+ .add({{"y",1}}, 10)));
+}
+
+TEST("require that mixed tensors can be mapped to mixed type") {
+ TEST_DO(verify(TensorSpec("tensor(x[2],y{})")
+ .add({{"x",0},{"y","0"}}, 1)
+ .add({{"x",0},{"y","1"}}, 3)
+ .add({{"x",1},{"y","0"}}, 5)
+ .add({{"x",1},{"y","1"}}, 7),
+ "tensor(x{},y[])",
+ TensorSpec("tensor(x{},y[2])")
+ .add({{"x","0"},{"y",0}}, 1)
+ .add({{"x","0"},{"y",1}}, 3)
+ .add({{"x","1"},{"y",0}}, 5)
+ .add({{"x","1"},{"y",1}}, 7)));
+}
+
+TEST("require that dense tensors can be mapped to mixed type") {
+ TEST_DO(verify(TensorSpec("tensor(x[2],y[2])")
+ .add({{"x",0},{"y",0}}, 1)
+ .add({{"x",0},{"y",1}}, 3)
+ .add({{"x",1},{"y",0}}, 5)
+ .add({{"x",1},{"y",1}}, 7),
+ "tensor(x{},y[])",
+ TensorSpec("tensor(x{},y[2])")
+ .add({{"x","0"},{"y",0}}, 1)
+ .add({{"x","0"},{"y",1}}, 3)
+ .add({{"x","1"},{"y",0}}, 5)
+ .add({{"x","1"},{"y",1}}, 7)));
}
-template <typename BuilderType>
-bool defaultBuilder() { return false; }
-
-template <>
-bool defaultBuilder<DefaultTensor::builder>() { return true; }
-
-template <typename BuilderType>
-struct TensorTFromBuilder;
-
-template <>
-struct TensorTFromBuilder<SparseTensorBuilder> {
- using TensorT = SparseTensor;
-};
-
-template <typename BuilderType>
-using TensorTFromBuilder_t = typename TensorTFromBuilder<BuilderType>::TensorT;
-
-struct FixtureBase
-{
- Tensor::UP createDenseTensor(const DenseTensorCells &cells) {
- return TensorFactory::createDense(cells);
- }
-};
-
-template <typename BuilderType>
-struct Fixture : public FixtureBase
-{
- BuilderType _builder;
- using TensorT = TensorTFromBuilder_t<BuilderType>;
- Fixture() : FixtureBase(), _builder() {}
-
- Tensor::UP createTensor(const TensorCells &cells,
- const TensorDimensions &dimensions) {
- return TensorFactory::create(cells, dimensions, _builder);
- }
-
- void assertSparseMapImpl(const Tensor &exp,
- const ValueType &tensorType,
- const Tensor &rhs, bool isDefaultBuilder)
- {
- EXPECT_TRUE(tensorType.is_sparse());
- if (isDefaultBuilder) {
- TensorMapper mapper(tensorType);
- std::unique_ptr<Tensor> mapped = mapper.map(rhs);
- EXPECT_TRUE(!!mapped);
- EXPECT_EQUAL(exp, *mapped);
- }
- std::unique_ptr<Tensor> mapped =
- TensorMapper::mapToSparse<TensorT>(rhs, tensorType);
- EXPECT_TRUE(!!mapped);
- EXPECT_EQUAL(exp, *mapped);
- }
-
- void assertDenseMapImpl(const Tensor &exp,
- const ValueType &tensorType,
- const Tensor &rhs)
- {
- EXPECT_TRUE(tensorType.is_dense());
- TensorMapper mapper(tensorType);
- std::unique_ptr<Tensor> mapped = mapper.map(rhs);
- EXPECT_TRUE(!!mapped);
- EXPECT_EQUAL(exp, *mapped);
- }
-
- void
- assertSparseMap(const TensorCells &expTensor,
- const TensorDimensions &expDimensions,
- const vespalib::string &typeSpec,
- const TensorCells &rhsTensor,
- const TensorDimensions &rhsDimensions)
- {
- assertSparseMapImpl(*createTensor(expTensor, expDimensions),
- ValueType::from_spec(typeSpec),
- *createTensor(rhsTensor, rhsDimensions),
- defaultBuilder<BuilderType>());
- }
-
- void
- assertDenseMap(const DenseTensorCells &expTensor,
- const vespalib::string &typeSpec,
- const TensorCells &rhsTensor,
- const TensorDimensions &rhsDimensions)
- {
- assertDenseMapImpl(*createDenseTensor(expTensor),
- ValueType::from_spec(typeSpec),
- *createTensor(rhsTensor, rhsDimensions));
- }
-};
-
-using SparseFixture = Fixture<SparseTensorBuilder>;
-
-template <typename FixtureType>
-void
-testTensorMapper(FixtureType &f)
-{
- TEST_DO(f.assertSparseMap({
- {{{"y","1"}}, 4},
- {{{"y","2"}}, 12}
- },
- { "y" },
- "tensor(y{})",
- {
- {{{"x","1"},{"y","1"}}, 1},
- {{{"x","2"},{"y","1"}}, 3},
- {{{"x","1"},{"y","2"}}, 5},
- {{{"x","2"},{"y","2"}}, 7}
- },
- { "x", "y" }));
- TEST_DO(f.assertSparseMap({
- {{{"x","1"}}, 6},
- {{{"x","2"}}, 10}
- },
- { "x" },
- "tensor(x{})",
- {
- {{{"x","1"},{"y","1"}}, 1},
- {{{"x","2"},{"y","1"}}, 3},
- {{{"x","1"},{"y","2"}}, 5},
- {{{"x","2"},{"y","2"}}, 7}
- },
- { "x", "y" }));
- TEST_DO(f.assertDenseMap({
- {{{"y",0}}, 4},
- {{{"y",1}}, 12},
- {{{"y",2}}, 0}
- },
- "tensor(y[3])",
- {
- {{{"x","1"},{"y","0"}}, 1},
- {{{"x","2"},{"y","0"}}, 3},
- {{{"x","1"},{"y","1"}}, 5},
- {{{"x","2"},{"y","1"}}, 7}
- },
- { "x", "y" }));
- TEST_DO(f.assertDenseMap({
- {{{"y",0}}, 3},
- {{{"y",1}}, 5},
- {{{"y",2}}, 0}
- },
- "tensor(y[3])",
- {
- {{{"x","1"},{"y","0x"}}, 1},
- {{{"x","2"},{"y",""}}, 3},
- {{{"x","1"},{"y","1"}}, 5},
- {{{"x","2"},{"y","10"}}, 7}
- },
- { "x", "y" }));
- TEST_DO(f.assertDenseMap({
- {{{"x",0},{"y",0}}, 1},
- {{{"x",0},{"y",1}}, 5},
- {{{"x",0},{"y",2}}, 0},
- {{{"x",1},{"y",0}}, 3},
- {{{"x",1},{"y",1}}, 0},
- {{{"x",1},{"y",2}}, 0}
- },
- "tensor(x[2], y[3])",
- {
- {{{"x","0"},{"y","0"}}, 1},
- {{{"x","1"},{"y","0"}}, 3},
- {{{"x","0"},{"y","1"}}, 5},
- {{{"x","10"},{"y","1"}}, 7}
- },
- { "x", "y" }));
- TEST_DO(f.assertDenseMap({
- {{{"x",0},{"y",0}}, 1},
- {{{"x",0},{"y",1}}, 5},
- {{{"x",1},{"y",0}}, 3},
- {{{"x",1},{"y",1}}, 0}
- },
- "tensor(x[2], y[])",
- {
- {{{"x","0"},{"y","0"}}, 1},
- {{{"x","1"},{"y","0"}}, 3},
- {{{"x","0"},{"y","1"}}, 5},
- {{{"x","10"},{"y","1"}}, 7}
- },
- { "x", "y" }));
- TEST_DO(f.assertDenseMap({
- {{{"x",0},{"y",0}}, 1},
- {{{"x",0},{"y",1}}, 5},
- {{{"x",1},{"y",0}}, 3},
- {{{"x",1},{"y",1}}, 0},
- {{{"x",2},{"y",0}}, 7},
- {{{"x",2},{"y",1}}, 0}
- },
- "tensor(x[], y[])",
- {
- {{{"x","0"},{"y","0"}}, 1},
- {{{"x","1"},{"y","0"}}, 3},
- {{{"x","0"},{"y","1"}}, 5},
- {{{"x","2"},{"y","0"}}, 7}
- },
- { "x", "y" }));
- TEST_DO(f.assertDenseMap({
- {{{"x",0},{"y",0}}, 1},
- {{{"x",0},{"y",1}}, 5},
- {{{"x",0},{"y",2}}, 0},
- {{{"x",1},{"y",0}}, 3},
- {{{"x",1},{"y",1}}, 0},
- {{{"x",1},{"y",2}}, 0}
- },
- "tensor(x[], y[3])",
- {
- {{{"x","0"},{"y","0"}}, 1},
- {{{"x","1"},{"y","0"}}, 3},
- {{{"x","0"},{"y","1"}}, 5},
- {{{"x","10"},{"y","3"}}, 7}
- },
- { "x", "y" }));
+TEST("require that sparse tensors can be mapped to mixed type") {
+ TEST_DO(verify(TensorSpec("tensor(x{},y{})")
+ .add({{"x","0"},{"y","0"}}, 1)
+ .add({{"x","0"},{"y","1"}}, 3)
+ .add({{"x","1"},{"y","0"}}, 5)
+ .add({{"x","1"},{"y","1"}}, 7),
+ "tensor(x[],y{})",
+ TensorSpec("tensor(x[2],y{})")
+ .add({{"x",0},{"y","0"}}, 1)
+ .add({{"x",0},{"y","1"}}, 3)
+ .add({{"x",1},{"y","0"}}, 5)
+ .add({{"x",1},{"y","1"}}, 7)));
}
-TEST_F("test tensor mapper for SparseTensor", SparseFixture)
-{
- testTensorMapper(f);
+TEST("require that missing dimensions are added appropriately") {
+ TEST_DO(verify(TensorSpec("tensor(x{})")
+ .add({{"x","foo"}}, 42),
+ "tensor(x{},y{})",
+ TensorSpec("tensor(x{},y{})")
+ .add({{"x","foo"},{"y",""}}, 42)));
+
+ TEST_DO(verify(TensorSpec("tensor(x[1])")
+ .add({{"x",0}}, 42),
+ "tensor(x[1],y[],z[2])",
+ TensorSpec("tensor(x[1],y[1],z[2])")
+ .add({{"x",0},{"y",0},{"z",0}}, 42)
+ .add({{"x",0},{"y",0},{"z",1}}, 0)));
+
+ TEST_DO(verify(TensorSpec("tensor(a{})")
+ .add({{"a","foo"}}, 42),
+ "tensor(a{},b[],c{},d[2])",
+ TensorSpec("tensor(a{},b[1],c{},d[2])")
+ .add({{"a","foo"},{"b",0},{"c",""},{"d",0}}, 42)
+ .add({{"a","foo"},{"b",0},{"c",""},{"d",1}}, 0)));
}
TEST_MAIN() { TEST_RUN_ALL(); }