summaryrefslogtreecommitdiffstats
path: root/eval/src/tests/tensor/tensor_serialization/tensor_serialization_test.cpp
blob: b43a127bc60537ed926bf91e6dbf8288ffe085fe (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/eval/tensor/sparse/sparse_tensor.h>
#include <vespa/eval/tensor/types.h>
#include <vespa/eval/tensor/default_tensor_engine.h>
#include <vespa/eval/tensor/serialization/typed_binary_format.h>
#include <vespa/eval/tensor/serialization/sparse_binary_format.h>
#include <vespa/vespalib/objects/nbostream.h>
#include <vespa/vespalib/objects/hexdump.h>
#include <ostream>
#include <vespa/eval/tensor/dense/dense_tensor_view.h>

using namespace vespalib::tensor;
using vespalib::eval::TensorSpec;
using vespalib::nbostream;
using ExpBuffer = std::vector<uint8_t>;

namespace std {

bool operator==(const std::vector<uint8_t> &exp, const nbostream &stream)
{
    return ((exp.size() == stream.size()) &&
            (memcmp(&exp[0], stream.peek(), exp.size()) == 0));
}

std::ostream &operator<<(std::ostream &out, const std::vector<uint8_t> &rhs)
{
    out << vespalib::HexDump(&rhs[0], rhs.size());
    return out;
}

}

//-----------------------------------------------------------------------------

template <typename T>
void verify_cells_only(const ExpBuffer &exp, const TensorSpec &spec) {
    nbostream input(&exp[0], exp.size());
    std::vector<T> cells;
    TypedBinaryFormat::deserializeCellsOnlyFromDenseTensors(input, cells);
    ASSERT_EQUAL(cells.size(), spec.cells().size());
    size_t i = 0;
    for (const auto &cell: spec.cells()) {
        EXPECT_EQUAL(cells[i++], cell.second.value);
    }
    ASSERT_EQUAL(i, cells.size());
}

void verify_serialized(const ExpBuffer &exp, const TensorSpec &spec) {
    auto &engine = DefaultTensorEngine::ref();
    auto value = engine.from_spec(spec);
    auto value_spec = engine.to_spec(*value);
    nbostream actual;
    engine.encode(*value, actual);
    EXPECT_EQUAL(exp, actual);
    auto decoded = engine.decode(actual);
    auto decoded_spec = engine.to_spec(*decoded);
    EXPECT_EQUAL(0u, actual.size());
    EXPECT_EQUAL(value_spec, decoded_spec);
    if (value->type().is_dense()) {
        TEST_DO(verify_cells_only<float>(exp, value_spec));
        TEST_DO(verify_cells_only<double>(exp, value_spec));
    }
}

//-----------------------------------------------------------------------------

TEST("test tensor serialization for SparseTensor") {
    TEST_DO(verify_serialized({ 0x01, 0x01, 0x01, 0x78, 0x00 },
                              TensorSpec("tensor(x{})")));
    TEST_DO(verify_serialized({ 0x01, 0x02, 0x01, 0x78, 0x01, 0x79, 0x00 },
                              TensorSpec("tensor(x{},y{})")));
    TEST_DO(verify_serialized({ 0x01, 0x01, 0x01, 0x78, 0x01, 0x01, 0x31, 0x40,
                                0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
                              TensorSpec("tensor(x{})")
                              .add({{"x", "1"}}, 3)));
    TEST_DO(verify_serialized({ 0x01, 0x02, 0x01, 0x78, 0x01, 0x79, 0x01, 0x00,
                                 0x00, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
                                 0x00 },
                              TensorSpec("tensor(x{},y{})")
                              .add({{"x", ""}, {"y", ""}}, 3)));
    TEST_DO(verify_serialized({ 0x01, 0x02, 0x01, 0x78, 0x01, 0x79, 0x01, 0x01,
                                0x31, 0x00, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00,
                                0x00, 0x00 },
                              TensorSpec("tensor(x{},y{})")
                              .add({{"x", "1"}, {"y", ""}}, 3)));
     TEST_DO(verify_serialized({ 0x01, 0x02, 0x01, 0x78, 0x01, 0x79, 0x01, 0x00,
                                  0x01, 0x33, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00,
                                  0x00, 0x00 },
                              TensorSpec("tensor(x{},y{})")
                              .add({{"x", ""}, {"y", "3"}}, 3)));
     TEST_DO(verify_serialized({ 0x01, 0x02, 0x01, 0x78, 0x01, 0x79, 0x01, 0x01,
                                 0x32, 0x01, 0x34, 0x40, 0x08, 0x00, 0x00, 0x00,
                                 0x00, 0x00, 0x00 },
                              TensorSpec("tensor(x{},y{})")
                              .add({{"x", "2"}, {"y", "4"}}, 3)));
     TEST_DO(verify_serialized({        0x01, 0x02, 0x01, 0x78, 0x01, 0x79,
                                        0x01, 0x01, 0x31, 0x00, 0x40, 0x08,
                                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
                              TensorSpec("tensor(x{},y{})")
                              .add({{"x", "1"}, {"y", ""}}, 3)));
}

TEST("test tensor serialization for DenseTensor") {
    TEST_DO(verify_serialized({0x02, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00},
                              TensorSpec("double")));
    TEST_DO(verify_serialized({0x02, 0x01, 0x01, 0x78, 0x01,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00},
                              TensorSpec("tensor(x[1])")
                              .add({{"x", 0}}, 0)));
    TEST_DO(verify_serialized({0x02, 0x02, 0x01, 0x78, 0x01,
                               0x01, 0x79, 0x01,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00},
                              TensorSpec("tensor(x[1],y[1])")
                              .add({{"x", 0}, {"y", 0}}, 0)));
    TEST_DO(verify_serialized({0x02, 0x01, 0x01, 0x78, 0x02,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x40, 0x08, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00},
                              TensorSpec("tensor(x[2])")
                              .add({{"x", 1}}, 3)));
    TEST_DO(verify_serialized({0x02, 0x02, 0x01, 0x78, 0x01,
                               0x01, 0x79, 0x01,
                               0x40, 0x08, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00},
                              TensorSpec("tensor(x[1],y[1])")
                              .add({{"x", 0}, {"y", 0}}, 3)));
    TEST_DO(verify_serialized({0x02, 0x02, 0x01, 0x78, 0x02,
                               0x01, 0x79, 0x01,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x40, 0x08, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00},
                              TensorSpec("tensor(x[2],y[1])")
                              .add({{"x", 1}, {"y", 0}}, 3)));
    TEST_DO(verify_serialized({0x02, 0x02, 0x01, 0x78, 0x01,
                               0x01, 0x79, 0x04,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x40, 0x08, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00},
                              TensorSpec("tensor(x[1],y[4])")
                              .add({{"x", 0}, {"y", 3}}, 3)));
    TEST_DO(verify_serialized({0x02, 0x02, 0x01, 0x78, 0x03,
                               0x01, 0x79, 0x05,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x40, 0x08, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00},
                              TensorSpec("tensor(x[3],y[5])")
                              .add({{"x", 2}, {"y", 4}}, 3)));
}

TEST("test 'float' cells") {
    TEST_DO(verify_serialized({0x06, 0x01, 0x02, 0x01, 0x78, 0x03,
                               0x01, 0x79, 0x05,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x00, 0x00, 0x00, 0x00,
                               0x40, 0x40, 0x00, 0x00 },
                              TensorSpec("tensor<float>(x[3],y[5])")
                              .add({{"x", 2}, {"y", 4}}, 3)));
}

TEST_MAIN() { TEST_RUN_ALL(); }