Files
libultraship/tests/path_diskfile_tests.cpp
a293e22ca0 Add Javadoc comments to all Ship directory headers (#1077)
* Add Javadoc comments to CoreAudioAudioPlayer.h and SoundMatrixDecoder.h

Add documentation comments to all undocumented classes, structs, methods,
and important member variables in:
- CoreAudioAudioPlayer.h: class, constructor, Buffered, DoInit, DoClose,
  DoPlay, CoreAudioRenderCallback, and ring buffer member variables
- SoundMatrixDecoder.h: BiquadCascade, FilterCoefficients, AllPassChain,
  CircularDelay structs, and DesignLowPass, DesignHighPass, ProcessFilter,
  PrepareAllPass, ProcessAllPass, ProcessDelay, Saturate methods

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com>

* Add Javadoc-style comments to controller mapping header files

Add /** ... */ documentation with @brief, @param, and @return tags to all
classes, structs, enums, constructors, and public/protected methods in:

- ControllerMapping.h
- ControllerInputMapping.h
- ControllerAxisDirectionMapping.h
- ControllerButtonMapping.h
- ControllerGyroMapping.h
- ControllerRumbleMapping.h
- ControllerLEDMapping.h
- ControllerDefaultMappings.h

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com>

* Add Javadoc comments to keyboard, mouse, SDL, and factory mapping headers

Add /** ... */ documentation with @brief, @param, and @return tags to all
classes, structs, enums, constructors, and public/protected methods across
26 controller mapping header files. Existing Javadoc comments (e.g. in
KeyboardScancodes.h) are left untouched.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com>

* Add Javadoc-style comments to physical device, control device, resource, and factory headers

Add /** ... */ documentation with @brief, @param, @return tags to all
classes, structs, enums, public/protected methods, and constructors in:

- ConnectedPhysicalDeviceManager.h
- GlobalSDLDeviceSettings.h
- PhysicalDeviceType.h
- SDLAddRemoveDeviceEventHandler.h
- ResourceFactoryBinary.h
- ResourceFactoryXML.h
- Blob.h, Json.h, Shader.h
- BlobFactory.h, JsonFactory.h, ShaderFactory.h
- FolderArchive.h

Files that were already fully documented (ControlDevice.h, ResourceFactory.h,
ResourceType.h, File.h) are left unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com>

* docs: add Javadoc-style comments to utility header files

Add /** ... */ documentation with @brief, @param, and @return tags to:
- Directory.h, DiskFile.h, FileHelper.h, Path.h, PathHelper.h
- glob.h, macUtils.h, stox.h

Files already documented (color.h, StrHash64.h, endianness.h) are left unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com>

* Add Javadoc-style comments to window, GUI, and resource headers

Add /** ... */ documentation with @brief, @param, and @return tags to:
- FileDropMgr.h: class, typedef, and all public methods
- MouseStateManager.h: class and all public/protected methods
- EventDebuggerWindow.h: class and lifecycle overrides
- Fonts.h: file-level documentation for embedded font data
- IconsFontAwesome4.h: file-level documentation for icon constants
- StatsWindow.h: destructor (class and methods already documented)
- Font.h: class, resource type macro, public methods, and data members
- FontFactory.h: class and ReadResource method
- GuiTexture.h: struct, class, resource type macro, methods, and members
- GuiTextureFactory.h: class and ReadResource method

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com>

* Add Javadoc-style comments to public headers

Add /** ... */ documentation comments with @brief, @param, and @return
tags to all classes, structs, enums, free functions, macros, and public
methods in the following header files:

- include/ship/Api.h
- include/ship/events/CoreEvents.h
- include/ship/port/mobile/MobileImpl.h
- include/ship/scripting/LibraryLoader.h
- include/ship/security/Keystore.h

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com>

* docs: add missing Javadoc comments to Controller.h and InputEditorWindow.h

Add Javadoc-style comments to all undocumented methods:

- Controller.h: Add doc for ~Controller() destructor
- InputEditorWindow.h: Add docs for ~InputEditorWindow() destructor and
  all 24 private methods (Draw*, Update*, GetButtonColors*, OffsetMappingPopup)

FileHelper.h and DiskFile.h already have complete Javadoc coverage from
prior commits on this branch.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com>

* style: apply clang-format-14 to fix formatting violations

Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com>

* fix: rename WheelDirections x/y to X/Y per CamelCase naming convention

Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com>

* docs: address review comments - fix inaccurate Doxygen comments in DiskFile, Shader, LibraryLoader, stox, Path, PathHelper

Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com>

* fix: auto-enable DISABLE_SCRIPTING for iOS to fix build-ios CI failure

Agent-Logs-Url: https://github.com/Kenix3/libultraship/sessions/e409640e-005b-4dce-a9cd-db23e80d5385

Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com>

* Flip tcc scripting to opt-in (#1084)

* Flip tcc scripting to opt-in

Per #1074

* Adhere to lgpl
Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com>

* docs: update README dependency list with tree structure and correct links (#1088)

Agent-Logs-Url: https://github.com/Kenix3/libultraship/sessions/dae72d20-385d-41c2-bba9-9229493d9e17

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com>

* fix: remove stale DISABLE_SCRIPTING iOS override (superseded by ENABLE_SCRIPTING opt-in from #1084)

Agent-Logs-Url: https://github.com/Kenix3/libultraship/sessions/e409640e-005b-4dce-a9cd-db23e80d5385

Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com>

* no changes yet

Agent-Logs-Url: https://github.com/Kenix3/libultraship/sessions/62cd9f10-ed50-45ab-b3fb-19f689b83025

Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com>

* fix: WriteAllBytes always creates parent dirs; GetFileNameExtension throws explicitly; fix Shader/MobileImpl docs; fix clang-tidy CI

Agent-Logs-Url: https://github.com/Kenix3/libultraship/sessions/62cd9f10-ed50-45ab-b3fb-19f689b83025

Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com>

* fix: revert MobileImpl.h to origin/main — removes it from PR diff, fixing clang-tidy CI

Agent-Logs-Url: https://github.com/Kenix3/libultraship/sessions/05a2642f-75da-4384-a7c5-4cc249a03f51

Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com>

* refactor: move library file writing from ScriptLoader into LibraryLoader; fix Init/Unload docstrings

Agent-Logs-Url: https://github.com/Kenix3/libultraship/sessions/8e68fb32-b97d-4c50-b75d-7268d54c7448

Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com>

* fix: add missing <cstdint> include to LibraryLoader.h for uint8_t

Agent-Logs-Url: https://github.com/Kenix3/libultraship/sessions/e9c0cf04-6e25-4714-9132-3556d3d93da0

Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Kenix3 <18299654+Kenix3@users.noreply.github.com>
Co-authored-by: Jeod <47716344+JeodC@users.noreply.github.com>
2026-04-29 06:49:11 -04:00

253 lines
8.3 KiB
C++

#include <gtest/gtest.h>
#include <filesystem>
#include <fstream>
#include <string>
#include <vector>
#include "ship/utils/filesystemtools/Path.h"
#include "ship/utils/filesystemtools/DiskFile.h"
#include "ship/utils/filesystemtools/Directory.h"
namespace fs = std::filesystem;
// ============================================================
// Path::GetFileName
// ============================================================
TEST(PathClass, GetFileNameBasicPath) {
EXPECT_EQ(Path::GetFileName("/some/dir/file.txt"), "file.txt");
}
TEST(PathClass, GetFileNameNoDirectory) {
EXPECT_EQ(Path::GetFileName("file.txt"), "file.txt");
}
TEST(PathClass, GetFileNameNoExtension) {
EXPECT_EQ(Path::GetFileName("/dir/filename"), "filename");
}
TEST(PathClass, GetFileNameTrailingSlash) {
// A trailing slash means the filename is empty
EXPECT_EQ(Path::GetFileName("/dir/"), "");
}
// ============================================================
// Path::GetFileNameWithoutExtension
// ============================================================
TEST(PathClass, GetStemBasic) {
EXPECT_EQ(Path::GetFileNameWithoutExtension("/dir/file.txt"), "file");
}
TEST(PathClass, GetStemMultipleDots) {
EXPECT_EQ(Path::GetFileNameWithoutExtension("/dir/archive.tar.gz"), "archive.tar");
}
TEST(PathClass, GetStemNoExtension) {
EXPECT_EQ(Path::GetFileNameWithoutExtension("/dir/filename"), "filename");
}
// ============================================================
// Path::GetFileNameExtension
// ============================================================
TEST(PathClass, GetExtensionBasic) {
EXPECT_EQ(Path::GetFileNameExtension("file.txt"), ".txt");
}
TEST(PathClass, GetExtensionMultipleDots) {
// Returns from the last dot to end
EXPECT_EQ(Path::GetFileNameExtension("archive.tar.gz"), ".gz");
}
TEST(PathClass, GetExtensionBin) {
EXPECT_EQ(Path::GetFileNameExtension("link.bin"), ".bin");
}
TEST(PathClass, GetExtensionNoDotThrows) {
EXPECT_THROW(Path::GetFileNameExtension("nodotfile"), std::out_of_range);
}
// ============================================================
// Path::GetPath (removes filename segments that contain a dot)
// ============================================================
TEST(PathClass, GetPathFiltersOutFileSegment) {
fs::path result = Path::GetPath("textures/player/link.png");
EXPECT_EQ(result, fs::path("textures/player"));
}
TEST(PathClass, GetPathPureDirectoryUnchanged) {
fs::path result = Path::GetPath("assets/textures");
EXPECT_EQ(result, fs::path("assets/textures"));
}
TEST(PathClass, GetPathSingleFileReturnsEmpty) {
fs::path result = Path::GetPath("file.txt");
EXPECT_TRUE(result.empty());
}
TEST(PathClass, GetPathMultiLevelWithFile) {
fs::path result = Path::GetPath("a/b/c/file.bin");
EXPECT_EQ(result, fs::path("a/b/c"));
}
// ============================================================
// Path::GetDirectoryName
// ============================================================
TEST(PathClass, GetDirectoryNameBasic) {
EXPECT_EQ(Path::GetDirectoryName("/some/dir/file.txt"), fs::path("/some/dir"));
}
TEST(PathClass, GetDirectoryNameRoot) {
EXPECT_EQ(Path::GetDirectoryName("/file.txt"), fs::path("/"));
}
TEST(PathClass, GetDirectoryNameRelative) {
EXPECT_EQ(Path::GetDirectoryName("dir/file.txt"), fs::path("dir"));
}
// ============================================================
// DiskFile test fixture — temp directory
// ============================================================
class DiskFileTest : public ::testing::Test {
protected:
fs::path mTestDir;
fs::path mTestFile;
void SetUp() override {
mTestDir = fs::temp_directory_path() / "lus_diskfile_test";
fs::remove_all(mTestDir);
Directory::MakeDirectory(mTestDir.string());
mTestFile = mTestDir / "test.bin";
}
void TearDown() override {
fs::remove_all(mTestDir);
}
};
// ============================================================
// DiskFile::Exists
// ============================================================
TEST_F(DiskFileTest, ExistsReturnsFalseForMissing) {
EXPECT_FALSE(DiskFile::Exists(mTestDir / "missing.bin"));
}
TEST_F(DiskFileTest, ExistsReturnsTrueAfterWrite) {
std::vector<uint8_t> data = { 1, 2, 3 };
DiskFile::WriteAllBytes(mTestFile, data);
EXPECT_TRUE(DiskFile::Exists(mTestFile));
}
// ============================================================
// DiskFile::WriteAllBytes / ReadAllBytes (uint8 vector)
// ============================================================
TEST_F(DiskFileTest, WriteReadAllBytesUint8RoundTrip) {
std::vector<uint8_t> data = { 0xDE, 0xAD, 0xBE, 0xEF };
DiskFile::WriteAllBytes(mTestFile, data);
auto read = DiskFile::ReadAllBytes(mTestFile);
EXPECT_EQ(read, data);
}
TEST_F(DiskFileTest, ReadAllBytesEmptyFile) {
// Write empty file
{ std::ofstream f(mTestFile, std::ios::binary); }
auto data = DiskFile::ReadAllBytes(mTestFile);
EXPECT_TRUE(data.empty());
}
TEST_F(DiskFileTest, ReadAllBytesMissingFileReturnsEmpty) {
auto data = DiskFile::ReadAllBytes(mTestDir / "nonexistent.bin");
EXPECT_TRUE(data.empty());
}
// ============================================================
// DiskFile::WriteAllBytes / ReadAllBytes (char vector overload)
// ============================================================
TEST_F(DiskFileTest, WriteReadAllBytesCharVectorRoundTrip) {
std::vector<char> data = { 'h', 'e', 'l', 'l', 'o' };
DiskFile::WriteAllBytes(mTestFile.string(), data);
auto read = DiskFile::ReadAllBytes(mTestFile);
ASSERT_EQ(read.size(), data.size());
for (size_t i = 0; i < data.size(); i++) {
EXPECT_EQ(static_cast<char>(read[i]), data[i]);
}
}
// ============================================================
// DiskFile::WriteAllBytes raw pointer overload
// ============================================================
TEST_F(DiskFileTest, WriteReadRawPointerRoundTrip) {
const char payload[] = "rawdata";
DiskFile::WriteAllBytes(mTestFile.string(), payload, static_cast<int>(sizeof(payload) - 1));
auto read = DiskFile::ReadAllBytes(mTestFile);
ASSERT_EQ(read.size(), sizeof(payload) - 1);
EXPECT_EQ(std::string(reinterpret_cast<char*>(read.data()), read.size()), "rawdata");
}
TEST_F(DiskFileTest, WriteAllBytesUint8CreatesParentIfMissing) {
fs::path nested = mTestDir / "sub" / "data.bin";
std::vector<uint8_t> data = { 0x01, 0x02 };
DiskFile::WriteAllBytes(nested, data);
EXPECT_TRUE(DiskFile::Exists(nested));
}
TEST_F(DiskFileTest, WriteAllBytesCharVecCreatesParentIfMissing) {
fs::path nested = mTestDir / "sub2" / "data.bin";
std::vector<char> data = { 'a', 'b' };
DiskFile::WriteAllBytes(nested.string(), data);
EXPECT_TRUE(DiskFile::Exists(nested));
}
TEST_F(DiskFileTest, WriteAllBytesRawPtrCreatesParentIfMissing) {
fs::path nested = mTestDir / "sub3" / "data.bin";
const char payload[] = "hi";
DiskFile::WriteAllBytes(nested.string(), payload, static_cast<int>(sizeof(payload) - 1));
EXPECT_TRUE(DiskFile::Exists(nested));
}
// ============================================================
// DiskFile::WriteAllText / ReadAllText
// ============================================================
TEST_F(DiskFileTest, WriteReadAllTextRoundTrip) {
std::string content = "Hello, World!\nLine 2\n";
DiskFile::WriteAllText(mTestFile, content);
std::string result = DiskFile::ReadAllText(mTestFile);
EXPECT_EQ(result, content);
}
TEST_F(DiskFileTest, WriteAllTextCreatesParentIfMissing) {
fs::path nested = mTestDir / "sub" / "data.txt";
DiskFile::WriteAllText(nested, "test");
EXPECT_TRUE(DiskFile::Exists(nested));
}
// ============================================================
// DiskFile::ReadAllLines
// ============================================================
TEST_F(DiskFileTest, ReadAllLinesProducesCorrectTokens) {
std::string content = "line1\nline2\nline3\n";
DiskFile::WriteAllText(mTestFile, content);
auto lines = DiskFile::ReadAllLines(mTestFile);
ASSERT_GE(lines.size(), 3u);
EXPECT_EQ(lines[0], "line1");
EXPECT_EQ(lines[1], "line2");
EXPECT_EQ(lines[2], "line3");
}
TEST_F(DiskFileTest, ReadAllLinesSingleLine) {
DiskFile::WriteAllText(mTestFile, "only");
auto lines = DiskFile::ReadAllLines(mTestFile);
ASSERT_GE(lines.size(), 1u);
EXPECT_EQ(lines[0], "only");
}