diff options
Diffstat (limited to 'eval/src/tests/tensor/dense_tensor_builder/dense_tensor_builder_test.cpp')
-rw-r--r-- | eval/src/tests/tensor/dense_tensor_builder/dense_tensor_builder_test.cpp | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/eval/src/tests/tensor/dense_tensor_builder/dense_tensor_builder_test.cpp b/eval/src/tests/tensor/dense_tensor_builder/dense_tensor_builder_test.cpp new file mode 100644 index 00000000000..5036f247db3 --- /dev/null +++ b/eval/src/tests/tensor/dense_tensor_builder/dense_tensor_builder_test.cpp @@ -0,0 +1,251 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include <vespa/vespalib/test/insertion_operators.h> +#include <vespa/vespalib/testkit/test_kit.h> +#include <vespa/vespalib/tensor/dense/dense_tensor_builder.h> +#include <vespa/vespalib/util/exceptions.h> + +using namespace vespalib::tensor; +using vespalib::IllegalArgumentException; +using Builder = DenseTensorBuilder; +using vespalib::eval::TensorSpec; +using vespalib::eval::ValueType; + +void +assertTensor(const std::vector<ValueType::Dimension> &expDims, + const DenseTensor::Cells &expCells, + const Tensor &tensor) +{ + const DenseTensor &realTensor = dynamic_cast<const DenseTensor &>(tensor); + EXPECT_EQUAL(ValueType::tensor_type(expDims), realTensor.type()); + EXPECT_EQUAL(expCells, realTensor.cells()); +} + +void +assertTensorSpec(const TensorSpec &expSpec, const Tensor &tensor) +{ + TensorSpec actSpec = tensor.toSpec(); + EXPECT_EQUAL(expSpec, actSpec); +} + +struct Fixture +{ + Builder builder; +}; + +Tensor::UP +build1DTensor(Builder &builder) +{ + Builder::Dimension dimX = builder.defineDimension("x", 3); + builder.addLabel(dimX, 0).addCell(10). + addLabel(dimX, 1).addCell(11). + addLabel(dimX, 2).addCell(12); + return builder.build(); +} + +TEST_F("require that 1d tensor can be constructed", Fixture) +{ + assertTensor({{"x",3}}, {10,11,12}, *build1DTensor(f.builder)); +} + +TEST_F("require that 1d tensor can be converted to tensor spec", Fixture) +{ + assertTensorSpec(TensorSpec("tensor(x[3])"). + add({{"x", 0}}, 10). + add({{"x", 1}}, 11). + add({{"x", 2}}, 12), + *build1DTensor(f.builder)); +} + +Tensor::UP +build2DTensor(Builder &builder) +{ + Builder::Dimension dimX = builder.defineDimension("x", 3); + Builder::Dimension dimY = builder.defineDimension("y", 2); + builder.addLabel(dimX, 0).addLabel(dimY, 0).addCell(10). + addLabel(dimX, 0).addLabel(dimY, 1).addCell(11). + addLabel(dimX, 1).addLabel(dimY, 0).addCell(12). + addLabel(dimX, 1).addLabel(dimY, 1).addCell(13). + addLabel(dimX, 2).addLabel(dimY, 0).addCell(14). + addLabel(dimX, 2).addLabel(dimY, 1).addCell(15); + return builder.build(); +} + +TEST_F("require that 2d tensor can be constructed", Fixture) +{ + assertTensor({{"x",3},{"y",2}}, {10,11,12,13,14,15}, *build2DTensor(f.builder)); +} + +TEST_F("require that 2d tensor can be converted to tensor spec", Fixture) +{ + assertTensorSpec(TensorSpec("tensor(x[3],y[2])"). + add({{"x", 0},{"y", 0}}, 10). + add({{"x", 0},{"y", 1}}, 11). + add({{"x", 1},{"y", 0}}, 12). + add({{"x", 1},{"y", 1}}, 13). + add({{"x", 2},{"y", 0}}, 14). + add({{"x", 2},{"y", 1}}, 15), + *build2DTensor(f.builder)); +} + +TEST_F("require that 3d tensor can be constructed", Fixture) +{ + Builder::Dimension dimX = f.builder.defineDimension("x", 3); + Builder::Dimension dimY = f.builder.defineDimension("y", 2); + Builder::Dimension dimZ = f.builder.defineDimension("z", 2); + f.builder.addLabel(dimX, 0).addLabel(dimY, 0).addLabel(dimZ, 0).addCell(10). + addLabel(dimX, 0).addLabel(dimY, 0).addLabel(dimZ, 1).addCell(11). + addLabel(dimX, 0).addLabel(dimY, 1).addLabel(dimZ, 0).addCell(12). + addLabel(dimX, 0).addLabel(dimY, 1).addLabel(dimZ, 1).addCell(13). + addLabel(dimX, 1).addLabel(dimY, 0).addLabel(dimZ, 0).addCell(14). + addLabel(dimX, 1).addLabel(dimY, 0).addLabel(dimZ, 1).addCell(15). + addLabel(dimX, 1).addLabel(dimY, 1).addLabel(dimZ, 0).addCell(16). + addLabel(dimX, 1).addLabel(dimY, 1).addLabel(dimZ, 1).addCell(17). + addLabel(dimX, 2).addLabel(dimY, 0).addLabel(dimZ, 0).addCell(18). + addLabel(dimX, 2).addLabel(dimY, 0).addLabel(dimZ, 1).addCell(19). + addLabel(dimX, 2).addLabel(dimY, 1).addLabel(dimZ, 0).addCell(20). + addLabel(dimX, 2).addLabel(dimY, 1).addLabel(dimZ, 1).addCell(21); + assertTensor({{"x",3},{"y",2},{"z",2}}, + {10,11,12,13,14,15,16,17,18,19,20,21}, + *f.builder.build()); +} + +TEST_F("require that cells get default value 0 if not specified", Fixture) +{ + Builder::Dimension dimX = f.builder.defineDimension("x", 3); + f.builder.addLabel(dimX, 1).addCell(11); + assertTensor({{"x",3}}, {0,11,0}, + *f.builder.build()); +} + +TEST_F("require that labels can be added in arbitrarily order", Fixture) +{ + Builder::Dimension dimX = f.builder.defineDimension("x", 2); + Builder::Dimension dimY = f.builder.defineDimension("y", 3); + f.builder.addLabel(dimY, 0).addLabel(dimX, 1).addCell(10); + assertTensor({{"x",2},{"y",3}}, {0,0,0,10,0,0}, + *f.builder.build()); +} + +TEST_F("require that builder can be re-used", Fixture) +{ + { + Builder::Dimension dimX = f.builder.defineDimension("x", 2); + f.builder.addLabel(dimX, 0).addCell(10). + addLabel(dimX, 1).addCell(11); + assertTensor({{"x",2}}, {10,11}, + *f.builder.build()); + } + { + Builder::Dimension dimY = f.builder.defineDimension("y", 3); + f.builder.addLabel(dimY, 0).addCell(20). + addLabel(dimY, 1).addCell(21). + addLabel(dimY, 2).addCell(22); + assertTensor({{"y",3}}, {20,21,22}, + *f.builder.build()); + } +} + +void +assertTensorCell(const std::vector<size_t> &expAddress, + double expCell, + const DenseTensor::CellsIterator &itr) +{ + EXPECT_TRUE(itr.valid()); + EXPECT_EQUAL(expAddress, itr.address()); + EXPECT_EQUAL(expCell, itr.cell()); +} + +TEST_F("require that dense tensor cells iterator works for 1d tensor", Fixture) +{ + Tensor::UP tensor; + { + Builder::Dimension dimX = f.builder.defineDimension("x", 2); + f.builder.addLabel(dimX, 0).addCell(2). + addLabel(dimX, 1).addCell(3); + tensor = f.builder.build(); + } + + const DenseTensor &denseTensor = dynamic_cast<const DenseTensor &>(*tensor); + DenseTensor::CellsIterator itr = denseTensor.cellsIterator(); + + assertTensorCell({0}, 2, itr); + itr.next(); + assertTensorCell({1}, 3, itr); + itr.next(); + EXPECT_FALSE(itr.valid()); +} + +TEST_F("require that dense tensor cells iterator works for 2d tensor", Fixture) +{ + Tensor::UP tensor; + { + Builder::Dimension dimX = f.builder.defineDimension("x", 2); + Builder::Dimension dimY = f.builder.defineDimension("y", 2); + f.builder.addLabel(dimX, 0).addLabel(dimY, 0).addCell(2). + addLabel(dimX, 0).addLabel(dimY, 1).addCell(3). + addLabel(dimX, 1).addLabel(dimY, 0).addCell(5). + addLabel(dimX, 1).addLabel(dimY, 1).addCell(7); + tensor = f.builder.build(); + } + + const DenseTensor &denseTensor = dynamic_cast<const DenseTensor &>(*tensor); + DenseTensor::CellsIterator itr = denseTensor.cellsIterator(); + + assertTensorCell({0,0}, 2, itr); + itr.next(); + assertTensorCell({0,1}, 3, itr); + itr.next(); + assertTensorCell({1,0}, 5, itr); + itr.next(); + assertTensorCell({1,1}, 7, itr); + itr.next(); + EXPECT_FALSE(itr.valid()); +} + +TEST_F("require that undefined label for a dimension throws exception", Fixture) +{ + Builder::Dimension dimX = f.builder.defineDimension("x", 2); + f.builder.defineDimension("y", 3); + EXPECT_EXCEPTION(f.builder.addLabel(dimX, 0).addCell(10), + IllegalArgumentException, + "Label for dimension 'y' is undefined. Expected a value in the range [0, 3>"); +} + +TEST_F("require that label outside range throws exception", Fixture) +{ + Builder::Dimension dimX = f.builder.defineDimension("x", 2); + EXPECT_EXCEPTION(f.builder.addLabel(dimX, 2).addCell(10), + IllegalArgumentException, + "Label '2' for dimension 'x' is outside range [0, 2>"); +} + +TEST_F("require that already specified label throws exception", Fixture) +{ + Builder::Dimension dimX = f.builder.defineDimension("x", 2); + EXPECT_EXCEPTION(f.builder.addLabel(dimX, 0).addLabel(dimX, 1).addCell(10), + IllegalArgumentException, + "Label for dimension 'x' is already specified with value '0'"); +} + +TEST_F("require that dimensions are sorted", Fixture) +{ + Builder::Dimension dimY = f.builder.defineDimension("y", 3); + Builder::Dimension dimX = f.builder.defineDimension("x", 5); + f.builder.addLabel(dimX, 0).addLabel(dimY, 0).addCell(10); + f.builder.addLabel(dimX, 0).addLabel(dimY, 1).addCell(11); + f.builder.addLabel(dimX, 1).addLabel(dimY, 0).addCell(12); + std::unique_ptr<Tensor> tensor = f.builder.build(); + const DenseTensor &denseTensor = dynamic_cast<const DenseTensor &>(*tensor); + assertTensor({{"x", 5}, {"y", 3}}, + {10, 11, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + denseTensor); + EXPECT_EQUAL("tensor(x[5],y[3])", denseTensor.getType().to_spec()); +} + + + + + + +TEST_MAIN() { TEST_RUN_ALL(); } |