TestUtilTest.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. * Copyright 2012-present Facebook, Inc.
  3. *
  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
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  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.
  15. */
  16. #include <folly/experimental/TestUtil.h>
  17. #include <system_error>
  18. #include <boost/algorithm/string.hpp>
  19. #include <glog/logging.h>
  20. #include <folly/Memory.h>
  21. #include <folly/portability/Fcntl.h>
  22. #include <folly/portability/GTest.h>
  23. #include <folly/portability/Stdlib.h>
  24. using namespace folly;
  25. using namespace folly::test;
  26. TEST(TemporaryFile, Simple) {
  27. int fd = -1;
  28. char c = 'x';
  29. {
  30. TemporaryFile f;
  31. EXPECT_FALSE(f.path().empty());
  32. EXPECT_TRUE(f.path().is_absolute());
  33. fd = f.fd();
  34. EXPECT_LE(0, fd);
  35. ssize_t r = write(fd, &c, 1);
  36. EXPECT_EQ(1, r);
  37. }
  38. msvcSuppressAbortOnInvalidParams([&] {
  39. // The file must have been closed. This assumes that no other thread
  40. // has opened another file in the meanwhile, which is a sane assumption
  41. // to make in this test.
  42. ssize_t r = write(fd, &c, 1);
  43. int savedErrno = errno;
  44. EXPECT_EQ(-1, r);
  45. EXPECT_EQ(EBADF, savedErrno);
  46. });
  47. }
  48. TEST(TemporaryFile, EarlyClose) {
  49. fs::path p;
  50. {
  51. TemporaryFile f;
  52. p = f.path();
  53. EXPECT_TRUE(fs::exists(p));
  54. f.close();
  55. EXPECT_EQ(-1, f.fd());
  56. EXPECT_TRUE(fs::exists(p));
  57. }
  58. EXPECT_FALSE(fs::exists(p));
  59. }
  60. TEST(TemporaryFile, Prefix) {
  61. TemporaryFile f("Foo");
  62. EXPECT_TRUE(f.path().is_absolute());
  63. EXPECT_TRUE(
  64. boost::algorithm::starts_with(f.path().filename().native(), "Foo"));
  65. }
  66. TEST(TemporaryFile, PathPrefix) {
  67. TemporaryFile f("Foo", ".");
  68. EXPECT_EQ(fs::path("."), f.path().parent_path());
  69. EXPECT_TRUE(
  70. boost::algorithm::starts_with(f.path().filename().native(), "Foo"));
  71. }
  72. TEST(TemporaryFile, NoSuchPath) {
  73. EXPECT_THROW({ TemporaryFile f("", "/no/such/path"); }, std::system_error);
  74. }
  75. TEST(TemporaryFile, moveAssignment) {
  76. TemporaryFile f;
  77. int fd;
  78. EXPECT_TRUE(f.path().is_absolute());
  79. {
  80. TemporaryFile g("Foo", ".");
  81. EXPECT_NE(g.fd(), -1);
  82. fd = g.fd();
  83. f = std::move(g);
  84. }
  85. EXPECT_EQ(fs::path("."), f.path().parent_path());
  86. EXPECT_EQ(f.fd(), fd);
  87. TemporaryFile h = TemporaryFile("FooBar", ".");
  88. EXPECT_NE(h.fd(), -1);
  89. }
  90. TEST(TemporaryFile, moveCtor) {
  91. struct FooBar {
  92. TemporaryFile f_;
  93. explicit FooBar(TemporaryFile&& f) : f_(std::move(f)) {}
  94. };
  95. TemporaryFile g("Foo");
  96. FooBar fb(std::move(g));
  97. EXPECT_EQ(g.fd(), -1);
  98. EXPECT_NE(fb.f_.fd(), -1);
  99. }
  100. void testTemporaryDirectory(TemporaryDirectory::Scope scope) {
  101. fs::path path;
  102. {
  103. TemporaryDirectory d("", "", scope);
  104. path = d.path();
  105. EXPECT_FALSE(path.empty());
  106. EXPECT_TRUE(path.is_absolute());
  107. EXPECT_TRUE(fs::exists(path));
  108. EXPECT_TRUE(fs::is_directory(path));
  109. fs::path fp = path / "bar";
  110. int fd = open(fp.string().c_str(), O_RDWR | O_CREAT | O_TRUNC, 0666);
  111. EXPECT_NE(fd, -1);
  112. close(fd);
  113. TemporaryFile f("Foo", d.path());
  114. EXPECT_EQ(d.path(), f.path().parent_path());
  115. }
  116. bool exists = (scope == TemporaryDirectory::Scope::PERMANENT);
  117. EXPECT_EQ(exists, fs::exists(path));
  118. }
  119. TEST(TemporaryDirectory, Permanent) {
  120. testTemporaryDirectory(TemporaryDirectory::Scope::PERMANENT);
  121. }
  122. TEST(TemporaryDirectory, DeleteOnDestruction) {
  123. testTemporaryDirectory(TemporaryDirectory::Scope::DELETE_ON_DESTRUCTION);
  124. }
  125. void expectTempdirExists(const TemporaryDirectory& d) {
  126. EXPECT_FALSE(d.path().empty());
  127. EXPECT_TRUE(fs::exists(d.path()));
  128. EXPECT_TRUE(fs::is_directory(d.path()));
  129. }
  130. TEST(TemporaryDirectory, SafelyMove) {
  131. std::unique_ptr<TemporaryDirectory> dir;
  132. TemporaryDirectory dir2;
  133. {
  134. auto scope = TemporaryDirectory::Scope::DELETE_ON_DESTRUCTION;
  135. TemporaryDirectory d("", "", scope);
  136. TemporaryDirectory d2("", "", scope);
  137. expectTempdirExists(d);
  138. expectTempdirExists(d2);
  139. dir = std::make_unique<TemporaryDirectory>(std::move(d));
  140. dir2 = std::move(d2);
  141. }
  142. expectTempdirExists(*dir);
  143. expectTempdirExists(dir2);
  144. }
  145. TEST(ChangeToTempDir, ChangeDir) {
  146. auto pwd1 = fs::current_path();
  147. {
  148. ChangeToTempDir d;
  149. EXPECT_NE(pwd1, fs::current_path());
  150. }
  151. EXPECT_EQ(pwd1, fs::current_path());
  152. }
  153. TEST(PCREPatternMatch, Simple) {
  154. EXPECT_PCRE_MATCH(".*a.c.*", "gabca");
  155. EXPECT_NO_PCRE_MATCH("a.c", "gabca");
  156. EXPECT_NO_PCRE_MATCH(".*ac.*", "gabca");
  157. }
  158. TEST(CaptureFD, GlogPatterns) {
  159. CaptureFD err(fileno(stderr));
  160. LOG(INFO) << "All is well";
  161. EXPECT_NO_PCRE_MATCH(glogErrOrWarnPattern(), err.readIncremental());
  162. {
  163. LOG(ERROR) << "Uh-oh";
  164. auto s = err.readIncremental();
  165. EXPECT_PCRE_MATCH(glogErrorPattern(), s);
  166. EXPECT_NO_PCRE_MATCH(glogWarningPattern(), s);
  167. EXPECT_PCRE_MATCH(glogErrOrWarnPattern(), s);
  168. }
  169. {
  170. LOG(WARNING) << "Oops";
  171. auto s = err.readIncremental();
  172. EXPECT_NO_PCRE_MATCH(glogErrorPattern(), s);
  173. EXPECT_PCRE_MATCH(glogWarningPattern(), s);
  174. EXPECT_PCRE_MATCH(glogErrOrWarnPattern(), s);
  175. }
  176. }
  177. TEST(CaptureFD, ChunkCob) {
  178. std::vector<std::string> chunks;
  179. {
  180. CaptureFD err(fileno(stderr), [&](StringPiece p) {
  181. chunks.emplace_back(p.str());
  182. switch (chunks.size()) {
  183. case 1:
  184. EXPECT_PCRE_MATCH(".*foo.*bar.*", p);
  185. break;
  186. case 2:
  187. EXPECT_PCRE_MATCH("[^\n]*baz.*", p);
  188. break;
  189. default:
  190. FAIL() << "Got too many chunks: " << chunks.size();
  191. }
  192. });
  193. LOG(INFO) << "foo";
  194. LOG(INFO) << "bar";
  195. EXPECT_PCRE_MATCH(".*foo.*bar.*", err.read());
  196. auto chunk = err.readIncremental();
  197. EXPECT_EQ(chunks.at(0), chunk);
  198. LOG(INFO) << "baz";
  199. EXPECT_PCRE_MATCH(".*foo.*bar.*baz.*", err.read());
  200. }
  201. EXPECT_EQ(2, chunks.size());
  202. }