From 6c8e3f09c185d7fa4664ccd9e5c4f623a17b84cc Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Tue, 12 Jul 2016 17:24:00 +0300 Subject: Extend fdstream --- tests/cpfile/driver.cxx | 21 ++--- tests/fdstream/driver.cxx | 192 ++++++++++++++++++++++++++++++++++++++++++++-- tests/link/driver.cxx | 12 ++- tests/pager/driver.cxx | 5 ++ tests/process/driver.cxx | 26 ++++--- 5 files changed, 219 insertions(+), 37 deletions(-) (limited to 'tests') diff --git a/tests/cpfile/driver.cxx b/tests/cpfile/driver.cxx index 669ac26..23b6fc3 100644 --- a/tests/cpfile/driver.cxx +++ b/tests/cpfile/driver.cxx @@ -2,12 +2,13 @@ // copyright : Copyright (c) 2014-2016 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file +#include #include #include -#include #include #include +#include #include using namespace std; @@ -20,22 +21,20 @@ 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); + ifdstream ifs (f, ios::binary); string s; getline (ifs, s, '\0'); + ifs.close (); // Not to miss failed close of the underlying file descriptor. 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); + ofdstream ofs (f, ios::binary); ofs << s; + ofs.close (); } int @@ -89,7 +88,7 @@ main () cpfile (from, to, cpflags::none); assert (false); } - catch (const system_error&) + catch (const ios::failure&) { } @@ -162,11 +161,13 @@ main () cpfile (from, tslink, cpflags::none); assert (false); } - catch (const system_error&) + catch (const ios::failure&) { } - // Check that copy fail if 'from' symlink points to non-existent file. + // Check that copy fail if 'from' symlink points to non-existent file. The + // std::system_error is thrown as cpfile() fails to obtain permissions for + // the 'from' symlink target. // try { diff --git a/tests/fdstream/driver.cxx b/tests/fdstream/driver.cxx index 3972473..0c6c480 100644 --- a/tests/fdstream/driver.cxx +++ b/tests/fdstream/driver.cxx @@ -2,9 +2,11 @@ // copyright : Copyright (c) 2014-2016 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file +#include #include #include -#include +#include +#include #include #include @@ -20,20 +22,20 @@ 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); + ifdstream ifs (f, m, ifdstream::badbit); string s; getline (ifs, s, '\0'); + ifs.close (); // Not to miss failed close of the underlying file descriptor. 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); + ofdstream ofs (f, m); ofs << s; + ofs.close (); } int @@ -55,7 +57,7 @@ main () fdopen (f, fdopen_mode::out); // fdopen_mode::create is missed. assert (false); } - catch (const system_error&) + catch (const ios::failure&) { } @@ -64,13 +66,45 @@ main () assert (from_file (f, fdopen_mode::create) == ""); assert (try_rmfile (f) == rmfile_status::success); + // Read from the newly created non-empty file. + // to_file (f, text1, fdopen_mode::create); assert (from_file (f) == text1); + // Check that skip on close as requested. + // + { + ifdstream ifs (fdopen (f, fdopen_mode::in), fdstream_mode::skip); + + string s; + getline (ifs, s); + assert (!ifs.eof ()); + + ifs.close (); + assert (ifs.eof ()); + } + + // Check that don't skip on close by default. + // + { + ifdstream ifs (fdopen (f, fdopen_mode::in)); + + string s; + getline (ifs, s); + assert (!ifs.eof ()); + + ifs.close (); + assert (!ifs.eof ()); + } + // Read from the file opened in R/W mode. // assert (from_file (f, fdopen_mode::out) == text1); + // Read starting from the file's end. + // + assert (from_file (f, fdopen_mode::at_end) == ""); + try { // Fail to create if the file already exists. @@ -80,7 +114,7 @@ main () assert (false); } - catch (const system_error&) + catch (const ios::failure&) { } @@ -101,6 +135,148 @@ main () to_file (f, text2, fdopen_mode::append); assert (from_file (f) == text1 + text2); + // Append to the file with the yet another way. + // + to_file (f, text1, fdopen_mode::truncate); + to_file (f, text2, fdopen_mode::at_end); + assert (from_file (f) == text1 + text2); + + // Check creating unopened ifdstream with a non-default exception mask. + // + to_file (f, "", fdopen_mode::truncate); + + { + ifdstream ifs (-1, ifdstream::badbit); + ifs.open (f); + + string s; + assert (!getline (ifs, s)); + } + + { + ifdstream ifs (-1, fdstream_mode::text, ifdstream::badbit); + ifs.open (f); + + string s; + assert (!getline (ifs, s)); + } + + // Check creating unopened ofdstream with a non-default exception mask. + // + { + ofdstream ofs (-1, ifdstream::badbit); + ofs.open (f); + + istringstream is; + ofs << is.rdbuf (); // Sets failbit if no characters is inserted. + ofs.close (); + } + + { + ofdstream ofs (-1, fdstream_mode::binary, ifdstream::badbit); + ofs.open (f); + + istringstream is; + ofs << is.rdbuf (); // Sets failbit if no characters is inserted. + ofs.close (); + } + + // Fail to write to a read-only file. + // + // Don't work well for MinGW GCC (5.2.0) that throws ios::failure, which in + // combination with libstdc++'s ios::failure ABI fiasco (#66145) make it + // impossible to properly catch in this situation. + // + try + { + { + ofdstream ofs (fdopen (f, fdopen_mode::in)); + ofs << text1; + ofs.flush (); + } + + assert (false); + } +#if !defined(_WIN32) || !defined(__GLIBCXX__) + catch (const ios::failure&) + { + } +#else + catch (const std::exception&) + { + } +#endif + + try + { + ofdstream ofs; + ofs.open (fdopen (f, fdopen_mode::in)); + ofs << text1; + ofs.close (); + + assert (false); + } +#if !defined(_WIN32) || !defined(__GLIBCXX__) + catch (const ios::failure&) + { + } +#else + catch (const std::exception&) + { + } +#endif + + // Fail to read from a write-only file. + // + try + { + ifdstream ifs (fdopen (f, fdopen_mode::out)); + ifs.peek (); + + assert (false); + } + catch (const ios::failure&) + { + } + + try + { + ifdstream ifs; + ifs.open (fdopen (f, fdopen_mode::out)); + ifs.peek (); + + assert (false); + } + catch (const ios::failure&) + { + } + + // Dtor of a not opened ofdstream doesn't terminate a program. + // + { + ofdstream ofs; + } + + // Dtor of an opened ofdstream doesn't terminate a program during the stack + // unwinding. + // + try + { + ofdstream ofs (f); + throw true; + } + catch (bool) + { + } + + // Dtor of an opened but being in a bad state ofdstream doesn't terminate a + // program. + // + { + ofdstream ofs (f, fdopen_mode::out, ofdstream::badbit); + ofs.clear (ofdstream::failbit); + } + #ifndef _WIN32 // Fail for an existing symlink to unexistent file. @@ -115,7 +291,7 @@ main () assert (false); } - catch (const system_error&) + catch (const ios::failure&) { } diff --git a/tests/link/driver.cxx b/tests/link/driver.cxx index 7ec4ac2..a32a8dc 100644 --- a/tests/link/driver.cxx +++ b/tests/link/driver.cxx @@ -4,11 +4,11 @@ #include #include -#include #include // pair #include #include +#include #include using namespace std; @@ -35,10 +35,9 @@ link_file (const path& target, const path& link, bool hard, bool check_content) return true; string s; - ifstream ifs; - ifs.exceptions (fstream::badbit | fstream::failbit); - ifs.open (link.string ()); + ifdstream ifs (link); ifs >> s; + ifs.close (); // Not to miss failed close of the underlying file descriptor. return s == text; } @@ -93,10 +92,9 @@ main () path fp (td / fn); { - ofstream ofs; - ofs.exceptions (fstream::badbit | fstream::failbit); - ofs.open (fp.string ()); + ofdstream ofs (fp); ofs << text; + ofs.close (); } // Create the file hard link. diff --git a/tests/pager/driver.cxx b/tests/pager/driver.cxx index cab3078..e921533 100644 --- a/tests/pager/driver.cxx +++ b/tests/pager/driver.cxx @@ -2,6 +2,7 @@ // copyright : Copyright (c) 2014-2016 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file +#include // ios_base::failure #include #include #include // move() @@ -104,6 +105,10 @@ public: assert (p.wait ()); } + catch (const ios_base::failure&) + { + assert (false); + } catch (const system_error&) { assert (false); diff --git a/tests/process/driver.cxx b/tests/process/driver.cxx index 741340c..5c43fb5 100644 --- a/tests/process/driver.cxx +++ b/tests/process/driver.cxx @@ -68,13 +68,12 @@ exec (const path& p, auto bin_mode = [bin](int fd) -> int { if (bin) - fdmode (fd, fdtranslate::binary); + fdmode (fd, fdstream_mode::binary); return fd; }; ofdstream os (bin_mode (pr.out_fd)); - os.exceptions (ofdstream::badbit); copy (in.begin (), in.end (), ostream_iterator (os)); os.close (); @@ -166,7 +165,6 @@ exec (const path& p, int main (int argc, const char* argv[]) -try { bool child (false); bool bin (false); @@ -201,8 +199,7 @@ try if (i != argc) { if (!child) - cerr << "usage: " << argv[0] << " [-c] [-i] [-o] [-e] [-b] []" - << endl; + cerr << "usage: " << argv[0] << " [-c] [-b] []" << endl; return 1; } @@ -235,9 +232,9 @@ try { if (bin) { - stdin_fdmode (fdtranslate::binary); - stdout_fdmode (fdtranslate::binary); - stderr_fdmode (fdtranslate::binary); + stdin_fdmode (fdstream_mode::binary); + stdout_fdmode (fdstream_mode::binary); + stderr_fdmode (fdstream_mode::binary); } vector data @@ -317,8 +314,13 @@ try // assert (exec ( fp.leaf (), vector (), false, false, false, true, fp.directory ())); -} -catch (const system_error&) -{ - assert (false); + +#ifndef _WIN32 + // Check that wait() works properly if the underlying low-level wait + // operation fails. + // + process pr; + pr.handle = reinterpret_cast(-1); + assert (!pr.wait (true) && !pr.wait (false)); +#endif } -- cgit v1.1