2 * Copyright 2015 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #ifndef FOLLY_TESTUTIL_H_
18 #define FOLLY_TESTUTIL_H_
21 #include <folly/Range.h>
22 #include <folly/experimental/io/FsUtil.h>
30 * By default, the file is created in a system-specific location (the value
31 * of the TMPDIR environment variable, or /tmp), but you can override that
32 * with a different (non-empty) directory passed to the constructor.
34 * By default, the file is closed and deleted when the TemporaryFile object
35 * is destroyed, but both these behaviors can be overridden with arguments
45 explicit TemporaryFile(StringPiece namePrefix = StringPiece(),
46 fs::path dir = fs::path(),
47 Scope scope = Scope::UNLINK_ON_DESTRUCTION,
48 bool closeOnDestruction = true);
51 // Movable, but not copiable
52 TemporaryFile(TemporaryFile&&) = default;
53 TemporaryFile& operator=(TemporaryFile&&) = default;
55 int fd() const { return fd_; }
56 const fs::path& path() const;
60 bool closeOnDestruction_;
66 * Temporary directory.
68 * By default, the temporary directory is created in a system-specific
69 * location (the value of the TMPDIR environment variable, or /tmp), but you
70 * can override that with a non-empty directory passed to the constructor.
72 * By default, the directory is recursively deleted when the TemporaryDirectory
73 * object is destroyed, but that can be overridden with an argument
77 class TemporaryDirectory {
83 explicit TemporaryDirectory(StringPiece namePrefix = StringPiece(),
84 fs::path dir = fs::path(),
85 Scope scope = Scope::DELETE_ON_DESTRUCTION);
86 ~TemporaryDirectory();
88 // Movable, but not copiable
89 TemporaryDirectory(TemporaryDirectory&&) = default;
90 TemporaryDirectory& operator=(TemporaryDirectory&&) = default;
92 const fs::path& path() const { return path_; }
100 * Changes into a temporary directory, and deletes it with all its contents
101 * upon destruction, also changing back to the original working directory.
103 class ChangeToTempDir {
108 // Movable, but not copiable
109 ChangeToTempDir(ChangeToTempDir&&) = default;
110 ChangeToTempDir& operator=(ChangeToTempDir&&) = default;
112 const fs::path& path() const { return dir_.path(); }
115 fs::path initialPath_;
116 TemporaryDirectory dir_;
120 * Easy PCRE regex matching. Note that pattern must match the ENTIRE target,
121 * so use .* at the start and end of the pattern, as appropriate. See
122 * http://regex101.com/ for a PCRE simulator.
124 #define EXPECT_PCRE_MATCH(pattern_stringpiece, target_stringpiece) \
126 ::folly::test::detail::hasPCREPatternMatch, \
127 pattern_stringpiece, \
130 #define EXPECT_NO_PCRE_MATCH(pattern_stringpiece, target_stringpiece) \
132 ::folly::test::detail::hasNoPCREPatternMatch, \
133 pattern_stringpiece, \
138 bool hasPCREPatternMatch(StringPiece pattern, StringPiece target);
139 bool hasNoPCREPatternMatch(StringPiece pattern, StringPiece target);
140 } // namespace detail
143 * Use these patterns together with CaptureFD and EXPECT_PCRE_MATCH() to
144 * test for the presence (or absence) of log lines at a particular level:
146 * CaptureFD stderr(2);
147 * LOG(INFO) << "All is well";
148 * EXPECT_NO_PCRE_MATCH(glogErrOrWarnPattern(), stderr.readIncremental());
149 * LOG(ERROR) << "Uh-oh";
150 * EXPECT_PCRE_MATCH(glogErrorPattern(), stderr.readIncremental());
152 inline std::string glogErrorPattern() { return ".*(^|\n)E[0-9].*"; }
153 inline std::string glogWarningPattern() { return ".*(^|\n)W[0-9].*"; }
155 inline std::string glogErrOrWarnPattern() { return ".*(^|\n)[EW][0-9].*"; }
158 * Temporarily capture a file descriptor by redirecting it into a file.
159 * You can consume its output either all-at-once or incrementally.
160 * Great for testing logging (see also glog*Pattern()).
164 explicit CaptureFD(int fd);
168 * Restore the captured FD to its original state. It can be useful to do
169 * this before the destructor so that you can read() the captured data and
170 * log about it to the formerly captured stderr or stdout.
175 * Reads the whole file into a string, but does not remove the redirect.
180 * Read any bytes that were appended to the file since the last
181 * readIncremental. Great for testing line-by-line output.
183 std::string readIncremental();
189 int oldFDCopy_; // equal to fd_ after restore()
191 off_t readOffset_; // for incremental reading
197 #endif /* FOLLY_TESTUTIL_H_ */