You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stdcxx.apache.org by el...@apache.org on 2008/05/07 01:01:56 UTC

svn commit: r653948 - /stdcxx/branches/4.2.x/tests/iostream/27.ios.members.static.cpp

Author: elemings
Date: Tue May  6 16:01:56 2008
New Revision: 653948

URL: http://svn.apache.org/viewvc?rev=653948&view=rev
Log:
2008-05-06  Eric Lemings <er...@roguewave.com>

	STDCXX-884
	* branches/4.2.x/tests/iostream/27.ios.members.static.cpp:
	Migrated older test from Perforce repository to new test driver
	in Subversion repository.


Added:
    stdcxx/branches/4.2.x/tests/iostream/27.ios.members.static.cpp

Added: stdcxx/branches/4.2.x/tests/iostream/27.ios.members.static.cpp
URL: http://svn.apache.org/viewvc/stdcxx/branches/4.2.x/tests/iostream/27.ios.members.static.cpp?rev=653948&view=auto
==============================================================================
--- stdcxx/branches/4.2.x/tests/iostream/27.ios.members.static.cpp (added)
+++ stdcxx/branches/4.2.x/tests/iostream/27.ios.members.static.cpp Tue May  6 16:01:56 2008
@@ -0,0 +1,462 @@
+/***************************************************************************
+ *
+ * 27.ios.members.static.cpp - test exercising [lib.ios.members.static]
+ *
+ * $Id$
+ *
+ ***************************************************************************
+ *
+ * Licensed to the Apache Software  Foundation (ASF) under one or more
+ * contributor  license agreements.  See  the NOTICE  file distributed
+ * with  this  work  for  additional information  regarding  copyright
+ * ownership.   The ASF  licenses this  file to  you under  the Apache
+ * License, Version  2.0 (the  "License"); you may  not use  this file
+ * except in  compliance with the License.   You may obtain  a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the  License is distributed on an  "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
+ * implied.   See  the License  for  the  specific language  governing
+ * permissions and limitations under the License.
+ *
+ * Copyright 1994-2008 Rogue Wave Software.
+ *
+ **************************************************************************/
+
+// exercise that the default setting of ios_base::sync_with_stdio()
+// produces the expected output, i.e., that the ouptut of the standard
+// iostream objects, std::cout, std::cerr, etc., is properly interleaved
+// with the output produced by interleaving calls to stdio printf()
+// also exercises the ability of buffered standard iostream objects
+// (i.e., cout, wcout, clog, and wclog) to flush output on program exit
+
+#include <cerrno>     // for errno
+#include <cstdio>     // for fprintf, L_tmpnam
+#include <cstdlib>    // for STD{ERR,OUT}_FILENO
+#include <cstring>    // for strerror
+#include <iostream>
+
+// rwtest headers
+#include <driver.h>
+#include <file.h>
+
+#if !defined _WIN32 && !defined _WIN64
+
+#  include <fcntl.h>
+#  include <unistd.h>
+#  include <sys/types.h>
+#  include <sys/wait.h>
+
+#  define DEV_TTY   "/dev/tty"
+
+#else   // if defined _WIN32 || defined _WIN64
+
+#  include <fcntl.h>
+#  include <io.h>
+
+#  ifndef STDIN_FILENO
+#    define STDIN_FILENO  0
+#    define STDOUT_FILENO 1
+#    define STDERR_FILENO 2
+#  endif   // STDIN_FILENO
+
+#  define DEV_TTY   "CON:"
+
+#endif   // _WIN{32,64}
+
+
+// use buffers larger than L_tmpnam with rw_tmpnam()
+char stderr_fname [256];   // name of file to which stderr is redirected
+char stdout_fname [256];   // name of file to which stderr is redirected
+char stdio_fname  [256];   // same as above but for both stderr and stdout
+
+/**************************************************************************/
+
+template <class charT>
+/*static*/ void
+test_file (const char* fname, const char* expect)
+{
+    std::FILE* fp = std::fopen (fname, "r");
+
+    if (!fp) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "fopen (\"%s\", \"r\") failed: %s",
+                   fname, std::strerror (errno));
+
+        return;
+    }
+
+    enum { bufsiz = 256 };
+    char buf [bufsiz] = { 0 };
+    std::fgets (buf, bufsiz, fp);
+
+    rw_assert (!std::strcmp (expect, buf), __FILE__, __LINE__,
+               "expected output: \"%s\", got: \"%s\"", expect, buf);
+
+    std::fclose (fp);
+}
+
+/**************************************************************************/
+
+static void
+do_test ()
+{
+    static const char stdout_expect[] = {
+        "[STDOUT_FILENO]"
+        "[cout,1][stdout,1][cout,2][stdout,2]"
+
+#ifndef _RWSTD_NO_WCHAR_T
+        "[wcout,1][stdout,3][wcout,2][stdout,4]"
+#endif   // _RWSTD_NO_WCHAR_T
+    };
+
+    static const char stderr_expect[] = {
+        "[STDERR_FILENO]"
+        "[cerr,1][stderr,1][cerr,2][stderr,2]"
+        "[clog,1][stderr,3][clog,2][stderr,4]"
+
+#ifndef _RWSTD_NO_WCHAR_T
+        "[wcerr,1][stderr,5][wcerr,2][stderr,6]"
+        "[wclog,1][stderr,7][wclog,2][stderr,8]"
+#endif   // _RWSTD_NO_WCHAR_T
+    };
+
+    static const char stdio_expect[] = {
+        "[STDOUT_FILENO][STDERR_FILENO]"
+        "[cout,1][stdout,1][cout,2]"   // no [stdout,2] here
+        "[cerr,1][stderr,1][cerr,2][stderr,2]"
+        "[clog,1][stderr,3][clog,2][stderr,4]"
+        "[stdout,2]"   // but [stdout,2] flushed here
+
+#ifndef _RWSTD_NO_WCHAR_T
+        "[wcout,1][stdout,3][wcout,2]"   // no [stdout,2] here
+        "[wcerr,1][stderr,5][wcerr,2][stderr,6]"
+        "[wclog,1][stderr,7][wclog,2][stderr,8]"
+        "[stdout,4]"   // but [stdout,2] flushed here
+#endif   // _RWSTD_NO_WCHAR_T
+    };
+
+    rw_info (0, __FILE__, __LINE__,
+             "ios_base::sync_with_stdio (true)");
+
+    // call not necessary, stdio synchronized by default
+    // std::ios_base::sync_with_stdio (true);
+
+    rw_info (0, __FILE__, __LINE__,
+             "interleaved std::cout and stdout output");
+    test_file<char> (stdout_fname, stdout_expect);
+
+    rw_info (0, __FILE__, __LINE__,
+             "interleaved std::cerr and stderr output");
+    test_file<char> (stderr_fname, stderr_expect);
+
+    rw_info (0, __FILE__, __LINE__,
+             "interleaved std::cout/cerr and stdout/stderr output");
+    test_file<char> (stdio_fname,  stdio_expect);
+}
+
+/**************************************************************************/
+
+static int
+redirect_to_file (const char* fname, int fd)
+{
+    static int fd_tty = open (DEV_TTY, O_WRONLY);
+
+    if (fd_tty < 0) {
+        std::fprintf (stderr,
+                      "open (\"" DEV_TTY "\", O_WRONLY) failed: %s\n",
+                      std::strerror (errno));
+
+        fd_tty = STDERR_FILENO;
+    }
+
+    char buf [1024];
+    int n;
+
+    // create a new file and redirect `fd' to it
+    const int fd_tmp =
+        open (fname, O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, 0666);
+
+    if (fd_tmp < 0) {
+        n = std::sprintf (buf,
+                          "open (\"%s\", O_WRONLY | O_CREAT | O_TRUNC, "
+                          "0666) failed: %s\n",
+                          fname, std::strerror (errno));
+        write (fd_tty, buf, n);
+        return -1;   // bail out after a critical error
+    }
+
+    const int fd2 = dup2 (fd_tmp, fd);
+
+    if (0 > fd2) {
+        n = std::sprintf (buf,
+                          "dup2 (%d, %d) failed: %s\n",
+                          fd2, fd, std::strerror (errno));
+        write (fd_tty, buf, n);
+        return -2;   // bail out after a critical error
+    }
+
+    if (fd2 != fd) {
+        n = std::sprintf (buf,
+                          "dup2 (%d, %d) != %d; got %d\n",
+                          fd_tmp, fd, fd, fd2);
+        // should never happen
+        write (fd_tty, buf, n);
+    }
+
+    if (close (fd_tmp)) {
+        n = std::sprintf (buf,
+                          "close (%d) failed: %s\n",
+                          fd_tmp, std::strerror (errno));
+        write (fd_tty, buf, n);
+        // proceed after a benign error
+    }
+
+    return fd2;
+}
+
+
+static int
+exec_stdout_setup ()
+{
+    // create a new file and redirect stdout to it
+    const int fd_stdout = redirect_to_file (stdout_fname, STDOUT_FILENO);
+
+    if (fd_stdout != STDOUT_FILENO)
+        return fd_stdout;
+
+    // expected output (w/o newlines):
+    //     "[STDOUT_FILENO]"
+    //     "[cout,1][stdout,1]"
+    //     "[cout,2][stdout,2]"
+    //     "[wcout,1][stdout,3]"
+    //     "[wcout,2][stdout,4]"
+
+    write (STDOUT_FILENO, "[STDOUT_FILENO]", 15);
+    std::cout << "[cout,1]";
+    std::printf ("[stdout,1]");
+    std::cout << "[cout,2]";      // flushes the printf() above
+    std::printf ("[stdout,2]");
+
+#ifndef _RWSTD_WCHAR_T
+
+    std::wcout << "[wcout,1]";    // flushes the printf() above
+    std::printf ("[stdout,3]");
+    std::wcout << "[wcout,2]";    // flushes the printf() above
+    std::printf ("[stdout,4]");   // flushed during termination
+
+#endif   // _RWSTD_WCHAR_T
+
+    return 0;
+}
+
+
+static int
+exec_stderr_setup ()
+{
+    // create a new file and redirect stderr to it
+    const int fd_stderr = redirect_to_file (stderr_fname, STDERR_FILENO);
+
+    if (fd_stderr != STDERR_FILENO)
+        return fd_stderr;
+
+    // expected output (w/o newlines):
+    //     "[STDERR_FILENO]"
+    //     "[cerr,1][stderr,1][cerr,2][stderr,2]"
+    //     "[clog,1][stderr,3][clog,2][stderr,4]"
+    //     "[wcerr,1][stderr,5][wcerr,2][stderr,6]"
+    //     "[wclog,1][stderr,7][wclog,2][stderr,8]"
+
+    write (STDERR_FILENO, "[STDERR_FILENO]", 15);
+    std::cerr << "[cerr,1]";
+    std::fprintf (stderr, "[stderr,1]");
+    std::cerr << "[cerr,2]";
+    std::fprintf (stderr, "[stderr,2]");
+    std::clog << "[clog,1]";
+    std::fprintf (stderr, "[stderr,3]");
+    std::clog << "[clog,2]";
+    std::fprintf (stderr, "[stderr,4]");
+
+#ifndef _RWSTD_WCHAR_T
+
+    std::wcerr << "[wcerr,1]";
+    std::fprintf (stderr, "[stderr,5]");
+    std::wcerr << "[wcerr,2]";
+    std::fprintf (stderr, "[stderr,6]");
+    std::wclog << "[wclog,1]";
+    std::fprintf (stderr, "[stderr,7]");
+    std::wclog << "[wclog,2]";
+    std::fprintf (stderr, "[stderr,8]");
+
+#endif   // _RWSTD_WCHAR_T
+
+    return 0;
+}
+
+
+static int
+exec_stdio_setup ()
+{
+    // create a new file and redirect both stdout and stderr to it
+    const int fd_stdout = redirect_to_file (stdio_fname, STDOUT_FILENO);
+    const int fd_stderr = redirect_to_file (stdio_fname, STDERR_FILENO);
+
+    if (fd_stdout != STDOUT_FILENO)
+        return fd_stdout;
+
+    if (fd_stderr != STDERR_FILENO)
+        return fd_stderr;
+
+    // expected output (w/o newlines):
+    //     "[STDOUT_FILENO][STDERR_FILENO]"
+    //     "[cout,1][stdout,1][cout,2]"
+    //     "[cerr,1][stderr,1][cerr,2][stderr,2]"
+    //     "[clog,1][stderr,3][clog,2][stderr,4]"
+    //     "[stdout,2]"
+    //     "[wcout,1][stdout,3][wcout,2]"
+    //     "[wcerr,1][stderr,5][wcerr,2][stderr,6]"
+    //     "[wclog,1][stderr,7][wclog,2][stderr,8]"
+    //     "[stdout,4]"
+
+    write (STDOUT_FILENO, "[STDOUT_FILENO]", 15);
+    write (STDERR_FILENO, "[STDERR_FILENO]", 15);
+
+    std::cout << "[cout,1]";
+    std::printf ("[stdout,1]");
+    std::cout << "[cout,2]";
+    std::printf ("[stdout,2]");    // flushed after STDERR output below
+
+    std::cerr << "[cerr,1]";
+    std::fprintf (stderr, "[stderr,1]");
+    std::cerr << "[cerr,2]";
+    std::fprintf (stderr, "[stderr,2]");
+    std::clog << "[clog,1]";
+    std::fprintf (stderr, "[stderr,3]");
+    std::clog << "[clog,2]";
+    std::fprintf (stderr, "[stderr,4]");
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+    std::wcout << "[wcout,1]";
+    std::printf ("[stdout,3]");
+    std::wcout << "[wcout,2]";
+    std::printf ("[stdout,4]");    // flushed after STDERR output below
+
+    std::wcerr << "[wcerr,1]";
+    std::fprintf (stderr, "[stderr,5]");
+    std::wcerr << "[wcerr,2]";
+    std::fprintf (stderr, "[stderr,6]");
+    std::wclog << "[wclog,1]";
+    std::fprintf (stderr, "[stderr,7]");
+    std::wclog << "[wclog,2]";
+    std::fprintf (stderr, "[stderr,8]");
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+    return 0;
+}
+
+/**************************************************************************/
+
+struct cleanup
+{
+    int dummy;
+
+    ~cleanup () {
+        if (*stdout_fname)
+            std::remove (stdout_fname);
+        if (*stderr_fname)
+            std::remove (stderr_fname);
+        if (*stdio_fname)
+            std::remove (stdio_fname);
+    }
+};
+
+
+static int
+run_test (int /* unused */, char* /* unused */ [])
+{
+    const cleanup remove_tmp_files = { 0 };
+
+    // prevent unused warnings
+    (void)&remove_tmp_files;
+
+    if (!rw_tmpnam (stdout_fname)) {
+        std::fprintf (stderr,
+                      "rw_tmpnam (%p) failed: %s\n",
+                      stdout_fname, std::strerror (errno));
+        return 1;
+    }
+
+    if (!rw_tmpnam (stderr_fname)) {
+        std::fprintf (stderr,
+                      "rw_tmpnam (%p) failed: %s\n",
+                      stderr_fname, std::strerror (errno));
+        return 1;
+    }
+
+    if (!rw_tmpnam (stdio_fname)) {
+        std::fprintf (stderr,
+                      "rw_tmpnam (%p) failed: %s\n",
+                      stdio_fname, std::strerror (errno));
+        return 1;
+    }
+
+#if !defined (_WIN32) && !defined (_WIN64)
+
+    // create three child process and have each redirect
+    // its stdout, stderr, and both, respectively, to
+    // a file
+    // after all the children exit, the parent will check
+    // the contents of the file to determine whether all
+    // streams have been properly flushed and synchronized
+
+    for (int i = 0; i != 3; ++i) {
+        const pid_t child_pid = fork ();
+
+        if (child_pid < 0) {   // fork error
+
+            std::fprintf (stderr, "fork() failed: %s\n",
+                          std::strerror (errno));
+
+            return 1;
+        }
+        else if (child_pid > 0) {   // parent
+            wait (0);
+        }
+        else {   // child
+
+            int ret = 1;
+
+            switch (i) {
+            case 0: ret = exec_stderr_setup (); break;
+            case 1: ret = exec_stdout_setup (); break;
+            case 2: ret = exec_stdio_setup (); break;
+            }
+
+            // prevent child process from cleaning up files
+            *stdout_fname = *stderr_fname = *stdio_fname = '\0';
+            return ret;
+        }
+    }
+
+#endif   // _WIN{32,64}
+
+    do_test ();
+
+    return 0;
+}
+
+
+/* extern */ int
+main (int argc, char* argv [])
+{
+    return rw_test (argc, argv, __FILE__,
+                    "lib.ios.members.static",
+                    "27.4.2.4 ios_base static members",
+                    run_test, "", 0);
+}
+