summaryrefslogtreecommitdiff
path: root/Source/UnitTests/Core
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2026-08-08 13:02:54 +0200
committerGitHub <noreply@github.com>2026-08-08 13:02:54 +0200
commitcd3ea814628d36939340ef67a6edb19e6b094279 (patch)
tree8057a9588d5135e98d087de65f2dba391bd3c7ff /Source/UnitTests/Core
parentf42c349c3210eeb8f14d0b997a6c0cfc9f2f0ef5 (diff)
parent8a90cbf63843c13584fc8ce9ddd1c5c62726d818 (diff)
Merge pull request #14767 from JosJuice/state-nand-open-file
IOS/FS: Fix loading savestate when files are open
Diffstat (limited to 'Source/UnitTests/Core')
-rw-r--r--Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp106
1 files changed, 106 insertions, 0 deletions
diff --git a/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp b/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp
index 37d047815a..14306cb46c 100644
--- a/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp
+++ b/Source/UnitTests/Core/IOS/FS/FileSystemTest.cpp
@@ -9,6 +9,7 @@
#include <gtest/gtest.h>
+#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#include "Core/IOS/FS/FileSystem.h"
@@ -469,3 +470,108 @@ TEST_F(FileSystemTest, CreateFullPath)
EXPECT_EQ(m_fs->CreateFullPath(Uid{0x1000}, Gid{1}, "/shared2/wc24/mbox/Readme.txt", 0, modes),
ResultCode::Success);
}
+
+TEST_F(FileSystemTest, DoState)
+{
+ const std::string TEST_DATA_1 = "123";
+ const std::string TEST_DATA_2 = "4567";
+
+ std::array<u8, 4> read_buffer;
+
+ ASSERT_EQ(m_fs->CreateDirectory(Uid{1}, Gid{2}, "/tmp/a", 0, modes), ResultCode::Success);
+ ASSERT_EQ(m_fs->CreateDirectory(Uid{1}, Gid{2}, "/tmp/a/b", 0, modes), ResultCode::Success);
+ ASSERT_EQ(m_fs->CreateDirectory(Uid{0}, Gid{0}, "/tmp/a/c", 0, modes), ResultCode::Success);
+
+ ASSERT_EQ(m_fs->CreateFile(Uid{1}, Gid{2}, "/tmp/a/d", 0, modes), ResultCode::Success);
+ ASSERT_EQ(m_fs->CreateFile(Uid{3}, Gid{4}, "/tmp/e", 0, modes), ResultCode::Success);
+
+ {
+ Result<FileHandle> file1 = m_fs->OpenFile(Uid{1}, Gid{2}, "/tmp/a/d", Mode::ReadWrite);
+ ASSERT_TRUE(file1.has_value());
+ ASSERT_TRUE(file1->Write(TEST_DATA_1.data(), TEST_DATA_1.size()).has_value());
+ }
+
+ std::array<u8, 1024> state_buffer;
+ size_t state_size;
+
+ {
+ Result<FileHandle> file2 = m_fs->OpenFile(Uid{3}, Gid{4}, "/tmp/e", Mode::ReadWrite);
+ ASSERT_TRUE(file2.has_value());
+ ASSERT_TRUE(file2->Write(TEST_DATA_2.data(), TEST_DATA_2.size()).has_value());
+
+ u8* state_pointer = state_buffer.data();
+ PointerWrap p(&state_pointer, state_buffer.size(), PointerWrap::Mode::Write);
+ m_fs->DoState(p);
+ ASSERT_TRUE(p.IsWriteMode());
+
+ ASSERT_TRUE(file2->Seek(2, SeekMode::Set).has_value());
+ ASSERT_TRUE(file2->Write("_", 1).has_value());
+
+ Fd fd = file2->Release();
+ p.Do(fd);
+ ASSERT_TRUE(p.IsWriteMode());
+
+ state_size = state_pointer - state_buffer.data();
+ }
+
+ ASSERT_EQ(m_fs->Delete(Uid{0}, Gid{0}, "/tmp/a"), ResultCode::Success);
+ ASSERT_EQ(m_fs->GetMetadata(Uid{0}, Gid{0}, "/tmp/a").error(), ResultCode::NotFound);
+ ASSERT_EQ(m_fs->GetMetadata(Uid{0}, Gid{0}, "/tmp/a/b").error(), ResultCode::NotFound);
+ ASSERT_EQ(m_fs->GetMetadata(Uid{0}, Gid{0}, "/tmp/a/c").error(), ResultCode::NotFound);
+ ASSERT_EQ(m_fs->GetMetadata(Uid{0}, Gid{0}, "/tmp/a/d").error(), ResultCode::NotFound);
+
+ ASSERT_EQ(m_fs->CreateFile(Uid{5}, Gid{6}, "/tmp/f", 0, modes), ResultCode::Success);
+
+ ASSERT_EQ(m_fs->CreateDirectory(Uid{7}, Gid{8}, "/tmp/g", 0, modes), ResultCode::Success);
+
+ u8* state_pointer = state_buffer.data();
+ PointerWrap p(&state_pointer, state_size, PointerWrap::Mode::Read);
+ m_fs->DoState(p);
+ ASSERT_TRUE(p.IsReadMode());
+
+ constexpr auto check_directory_metadata = [](const Result<Metadata>& metadata, Uid uid, Gid gid) {
+ ASSERT_TRUE(metadata.has_value());
+ ASSERT_EQ(metadata->uid, uid);
+ ASSERT_EQ(metadata->gid, gid);
+ ASSERT_FALSE(metadata->is_file);
+ };
+
+ constexpr auto check_file_metadata = [](const Result<Metadata>& metadata, Uid uid, Gid gid,
+ u32 size) {
+ ASSERT_TRUE(metadata.has_value());
+ ASSERT_EQ(metadata->uid, uid);
+ ASSERT_EQ(metadata->gid, gid);
+ ASSERT_TRUE(metadata->is_file);
+ ASSERT_EQ(metadata->size, size);
+ };
+
+ check_directory_metadata(m_fs->GetMetadata(Uid{0}, Gid{0}, "/tmp/a"), Uid{1}, Gid{2});
+ check_directory_metadata(m_fs->GetMetadata(Uid{0}, Gid{0}, "/tmp/a/b"), Uid{1}, Gid{2});
+ check_directory_metadata(m_fs->GetMetadata(Uid{0}, Gid{0}, "/tmp/a/c"), Uid{0}, Gid{0});
+
+ check_file_metadata(m_fs->GetMetadata(Uid{0}, Gid{0}, "/tmp/a/d"), Uid{1}, Gid{2}, 3);
+ check_file_metadata(m_fs->GetMetadata(Uid{0}, Gid{0}, "/tmp/e"), Uid{3}, Gid{4}, 4);
+
+ ASSERT_EQ(m_fs->GetMetadata(Uid{0}, Gid{0}, "/tmp/f").error(), ResultCode::NotFound);
+ ASSERT_EQ(m_fs->GetMetadata(Uid{0}, Gid{0}, "/tmp/g").error(), ResultCode::NotFound);
+
+ Fd fd{};
+ p.Do(fd);
+ ASSERT_TRUE(p.IsReadMode());
+
+ {
+ FileHandle file2(m_fs.get(), fd);
+ ASSERT_EQ(file2.GetStatus()->offset, 4u);
+ ASSERT_TRUE(file2.Seek(0, SeekMode::Set).has_value());
+ ASSERT_TRUE(file2.Read(read_buffer.data(), TEST_DATA_2.size()).has_value());
+ for (size_t i = 0; i < TEST_DATA_2.size(); ++i)
+ ASSERT_EQ(read_buffer[i], TEST_DATA_2[i]);
+ }
+
+ {
+ Result<FileHandle> file1 = m_fs->OpenFile(Uid{5}, Gid{6}, "/tmp/a/d", Mode::Read);
+ ASSERT_TRUE(file1->Read(read_buffer.data(), TEST_DATA_1.size()).has_value());
+ for (size_t i = 0; i < TEST_DATA_1.size(); ++i)
+ ASSERT_EQ(read_buffer[i], TEST_DATA_1[i]);
+ }
+}