feat(file): implemented file reading/writting #11

Merged
Mineplay merged 30 commits from feat/4-file into main 2025-12-21 06:12:09 -06:00
7 changed files with 197 additions and 27 deletions
Showing only changes of commit 91ff52883c - Show all commits

3
.gitignore vendored
View file

@ -69,3 +69,6 @@ build
# clangd
.cache/
# generated test data
tests/data/*.bin

View file

@ -6,9 +6,14 @@
* You may obtain a copy of the License in the file LICENSE or at
* http://www.apache.org/licenses/LICENSE-2.0
*/
#include "tools/tool.h"
#include "unit/unit.h"
int main(void) {
if (cosms_core_tool_generate_test_data() != 0) {
return -1;
}
COSMS_CORE_TEST_RUN()
return 0;
}

89
tests/tools/tool-file.c Normal file
View file

@ -0,0 +1,89 @@
/*
* Copyright (C) Tristan Franssen, <tristanfranssen@strawhats.nl>.
*
* This software is licensed under the Apache License, Version 2.0 (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License in the file LICENSE or at
* http://www.apache.org/licenses/LICENSE-2.0
*/
#include "tool-file.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define COSMS_CORE_FILE_TOOL_LARGE_FILE_SIZE 5242880000ULL
#define CHUNK 4096
#define LARGE_FILE_PATH "tests/data/large-file.bin"
#define SMALL_DELETE_FILE_PATH "tests/data/small-delete-file.bin"
#define LARGE_DELETE_FILE_PATH "tests/data/large-delete-file.bin"
/**
* @brief Generates a large nearly 5GB file for testing.
*/
int cosms_core_tool_file_generate_large_file(void) {
FILE *file = fopen(LARGE_FILE_PATH, "wb");
if (file == NULL) {
return -1;
}
static char buffer[CHUNK];
for (unsigned int index = 0; index < CHUNK; index += 1) {
buffer[index] = 'a';
}
unsigned long long written_bytes = 0;
while (written_bytes < COSMS_CORE_FILE_TOOL_LARGE_FILE_SIZE) {
unsigned int bytes_to_write = CHUNK;
if (written_bytes + CHUNK > COSMS_CORE_FILE_TOOL_LARGE_FILE_SIZE) {
bytes_to_write = (unsigned int)(COSMS_CORE_FILE_TOOL_LARGE_FILE_SIZE - written_bytes);
}
fwrite(buffer, 1, bytes_to_write, file);
written_bytes += bytes_to_write;
}
fclose(file);
return 0;
}
/**
* @brief Generates files to be deleted.
*/
int cosms_core_tool_file_generate_delete_file(void) {
FILE *file = fopen(SMALL_DELETE_FILE_PATH, "wb");
if (file == NULL) {
return -1;
}
char *small_buffer = "Hello, World!";
fwrite(small_buffer, 1, strlen(small_buffer), file);
fclose(file);
fopen_s(&file, LARGE_DELETE_FILE_PATH, "wb");
if (file == NULL) {
return -1;
}
static char large_buffer[CHUNK];
for (unsigned int index = 0; index < CHUNK; index += 1) {
large_buffer[index] = 'a';
}
unsigned long long written_bytes = 0;
while (written_bytes < COSMS_CORE_FILE_TOOL_LARGE_FILE_SIZE) {
unsigned int bytes_to_write = CHUNK;
if (written_bytes + CHUNK > COSMS_CORE_FILE_TOOL_LARGE_FILE_SIZE) {
bytes_to_write = (unsigned int)(COSMS_CORE_FILE_TOOL_LARGE_FILE_SIZE - written_bytes);
}
fwrite(large_buffer, 1, bytes_to_write, file);
written_bytes += bytes_to_write;
}
fclose(file);
return 0;
}

21
tests/tools/tool-file.h Normal file
View file

