chore(file): add tests for SFile functions

This commit is contained in:
Adam Heinermann 2026-01-15 19:24:18 -08:00 committed by fallenoak
parent 1e86f98691
commit 40d58978e1
20 changed files with 567 additions and 18 deletions

View file

@ -10,10 +10,12 @@
#endif
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
#define ERROR_SUCCESS 0x0
#define ERROR_INVALID_HANDLE 0x6
#define ERROR_NOT_ENOUGH_MEMORY 0x8
#define ERROR_INVALID_PARAMETER 0x57
#define ERROR_SUCCESS 0
#define ERROR_FILE_NOT_FOUND 2
#define ERROR_INVALID_HANDLE 6
#define ERROR_NOT_ENOUGH_MEMORY 8
#define ERROR_HANDLE_EOF 38
#define ERROR_INVALID_PARAMETER 87
#endif
[[noreturn]] void STORMCDECL SErrDisplayAppFatal(const char* format, ...);

View file

@ -12,18 +12,78 @@
DECLARE_STORM_HANDLE(HSARCHIVE);
DECLARE_STORM_HANDLE(HSFILE);
int32_t STORMAPI SFileOpenArchive(const char* archivename, int32_t priority, uint32_t flags, HSARCHIVE* handle);
#define SFILE_ARCHIVE_READ_FROM_CD_ONLY 0x000001
#define SFILE_ARCHIVE_ENABLE_OVERLAPPED 0x000002
#define SFILE_ARCHIVE_DONT_CHECKDISK 0x000004
#define SFILE_ARCHIVE_DONT_SEARCH 0x000008
#define SFILE_ARCHIVE_ARC4_DECRYPT 0x000010
#define SFILE_ARCHIVE_DECRYPTION_TYPES 0x000010
#define SFILE_ARCHIVE_WRITE_PERMISSION 0x000010
#define SFILE_ARCHIVE_OPEN_LAST_ARCHIVE 0x000020
#define SFILE_ARCHIVE_LOAD_MD5_VALUES 0x000040
#define SFILE_ARCHIVE_LOAD_CRC_VALUES 0x000080
#define SFILE_ARCHIVE_LOAD_TIMESTAMPS 0x000100
#define SFILE_ARCHIVE_CHECK_MD5_VALUES 0x000200
#define SFILE_ARCHIVE_USE_NEW_BLOCK_HASH_FORMAT 0x000400
#define SFILE_ARCHIVE_INIT_TABLE_ON_OPEN 0x000800
#define SFILE_ARCHIVE_LOAD_DELTA_VALUES 0x001000
#define SFILE_ARCHIVE_LOAD_DELTA_AS_RAW 0x002000
#define SFILE_ARCHIVE_DONT_TRUNCATE 0x004000
#define SFILE_ARCHIVE_DISK_DELETE_CAN_FAIL 0x010000
#define SFILE_ARCHIVE_SC1161_PERMISSIVE 0x020000
#define SFILE_OPENFLAG_CHECKDISK 1
#define SFILE_OPENFLAG_CHECKDISK_NOPATH 2
#define SFILE_OPENFLAG_NATIVEHANDLE 4 // made up
#define SFILE_OPENFLAG_PERM_SHARED_WRITE 0x8000
#define SFILE_OPENFLAG_PRESERVE_PATH_SEPARATORS 0x10000
#define SFILE_BEGIN 0
#define SFILE_CURRENT 1
#define SFILE_END 2
/* // Leaving as documentation
#define SFILE_AUTH_UNABLETOAUTHENTICATE 0
#define SFILE_AUTH_NOSIGNATURE 1
#define SFILE_AUTH_BADSIGNATURE 2
#define SFILE_AUTH_UNKNOWNSIGNATURE 3
#define SFILE_AUTH_FIRSTAUTHENTIC 5
#define SFILE_AUTH_AUTHENTICBLIZZARD 5
#define SFILE_DIRECT_ENABLE_RELATIVE 1
#define SFILE_DIRECT_ENABLE_NOPATH 2
#define SFILE_PLATFORM_ANY 0
#define SFILE_PLATFORM_WIN32 1
#define SFILE_PLATFORM_MAC 2
enum SARCHIVE_TYPE {
SARCHIVE_MPQ,
SARCHIVE_ZIP,
};
enum SFILE_TYPE {
SFILE_PLAIN,
SFILE_COMPRESSED,
SFILE_PAQ,
SFILE_OLD_SFILE,
SFILE_ZIP_FILE,
};
*/
int32_t STORMAPI SFileCloseArchive(HSARCHIVE handle);
int32_t STORMAPI SFileCloseFile(HSFILE handle);
uint32_t STORMAPI SFileGetFileSize(HSFILE handle, uint32_t* filesizehigh = nullptr);
int32_t STORMAPI SFileOpenArchive(const char* archivename, int32_t priority, uint32_t flags, HSARCHIVE* handle);
int32_t STORMAPI SFileOpenFileEx(HSARCHIVE archivehandle, const char* filename, uint32_t flags, HSFILE* handle);
int32_t STORMAPI SFileReadFile(HSFILE handle, void* buffer, uint32_t bytestoread, uint32_t* bytesread, LPOVERLAPPED overlapped);
uint32_t STORMAPI SFileGetFileSize(HSFILE handle, uint32_t* filesizehigh);
int32_t STORMAPI SFileReadFile(HSFILE handle, void* buffer, uint32_t bytestoread, uint32_t* bytesread = nullptr, LPOVERLAPPED overlapped = nullptr);
uint32_t STORMAPI SFileSetFilePointer(HSFILE handle, int32_t distancetomove, int32_t* distancetomovehigh, uint32_t movemethod);
int32_t STORMAPI SFileCloseFile(HSFILE handle);
#endif

