Add file write tests and delete functionality
This commit is contained in:
parent
93bbc25b11
commit
84149d0ad1
31
dqn.h
31
dqn.h
@ -801,7 +801,6 @@ DQN_FILE_SCOPE u32 DqnRnd_PCGNext (DqnRandPCGState *pcg);
|
||||
DQN_FILE_SCOPE f32 DqnRnd_PCGNextf(DqnRandPCGState *pcg);
|
||||
// Returns a random integer N between [min, max]
|
||||
DQN_FILE_SCOPE i32 DqnRnd_PCGRange(DqnRandPCGState *pcg, i32 min, i32 max);
|
||||
|
||||
#endif /* DQN_H */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -817,6 +816,7 @@ DQN_FILE_SCOPE i32 DqnRnd_PCGRange(DqnRandPCGState *pcg, i32 min, i32 max);
|
||||
|
||||
#ifdef DQN_UNIX_PLATFORM
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h> // unlink()
|
||||
#include <stdio.h> // Basic File I/O
|
||||
#include <dirent.h> // readdir()/opendir()/closedir()
|
||||
#endif
|
||||
@ -854,6 +854,7 @@ typedef struct DqnFile
|
||||
u32 permissionFlags;
|
||||
} DqnFile;
|
||||
|
||||
// NOTE: W(ide) versions of functions only work on Win32, since Unix is UTF-8 compatible.
|
||||
// Open a handle to the file
|
||||
DQN_FILE_SCOPE bool DqnFile_Open (const char *const path, DqnFile *const file, const u32 permissionFlags, const enum DqnFileAction action);
|
||||
DQN_FILE_SCOPE bool DqnFile_OpenW(const wchar_t *const path, DqnFile *const file, const u32 permissionFlags, const enum DqnFileAction action);
|
||||
@ -864,6 +865,10 @@ DQN_FILE_SCOPE size_t DqnFile_Write(const DqnFile *const file, u8 *const buffer,
|
||||
DQN_FILE_SCOPE size_t DqnFile_Read (const DqnFile file, u8 *const buffer, const size_t numBytesToRead);
|
||||
DQN_FILE_SCOPE void DqnFile_Close(DqnFile *const file);
|
||||
|
||||
// NOTE: You can't delete a file unless the handle has been closed to it on Win32.
|
||||
DQN_FILE_SCOPE bool DqnFile_Delete (const char *const path);
|
||||
DQN_FILE_SCOPE bool DqnFile_DeleteW(const wchar_t *const path);
|
||||
|
||||
// Return an array of strings of the files in the directory in UTF-8. numFiles
|
||||
// returns the number of strings read.
|
||||
// This is allocated using malloc and MUST BE FREED! Can be done manually or
|
||||
@ -1704,9 +1709,10 @@ DQN_FILE_SCOPE bool DqnMemStack_Pop(DqnMemStack *const stack, void *ptr, size_t
|
||||
"'ptr' to pop does not belong to current memStack attached block"))
|
||||
{
|
||||
size_t calcSize = (size_t)currPtr - (size_t)ptr;
|
||||
if (DQN_ASSERT_MSG(calcSize == size, "'ptr' was not the last item allocated to memStack"))
|
||||
size_t sizeAligned = DQN_ALIGN_POW_N(size, stack->byteAlign);
|
||||
if (DQN_ASSERT_MSG(calcSize == sizeAligned, "'ptr' was not the last item allocated to memStack"))
|
||||
{
|
||||
stack->block->used -= size;
|
||||
stack->block->used -= sizeAligned;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -3878,7 +3884,7 @@ DQN_FILE_SCOPE size_t DqnFile_Write(const DqnFile *const file,
|
||||
{
|
||||
size_t numBytesWritten = 0;
|
||||
// TODO(doyle): Implement when it's needed
|
||||
if (DQN_ASSERT_MSG(fileOffset != 0, "'fileOffset' not implemented yet")) return 0;
|
||||
if (!DQN_ASSERT_MSG(fileOffset == 0, "'fileOffset' not implemented yet")) return 0;
|
||||
if (!file || !buffer) return numBytesToWrite;
|
||||
|
||||
#if defined(DQN_WIN32_PLATFORM)
|
||||
@ -3963,6 +3969,23 @@ DQN_FILE_SCOPE void DqnFile_Close(DqnFile *const file)
|
||||
}
|
||||
}
|
||||
|
||||
DQN_FILE_SCOPE bool DqnFile_Delete(const char *const path)
|
||||
{
|
||||
if (!path) return false;
|
||||
|
||||
// TODO(doyle): Logging
|
||||
#if defined(DQN_WIN32_PLATFORM)
|
||||
return DeleteFile(path);
|
||||
|
||||
#elif defined(DQN_UNIX_PLATFORM)
|
||||
i32 result = unlink(path);
|
||||
|
||||
if (result == 0) return true;
|
||||
return false;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
DQN_FILE_SCOPE char **DqnDir_Read(const char *const dir, u32 *const numFiles)
|
||||
{
|
||||
char **result = DqnDirInternal_PlatformRead(dir, numFiles);
|
||||
|
@ -1,5 +1,6 @@
|
||||
#if (defined(_WIN32) || defined(_WIN64))
|
||||
#define DQN_WIN32_IMPLEMENTATION
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
@ -1445,21 +1446,46 @@ void FileTest()
|
||||
{
|
||||
// File i/o
|
||||
{
|
||||
|
||||
// Test file open
|
||||
{
|
||||
const char *const FILE_TO_OPEN = ".clang-format";
|
||||
u32 expectedSize = 0;
|
||||
#if defined(DQN_UNIX_IMPLEMENTATION)
|
||||
{
|
||||
struct stat fileStat = {0};
|
||||
DQN_ASSERT(stat(FILE_TO_OPEN, &fileStat) == 0);
|
||||
expectedSize = fileStat.st_size;
|
||||
}
|
||||
|
||||
#elif defined(DQN_WIN32_IMPLEMENTATION)
|
||||
{
|
||||
HANDLE handle =
|
||||
CreateFile(FILE_TO_OPEN, GENERIC_READ, 0, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DqnWin32_DisplayLastError("CreateFile() failed");
|
||||
}
|
||||
DQN_ASSERT(handle != INVALID_HANDLE_VALUE);
|
||||
|
||||
LARGE_INTEGER size;
|
||||
DQN_ASSERT(GetFileSizeEx(handle, &size));
|
||||
|
||||
CloseHandle(handle);
|
||||
expectedSize = size.LowPart;
|
||||
}
|
||||
#endif
|
||||
|
||||
DqnFile file = {};
|
||||
DQN_ASSERT(DqnFile_Open(
|
||||
".clang-format", &file,
|
||||
(DqnFilePermissionFlag_Write | DqnFilePermissionFlag_Read),
|
||||
DqnFileAction_OpenOnly));
|
||||
|
||||
#if defined(DQN_UNIX_IMPLEMENTATION)
|
||||
const u32 EXPECTED_SIZE = 1274;
|
||||
#elif defined(DQN_WIN32_IMPLEMENTATION)
|
||||
const u32 EXPECTED_SIZE = 1320;
|
||||
#endif
|
||||
DQN_ASSERT_MSG(file.size == EXPECTED_SIZE,
|
||||
DQN_ASSERT_MSG(file.size == expectedSize,
|
||||
"DqnFileOpen() failed: file.size: %d, expected:%d\n",
|
||||
file.size, EXPECTED_SIZE);
|
||||
file.size, expectedSize);
|
||||
|
||||
u8 *buffer = (u8 *)calloc(1, (size_t)file.size * sizeof(u8));
|
||||
DQN_ASSERT(DqnFile_Read(file, buffer, (u32)file.size) == file.size);
|
||||
@ -1470,6 +1496,7 @@ void FileTest()
|
||||
file.permissionFlags == 0);
|
||||
}
|
||||
|
||||
// Test invalid file
|
||||
{
|
||||
DqnFile file = {};
|
||||
DQN_ASSERT(!DqnFile_Open(
|
||||
@ -1482,7 +1509,74 @@ void FileTest()
|
||||
printf("FileTest(): FileIO: Completed successfully\n");
|
||||
}
|
||||
|
||||
// TODO(doyle): Write tests for writing out to file
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Write Test
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
const char *fileNames[] = {"dqn_1", "dqn_2", "dqn_3", "dqn_4", "dqn_5"};
|
||||
const char *writeData[] = {"1234", "2468", "36912", "481216",
|
||||
"5101520"};
|
||||
DqnFile files[DQN_ARRAY_COUNT(fileNames)] = {};
|
||||
|
||||
// Write data out to some files
|
||||
for (u32 i = 0; i < DQN_ARRAY_COUNT(fileNames); i++)
|
||||
{
|
||||
u32 permissions =
|
||||
DqnFilePermissionFlag_Read | DqnFilePermissionFlag_Write;
|
||||
if (!DqnFile_Open(fileNames[i], files + i, permissions,
|
||||
DqnFileAction_ClearIfExist))
|
||||
{
|
||||
bool result = DqnFile_Open(fileNames[i], files + i, permissions,
|
||||
DqnFileAction_CreateIfNotExist);
|
||||
DQN_ASSERT(result);
|
||||
}
|
||||
|
||||
size_t bytesToWrite = DqnStr_Len(writeData[i]);
|
||||
u8 *dataToWrite = (u8 *)(writeData[i]);
|
||||
size_t bytesWritten = DqnFile_Write(files + i, dataToWrite, bytesToWrite, 0);
|
||||
DQN_ASSERT(bytesWritten == bytesToWrite);
|
||||
DqnFile_Close(&files[i]);
|
||||
}
|
||||
|
||||
DqnMemStack memStack = {};
|
||||
DQN_ASSERT(DqnMemStack_Init(&memStack, DQN_MEGABYTE(1), true));
|
||||
// Read data back in
|
||||
for (u32 i = 0; i < DQN_ARRAY_COUNT(fileNames); i++)
|
||||
{
|
||||
u32 permissions = DqnFilePermissionFlag_Read;
|
||||
DqnFile *file = files + i;
|
||||
bool result = DqnFile_Open(fileNames[i], file, permissions,
|
||||
DqnFileAction_OpenOnly);
|
||||
DQN_ASSERT(result);
|
||||
|
||||
u8 *buffer = (u8 *)DqnMemStack_Push(&memStack, file->size);
|
||||
DQN_ASSERT(buffer);
|
||||
|
||||
size_t bytesRead = DqnFile_Read(files[i], buffer, file->size);
|
||||
DQN_ASSERT(bytesRead == file->size);
|
||||
|
||||
// Verify the data is the same as we wrote out
|
||||
DQN_ASSERT(DqnStr_Cmp((char *)buffer, (writeData[i])) == 0);
|
||||
|
||||
// Delete when we're done with it
|
||||
DQN_ASSERT(DqnMemStack_Pop(&memStack, buffer, file->size));
|
||||
DqnFile_Close(file);
|
||||
|
||||
DQN_ASSERT(DqnFile_Delete(fileNames[i]));
|
||||
}
|
||||
|
||||
// Then check delete actually worked, files should not exist.
|
||||
for (u32 i = 0; i < DQN_ARRAY_COUNT(fileNames); i++)
|
||||
{
|
||||
DqnFile dummy = {};
|
||||
u32 permissions = DqnFilePermissionFlag_Read;
|
||||
bool fileExists = DqnFile_Open(fileNames[i], &dummy, permissions,
|
||||
DqnFileAction_OpenOnly);
|
||||
DQN_ASSERT(!fileExists);
|
||||
}
|
||||
DqnMemStack_Free(&memStack);
|
||||
}
|
||||
|
||||
{
|
||||
@ -1559,6 +1653,10 @@ FILE_SCOPE void JobQueueTest()
|
||||
for (i32 i = 0; i < DQN_ARRAY_COUNT(globalDebugCounterMemoize); i++)
|
||||
DQN_ASSERT(globalDebugCounterMemoize[i]);
|
||||
|
||||
while (DqnJobQueue_TryExecuteNextJob(jobQueue) &&
|
||||
!DqnJobQueue_AllJobsComplete(jobQueue))
|
||||
;
|
||||
|
||||
printf("\nJobQueueTest(): Final incremented value: %d\n", globalDebugCounter);
|
||||
DQN_ASSERT(globalDebugCounter == DQN_ARRAY_COUNT(globalDebugCounterMemoize));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user