From 40419a16eb8bfbfd9bbb4e20957a5ec9e846a22a Mon Sep 17 00:00:00 2001 From: Ian Gudger Date: Thu, 16 May 2019 11:58:10 -0700 Subject: Add test for duplicate proc entries. The issue with duplicate /proc/sys entries seems to have been fixed in: PiperOrigin-RevId 229305982 Git hash dc8450b5676d4c4ac9bcfa23cabd862e0060527d Fixes google/gvisor#125 PiperOrigin-RevId: 248571903 Change-Id: I76ff3b525c93dafb92da6e5cf56e440187f14579 --- test/syscalls/linux/proc.cc | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'test/syscalls/linux') diff --git a/test/syscalls/linux/proc.cc b/test/syscalls/linux/proc.cc index 654f26242..d0c3a90b3 100644 --- a/test/syscalls/linux/proc.cc +++ b/test/syscalls/linux/proc.cc @@ -33,9 +33,12 @@ #include #include #include +#include #include #include +#include #include +#include #include #include @@ -1838,6 +1841,47 @@ TEST(ProcSelfMounts, RequiredFieldsArePresent) { // Root mount. ContainsRegex(R"(\S+ /proc \S+ rw\S* [0-9]+ [0-9]+\s)"))); } + +void CheckDuplicatesRecursively(std::string path) { + errno = 0; + DIR* dir = opendir(path.c_str()); + if (dir == nullptr) { + ASSERT_THAT(errno, ::testing::AnyOf(EPERM, EACCES)) << path; + return; + } + auto dir_closer = Cleanup([&dir]() { closedir(dir); }); + std::unordered_set children; + while (true) { + // Readdir(3): If the end of the directory stream is reached, NULL is + // returned and errno is not changed. If an error occurs, NULL is returned + // and errno is set appropriately. To distinguish end of stream and from an + // error, set errno to zero before calling readdir() and then check the + // value of errno if NULL is returned. + errno = 0; + struct dirent* dp = readdir(dir); + if (dp == nullptr) { + ASSERT_EQ(errno, 0) << path; + break; // We're done. + } + + if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) { + continue; + } + + ASSERT_EQ(children.find(std::string(dp->d_name)), children.end()) << dp->d_name; + children.insert(std::string(dp->d_name)); + + ASSERT_NE(dp->d_type, DT_UNKNOWN); + + if (dp->d_type != DT_DIR) { + continue; + } + CheckDuplicatesRecursively(absl::StrCat(path, "/", dp->d_name)); + } +} + +TEST(Proc, NoDuplicates) { CheckDuplicatesRecursively("/proc"); } + } // namespace } // namespace testing } // namespace gvisor -- cgit v1.2.3