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