]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/fmt/test/gtest-extra.cc
update download target update for octopus release
[ceph.git] / ceph / src / seastar / fmt / test / gtest-extra.cc
1 // Formatting library for C++ - custom Google Test assertions
2 //
3 // Copyright (c) 2012 - present, Victor Zverovich
4 // All rights reserved.
5 //
6 // For the license information refer to format.h.
7
8 #include "gtest-extra.h"
9
10 #if FMT_USE_FILE_DESCRIPTORS
11
12 using fmt::file;
13
14 void OutputRedirect::flush() {
15 #if EOF != -1
16 # error "FMT_RETRY assumes return value of -1 indicating failure"
17 #endif
18 int result = 0;
19 FMT_RETRY(result, fflush(file_));
20 if (result != 0)
21 throw fmt::system_error(errno, "cannot flush stream");
22 }
23
24 void OutputRedirect::restore() {
25 if (original_.descriptor() == -1)
26 return; // Already restored.
27 flush();
28 // Restore the original file.
29 original_.dup2(FMT_POSIX(fileno(file_)));
30 original_.close();
31 }
32
33 OutputRedirect::OutputRedirect(FILE *f) : file_(f) {
34 flush();
35 int fd = FMT_POSIX(fileno(f));
36 // Create a file object referring to the original file.
37 original_ = file::dup(fd);
38 // Create a pipe.
39 file write_end;
40 file::pipe(read_end_, write_end);
41 // Connect the passed FILE object to the write end of the pipe.
42 write_end.dup2(fd);
43 }
44
45 OutputRedirect::~OutputRedirect() FMT_NOEXCEPT {
46 try {
47 restore();
48 } catch (const std::exception &e) {
49 std::fputs(e.what(), stderr);
50 }
51 }
52
53 std::string OutputRedirect::restore_and_read() {
54 // Restore output.
55 restore();
56
57 // Read everything from the pipe.
58 std::string content;
59 if (read_end_.descriptor() == -1)
60 return content; // Already read.
61 enum { BUFFER_SIZE = 4096 };
62 char buffer[BUFFER_SIZE];
63 std::size_t count = 0;
64 do {
65 count = read_end_.read(buffer, BUFFER_SIZE);
66 content.append(buffer, count);
67 } while (count != 0);
68 read_end_.close();
69 return content;
70 }
71
72 std::string read(file &f, std::size_t count) {
73 std::string buffer(count, '\0');
74 std::size_t n = 0, offset = 0;
75 do {
76 n = f.read(&buffer[offset], count - offset);
77 // We can't read more than size_t bytes since count has type size_t.
78 offset += n;
79 } while (offset < count && n != 0);
80 buffer.resize(offset);
81 return buffer;
82 }
83
84 #endif // FMT_USE_FILE_DESCRIPTORS
85
86 std::string format_system_error(int error_code, fmt::string_view message) {
87 fmt::memory_buffer out;
88 format_system_error(out, error_code, message);
89 return to_string(out);
90 }