proxygen
folly::test::CaptureFD Class Reference

#include <TestUtil.h>

Classes

struct  NoOpChunkCob
 

Public Types

using ChunkCob = std::function< void(folly::StringPiece)>
 

Public Member Functions

 CaptureFD (int fd, ChunkCob chunk_cob=NoOpChunkCob())
 
 ~CaptureFD ()
 
void release ()
 
std::string read () const
 
std::string readIncremental ()
 

Private Attributes

ChunkCob chunkCob_
 
TemporaryFile file_
 
int fd_
 
int oldFDCopy_
 
off_t readOffset_
 

Detailed Description

Temporarily capture a file descriptor by redirecting it into a file. You can consume its entire output thus far via read(), incrementally via readIncremental(), or via callback using chunk_cob. Great for testing logging (see also glog*Pattern()).

Definition at line 222 of file TestUtil.h.

Member Typedef Documentation

Definition at line 229 of file TestUtil.h.

Constructor & Destructor Documentation

folly::test::CaptureFD::CaptureFD ( int  fd,
ChunkCob  chunk_cob = NoOpChunkCob() 
)
explicit

chunk_cob is is guaranteed to consume all the captured output. It is invoked on each readIncremental(), and also on FD release to capture as-yet unread lines. Chunks can be empty.

Definition at line 185 of file TestUtil.cpp.

References folly::netops::close(), fd_, file_, oldFDCopy_, and folly::test::TemporaryFile::path().

186  : chunkCob_(std::move(chunk_cob)), fd_(fd), readOffset_(0) {
187  oldFDCopy_ = dup(fd_);
188  PCHECK(oldFDCopy_ != -1) << "Could not copy FD " << fd_;
189 
190  int file_fd = open(file_.path().string().c_str(), O_WRONLY | O_CREAT, 0600);
191  PCHECK(dup2(file_fd, fd_) != -1)
192  << "Could not replace FD " << fd_ << " with " << file_fd;
193  PCHECK(close(file_fd) != -1) << "Could not close " << file_fd;
194 }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
const fs::path & path() const
Definition: TestUtil.cpp:85
TemporaryFile file_
Definition: TestUtil.h:259
int close(NetworkSocket s)
Definition: NetOps.cpp:90
folly::test::CaptureFD::~CaptureFD ( )

Definition at line 206 of file TestUtil.cpp.

References release().

206  {
207  release();
208 }

Member Function Documentation

std::string folly::test::CaptureFD::read ( ) const

Reads the whole file into a string, but does not remove the redirect.

Definition at line 210 of file TestUtil.cpp.

References file_, folly::test::TemporaryFile::path(), folly::readFile(), and string.

210  {
211  std::string contents;
212  std::string filename = file_.path().string();
213  PCHECK(folly::readFile(filename.c_str(), contents));
214  return contents;
215 }
bool readFile(int fd, Container &out, size_t num_bytes=std::numeric_limits< size_t >::max())
Definition: FileUtil.h:125
const fs::path & path() const
Definition: TestUtil.cpp:85
TemporaryFile file_
Definition: TestUtil.h:259
const char * string
Definition: Conv.cpp:212
std::string folly::test::CaptureFD::readIncremental ( )

Read any bytes that were appended to the file since the last readIncremental. Great for testing line-by-line output.

Definition at line 217 of file TestUtil.cpp.

References chunkCob_, f, folly::File::fd(), file_, folly::openNoInt(), folly::test::TemporaryFile::path(), folly::preadFull(), readOffset_, folly::size(), and string.

Referenced by release(), and TEST().

217  {
218  std::string filename = file_.path().string();
219  // Yes, I know that I could just keep the file open instead. So sue me.
220  folly::File f(openNoInt(filename.c_str(), O_RDONLY), true);
221  auto size = size_t(lseek(f.fd(), 0, SEEK_END) - readOffset_);
222  std::unique_ptr<char[]> buf(new char[size]);
223  auto bytes_read = folly::preadFull(f.fd(), buf.get(), size, readOffset_);
224  PCHECK(ssize_t(size) == bytes_read);
225  readOffset_ += off_t(size);
226  chunkCob_(StringPiece(buf.get(), buf.get() + size));
227  return std::string(buf.get(), size);
228 }
auto f
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
ssize_t preadFull(int fd, void *buf, size_t count, off_t offset)
Definition: FileUtil.cpp:130
const fs::path & path() const
Definition: TestUtil.cpp:85
TemporaryFile file_
Definition: TestUtil.h:259
int openNoInt(const char *name, int flags, mode_t mode)
Definition: FileUtil.cpp:36
const char * string
Definition: Conv.cpp:212
Range< const char * > StringPiece
void folly::test::CaptureFD::release ( )

Restore the captured FD to its original state. It can be useful to do this before the destructor so that you can read() the captured data and log about it to the formerly captured stderr or stdout.

Definition at line 196 of file TestUtil.cpp.

References folly::netops::close(), fd_, oldFDCopy_, and readIncremental().

Referenced by ~CaptureFD().

196  {
197  if (oldFDCopy_ != fd_) {
198  readIncremental(); // Feed chunkCob_
199  PCHECK(dup2(oldFDCopy_, fd_) != -1)
200  << "Could not restore old FD " << oldFDCopy_ << " into " << fd_;
201  PCHECK(close(oldFDCopy_) != -1) << "Could not close " << oldFDCopy_;
202  oldFDCopy_ = fd_; // Make this call idempotent
203  }
204 }
std::string readIncremental()
Definition: TestUtil.cpp:217
int close(NetworkSocket s)
Definition: NetOps.cpp:90

Member Data Documentation

ChunkCob folly::test::CaptureFD::chunkCob_
private

Definition at line 258 of file TestUtil.h.

Referenced by readIncremental().

int folly::test::CaptureFD::fd_
private

Definition at line 261 of file TestUtil.h.

Referenced by CaptureFD(), and release().

TemporaryFile folly::test::CaptureFD::file_
private

Definition at line 259 of file TestUtil.h.

Referenced by CaptureFD(), read(), and readIncremental().

int folly::test::CaptureFD::oldFDCopy_
private

Definition at line 262 of file TestUtil.h.

Referenced by CaptureFD(), and release().

off_t folly::test::CaptureFD::readOffset_
private

Definition at line 264 of file TestUtil.h.

Referenced by readIncremental().


The documentation for this class was generated from the following files: