diff options
author | Elliott Hughes <enh@google.com> | 2019-11-01 08:07:25 -0700 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2020-01-22 18:30:50 -0800 |
commit | 22fb267ad6f95ab083abb56e914f8081552108a7 (patch) | |
tree | 6c29afacad5803924a83a0430ea509eaa76a0564 /tests/stdlib_test.cpp | |
parent | 73e9f242ed07631798433df4e35f5f73443cb9f9 (diff) |
Reimplement realpath.
Use O_PATH like musl to let the kernel do the hard work, rather than the
traditional BSD manual scheme.
Also add the most obvious missing tests from reading the man page, plus
a non-obvious test for deleted files.
Bug: http://b/131435126
Test: treehugger
Change-Id: Ie8a8986fea55f045952a81afee377ce8288a49d5
Diffstat (limited to 'tests/stdlib_test.cpp')
-rw-r--r-- | tests/stdlib_test.cpp | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp index ff4cb71ee..c522fffb8 100644 --- a/tests/stdlib_test.cpp +++ b/tests/stdlib_test.cpp @@ -29,6 +29,7 @@ #include <limits> #include <string> +#include <android-base/file.h> #include <android-base/macros.h> #include <gtest/gtest.h> @@ -36,6 +37,8 @@ #include "math_data_test.h" #include "utils.h" +using namespace std::string_literals; + template <typename T = int (*)(char*)> class GenericTemporaryFile { public: @@ -322,6 +325,17 @@ TEST(stdlib, realpath__ENOENT) { ASSERT_EQ(ENOENT, errno); } +TEST(stdlib, realpath__ELOOP) { + TemporaryDir td; + std::string link = std::string(td.path) + "/loop"; + ASSERT_EQ(0, symlink(link.c_str(), link.c_str())); + + errno = 0; + char* p = realpath(link.c_str(), nullptr); + ASSERT_TRUE(p == nullptr); + ASSERT_EQ(ELOOP, errno); +} + TEST(stdlib, realpath__component_after_non_directory) { errno = 0; char* p = realpath("/dev/null/.", nullptr); @@ -350,6 +364,47 @@ TEST(stdlib, realpath) { free(p); } +TEST(stdlib, realpath__dot) { + char* p = realpath("/proc/./version", nullptr); + ASSERT_STREQ("/proc/version", p); + free(p); +} + +TEST(stdlib, realpath__dot_dot) { + char* p = realpath("/dev/../proc/version", nullptr); + ASSERT_STREQ("/proc/version", p); + free(p); +} + +TEST(stdlib, realpath__deleted) { + TemporaryDir td; + + // Create a file "A". + std::string A_path = td.path + "/A"s; + ASSERT_TRUE(android::base::WriteStringToFile("test\n", A_path)); + + // Get an O_PATH fd for it. + android::base::unique_fd fd(open(A_path.c_str(), O_PATH)); + ASSERT_NE(fd, -1); + + // Create a file "A (deleted)". + android::base::unique_fd fd2(open((td.path + "/A (deleted)"s).c_str(), + O_CREAT | O_TRUNC | O_WRONLY, 0644)); + ASSERT_NE(fd2, -1); + + // Delete "A". + ASSERT_EQ(0, unlink(A_path.c_str())); + + // Now realpath() on the O_PATH fd, and check we *don't* get "A (deleted)". + std::string path = android::base::StringPrintf("/proc/%d/fd/%d", static_cast<int>(getpid()), + fd.get()); + errno = 0; + char* result = realpath(path.c_str(), nullptr); + ASSERT_EQ(nullptr, result) << result; + ASSERT_EQ(ENOENT, errno); + free(result); +} + TEST(stdlib, qsort) { struct s { char name[16]; |