-
-
Notifications
You must be signed in to change notification settings - Fork 191
Expand file tree
/
Copy pathstream_capture_helpers.hpp
More file actions
94 lines (81 loc) · 3.34 KB
/
Copy pathstream_capture_helpers.hpp
File metadata and controls
94 lines (81 loc) · 3.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*
This file is part of libhttpserver
Copyright (C) 2011-2026 Sebastiano Merlino
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
// Shared stdout/stderr capture helpers for integ
// tests that must assert on what the process writes to those streams
// (debug_dump_request_body_set_test.cpp and
// debug_dump_request_body_unset_test.cpp previously carried verbatim
// copies of these).
//
// Redirects FILENO to a tmp file via dup2 so the test can read back
// what the process wrote to stdout/stderr in-process. Pair every
// begin_capture with an end_capture on the same fd; end_capture
// restores the original stream, returns the captured bytes, and
// unlinks the tmp file.
#ifndef TEST_INTEG_STREAM_CAPTURE_HELPERS_HPP_
#define TEST_INTEG_STREAM_CAPTURE_HELPERS_HPP_
#include <unistd.h>
#include <cstdio>
#include <cstdlib>
#include <string>
namespace httpserver_test {
struct stream_capture {
int saved_fd = -1;
int captured_fd = -1;
std::string path;
};
// Redirect @p fileno_to_capture (STDOUT_FILENO / STDERR_FILENO) into a
// fresh mkstemp file whose name embeds @p tmp_label. The stdio buffer
// of the corresponding stream is flushed first so previously buffered
// bytes do not leak into the capture window.
inline stream_capture begin_capture(int fileno_to_capture,
const char* tmp_label) {
stream_capture c;
char tpl[256];
std::snprintf(tpl, sizeof(tpl),
"/tmp/libhttpserver_%s_XXXXXX", tmp_label);
c.captured_fd = mkstemp(tpl);
c.path = tpl;
c.saved_fd = dup(fileno_to_capture);
if (fileno_to_capture == STDOUT_FILENO) std::fflush(stdout);
else if (fileno_to_capture == STDERR_FILENO) std::fflush(stderr);
dup2(c.captured_fd, fileno_to_capture);
return c;
}
// Flush, restore the original stream onto @p fileno_to_restore, and
// return everything written to the captured stream since the matching
// begin_capture. The tmp file is unlinked before returning.
inline std::string end_capture(stream_capture& c, int fileno_to_restore) {
if (fileno_to_restore == STDOUT_FILENO) std::fflush(stdout);
else if (fileno_to_restore == STDERR_FILENO) std::fflush(stderr);
dup2(c.saved_fd, fileno_to_restore);
::close(c.saved_fd);
::close(c.captured_fd);
FILE* f = std::fopen(c.path.c_str(), "rb");
std::string out;
if (f != nullptr) {
char buf[4096];
size_t n;
while ((n = std::fread(buf, 1, sizeof(buf), f)) > 0) {
out.append(buf, n);
}
std::fclose(f);
}
::unlink(c.path.c_str());
return out;
}
} // namespace httpserver_test
#endif // TEST_INTEG_STREAM_CAPTURE_HELPERS_HPP_