View file

@ -6,6 +6,8 @@ if(WHOA_TEST_STORMDLL)
Error.cpp
Event.cpp
EventTest.cpp
File.cpp
FileTest.cpp
Memory.cpp
Region.cpp
String.cpp
@ -24,6 +26,8 @@ else()
)
endif()
file(GLOB TEST_FILES "fixture/*")
if(WHOA_SYSTEM_MAC)
set_source_files_properties(${TEST_SOURCES}
PROPERTIES COMPILE_FLAGS "-x objective-c++"
@ -54,6 +58,14 @@ target_include_directories(StormTest
${PROJECT_SOURCE_DIR}
)
file(GLOB TEST_FILES "fixture/*")
add_custom_target(copy_test_files ALL
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${TEST_FILES}
$<TARGET_FILE_DIR:StormTest>
)
# Debug build options
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
# GCC debug build options

401
test/File.cpp Normal file
View file

@ -0,0 +1,401 @@
#include "FileTest.hpp"
// most of these only pass against storm.dll for now
#if defined(WHOA_TEST_STORMDLL)
TEST_CASE("SFileCloseArchive", "[file]") {
HSARCHIVE archive = nullptr;
SECTION("closes an archive") {
SFileOpenArchive("wowtest1.mpq", 0, 0, &archive);
REQUIRE(archive != nullptr);
HSFILE file;
CHECK(SFileOpenFileEx(nullptr, "test.txt", 0, &file));
CHECK(SFileCloseFile(file));
CHECK(SFileCloseArchive(archive) == 1);
CHECK_FALSE(SFileOpenFileEx(nullptr, "test.txt", 0, &file));
}
// TODO determine how to test this
// SECTION("doesn't delete if there is more than one reference") {}
}
TEST_CASE("SFileCloseFile", "[file]") {
HSFILE file = nullptr;
SECTION("closes a MPQ file") {
file = ReadTestFileFromMpq();
CHECK(SFileCloseFile(file) == 1);
}
SECTION("closes a filesystem file") {
file = ReadTestFileFromDisk();
CHECK(SFileCloseFile(file) == 1);
}
// TODO determine how to test this
// SECTION("doesn't delete if there is more than one reference") {}
}
TEST_CASE("SFileGetFileSize", "[file]") {
HSARCHIVE archive;
HSFILE file;
SECTION("retrieves MPQ file size") {
SFileOpenArchive("wowtest1.mpq", 0, 0, &archive);
REQUIRE(SFileOpenFileEx(archive, "test2.txt", 0, &file));
CHECK(SFileGetFileSize(file) == 13);
REQUIRE(SFileOpenFileEx(archive, "empty.txt", 0, &file));
CHECK(SFileGetFileSize(file) == 0);
uint32_t filesizehigh = 1234;
REQUIRE(SFileOpenFileEx(archive, "test.txt", 0, &file));
CHECK(SFileGetFileSize(file, &filesizehigh) == 6);
CHECK(filesizehigh == 0);
}
SECTION("retrieves filesystem file size") {
REQUIRE(SFileOpenFileEx(nullptr, "empty_diskonly.txt", SFILE_OPENFLAG_CHECKDISK, &file));
CHECK(SFileGetFileSize(file) == 0);
uint32_t filesizehigh = 1234;
REQUIRE(SFileOpenFileEx(nullptr, "test_diskonly.txt", SFILE_OPENFLAG_CHECKDISK, &file));
CHECK(SFileGetFileSize(file, &filesizehigh) == 6);
CHECK(filesizehigh == 0);
}
}
TEST_CASE("SFileOpenArchive", "[file]") {
HSARCHIVE mpq = nullptr;
SErrSetLastError(ERROR_SUCCESS);
SECTION("opens a MPQ archive") {
CHECK(SFileOpenArchive("wowtest1.mpq", 0, 0, &mpq) == 1);
CHECK(mpq != nullptr);
}
// TODO determine how to test this (something about CD ROM drives)
// SECTION("fails if drive is inaccessible") {}
SECTION("fails if archive file is nonexistent") {
mpq = reinterpret_cast<HSARCHIVE>(1234);
CHECK_FALSE(SFileOpenArchive("nice_try.mpq", 0, 0, &mpq));
CHECK(mpq == nullptr);
CHECK(SErrGetLastError() == ERROR_SUCCESS);
}
SECTION("fails if archive file is too small") {
mpq = reinterpret_cast<HSARCHIVE>(1234);
CHECK_FALSE(SFileOpenArchive("bad_toosmall.mpq", 0, 0, &mpq));
CHECK(mpq == nullptr);
CHECK(SErrGetLastError() == STORM_ERROR_NOT_ARCHIVE);
}
SECTION("fails if using a directory") {
mpq = reinterpret_cast<HSARCHIVE>(1234);
CHECK_FALSE(SFileOpenArchive("directorytest", 0, 0, &mpq));
CHECK(mpq == nullptr);
CHECK(SErrGetLastError() == ERROR_SUCCESS);
}
SECTION("fails if archive header magic doesn't match") {
mpq = reinterpret_cast<HSARCHIVE>(1234);
CHECK_FALSE(SFileOpenArchive("bad_nomagic.mpq", 0, 0, &mpq));
CHECK(mpq == nullptr);
CHECK(SErrGetLastError() == STORM_ERROR_NOT_ARCHIVE);
}
SECTION("fails if archive header size doesn't match") {
mpq = reinterpret_cast<HSARCHIVE>(1234);
CHECK_FALSE(SFileOpenArchive("bad_headertoosmall.mpq", 0, 0, &mpq));
CHECK(mpq == nullptr);
CHECK(SErrGetLastError() == STORM_ERROR_NOT_ARCHIVE);
}
}
TEST_CASE("SFileOpenFileEx", "[file]") {
SECTION("shared testcases") {
OpenFileTestCase testcase = GENERATE(OpenFromDiskCase, OpenFromMPQCase);
INFO(testcase.info);
HSARCHIVE archive = testcase.OpenArchiveFn();
HSFILE file = nullptr;
SECTION("opens a file") {
CHECK(SFileOpenFileEx(archive, "test.txt", testcase.flags, &file) == 1);
CHECK(file != nullptr);
CHECK(file != reinterpret_cast<HSFILE>(1234));
}
SECTION("fails if file not found") {
SErrSetLastError(ERROR_SUCCESS);
file = reinterpret_cast<HSFILE>(1234);
CHECK_FALSE(SFileOpenFileEx(archive, "nice try buddy but your file is in another castle", testcase.flags, &file));
CHECK(file == nullptr);
CHECK(SErrGetLastError() == ERROR_FILE_NOT_FOUND);
}
}
SECTION("fails when trying to open a directory") {
SErrSetLastError(ERROR_SUCCESS);
HSFILE file = reinterpret_cast<HSFILE>(1234);
CHECK_FALSE(SFileOpenFileEx(nullptr, "directorytest", SFILE_OPENFLAG_CHECKDISK, &file));
CHECK(file == nullptr);
CHECK(SErrGetLastError() == ERROR_FILE_NOT_FOUND);
}
SECTION("mpq testcases") {
HSARCHIVE mpq1, mpq2, mpq3;
HSFILE file;
SECTION("opens the highest priority file from all MPQs") {
SFileOpenArchive("wowtest1.mpq", 100, 0, &mpq1);
SFileOpenArchive("wowtest2.mpq", 500, 0, &mpq2);
SFileOpenArchive("wowtest3.mpq", 400, 0, &mpq3);
CHECK(SFileOpenFileEx(nullptr, "test.txt", 0, &file) == 1);
char result[16] = {};
SFileReadFile(file, result, sizeof(result));
CHECK(std::string(result) == "skibbidy");
}
SECTION("opens the most recently opened file from same priority MPQs") {
SFileOpenArchive("wowtest1.mpq", 100, 0, &mpq1);
SFileOpenArchive("wowtest2.mpq", 500, 0, &mpq2);
SFileOpenArchive("wowtest3.mpq", 500, 0, &mpq3);
CHECK(SFileOpenFileEx(nullptr, "test.txt", 0, &file) == 1);
char result[16] = {};
SFileReadFile(file, result, sizeof(result));
CHECK(std::string(result) == "rizz");
}
// TODO implement after adding SFileSetLocale
// SECTION("opens the file for the currently selected locale") {}
SECTION("fails if file not found in target MPQ") {
SFileOpenArchive("wowtest1.mpq", 100, 0, &mpq1);
SFileOpenArchive("wowtest2.mpq", 500, 0, &mpq2);
SFileOpenArchive("wowtest3.mpq", 400, 0, &mpq3);
CHECK(SFileOpenFileEx(nullptr, "test2.txt", 0, &file) == 1);
SFileCloseFile(file);
SErrSetLastError(ERROR_SUCCESS);
CHECK_FALSE(SFileOpenFileEx(mpq3, "test2.txt", 0, &file));
CHECK(SErrGetLastError() == ERROR_FILE_NOT_FOUND);
}
SECTION("fails if file not found in any MPQ") {
SFileOpenArchive("wowtest1.mpq", 100, 0, &mpq1);
SFileOpenArchive("wowtest2.mpq", 500, 0, &mpq2);
SFileOpenArchive("wowtest3.mpq", 400, 0, &mpq3);
SErrSetLastError(ERROR_SUCCESS);
CHECK_FALSE(SFileOpenFileEx(nullptr, "yep not here", 0, &file));
CHECK(SErrGetLastError() == ERROR_FILE_NOT_FOUND);
}
SECTION("can open attributes file") {
SFileOpenArchive("wowtest1.mpq", 100, 0, &mpq1);
CHECK(SFileOpenFileEx(nullptr, "(attributes)", 0, &file) == 1);
}
SECTION("can open listfile") {
SFileOpenArchive("wowtest1.mpq", 100, 0, &mpq1);
CHECK(SFileOpenFileEx(nullptr, "(listfile)", 0, &file) == 1);
}
}
}
TEST_CASE("SFileReadFile", "[file]") {
SECTION("shared testcases") {
ReadFileTestCase testcase = GENERATE(ReadFromDiskCase, ReadFromMPQCase);
INFO(testcase.info);
HSFILE file = testcase.OpenFileFn();
REQUIRE(file != nullptr);
SECTION("reads a file") {
char buffer[32] = {};
CHECK(SFileReadFile(file, buffer, 6, nullptr, nullptr) == 1);
CHECK(std::string(buffer) == "catdog");
}
SECTION("reads partial file if bytestoread is too small") {
char buffer[4] = "";
CHECK(SFileReadFile(file, &buffer, 3, nullptr, nullptr) == 1);
CHECK(std::string(buffer) == "cat");
}
SECTION("continues reading from the last stored position") {
char buffer[4] = "";
CHECK(SFileReadFile(file, &buffer, 3, nullptr, nullptr) == 1);
CHECK(SFileReadFile(file, &buffer, 3, nullptr, nullptr) == 1);
CHECK(std::string(buffer) == "dog");
}
SECTION("continues reading from an explicitly set position") {
char buffer[4] = "";
SFileSetFilePointer(file, 3, nullptr, SFILE_BEGIN);
CHECK(SFileReadFile(file, &buffer, 3, nullptr, nullptr) == 1);
CHECK(std::string(buffer) == "dog");
}
SECTION("succeeds if bytestoread is 0") {
char buffer;
CHECK(SFileReadFile(file, &buffer, 0, nullptr, nullptr) == 1);
uint32_t read = 42;
CHECK(SFileReadFile(file, &buffer, 0, &read, nullptr) == 1);
CHECK(read == 0);
}
SECTION("succeeds if bytestoread is 0 past eof") {
char buffer[8];
CHECK_FALSE(SFileReadFile(file, &buffer, 8, nullptr, nullptr));
uint32_t read = 42;
CHECK(SFileReadFile(file, &buffer, 0, &read, nullptr) == 1);
CHECK(read == 0);
}
SECTION("fails when reading past end of file") {
char buffer[8] = "";
CHECK(SFileReadFile(file, &buffer, 6, nullptr, nullptr) == 1);
CHECK(std::string(buffer) == "catdog");
SErrSetLastError(0);
CHECK_FALSE(SFileReadFile(file, &buffer, 1, nullptr, nullptr));
CHECK(SErrGetLastError() == testcase.eofcode);
CHECK(std::string(buffer) == "catdog");
}
SECTION("fails if bytestoread is larger than file size when reading from disk") {
char buffer[32] = "";
SErrSetLastError(0);
CHECK_FALSE(SFileReadFile(file, buffer, sizeof(buffer), nullptr, nullptr));
CHECK(SErrGetLastError() == testcase.eofcode);
CHECK(std::string(buffer) == "catdog");
}
}
}
TEST_CASE("SFileSetFilePointer", "[file]") {
SECTION("shared testcases") {
ReadFileTestCase testcase = GENERATE(ReadFromDiskCase, ReadFromMPQCase);
INFO(testcase.info);
HSFILE file = testcase.OpenFileFn();
REQUIRE(file != nullptr);
SECTION("sets position from beginning") {
CHECK(SFileSetFilePointer(file, 2, nullptr, SFILE_BEGIN) == 2);
CHECK(SFileSetFilePointer(file, 0, nullptr, SFILE_BEGIN) == 0);
CHECK(SFileSetFilePointer(file, 5, nullptr, SFILE_BEGIN) == 5);
}
SECTION("returns the cursor position") {
CHECK(SFileSetFilePointer(file, 2, nullptr, SFILE_BEGIN) == 2);
CHECK(SFileSetFilePointer(file, 1, nullptr, SFILE_BEGIN) == 1);
CHECK(SFileSetFilePointer(file, 5, nullptr, SFILE_BEGIN) == 5);
CHECK(SFileSetFilePointer(file, -4, nullptr, SFILE_CURRENT) == 1);
CHECK(SFileSetFilePointer(file, 0, nullptr, SFILE_BEGIN) == 0);
}
SECTION("sets position from current") {
CHECK(SFileSetFilePointer(file, 0, nullptr, SFILE_CURRENT) == 0);
CHECK(SFileSetFilePointer(file, 1, nullptr, SFILE_CURRENT) == 1);
CHECK(SFileSetFilePointer(file, 1, nullptr, SFILE_CURRENT) == 2);
CHECK(SFileSetFilePointer(file, 1, nullptr, SFILE_CURRENT) == 3);
CHECK(SFileSetFilePointer(file, 0, nullptr, SFILE_CURRENT) == 3);
CHECK(SFileSetFilePointer(file, -2, nullptr, SFILE_CURRENT) == 1);
CHECK(SFileSetFilePointer(file, -1, nullptr, SFILE_CURRENT) == 0);
}
}
SECTION("cases from filesystem") {
// Probably Windows specific, return values are directly from WinAPI calls
// TODO compare with Mac build results
HSFILE file = ReadTestFileFromDisk();
REQUIRE(file != nullptr);
SECTION("sets position from beginning out of bounds") {
CHECK(SFileSetFilePointer(file, -1, nullptr, SFILE_BEGIN) == -1);
CHECK(SFileSetFilePointer(file, -100, nullptr, SFILE_BEGIN) == -1);
CHECK(SFileSetFilePointer(file, 6, nullptr, SFILE_BEGIN) == 6);
CHECK(SFileSetFilePointer(file, 100, nullptr, SFILE_BEGIN) == 100);
}
SECTION("sets position from current out of bounds") {
CHECK(SFileSetFilePointer(file, -1, nullptr, SFILE_CURRENT) == -1);
CHECK(SFileSetFilePointer(file, -100, nullptr, SFILE_CURRENT) == -1);
CHECK(SFileSetFilePointer(file, 106, nullptr, SFILE_CURRENT) == 106);
CHECK(SFileSetFilePointer(file, 100, nullptr, SFILE_CURRENT) == 206);
}
SECTION("sets position from end") {
CHECK(SFileSetFilePointer(file, -5, nullptr, SFILE_END) == 1);
CHECK(SFileSetFilePointer(file, -2, nullptr, SFILE_END) == 4);
CHECK(SFileSetFilePointer(file, -1, nullptr, SFILE_END) == 5);
CHECK(SFileSetFilePointer(file, 0, nullptr, SFILE_END) == 6);
}
SECTION("sets position from end out of bounds") {
CHECK(SFileSetFilePointer(file, -100, nullptr, SFILE_END) == -1);
CHECK(SFileSetFilePointer(file, -10, nullptr, SFILE_END) == -1);
CHECK(SFileSetFilePointer(file, 1, nullptr, SFILE_END) == 7);
CHECK(SFileSetFilePointer(file, 5, nullptr, SFILE_END) == 11);
}
}
SECTION("cases from MPQ") {
HSFILE file = ReadTestFileFromMpq();
REQUIRE(file != nullptr);
SECTION("sets position from beginning out of bounds") {
CHECK(SFileSetFilePointer(file, -1, nullptr, SFILE_BEGIN) == 5);
CHECK(SFileSetFilePointer(file, -100, nullptr, SFILE_BEGIN) == 5);
CHECK(SFileSetFilePointer(file, 6, nullptr, SFILE_BEGIN) == 5);
CHECK(SFileSetFilePointer(file, 100, nullptr, SFILE_BEGIN) == 5);
}
SECTION("sets position from current out of bounds") {
CHECK(SFileSetFilePointer(file, -1, nullptr, SFILE_CURRENT) == 0);
CHECK(SFileSetFilePointer(file, -100, nullptr, SFILE_CURRENT) == 0);
CHECK(SFileSetFilePointer(file, 106, nullptr, SFILE_CURRENT) == 5);
CHECK(SFileSetFilePointer(file, 100, nullptr, SFILE_CURRENT) == 5);
}
SECTION("sets position from end") {
CHECK(SFileSetFilePointer(file, -5, nullptr, SFILE_END) == 1);
CHECK(SFileSetFilePointer(file, -2, nullptr, SFILE_END) == 4);
CHECK(SFileSetFilePointer(file, -1, nullptr, SFILE_END) == 5);
CHECK(SFileSetFilePointer(file, 0, nullptr, SFILE_END) == 5);
}
SECTION("sets position from end out of bounds") {
CHECK(SFileSetFilePointer(file, -100, nullptr, SFILE_END) == 0);
CHECK(SFileSetFilePointer(file, -10, nullptr, SFILE_END) == 0);
CHECK(SFileSetFilePointer(file, 1, nullptr, SFILE_END) == 5);
CHECK(SFileSetFilePointer(file, 5, nullptr, SFILE_END) == 5);
}
}
}
#endif

33
test/FileTest.cpp Normal file
View file

@ -0,0 +1,33 @@
#include "FileTest.hpp"
HSARCHIVE OpenNullArchive() {
return nullptr;
}
HSARCHIVE OpenTestArchive() {
HSARCHIVE archive = nullptr;
SFileOpenArchive("wowtest1.mpq", 0, 0, &archive);
REQUIRE(archive != nullptr);
return archive;
}
HSFILE ReadTestFileFromDisk() {
HSFILE file = nullptr;
SFileOpenFileEx(nullptr, "test_diskonly.txt", SFILE_OPENFLAG_CHECKDISK, &file);
return file;
}
HSFILE ReadTestFileFromMpq() {
HSARCHIVE archive = nullptr;
SFileOpenArchive("wowtest1.mpq", 0, 0, &archive);
HSFILE file = nullptr;
SFileOpenFileEx(archive, "test.txt", 0, &file);
return file;
}
OpenFileTestCase OpenFromDiskCase{ "file from disk", OpenNullArchive, SFILE_OPENFLAG_CHECKDISK };
OpenFileTestCase OpenFromMPQCase{ "file from MPQ", OpenTestArchive, 0 };
ReadFileTestCase ReadFromDiskCase{ "file from disk", ReadTestFileFromDisk, ERROR_SUCCESS };
ReadFileTestCase ReadFromMPQCase{ "file from MPQ", ReadTestFileFromMpq, ERROR_HANDLE_EOF };

29
test/FileTest.hpp Normal file
View file

@ -0,0 +1,29 @@
#include "Test.hpp"
#include "storm/Error.hpp"
#include "storm/File.hpp"
#include <string>
struct OpenFileTestCase {
std::string info;
HSARCHIVE (*OpenArchiveFn)();
uint32_t flags;
};
struct ReadFileTestCase {
std::string info;
HSFILE (*OpenFileFn)();
uint32_t eofcode;
};
HSARCHIVE OpenNullArchive();
HSARCHIVE OpenTestArchive();
HSFILE ReadTestFileFromDisk();
HSFILE ReadTestFileFromMpq();
extern OpenFileTestCase OpenFromDiskCase;
extern OpenFileTestCase OpenFromMPQCase;
extern ReadFileTestCase ReadFromDiskCase;
extern ReadFileTestCase ReadFromMPQCase;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
test/fixture/broken4.mpq Normal file

Binary file not shown.

View file

View file

1
test/fixture/test.txt Normal file
View file

@ -0,0 +1 @@
catdog

View file

@ -0,0 +1 @@
catdog

BIN
test/fixture/wowtest1.mpq Normal file

Binary file not shown.

BIN
test/fixture/wowtest2.mpq Normal file

Binary file not shown.

BIN
test/fixture/wowtest3.mpq Normal file

Binary file not shown.

View file

@ -87,8 +87,8 @@ EXPORTS
; File
;SFileAuthenticateArchive @251 NONAME
;SFileCloseArchive @252 NONAME
;SFileCloseFile @253 NONAME
SFileCloseArchive @252 NONAME
SFileCloseFile @253 NONAME
;SFileDdaBegin @254 NONAME
;SFileDdaBeginEx @255 NONAME
;SFileDdaDestroy @256 NONAME
@ -100,13 +100,13 @@ EXPORTS
;SFileDestroy @262 NONAME
;SFileEnableDirectAccess @263 NONAME
;SFileGetFileArchive @264 NONAME
;SFileGetFileSize @265 NONAME
;SFileOpenArchive @266 NONAME
SFileGetFileSize @265 NONAME
SFileOpenArchive @266 NONAME
;SFileOpenFile @267 NONAME
;SFileOpenFileEx @268 NONAME
;SFileReadFile @269 NONAME
SFileOpenFileEx @268 NONAME
SFileReadFile @269 NONAME
;SFileSetBasePath @270 NONAME
;SFileSetFilePointer @271 NONAME
SFileSetFilePointer @271 NONAME
;SFileSetLocale @272 NONAME
;SFileGetBasePath @273 NONAME
;SFileSetIoErrorMode @274 NONAME
@ -280,7 +280,7 @@ EXPORTS
;SErrGetErrorStr @462 NONAME
SErrGetLastError @463 NONAME
;SErrRegisterMessageSource @464 NONAME
;SErrSetLastError @465 NONAME
SErrSetLastError @465 NONAME
;SErrReportNamedResourceLeak @466 NONAME
;SErrReportResourceLeak @467 NONAME
SErrSuppressErrors @468 NONAME

View file

@ -55,6 +55,16 @@ int32_t STORMAPI SEvtRegisterHandler(uint32_t, uint32_t, uint32_t, uint32_t, SEV
int32_t STORMAPI SEvtUnregisterHandler(uint32_t, uint32_t, uint32_t, SEVTHANDLER) { return 0; }
int32_t STORMAPI SEvtUnregisterType(uint32_t, uint32_t) { return 0; }
#include <storm/File.hpp>
int32_t STORMAPI SFileCloseArchive(HSARCHIVE) { return 0; }
int32_t STORMAPI SFileCloseFile(HSFILE) { return 0; }
uint32_t STORMAPI SFileGetFileSize(HSFILE, uint32_t*) { return 0; }
int32_t STORMAPI SFileOpenArchive(const char*, int32_t, uint32_t, HSARCHIVE*) { return 0; }
int32_t STORMAPI SFileOpenFileEx(HSARCHIVE, const char*, uint32_t, HSFILE*) { return 0; }
int32_t STORMAPI SFileReadFile(HSFILE, void*, uint32_t, uint32_t*, LPOVERLAPPED) { return 0; }
uint32_t STORMAPI SFileSetFilePointer(HSFILE, int32_t, int32_t*, uint32_t) { return 0; }
#include <storm/Memory.hpp>
void* STORMAPI SMemAlloc(size_t, const char*, int32_t, uint32_t) { return 0; }