Browse Source

* Implemented 'file' class

* Implemented 'file_events' for 'select'
master
bergmann 4 years ago
parent
commit
43f7862964
22 changed files with 933 additions and 31 deletions
  1. +1
    -0
      include/cppfs.h
  2. +0
    -2
      include/cppfs/config.h
  3. +1
    -7
      include/cppfs/directory/directory.h
  4. +0
    -18
      include/cppfs/directory/directory.inl
  5. +61
    -0
      include/cppfs/file/file.h
  6. +3
    -0
      include/cppfs/file/file.inl
  7. +102
    -0
      include/cppfs/file/file.linux.inl
  8. +15
    -0
      include/cppfs/file_events.h
  9. +59
    -0
      include/cppfs/file_events/fdset.h
  10. +63
    -0
      include/cppfs/file_events/fdset.inl
  11. +96
    -0
      include/cppfs/file_events/file_events.h
  12. +89
    -0
      include/cppfs/file_events/file_events.inl
  13. +68
    -0
      include/cppfs/file_events/select.h
  14. +114
    -0
      include/cppfs/file_events/select.inl
  15. +23
    -0
      include/cppfs/file_events/types.h
  16. +2
    -0
      include/cppfs/misc.h
  17. +20
    -4
      include/cppfs/misc/misc.h
  18. +26
    -0
      include/cppfs/misc/misc.inl
  19. +7
    -0
      include/cppfs/misc/misc.linux.inl
  20. +2
    -0
      test/cppfs/directory_tests.cpp
  21. +108
    -0
      test/cppfs/file_events_tests.cpp
  22. +73
    -0
      test/cppfs/file_tests.cpp

+ 1
- 0
include/cppfs.h View File

@@ -3,4 +3,5 @@
#include <cppfs/config.h>
#include <cppfs/directory.h>
#include <cppfs/file.h>
#include <cppfs/file_events.h>
#include <cppfs/path.h>

+ 0
- 2
include/cppfs/config.h View File

@@ -19,8 +19,6 @@ namespace cppfs
static constexpr char path_delimiter = '/';
static constexpr const char * temp_dir = "/tmp";
};

using fd_handle = int;
#endif

}

+ 1
- 7
include/cppfs/directory/directory.h View File

@@ -66,12 +66,6 @@ namespace cppfs
#endif
};

public:
/**
* @brief Get the default file permissions for directories.
*/
static inline const file_permissions& default_permissions();

private:
cppfs::path _path;

@@ -97,7 +91,7 @@ namespace cppfs
*/
inline const directory& create(
bool p_parent,
const file_permissions& p_perm = default_permissions()) const;
const file_permissions& p_perm = file_permissions::defaults()) const;

/**
* @brief Remove the directory (and all it's content if the parameter is set to true)


+ 0
- 18
include/cppfs/directory/directory.inl View File

@@ -9,24 +9,6 @@ namespace cppfs

/* directory */

const file_permissions& directory::default_permissions()
{
static const file_permissions value({
file_permission::user_read,
file_permission::user_write,
file_permission::user_execute,

file_permission::group_read,
file_permission::group_write,
file_permission::group_execute,

file_permission::others_read,
file_permission::others_execute,
});

return value;
}

template<typename... T_args>
directory::directory(T_args&&... p_args)
: _path(std::forward<T_args>(p_args)...)


+ 61
- 0
include/cppfs/file/file.h View File

@@ -2,13 +2,37 @@

#include <string>

#include <cppcore/misc/flags.h>

#include <cppfs/config.h>

#include "../path.h"
#include "../misc.h"

namespace cppfs
{

enum class access_mode
{
unknown = 0,
read_only,
write_only,
read_write,
};

enum class open_flag
{
unknown = 0,
create,
append,
truncate,
non_blocking,
};

using open_flags = cppcore::shifted_flags<open_flag>;

struct file
: public raw_handle
{
private:
cppfs::path _path;
@@ -20,6 +44,11 @@ namespace cppfs
template<typename... T_args>
inline file(T_args&&... p_args);

/**
* @brief Destrutor.
*/
inline ~file();

/**
* @brief Get the path of the file.
*/
@@ -30,10 +59,42 @@ namespace cppfs
*/
inline bool exists() const;

/**
* @brief Get the size of the file.
*/
inline size_t size() const;

/**
* @brief Remove the file.
*/
inline const file& remove() const;

/**
* @brief Open the file for reading or writing.
*/
inline void open(
const access_mode& p_access,
const open_flags& p_flags = open_flags::empty(),
const file_permissions& p_permissions = file_permissions::defaults());

/**
* @brief Read data from the file and store it in the passed buffer.
*/
inline size_t read(
void * p_buffer,
size_t p_count);

/**
* @brief Write data from the passed buffer to the file.
*/
inline size_t write(
const void * p_buffer,
size_t p_count);

/**
* @brief Close the file.
*/
inline void close();
};

}

+ 3
- 0
include/cppfs/file/file.inl View File

@@ -12,6 +12,9 @@ namespace cppfs
: _path(std::forward<T_args>(p_args)...)
{ }

file::~file()
{ close(); }

const cppfs::path& file::path() const
{ return _path; }



+ 102
- 0
include/cppfs/file/file.linux.inl View File

@@ -1,5 +1,8 @@
#pragma once

#include <fcntl.h>
#include <sys/stat.h>

#include "file.h"

namespace cppfs
@@ -7,6 +10,20 @@ namespace cppfs

/* file */

size_t file::size() const
{
struct stat st;
auto& s = _path.str();

if (stat(s.c_str(), &st))
{
using namespace std::string_literals;
throw cppcore::error_exception("Unable to get file size: "s + s, errno);
}

return cppcore::convert_cast<size_t>(st.st_size);
}

const file& file::remove() const
{
using namespace std::string_literals;
@@ -18,4 +35,89 @@ namespace cppfs
return *this;
}


void file::open(
const access_mode& p_access,
const open_flags& p_flags,
const file_permissions& p_permissions)
{
close();

int flags = 0;
switch (p_access)
{
case access_mode::read_only:
flags |= O_RDONLY;
break;
case access_mode::write_only:
flags |= O_WRONLY;
break;
case access_mode::read_write:
flags |= O_RDWR;
break;
case access_mode::unknown:
throw cppcore::exception("Invalid access mode: unknown");
}

if (p_flags.is_set(open_flag::create)) flags |= O_CREAT;
if (p_flags.is_set(open_flag::append)) flags |= O_APPEND;
if (p_flags.is_set(open_flag::truncate)) flags |= O_TRUNC;
if (p_flags.is_set(open_flag::non_blocking)) flags |= O_NONBLOCK;

auto& s = _path.str();
_handle = ::open(s.c_str(), flags, file_permissions::to_unix(p_permissions));
if (_handle < 0)
{
using namespace std::string_literals;
throw cppcore::error_exception("Unable to open file: "s + s, errno);
}
}

size_t file::read(
void * p_buffer,
size_t p_count)
{
if (_handle < 0)
open(access_mode::read_only, open_flags::empty(), file_permissions::defaults());

ssize_t ret = ::read(_handle, p_buffer, p_count);
if (ret < 0)
{
using namespace std::string_literals;
throw cppcore::error_exception("Unable to read from file: "s + _path.str(), errno);
}

return static_cast<size_t>(ret);
}

size_t file::write(
const void * p_buffer,
size_t p_count)
{
if (_handle < 0)
open(access_mode::write_only, open_flag::append, file_permissions::defaults());

ssize_t ret = ::write(_handle, p_buffer, p_count);
if (ret < 0)
{
using namespace std::string_literals;
throw cppcore::error_exception("Unable to write to file: "s + _path.str(), errno);
}

return static_cast<size_t>(ret);
}

