dirent_test.cpp revision 063cfb2084ea4b12d3c85b2d2c44e888f0857eb4
1/* 2 * Copyright (C) 2012 The Android Open Source Project 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 <gtest/gtest.h> 18 19#include <dirent.h> 20#include <errno.h> 21#include <fcntl.h> 22#include <limits.h> 23#include <sys/stat.h> 24#include <sys/types.h> 25#include <unistd.h> 26 27#include <algorithm> 28#include <set> 29#include <string> 30 31#ifdef __BIONIC__ 32static int my_alphasort(const dirent** lhs, const dirent** rhs) { 33 return alphasort(lhs, rhs); 34} 35#endif 36 37static void CheckProcSelf(std::set<std::string>& names) { 38 // We have a good idea of what should be in /proc/self. 39 ASSERT_TRUE(names.find(".") != names.end()); 40 ASSERT_TRUE(names.find("..") != names.end()); 41 ASSERT_TRUE(names.find("cmdline") != names.end()); 42 ASSERT_TRUE(names.find("fd") != names.end()); 43 ASSERT_TRUE(names.find("stat") != names.end()); 44} 45 46TEST(dirent, scandir) { 47 // Get everything from /proc/self... 48 dirent** entries; 49#ifdef __BIONIC__ 50 int entry_count = scandir("/proc/self", &entries, NULL, my_alphasort); 51#else 52 int entry_count = scandir("/proc/self", &entries, NULL, alphasort); 53#endif 54 ASSERT_GE(entry_count, 0); 55 56 // Turn the directory entries into a set and vector of the names. 57 std::set<std::string> name_set; 58 std::vector<std::string> unsorted_name_list; 59 for (size_t i = 0; i < static_cast<size_t>(entry_count); ++i) { 60 name_set.insert(entries[i]->d_name); 61 unsorted_name_list.push_back(entries[i]->d_name); 62 free(entries[i]); 63 } 64 free(entries); 65 66 // No duplicates. 67 ASSERT_EQ(name_set.size(), unsorted_name_list.size()); 68 69 // All entries sorted. 70 std::vector<std::string> sorted_name_list(unsorted_name_list); 71 std::sort(sorted_name_list.begin(), sorted_name_list.end()); 72 ASSERT_EQ(sorted_name_list, unsorted_name_list); 73 74 CheckProcSelf(name_set); 75} 76 77TEST(dirent, fdopendir_invalid) { 78 ASSERT_TRUE(fdopendir(-1) == NULL); 79 ASSERT_EQ(errno, EBADF); 80 81 int fd = open("/dev/null", O_RDONLY); 82 ASSERT_NE(fd, -1); 83 ASSERT_TRUE(fdopendir(fd) == NULL); 84 ASSERT_EQ(errno, ENOTDIR); 85 close(fd); 86} 87 88TEST(dirent, fdopendir) { 89 int fd = open("/proc/self", O_RDONLY); 90 DIR* d = fdopendir(fd); 91 ASSERT_TRUE(d != NULL); 92 dirent* e = readdir(d); 93 ASSERT_STREQ(e->d_name, "."); 94 ASSERT_EQ(closedir(d), 0); 95 96 // fdopendir(3) took ownership, so closedir(3) closed our fd. 97 ASSERT_EQ(close(fd), -1); 98 ASSERT_EQ(errno, EBADF); 99} 100 101TEST(dirent, opendir_invalid) { 102 ASSERT_TRUE(opendir("/does/not/exist") == NULL); 103 ASSERT_EQ(errno, ENOENT); 104 105 ASSERT_TRUE(opendir("/dev/null") == NULL); 106 ASSERT_EQ(errno, ENOTDIR); 107} 108 109TEST(dirent, opendir) { 110 DIR* d = opendir("/proc/self"); 111 ASSERT_TRUE(d != NULL); 112 dirent* e = readdir(d); 113 ASSERT_STREQ(e->d_name, "."); 114 ASSERT_EQ(closedir(d), 0); 115} 116 117TEST(dirent, closedir_invalid) { 118 DIR* d = NULL; 119 ASSERT_EQ(closedir(d), -1); 120 ASSERT_EQ(errno, EINVAL); 121} 122 123TEST(dirent, closedir) { 124 DIR* d = opendir("/proc/self"); 125 ASSERT_TRUE(d != NULL); 126 ASSERT_EQ(closedir(d), 0); 127} 128 129TEST(dirent, readdir) { 130 DIR* d = opendir("/proc/self"); 131 ASSERT_TRUE(d != NULL); 132 std::set<std::string> name_set; 133 errno = 0; 134 dirent* e; 135 while ((e = readdir(d)) != NULL) { 136 name_set.insert(e->d_name); 137 } 138 // Reading to the end of the directory is not an error. 139 // readdir(3) returns NULL, but leaves errno as 0. 140 ASSERT_EQ(errno, 0); 141 ASSERT_EQ(closedir(d), 0); 142 143 CheckProcSelf(name_set); 144} 145 146TEST(dirent, readdir_r) { 147 DIR* d = opendir("/proc/self"); 148 ASSERT_TRUE(d != NULL); 149 std::set<std::string> name_set; 150 errno = 0; 151 dirent storage; 152 dirent* e = NULL; 153 while (readdir_r(d, &storage, &e) == 0 && e != NULL) { 154 name_set.insert(e->d_name); 155 } 156 // Reading to the end of the directory is not an error. 157 // readdir_r(3) returns NULL, but leaves errno as 0. 158 ASSERT_EQ(errno, 0); 159 ASSERT_EQ(closedir(d), 0); 160 161 CheckProcSelf(name_set); 162} 163 164TEST(dirent, rewinddir) { 165 DIR* d = opendir("/proc/self"); 166 ASSERT_TRUE(d != NULL); 167 168 // Get all the names once... 169 std::vector<std::string> pass1; 170 dirent* e; 171 while ((e = readdir(d)) != NULL) { 172 pass1.push_back(e->d_name); 173 } 174 175 // ...rewind... 176 rewinddir(d); 177 178 // ...and get all the names again. 179 std::vector<std::string> pass2; 180 while ((e = readdir(d)) != NULL) { 181 pass2.push_back(e->d_name); 182 } 183 184 ASSERT_EQ(closedir(d), 0); 185 186 // We should have seen the same names in the same order both times. 187 ASSERT_EQ(pass1.size(), pass2.size()); 188 for (size_t i = 0; i < pass1.size(); ++i) { 189 ASSERT_EQ(pass1[i], pass2[i]); 190 } 191} 192