Spicy
utils.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <unistd.h>
6 
7 #include <cstdlib>
8 #include <fstream>
9 #include <sstream>
10 #include <streambuf>
11 #include <string>
12 #include <vector>
13 
14 #include <hilti/rt/context.h>
15 #include <hilti/rt/doctest.h>
16 #include <hilti/rt/filesystem.h>
17 #include <hilti/rt/logging.h>
18 #include <hilti/rt/util.h>
19 
20 namespace hilti::rt::test {
21 // RAII helper to maintain a temporary file
23 public:
24  explicit TemporaryFile() {
25  std::string path = hilti::rt::filesystem::temp_directory_path() / "hilti-rt-tests-XXXXXX";
26 
27  auto fd = ::mkstemp(path.data());
28  REQUIRE_NE(fd, -1);
29  ::close(fd);
30 
31  _path = path;
32  }
33 
34  std::vector<std::string> lines() const {
35  auto file = std::ifstream(_path);
36 
37  std::string line;
38  std::vector<std::string> lines;
39  while ( std::getline(file, line) )
40  lines.push_back(line);
41 
42  return lines;
43  }
44 
45  const auto& path() const { return _path; }
46 
47  ~TemporaryFile() {
48  std::error_code ec;
49  auto exists = hilti::rt::filesystem::exists(_path, ec);
50 
51  if ( ec )
52  fatalError(fmt("failed to check whether %s exists: %s", _path, ec));
53 
54  if ( exists )
55  hilti::rt::filesystem::remove_all(_path, ec); // Swallow any error from removal.
56  }
57 
58 private:
59  hilti::rt::filesystem::path _path;
60 };
61 
62 // RAII helper to redirect output.
63 class CaptureIO {
64 public:
65  CaptureIO(std::ostream& stream) : _old(stream.rdbuf(_buffer.rdbuf())), _stream(&stream) {}
66  ~CaptureIO() { _stream->rdbuf(_old); }
67 
68  auto str() const { return _buffer.str(); }
69 
70 private:
71  std::stringstream _buffer = std::stringstream{};
72  std::streambuf* _old = nullptr;
73  std::ostream* _stream = nullptr;
74 };
75 
76 // RAII helper to maintain a controlled context in tests.
77 class TestContext {
78 public:
79  TestContext(Context* current) {
80  _prev = context::detail::current();
81  context::detail::current() = current;
82  }
83 
84  ~TestContext() { context::detail::current() = _prev; }
85 
86 private:
87  Context* _prev = nullptr;
88 };
89 
90 } // namespace hilti::rt::test
void fatalError(const std::string &msg) __attribute__((noreturn))
Definition: logging.cc:22
Definition: utils.h:20
Definition: utils.h:22
Definition: utils.h:63
Definition: utils.h:77
Definition: context.h:24
std::string fmt(const char *fmt, const Args &... args)
Definition: fmt.h:13