void file::close()
{
if (_handle >= 0)
{
if (::close(_handle))
{
using namespace std::string_literals;
throw cppcore::error_exception("Unable to close file: "s + _path.str(), errno);
}
_handle = -1;
}
}

}

+ 15
- 0
include/cppfs/file_events.h View File

@@ -0,0 +1,15 @@
#pragma once

#include <cppfs/config.h>

#include "file_events/file_events.h"

#if cppfs_os == cppfs_os_linux
#include "file_events/select.h"
#endif

#include "file_events/file_events.inl"

#if cppfs_os == cppfs_os_linux
#include "file_events/select.inl"
#endif

+ 59
- 0
include/cppfs/file_events/fdset.h View File

@@ -0,0 +1,59 @@
#pragma once

#include <sys/select.h>

namespace cppfs
{

struct fdset final
: public fd_set
{
public:
/**
* @brief Constructor.
*/
inline fdset();

/**
* @brief Check if any file descriptor is set in this set.
*
* @param[in] max_fd Largest file descriptor stored.
*
* @retval true If any file descriptor is set.
* @retval false If no file descriptor is set.
*/
inline bool is_any(int max_fd) const;

/**
* @brief Check if the passed file descriptor is set in this set.
*
* @param[in] fd File descriptor to check for.
*
* @retval true If the passed file descriptor is set.
* @retval false If the passed file descriptor is not set.
*/
inline bool is_set(int fd) const;

/**
* @brief Set the passed file descriptor in the set.
*
* @param[in] fd File descriptor to set.
*/
inline void set(int fd);

/**
* @brief Clear the passed file descriptor in the set.
*
* @param[in] fd File descriptor to clear.
*/
inline void clear(int fd);

/**
* @brief Clear the complete file descriptor set.
*/
inline void reset();
};

}

#include "fdset.inl"

+ 63
- 0
include/cppfs/file_events/fdset.inl View File

@@ -0,0 +1,63 @@
#pragma once

#include "fdset.h"

namespace cppfs
{

/* fdset */

static_assert(
sizeof(fd_set) == sizeof(fdset),
"Size of fd set implementation does not match.");

fdset::fdset()
{
FD_ZERO(this);
}

bool fdset::is_any(int max_fd) const
{
static constexpr int field_count = sizeof(fds_bits) / sizeof(fds_bits[0]);

if (max_fd >= FD_SETSIZE)
throw cppcore::exception("Size of fd set exceeded!");

if (max_fd < 0)
return false;

auto cnt = (max_fd / field_count) + 1;
for (int i = 0; i < cnt; ++i)
{
if (fds_bits[i])
return true;
}

return false;
}

bool fdset::is_set(int fd) const
{
if (fd >= FD_SETSIZE)
throw cppcore::exception("Size of fd set exceeded!");
return FD_ISSET(fd, this);
}

void fdset::set(int fd)
{
if (fd >= FD_SETSIZE)
throw cppcore::exception("Size of fd set exceeded!");
FD_SET(fd, this);
}

void fdset::clear(int fd)
{
if (fd >= FD_SETSIZE)
throw cppcore::exception("Size of fd set exceeded!");
FD_CLR(fd, this);
}

void fdset::reset()
{ FD_ZERO(this); }

}

+ 96
- 0
include/cppfs/file_events/file_events.h View File

@@ -0,0 +1,96 @@
#pragma once

#include <cppfs/misc.h>

#include "types.h"

