summaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/syscalls/BUILD2
-rw-r--r--test/syscalls/linux/proc.cc44
2 files changed, 46 insertions, 0 deletions
diff --git a/test/syscalls/BUILD b/test/syscalls/BUILD
index d35f59433..79be06494 100644
--- a/test/syscalls/BUILD
+++ b/test/syscalls/BUILD
@@ -214,6 +214,8 @@ syscall_test(test = "//test/syscalls/linux:priority_test")
syscall_test(
size = "medium",
+ # We don't want our proc changing out from under us.
+ parallel = False,
test = "//test/syscalls/linux:proc_test",
)
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 <algorithm>
#include <atomic>
#include <functional>
+#include <iostream>
#include <map>
#include <memory>
+#include <ostream>
#include <string>
+#include <unordered_set>
#include <utility>
#include <vector>
@@ -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<std::string> 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