73ccf0e39718f46f7b3829cd8a96e09bb4e793a1
[folly.git] / folly / test / FileTest.cpp
1 /*
2  * Copyright 2017 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/File.h>
18
19 #include <folly/String.h>
20 #include <folly/portability/Fcntl.h>
21 #include <folly/portability/GTest.h>
22
23 using namespace folly;
24
25 namespace {
26 void expectWouldBlock(ssize_t r) {
27   int savedErrno = errno;
28   EXPECT_EQ(-1, r);
29   EXPECT_EQ(EAGAIN, savedErrno) << errnoStr(savedErrno);
30 }
31 void expectOK(ssize_t r) {
32   int savedErrno = errno;
33   EXPECT_LE(0, r) << ": errno=" << errnoStr(savedErrno);
34 }
35 }  // namespace
36
37 TEST(File, Simple) {
38   // Open a file, ensure it's indeed open for reading
39   char buf = 'x';
40   {
41     File f("/etc/hosts");
42     EXPECT_NE(-1, f.fd());
43     EXPECT_EQ(1, ::read(f.fd(), &buf, 1));
44     f.close();
45     EXPECT_EQ(-1, f.fd());
46   }
47 }
48
49 TEST(File, SimpleStringPiece) {
50   char buf = 'x';
51   File f(StringPiece("/etc/hosts"));
52   EXPECT_NE(-1, f.fd());
53   EXPECT_EQ(1, ::read(f.fd(), &buf, 1));
54   f.close();
55   EXPECT_EQ(-1, f.fd());
56 }
57
58 TEST(File, OwnsFd) {
59   // Wrap a file descriptor, make sure that ownsFd works
60   // We'll test that the file descriptor is closed by closing the writing
61   // end of a pipe and making sure that a non-blocking read from the reading
62   // end returns 0.
63
64   char buf = 'x';
65   int p[2];
66   expectOK(::pipe(p));
67   int flags = ::fcntl(p[0], F_GETFL);
68   expectOK(flags);
69   expectOK(::fcntl(p[0], F_SETFL, flags | O_NONBLOCK));
70   expectWouldBlock(::read(p[0], &buf, 1));
71   {
72     File f(p[1]);
73     EXPECT_EQ(p[1], f.fd());
74   }
75   // Ensure that moving the file doesn't close it
76   {
77     File f(p[1]);
78     EXPECT_EQ(p[1], f.fd());
79     File f1(std::move(f));
80     EXPECT_EQ(-1, f.fd());
81     EXPECT_EQ(p[1], f1.fd());
82   }
83   expectWouldBlock(::read(p[0], &buf, 1));  // not closed
84   {
85     File f(p[1], true);
86     EXPECT_EQ(p[1], f.fd());
87   }
88   ssize_t r = ::read(p[0], &buf, 1);  // eof
89   expectOK(r);
90   EXPECT_EQ(0, r);
91   ::close(p[0]);
92 }
93
94 TEST(File, Release) {
95   File in(STDOUT_FILENO, false);
96   CHECK_EQ(STDOUT_FILENO, in.release());
97   CHECK_EQ(-1, in.release());
98 }
99
100 #define EXPECT_CONTAINS(haystack, needle) \
101   EXPECT_NE(::std::string::npos, ::folly::StringPiece(haystack).find(needle)) \
102     << "Haystack: '" << haystack << "'\nNeedle: '" << needle << "'";
103
104 TEST(File, UsefulError) {
105   try {
106     File("does_not_exist.txt", 0, 0666);
107   } catch (const std::runtime_error& e) {
108     EXPECT_CONTAINS(e.what(), "does_not_exist.txt");
109     EXPECT_CONTAINS(e.what(), "0666");
110   }
111 }
112
113 TEST(File, Truthy) {
114   File temp = File::temporary();
115
116   EXPECT_TRUE(bool(temp));
117
118   if (temp) {
119     ;
120   } else {
121     EXPECT_FALSE(true);
122   }
123
124   if (File file = File::temporary()) {
125     ;
126   } else {
127     EXPECT_FALSE(true);
128   }
129
130   EXPECT_FALSE(bool(File()));
131   if (File()) {
132     EXPECT_TRUE(false);
133   }
134   if (File notOpened = File()) {
135     EXPECT_TRUE(false);
136   }
137 }