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