gtest-extra.cc 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  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. #include "gtest-extra.h"
  8. #if FMT_USE_FCNTL
  9. using fmt::file;
  10. output_redirect::output_redirect(FILE* f) : file_(f) {
  11. flush();
  12. int fd = FMT_POSIX(fileno(f));
  13. // Create a file object referring to the original file.
  14. original_ = file::dup(fd);
  15. // Create a pipe.
  16. file write_end;
  17. file::pipe(read_end_, write_end);
  18. // Connect the passed FILE object to the write end of the pipe.
  19. write_end.dup2(fd);
  20. }
  21. output_redirect::~output_redirect() noexcept {
  22. try {
  23. restore();
  24. } catch (const std::exception& e) {
  25. std::fputs(e.what(), stderr);
  26. }
  27. }
  28. void output_redirect::flush() {
  29. int result = 0;
  30. do {
  31. result = fflush(file_);
  32. } while (result == EOF && errno == EINTR);
  33. if (result != 0) throw fmt::system_error(errno, "cannot flush stream");
  34. }
  35. void output_redirect::restore() {
  36. if (original_.descriptor() == -1) return; // Already restored.
  37. flush();
  38. // Restore the original file.
  39. original_.dup2(FMT_POSIX(fileno(file_)));
  40. original_.close();
  41. }
  42. std::string output_redirect::restore_and_read() {
  43. // Restore output.
  44. restore();
  45. // Read everything from the pipe.
  46. std::string content;
  47. if (read_end_.descriptor() == -1) return content; // Already read.
  48. enum { BUFFER_SIZE = 4096 };
  49. char buffer[BUFFER_SIZE];
  50. size_t count = 0;
  51. do {
  52. count = read_end_.read(buffer, BUFFER_SIZE);
  53. content.append(buffer, count);
  54. } while (count != 0);
  55. read_end_.close();
  56. return content;
  57. }
  58. std::string read(file& f, size_t count) {
  59. std::string buffer(count, '\0');
  60. size_t n = 0, offset = 0;
  61. do {
  62. n = f.read(&buffer[offset], count - offset);
  63. // We can't read more than size_t bytes since count has type size_t.
  64. offset += n;
  65. } while (offset < count && n != 0);
  66. buffer.resize(offset);
  67. return buffer;
  68. }
  69. #endif // FMT_USE_FCNTL