xref: /aosp_15_r20/external/leveldb/util/env_posix_test.cc (revision 9507f98c5f32dee4b5f9e4a38cd499f3ff5c4490)
1*9507f98cSAndroid Build Coastguard Worker // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2*9507f98cSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*9507f98cSAndroid Build Coastguard Worker // found in the LICENSE file. See the AUTHORS file for names of contributors.
4*9507f98cSAndroid Build Coastguard Worker 
5*9507f98cSAndroid Build Coastguard Worker #include <sys/resource.h>
6*9507f98cSAndroid Build Coastguard Worker #include <sys/wait.h>
7*9507f98cSAndroid Build Coastguard Worker #include <unistd.h>
8*9507f98cSAndroid Build Coastguard Worker 
9*9507f98cSAndroid Build Coastguard Worker #include <cstdio>
10*9507f98cSAndroid Build Coastguard Worker #include <cstdlib>
11*9507f98cSAndroid Build Coastguard Worker #include <cstring>
12*9507f98cSAndroid Build Coastguard Worker #include <string>
13*9507f98cSAndroid Build Coastguard Worker #include <unordered_set>
14*9507f98cSAndroid Build Coastguard Worker #include <vector>
15*9507f98cSAndroid Build Coastguard Worker 
16*9507f98cSAndroid Build Coastguard Worker #include "gtest/gtest.h"
17*9507f98cSAndroid Build Coastguard Worker #include "leveldb/env.h"
18*9507f98cSAndroid Build Coastguard Worker #include "port/port.h"
19*9507f98cSAndroid Build Coastguard Worker #include "util/env_posix_test_helper.h"
20*9507f98cSAndroid Build Coastguard Worker #include "util/testutil.h"
21*9507f98cSAndroid Build Coastguard Worker 
22*9507f98cSAndroid Build Coastguard Worker #if HAVE_O_CLOEXEC
23*9507f98cSAndroid Build Coastguard Worker 
24*9507f98cSAndroid Build Coastguard Worker namespace {
25*9507f98cSAndroid Build Coastguard Worker 
26*9507f98cSAndroid Build Coastguard Worker // Exit codes for the helper process spawned by TestCloseOnExec* tests.
27*9507f98cSAndroid Build Coastguard Worker // Useful for debugging test failures.
28*9507f98cSAndroid Build Coastguard Worker constexpr int kTextCloseOnExecHelperExecFailedCode = 61;
29*9507f98cSAndroid Build Coastguard Worker constexpr int kTextCloseOnExecHelperDup2FailedCode = 62;
30*9507f98cSAndroid Build Coastguard Worker constexpr int kTextCloseOnExecHelperFoundOpenFdCode = 63;
31*9507f98cSAndroid Build Coastguard Worker 
32*9507f98cSAndroid Build Coastguard Worker // Global set by main() and read in TestCloseOnExec.
33*9507f98cSAndroid Build Coastguard Worker //
34*9507f98cSAndroid Build Coastguard Worker // The argv[0] value is stored in a std::vector instead of a std::string because
35*9507f98cSAndroid Build Coastguard Worker // std::string does not return a mutable pointer to its buffer until C++17.
36*9507f98cSAndroid Build Coastguard Worker //
37*9507f98cSAndroid Build Coastguard Worker // The vector stores the string pointed to by argv[0], plus the trailing null.
GetArgvZero()38*9507f98cSAndroid Build Coastguard Worker std::vector<char>* GetArgvZero() {
39*9507f98cSAndroid Build Coastguard Worker   static std::vector<char> program_name;
40*9507f98cSAndroid Build Coastguard Worker   return &program_name;
41*9507f98cSAndroid Build Coastguard Worker }
42*9507f98cSAndroid Build Coastguard Worker 
43*9507f98cSAndroid Build Coastguard Worker // Command-line switch used to run this test as the CloseOnExecSwitch helper.
44*9507f98cSAndroid Build Coastguard Worker static const char kTestCloseOnExecSwitch[] = "--test-close-on-exec-helper";
45*9507f98cSAndroid Build Coastguard Worker 
46*9507f98cSAndroid Build Coastguard Worker // Executed in a separate process by TestCloseOnExec* tests.
47*9507f98cSAndroid Build Coastguard Worker //
48*9507f98cSAndroid Build Coastguard Worker // main() delegates to this function when the test executable is launched with
49*9507f98cSAndroid Build Coastguard Worker // a special command-line switch. TestCloseOnExec* tests fork()+exec() the test
50*9507f98cSAndroid Build Coastguard Worker // executable and pass the special command-line switch.
51*9507f98cSAndroid Build Coastguard Worker //
52*9507f98cSAndroid Build Coastguard Worker 
53*9507f98cSAndroid Build Coastguard Worker // main() delegates to this function when the test executable is launched with
54*9507f98cSAndroid Build Coastguard Worker // a special command-line switch. TestCloseOnExec* tests fork()+exec() the test
55*9507f98cSAndroid Build Coastguard Worker // executable and pass the special command-line switch.
56*9507f98cSAndroid Build Coastguard Worker //
57*9507f98cSAndroid Build Coastguard Worker // When main() delegates to this function, the process probes whether a given
58*9507f98cSAndroid Build Coastguard Worker // file descriptor is open, and communicates the result via its exit code.
TestCloseOnExecHelperMain(char * pid_arg)59*9507f98cSAndroid Build Coastguard Worker int TestCloseOnExecHelperMain(char* pid_arg) {
60*9507f98cSAndroid Build Coastguard Worker   int fd = std::atoi(pid_arg);
61*9507f98cSAndroid Build Coastguard Worker   // When given the same file descriptor twice, dup2() returns -1 if the
62*9507f98cSAndroid Build Coastguard Worker   // file descriptor is closed, or the given file descriptor if it is open.
63*9507f98cSAndroid Build Coastguard Worker   if (::dup2(fd, fd) == fd) {
64*9507f98cSAndroid Build Coastguard Worker     std::fprintf(stderr, "Unexpected open fd %d\n", fd);
65*9507f98cSAndroid Build Coastguard Worker     return kTextCloseOnExecHelperFoundOpenFdCode;
66*9507f98cSAndroid Build Coastguard Worker   }
67*9507f98cSAndroid Build Coastguard Worker   // Double-check that dup2() is saying the file descriptor is closed.
68*9507f98cSAndroid Build Coastguard Worker   if (errno != EBADF) {
69*9507f98cSAndroid Build Coastguard Worker     std::fprintf(stderr, "Unexpected errno after calling dup2 on fd %d: %s\n",
70*9507f98cSAndroid Build Coastguard Worker                  fd, std::strerror(errno));
71*9507f98cSAndroid Build Coastguard Worker     return kTextCloseOnExecHelperDup2FailedCode;
72*9507f98cSAndroid Build Coastguard Worker   }
73*9507f98cSAndroid Build Coastguard Worker   return 0;
74*9507f98cSAndroid Build Coastguard Worker }
75*9507f98cSAndroid Build Coastguard Worker 
76*9507f98cSAndroid Build Coastguard Worker // File descriptors are small non-negative integers.
77*9507f98cSAndroid Build Coastguard Worker //
78*9507f98cSAndroid Build Coastguard Worker // Returns void so the implementation can use ASSERT_EQ.
GetMaxFileDescriptor(int * result_fd)79*9507f98cSAndroid Build Coastguard Worker void GetMaxFileDescriptor(int* result_fd) {
80*9507f98cSAndroid Build Coastguard Worker   // Get the maximum file descriptor number.
81*9507f98cSAndroid Build Coastguard Worker   ::rlimit fd_rlimit;
82*9507f98cSAndroid Build Coastguard Worker   ASSERT_EQ(0, ::getrlimit(RLIMIT_NOFILE, &fd_rlimit));
83*9507f98cSAndroid Build Coastguard Worker   *result_fd = fd_rlimit.rlim_cur;
84*9507f98cSAndroid Build Coastguard Worker }
85*9507f98cSAndroid Build Coastguard Worker 
86*9507f98cSAndroid Build Coastguard Worker // Iterates through all possible FDs and returns the currently open ones.
87*9507f98cSAndroid Build Coastguard Worker //
88*9507f98cSAndroid Build Coastguard Worker // Returns void so the implementation can use ASSERT_EQ.
GetOpenFileDescriptors(std::unordered_set<int> * open_fds)89*9507f98cSAndroid Build Coastguard Worker void GetOpenFileDescriptors(std::unordered_set<int>* open_fds) {
90*9507f98cSAndroid Build Coastguard Worker   int max_fd = 0;
91*9507f98cSAndroid Build Coastguard Worker   GetMaxFileDescriptor(&max_fd);
92*9507f98cSAndroid Build Coastguard Worker 
93*9507f98cSAndroid Build Coastguard Worker   for (int fd = 0; fd < max_fd; ++fd) {
94*9507f98cSAndroid Build Coastguard Worker     if (::dup2(fd, fd) != fd) {
95*9507f98cSAndroid Build Coastguard Worker       // When given the same file descriptor twice, dup2() returns -1 if the
96*9507f98cSAndroid Build Coastguard Worker       // file descriptor is closed, or the given file descriptor if it is open.
97*9507f98cSAndroid Build Coastguard Worker       //
98*9507f98cSAndroid Build Coastguard Worker       // Double-check that dup2() is saying the fd is closed.
99*9507f98cSAndroid Build Coastguard Worker       ASSERT_EQ(EBADF, errno)
100*9507f98cSAndroid Build Coastguard Worker           << "dup2() should set errno to EBADF on closed file descriptors";
101*9507f98cSAndroid Build Coastguard Worker       continue;
102*9507f98cSAndroid Build Coastguard Worker     }
103*9507f98cSAndroid Build Coastguard Worker     open_fds->insert(fd);
104*9507f98cSAndroid Build Coastguard Worker   }
105*9507f98cSAndroid Build Coastguard Worker }
106*9507f98cSAndroid Build Coastguard Worker 
107*9507f98cSAndroid Build Coastguard Worker // Finds an FD open since a previous call to GetOpenFileDescriptors().
108*9507f98cSAndroid Build Coastguard Worker //
109*9507f98cSAndroid Build Coastguard Worker // |baseline_open_fds| is the result of a previous GetOpenFileDescriptors()
110*9507f98cSAndroid Build Coastguard Worker // call. Assumes that exactly one FD was opened since that call.
111*9507f98cSAndroid Build Coastguard Worker //
112*9507f98cSAndroid Build Coastguard Worker // Returns void so the implementation can use ASSERT_EQ.
GetNewlyOpenedFileDescriptor(const std::unordered_set<int> & baseline_open_fds,int * result_fd)113*9507f98cSAndroid Build Coastguard Worker void GetNewlyOpenedFileDescriptor(
114*9507f98cSAndroid Build Coastguard Worker     const std::unordered_set<int>& baseline_open_fds, int* result_fd) {
115*9507f98cSAndroid Build Coastguard Worker   std::unordered_set<int> open_fds;
116*9507f98cSAndroid Build Coastguard Worker   GetOpenFileDescriptors(&open_fds);
117*9507f98cSAndroid Build Coastguard Worker   for (int fd : baseline_open_fds) {
118*9507f98cSAndroid Build Coastguard Worker     ASSERT_EQ(1, open_fds.count(fd))
119*9507f98cSAndroid Build Coastguard Worker         << "Previously opened file descriptor was closed during test setup";
120*9507f98cSAndroid Build Coastguard Worker     open_fds.erase(fd);
121*9507f98cSAndroid Build Coastguard Worker   }
122*9507f98cSAndroid Build Coastguard Worker   ASSERT_EQ(1, open_fds.size())
123*9507f98cSAndroid Build Coastguard Worker       << "Expected exactly one newly opened file descriptor during test setup";
124*9507f98cSAndroid Build Coastguard Worker   *result_fd = *open_fds.begin();
125*9507f98cSAndroid Build Coastguard Worker }
126*9507f98cSAndroid Build Coastguard Worker 
127*9507f98cSAndroid Build Coastguard Worker // Check that a fork()+exec()-ed child process does not have an extra open FD.
CheckCloseOnExecDoesNotLeakFDs(const std::unordered_set<int> & baseline_open_fds)128*9507f98cSAndroid Build Coastguard Worker void CheckCloseOnExecDoesNotLeakFDs(
129*9507f98cSAndroid Build Coastguard Worker     const std::unordered_set<int>& baseline_open_fds) {
130*9507f98cSAndroid Build Coastguard Worker   // Prepare the argument list for the child process.
131*9507f98cSAndroid Build Coastguard Worker   // execv() wants mutable buffers.
132*9507f98cSAndroid Build Coastguard Worker   char switch_buffer[sizeof(kTestCloseOnExecSwitch)];
133*9507f98cSAndroid Build Coastguard Worker   std::memcpy(switch_buffer, kTestCloseOnExecSwitch,
134*9507f98cSAndroid Build Coastguard Worker               sizeof(kTestCloseOnExecSwitch));
135*9507f98cSAndroid Build Coastguard Worker 
136*9507f98cSAndroid Build Coastguard Worker   int probed_fd;
137*9507f98cSAndroid Build Coastguard Worker   GetNewlyOpenedFileDescriptor(baseline_open_fds, &probed_fd);
138*9507f98cSAndroid Build Coastguard Worker   std::string fd_string = std::to_string(probed_fd);
139*9507f98cSAndroid Build Coastguard Worker   std::vector<char> fd_buffer(fd_string.begin(), fd_string.end());
140*9507f98cSAndroid Build Coastguard Worker   fd_buffer.emplace_back('\0');
141*9507f98cSAndroid Build Coastguard Worker 
142*9507f98cSAndroid Build Coastguard Worker   // The helper process is launched with the command below.
143*9507f98cSAndroid Build Coastguard Worker   //      env_posix_tests --test-close-on-exec-helper 3
144*9507f98cSAndroid Build Coastguard Worker   char* child_argv[] = {GetArgvZero()->data(), switch_buffer, fd_buffer.data(),
145*9507f98cSAndroid Build Coastguard Worker                         nullptr};
146*9507f98cSAndroid Build Coastguard Worker 
147*9507f98cSAndroid Build Coastguard Worker   constexpr int kForkInChildProcessReturnValue = 0;
148*9507f98cSAndroid Build Coastguard Worker   int child_pid = fork();
149*9507f98cSAndroid Build Coastguard Worker   if (child_pid == kForkInChildProcessReturnValue) {
150*9507f98cSAndroid Build Coastguard Worker     ::execv(child_argv[0], child_argv);
151*9507f98cSAndroid Build Coastguard Worker     std::fprintf(stderr, "Error spawning child process: %s\n", strerror(errno));
152*9507f98cSAndroid Build Coastguard Worker     std::exit(kTextCloseOnExecHelperExecFailedCode);
153*9507f98cSAndroid Build Coastguard Worker   }
154*9507f98cSAndroid Build Coastguard Worker 
155*9507f98cSAndroid Build Coastguard Worker   int child_status = 0;
156*9507f98cSAndroid Build Coastguard Worker   ASSERT_EQ(child_pid, ::waitpid(child_pid, &child_status, 0));
157*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(WIFEXITED(child_status))
158*9507f98cSAndroid Build Coastguard Worker       << "The helper process did not exit with an exit code";
159*9507f98cSAndroid Build Coastguard Worker   ASSERT_EQ(0, WEXITSTATUS(child_status))
160*9507f98cSAndroid Build Coastguard Worker       << "The helper process encountered an error";
161*9507f98cSAndroid Build Coastguard Worker }
162*9507f98cSAndroid Build Coastguard Worker 
163*9507f98cSAndroid Build Coastguard Worker }  // namespace
164*9507f98cSAndroid Build Coastguard Worker 
165*9507f98cSAndroid Build Coastguard Worker #endif  // HAVE_O_CLOEXEC
166*9507f98cSAndroid Build Coastguard Worker 
167*9507f98cSAndroid Build Coastguard Worker namespace leveldb {
168*9507f98cSAndroid Build Coastguard Worker 
169*9507f98cSAndroid Build Coastguard Worker static const int kReadOnlyFileLimit = 4;
170*9507f98cSAndroid Build Coastguard Worker static const int kMMapLimit = 4;
171*9507f98cSAndroid Build Coastguard Worker 
172*9507f98cSAndroid Build Coastguard Worker class EnvPosixTest : public testing::Test {
173*9507f98cSAndroid Build Coastguard Worker  public:
SetFileLimits(int read_only_file_limit,int mmap_limit)174*9507f98cSAndroid Build Coastguard Worker   static void SetFileLimits(int read_only_file_limit, int mmap_limit) {
175*9507f98cSAndroid Build Coastguard Worker     EnvPosixTestHelper::SetReadOnlyFDLimit(read_only_file_limit);
176*9507f98cSAndroid Build Coastguard Worker     EnvPosixTestHelper::SetReadOnlyMMapLimit(mmap_limit);
177*9507f98cSAndroid Build Coastguard Worker   }
178*9507f98cSAndroid Build Coastguard Worker 
EnvPosixTest()179*9507f98cSAndroid Build Coastguard Worker   EnvPosixTest() : env_(Env::Default()) {}
180*9507f98cSAndroid Build Coastguard Worker 
181*9507f98cSAndroid Build Coastguard Worker   Env* env_;
182*9507f98cSAndroid Build Coastguard Worker };
183*9507f98cSAndroid Build Coastguard Worker 
TEST_F(EnvPosixTest,TestOpenOnRead)184*9507f98cSAndroid Build Coastguard Worker TEST_F(EnvPosixTest, TestOpenOnRead) {
185*9507f98cSAndroid Build Coastguard Worker   // Write some test data to a single file that will be opened |n| times.
186*9507f98cSAndroid Build Coastguard Worker   std::string test_dir;
187*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->GetTestDirectory(&test_dir));
188*9507f98cSAndroid Build Coastguard Worker   std::string test_file = test_dir + "/open_on_read.txt";
189*9507f98cSAndroid Build Coastguard Worker 
190*9507f98cSAndroid Build Coastguard Worker   FILE* f = std::fopen(test_file.c_str(), "we");
191*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(f != nullptr);
192*9507f98cSAndroid Build Coastguard Worker   const char kFileData[] = "abcdefghijklmnopqrstuvwxyz";
193*9507f98cSAndroid Build Coastguard Worker   fputs(kFileData, f);
194*9507f98cSAndroid Build Coastguard Worker   std::fclose(f);
195*9507f98cSAndroid Build Coastguard Worker 
196*9507f98cSAndroid Build Coastguard Worker   // Open test file some number above the sum of the two limits to force
197*9507f98cSAndroid Build Coastguard Worker   // open-on-read behavior of POSIX Env leveldb::RandomAccessFile.
198*9507f98cSAndroid Build Coastguard Worker   const int kNumFiles = kReadOnlyFileLimit + kMMapLimit + 5;
199*9507f98cSAndroid Build Coastguard Worker   leveldb::RandomAccessFile* files[kNumFiles] = {0};
200*9507f98cSAndroid Build Coastguard Worker   for (int i = 0; i < kNumFiles; i++) {
201*9507f98cSAndroid Build Coastguard Worker     ASSERT_LEVELDB_OK(env_->NewRandomAccessFile(test_file, &files[i]));
202*9507f98cSAndroid Build Coastguard Worker   }
203*9507f98cSAndroid Build Coastguard Worker   char scratch;
204*9507f98cSAndroid Build Coastguard Worker   Slice read_result;
205*9507f98cSAndroid Build Coastguard Worker   for (int i = 0; i < kNumFiles; i++) {
206*9507f98cSAndroid Build Coastguard Worker     ASSERT_LEVELDB_OK(files[i]->Read(i, 1, &read_result, &scratch));
207*9507f98cSAndroid Build Coastguard Worker     ASSERT_EQ(kFileData[i], read_result[0]);
208*9507f98cSAndroid Build Coastguard Worker   }
209*9507f98cSAndroid Build Coastguard Worker   for (int i = 0; i < kNumFiles; i++) {
210*9507f98cSAndroid Build Coastguard Worker     delete files[i];
211*9507f98cSAndroid Build Coastguard Worker   }
212*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->RemoveFile(test_file));
213*9507f98cSAndroid Build Coastguard Worker }
214*9507f98cSAndroid Build Coastguard Worker 
215*9507f98cSAndroid Build Coastguard Worker #if HAVE_O_CLOEXEC
216*9507f98cSAndroid Build Coastguard Worker 
TEST_F(EnvPosixTest,TestCloseOnExecSequentialFile)217*9507f98cSAndroid Build Coastguard Worker TEST_F(EnvPosixTest, TestCloseOnExecSequentialFile) {
218*9507f98cSAndroid Build Coastguard Worker   std::unordered_set<int> open_fds;
219*9507f98cSAndroid Build Coastguard Worker   GetOpenFileDescriptors(&open_fds);
220*9507f98cSAndroid Build Coastguard Worker 
221*9507f98cSAndroid Build Coastguard Worker   std::string test_dir;
222*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->GetTestDirectory(&test_dir));
223*9507f98cSAndroid Build Coastguard Worker   std::string file_path = test_dir + "/close_on_exec_sequential.txt";
224*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(WriteStringToFile(env_, "0123456789", file_path));
225*9507f98cSAndroid Build Coastguard Worker 
226*9507f98cSAndroid Build Coastguard Worker   leveldb::SequentialFile* file = nullptr;
227*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->NewSequentialFile(file_path, &file));
228*9507f98cSAndroid Build Coastguard Worker   CheckCloseOnExecDoesNotLeakFDs(open_fds);
229*9507f98cSAndroid Build Coastguard Worker   delete file;
230*9507f98cSAndroid Build Coastguard Worker 
231*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->RemoveFile(file_path));
232*9507f98cSAndroid Build Coastguard Worker }
233*9507f98cSAndroid Build Coastguard Worker 
TEST_F(EnvPosixTest,TestCloseOnExecRandomAccessFile)234*9507f98cSAndroid Build Coastguard Worker TEST_F(EnvPosixTest, TestCloseOnExecRandomAccessFile) {
235*9507f98cSAndroid Build Coastguard Worker   std::unordered_set<int> open_fds;
236*9507f98cSAndroid Build Coastguard Worker   GetOpenFileDescriptors(&open_fds);
237*9507f98cSAndroid Build Coastguard Worker 
238*9507f98cSAndroid Build Coastguard Worker   std::string test_dir;
239*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->GetTestDirectory(&test_dir));
240*9507f98cSAndroid Build Coastguard Worker   std::string file_path = test_dir + "/close_on_exec_random_access.txt";
241*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(WriteStringToFile(env_, "0123456789", file_path));
242*9507f98cSAndroid Build Coastguard Worker 
243*9507f98cSAndroid Build Coastguard Worker   // Exhaust the RandomAccessFile mmap limit. This way, the test
244*9507f98cSAndroid Build Coastguard Worker   // RandomAccessFile instance below is backed by a file descriptor, not by an
245*9507f98cSAndroid Build Coastguard Worker   // mmap region.
246*9507f98cSAndroid Build Coastguard Worker   leveldb::RandomAccessFile* mmapped_files[kReadOnlyFileLimit] = {nullptr};
247*9507f98cSAndroid Build Coastguard Worker   for (int i = 0; i < kReadOnlyFileLimit; i++) {
248*9507f98cSAndroid Build Coastguard Worker     ASSERT_LEVELDB_OK(env_->NewRandomAccessFile(file_path, &mmapped_files[i]));
249*9507f98cSAndroid Build Coastguard Worker   }
250*9507f98cSAndroid Build Coastguard Worker 
251*9507f98cSAndroid Build Coastguard Worker   leveldb::RandomAccessFile* file = nullptr;
252*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->NewRandomAccessFile(file_path, &file));
253*9507f98cSAndroid Build Coastguard Worker   CheckCloseOnExecDoesNotLeakFDs(open_fds);
254*9507f98cSAndroid Build Coastguard Worker   delete file;
255*9507f98cSAndroid Build Coastguard Worker 
256*9507f98cSAndroid Build Coastguard Worker   for (int i = 0; i < kReadOnlyFileLimit; i++) {
257*9507f98cSAndroid Build Coastguard Worker     delete mmapped_files[i];
258*9507f98cSAndroid Build Coastguard Worker   }
259*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->RemoveFile(file_path));
260*9507f98cSAndroid Build Coastguard Worker }
261*9507f98cSAndroid Build Coastguard Worker 
TEST_F(EnvPosixTest,TestCloseOnExecWritableFile)262*9507f98cSAndroid Build Coastguard Worker TEST_F(EnvPosixTest, TestCloseOnExecWritableFile) {
263*9507f98cSAndroid Build Coastguard Worker   std::unordered_set<int> open_fds;
264*9507f98cSAndroid Build Coastguard Worker   GetOpenFileDescriptors(&open_fds);
265*9507f98cSAndroid Build Coastguard Worker 
266*9507f98cSAndroid Build Coastguard Worker   std::string test_dir;
267*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->GetTestDirectory(&test_dir));
268*9507f98cSAndroid Build Coastguard Worker   std::string file_path = test_dir + "/close_on_exec_writable.txt";
269*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(WriteStringToFile(env_, "0123456789", file_path));
270*9507f98cSAndroid Build Coastguard Worker 
271*9507f98cSAndroid Build Coastguard Worker   leveldb::WritableFile* file = nullptr;
272*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->NewWritableFile(file_path, &file));
273*9507f98cSAndroid Build Coastguard Worker   CheckCloseOnExecDoesNotLeakFDs(open_fds);
274*9507f98cSAndroid Build Coastguard Worker   delete file;
275*9507f98cSAndroid Build Coastguard Worker 
276*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->RemoveFile(file_path));
277*9507f98cSAndroid Build Coastguard Worker }
278*9507f98cSAndroid Build Coastguard Worker 
TEST_F(EnvPosixTest,TestCloseOnExecAppendableFile)279*9507f98cSAndroid Build Coastguard Worker TEST_F(EnvPosixTest, TestCloseOnExecAppendableFile) {
280*9507f98cSAndroid Build Coastguard Worker   std::unordered_set<int> open_fds;
281*9507f98cSAndroid Build Coastguard Worker   GetOpenFileDescriptors(&open_fds);
282*9507f98cSAndroid Build Coastguard Worker 
283*9507f98cSAndroid Build Coastguard Worker   std::string test_dir;
284*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->GetTestDirectory(&test_dir));
285*9507f98cSAndroid Build Coastguard Worker   std::string file_path = test_dir + "/close_on_exec_appendable.txt";
286*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(WriteStringToFile(env_, "0123456789", file_path));
287*9507f98cSAndroid Build Coastguard Worker 
288*9507f98cSAndroid Build Coastguard Worker   leveldb::WritableFile* file = nullptr;
289*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->NewAppendableFile(file_path, &file));
290*9507f98cSAndroid Build Coastguard Worker   CheckCloseOnExecDoesNotLeakFDs(open_fds);
291*9507f98cSAndroid Build Coastguard Worker   delete file;
292*9507f98cSAndroid Build Coastguard Worker 
293*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->RemoveFile(file_path));
294*9507f98cSAndroid Build Coastguard Worker }
295*9507f98cSAndroid Build Coastguard Worker 
TEST_F(EnvPosixTest,TestCloseOnExecLockFile)296*9507f98cSAndroid Build Coastguard Worker TEST_F(EnvPosixTest, TestCloseOnExecLockFile) {
297*9507f98cSAndroid Build Coastguard Worker   std::unordered_set<int> open_fds;
298*9507f98cSAndroid Build Coastguard Worker   GetOpenFileDescriptors(&open_fds);
299*9507f98cSAndroid Build Coastguard Worker 
300*9507f98cSAndroid Build Coastguard Worker   std::string test_dir;
301*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->GetTestDirectory(&test_dir));
302*9507f98cSAndroid Build Coastguard Worker   std::string file_path = test_dir + "/close_on_exec_lock.txt";
303*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(WriteStringToFile(env_, "0123456789", file_path));
304*9507f98cSAndroid Build Coastguard Worker 
305*9507f98cSAndroid Build Coastguard Worker   leveldb::FileLock* lock = nullptr;
306*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->LockFile(file_path, &lock));
307*9507f98cSAndroid Build Coastguard Worker   CheckCloseOnExecDoesNotLeakFDs(open_fds);
308*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->UnlockFile(lock));
309*9507f98cSAndroid Build Coastguard Worker 
310*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->RemoveFile(file_path));
311*9507f98cSAndroid Build Coastguard Worker }
312*9507f98cSAndroid Build Coastguard Worker 
TEST_F(EnvPosixTest,TestCloseOnExecLogger)313*9507f98cSAndroid Build Coastguard Worker TEST_F(EnvPosixTest, TestCloseOnExecLogger) {
314*9507f98cSAndroid Build Coastguard Worker   std::unordered_set<int> open_fds;
315*9507f98cSAndroid Build Coastguard Worker   GetOpenFileDescriptors(&open_fds);
316*9507f98cSAndroid Build Coastguard Worker 
317*9507f98cSAndroid Build Coastguard Worker   std::string test_dir;
318*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->GetTestDirectory(&test_dir));
319*9507f98cSAndroid Build Coastguard Worker   std::string file_path = test_dir + "/close_on_exec_logger.txt";
320*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(WriteStringToFile(env_, "0123456789", file_path));
321*9507f98cSAndroid Build Coastguard Worker 
322*9507f98cSAndroid Build Coastguard Worker   leveldb::Logger* file = nullptr;
323*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->NewLogger(file_path, &file));
324*9507f98cSAndroid Build Coastguard Worker   CheckCloseOnExecDoesNotLeakFDs(open_fds);
325*9507f98cSAndroid Build Coastguard Worker   delete file;
326*9507f98cSAndroid Build Coastguard Worker 
327*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->RemoveFile(file_path));
328*9507f98cSAndroid Build Coastguard Worker }
329*9507f98cSAndroid Build Coastguard Worker 
330*9507f98cSAndroid Build Coastguard Worker #endif  // HAVE_O_CLOEXEC
331*9507f98cSAndroid Build Coastguard Worker 
332*9507f98cSAndroid Build Coastguard Worker }  // namespace leveldb
333*9507f98cSAndroid Build Coastguard Worker 
334