aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2016-07-02 17:21:54 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2016-07-07 17:39:46 +0300
commit5b1c20f2315cd7fc624ffd31abdcc03b409bfcb2 (patch)
treec5c7b76dead92292b84586bda1b1256170195c48 /tests
parent15634965e8f0ab753898f5607ba11288556d1235 (diff)
Add cpfile()
Diffstat (limited to 'tests')
-rw-r--r--tests/buildfile4
-rw-r--r--tests/cpfile/buildfile7
-rw-r--r--tests/cpfile/driver.cxx182
-rw-r--r--tests/fdstream/buildfile7
-rw-r--r--tests/fdstream/driver.cxx135
5 files changed, 333 insertions, 2 deletions
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 <string>
+#include <cassert>
+#include <fstream>
+#include <system_error>
+
+#include <butl/path>
+#include <butl/filesystem>
+
+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 <string>
+#include <cassert>
+#include <system_error>
+
+#include <butl/path>
+#include <butl/fdstream>
+#include <butl/filesystem>
+
+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);
+}