From 5b1c20f2315cd7fc624ffd31abdcc03b409bfcb2 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Sat, 2 Jul 2016 17:21:54 +0300 Subject: Add cpfile() --- tests/buildfile | 4 +- tests/cpfile/buildfile | 7 ++ tests/cpfile/driver.cxx | 182 ++++++++++++++++++++++++++++++++++++++++++++++ tests/fdstream/buildfile | 7 ++ tests/fdstream/driver.cxx | 135 ++++++++++++++++++++++++++++++++++ 5 files changed, 333 insertions(+), 2 deletions(-) create mode 100644 tests/cpfile/buildfile create mode 100644 tests/cpfile/driver.cxx create mode 100644 tests/fdstream/buildfile create mode 100644 tests/fdstream/driver.cxx (limited to 'tests') diff --git a/tests/buildfile b/tests/buildfile index 311a290..8f20b9f 100644 --- a/tests/buildfile +++ b/tests/buildfile @@ -2,8 +2,8 @@ # copyright : Copyright (c) 2014-2016 Code Synthesis Ltd # license : MIT; see accompanying LICENSE file -d = base64/ dir-iterator/ link/ pager/ path/ prefix-map/ process/ sha256/ \ - timestamp/ triplet/ +d = base64/ cpfile/ dir-iterator/ fdstream/ link/ pager/ path/ prefix-map/ \ + process/ sha256/ timestamp/ triplet/ .: $d include $d diff --git a/tests/cpfile/buildfile b/tests/cpfile/buildfile new file mode 100644 index 0000000..7d02738 --- /dev/null +++ b/tests/cpfile/buildfile @@ -0,0 +1,7 @@ +# file : tests/cpfile/buildfile +# copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +# license : MIT; see accompanying LICENSE file + +exe{driver}: cxx{driver} ../../butl/lib{butl} + +include ../../butl/ diff --git a/tests/cpfile/driver.cxx b/tests/cpfile/driver.cxx new file mode 100644 index 0000000..669ac26 --- /dev/null +++ b/tests/cpfile/driver.cxx @@ -0,0 +1,182 @@ +// file : tests/cpfile/driver.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include +#include +#include +#include + +#include +#include + +using namespace std; +using namespace butl; + +static const char text1[] = "ABCDEF\nXYZ"; +static const char text2[] = "12345\nDEF"; +static const char text3[] = "XAB\r\n9"; + +static string +from_file (const path& f) +{ + ifstream ifs; + ifs.exceptions (fstream::badbit | fstream::failbit); + ifs.open (f.string (), ios::binary); + + string s; + getline (ifs, s, '\0'); + return s; +} + +static void +to_file (const path& f, const char* s) +{ + ofstream ofs; + ofs.exceptions (fstream::badbit | fstream::failbit); + ofs.open (f.string (), ios::binary); + ofs << s; +} + +int +main () +{ + dir_path td (dir_path::temp_directory () / dir_path ("butl-cpfile")); + + // Recreate the temporary directory (that possibly exists from the previous + // faulty run) for the test files. Delete the directory only if the test + // succeeds to simplify the failure research. + // + try_rmdir_r (td); + assert (try_mkdir (td) == mkdir_status::success); + + path from (td / path ("from")); + to_file (from, text1); + + permissions p (path_permissions (from)); + path_permissions (from, permissions::ru | permissions::xu); + + // Check that content and permissions of newly created destination file are + // the same as that ones of the source file. + // + path to (td / path ("to")); + cpfile (from, to, cpflags::none); + assert (from_file (to) == text1); + assert (path_permissions (to) == path_permissions (from)); + + // Check that permissions of an existent destination file stays intact if + // their overwrite is not requested. + // + path_permissions (to, p); + cpfile (from, to, cpflags::overwrite_content); + assert (from_file (to) == text1); + assert (path_permissions (to) == p); + + // Check that permissions of an existent destination file get overwritten if + // requested. + // + cpfile ( + from, to, cpflags::overwrite_content | cpflags::overwrite_permissions); + + assert (from_file (to) == text1); + assert (path_permissions (to) == path_permissions (from)); + + path_permissions (to, p); + path_permissions (from, p); + + try + { + cpfile (from, to, cpflags::none); + assert (false); + } + catch (const system_error&) + { + } + + // Copy to the directory. + // + dir_path sd (td / dir_path ("sub")); + assert (try_mkdir (sd) == mkdir_status::success); + + cpfile (from, sd, cpflags::none); + + assert (from_file (sd / path ("from")) == text1); + + // Check that a hard link to the destination file is preserved. + // + path hlink (td / path ("hlink")); + mkhardlink (to, hlink); + to_file (hlink, text1); + + to_file (from, text2); + cpfile (from, to, cpflags::overwrite_content); + + assert (from_file (hlink) == text2); + +#ifndef _WIN32 + + // Check that 'from' being a symbolic link is properly resolved. + // + path fslink (td / path ("fslink")); + mksymlink (from, fslink); + + cpfile (fslink, to, cpflags::overwrite_content); + + // Make sure 'to' is not a symbolic link to 'from' and from_file() just + // follows it. + // + assert (try_rmfile (from) == rmfile_status::success); + assert (from_file (to) == text2); + + // Check that 'to' being a symbolic link is properly resolved. + // + path tslink (td / path ("tslink")); + mksymlink (to, tslink); + + to_file (from, text3); + cpfile (from, tslink, cpflags::overwrite_content); + assert (from_file (to) == text3); + + // Check that permissions are properly overwritten when 'to' is a symbolic + // link. + // + to_file (from, text1); + path_permissions (from, permissions::ru | permissions::xu); + + cpfile ( + from, tslink, cpflags::overwrite_content | cpflags::overwrite_permissions); + + assert (from_file (to) == text1); + assert (path_permissions (to) == path_permissions (from)); + + path_permissions (to, p); + path_permissions (from, p); + + // Check that no-overwrite file copy fails even if 'to' symlink points to + // non-existent file. + // + assert (try_rmfile (to) == rmfile_status::success); + + try + { + cpfile (from, tslink, cpflags::none); + assert (false); + } + catch (const system_error&) + { + } + + // Check that copy fail if 'from' symlink points to non-existent file. + // + try + { + cpfile (tslink, from, cpflags::none); + assert (false); + } + catch (const system_error&) + { + } +#endif + + rmdir_r (td); +} diff --git a/tests/fdstream/buildfile b/tests/fdstream/buildfile new file mode 100644 index 0000000..bc4c6d2 --- /dev/null +++ b/tests/fdstream/buildfile @@ -0,0 +1,7 @@ +# file : tests/fdstream/buildfile +# copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +# license : MIT; see accompanying LICENSE file + +exe{driver}: cxx{driver} ../../butl/lib{butl} + +include ../../butl/ diff --git a/tests/fdstream/driver.cxx b/tests/fdstream/driver.cxx new file mode 100644 index 0000000..3972473 --- /dev/null +++ b/tests/fdstream/driver.cxx @@ -0,0 +1,135 @@ +// file : tests/fdstream/driver.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include +#include +#include + +#include +#include +#include + +using namespace std; +using namespace butl; + +static const string text1 ("ABCDEF\nXYZ"); +static const string text2 ("12"); // Keep shorter than text1. +static const string text3 ("ABCDEF\r\nXYZ"); + +static string +from_file (const path& f, fdopen_mode m = fdopen_mode::none) +{ + ifdstream ifs (fdopen (f, m | fdopen_mode::in)); + ifs.exceptions (ifdstream::badbit); + + string s; + getline (ifs, s, '\0'); + return s; +} + +static void +to_file (const path& f, const string& s, fdopen_mode m = fdopen_mode::none) +{ + ofdstream ofs (fdopen (f, m | fdopen_mode::out)); + ofs.exceptions (ofdstream::badbit | ofdstream::failbit); + ofs << s; +} + +int +main () +{ + dir_path td (dir_path::temp_directory () / dir_path ("butl-fdstream")); + + // Recreate the temporary directory (that possibly exists from the previous + // faulty run) for the test files. Delete the directory only if the test + // succeeds to simplify the failure research. + // + try_rmdir_r (td); + assert (try_mkdir (td) == mkdir_status::success); + + path f (td / path ("file")); + + try + { + fdopen (f, fdopen_mode::out); // fdopen_mode::create is missed. + assert (false); + } + catch (const system_error&) + { + } + + // Read from the newly created empty file. + // + assert (from_file (f, fdopen_mode::create) == ""); + assert (try_rmfile (f) == rmfile_status::success); + + to_file (f, text1, fdopen_mode::create); + assert (from_file (f) == text1); + + // Read from the file opened in R/W mode. + // + assert (from_file (f, fdopen_mode::out) == text1); + + try + { + // Fail to create if the file already exists. + // + fdopen ( + f, fdopen_mode::out | fdopen_mode::create | fdopen_mode::exclusive); + + assert (false); + } + catch (const system_error&) + { + } + + // Write text2 over text1. + // + to_file (f, text2); + string s (text2); + s += string (text1, text2.size ()); + assert (from_file (f) == s); + + // Truncate before reading. + // + assert (from_file (f, fdopen_mode::out | fdopen_mode::truncate) == ""); + + // Append to the file. + // + to_file (f, text1, fdopen_mode::truncate); + to_file (f, text2, fdopen_mode::append); + assert (from_file (f) == text1 + text2); + +#ifndef _WIN32 + + // Fail for an existing symlink to unexistent file. + // + path link (td / path ("link")); + mksymlink (td / path ("unexistent"), link); + + try + { + fdopen ( + link, fdopen_mode::out | fdopen_mode::create | fdopen_mode::exclusive); + + assert (false); + } + catch (const system_error&) + { + } + +#else + + // Check translation modes. + // + to_file (f, text1, fdopen_mode::truncate); + assert (from_file (f, fdopen_mode::binary) == text3); + + to_file (f, text3, fdopen_mode::truncate | fdopen_mode::binary); + assert (from_file (f) == text1); + +#endif + + rmdir_r (td); +} -- cgit v1.1