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