Added delimeter and settings constants to FileTape
Removed unneccesary copy and move constructors Added constructor for tmp FileTape Added Catch2 for unit testing Added example unit tests
This commit is contained in:
parent
cab1b88a77
commit
0e49b35f12
6 changed files with 157 additions and 25 deletions
|
@ -2,6 +2,7 @@
|
|||
#define FILE_TAPE_H
|
||||
|
||||
#include "tape.h"
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
@ -19,39 +20,68 @@ struct FileTapeSettings {
|
|||
unsigned int seek_backwards_delay_ms;
|
||||
};
|
||||
|
||||
const static struct FileTapeSettings DEFAULT_FT_SETTINGS =
|
||||
FileTapeSettings{.read_delay_ms = 0,
|
||||
.write_delay_ms = 0,
|
||||
.seek_forward_delay_ms = 0,
|
||||
.seek_backwards_delay_ms = 0};
|
||||
|
||||
const static char FT_DELIMETER = '\n';
|
||||
|
||||
/**
|
||||
* Mock tape implementation that uses text files as data source.
|
||||
*
|
||||
* Simulates tape operations by artificially pausing the execution of some
|
||||
* methods using time intervals, specified in command line arguments or a
|
||||
* configuration file. Each cell is represented as a seperate line in a file,
|
||||
* cell data is stored as plain text.
|
||||
* configuration file. Each cell is represented as a plain text 32-bit int
|
||||
* separated by FT_DELIMETER. End of the file tape is indicated either by EOF
|
||||
* or some arbitrary data that cannot be parsed to int32_t
|
||||
*/
|
||||
class FileTape : public Tape {
|
||||
private:
|
||||
std::fstream file;
|
||||
FileTapeSettings settings;
|
||||
size_t prev_line_pos = 0;
|
||||
bool at_first_line = false;
|
||||
|
||||
public:
|
||||
FileTape &operator=(const FileTape &) = delete;
|
||||
FileTape(const FileTape &) = delete;
|
||||
FileTape(FileTape &&) = delete;
|
||||
FileTape &operator=(FileTape &&) = delete;
|
||||
~FileTape() override;
|
||||
|
||||
/**
|
||||
* Initialize a new instance of FileTape that will open a file with the
|
||||
* specified name. File must be read and write accessible.
|
||||
* Initializes a new instance of FileTape that will open an existing file
|
||||
* with the specified name, already filled with data. File must be read and
|
||||
* write accessible.
|
||||
*
|
||||
* @param file_name Name of a file to be opened.
|
||||
* @param settings File tape settings
|
||||
* @param settings FileTape settings
|
||||
*/
|
||||
explicit FileTape(const std::string &file_name, FileTapeSettings settings);
|
||||
explicit FileTape(const std::string &file_name,
|
||||
FileTapeSettings settings = DEFAULT_FT_SETTINGS);
|
||||
|
||||
/**
|
||||
* Initializes a new instance of FileTape that will create and open a file
|
||||
* with the specified name, and write *size* zeroes into it.
|
||||
* File must not exist and directory must be write accessible.
|
||||
*
|
||||
* @param size Size of a newly created FileTpae
|
||||
* @param file_name Name of a file to be created and opened
|
||||
* @param settings FileTape settings
|
||||
*/
|
||||
explicit FileTape(size_t size, const std::string &file_name,
|
||||
FileTapeSettings settings = DEFAULT_FT_SETTINGS);
|
||||
|
||||
/**
|
||||
* Initializes a new instance of FileTape that will create and open a
|
||||
* temporary file, and write *size* zeroes into it.
|
||||
*
|
||||
* @param size Size of a newly created FileTape
|
||||
* @param settings FileTape settings
|
||||
*/
|
||||
explicit FileTape(size_t size,
|
||||
FileTapeSettings settings = DEFAULT_FT_SETTINGS);
|
||||
|
||||
/**
|
||||
* Advances the underlying fstream to a new line.
|
||||
*
|
||||
* @return false if EOF is reached, otherwise true.
|
||||
* @return false if empty line is reached, otherwise true.
|
||||
*/
|
||||
bool seek_forward() override;
|
||||
|
||||
|
|
|
@ -17,11 +17,11 @@ namespace tape {
|
|||
*/
|
||||
class Tape {
|
||||
public:
|
||||
Tape(const Tape &) = default;
|
||||
Tape(Tape &&) = default;
|
||||
Tape &operator=(const Tape &) = default;
|
||||
Tape &operator=(Tape &&) = default;
|
||||
Tape() = default;
|
||||
Tape(const Tape &) = default;
|
||||
Tape(Tape &&) = delete;
|
||||
Tape &operator=(const Tape &) = default;
|
||||
Tape &operator=(Tape &&) = delete;
|
||||
virtual ~Tape() = default;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,20 +1,41 @@
|
|||
#include "filetape.h"
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
tape::FileTape::FileTape(const std::string &file_name,
|
||||
FileTapeSettings settings)
|
||||
using tape::FileTape;
|
||||
|
||||
FileTape::FileTape(const std::string &file_name, FileTapeSettings settings)
|
||||
: settings(settings) {
|
||||
this->file = std::fstream(file_name);
|
||||
}
|
||||
|
||||
bool tape::FileTape::seek_forward() { return true; }
|
||||
FileTape::FileTape(size_t size, const std::string &file_name,
|
||||
FileTapeSettings settings)
|
||||
: FileTape(file_name, settings) {
|
||||
this->file << "0";
|
||||
for (int i = 0; i < size; i++) {
|
||||
this->file << FT_DELIMETER << "0";
|
||||
}
|
||||
}
|
||||
|
||||
bool tape::FileTape::seek_backwards() { return true; }
|
||||
FileTape::FileTape(size_t size, FileTapeSettings settings)
|
||||
: settings(settings) {
|
||||
std::array<char, L_tmpnam> file_name{};
|
||||
std::tmpnam(file_name.data());
|
||||
this->file = std::fstream(file_name.data());
|
||||
this->file << "0";
|
||||
for (int i = 0; i < size; i++) {
|
||||
this->file << FT_DELIMETER << "0";
|
||||
}
|
||||
}
|
||||
|
||||
int32_t tape::FileTape::read() { return 0; }
|
||||
bool FileTape::seek_forward() { return true; }
|
||||
|
||||
void tape::FileTape::write(int32_t data) {}
|
||||
bool FileTape::seek_backwards() { return true; }
|
||||
|
||||
tape::FileTape::~FileTape() { this->file.close(); }
|
||||
int32_t FileTape::read() { return 0; }
|
||||
|
||||
void FileTape::write(int32_t data) {}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
find_package(Catch2 3 REQUIRED)
|
||||
|
||||
add_executable(filetape_tests ${PROJECT_SOURCE_DIR}/tests/filetape_tests.cpp)
|
||||
target_link_libraries(filetape_tests PRIVATE tapelib)
|
||||
target_link_libraries(filetape_tests PRIVATE Catch2::Catch2WithMain)
|
||||
|
||||
add_test(filetape_tests filetape_tests)
|
||||
|
|
5
tests/assets/filetape_test_data.txt
Normal file
5
tests/assets/filetape_test_data.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
|
@ -1 +1,74 @@
|
|||
int main(int argc, char *argv[]) { return 0; }
|
||||
#include "filetape.h"
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <cstdio>
|
||||
|
||||
// NOLINTBEGIN(readability-function-cognitive-complexity)
|
||||
TEST_CASE("Reading data from a FileTape", "[filetape]") {
|
||||
tape::FileTape tape("assets/filetape_test_data.txt");
|
||||
|
||||
SECTION("Read all data sequentially") {
|
||||
REQUIRE(tape.read() == 1);
|
||||
REQUIRE(tape.seek_forward() == true);
|
||||
REQUIRE(tape.read() == 2);
|
||||
REQUIRE(tape.seek_forward() == true);
|
||||
REQUIRE(tape.read() == 3);
|
||||
REQUIRE(tape.seek_forward() == true);
|
||||
REQUIRE(tape.read() == 4);
|
||||
REQUIRE(tape.seek_forward() == true);
|
||||
REQUIRE(tape.read() == 5);
|
||||
}
|
||||
|
||||
SECTION("Read data non-sequentially") {
|
||||
REQUIRE(tape.read() == 1);
|
||||
REQUIRE(tape.seek_forward() == true);
|
||||
REQUIRE(tape.read() == 2);
|
||||
REQUIRE(tape.seek_backwards() == true);
|
||||
REQUIRE(tape.read() == 1);
|
||||
REQUIRE(tape.seek_forward() == true);
|
||||
REQUIRE(tape.seek_forward() == true);
|
||||
REQUIRE(tape.seek_forward() == true);
|
||||
REQUIRE(tape.read() == 4);
|
||||
REQUIRE(tape.seek_backwards() == true);
|
||||
REQUIRE(tape.seek_backwards() == true);
|
||||
REQUIRE(tape.read() == 2);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Seeking forward and backwards", "[filetape]") {
|
||||
tape::FileTape tape("assets/filetape_test_data.txt");
|
||||
|
||||
SECTION("Rewinding at the beginning of a file tape") {
|
||||
REQUIRE(tape.seek_backwards() == false);
|
||||
REQUIRE(tape.read() == 1);
|
||||
REQUIRE(tape.seek_forward() == true);
|
||||
REQUIRE(tape.read() == 2);
|
||||
REQUIRE(tape.seek_backwards() == true);
|
||||
REQUIRE(tape.seek_backwards() == false);
|
||||
REQUIRE(tape.read() == 1);
|
||||
}
|
||||
|
||||
SECTION("Seeking at the end of a file tape") {
|
||||
const int size = 5;
|
||||
// seek to end of a file tape
|
||||
for (int i = 0; i < size - 1; i++) {
|
||||
REQUIRE(tape.seek_forward() == true);
|
||||
}
|
||||
REQUIRE(tape.seek_forward() == false);
|
||||
REQUIRE(tape.read() == 5);
|
||||
REQUIRE(tape.seek_backwards() == true);
|
||||
REQUIRE(tape.read() == 4);
|
||||
REQUIRE(tape.seek_forward() == true);
|
||||
REQUIRE(tape.seek_forward() == false);
|
||||
REQUIRE(tape.read() == 5);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Writing to a file tape", "[filetape]") {
|
||||
// init a temp file to modify
|
||||
// std::string tmp_file_name = "/tmp/"
|
||||
// std::unique_ptr<std::FILE> tmp_file(std::tmpfile());
|
||||
// std::fstream tmp(tmp_file);
|
||||
// std::fstream tmp(tmp_file);
|
||||
// tape::FileTape tape("assets/filetape_test_data.txt");
|
||||
}
|
||||
// NOLINTEND(readability-function-cognitive-complexity)
|
||||
|
|
Loading…
Reference in a new issue