@ -0,0 +1,21 @@
/*
* Copyright (C) Tristan Franssen, <tristanfranssen@strawhats.nl>.
*
* This software is licensed under the Apache License, Version 2.0 (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License in the file LICENSE or at
* http://www.apache.org/licenses/LICENSE-2.0
*/
#ifndef COSMS_CORE_TOOL_FILE
#define COSMS_CORE_TOOL_FILE
/**
* @brief Generates a large nearly 5GB file for testing.
*/
int cosms_core_tool_file_generate_large_file(void);
/**
* @brief Generates files to be deleted.
*/
int cosms_core_tool_file_generate_delete_file(void);
#endif /* COSMS_CORE_TOOL_FILE */

30
tests/tools/tool.c Normal file
View file

@ -0,0 +1,30 @@
/*
* Copyright (C) Tristan Franssen, <tristanfranssen@strawhats.nl>.
*
* This software is licensed under the Apache License, Version 2.0 (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License in the file LICENSE or at
* http://www.apache.org/licenses/LICENSE-2.0
*/
#include "tool.h"
#include "tool-file.h"
#include <stdio.h>
int cosms_core_tool_generate_test_data(void) {
printf("[*] Generating test data...");
fflush(stdout);
if (cosms_core_tool_file_generate_large_file() != 0) {
printf("\r[FAILED] could not generate large file!\n");
return -1;
}
if (cosms_core_tool_file_generate_delete_file() != 0) {
printf("\r[FAILED] could not generate delete files!\n");
return -1;
}
printf("\r[COMPLETED] finished generating test data!\n");
return 0;
}

14
tests/tools/tool.h Normal file
View file

@ -0,0 +1,14 @@
/*
* Copyright (C) Tristan Franssen, <tristanfranssen@strawhats.nl>.
*
* This software is licensed under the Apache License, Version 2.0 (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License in the file LICENSE or at
* http://www.apache.org/licenses/LICENSE-2.0
*/
#ifndef COSMS_CORE_TOOL
#define COSMS_CORE_TOOL
int cosms_core_tool_generate_test_data(void);
#endif /* COSMS_CORE_TOOL */

View file