namespace cppfs
{

template<typename T_impl>
struct file_events
{
public:
using impl_type = T_impl;
using result_impl_type = typename impl_type::result_type;

struct result
{
private:
result_impl_type _impl;

public:
/**
* @brief Constructor.
*/
template<typename X_impl>
inline result(X_impl&& p_impl);

/**
* @brief Check if any event has occured in any handle.
*/
bool is_set() const;

/**
* @brief Check if any event has occured in the passed handle.
*/
bool is_set(
const raw_handle& p_handle) const;

/**
* @brief Check if any of the passed event has occured in any handle.
*/
bool is_set(
const event_types& p_events) const;

/**
* @brief Check if any of the passed event has occured in the passed handle.
*/
bool is_set(
const event_types& p_events,
const raw_handle& p_handle) const;
};

private:
impl_type _impl;

public:
/**
* @brief Constructor.
*/
inline file_events();

/**
* @brief Add or change a event listener for the passed file.
*/
inline void add(
const raw_handle& p_handle,
const event_types& p_events);

/**
* @brief Remove the event listener for the passed file.
*/
inline void erase(
const raw_handle& p_handle);

/**
* @brief Reset all event listeners.
*/
inline void reset();

/**
* @brief Wait for file events and return the result.
*/
inline result wait(
const event_timeout * p_timeout) const;

/**
* @brief Wait for file events and call the passed callback for each event.
*/
template<typename T_lambda>
inline void wait(
T_lambda&& p_lambda,
const event_timeout * p_timeout) const;
};

}

+ 89
- 0
include/cppfs/file_events/file_events.inl View File

@@ -0,0 +1,89 @@
#pragma once

#include "file_events.h"

namespace cppfs
{

/* file_events::result */

template<typename T_impl>
template<typename X_impl>
file_events<T_impl>::result::result(X_impl&& p_impl)
: _impl(std::forward<X_impl>(p_impl))
{ }

template<typename T_impl>
bool file_events<T_impl>::result::is_set() const
{
static const event_types all_types({
event_type::read,
event_type::write,
event_type::except,
});
return _impl.is_set(all_types, nullptr);
}

template<typename T_impl>
bool file_events<T_impl>::result::is_set(
const raw_handle& p_handle) const
{
static const event_types all_types({
event_type::read,
event_type::write,
event_type::except,
});
return _impl.is_set(all_types, &p_handle);
}

template<typename T_impl>
bool file_events<T_impl>::result::is_set(
const event_types& p_events) const
{
return _impl.is_set(p_events, nullptr);
}

template<typename T_impl>
bool file_events<T_impl>::result::is_set(
const event_types& p_events,
const raw_handle& p_handle) const
{
return _impl.is_set(p_events, &p_handle);
}

/* file_events */

template<typename T_impl>
file_events<T_impl>::file_events()
: _impl()
{ }

template<typename T_impl>
void file_events<T_impl>::add(
const raw_handle& p_handle,
const event_types& p_events)
{ _impl.add(p_handle, p_events); }

template<typename T_impl>
void file_events<T_impl>::erase(
const raw_handle& p_handle)
{ _impl.erase(p_handle); }

template<typename T_impl>
void file_events<T_impl>::reset()
{ _impl = impl_type(); }

template<typename T_impl>
typename file_events<T_impl>::result
file_events<T_impl>::wait(
const event_timeout * p_timeout) const
{ return result(_impl.wait(p_timeout)); }

template<typename T_impl>
template<typename T_lambda>
void file_events<T_impl>::wait(
T_lambda&& p_lambda,
const event_timeout * p_timeout) const
{ _impl.wait(std::forward<T_lambda>(p_lambda), p_timeout); }

}

+ 68
- 0
include/cppfs/file_events/select.h View File

@@ -0,0 +1,68 @@
#pragma once

#include <sys/select.h>

#include <cppfs/file/file.h>

#include "types.h"
#include "fdset.h"

namespace cppfs
{

struct fe_select
{
public:
struct storage
{
int max_fd { -1 };
fdset read;
fdset write;
fdset except;

inline bool is_set(
const event_types& p_events,
const raw_handle* p_handle) const;
};

using result_type = storage;

private:
storage _storage;

public:
/**
* @brief Constructor.
*/
inline fe_select() = default;

public: /* file_events implementation */
/**
* @brief Add or change a event listener for the passed file.
*/
inline void add(
const raw_handle& p_handle,
const event_types& p_events);

/**
* @brief Remove the event listener for the passed handle.
*/
inline void erase(
const raw_handle& p_handle);

/**
* @brief Wait for file events and return the result.
*/
inline result_type wait(
const event_timeout * p_timeout) const;

/**
* @brief Wait for file events and call the passed callback for each event.
*/
template<typename T_lambda>
inline void wait(
T_lambda&& p_lambda,
const event_timeout * p_timeout) const;
};

}

