Use the GTest portability headers
[folly.git] / folly / experimental / test / TestUtilTest.cpp
1 /*
2  * Copyright 2016 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
17 #include <folly/experimental/TestUtil.h>
18
19 #include <sys/stat.h>
20 #include <sys/types.h>
21
22 #include <system_error>
23
24 #include <boost/algorithm/string.hpp>
25 #include <glog/logging.h>
26
27 #include <folly/Memory.h>
28 #include <folly/portability/Environment.h>
29 #include <folly/portability/Fcntl.h>
30 #include <folly/portability/GTest.h>
31
32 using namespace folly;
33 using namespace folly::test;
34
35 TEST(TemporaryFile, Simple) {
36   int fd = -1;
37   char c = 'x';
38   {
39     TemporaryFile f;
40     EXPECT_FALSE(f.path().empty());
41     EXPECT_TRUE(f.path().is_absolute());
42     fd = f.fd();
43     EXPECT_LE(0, fd);
44     ssize_t r = write(fd, &c, 1);
45     EXPECT_EQ(1, r);
46   }
47
48   msvcSuppressAbortOnInvalidParams([&] {
49     // The file must have been closed.  This assumes that no other thread
50     // has opened another file in the meanwhile, which is a sane assumption
51     // to make in this test.
52     ssize_t r = write(fd, &c, 1);
53     int savedErrno = errno;
54     EXPECT_EQ(-1, r);
55     EXPECT_EQ(EBADF, savedErrno);
56   });
57 }
58
59 TEST(TemporaryFile, Prefix) {
60   TemporaryFile f("Foo");
61   EXPECT_TRUE(f.path().is_absolute());
62   EXPECT_TRUE(boost::algorithm::starts_with(f.path().filename().native(),
63                                             "Foo"));
64 }
65
66 TEST(TemporaryFile, PathPrefix) {
67   TemporaryFile f("Foo", ".");
68   EXPECT_EQ(fs::path("."), f.path().parent_path());
69   EXPECT_TRUE(boost::algorithm::starts_with(f.path().filename().native(),
70                                             "Foo"));
71 }
72
73 TEST(TemporaryFile, NoSuchPath) {
74   EXPECT_THROW({TemporaryFile f("", "/no/such/path");},
75                std::system_error);
76 }
77
78 void testTemporaryDirectory(TemporaryDirectory::Scope scope) {
79   fs::path path;
80   {
81     TemporaryDirectory d("", "", scope);
82     path = d.path();
83     EXPECT_FALSE(path.empty());
84     EXPECT_TRUE(path.is_absolute());
85     EXPECT_TRUE(fs::exists(path));
86     EXPECT_TRUE(fs::is_directory(path));
87
88     fs::path fp = path / "bar";
89     int fd = open(fp.string().c_str(), O_RDWR | O_CREAT | O_TRUNC, 0666);
90     EXPECT_NE(fd, -1);
91     close(fd);
92
93     TemporaryFile f("Foo", d.path());
94     EXPECT_EQ(d.path(), f.path().parent_path());
95   }
96   bool exists = (scope == TemporaryDirectory::Scope::PERMANENT);
97   EXPECT_EQ(exists, fs::exists(path));
98 }
99
100 TEST(TemporaryDirectory, Permanent) {
101   testTemporaryDirectory(TemporaryDirectory::Scope::PERMANENT);
102 }
103
104 TEST(TemporaryDirectory, DeleteOnDestruction) {
105   testTemporaryDirectory(TemporaryDirectory::Scope::DELETE_ON_DESTRUCTION);
106 }
107
108 void expectTempdirExists(const TemporaryDirectory& d) {
109   EXPECT_FALSE(d.path().empty());
110   EXPECT_TRUE(fs::exists(d.path()));
111   EXPECT_TRUE(fs::is_directory(d.path()));
112 }
113
114 TEST(TemporaryDirectory, SafelyMove) {
115   std::unique_ptr<TemporaryDirectory> dir;
116   TemporaryDirectory dir2;
117   {
118     auto scope = TemporaryDirectory::Scope::DELETE_ON_DESTRUCTION;
119     TemporaryDirectory d("", "", scope);
120     TemporaryDirectory d2("", "", scope);
121     expectTempdirExists(d);
122     expectTempdirExists(d2);
123
124     dir = folly::make_unique<TemporaryDirectory>(std::move(d));
125     dir2 = std::move(d2);
126   }
127
128   expectTempdirExists(*dir);
129   expectTempdirExists(dir2);
130 }
131
132 TEST(ChangeToTempDir, ChangeDir) {
133   auto pwd1 = fs::current_path();
134   {
135     ChangeToTempDir d;
136     EXPECT_NE(pwd1, fs::current_path());
137   }
138   EXPECT_EQ(pwd1, fs::current_path());
139 }
140
141 TEST(PCREPatternMatch, Simple) {
142   EXPECT_PCRE_MATCH(".*a.c.*", "gabca");
143   EXPECT_NO_PCRE_MATCH("a.c", "gabca");
144   EXPECT_NO_PCRE_MATCH(".*ac.*", "gabca");
145 }
146
147 TEST(CaptureFD, GlogPatterns) {
148   CaptureFD err(fileno(stderr));
149   LOG(INFO) << "All is well";
150   EXPECT_NO_PCRE_MATCH(glogErrOrWarnPattern(), err.readIncremental());
151   {
152     LOG(ERROR) << "Uh-oh";
153     auto s = err.readIncremental();
154     EXPECT_PCRE_MATCH(glogErrorPattern(), s);
155     EXPECT_NO_PCRE_MATCH(glogWarningPattern(), s);
156     EXPECT_PCRE_MATCH(glogErrOrWarnPattern(), s);
157   }
158   {
159     LOG(WARNING) << "Oops";
160     auto s = err.readIncremental();
161     EXPECT_NO_PCRE_MATCH(glogErrorPattern(), s);
162     EXPECT_PCRE_MATCH(glogWarningPattern(), s);
163     EXPECT_PCRE_MATCH(glogErrOrWarnPattern(), s);
164   }
165 }
166
167 TEST(CaptureFD, ChunkCob) {
168   std::vector<std::string> chunks;
169   {
170     CaptureFD err(fileno(stderr), [&](StringPiece p) {
171       chunks.emplace_back(p.str());
172       switch (chunks.size()) {
173         case 1:
174           EXPECT_PCRE_MATCH(".*foo.*bar.*", p);
175           break;
176         case 2:
177           EXPECT_PCRE_MATCH("[^\n]*baz.*", p);
178           break;
179         default:
180           FAIL() << "Got too many chunks: " << chunks.size();
181       }
182     });
183     LOG(INFO) << "foo";
184     LOG(INFO) << "bar";
185     EXPECT_PCRE_MATCH(".*foo.*bar.*", err.read());
186     auto chunk = err.readIncremental();
187     EXPECT_EQ(chunks.at(0), chunk);
188     LOG(INFO) << "baz";
189     EXPECT_PCRE_MATCH(".*foo.*bar.*baz.*", err.read());
190   }
191   EXPECT_EQ(2, chunks.size());
192 }
193
194
195 class EnvVarSaverTest : public testing::Test {};
196
197 TEST_F(EnvVarSaverTest, ExampleNew) {
198   auto key = "hahahahaha";
199   EXPECT_EQ(nullptr, getenv(key));
200
201   PCHECK(0 == setenv(key, "", true));
202   EXPECT_STREQ("", getenv(key));
203   PCHECK(0 == unsetenv(key));
204   EXPECT_EQ(nullptr, getenv(key));
205
206   auto saver = make_unique<EnvVarSaver>();
207   PCHECK(0 == setenv(key, "blah", true));
208   EXPECT_EQ("blah", std::string{getenv(key)});
209   saver = nullptr;
210   EXPECT_EQ(nullptr, getenv(key));
211 }
212
213 TEST_F(EnvVarSaverTest, ExampleExisting) {
214   auto key = "PATH";
215   EXPECT_NE(nullptr, getenv(key));
216   auto value = std::string{getenv(key)};
217
218   auto saver = make_unique<EnvVarSaver>();
219   PCHECK(0 == setenv(key, "blah", true));
220   EXPECT_EQ("blah", std::string{getenv(key)});
221   saver = nullptr;
222   EXPECT_TRUE(value == getenv(key));
223 }
224
225 TEST_F(EnvVarSaverTest, ExampleDeleting) {
226   auto key = "PATH";
227   EXPECT_NE(nullptr, getenv(key));
228   auto value = std::string{getenv(key)};
229
230   auto saver = make_unique<EnvVarSaver>();
231   PCHECK(0 == unsetenv(key));
232   EXPECT_EQ(nullptr, getenv(key));
233   saver = nullptr;
234   EXPECT_TRUE(value == getenv(key));
235 }
236
237 int main(int argc, char *argv[]) {
238   testing::InitGoogleTest(&argc, argv);
239   gflags::ParseCommandLineFlags(&argc, &argv, true);
240   return RUN_ALL_TESTS();
241 }