@ -13,6 +13,14 @@
#include <stdlib.h>
#include <string.h>
#if defined (__GNUC__)
#define COSMS_CORE_FILE_TEST_INVALID_NATIVE_FILE -1
#elif defined(_WIN32)
#define COSMS_CORE_FILE_TEST_INVALID_NATIVE_FILE NULL
#endif
#define COSMS_CORE_FILE_TEST_LARGE_FILE_SIZE 5242880000ULL
COSMS_CORE_TEST_TEST(file_open_small_file_read,
struct cosms_core_file file;
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/small-file.txt", COSMS_CORE_FILE_MODE_READ);
@ -30,7 +38,7 @@ COSMS_CORE_TEST_TEST(file_open_small_file_read,
COSMS_CORE_TEST_TEST(file_open_large_file_read,
struct cosms_core_file file;
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/large-file.txt", COSMS_CORE_FILE_MODE_READ);
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/large-file.bin", COSMS_CORE_FILE_MODE_READ);
if (error != COSMS_CORE_FILE_OK) {
return cosms_core_file_error_string(error);
}
@ -80,7 +88,7 @@ COSMS_CORE_TEST_TEST(file_open_small_file_write,
COSMS_CORE_TEST_TEST(file_open_large_file_write,
struct cosms_core_file file;
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/large-file.txt", COSMS_CORE_FILE_MODE_WRITE);
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/large-file.bin", COSMS_CORE_FILE_MODE_WRITE);
if (error != COSMS_CORE_FILE_OK) {
return cosms_core_file_error_string(error);
}
@ -110,7 +118,7 @@ COSMS_CORE_TEST_TEST(file_open_small_file_append,
COSMS_CORE_TEST_TEST(file_open_large_file_append,
struct cosms_core_file file;
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/large-file.txt", COSMS_CORE_FILE_MODE_APPEND);
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/large-file.bin", COSMS_CORE_FILE_MODE_APPEND);
if (error != COSMS_CORE_FILE_OK) {
return cosms_core_file_error_string(error);
}
@ -140,7 +148,7 @@ COSMS_CORE_TEST_TEST(file_open_small_file_read_write,
COSMS_CORE_TEST_TEST(file_open_large_file_read_write,
struct cosms_core_file file;
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/large-file.txt", COSMS_CORE_FILE_MODE_READ | COSMS_CORE_FILE_MODE_WRITE);
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/large-file.bin", COSMS_CORE_FILE_MODE_READ | COSMS_CORE_FILE_MODE_WRITE);
if (error != COSMS_CORE_FILE_OK) {
return cosms_core_file_error_string(error);
}
@ -170,7 +178,7 @@ COSMS_CORE_TEST_TEST(file_close,
COSMS_CORE_TEST_TEST(file_close_non_existing_file,
struct cosms_core_file file;
file.native_file = -1;
file.native_file = COSMS_CORE_FILE_TEST_INVALID_NATIVE_FILE;
CosmsCoreFileError error = cosms_core_file_close(&file);
if (error != COSMS_CORE_FILE_INVALID_FILE) {
@ -209,7 +217,7 @@ COSMS_CORE_TEST_TEST(file_size_small_file,
COSMS_CORE_TEST_TEST(file_size_large,
struct cosms_core_file file;
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/large-file.txt", COSMS_CORE_FILE_MODE_READ);
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/large-file.bin", COSMS_CORE_FILE_MODE_READ);
if (error != COSMS_CORE_FILE_OK) {
return cosms_core_file_error_string(error);
}
@ -221,7 +229,7 @@ COSMS_CORE_TEST_TEST(file_size_large,
return cosms_core_file_error_string(error);
}
if (size != 5242880000ULL) {
if (size != COSMS_CORE_FILE_TEST_LARGE_FILE_SIZE) {
cosms_core_file_close(&file);
return "result does not match expected result";
}
@ -236,7 +244,7 @@ COSMS_CORE_TEST_TEST(file_size_large,
COSMS_CORE_TEST_TEST(file_size_non_existing_file,
struct cosms_core_file file;
file.native_file = -1;
file.native_file = COSMS_CORE_FILE_TEST_INVALID_NATIVE_FILE;
unsigned long long size = 0;
CosmsCoreFileError error = cosms_core_file_get_size(&file, &size);
@ -279,12 +287,12 @@ COSMS_CORE_TEST_TEST(file_read_small_file,
COSMS_CORE_TEST_TEST(file_read_large_file,
struct cosms_core_file file;
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/large-file.txt", COSMS_CORE_FILE_MODE_READ);
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/large-file.bin", COSMS_CORE_FILE_MODE_READ);
if (error != COSMS_CORE_FILE_OK) {
return cosms_core_file_error_string(error);
}
unsigned long long bytes_to_read = 5242880000ULL;
unsigned long long bytes_to_read = COSMS_CORE_FILE_TEST_LARGE_FILE_SIZE;
unsigned long long bytes_read = 0;
char *buffer = NULL;
@ -330,7 +338,7 @@ COSMS_CORE_TEST_TEST(file_read_large_file,
COSMS_CORE_TEST_TEST(file_read_non_existing_file,
struct cosms_core_file file;
file.mode = COSMS_CORE_FILE_MODE_READ;
file.native_file = -1;
file.native_file = COSMS_CORE_FILE_TEST_INVALID_NATIVE_FILE;
unsigned int bytes_to_read = 13;
unsigned int bytes_read = 0;
@ -347,7 +355,7 @@ COSMS_CORE_TEST_TEST(file_read_non_existing_file,
COSMS_CORE_TEST_TEST(file_read_full_non_existing_file,
struct cosms_core_file file;
file.mode = COSMS_CORE_FILE_MODE_READ;
file.native_file = -1;
file.native_file = COSMS_CORE_FILE_TEST_INVALID_NATIVE_FILE;
unsigned long long bytes_read = 0;
char *buffer = NULL;
@ -417,7 +425,7 @@ COSMS_CORE_TEST_TEST(file_read_full_file_using_wrong_mode,
COSMS_CORE_TEST_TEST(file_write_small_file,
struct cosms_core_file file;
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/small-write-file.txt", COSMS_CORE_FILE_MODE_WRITE | COSMS_CORE_FILE_MODE_CREATE);
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/small-write-file.bin", COSMS_CORE_FILE_MODE_WRITE | COSMS_CORE_FILE_MODE_CREATE);
if (error != COSMS_CORE_FILE_OK) {
return cosms_core_file_error_string(error);
}
@ -442,7 +450,7 @@ COSMS_CORE_TEST_TEST(file_write_small_file,
return cosms_core_file_error_string(error);
}
error = cosms_core_file_open(&file, "tests/data/small-write-file.txt", COSMS_CORE_FILE_MODE_READ);
error = cosms_core_file_open(&file, "tests/data/small-write-file.bin", COSMS_CORE_FILE_MODE_READ);
if (error != COSMS_CORE_FILE_OK) {
return cosms_core_file_error_string(error);
}
@ -469,12 +477,12 @@ COSMS_CORE_TEST_TEST(file_write_small_file,
COSMS_CORE_TEST_TEST(file_write_large_file,
struct cosms_core_file file;
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/large-write-file.txt", COSMS_CORE_FILE_MODE_WRITE | COSMS_CORE_FILE_MODE_CREATE);
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/large-write-file.bin", COSMS_CORE_FILE_MODE_WRITE | COSMS_CORE_FILE_MODE_CREATE);
if (error != COSMS_CORE_FILE_OK) {
return cosms_core_file_error_string(error);
}
unsigned long long bytes_to_write = 5242880000ULL;
unsigned long long bytes_to_write = COSMS_CORE_FILE_TEST_LARGE_FILE_SIZE;
char *write_buffer = (char*)malloc((bytes_to_write + 1) * sizeof(char));
for (unsigned long long index = 0; index < bytes_to_write; index += 1) {
write_buffer[index] = 'a';
@ -495,7 +503,7 @@ COSMS_CORE_TEST_TEST(file_write_large_file,
return cosms_core_file_error_string(error);
}
error = cosms_core_file_open(&file, "tests/data/large-write-file.txt", COSMS_CORE_FILE_MODE_READ);
error = cosms_core_file_open(&file, "tests/data/large-write-file.bin", COSMS_CORE_FILE_MODE_READ);
if (error != COSMS_CORE_FILE_OK) {
free(write_buffer);
return cosms_core_file_error_string(error);
@ -532,7 +540,7 @@ COSMS_CORE_TEST_TEST(file_write_large_file,
COSMS_CORE_TEST_TEST(file_write_append_small_file,
struct cosms_core_file file;
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/small-write-file.txt", COSMS_CORE_FILE_MODE_WRITE | COSMS_CORE_FILE_MODE_APPEND);
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/small-write-file.bin", COSMS_CORE_FILE_MODE_WRITE | COSMS_CORE_FILE_MODE_APPEND);
if (error != COSMS_CORE_FILE_OK) {
return cosms_core_file_error_string(error);
}
@ -557,7 +565,7 @@ COSMS_CORE_TEST_TEST(file_write_append_small_file,
return cosms_core_file_error_string(error);
}
error = cosms_core_file_open(&file, "tests/data/small-write-file.txt", COSMS_CORE_FILE_MODE_READ);
error = cosms_core_file_open(&file, "tests/data/small-write-file.bin", COSMS_CORE_FILE_MODE_READ);
if (error != COSMS_CORE_FILE_OK) {
return cosms_core_file_error_string(error);
}
@ -585,7 +593,7 @@ COSMS_CORE_TEST_TEST(file_write_append_small_file,
COSMS_CORE_TEST_TEST(file_write_append_large_file,
struct cosms_core_file file;
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/large-write-file.txt", COSMS_CORE_FILE_MODE_WRITE | COSMS_CORE_FILE_MODE_APPEND);
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/large-write-file.bin", COSMS_CORE_FILE_MODE_WRITE | COSMS_CORE_FILE_MODE_APPEND);
if (error != COSMS_CORE_FILE_OK) {
return cosms_core_file_error_string(error);
}
@ -603,12 +611,12 @@ COSMS_CORE_TEST_TEST(file_write_append_large_file,
return cosms_core_file_error_string(error);
}
error = cosms_core_file_open(&file, "tests/data/large-write-file.txt", COSMS_CORE_FILE_MODE_READ);
error = cosms_core_file_open(&file, "tests/data/large-write-file.bin", COSMS_CORE_FILE_MODE_READ);
if (error != COSMS_CORE_FILE_OK) {
return cosms_core_file_error_string(error);
}
unsigned long long bytes_to_read = 5242880002ULL;
unsigned long long bytes_to_read = COSMS_CORE_FILE_TEST_LARGE_FILE_SIZE + 2;
unsigned long long bytes_read = 0;
char *read_buffer = NULL;
error = cosms_core_file_read_all(&file, &read_buffer, &bytes_read);
@ -648,7 +656,7 @@ COSMS_CORE_TEST_TEST(file_write_append_large_file,
COSMS_CORE_TEST_TEST(file_write_using_wrong_mode,
struct cosms_core_file file;
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/small-write-file.txt", COSMS_CORE_FILE_MODE_READ);
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/small-write-file.bin", COSMS_CORE_FILE_MODE_READ);
if (error != COSMS_CORE_FILE_OK) {
return cosms_core_file_error_string(error);
}
@ -673,12 +681,12 @@ COSMS_CORE_TEST_TEST(file_write_using_wrong_mode,
COSMS_CORE_TEST_TEST(file_write_full_file_using_wrong_mode,
struct cosms_core_file file;
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/large-write-file.txt", COSMS_CORE_FILE_MODE_READ);
CosmsCoreFileError error = cosms_core_file_open(&file, "tests/data/large-write-file.bin", COSMS_CORE_FILE_MODE_READ);
if (error != COSMS_CORE_FILE_OK) {
return cosms_core_file_error_string(error);
}
unsigned long long bytes_to_write = 5242880000ULL;
unsigned long long bytes_to_write = COSMS_CORE_FILE_TEST_LARGE_FILE_SIZE;
char *write_buffer = (char*)malloc((bytes_to_write + 1) * sizeof(char));
for (unsigned long long index = 0; index < bytes_to_write; index += 1) {
write_buffer[index] = 'a';
@ -703,7 +711,7 @@ COSMS_CORE_TEST_TEST(file_write_full_file_using_wrong_mode,
)
COSMS_CORE_TEST_TEST(file_delete_small_file,
CosmsCoreFileError error = cosms_core_file_delete("tests/data/small-write-file.txt");
CosmsCoreFileError error = cosms_core_file_delete("tests/data/small-delete-file.bin");
if (error != COSMS_CORE_FILE_OK) {
return cosms_core_file_error_string(error);
}
@ -712,7 +720,7 @@ COSMS_CORE_TEST_TEST(file_delete_small_file,
)
COSMS_CORE_TEST_TEST(file_delete_large_file,
CosmsCoreFileError error = cosms_core_file_delete("tests/data/large-write-file.txt");
CosmsCoreFileError error = cosms_core_file_delete("tests/data/large-delete-file.bin");
if (error != COSMS_CORE_FILE_OK) {
return cosms_core_file_error_string(error);
}