-
Sam Jenkins authoredSam Jenkins authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
BinaryFileTest.h 5.76 KiB
// 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 BINARYFILETEST_H_
#define BINARYFILETEST_H_
#include "MantidKernel/BinaryFile.h"
#include "MantidKernel/ConfigService.h"
#include "MantidKernel/System.h"
#include <cxxtest/TestSuite.h>
#include <sys/stat.h>
using namespace Mantid::Kernel;
using std::cout;
using std::runtime_error;
using std::size_t;
using std::vector;
//==========================================================================================
/// Make the code clearer by having this an explicit type
using PixelType = uint32_t;
/// Type for the DAS time of flight (data file)
using DasTofType = uint32_t;
/// Structure that matches the form in the binary event list.
struct DasEvent {
/// Time of flight.
DasTofType tof;
/// Pixel identifier as published by the DAS/DAE/DAQ.
PixelType pid;
};
/** Creates a dummy file with so many bytes */
static void MakeDummyFile(std::string filename, size_t num_bytes) {
std::vector<char> buffer(num_bytes);
for (size_t i = 0; i < num_bytes; i++) {
// Put 1,2,3 in 32-bit ints
if (i % 4 == 0)
buffer[i] = static_cast<char>(i / 4);
else
buffer[i] = 0;
}
std::ofstream myFile(filename.c_str(), std::ios::out | std::ios::binary);
myFile.write(buffer.data(), num_bytes);
myFile.close();
}
//==========================================================================================
class BinaryFileTest : public CxxTest::TestSuite {
private:
BinaryFile<DasEvent> file;
std::string dummy_file;
public:
static BinaryFileTest *createSuite() { return new BinaryFileTest(); }
static void destroySuite(BinaryFileTest *suite) { delete suite; }
BinaryFileTest() { dummy_file = "dummy.bin"; }
void testFileNotFound() {
TS_ASSERT_THROWS(file.open("nonexistentfile.dat"),
const std::invalid_argument &);
}
void testFileWrongSize() {
MakeDummyFile(dummy_file, 3);
TS_ASSERT_THROWS(file.open(dummy_file), const std::runtime_error &);
file.close();
Poco::File(dummy_file).remove();
}
void testOpen() {
MakeDummyFile(dummy_file, 20 * 8);
// If this throws, then the file does not exist.
file.open(dummy_file);
// Right size?
size_t num = 20;
TS_ASSERT_EQUALS(file.getNumElements(), num);
// Get it
std::vector<DasEvent> data;
TS_ASSERT_THROWS_NOTHING(data = file.loadAll());
TS_ASSERT_EQUALS(data.size(), num);
// Check the first event
TS_ASSERT_EQUALS(data.at(0).tof, 0);
TS_ASSERT_EQUALS(data.at(0).pid, 1);
// Check the last event
TS_ASSERT_EQUALS(data.at(num - 1).tof, 38);
TS_ASSERT_EQUALS(data.at(num - 1).pid, 39);
file.close();
Poco::File(dummy_file).remove();
}
void testLoadAllIntoVector() {
MakeDummyFile(dummy_file, 20 * 8);
file.open(dummy_file);
// Right size?
size_t num = 20;
TS_ASSERT_EQUALS(file.getNumElements(), num);
// Get it
std::vector<DasEvent> data;
TS_ASSERT_THROWS_NOTHING(data = file.loadAllIntoVector());
TS_ASSERT_EQUALS(data.size(), num);
// Check the first event
TS_ASSERT_EQUALS(data.at(0).tof, 0);
TS_ASSERT_EQUALS(data.at(0).pid, 1);
// Check the last event
TS_ASSERT_EQUALS(data.at(num - 1).tof, 38);
TS_ASSERT_EQUALS(data.at(num - 1).pid, 39);
file.close();
Poco::File(dummy_file).remove();
}
void testLoadInBlocks() {
MakeDummyFile(dummy_file, 20 * 8);
file.open(dummy_file);
// Right size?
size_t num = 20;
TS_ASSERT_EQUALS(file.getNumElements(), num);
// Get it
size_t block_size = 10;
auto data = std::make_unique<DasEvent[]>(block_size);
size_t loaded_size = file.loadBlock(data.get(), block_size);
// Yes, we loaded that amount
TS_ASSERT_EQUALS(loaded_size, block_size);
// Check the first event
TS_ASSERT_EQUALS(data[0].tof, 0);
TS_ASSERT_EQUALS(data[0].pid, 1);
// Now try to load a lot more - going past the end
block_size = 10;
data = std::make_unique<DasEvent[]>(block_size);
loaded_size = file.loadBlock(data.get(), block_size);
TS_ASSERT_EQUALS(loaded_size, 10);
// Check the last event
TS_ASSERT_EQUALS(data[9].tof, 38);
TS_ASSERT_EQUALS(data[9].pid, 39);
file.close();
Poco::File(dummy_file).remove();
}
void testLoadBlockAt() {
MakeDummyFile(dummy_file, 20 * 8);
file.open(dummy_file);
// Right size?
size_t num = 20;
TS_ASSERT_EQUALS(file.getNumElements(), num);
// Get it
size_t block_size = 10;
auto data = std::make_unique<DasEvent[]>(block_size);
size_t loaded_size = file.loadBlockAt(data.get(), 5, block_size);
// Yes, we loaded that amount
TS_ASSERT_EQUALS(loaded_size, block_size);
// The first event is at index 5
TS_ASSERT_EQUALS(data[0].tof, 10);
TS_ASSERT_EQUALS(data[0].pid, 11);
// Now try to load a lot more - going past the end
block_size = 10;
data = std::make_unique<DasEvent[]>(block_size);
loaded_size = file.loadBlock(data.get(), block_size);
TS_ASSERT_EQUALS(loaded_size, 5);
file.close();
Poco::File(dummy_file).remove();
}
void testCallingDestructorOnUnitializedObject() {
BinaryFile<DasEvent> file2;
}
void testReadingNotOpenFile() {
BinaryFile<DasEvent> file2;
std::vector<DasEvent> data;
DasEvent *buffer = nullptr;
TS_ASSERT_EQUALS(file2.getNumElements(), 0);
TS_ASSERT_THROWS(file2.loadAll(), const std::runtime_error &);
TS_ASSERT_THROWS(data = file2.loadAllIntoVector(),
const std::runtime_error &);
TS_ASSERT_THROWS(file2.loadBlock(buffer, 10), const std::runtime_error &);
}
};
#endif /*BINARYFILETEST_H_*/