summaryrefslogtreecommitdiff
path: root/tests/stdlib_test.cpp
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2019-11-01 08:07:25 -0700
committerElliott Hughes <enh@google.com>2020-01-22 18:30:50 -0800
commit22fb267ad6f95ab083abb56e914f8081552108a7 (patch)
tree6c29afacad5803924a83a0430ea509eaa76a0564 /tests/stdlib_test.cpp
parent73e9f242ed07631798433df4e35f5f73443cb9f9 (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.cpp55
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];