dirent_test.cpp revision 063cfb2084ea4b12d3c85b2d2c44e888f0857eb4
1063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes/*
2063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes * Copyright (C) 2012 The Android Open Source Project
3063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes *
4063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
5063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes * you may not use this file except in compliance with the License.
6063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes * You may obtain a copy of the License at
7063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes *
8063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes *
10063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes * Unless required by applicable law or agreed to in writing, software
11063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
12063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes * See the License for the specific language governing permissions and
14063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes * limitations under the License.
15063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes */
16063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
17063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <gtest/gtest.h>
18063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
19063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <dirent.h>
20063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <errno.h>
21063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <fcntl.h>
22063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <limits.h>
23063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <sys/stat.h>
24063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <sys/types.h>
25063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <unistd.h>
26063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
27063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <algorithm>
28063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <set>
29063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <string>
30063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
31063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#ifdef __BIONIC__
32063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughesstatic int my_alphasort(const dirent** lhs, const dirent** rhs) {
33063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  return alphasort(lhs, rhs);
34063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
35063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#endif
36063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
37063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughesstatic void CheckProcSelf(std::set<std::string>& names) {
38063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // We have a good idea of what should be in /proc/self.
39063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(names.find(".") != names.end());
40063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(names.find("..") != names.end());
41063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(names.find("cmdline") != names.end());
42063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(names.find("fd") != names.end());
43063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(names.find("stat") != names.end());
44063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
45063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
46063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott HughesTEST(dirent, scandir) {
47063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // Get everything from /proc/self...
48063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  dirent** entries;
49063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#ifdef __BIONIC__
50063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  int entry_count = scandir("/proc/self", &entries, NULL, my_alphasort);
51063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#else
52063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  int entry_count = scandir("/proc/self", &entries, NULL, alphasort);
53063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#endif
54063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_GE(entry_count, 0);
55063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
56063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // Turn the directory entries into a set and vector of the names.
57063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  std::set<std::string> name_set;
58063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  std::vector<std::string> unsorted_name_list;
59063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  for (size_t i = 0; i < static_cast<size_t>(entry_count); ++i) {
60063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes    name_set.insert(entries[i]->d_name);
61063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes    unsorted_name_list.push_back(entries[i]->d_name);
62063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes    free(entries[i]);
63063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  }
64063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  free(entries);
65063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
66063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // No duplicates.
67063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(name_set.size(), unsorted_name_list.size());
68063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
69063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // All entries sorted.
70063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  std::vector<std::string> sorted_name_list(unsorted_name_list);
71063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  std::sort(sorted_name_list.begin(), sorted_name_list.end());
72063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(sorted_name_list, unsorted_name_list);
73063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
74063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  CheckProcSelf(name_set);
75063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
76063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
77063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott HughesTEST(dirent, fdopendir_invalid) {
78063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(fdopendir(-1) == NULL);
79063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(errno, EBADF);
80063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
81063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  int fd = open("/dev/null", O_RDONLY);
82063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_NE(fd, -1);
83063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(fdopendir(fd) == NULL);
84063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(errno, ENOTDIR);
85063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  close(fd);
86063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
87063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
88063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott HughesTEST(dirent, fdopendir) {
89063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  int fd = open("/proc/self", O_RDONLY);
90063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  DIR* d = fdopendir(fd);
91063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(d != NULL);
92063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  dirent* e = readdir(d);
93063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_STREQ(e->d_name, ".");
94063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(closedir(d), 0);
95063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
96063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // fdopendir(3) took ownership, so closedir(3) closed our fd.
97063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(close(fd), -1);
98063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(errno, EBADF);
99063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
100063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
101063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott HughesTEST(dirent, opendir_invalid) {
102063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(opendir("/does/not/exist") == NULL);
103063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(errno, ENOENT);
104063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
105063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(opendir("/dev/null") == NULL);
106063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(errno, ENOTDIR);
107063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
108063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
109063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott HughesTEST(dirent, opendir) {
110063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  DIR* d = opendir("/proc/self");
111063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(d != NULL);
112063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  dirent* e = readdir(d);
113063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_STREQ(e->d_name, ".");
114063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(closedir(d), 0);
115063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
116063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
117063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott HughesTEST(dirent, closedir_invalid) {
118063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  DIR* d = NULL;
119063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(closedir(d), -1);
120063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(errno, EINVAL);
121063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
122063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
123063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott HughesTEST(dirent, closedir) {
124063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  DIR* d = opendir("/proc/self");
125063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(d != NULL);
126063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(closedir(d), 0);
127063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
128063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
129063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott HughesTEST(dirent, readdir) {
130063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  DIR* d = opendir("/proc/self");
131063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(d != NULL);
132063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  std::set<std::string> name_set;
133063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  errno = 0;
134063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  dirent* e;
135063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  while ((e = readdir(d)) != NULL) {
136063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes    name_set.insert(e->d_name);
137063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  }
138063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // Reading to the end of the directory is not an error.
139063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // readdir(3) returns NULL, but leaves errno as 0.
140063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(errno, 0);
141063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(closedir(d), 0);
142063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
143063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  CheckProcSelf(name_set);
144063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
145063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
146063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott HughesTEST(dirent, readdir_r) {
147063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  DIR* d = opendir("/proc/self");
148063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(d != NULL);
149063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  std::set<std::string> name_set;
150063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  errno = 0;
151063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  dirent storage;
152063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  dirent* e = NULL;
153063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  while (readdir_r(d, &storage, &e) == 0 && e != NULL) {
154063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes    name_set.insert(e->d_name);
155063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  }
156063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // Reading to the end of the directory is not an error.
157063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // readdir_r(3) returns NULL, but leaves errno as 0.
158063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(errno, 0);
159063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(closedir(d), 0);
160063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
161063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  CheckProcSelf(name_set);
162063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
163063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
164063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott HughesTEST(dirent, rewinddir) {
165063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  DIR* d = opendir("/proc/self");
166063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(d != NULL);
167063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
168063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // Get all the names once...
169063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  std::vector<std::string> pass1;
170063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  dirent* e;
171063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  while ((e = readdir(d)) != NULL) {
172063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes    pass1.push_back(e->d_name);
173063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  }
174063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
175063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // ...rewind...
176063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  rewinddir(d);
177063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
178063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // ...and get all the names again.
179063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  std::vector<std::string> pass2;
180063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  while ((e = readdir(d)) != NULL) {
181063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes    pass2.push_back(e->d_name);
182063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  }
183063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
184063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(closedir(d), 0);
185063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
186063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // We should have seen the same names in the same order both times.
187063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(pass1.size(), pass2.size());
188063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  for (size_t i = 0; i < pass1.size(); ++i) {
189063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes    ASSERT_EQ(pass1[i], pass2[i]);
190063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  }
191063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
192