+ 114
- 0
include/cppfs/file_events/select.inl View File

@@ -0,0 +1,114 @@
#pragma once

#include <cppcore/conversion/time.h>

#include "select.h"

namespace cppfs
{

/* fe_select::storage */

bool fe_select::storage::is_set(
const event_types& p_events,
const raw_handle* p_handle) const
{
if (p_handle)
{
auto fd = p_handle->handle();
return (p_events.is_set(event_type::read) && read.is_set(fd))
|| (p_events.is_set(event_type::write) && write.is_set(fd))
|| (p_events.is_set(event_type::except) && except.is_set(fd));
}
else
{
return (p_events.is_set(event_type::read) && read.is_any(max_fd))
|| (p_events.is_set(event_type::write) && write.is_any(max_fd))
|| (p_events.is_set(event_type::except) && except.is_any(max_fd));
}
}

/* fe_select */

void fe_select::add(
const raw_handle& p_handle,
const event_types& p_events)
{
int fd = p_handle.handle();
if (fd < 0)
throw cppcore::exception("The passed file is not opened!");

if (p_events.is_set(event_type::read)) _storage.read.set(fd);
if (p_events.is_set(event_type::write)) _storage.write.set(fd);
if (p_events.is_set(event_type::except)) _storage.except.set(fd);

if ( !_storage.read.is_set(fd)
&& !_storage.write.is_set(fd)
&& !_storage.except.is_set(fd))
throw cppcore::exception("No or unkown events passed!");

_storage.max_fd = std::max(fd, _storage.max_fd);
}

void fe_select::erase(const raw_handle& p_handle)
{
int fd = p_handle.handle();
if (fd < 0)
throw cppcore::exception("The passed file is not opened!");

_storage.read.clear(fd);
_storage.write.clear(fd);
_storage.except.clear(fd);

if (fd == _storage.max_fd)
{
while (_storage.max_fd >= 0
&& !_storage.read.is_set(_storage.max_fd)
&& !_storage.write.is_set(_storage.max_fd)
&& !_storage.except.is_set(_storage.max_fd))
--_storage.max_fd;
}
}

fe_select::result_type fe_select::wait(const event_timeout * p_timeout) const
{
auto ret = _storage;

struct timespec timeout { 0, 0 };
if (p_timeout)
{
auto now = std::chrono::steady_clock::now();
if (now < *p_timeout)
{
auto diff = *p_timeout - now;
timeout = cppcore::duration_cast<timespec>(diff);
}
}

if (::pselect(ret.max_fd + 1, &ret.read, &ret.write, &ret.except, p_timeout ? &timeout : nullptr, nullptr) < 0)
{
auto err = errno;
if (err != EINTR)
throw cppcore::error_exception("Error while fetching file events with 'select'", err);
}

return ret;
}

template<typename T_lambda>
void fe_select::wait(T_lambda&& p_lambda, const event_timeout * p_timeout) const
{
auto ret = wait(p_timeout);
for (auto fd = 0; fd <= ret.max_fd; ++fd)
{
event_types ev;
if (ret.read.is_set(fd)) ev.set(event_type::read);
if (ret.write.is_set(fd)) ev.set(event_type::write);
if (ret.except.is_set(fd)) ev.set(event_type::except);

if (ev)
p_lambda(fd, ev);
}
}

}

+ 23
- 0
include/cppfs/file_events/types.h View File

@@ -0,0 +1,23 @@
#pragma once

#include <chrono>

#include <cppcore/misc/flags.h>

