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