Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
catch_output_redirect.cpp
Go to the documentation of this file.
1/*
2 * Created by Martin on 28/04/2018.
3 *
4 * Distributed under the Boost Software License, Version 1.0. (See accompanying
5 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 */
7
9#include "catch_enforce.h"
10
11#include <cstdio>
12#include <cstring>
13#include <fstream>
14#include <sstream>
15#include <stdexcept>
16
17#if defined(CATCH_CONFIG_NEW_CAPTURE)
18 #if defined(_MSC_VER)
19 #include <io.h> //_dup and _dup2
20 #define dup _dup
21 #define dup2 _dup2
22 #define fileno _fileno
23 #else
24 #include <unistd.h> // dup and dup2
25 #endif
26#endif
27
28
29namespace Catch {
30
31 RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
32 : m_originalStream( originalStream ),
33 m_redirectionStream( redirectionStream ),
34 m_prevBuf( m_originalStream.rdbuf() )
35 {
36 m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
37 }
38
40 m_originalStream.rdbuf( m_prevBuf );
41 }
42
43 RedirectedStdOut::RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {}
44 auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); }
45
47 : m_cerr( Catch::cerr(), m_rss.get() ),
48 m_clog( Catch::clog(), m_rss.get() )
49 {}
50 auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); }
51
52 RedirectedStreams::RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr)
53 : m_redirectedCout(redirectedCout),
54 m_redirectedCerr(redirectedCerr)
55 {}
56
58 m_redirectedCout += m_redirectedStdOut.str();
59 m_redirectedCerr += m_redirectedStdErr.str();
60 }
61
62#if defined(CATCH_CONFIG_NEW_CAPTURE)
63
64#if defined(_MSC_VER)
65 TempFile::TempFile() {
66 if (tmpnam_s(m_buffer)) {
67 CATCH_RUNTIME_ERROR("Could not get a temp filename");
68 }
69 if (fopen_s(&m_file, m_buffer, "w")) {
70 char buffer[100];
71 if (strerror_s(buffer, errno)) {
72 CATCH_RUNTIME_ERROR("Could not translate errno to a string");
73 }
74 CATCH_RUNTIME_ERROR("Could not open the temp file: '" << m_buffer << "' because: " << buffer);
75 }
76 }
77#else
78 TempFile::TempFile() {
79 m_file = std::tmpfile();
80 if (!m_file) {
81 CATCH_RUNTIME_ERROR("Could not create a temp file.");
82 }
83 }
84
85#endif
86
87 TempFile::~TempFile() {
88 // TBD: What to do about errors here?
89 std::fclose(m_file);
90 // We manually create the file on Windows only, on Linux
91 // it will be autodeleted
92#if defined(_MSC_VER)
93 std::remove(m_buffer);
94#endif
95 }
96
97
98 FILE* TempFile::getFile() {
99 return m_file;
100 }
101
102 std::string TempFile::getContents() {
103 std::stringstream sstr;
104 char buffer[100] = {};
105 std::rewind(m_file);
106 while (std::fgets(buffer, sizeof(buffer), m_file)) {
107 sstr << buffer;
108 }
109 return sstr.str();
110 }
111
112 OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) :
113 m_originalStdout(dup(1)),
114 m_originalStderr(dup(2)),
115 m_stdoutDest(stdout_dest),
116 m_stderrDest(stderr_dest) {
117 dup2(fileno(m_stdoutFile.getFile()), 1);
118 dup2(fileno(m_stderrFile.getFile()), 2);
119 }
120
121 OutputRedirect::~OutputRedirect() {
122 Catch::cout() << std::flush;
123 fflush(stdout);
124 // Since we support overriding these streams, we flush cerr
125 // even though std::cerr is unbuffered
126 Catch::cerr() << std::flush;
127 Catch::clog() << std::flush;
128 fflush(stderr);
129
130 dup2(m_originalStdout, 1);
131 dup2(m_originalStderr, 2);
132
133 m_stdoutDest += m_stdoutFile.getContents();
134 m_stderrDest += m_stderrFile.getContents();
135 }
136
137#endif // CATCH_CONFIG_NEW_CAPTURE
138
139} // namespace Catch
140
141#if defined(CATCH_CONFIG_NEW_CAPTURE)
142 #if defined(_MSC_VER)
143 #undef dup
144 #undef dup2
145 #undef fileno
146 #endif
147#endif
#define CATCH_RUNTIME_ERROR(msg)
auto str() const -> std::string
auto str() const -> std::string
RedirectedStream(std::ostream &originalStream, std::ostream &redirectionStream)
RedirectedStreams(RedirectedStreams const &)=delete
auto str() const -> std::string
std::ostream & cout()
std::ostream & clog()
std::ostream & cerr()
Definition name.hpp:106