namespace cppfs
{

enum class event_type
{
unknown = 0,
read,
write,
except,
};

using event_types = cppcore::shifted_flags<event_type>;

using event_clock = std::chrono::steady_clock;
using event_timeout = event_clock::time_point;

}

+ 2
- 0
include/cppfs/misc.h View File

@@ -2,6 +2,8 @@

#include "misc/misc.h"

#include "misc/misc.inl"

#if cppfs_os == cppfs_os_linux
#include "misc/misc.linux.inl"
#endif

+ 20
- 4
include/cppfs/misc/misc.h View File

@@ -2,10 +2,6 @@

#include <cppcore/misc/flags.h>

#if cppfs_os == cppfs_os_linux
#include <sys/stat.h>
#endif

namespace cppfs
{

@@ -39,6 +35,20 @@ namespace cppfs
others_execute,
};

struct raw_handle
{
#if cppfs_os == cppfs_os_linux
protected:
int _handle { -1 };

public:
/**
* @brief Get the raw handle.
*/
inline int handle() const;
#endif
};

struct file_permissions
: public cppcore::shifted_flags<file_permission>
{
@@ -48,6 +58,12 @@ namespace cppfs
public:
using base_type::base_type;

public:
/**
* @brief Get the default file permissions.
*/
inline static const file_permissions& defaults();

#if cppfs_os == cppfs_os_linux
public:
/**


+ 26
- 0
include/cppfs/misc/misc.inl View File

@@ -0,0 +1,26 @@
#pragma once

#include "misc.h"

namespace cppfs
{

const file_permissions& file_permissions::defaults()
{
static const file_permissions value({
file_permission::user_read,
file_permission::user_write,
file_permission::user_execute,

file_permission::group_read,
file_permission::group_write,
file_permission::group_execute,

file_permission::others_read,
file_permission::others_execute,
});

return value;
}

}

+ 7
- 0
include/cppfs/misc/misc.linux.inl View File

@@ -5,6 +5,8 @@
namespace cppfs
{

/* file_permissions */

mode_t file_permissions::to_unix(const file_permissions& p_perm)
{
mode_t perm = 0;
@@ -43,4 +45,9 @@ namespace cppfs
return perm;
}

/* raw_handle */

int raw_handle::handle() const
{ return _handle; }

}

+ 2
- 0
test/cppfs/directory_tests.cpp View File

@@ -31,6 +31,8 @@ TEST(directory_tests, iterator)
files,
std::vector<std::string>({
"directory_tests.cpp",
"file_events_tests.cpp",
"file_tests.cpp",
"path_tests.cpp",
}));
}

+ 108
- 0
test/cppfs/file_events_tests.cpp View File

@@ -0,0 +1,108 @@
#include <gtest/gtest.h>

#include <fstream>

#include <cppfs.h>

using namespace ::testing;
using namespace ::cppfs;

struct pipe_handle
: public raw_handle
{
pipe_handle(int p_handle)
{
_handle = p_handle;
}

~pipe_handle()
{
close(_handle);
}
};

TEST(file_events_tests, select_with_callback)
{
int fds[2];
ASSERT_EQ(0, pipe(fds));

pipe_handle read_handle(fds[0]);
pipe_handle write_handle(fds[1]);

file_events<fe_select> fe;

fe.add(read_handle, event_types::all());
fe.add(write_handle, event_types::all());

auto timeout = event_clock::now();
fe.wait(
[&](auto fd, auto events) {
EXPECT_EQ(fd, write_handle.handle());
},
&timeout);

write(write_handle.handle(), "fuuu", 4);

auto i = 0;
fe.wait(
[&](auto fd, auto events) {
switch (i)
{
case 0:
EXPECT_EQ(fd, read_handle.handle());
EXPECT_EQ(events, event_types(event_type::read));
break;
case 1:
EXPECT_EQ(fd, write_handle.handle());
EXPECT_EQ(events, event_types(event_type::write));
break;
}
++i;
},
&timeout);
}


