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