Newer
Older
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source
// & Institut Laue - Langevin
// SPDX - License - Identifier: GPL - 3.0 +
#ifndef MANTID_KERNEL_BINARYSTREAMREADERTEST_H_
#define MANTID_KERNEL_BINARYSTREAMREADERTEST_H_
#include <cxxtest/TestSuite.h>
#include <cxxtest/ValueTraits.h>
#include "MantidKernel/BinaryStreamReader.h"
#include "MantidKernel/Matrix.h"
using Mantid::Kernel::BinaryStreamReader;
using Mantid::Kernel::Matrix;
class BinaryStreamReaderTest : public CxxTest::TestSuite {
public:
// This pair of boilerplate methods prevent the suite being created statically
// This means the constructor isn't called when running other tests
static BinaryStreamReaderTest *createSuite() {
return new BinaryStreamReaderTest();
static void destroySuite(BinaryStreamReaderTest *suite) { delete suite; }
BinaryStreamReaderTest() : CxxTest::TestSuite(), m_bytes() {
void setUp() override { resetStreamToStart(); }
//----------------------------------------------------------------------------
// Successes cases
//----------------------------------------------------------------------------
void test_Constructor_With_Good_Stream_Does_Not_Touch_Stream() {
BinaryStreamReader reader(m_bytes);
TS_ASSERT_EQUALS(std::ios_base::beg, m_bytes.tellg());
doReadSingleValueTest<int16_t>(6, sizeof(int16_t));
}
void test_Read_int32_t_Gives_Correct_Value() {
moveStreamToPosition(10);
doReadSingleValueTest<int32_t>(580, sizeof(int32_t));
}
void test_Read_int64_t_Gives_Correct_Value() {
moveStreamToPosition(42);
doReadSingleValueTest<int64_t>(200, sizeof(int64_t));
}
void test_Read_float_Gives_Correct_Value() {
// Move to where a float should be
doReadSingleValueTest<float>(787.0f, sizeof(float));
}
void test_Read_double_Gives_Correct_Value() {
doReadSingleValueTest<double>(2.0, sizeof(double));
}
void test_Read_String_Gives_Expected_String() {
const size_t offset = sizeof(int32_t) + 6;
doReadSingleValueTest<std::string>("mantid", offset);
moveStreamToPosition(30);
const size_t nvals(3);
std::vector<int16_t> expectedValue{2, 0, 4};
doReadArrayValueTest(nvals, expectedValue, nvals * sizeof(int16_t));
}
void test_Read_Vector_int32_t() {
moveStreamToPosition(30);
const size_t nvals(3);
std::vector<int32_t> expectedValue{2, 4, 6};
doReadArrayValueTest(nvals, expectedValue, nvals * sizeof(int32_t));
}
void test_Read_Vector_int64_t() {
moveStreamToPosition(42);
std::vector<int64_t> expectedValue{200, 400, 600, 900};
const auto nvals(expectedValue.size());
doReadArrayValueTest(expectedValue.size(), expectedValue,
nvals * sizeof(int64_t));
}
void test_Read_Vector_float() {
moveStreamToPosition(74);
std::vector<float> expectedValue{0.0f, 5.0f, 10.0f};
const auto nvals(expectedValue.size());
doReadArrayValueTest(nvals, expectedValue, nvals * sizeof(float));
}
void test_Read_Vector_double() {
moveStreamToPosition(86);
std::vector<double> expectedValue{10.0, 15.0, 20.0, 25.0};
const auto nvals(expectedValue.size());
doReadArrayValueTest(nvals, expectedValue, nvals * sizeof(double));
}
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
void test_Read_Vector_String_In_Row_Major_Order() {
moveStreamToPosition(118);
BinaryStreamReader reader(m_bytes);
std::vector<std::string> expected{"abc", "def"}, value;
std::vector<int32_t> shape{2, 3};
reader.read(value, shape, BinaryStreamReader::MatrixOrdering::RowMajor);
TS_ASSERT_EQUALS(expected, value);
}
void test_Read_Vector_String_In_Column_Major_Order() {
moveStreamToPosition(118);
BinaryStreamReader reader(m_bytes);
std::vector<std::string> expected{"ace", "bdf"}, value;
std::vector<int32_t> shape{2, 3};
reader.read(value, shape, BinaryStreamReader::MatrixOrdering::ColumnMajor);
TS_ASSERT_EQUALS(expected, value);
}
void test_Read_Matrix_Float_In_RowMajor_Order() {
moveStreamToPosition(124);
BinaryStreamReader reader(m_bytes);
std::vector<int32_t> shape{2, 3};
Matrix<float> expected(shape[0], shape[1]);
expected[0][0] = 1.0f;
expected[0][1] = 2.0f;
expected[0][2] = 3.0f;
expected[1][0] = 4.0f;
expected[1][1] = 5.0f;
expected[1][2] = 6.0f;
Matrix<float> value;
reader.read(value, shape, BinaryStreamReader::MatrixOrdering::RowMajor);
TS_ASSERT_EQUALS(expected, value);
}
void test_Read_Matrix_Float_In_ColumnMajor_Order() {
moveStreamToPosition(124);
BinaryStreamReader reader(m_bytes);
std::vector<int32_t> shape{2, 3};
Matrix<float> expected(shape[0], shape[1]);
expected[0][0] = 1.0f;
expected[0][1] = 3.0f;
expected[0][2] = 5.0f;
expected[1][0] = 2.0f;
expected[1][1] = 4.0f;
expected[1][2] = 6.0f;
Matrix<float> value;
reader.read(value, shape, BinaryStreamReader::MatrixOrdering::ColumnMajor);
TS_ASSERT_EQUALS(expected, value);
}
void test_Read_Matrix_Double_In_RowMajor_Order() {
moveStreamToPosition(148);
BinaryStreamReader reader(m_bytes);
std::vector<int32_t> shape{2, 3};
Matrix<double> expected(shape[0], shape[1]);
expected[0][0] = 1.0;
expected[0][1] = 2.0;
expected[0][2] = 3.0;
expected[1][0] = 4.0;
expected[1][1] = 5.0;
expected[1][2] = 6.0;
Matrix<double> value;
reader.read(value, shape, BinaryStreamReader::MatrixOrdering::RowMajor);
TS_ASSERT_EQUALS(expected, value);
}
void test_Read_Matrix_Double_In_ColumnMajor_Order() {
moveStreamToPosition(148);
BinaryStreamReader reader(m_bytes);
std::vector<int32_t> shape{2, 3};
Matrix<double> expected(shape[0], shape[1]);
expected[0][0] = 1.0;
expected[0][1] = 3.0;
expected[0][2] = 5.0;
expected[1][0] = 2.0;
expected[1][1] = 4.0;
expected[1][2] = 6.0;
Matrix<double> value;
reader.read(value, shape, BinaryStreamReader::MatrixOrdering::ColumnMajor);
TS_ASSERT_EQUALS(expected, value);
}
// Only test this for a single type assuming it is the same for all
void test_Read_Vector_With_Bigger_Vector_Leaves_Size_Untouched() {
moveStreamToPosition(30);
BinaryStreamReader reader(m_bytes);
auto streamPosBeg = m_bytes.tellg();
std::vector<int32_t> values(nvals + 2, 0);
reader.read(values, nvals);
std::vector<int32_t> expectedValue{2, 4, 6, 0, 0};
TS_ASSERT_EQUALS(expectedValue, values);
TS_ASSERT_EQUALS(nvals + 2, values.size());
auto expectedStreamOffset = nvals * sizeof(int32_t);
TS_ASSERT_EQUALS(expectedStreamOffset, m_bytes.tellg() - streamPosBeg);
}
void test_Read_String_Of_Given_Size() {
BinaryStreamReader reader(m_bytes);
auto streamPosBeg = m_bytes.tellg();
std::string value;
reader.read(value, nchars);
TS_ASSERT_EQUALS(nchars, value.length());
TS_ASSERT_EQUALS("man", value);
TS_ASSERT_EQUALS(nchars, m_bytes.tellg() - streamPosBeg);
}
//----------------------------------------------------------------------------
// Failure cases
//----------------------------------------------------------------------------
void test_Stream_Marked_Not_Good_Throws_RuntimeError_On_Construction() {
// read will put it into a 'bad' state
int i(0);
TSM_ASSERT_THROWS("Expected a runtime_error when given a bad stream",
BinaryStreamReader reader(m_bytes),
const std::runtime_error &);
template <typename T>
void doReadSingleValueTest(T expectedValue, size_t expectedStreamOffset) {
BinaryStreamReader reader(m_bytes);
auto streamPosBeg = m_bytes.tellg();
T value;
reader >> value;
TS_ASSERT_EQUALS(expectedValue, value);
TS_ASSERT_EQUALS(expectedStreamOffset, m_bytes.tellg() - streamPosBeg);
}
template <typename T>
void doReadArrayValueTest(const size_t nvals,
const std::vector<T> &expectedValue,
size_t expectedStreamOffset) {
BinaryStreamReader reader(m_bytes);
auto streamPosBeg = m_bytes.tellg();
std::vector<T> values;
reader.read(values, nvals);
TS_ASSERT_EQUALS(expectedValue, values);
TS_ASSERT_EQUALS(nvals, values.size());
TS_ASSERT_EQUALS(expectedStreamOffset, m_bytes.tellg() - streamPosBeg);
}
void createTestStream() {
// int32_t + series of characters
int32_t length(6);
writeSingleValueToStream<int32_t>(m_bytes, length);
m_bytes.write("mantid", length);
// single int64_t
writeSingleValueToStream<int64_t>(m_bytes, 580);
// single float
writeSingleValueToStream<float>(m_bytes, 787.0f);
// single double
writeSingleValueToStream<double>(m_bytes, 2.0);
// vector int32_t
writeArrayValuesToStream<int32_t>(m_bytes, {2, 4, 6});
// vector int64_t
writeArrayValuesToStream<int64_t>(m_bytes, {200, 400, 600, 900});
// vector float
writeArrayValuesToStream<float>(m_bytes, {0.0f, 5.0f, 10.0f});
// vector double
writeArrayValuesToStream<double>(m_bytes, {10.0, 15.0, 20.0, 25.0});
// array of characters
m_bytes.write("abcdef", 6);
// matrix of floats
writeArrayValuesToStream<float>(m_bytes,
{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f});
// matrix of doubles
writeArrayValuesToStream<double>(m_bytes, {1.0, 2.0, 3.0, 4.0, 5.0, 6.0});
}
template <typename T> void writeSingleValueToStream(std::ostream &, T value) {
m_bytes.write(reinterpret_cast<const char *>(&value), sizeof(T));
}
template <typename T>
void writeArrayValuesToStream(std::ostream &,
std::initializer_list<T> values) {
auto length = values.size();
std::vector<T> asVector(values);
m_bytes.write(reinterpret_cast<const char *>(asVector.data()),
length * sizeof(T));
void resetStreamToStart() {
m_bytes.clear();
m_bytes.seekg(std::ios_base::beg);
}
/// Move the stream nbytes from the beginning
void moveStreamToPosition(size_t nbytes) {
}
};
#endif /* MANTID_KERNEL_BINARYSTREAMREADERTEST_H_ */