From 484cfb93288ee593d860e824ee466dc244f72ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 29 Dec 2019 15:42:16 +0100 Subject: UnitTests/FS: Add metadata tests --- Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp') diff --git a/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp b/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp index 3a4f443139..c84caf6f6a 100644 --- a/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp +++ b/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp @@ -52,14 +52,18 @@ TEST_F(FileSystemTest, CreateFile) { const std::string PATH = "/tmp/f"; - ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, PATH, 0, modes), ResultCode::Success); + constexpr u8 ArbitraryAttribute = 0xE1; + + ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, PATH, ArbitraryAttribute, modes), ResultCode::Success); const Result stats = m_fs->GetMetadata(Uid{0}, Gid{0}, PATH); ASSERT_TRUE(stats.Succeeded()); EXPECT_TRUE(stats->is_file); EXPECT_EQ(stats->size, 0u); - // TODO: After we start saving metadata correctly, check the UID, GID, permissions - // as well (issue 10234). + EXPECT_EQ(stats->uid, 0); + EXPECT_EQ(stats->gid, 0); + EXPECT_EQ(stats->modes, modes); + EXPECT_EQ(stats->attribute, ArbitraryAttribute); ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, PATH, 0, modes), ResultCode::AlreadyExists); @@ -72,21 +76,24 @@ TEST_F(FileSystemTest, CreateDirectory) { const std::string PATH = "/tmp/d"; - ASSERT_EQ(m_fs->CreateDirectory(Uid{0}, Gid{0}, PATH, 0, modes), ResultCode::Success); + constexpr u8 ArbitraryAttribute = 0x20; + + ASSERT_EQ(m_fs->CreateDirectory(Uid{0}, Gid{0}, PATH, ArbitraryAttribute, modes), + ResultCode::Success); const Result stats = m_fs->GetMetadata(Uid{0}, Gid{0}, PATH); ASSERT_TRUE(stats.Succeeded()); EXPECT_FALSE(stats->is_file); - // TODO: After we start saving metadata correctly, check the UID, GID, permissions - // as well (issue 10234). + EXPECT_EQ(stats->uid, 0); + EXPECT_EQ(stats->gid, 0); + EXPECT_EQ(stats->modes, modes); + EXPECT_EQ(stats->attribute, ArbitraryAttribute); const Result> children = m_fs->ReadDirectory(Uid{0}, Gid{0}, PATH); ASSERT_TRUE(children.Succeeded()); EXPECT_TRUE(children->empty()); - // TODO: uncomment this after the FS code is fixed to return AlreadyExists. - // EXPECT_EQ(m_fs->CreateDirectory(Uid{0}, Gid{0}, PATH, 0, Mode::Read, Mode::None, Mode::None), - // ResultCode::AlreadyExists); + EXPECT_EQ(m_fs->CreateDirectory(Uid{0}, Gid{0}, PATH, 0, modes), ResultCode::AlreadyExists); } TEST_F(FileSystemTest, Delete) -- cgit v1.2.3 From d4ba0acb3a6422da70951c9ea0b50895d8b2666f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 29 Dec 2019 16:13:26 +0100 Subject: UnitTests/FS: Add path validity and splitting tests --- Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp | 46 +++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp') diff --git a/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp b/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp index c84caf6f6a..0f65bcd0ce 100644 --- a/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp +++ b/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp @@ -39,6 +39,41 @@ private: std::string m_profile_path; }; +TEST(FileSystem, BasicPathValidity) +{ + EXPECT_TRUE(IsValidPath("/")); + EXPECT_FALSE(IsValidNonRootPath("/")); + + EXPECT_TRUE(IsValidNonRootPath("/shared2/sys/SYSCONF")); + EXPECT_TRUE(IsValidNonRootPath("/shared2/sys")); + EXPECT_TRUE(IsValidNonRootPath("/shared2")); + + // Paths must start with /. + EXPECT_FALSE(IsValidNonRootPath("\\test")); + // Paths must not end with /. + EXPECT_FALSE(IsValidNonRootPath("/shared2/sys/")); + // Paths must not be longer than 64 characters. + EXPECT_FALSE(IsValidPath( + "/abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz")); +} + +TEST(FileSystem, PathSplitting) +{ + SplitPathResult result; + + result = {"/shared1", "00000042.app"}; + EXPECT_EQ(SplitPathAndBasename("/shared1/00000042.app"), result); + + result = {"/shared2/sys", "SYSCONF"}; + EXPECT_EQ(SplitPathAndBasename("/shared2/sys/SYSCONF"), result); + + result = {"/shared2", "sys"}; + EXPECT_EQ(SplitPathAndBasename("/shared2/sys"), result); + + result = {"/", "shared2"}; + EXPECT_EQ(SplitPathAndBasename("/shared2"), result); +} + TEST_F(FileSystemTest, EssentialDirectories) { for (const std::string& path : @@ -70,6 +105,13 @@ TEST_F(FileSystemTest, CreateFile) const Result> tmp_files = m_fs->ReadDirectory(Uid{0}, Gid{0}, "/tmp"); ASSERT_TRUE(tmp_files.Succeeded()); EXPECT_EQ(std::count(tmp_files->begin(), tmp_files->end(), "f"), 1u); + + // Test invalid paths + // Unprintable characters + EXPECT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/tes\1t", 0, modes), ResultCode::Invalid); + EXPECT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/te\x7fst", 0, modes), ResultCode::Invalid); + // Paths with too many components are not rejected for files. + EXPECT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/1/2/3/4/5/6/7/8/9", 0, modes), ResultCode::NotFound); } TEST_F(FileSystemTest, CreateDirectory) @@ -94,6 +136,10 @@ TEST_F(FileSystemTest, CreateDirectory) EXPECT_TRUE(children->empty()); EXPECT_EQ(m_fs->CreateDirectory(Uid{0}, Gid{0}, PATH, 0, modes), ResultCode::AlreadyExists); + + // Paths with too many components should be rejected. + EXPECT_EQ(m_fs->CreateDirectory(Uid{0}, Gid{0}, "/1/2/3/4/5/6/7/8/9", 0, modes), + ResultCode::TooManyPathComponents); } TEST_F(FileSystemTest, Delete) -- cgit v1.2.3 From 8789a6ddb38df1559201582c2fe946479643e14b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 29 Dec 2019 18:14:51 +0100 Subject: UnitTests/FS: Fix file rename tests Files cannot be given a different file name, only moved across directories. Add a test for that behaviour and fix the existing RenameWithExistingTargetFile test. --- Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp | 27 +++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp') diff --git a/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp b/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp index 0f65bcd0ce..39936678b8 100644 --- a/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp +++ b/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp @@ -157,6 +157,14 @@ TEST_F(FileSystemTest, Rename) EXPECT_EQ(m_fs->ReadDirectory(Uid{0}, Gid{0}, "/tmp").Error(), ResultCode::NotFound); EXPECT_TRUE(m_fs->ReadDirectory(Uid{0}, Gid{0}, "/test").Succeeded()); + + // Rename /test back to /tmp. + EXPECT_EQ(m_fs->Rename(Uid{0}, Gid{0}, "/test", "/tmp"), ResultCode::Success); + + // Create a file called /tmp/f1, and rename it to /tmp/f2. + // This should not work; file name changes are not allowed for files. + ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/f1", 0, modes), ResultCode::Success); + EXPECT_EQ(m_fs->Rename(Uid{0}, Gid{0}, "/tmp/f1", "/tmp/f2"), ResultCode::Invalid); } TEST_F(FileSystemTest, RenameWithExistingTargetDirectory) @@ -177,26 +185,29 @@ TEST_F(FileSystemTest, RenameWithExistingTargetDirectory) TEST_F(FileSystemTest, RenameWithExistingTargetFile) { + const std::string source_path = "/sys/f2"; + const std::string dest_path = "/tmp/f2"; + // Create the test source file and write some data (so that we can check its size later on). - ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/f1", 0, modes), ResultCode::Success); + ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, source_path, 0, modes), ResultCode::Success); const std::vector TEST_DATA{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}}; std::vector read_buffer(TEST_DATA.size()); { - const Result file = m_fs->OpenFile(Uid{0}, Gid{0}, "/tmp/f1", Mode::ReadWrite); + const Result file = m_fs->OpenFile(Uid{0}, Gid{0}, source_path, Mode::ReadWrite); ASSERT_TRUE(file.Succeeded()); ASSERT_TRUE(file->Write(TEST_DATA.data(), TEST_DATA.size()).Succeeded()); } // Create the test target file and leave it empty. - ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/f2", 0, modes), ResultCode::Success); + ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, dest_path, 0, modes), ResultCode::Success); - // Rename f1 to f2 and check that f1 replaced f2. - EXPECT_EQ(m_fs->Rename(Uid{0}, Gid{0}, "/tmp/f1", "/tmp/f2"), ResultCode::Success); + // Rename /sys/f2 to /tmp/f2 and check that f1 replaced f2. + EXPECT_EQ(m_fs->Rename(Uid{0}, Gid{0}, source_path, dest_path), ResultCode::Success); - ASSERT_FALSE(m_fs->GetMetadata(Uid{0}, Gid{0}, "/tmp/f1").Succeeded()); - EXPECT_EQ(m_fs->GetMetadata(Uid{0}, Gid{0}, "/tmp/f1").Error(), ResultCode::NotFound); + ASSERT_FALSE(m_fs->GetMetadata(Uid{0}, Gid{0}, source_path).Succeeded()); + EXPECT_EQ(m_fs->GetMetadata(Uid{0}, Gid{0}, source_path).Error(), ResultCode::NotFound); - const Result metadata = m_fs->GetMetadata(Uid{0}, Gid{0}, "/tmp/f2"); + const Result metadata = m_fs->GetMetadata(Uid{0}, Gid{0}, dest_path); ASSERT_TRUE(metadata.Succeeded()); EXPECT_TRUE(metadata->is_file); EXPECT_EQ(metadata->size, TEST_DATA.size()); -- cgit v1.2.3 From af416c60b054277603fa4386a253517801a55111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 29 Dec 2019 21:19:11 +0100 Subject: UnitTests/FS: Add ReadDirectory ordering test (issue 10234) --- Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp') diff --git a/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp b/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp index 39936678b8..b39e4a48cb 100644 --- a/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp +++ b/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include #include #include #include @@ -389,3 +390,27 @@ TEST_F(FileSystemTest, ReadDirectoryOnFile) ASSERT_FALSE(result.Succeeded()); EXPECT_EQ(result.Error(), ResultCode::Invalid); } + +TEST_F(FileSystemTest, ReadDirectoryOrdering) +{ + ASSERT_EQ(m_fs->CreateDirectory(Uid{0}, Gid{0}, "/tmp/o", 0, modes), ResultCode::Success); + + // Randomly generated file names in no particular order. + const std::array file_names{{ + "Rkj62lGwHp", + "XGDQTDJMea", + "1z5M43WeFw", + "YAY39VuMRd", + "hxJ86nkoBX", + }}; + // Create the files. + for (const auto& name : file_names) + ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/tmp/o/" + name, 0, modes), ResultCode::Success); + + // Verify that ReadDirectory returns a file list that is ordered by descending creation date + // (issue 10234). + const Result> result = m_fs->ReadDirectory(Uid{0}, Gid{0}, "/tmp/o"); + ASSERT_TRUE(result.Succeeded()); + ASSERT_EQ(result->size(), file_names.size()); + EXPECT_TRUE(std::equal(result->begin(), result->end(), file_names.rbegin())); +} -- cgit v1.2.3 From 031c63eb8a931eb007ec285840f848332a1cf526 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 29 Dec 2019 22:27:28 +0100 Subject: UnitTests/FS: Improve deletion test * Test recursive directory deletion * Test "in use" check for both files and directories --- Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp') diff --git a/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp b/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp index b39e4a48cb..79f853f441 100644 --- a/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp +++ b/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -148,6 +149,25 @@ TEST_F(FileSystemTest, Delete) EXPECT_TRUE(m_fs->ReadDirectory(Uid{0}, Gid{0}, "/tmp").Succeeded()); EXPECT_EQ(m_fs->Delete(Uid{0}, Gid{0}, "/tmp"), ResultCode::Success); EXPECT_EQ(m_fs->ReadDirectory(Uid{0}, Gid{0}, "/tmp").Error(), ResultCode::NotFound); + + // Test recursive directory deletion. + ASSERT_EQ(m_fs->CreateDirectory(Uid{0}, Gid{0}, "/sys/1", 0, modes), ResultCode::Success); + ASSERT_EQ(m_fs->CreateDirectory(Uid{0}, Gid{0}, "/sys/1/2", 0, modes), ResultCode::Success); + ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/sys/1/2/3", 0, modes), ResultCode::Success); + ASSERT_EQ(m_fs->CreateFile(Uid{0}, Gid{0}, "/sys/1/2/4", 0, modes), ResultCode::Success); + + // Leave a file open. Deletion should fail while the file is in use. + auto handle = std::make_optional(m_fs->OpenFile(Uid{0}, Gid{0}, "/sys/1/2/3", Mode::Read)); + ASSERT_TRUE(handle->Succeeded()); + EXPECT_EQ(m_fs->Delete(Uid{0}, Gid{0}, "/sys/1/2/3"), ResultCode::InUse); + // A directory that contains a file that is in use is considered to be in use, + // so this should fail too. + EXPECT_EQ(m_fs->Delete(Uid{0}, Gid{0}, "/sys/1"), ResultCode::InUse); + + // With the handle closed, both of these should work: + handle.reset(); + EXPECT_EQ(m_fs->Delete(Uid{0}, Gid{0}, "/sys/1/2/3"), ResultCode::Success); + EXPECT_EQ(m_fs->Delete(Uid{0}, Gid{0}, "/sys/1"), ResultCode::Success); } TEST_F(FileSystemTest, Rename) -- cgit v1.2.3