First Commit
This commit is contained in:
18
tests/ctest/common/CMakeLists.txt
Normal file
18
tests/ctest/common/CMakeLists.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
add_pcsx2_test(common_test
|
||||
byteswap_tests.cpp
|
||||
filesystem_tests.cpp
|
||||
path_tests.cpp
|
||||
string_util_tests.cpp
|
||||
)
|
||||
|
||||
if(_M_X86)
|
||||
target_sources(common_test PRIVATE
|
||||
x86emitter/codegen_tests.cpp
|
||||
x86emitter/codegen_tests.h
|
||||
x86emitter/codegen_tests_main.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_libraries(common_test PRIVATE
|
||||
common
|
||||
)
|
||||
14
tests/ctest/common/byteswap_tests.cpp
Normal file
14
tests/ctest/common/byteswap_tests.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
#include "common/ByteSwap.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(ByteSwap, ByteSwap)
|
||||
{
|
||||
ASSERT_EQ(ByteSwap(static_cast<u16>(0xabcd)), 0xcdabu);
|
||||
ASSERT_EQ(ByteSwap(static_cast<u32>(0xabcdef01)), 0x01efcdabu);
|
||||
ASSERT_EQ(ByteSwap(static_cast<u64>(0xabcdef0123456789ULL)), 0x8967452301efcdabu);
|
||||
ASSERT_EQ(ByteSwap(static_cast<s32>(0x80123456)), 0x56341280);
|
||||
}
|
||||
58
tests/ctest/common/filesystem_tests.cpp
Normal file
58
tests/ctest/common/filesystem_tests.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/Path.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
static std::optional<std::string> create_test_directory()
|
||||
{
|
||||
for (u16 i = 0; i < UINT16_MAX; i++)
|
||||
{
|
||||
std::string path = std::string("/tmp/pcsx2_filesystem_test_") + std::to_string(i);
|
||||
if (!FileSystem::DirectoryExists(path.c_str()))
|
||||
{
|
||||
if (!FileSystem::CreateDirectoryPath(path.c_str(), false))
|
||||
break;
|
||||
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
TEST(FileSystem, RecursiveDeleteDirectoryDontFollowSymbolicLinks)
|
||||
{
|
||||
// Find a suitable location to write some test files.
|
||||
std::optional<std::string> test_dir = create_test_directory();
|
||||
ASSERT_TRUE(test_dir.has_value());
|
||||
|
||||
// Create a target directory containing a file that shouldn't be deleted.
|
||||
std::string target_dir = Path::Combine(*test_dir, "target_dir");
|
||||
ASSERT_TRUE(FileSystem::CreateDirectoryPath(target_dir.c_str(), false));
|
||||
std::string file_path = Path::Combine(target_dir, "file.txt");
|
||||
ASSERT_TRUE(FileSystem::WriteStringToFile(file_path.c_str(), "Lorem ipsum!"));
|
||||
|
||||
// Create a directory containing a symlink to the target directory.
|
||||
std::string dir_to_delete = Path::Combine(*test_dir, "dir_to_delete");
|
||||
ASSERT_TRUE(FileSystem::CreateDirectoryPath(dir_to_delete.c_str(), false));
|
||||
std::string symlink_path = Path::Combine(dir_to_delete, "link");
|
||||
ASSERT_TRUE(FileSystem::CreateSymLink(symlink_path.c_str(), target_dir.c_str()));
|
||||
|
||||
// Delete the directory containing the symlink.
|
||||
ASSERT_TRUE(dir_to_delete.starts_with("/tmp/pcsx2_filesystem_test_"));
|
||||
ASSERT_TRUE(FileSystem::RecursiveDeleteDirectory(dir_to_delete.c_str()));
|
||||
|
||||
// Make sure the file in the target directory didn't get deleted.
|
||||
ASSERT_TRUE(FileSystem::FileExists(file_path.c_str()));
|
||||
|
||||
// Clean up.
|
||||
ASSERT_TRUE(FileSystem::DeleteFilePath(file_path.c_str()));
|
||||
ASSERT_TRUE(FileSystem::DeleteDirectory(target_dir.c_str()));
|
||||
ASSERT_TRUE(FileSystem::DeleteDirectory(test_dir->c_str()));
|
||||
}
|
||||
|
||||
#endif
|
||||
367
tests/ctest/common/path_tests.cpp
Normal file
367
tests/ctest/common/path_tests.cpp
Normal file
@@ -0,0 +1,367 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/Pcsx2Defs.h"
|
||||
#include "common/Path.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(Path, ToNativePath)
|
||||
{
|
||||
ASSERT_EQ(Path::ToNativePath(""), "");
|
||||
|
||||
#ifdef _WIN32
|
||||
ASSERT_EQ(Path::ToNativePath("foo"), "foo");
|
||||
ASSERT_EQ(Path::ToNativePath("foo\\"), "foo");
|
||||
ASSERT_EQ(Path::ToNativePath("foo\\\\bar"), "foo\\bar");
|
||||
ASSERT_EQ(Path::ToNativePath("foo\\bar"), "foo\\bar");
|
||||
ASSERT_EQ(Path::ToNativePath("foo\\bar\\baz"), "foo\\bar\\baz");
|
||||
ASSERT_EQ(Path::ToNativePath("foo\\bar/baz"), "foo\\bar\\baz");
|
||||
ASSERT_EQ(Path::ToNativePath("foo/bar/baz"), "foo\\bar\\baz");
|
||||
ASSERT_EQ(Path::ToNativePath("foo/🙃bar/b🙃az"), "foo\\🙃bar\\b🙃az");
|
||||
ASSERT_EQ(Path::ToNativePath("\\\\foo\\bar\\baz"), "\\\\foo\\bar\\baz");
|
||||
#else
|
||||
ASSERT_EQ(Path::ToNativePath("foo"), "foo");
|
||||
ASSERT_EQ(Path::ToNativePath("foo/"), "foo");
|
||||
ASSERT_EQ(Path::ToNativePath("foo//bar"), "foo/bar");
|
||||
ASSERT_EQ(Path::ToNativePath("foo/bar"), "foo/bar");
|
||||
ASSERT_EQ(Path::ToNativePath("foo/bar/baz"), "foo/bar/baz");
|
||||
ASSERT_EQ(Path::ToNativePath("/foo/bar/baz"), "/foo/bar/baz");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Path, IsValidFileName)
|
||||
{
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
ASSERT_FALSE(Path::IsValidFileName("foo:bar", false));
|
||||
ASSERT_FALSE(Path::IsValidFileName("baz\\foo:bar", false));
|
||||
ASSERT_FALSE(Path::IsValidFileName("baz/foo:bar", false));
|
||||
ASSERT_FALSE(Path::IsValidFileName("baz\\foo:bar", true));
|
||||
ASSERT_FALSE(Path::IsValidFileName("baz/foo:bar", true));
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
ASSERT_TRUE(Path::IsValidFileName("baz\\foo", true));
|
||||
ASSERT_FALSE(Path::IsValidFileName("baz\\foo", false));
|
||||
ASSERT_FALSE(Path::IsValidFileName("foo.", true));
|
||||
ASSERT_FALSE(Path::IsValidFileName("foo\\.", true));
|
||||
#else
|
||||
ASSERT_FALSE(Path::IsValidFileName("foo\\*", true));
|
||||
ASSERT_FALSE(Path::IsValidFileName("foo*", true));
|
||||
#endif
|
||||
|
||||
ASSERT_TRUE(Path::IsValidFileName("baz/foo", true));
|
||||
ASSERT_FALSE(Path::IsValidFileName("baz/foo", false));
|
||||
}
|
||||
|
||||
TEST(Path, IsAbsolute)
|
||||
{
|
||||
ASSERT_FALSE(Path::IsAbsolute(""));
|
||||
ASSERT_FALSE(Path::IsAbsolute("foo"));
|
||||
ASSERT_FALSE(Path::IsAbsolute("foo/bar"));
|
||||
ASSERT_FALSE(Path::IsAbsolute("foo/b🙃ar"));
|
||||
#ifdef _WIN32
|
||||
ASSERT_TRUE(Path::IsAbsolute("C:\\foo/bar"));
|
||||
ASSERT_TRUE(Path::IsAbsolute("C://foo\\bar"));
|
||||
ASSERT_FALSE(Path::IsAbsolute("\\foo/bar"));
|
||||
ASSERT_TRUE(Path::IsAbsolute("\\\\foo\\bar\\baz"));
|
||||
#else
|
||||
ASSERT_TRUE(Path::IsAbsolute("/foo/bar"));
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Path, Canonicalize)
|
||||
{
|
||||
ASSERT_EQ(Path::Canonicalize(""), Path::ToNativePath(""));
|
||||
ASSERT_EQ(Path::Canonicalize("foo/bar/../baz"), Path::ToNativePath("foo/baz"));
|
||||
ASSERT_EQ(Path::Canonicalize("foo/bar/./baz"), Path::ToNativePath("foo/bar/baz"));
|
||||
ASSERT_EQ(Path::Canonicalize("foo/./bar/./baz"), Path::ToNativePath("foo/bar/baz"));
|
||||
ASSERT_EQ(Path::Canonicalize("foo/bar/../baz/../foo"), Path::ToNativePath("foo/foo"));
|
||||
ASSERT_EQ(Path::Canonicalize("foo/bar/../baz/./foo"), Path::ToNativePath("foo/baz/foo"));
|
||||
ASSERT_EQ(Path::Canonicalize("./foo"), Path::ToNativePath("foo"));
|
||||
ASSERT_EQ(Path::Canonicalize("../foo"), Path::ToNativePath("../foo"));
|
||||
ASSERT_EQ(Path::Canonicalize("foo/b🙃ar/../b🙃az/./foo"), Path::ToNativePath("foo/b🙃az/foo"));
|
||||
ASSERT_EQ(Path::Canonicalize("ŻąłóРстуぬねのはen🍪⟑η∏☉ⴤℹ︎∩₲ ₱⟑♰⫳🐱/b🙃az/../foℹ︎o"), Path::ToNativePath("ŻąłóРстуぬねのはen🍪⟑η∏☉ⴤℹ︎∩₲ ₱⟑♰⫳🐱/foℹ︎o"));
|
||||
#ifdef _WIN32
|
||||
ASSERT_EQ(Path::Canonicalize("C:\\foo\\bar\\..\\baz\\.\\foo"), "C:\\foo\\baz\\foo");
|
||||
ASSERT_EQ(Path::Canonicalize("C:/foo\\bar\\..\\baz\\.\\foo"), "C:\\foo\\baz\\foo");
|
||||
ASSERT_EQ(Path::Canonicalize("foo\\bar\\..\\baz\\.\\foo"), "foo\\baz\\foo");
|
||||
ASSERT_EQ(Path::Canonicalize("foo\\bar/..\\baz/.\\foo"), "foo\\baz\\foo");
|
||||
ASSERT_EQ(Path::Canonicalize("\\\\foo\\bar\\baz/..\\foo"), "\\\\foo\\bar\\foo");
|
||||
#else
|
||||
ASSERT_EQ(Path::Canonicalize("/foo/bar/../baz/./foo"), "/foo/baz/foo");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Path, Combine)
|
||||
{
|
||||
ASSERT_EQ(Path::Combine("", ""), Path::ToNativePath(""));
|
||||
ASSERT_EQ(Path::Combine("foo", "bar"), Path::ToNativePath("foo/bar"));
|
||||
ASSERT_EQ(Path::Combine("foo/bar", "baz"), Path::ToNativePath("foo/bar/baz"));
|
||||
ASSERT_EQ(Path::Combine("foo/bar", "../baz"), Path::ToNativePath("foo/bar/../baz"));
|
||||
ASSERT_EQ(Path::Combine("foo/bar/", "/baz/"), Path::ToNativePath("foo/bar/baz"));
|
||||
ASSERT_EQ(Path::Combine("foo//bar", "baz/"), Path::ToNativePath("foo/bar/baz"));
|
||||
ASSERT_EQ(Path::Combine("foo//ba🙃r", "b🙃az/"), Path::ToNativePath("foo/ba🙃r/b🙃az"));
|
||||
#ifdef _WIN32
|
||||
ASSERT_EQ(Path::Combine("C:\\foo\\bar", "baz"), "C:\\foo\\bar\\baz");
|
||||
ASSERT_EQ(Path::Combine("\\\\server\\foo\\bar", "baz"), "\\\\server\\foo\\bar\\baz");
|
||||
ASSERT_EQ(Path::Combine("foo\\bar", "baz"), "foo\\bar\\baz");
|
||||
ASSERT_EQ(Path::Combine("foo\\bar\\", "baz"), "foo\\bar\\baz");
|
||||
ASSERT_EQ(Path::Combine("foo/bar\\", "\\baz"), "foo\\bar\\baz");
|
||||
ASSERT_EQ(Path::Combine("\\\\foo\\bar", "baz"), "\\\\foo\\bar\\baz");
|
||||
#else
|
||||
ASSERT_EQ(Path::Combine("/foo/bar", "baz"), "/foo/bar/baz");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Path, AppendDirectory)
|
||||
{
|
||||
ASSERT_EQ(Path::AppendDirectory("foo/bar", "baz"), Path::ToNativePath("foo/baz/bar"));
|
||||
ASSERT_EQ(Path::AppendDirectory("", "baz"), Path::ToNativePath("baz"));
|
||||
ASSERT_EQ(Path::AppendDirectory("", ""), Path::ToNativePath(""));
|
||||
ASSERT_EQ(Path::AppendDirectory("foo/bar", "🙃"), Path::ToNativePath("foo/🙃/bar"));
|
||||
#ifdef _WIN32
|
||||
ASSERT_EQ(Path::AppendDirectory("foo\\bar", "baz"), "foo\\baz\\bar");
|
||||
ASSERT_EQ(Path::AppendDirectory("\\\\foo\\bar", "baz"), "\\\\foo\\baz\\bar");
|
||||
#else
|
||||
ASSERT_EQ(Path::AppendDirectory("/foo/bar", "baz"), "/foo/baz/bar");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Path, MakeRelative)
|
||||
{
|
||||
ASSERT_EQ(Path::MakeRelative("", ""), Path::ToNativePath(""));
|
||||
ASSERT_EQ(Path::MakeRelative("foo", ""), Path::ToNativePath("foo"));
|
||||
ASSERT_EQ(Path::MakeRelative("", "foo"), Path::ToNativePath(""));
|
||||
ASSERT_EQ(Path::MakeRelative("foo", "bar"), Path::ToNativePath("foo"));
|
||||
|
||||
#ifdef _WIN32
|
||||
#define A "C:\\"
|
||||
#else
|
||||
#define A "/"
|
||||
#endif
|
||||
|
||||
ASSERT_EQ(Path::MakeRelative(A "foo", A "bar"), Path::ToNativePath("../foo"));
|
||||
ASSERT_EQ(Path::MakeRelative(A "foo/bar", A "foo"), Path::ToNativePath("bar"));
|
||||
ASSERT_EQ(Path::MakeRelative(A "foo/bar", A "foo/baz"), Path::ToNativePath("../bar"));
|
||||
ASSERT_EQ(Path::MakeRelative(A "foo/b🙃ar", A "foo/b🙃az"), Path::ToNativePath("../b🙃ar"));
|
||||
ASSERT_EQ(Path::MakeRelative(A "f🙃oo/b🙃ar", A "f🙃oo/b🙃az"), Path::ToNativePath("../b🙃ar"));
|
||||
ASSERT_EQ(Path::MakeRelative(A "ŻąłóРстуぬねのはen🍪⟑η∏☉ⴤℹ︎∩₲ ₱⟑♰⫳🐱/b🙃ar", A "ŻąłóРстуぬねのはen🍪⟑η∏☉ⴤℹ︎∩₲ ₱⟑♰⫳🐱/b🙃az"), Path::ToNativePath("../b🙃ar"));
|
||||
|
||||
#undef A
|
||||
|
||||
#ifdef _WIN32
|
||||
ASSERT_EQ(Path::MakeRelative("\\\\foo\\bar\\baz\\foo", "\\\\foo\\bar\\baz"), "foo");
|
||||
ASSERT_EQ(Path::MakeRelative("\\\\foo\\bar\\foo", "\\\\foo\\bar\\baz"), "..\\foo");
|
||||
ASSERT_EQ(Path::MakeRelative("\\\\foo\\bar\\foo", "\\\\other\\bar\\foo"), "\\\\foo\\bar\\foo");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Path, GetExtension)
|
||||
{
|
||||
ASSERT_EQ(Path::GetExtension("foo"), "");
|
||||
ASSERT_EQ(Path::GetExtension("foo.txt"), "txt");
|
||||
ASSERT_EQ(Path::GetExtension("foo.t🙃t"), "t🙃t");
|
||||
ASSERT_EQ(Path::GetExtension("foo."), "");
|
||||
ASSERT_EQ(Path::GetExtension("a/b/foo.txt"), "txt");
|
||||
ASSERT_EQ(Path::GetExtension("a/b/foo"), "");
|
||||
}
|
||||
|
||||
TEST(Path, GetFileName)
|
||||
{
|
||||
ASSERT_EQ(Path::GetFileName(""), "");
|
||||
ASSERT_EQ(Path::GetFileName("foo"), "foo");
|
||||
ASSERT_EQ(Path::GetFileName("foo.txt"), "foo.txt");
|
||||
ASSERT_EQ(Path::GetFileName("foo"), "foo");
|
||||
ASSERT_EQ(Path::GetFileName("foo/bar/."), ".");
|
||||
ASSERT_EQ(Path::GetFileName("foo/bar/baz"), "baz");
|
||||
ASSERT_EQ(Path::GetFileName("foo/bar/baz.txt"), "baz.txt");
|
||||
#ifdef _WIN32
|
||||
ASSERT_EQ(Path::GetFileName("foo/bar\\baz"), "baz");
|
||||
ASSERT_EQ(Path::GetFileName("foo\\bar\\baz.txt"), "baz.txt");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Path, GetFileTitle)
|
||||
{
|
||||
ASSERT_EQ(Path::GetFileTitle(""), "");
|
||||
ASSERT_EQ(Path::GetFileTitle("foo"), "foo");
|
||||
ASSERT_EQ(Path::GetFileTitle("foo.txt"), "foo");
|
||||
ASSERT_EQ(Path::GetFileTitle("foo/bar/."), "");
|
||||
ASSERT_EQ(Path::GetFileTitle("foo/bar/baz"), "baz");
|
||||
ASSERT_EQ(Path::GetFileTitle("foo/bar/baz.txt"), "baz");
|
||||
#ifdef _WIN32
|
||||
ASSERT_EQ(Path::GetFileTitle("foo/bar\\baz"), "baz");
|
||||
ASSERT_EQ(Path::GetFileTitle("foo\\bar\\baz.txt"), "baz");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Path, GetDirectory)
|
||||
{
|
||||
ASSERT_EQ(Path::GetDirectory(""), "");
|
||||
ASSERT_EQ(Path::GetDirectory("foo"), "");
|
||||
ASSERT_EQ(Path::GetDirectory("foo.txt"), "");
|
||||
ASSERT_EQ(Path::GetDirectory("foo/bar/."), "foo/bar");
|
||||
ASSERT_EQ(Path::GetDirectory("foo/bar/baz"), "foo/bar");
|
||||
ASSERT_EQ(Path::GetDirectory("foo/bar/baz.txt"), "foo/bar");
|
||||
#ifdef _WIN32
|
||||
ASSERT_EQ(Path::GetDirectory("foo\\bar\\baz"), "foo\\bar");
|
||||
ASSERT_EQ(Path::GetDirectory("foo\\bar/baz.txt"), "foo\\bar");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Path, ChangeFileName)
|
||||
{
|
||||
ASSERT_EQ(Path::ChangeFileName("", ""), Path::ToNativePath(""));
|
||||
ASSERT_EQ(Path::ChangeFileName("", "bar"), Path::ToNativePath("bar"));
|
||||
ASSERT_EQ(Path::ChangeFileName("bar", ""), Path::ToNativePath(""));
|
||||
ASSERT_EQ(Path::ChangeFileName("foo/bar", ""), Path::ToNativePath("foo"));
|
||||
ASSERT_EQ(Path::ChangeFileName("foo/", "bar"), Path::ToNativePath("foo/bar"));
|
||||
ASSERT_EQ(Path::ChangeFileName("foo/bar", "baz"), Path::ToNativePath("foo/baz"));
|
||||
ASSERT_EQ(Path::ChangeFileName("foo//bar", "baz"), Path::ToNativePath("foo/baz"));
|
||||
ASSERT_EQ(Path::ChangeFileName("foo//bar.txt", "baz.txt"), Path::ToNativePath("foo/baz.txt"));
|
||||
ASSERT_EQ(Path::ChangeFileName("foo//ba🙃r.txt", "ba🙃z.txt"), Path::ToNativePath("foo/ba🙃z.txt"));
|
||||
#ifdef _WIN32
|
||||
ASSERT_EQ(Path::ChangeFileName("foo/bar", "baz"), "foo\\baz");
|
||||
ASSERT_EQ(Path::ChangeFileName("foo//bar\\foo", "baz"), "foo\\bar\\baz");
|
||||
ASSERT_EQ(Path::ChangeFileName("\\\\foo\\bar\\foo", "baz"), "\\\\foo\\bar\\baz");
|
||||
#else
|
||||
ASSERT_EQ(Path::ChangeFileName("/foo/bar", "baz"), "/foo/baz");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Path, CreateFileURL)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
ASSERT_EQ(Path::CreateFileURL("C:\\foo\\bar"), "file:///C:/foo/bar");
|
||||
ASSERT_EQ(Path::CreateFileURL("\\\\server\\share\\file.txt"), "file://server/share/file.txt");
|
||||
#else
|
||||
ASSERT_EQ(Path::CreateFileURL("/foo/bar"), "file:///foo/bar");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if __linux__
|
||||
|
||||
static std::optional<std::string> create_test_directory()
|
||||
{
|
||||
for (u16 i = 0; i < UINT16_MAX; i++)
|
||||
{
|
||||
std::string path = std::string("/tmp/pcsx2_path_test_") + std::to_string(i);
|
||||
if (!FileSystem::DirectoryExists(path.c_str()))
|
||||
{
|
||||
if (!FileSystem::CreateDirectoryPath(path.c_str(), false))
|
||||
break;
|
||||
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
TEST(Path, RealPathAbsoluteSymbolicLink)
|
||||
{
|
||||
std::optional<std::string> test_dir = create_test_directory();
|
||||
ASSERT_TRUE(test_dir.has_value());
|
||||
|
||||
// Create a file to point at.
|
||||
std::string file_path = Path::Combine(*test_dir, "file");
|
||||
ASSERT_TRUE(FileSystem::WriteStringToFile(file_path.c_str(), "Hello, world!"));
|
||||
|
||||
// Create a symbolic link that points to said file.
|
||||
std::string link_path = Path::Combine(*test_dir, "link");
|
||||
ASSERT_TRUE(FileSystem::CreateSymLink(link_path.c_str(), file_path.c_str()));
|
||||
|
||||
// Make sure the symbolic link is resolved correctly.
|
||||
ASSERT_EQ(Path::RealPath(link_path), file_path);
|
||||
|
||||
// Clean up.
|
||||
ASSERT_TRUE(FileSystem::DeleteSymbolicLink(link_path.c_str()));
|
||||
ASSERT_TRUE(FileSystem::DeleteFilePath(file_path.c_str()));
|
||||
ASSERT_TRUE(FileSystem::DeleteDirectory(test_dir->c_str()));
|
||||
}
|
||||
|
||||
TEST(Path, RealPathRelativeSymbolicLink)
|
||||
{
|
||||
std::optional<std::string> test_dir = create_test_directory();
|
||||
ASSERT_TRUE(test_dir.has_value());
|
||||
|
||||
// Create a file to point at.
|
||||
std::string file_path = Path::Combine(*test_dir, "file");
|
||||
ASSERT_TRUE(FileSystem::WriteStringToFile(file_path.c_str(), "Hello, world!"));
|
||||
|
||||
// Create a symbolic link that points to said file.
|
||||
std::string link_path = Path::Combine(*test_dir, "link");
|
||||
ASSERT_TRUE(FileSystem::CreateSymLink(link_path.c_str(), "file"));
|
||||
|
||||
// Make sure the symbolic link is resolved correctly.
|
||||
ASSERT_EQ(Path::RealPath(link_path), file_path);
|
||||
|
||||
// Clean up.
|
||||
ASSERT_TRUE(FileSystem::DeleteSymbolicLink(link_path.c_str()));
|
||||
ASSERT_TRUE(FileSystem::DeleteFilePath(file_path.c_str()));
|
||||
ASSERT_TRUE(FileSystem::DeleteDirectory(test_dir->c_str()));
|
||||
}
|
||||
|
||||
TEST(Path, RealPathDotDotSymbolicLink)
|
||||
{
|
||||
std::optional<std::string> test_dir = create_test_directory();
|
||||
ASSERT_TRUE(test_dir.has_value());
|
||||
|
||||
// Create a file to point at.
|
||||
std::string file_path = Path::Combine(*test_dir, "file");
|
||||
ASSERT_TRUE(FileSystem::WriteStringToFile(file_path.c_str(), "Hello, world!"));
|
||||
|
||||
// Create a directory to put the link in.
|
||||
std::string link_dir = Path::Combine(*test_dir, "dir");
|
||||
ASSERT_TRUE(FileSystem::CreateDirectoryPath(link_dir.c_str(), false));
|
||||
|
||||
// Create a symbolic link that points to said file.
|
||||
std::string link_path = Path::Combine(link_dir, "link");
|
||||
ASSERT_TRUE(FileSystem::CreateSymLink(link_path.c_str(), "../file"));
|
||||
|
||||
// Make sure the symbolic link is resolved correctly.
|
||||
ASSERT_EQ(Path::RealPath(link_path), file_path);
|
||||
|
||||
// Clean up.
|
||||
ASSERT_TRUE(FileSystem::DeleteSymbolicLink(link_path.c_str()));
|
||||
ASSERT_TRUE(FileSystem::DeleteDirectory(link_dir.c_str()));
|
||||
ASSERT_TRUE(FileSystem::DeleteFilePath(file_path.c_str()));
|
||||
ASSERT_TRUE(FileSystem::DeleteDirectory(test_dir->c_str()));
|
||||
}
|
||||
|
||||
TEST(Path, RealPathCircularSymbolicLink)
|
||||
{
|
||||
std::optional<std::string> test_dir = create_test_directory();
|
||||
ASSERT_TRUE(test_dir.has_value());
|
||||
|
||||
// Create a circular symbolic link.
|
||||
std::string link_path = Path::Combine(*test_dir, "link");
|
||||
ASSERT_TRUE(FileSystem::CreateSymLink(link_path.c_str(), "."));
|
||||
|
||||
// Make sure the link gets resolved correctly.
|
||||
ASSERT_EQ(Path::RealPath(link_path), *test_dir);
|
||||
ASSERT_EQ(Path::RealPath(Path::Combine(link_path, "link")), *test_dir);
|
||||
|
||||
// Clean up.
|
||||
ASSERT_TRUE(FileSystem::DeleteSymbolicLink(link_path.c_str()));
|
||||
ASSERT_TRUE(FileSystem::DeleteDirectory(test_dir->c_str()));
|
||||
}
|
||||
|
||||
TEST(Path, RealPathLoopingSymbolicLink)
|
||||
{
|
||||
std::optional<std::string> test_dir = create_test_directory();
|
||||
ASSERT_TRUE(test_dir.has_value());
|
||||
|
||||
// Create a symbolic link that points to itself.
|
||||
std::string link_path = Path::Combine(*test_dir, "link");
|
||||
ASSERT_TRUE(FileSystem::CreateSymLink(link_path.c_str(), "link"));
|
||||
|
||||
// Make sure this doesn't cause problems.
|
||||
ASSERT_EQ(Path::RealPath(link_path), link_path);
|
||||
|
||||
// Clean up.
|
||||
ASSERT_TRUE(FileSystem::DeleteSymbolicLink(link_path.c_str()));
|
||||
ASSERT_TRUE(FileSystem::DeleteDirectory(test_dir->c_str()));
|
||||
}
|
||||
|
||||
#endif
|
||||
132
tests/ctest/common/string_util_tests.cpp
Normal file
132
tests/ctest/common/string_util_tests.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
#include "common/StringUtil.h"
|
||||
#include <locale>
|
||||
#include <clocale>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(StringUtil, ToChars)
|
||||
{
|
||||
ASSERT_EQ(StringUtil::ToChars(false), "false");
|
||||
ASSERT_EQ(StringUtil::ToChars(true), "true");
|
||||
ASSERT_EQ(StringUtil::ToChars(0), "0");
|
||||
ASSERT_EQ(StringUtil::ToChars(-1337), "-1337");
|
||||
ASSERT_EQ(StringUtil::ToChars(1337), "1337");
|
||||
ASSERT_EQ(StringUtil::ToChars(1337u), "1337");
|
||||
ASSERT_EQ(StringUtil::ToChars(13.37f), "13.37");
|
||||
ASSERT_EQ(StringUtil::ToChars(255, 16), "ff");
|
||||
}
|
||||
|
||||
TEST(StringUtil, FromChars)
|
||||
{
|
||||
ASSERT_EQ(StringUtil::FromChars<bool>("false").value_or(true), false);
|
||||
ASSERT_EQ(StringUtil::FromChars<bool>("true").value_or(false), true);
|
||||
ASSERT_EQ(StringUtil::FromChars<int>("0").value_or(-1), 0);
|
||||
ASSERT_EQ(StringUtil::FromChars<int>("-1337").value_or(0), -1337);
|
||||
ASSERT_EQ(StringUtil::FromChars<int>("1337").value_or(0), 1337);
|
||||
ASSERT_EQ(StringUtil::FromChars<u32>("1337").value_or(0), 1337);
|
||||
ASSERT_TRUE(std::abs(StringUtil::FromChars<float>("13.37").value_or(0.0f) - 13.37) < 0.01f);
|
||||
ASSERT_EQ(StringUtil::FromChars<int>("ff", 16).value_or(0), 255);
|
||||
}
|
||||
|
||||
TEST(StringUtil, FromCharsWithEndPtr)
|
||||
{
|
||||
using namespace std::literals;
|
||||
|
||||
std::string_view endptr;
|
||||
ASSERT_EQ(StringUtil::FromChars<u32>("123x456", 16, &endptr), std::optional<u32>(0x123));
|
||||
ASSERT_EQ(endptr, "x456"sv);
|
||||
|
||||
ASSERT_EQ(StringUtil::FromChars<u32>("0x1234", 16, &endptr), std::optional<u32>(0u));
|
||||
ASSERT_EQ(endptr, "x1234"sv);
|
||||
|
||||
ASSERT_EQ(StringUtil::FromChars<u32>("1234", 16, &endptr), std::optional<u32>(0x1234u));
|
||||
ASSERT_TRUE(endptr.empty());
|
||||
|
||||
ASSERT_EQ(StringUtil::FromChars<u32>("abcdefg", 16, &endptr), std::optional<u32>(0xabcdef));
|
||||
ASSERT_EQ(endptr, "g"sv);
|
||||
|
||||
ASSERT_EQ(StringUtil::FromChars<u32>("123abc", 10, &endptr), std::optional<u32>(123));
|
||||
ASSERT_EQ(endptr, "abc"sv);
|
||||
|
||||
ASSERT_EQ(StringUtil::FromChars<float>("1.0g", &endptr), std::optional<float>(1.0f));
|
||||
ASSERT_EQ(endptr, "g"sv);
|
||||
|
||||
ASSERT_EQ(StringUtil::FromChars<float>("2x", &endptr), std::optional<float>(2.0f));
|
||||
ASSERT_EQ(endptr, "x"sv);
|
||||
|
||||
ASSERT_EQ(StringUtil::FromChars<float>(".1p", &endptr), std::optional<float>(0.1f));
|
||||
ASSERT_EQ(endptr, "p"sv);
|
||||
|
||||
ASSERT_EQ(StringUtil::FromChars<float>("1", &endptr), std::optional<float>(1.0f));
|
||||
ASSERT_TRUE(endptr.empty());
|
||||
}
|
||||
|
||||
#if 0
|
||||
// NOTE: These tests are disabled, because they require the da_DK locale to actually be present.
|
||||
// Which probably isn't going to be the case on the CI.
|
||||
|
||||
TEST(StringUtil, ToCharsIsLocaleIndependent)
|
||||
{
|
||||
const auto old_locale = std::locale();
|
||||
std::locale::global(std::locale::classic());
|
||||
|
||||
std::string classic_result(StringUtil::ToChars(13.37f));
|
||||
|
||||
std::locale::global(std::locale("da_DK"));
|
||||
|
||||
std::string dk_result(StringUtil::ToChars(13.37f));
|
||||
|
||||
std::locale::global(old_locale);
|
||||
|
||||
ASSERT_EQ(classic_result, dk_result);
|
||||
}
|
||||
|
||||
TEST(StringUtil, FromCharsIsLocaleIndependent)
|
||||
{
|
||||
const auto old_locale = std::locale();
|
||||
std::locale::global(std::locale::classic());
|
||||
|
||||
const float classic_result = StringUtil::FromChars<float>("13.37").value_or(0.0f);
|
||||
|
||||
std::locale::global(std::locale("da_DK"));
|
||||
|
||||
const float dk_result = StringUtil::FromChars<float>("13.37").value_or(0.0f);
|
||||
|
||||
std::locale::global(old_locale);
|
||||
|
||||
ASSERT_EQ(classic_result, dk_result);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST(StringUtil, Ellipsise)
|
||||
{
|
||||
ASSERT_EQ(StringUtil::Ellipsise("HelloWorld", 6, "..."), "Hel...");
|
||||
ASSERT_EQ(StringUtil::Ellipsise("HelloWorld", 7, ".."), "Hello..");
|
||||
ASSERT_EQ(StringUtil::Ellipsise("HelloWorld", 20, ".."), "HelloWorld");
|
||||
ASSERT_EQ(StringUtil::Ellipsise("", 20, "..."), "");
|
||||
ASSERT_EQ(StringUtil::Ellipsise("Hello", 10, "..."), "Hello");
|
||||
}
|
||||
|
||||
TEST(StringUtil, EllipsiseInPlace)
|
||||
{
|
||||
std::string s;
|
||||
s = "HelloWorld";
|
||||
StringUtil::EllipsiseInPlace(s, 6, "...");
|
||||
ASSERT_EQ(s, "Hel...");
|
||||
s = "HelloWorld";
|
||||
StringUtil::EllipsiseInPlace(s, 7, "..");
|
||||
ASSERT_EQ(s, "Hello..");
|
||||
s = "HelloWorld";
|
||||
StringUtil::EllipsiseInPlace(s, 20, "..");
|
||||
ASSERT_EQ(s, "HelloWorld");
|
||||
s = "";
|
||||
StringUtil::EllipsiseInPlace(s, 20, "...");
|
||||
ASSERT_EQ(s, "");
|
||||
s = "Hello";
|
||||
StringUtil::EllipsiseInPlace(s, 10, "...");
|
||||
ASSERT_EQ(s, "Hello");
|
||||
}
|
||||
32
tests/ctest/common/x86emitter/codegen_tests.cpp
Normal file
32
tests/ctest/common/x86emitter/codegen_tests.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "codegen_tests.h"
|
||||
#include <gtest/gtest.h>
|
||||
#include <common/emitter/x86emitter.h>
|
||||
#include <common/Assertions.h>
|
||||
|
||||
using namespace x86Emitter;
|
||||
|
||||
thread_local const char *currentTest;
|
||||
|
||||
void runCodegenTest(void (*exec)(void *base), const char* description, const char* expected) {
|
||||
u8 code[4096];
|
||||
memset(code, 0xcc, sizeof(code));
|
||||
char str[4096] = {0};
|
||||
|
||||
if (!expected) return;
|
||||
currentTest = description;
|
||||
xSetPtr(code);
|
||||
exec(code);
|
||||
char *strPtr = str;
|
||||
for (u8* ptr = code; ptr < xGetPtr(); ptr++) {
|
||||
sprintf(strPtr, "%02x ", *ptr);
|
||||
strPtr += 3;
|
||||
}
|
||||
if (strPtr != str) {
|
||||
// Remove final space
|
||||
*--strPtr = '\0';
|
||||
}
|
||||
EXPECT_STRCASEEQ(expected, str) << "Unexpected codegen from " << description;
|
||||
}
|
||||
8
tests/ctest/common/x86emitter/codegen_tests.h
Normal file
8
tests/ctest/common/x86emitter/codegen_tests.h
Normal file
@@ -0,0 +1,8 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
|
||||
void runCodegenTest(void (*exec)(void *base), const char* description, const char* expected);
|
||||
|
||||
#define CODEGEN_TEST(command, expected) runCodegenTest([](void *base){ command; }, #command, expected)
|
||||
285
tests/ctest/common/x86emitter/codegen_tests_main.cpp
Normal file
285
tests/ctest/common/x86emitter/codegen_tests_main.cpp
Normal file
@@ -0,0 +1,285 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "codegen_tests.h"
|
||||
#include <gtest/gtest.h>
|
||||
#include <common/emitter/x86emitter.h>
|
||||
#include <cstdio>
|
||||
|
||||
using namespace x86Emitter;
|
||||
|
||||
TEST(CodegenTests, MOVTest)
|
||||
{
|
||||
CODEGEN_TEST(xMOV(rax, 0), "31 c0");
|
||||
CODEGEN_TEST(xMOV(rax, rcx), "48 89 c8");
|
||||
CODEGEN_TEST(xMOV(eax, ecx), "89 c8");
|
||||
CODEGEN_TEST(xMOV(r8, 0), "45 31 c0");
|
||||
CODEGEN_TEST(xMOV(rax, r8), "4c 89 c0");
|
||||
CODEGEN_TEST(xMOV(r8, rax), "49 89 c0");
|
||||
CODEGEN_TEST(xMOV(r8, r9), "4d 89 c8");
|
||||
CODEGEN_TEST(xMOV(rax, ptr64[rcx]), "48 8b 01");
|
||||
CODEGEN_TEST(xMOV(eax, ptr32[rcx]), "8b 01");
|
||||
CODEGEN_TEST(xMOV(ptr64[rax], rcx), "48 89 08");
|
||||
CODEGEN_TEST(xMOV(ptr32[rax], ecx), "89 08");
|
||||
CODEGEN_TEST(xMOV(rax, ptr64[r8]), "49 8b 00");
|
||||
CODEGEN_TEST(xMOV(ptr64[r8], rax), "49 89 00");
|
||||
CODEGEN_TEST(xMOV(r8, ptr64[r9]), "4d 8b 01");
|
||||
CODEGEN_TEST(xMOV(ptr64[r8], r9), "4d 89 08");
|
||||
CODEGEN_TEST(xMOV(rax, ptr64[rbx*4+3+rcx]), "48 8b 44 99 03");
|
||||
CODEGEN_TEST(xMOV(ptr64[rbx*4+3+rax], rcx), "48 89 4c 98 03");
|
||||
CODEGEN_TEST(xMOV(eax, ptr32[rbx*4+3+rcx]), "8b 44 99 03");
|
||||
CODEGEN_TEST(xMOV(ptr32[rbx*4+3+rax], ecx), "89 4c 98 03");
|
||||
CODEGEN_TEST(xMOV(r8, ptr64[r10*4+3+r9]), "4f 8b 44 91 03");
|
||||
CODEGEN_TEST(xMOV(ptr64[r9*4+3+r8], r10), "4f 89 54 88 03");
|
||||
CODEGEN_TEST(xMOV(ptr64[r8], 0), "49 c7 00 00 00 00 00");
|
||||
CODEGEN_TEST(xMOV(ptr32[rax], 0), "c7 00 00 00 00 00");
|
||||
CODEGEN_TEST(xMOV(ptr32[rbx*4+3+rax], -1), "c7 44 98 03 ff ff ff ff");
|
||||
CODEGEN_TEST(xMOV(rax, 0xffffffff), "b8 ff ff ff ff");
|
||||
CODEGEN_TEST(xMOV(r8, -1), "49 c7 c0 ff ff ff ff");
|
||||
CODEGEN_TEST(xMOV64(rax, 0x1234567890), "48 b8 90 78 56 34 12 00 00 00");
|
||||
CODEGEN_TEST(xMOV64(r8, 0x1234567890), "49 b8 90 78 56 34 12 00 00 00");
|
||||
CODEGEN_TEST(xMOV(ptr32[base], 0x12), "c7 05 f6 ff ff ff 12 00 00 00");
|
||||
CODEGEN_TEST(xMOVSX(eax, dx), "0f bf c2");
|
||||
CODEGEN_TEST(xMOVSX(rax, r8d), "49 63 c0");
|
||||
CODEGEN_TEST(xMOVSX(rax, ebx), "48 63 c3");
|
||||
}
|
||||
|
||||
TEST(CodegenTests, LEATest)
|
||||
{
|
||||
CODEGEN_TEST(xLEA(rax, ptr[rcx]), "48 89 c8"); // Converted to mov rax, rcx
|
||||
CODEGEN_TEST(xLEA(eax, ptr[rcx]), "89 c8"); // Converted to mov eax, ecx
|
||||
CODEGEN_TEST(xLEA(rax, ptr[r8]), "4c 89 c0"); // Converted to mov rax, r8
|
||||
CODEGEN_TEST(xLEA(r8, ptr[r9]), "4d 89 c8"); // Converted to mov r8, r9
|
||||
CODEGEN_TEST(xLEA(rax, ptr[rbx*4+3+rcx]), "48 8d 44 99 03");
|
||||
CODEGEN_TEST(xLEA(eax, ptr32[rbx*4+3+rcx]), "8d 44 99 03");
|
||||
CODEGEN_TEST(xLEA(r8, ptr[r10*4+3+r9]), "4f 8d 44 91 03");
|
||||
CODEGEN_TEST(xLEA(r8, ptr[base]), "4c 8d 05 f9 ff ff ff");
|
||||
CODEGEN_TEST(xLoadFarAddr(r8, base), "4c 8d 05 f9 ff ff ff");
|
||||
CODEGEN_TEST(xLoadFarAddr(r8, (void*)0xff00001234567890), "49 b8 90 78 56 34 12 00 00 ff");
|
||||
CODEGEN_TEST(xLEA(rax, ptr[(void*)0x1234]), "b8 34 12 00 00"); // Converted to mov rax, 0x1234
|
||||
CODEGEN_TEST(xLoadFarAddr(rax, (void*)0x1234), "b8 34 12 00 00");
|
||||
CODEGEN_TEST(xLEA_Writeback(rbx), "48 8d 1d cd cd cd 0d");
|
||||
}
|
||||
|
||||
TEST(CodegenTests, PUSHTest)
|
||||
{
|
||||
CODEGEN_TEST(xPUSH(rax), "50");
|
||||
CODEGEN_TEST(xPUSH(r8), "41 50");
|
||||
CODEGEN_TEST(xPUSH(0x1234), "68 34 12 00 00");
|
||||
CODEGEN_TEST(xPUSH(0x12), "6a 12");
|
||||
CODEGEN_TEST(xPUSH(ptr64[rax]), "ff 30");
|
||||
CODEGEN_TEST(xPUSH(ptr64[r8]), "41 ff 30");
|
||||
CODEGEN_TEST(xPUSH(ptr64[rax*2+3+rbx]), "ff 74 43 03");
|
||||
CODEGEN_TEST(xPUSH(ptr64[rax*2+3+r8]), "41 ff 74 40 03");
|
||||
CODEGEN_TEST(xPUSH(ptr64[r9*4+3+r8]), "43 ff 74 88 03");
|
||||
CODEGEN_TEST(xPUSH(ptr64[r8*4+3+rax]), "42 ff 74 80 03");
|
||||
CODEGEN_TEST(xPUSH(ptr64[rax*8+0x1234+rbx]), "ff b4 c3 34 12 00 00");
|
||||
CODEGEN_TEST(xPUSH(ptr64[base]), "ff 35 fa ff ff ff");
|
||||
CODEGEN_TEST(xPUSH(ptr64[(void*)0x1234]), "ff 34 25 34 12 00 00");
|
||||
}
|
||||
|
||||
TEST(CodegenTests, POPTest)
|
||||
{
|
||||
CODEGEN_TEST(xPOP(rax), "58");
|
||||
CODEGEN_TEST(xPOP(r8), "41 58");
|
||||
CODEGEN_TEST(xPOP(ptr64[rax]), "8f 00");
|
||||
CODEGEN_TEST(xPOP(ptr64[r8]), "41 8f 00");
|
||||
CODEGEN_TEST(xPOP(ptr64[rax*2+3+rbx]), "8f 44 43 03");
|
||||
CODEGEN_TEST(xPOP(ptr64[rax*2+3+r8]), "41 8f 44 40 03");
|
||||
CODEGEN_TEST(xPOP(ptr64[r9*4+3+r8]), "43 8f 44 88 03");
|
||||
CODEGEN_TEST(xPOP(ptr64[r8*4+3+rax]), "42 8f 44 80 03");
|
||||
CODEGEN_TEST(xPOP(ptr64[rax*8+0x1234+rbx]), "8f 84 c3 34 12 00 00");
|
||||
CODEGEN_TEST(xPOP(ptr64[base]), "8f 05 fa ff ff ff");
|
||||
CODEGEN_TEST(xPOP(ptr64[(void*)0x1234]), "8f 04 25 34 12 00 00");
|
||||
}
|
||||
|
||||
TEST(CodegenTests, MathTest)
|
||||
{
|
||||
CODEGEN_TEST(xINC(eax), "ff c0");
|
||||
CODEGEN_TEST(xDEC(rax), "48 ff c8");
|
||||
CODEGEN_TEST(xINC(r8), "49 ff c0");
|
||||
CODEGEN_TEST(xADD(r8, r9), "4d 01 c8");
|
||||
CODEGEN_TEST(xADD(r8, 0x12), "49 83 c0 12");
|
||||
CODEGEN_TEST(xADD(rax, 0x1234), "48 05 34 12 00 00");
|
||||
CODEGEN_TEST(xADD(ptr8[base], 1), "80 05 f9 ff ff ff 01");
|
||||
CODEGEN_TEST(xADD(ptr32[base], -0x60), "83 05 f9 ff ff ff a0");
|
||||
CODEGEN_TEST(xADD(ptr32[base], 0x1234), "81 05 f6 ff ff ff 34 12 00 00");
|
||||
CODEGEN_TEST(xADD(eax, ebx), "01 d8");
|
||||
CODEGEN_TEST(xADD(eax, 0x1234), "05 34 12 00 00");
|
||||
CODEGEN_TEST(xADD(r8, ptr64[r10*4+3+r9]), "4f 03 44 91 03");
|
||||
CODEGEN_TEST(xADD(ptr64[r9*4+3+r8], r10), "4f 01 54 88 03");
|
||||
CODEGEN_TEST(xADD(eax, ptr32[rbx*4+3+rcx]), "03 44 99 03");
|
||||
CODEGEN_TEST(xADD(ptr32[rax*4+3+rbx], ecx), "01 4c 83 03");
|
||||
CODEGEN_TEST(xSUB(r8, 0x12), "49 83 e8 12");
|
||||
CODEGEN_TEST(xSUB(rax, 0x1234), "48 2d 34 12 00 00");
|
||||
CODEGEN_TEST(xSUB(eax, ptr32[rcx*4+rax]), "2b 04 88");
|
||||
CODEGEN_TEST(xMUL(ptr32[base]), "f7 2d fa ff ff ff");
|
||||
CODEGEN_TEST(xMUL(ptr32[(void*)0x1234]), "f7 2c 25 34 12 00 00");
|
||||
CODEGEN_TEST(xDIV(ecx), "f7 f9");
|
||||
}
|
||||
|
||||
TEST(CodegenTests, BitwiseTest)
|
||||
{
|
||||
CODEGEN_TEST(xSHR(r8, cl), "49 d3 e8");
|
||||
CODEGEN_TEST(xSHR(rax, cl), "48 d3 e8");
|
||||
CODEGEN_TEST(xSHR(ecx, cl), "d3 e9");
|
||||
CODEGEN_TEST(xSAR(r8, 1), "49 d1 f8");
|
||||
CODEGEN_TEST(xSAR(rax, 60), "48 c1 f8 3c");
|
||||
CODEGEN_TEST(xSAR(eax, 30), "c1 f8 1e");
|
||||
CODEGEN_TEST(xSHL(ebx, 30), "c1 e3 1e");
|
||||
CODEGEN_TEST(xSHL(ptr32[base], 4), "c1 25 f9 ff ff ff 04");
|
||||
CODEGEN_TEST(xAND(r8, r9), "4d 21 c8");
|
||||
CODEGEN_TEST(xXOR(rax, ptr64[r10]), "49 33 02");
|
||||
CODEGEN_TEST(xOR(esi, ptr32[rax+rbx]), "0b 34 18");
|
||||
CODEGEN_TEST(xNOT(r8), "49 f7 d0");
|
||||
CODEGEN_TEST(xNOT(ptr64[rax]), "48 f7 10");
|
||||
CODEGEN_TEST(xNOT(ptr32[rbx]), "f7 13");
|
||||
}
|
||||
|
||||
TEST(CodegenTests, JmpTest)
|
||||
{
|
||||
CODEGEN_TEST(xJMP(r8), "41 ff e0");
|
||||
CODEGEN_TEST(xJMP(rdi), "ff e7");
|
||||
CODEGEN_TEST(xJMP(ptr64[rax]), "ff 20");
|
||||
CODEGEN_TEST(xJA(base), "77 fe");
|
||||
CODEGEN_TEST(xJB((char*)base - 0xFFFF), "0f 82 fb ff fe ff");
|
||||
}
|
||||
|
||||
TEST(CodegenTests, SSETest)
|
||||
{
|
||||
CODEGEN_TEST(xMOVAPS(xmm0, xmm1), "0f 28 c1");
|
||||
CODEGEN_TEST(xMOVAPS(xmm8, xmm9), "45 0f 28 c1");
|
||||
CODEGEN_TEST(xMOVUPS(xmm8, ptr128[r8+r9]), "47 0f 10 04 08");
|
||||
CODEGEN_TEST(xMOVAPS(ptr128[rax+r9], xmm8), "46 0f 29 04 08");
|
||||
CODEGEN_TEST(xBLEND.PS(xmm0, xmm1, 0x55), "66 0f 3a 0c c1 55");
|
||||
CODEGEN_TEST(xBLEND.PD(xmm8, xmm9, 0xaa), "66 45 0f 3a 0d c1 aa");
|
||||
CODEGEN_TEST(xPBLEND.W(xmm0, xmm1, 0x55), "66 0f 3a 0e c1 55");
|
||||
CODEGEN_TEST(xPBLEND.VB(xmm1, xmm2), "66 0f 38 10 ca");
|
||||
CODEGEN_TEST(xEXTRACTPS(ptr32[base], xmm1, 2), "66 0f 3a 17 0d f6 ff ff ff 02");
|
||||
CODEGEN_TEST(xMOVD(eax, xmm1), "66 0f 7e c8");
|
||||
CODEGEN_TEST(xMOVD(eax, xmm10), "66 44 0f 7e d0");
|
||||
CODEGEN_TEST(xMOVD(rax, xmm1), "66 48 0f 7e c8");
|
||||
CODEGEN_TEST(xMOVD(r10, xmm1), "66 49 0f 7e ca");
|
||||
CODEGEN_TEST(xMOVD(rax, xmm10), "66 4c 0f 7e d0");
|
||||
CODEGEN_TEST(xMOVD(r10, xmm10), "66 4d 0f 7e d2");
|
||||
CODEGEN_TEST(xPINSR.B(xmm0, ebx, 1), "66 0f 3a 20 c3 01");
|
||||
CODEGEN_TEST(xPINSR.W(xmm0, ebx, 1), "66 0f c4 c3 01");
|
||||
CODEGEN_TEST(xPINSR.D(xmm0, ebx, 1), "66 0f 3a 22 c3 01");
|
||||
CODEGEN_TEST(xPINSR.Q(xmm0, rbx, 1), "66 48 0f 3a 22 c3 01");
|
||||
CODEGEN_TEST(xPEXTR.B(ebx, xmm0, 1), "66 0f 3a 14 c3 01");
|
||||
CODEGEN_TEST(xPEXTR.W(ebx, xmm0, 1), "66 0f c5 c3 01");
|
||||
CODEGEN_TEST(xPEXTR.D(ebx, xmm0, 1), "66 0f 3a 16 c3 01");
|
||||
CODEGEN_TEST(xPEXTR.Q(rbx, xmm0, 1), "66 48 0f 3a 16 c3 01");
|
||||
CODEGEN_TEST(xPEXTR.Q(ptr64[rax], xmm0, 1), "66 48 0f 3a 16 00 01");
|
||||
}
|
||||
|
||||
TEST(CodegenTests, AVXTest)
|
||||
{
|
||||
CODEGEN_TEST(xVMOVAPS(xmm0, xmm1), "c5 f8 28 c1");
|
||||
CODEGEN_TEST(xVMOVAPS(xmm0, ptr32[rdi]), "c5 f8 28 07");
|
||||
CODEGEN_TEST(xVMOVAPS(ptr32[rdi], xmm0), "c5 f8 29 07");
|
||||
CODEGEN_TEST(xVMOVUPS(xmm0, ptr32[rdi]), "c5 f8 10 07");
|
||||
CODEGEN_TEST(xVMOVUPS(ptr32[rdi], xmm0), "c5 f8 11 07");
|
||||
|
||||
CODEGEN_TEST(xVADD.PS(xmm0, xmm1, xmm2), "c5 f0 58 c2");
|
||||
CODEGEN_TEST(xVADD.PD(xmm0, xmm1, xmm2), "c5 f1 58 c2");
|
||||
CODEGEN_TEST(xVADD.SS(xmm0, xmm1, xmm2), "c5 f2 58 c2");
|
||||
CODEGEN_TEST(xVADD.SD(xmm0, xmm1, xmm2), "c5 f3 58 c2");
|
||||
CODEGEN_TEST(xVSUB.PS(xmm0, xmm1, xmm2), "c5 f0 5c c2");
|
||||
CODEGEN_TEST(xVSUB.PD(xmm0, xmm1, xmm2), "c5 f1 5c c2");
|
||||
CODEGEN_TEST(xVSUB.SS(xmm0, xmm1, xmm2), "c5 f2 5c c2");
|
||||
CODEGEN_TEST(xVSUB.SD(xmm0, xmm1, xmm2), "c5 f3 5c c2");
|
||||
CODEGEN_TEST(xVMUL.PS(xmm0, xmm1, xmm2), "c5 f0 59 c2");
|
||||
CODEGEN_TEST(xVMUL.PD(xmm0, xmm1, xmm2), "c5 f1 59 c2");
|
||||
CODEGEN_TEST(xVMUL.SS(xmm0, xmm1, xmm2), "c5 f2 59 c2");
|
||||
CODEGEN_TEST(xVMUL.SD(xmm0, xmm1, xmm2), "c5 f3 59 c2");
|
||||
CODEGEN_TEST(xVDIV.PS(xmm0, xmm1, xmm2), "c5 f0 5e c2");
|
||||
CODEGEN_TEST(xVDIV.PD(xmm0, xmm1, xmm2), "c5 f1 5e c2");
|
||||
CODEGEN_TEST(xVDIV.SS(xmm0, xmm1, xmm2), "c5 f2 5e c2");
|
||||
CODEGEN_TEST(xVDIV.SD(xmm0, xmm1, xmm2), "c5 f3 5e c2");
|
||||
|
||||
// Don't need to test all variants, since they just change the condition immediate.
|
||||
CODEGEN_TEST(xVCMP.EQ.PS(xmm0, xmm1, xmm2), "c5 f0 c2 c2 00");
|
||||
CODEGEN_TEST(xVCMP.EQ.PD(xmm0, xmm1, xmm2), "c5 f1 c2 c2 00");
|
||||
CODEGEN_TEST(xVCMP.EQ.SS(xmm0, xmm1, xmm2), "c5 f2 c2 c2 00");
|
||||
CODEGEN_TEST(xVCMP.EQ.SD(xmm0, xmm1, xmm2), "c5 f3 c2 c2 00");
|
||||
CODEGEN_TEST(xVCMP.LE.PS(xmm0, xmm1, xmm2), "c5 f0 c2 c2 02");
|
||||
CODEGEN_TEST(xVCMP.LE.PD(xmm0, xmm1, xmm2), "c5 f1 c2 c2 02");
|
||||
CODEGEN_TEST(xVCMP.LE.SS(xmm0, xmm1, xmm2), "c5 f2 c2 c2 02");
|
||||
CODEGEN_TEST(xVCMP.LE.SD(xmm0, xmm1, xmm2), "c5 f3 c2 c2 02");
|
||||
|
||||
CODEGEN_TEST(xVPCMP.EQB(xmm0, xmm1, xmm2), "c5 f1 74 c2");
|
||||
CODEGEN_TEST(xVPCMP.EQW(xmm0, xmm1, xmm2), "c5 f1 75 c2");
|
||||
CODEGEN_TEST(xVPCMP.EQD(xmm0, xmm1, xmm2), "c5 f1 76 c2");
|
||||
CODEGEN_TEST(xVPCMP.GTB(xmm0, xmm1, xmm2), "c5 f1 64 c2");
|
||||
CODEGEN_TEST(xVPCMP.GTW(xmm0, xmm1, xmm2), "c5 f1 65 c2");
|
||||
CODEGEN_TEST(xVPCMP.GTD(xmm0, xmm1, xmm2), "c5 f1 66 c2");
|
||||
|
||||
CODEGEN_TEST(xVPAND(xmm0, xmm1, xmm2), "c5 f1 db c2");
|
||||
CODEGEN_TEST(xVPANDN(xmm0, xmm1, xmm2), "c5 f1 df c2");
|
||||
CODEGEN_TEST(xVPOR(xmm0, xmm1, xmm2), "c5 f1 eb c2");
|
||||
CODEGEN_TEST(xVPXOR(xmm0, xmm1, xmm2), "c5 f1 ef c2");
|
||||
|
||||
CODEGEN_TEST(xVMOVMSKPS(eax, xmm1), "c5 f8 50 c1");
|
||||
CODEGEN_TEST(xVMOVMSKPD(eax, xmm1), "c5 f9 50 c1");
|
||||
}
|
||||
|
||||
TEST(CodegenTests, AVX256Test)
|
||||
{
|
||||
CODEGEN_TEST(xVMOVAPS(ymm0, ymm1), "c5 fc 28 c1");
|
||||
CODEGEN_TEST(xVMOVAPS(ymm0, ptr32[rdi]), "c5 fc 28 07");
|
||||
CODEGEN_TEST(xVMOVAPS(ptr32[rdi], ymm0), "c5 fc 29 07");
|
||||
CODEGEN_TEST(xVMOVUPS(ymm0, ptr32[rdi]), "c5 fc 10 07");
|
||||
CODEGEN_TEST(xVMOVUPS(ptr32[rdi], ymm0), "c5 fc 11 07");
|
||||
|
||||
CODEGEN_TEST(xVZEROUPPER(), "c5 f8 77");
|
||||
|
||||
CODEGEN_TEST(xVADD.PS(ymm0, ymm1, ymm2), "c5 f4 58 c2");
|
||||
CODEGEN_TEST(xVADD.PD(ymm0, ymm1, ymm2), "c5 f5 58 c2");
|
||||
CODEGEN_TEST(xVSUB.PS(ymm0, ymm1, ymm2), "c5 f4 5c c2");
|
||||
CODEGEN_TEST(xVSUB.PD(ymm0, ymm1, ymm2), "c5 f5 5c c2");
|
||||
CODEGEN_TEST(xVMUL.PS(ymm0, ymm1, ymm2), "c5 f4 59 c2");
|
||||
CODEGEN_TEST(xVMUL.PD(ymm0, ymm1, ymm2), "c5 f5 59 c2");
|
||||
CODEGEN_TEST(xVDIV.PS(ymm0, ymm1, ymm2), "c5 f4 5e c2");
|
||||
CODEGEN_TEST(xVDIV.PD(ymm0, ymm1, ymm2), "c5 f5 5e c2");
|
||||
|
||||
CODEGEN_TEST(xVCMP.EQ.PS(ymm0, ymm1, ymm2), "c5 f4 c2 c2 00");
|
||||
CODEGEN_TEST(xVCMP.EQ.PD(ymm0, ymm1, ymm2), "c5 f5 c2 c2 00");
|
||||
CODEGEN_TEST(xVCMP.LE.PS(ymm0, ymm1, ymm2), "c5 f4 c2 c2 02");
|
||||
CODEGEN_TEST(xVCMP.LE.PD(ymm0, ymm1, ymm2), "c5 f5 c2 c2 02");
|
||||
|
||||
CODEGEN_TEST(xVPCMP.EQB(ymm0, ymm1, ymm2), "c5 f5 74 c2");
|
||||
CODEGEN_TEST(xVPCMP.EQW(ymm0, ymm1, ymm2), "c5 f5 75 c2");
|
||||
CODEGEN_TEST(xVPCMP.EQD(ymm0, ymm1, ymm2), "c5 f5 76 c2");
|
||||
CODEGEN_TEST(xVPCMP.GTB(ymm0, ymm1, ymm2), "c5 f5 64 c2");
|
||||
CODEGEN_TEST(xVPCMP.GTW(ymm0, ymm1, ymm2), "c5 f5 65 c2");
|
||||
CODEGEN_TEST(xVPCMP.GTD(ymm0, ymm1, ymm2), "c5 f5 66 c2");
|
||||
|
||||
CODEGEN_TEST(xVPAND(ymm0, ymm1, ymm2), "c5 f5 db c2");
|
||||
CODEGEN_TEST(xVPANDN(ymm0, ymm1, ymm2), "c5 f5 df c2");
|
||||
CODEGEN_TEST(xVPOR(ymm0, ymm1, ymm2), "c5 f5 eb c2");
|
||||
CODEGEN_TEST(xVPXOR(ymm0, ymm1, ymm2), "c5 f5 ef c2");
|
||||
|
||||
CODEGEN_TEST(xVMOVMSKPS(eax, ymm1), "c5 fc 50 c1");
|
||||
CODEGEN_TEST(xVMOVMSKPD(eax, ymm1), "c5 fd 50 c1");
|
||||
}
|
||||
|
||||
TEST(CodegenTests, Extended8BitTest)
|
||||
{
|
||||
CODEGEN_TEST(xSETL(al), "0f 9c c0");
|
||||
CODEGEN_TEST(xSETL(cl), "0f 9c c1");
|
||||
CODEGEN_TEST(xSETL(dl), "0f 9c c2");
|
||||
CODEGEN_TEST(xSETL(bl), "0f 9c c3");
|
||||
CODEGEN_TEST(xSETL(spl), "40 0f 9c c4");
|
||||
CODEGEN_TEST(xSETL(bpl), "40 0f 9c c5");
|
||||
CODEGEN_TEST(xSETL(sil), "40 0f 9c c6");
|
||||
CODEGEN_TEST(xSETL(dil), "40 0f 9c c7");
|
||||
CODEGEN_TEST(xSETL(r8b), "41 0f 9c c0");
|
||||
CODEGEN_TEST(xSETL(r9b), "41 0f 9c c1");
|
||||
CODEGEN_TEST(xSETL(r10b), "41 0f 9c c2");
|
||||
CODEGEN_TEST(xSETL(r11b), "41 0f 9c c3");
|
||||
CODEGEN_TEST(xSETL(r12b), "41 0f 9c c4");
|
||||
CODEGEN_TEST(xSETL(r13b), "41 0f 9c c5");
|
||||
CODEGEN_TEST(xSETL(r14b), "41 0f 9c c6");
|
||||
CODEGEN_TEST(xSETL(r15b), "41 0f 9c c7");
|
||||
}
|
||||
Reference in New Issue
Block a user