TEST(file_events_tests, select_with_result)
{
int fds[2];
ASSERT_EQ(0, pipe(fds));

pipe_handle read_handle(fds[0]);
pipe_handle write_handle(fds[1]);

file_events<fe_select> fe;

fe.add(read_handle, event_types::all());
fe.add(write_handle, event_types::all());

auto timeout = event_clock::now();

auto ret = fe.wait(&timeout);

EXPECT_TRUE (ret.is_set());
EXPECT_FALSE(ret.is_set(event_type::read));
EXPECT_TRUE (ret.is_set(event_type::write));
EXPECT_FALSE(ret.is_set(event_type::except));
EXPECT_FALSE(ret.is_set(event_type::read, read_handle));
EXPECT_FALSE(ret.is_set(event_type::write, read_handle));
EXPECT_FALSE(ret.is_set(event_type::except, read_handle));
EXPECT_FALSE(ret.is_set(event_type::read, write_handle));
EXPECT_TRUE (ret.is_set(event_type::write, write_handle));
EXPECT_FALSE(ret.is_set(event_type::except, write_handle));

write(write_handle.handle(), "fuuu", 4);

ret = fe.wait(&timeout);

EXPECT_TRUE (ret.is_set());
EXPECT_TRUE (ret.is_set(event_type::read));
EXPECT_TRUE (ret.is_set(event_type::write));
EXPECT_FALSE(ret.is_set(event_type::except));
EXPECT_TRUE (ret.is_set(event_type::read, read_handle));
EXPECT_FALSE(ret.is_set(event_type::write, read_handle));
EXPECT_FALSE(ret.is_set(event_type::except, read_handle));
EXPECT_FALSE(ret.is_set(event_type::read, write_handle));
EXPECT_TRUE (ret.is_set(event_type::write, write_handle));
EXPECT_FALSE(ret.is_set(event_type::except, write_handle));
}

+ 73
- 0
test/cppfs/file_tests.cpp View File

@@ -0,0 +1,73 @@
#include <gtest/gtest.h>

#include <fstream>

#include <cppfs.h>

using namespace ::testing;
using namespace ::cppfs;

TEST(file_tests, exists)
{
EXPECT_FALSE(file("./cppfs").exists());
EXPECT_TRUE (file("./cppfs/file_tests.cpp").exists());
EXPECT_FALSE(file("./cppfs/asdf.txt").exists());
}

TEST(file_tests, size)
{
EXPECT_EQ(1619, file("./cppfs/file_tests.cpp").size());
}

TEST(file_tests, open_close_and_remove)
{
EXPECT_ANY_THROW(file("/tmp/cppfs/file_tests/test.file").open(access_mode::read_write));

file f("/tmp/cppfs_file_tests.test_file");
f.open(access_mode::read_write, open_flag::create);
f.close();

EXPECT_TRUE(f.exists());

f.remove();

EXPECT_FALSE(f.exists());
}

TEST(file_tests, open_write_close_remove)
{
file f("/tmp/cppfs_file_tests.write_file");
f.open(access_mode::write_only, open_flag::create);
EXPECT_EQ(15, f.write("Hello World :)\n", 15));
f.close();

std::string s;
std::getline(std::ifstream("/tmp/cppfs_file_tests.write_file"), s);
EXPECT_EQ(s, "Hello World :)");

EXPECT_TRUE(f.exists());

f.remove();

EXPECT_FALSE(f.exists());
}

TEST(file_tests, open_read_close_remove)
{
std::ofstream("/tmp/cppfs_file_tests.read_file") << "Hello World :)" << std::endl;

char buffer[100] = { };

file f("/tmp/cppfs_file_tests.read_file");
f.open(access_mode::read_only);
EXPECT_EQ(15, f.read(&buffer[0], sizeof(buffer)));
f.close();

EXPECT_EQ(std::string(&buffer[0]), std::string("Hello World :)\n"));

EXPECT_TRUE(f.exists());

f.remove();

EXPECT_FALSE(f.exists());
}

Loading…
Cancel
Save