ocarina/tests/core/file.c
Anna Schumaker 1633946981 core/file: Check if a file is too new to be opened
I'm hitting this problem while developing 6.5, since file formats are
going to change.  Let's handle this situation gracefully rather than
segfaulting.

This patch changes versioning problems into fatal errors to prevent us
from overwriting data already on disk.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
2016-08-28 10:07:27 -04:00

201 lines
5.9 KiB
C

/*
* Copyright 2014 (c) Anna Schumaker.
*/
#include <core/file.h>
#include <core/version.h>
#include <tests/test.h>
#include <stdlib.h>
static void test_verify_constructor(struct file *file, gchar *fpath, gchar *ftmp)
{
test_equal((void *)file->f_file, NULL);
test_equal(file_version(file), 0);
test_equal(file->f_mode, OPEN_READ);
test_str_equal(file_path(file), fpath);
test_str_equal(file_write_path(file), ftmp);
}
static void test_invalid_file(struct file *file)
{
test_verify_constructor(file, "", "");
test_equal(file_open(file, OPEN_READ), (bool)false);
test_equal((void *)file->f_file, NULL);
test_equal(file_open(file, OPEN_WRITE), (bool)false);
test_equal((void *)file->f_file, NULL);
test_equal(file->f_mode, OPEN_READ);
test_equal(file_exists(file), (bool)false);
test_equal(test_data_file_exists(NULL), (bool)false);
}
static void test_null()
{
struct file fnull;
file_init(&fnull, NULL, 0, 0);
test_invalid_file(&fnull);
}
static void test_empty()
{
struct file fempty;
file_init(&fempty, "", 0, 0);
test_invalid_file(&fempty);
}
static void test_file()
{
struct file file = FILE_INIT("file.txt", 0, 0);
gchar *basepath, *filepath, *realpath;
basepath = g_strjoin("/", g_get_user_data_dir(), OCARINA_NAME, NULL);
filepath = g_strjoin("/", basepath, "file.txt", NULL);
realpath = g_strjoin("/", basepath, ".file.txt.tmp", NULL);
test_verify_constructor(&file, filepath, realpath);
test_equal(file_exists(&file), (bool)false);
test_equal(test_data_file_exists(NULL), (bool)false);
test_equal(file_open(&file, OPEN_READ), (bool)false);
test_equal(file_open(&file, OPEN_WRITE), (bool)true);
test_not_equal((void *)file.f_file, NULL);
test_equal(file.f_mode, OPEN_WRITE);
test_equal(file_open(&file, OPEN_WRITE), (bool)false);
test_equal(file_exists(&file), (bool)false);
file_close(&file);
test_equal((void *)file.f_file, NULL);
test_equal(file.f_mode, OPEN_WRITE);
test_equal(file_exists(&file), (bool)true);
test_equal(test_data_file_exists("file.txt"), (bool)true);
g_chmod(filepath, 0444);
test_equal(file_open(&file, OPEN_WRITE), (bool)false);
g_chmod(filepath, 0200);
test_equal(file_open(&file, OPEN_READ), (bool)false);
g_chmod(filepath, 0644);
test_equal(file_open(&file, OPEN_READ), (bool)true);
test_not_equal((void *)file.f_file, NULL);
test_equal(file.f_mode, OPEN_READ);
test_equal(file_open(&file, OPEN_READ), (bool)false);
test_equal(file_remove(&file), (bool)false);
test_equal(file_exists(&file), (bool)true);
file_close(&file);
test_equal(file_remove(&file), (bool)true);
test_equal(file_exists(&file), (bool)false);
g_free(filepath);
}
static void test_io()
{
struct file fout = FILE_INIT("file.txt", 1, 1);
struct file fin = FILE_INIT("file.txt", 2, 1);
char *res = NULL;
unsigned int i;
test_equal(file_open(&fout, OPEN_WRITE), (bool)true);
file_writef(&fout, "1 ABCDE\n");
file_writef(&fout, "2 FGHIJ KLMNO\n");
file_writef(&fout, "3 \n");
file_writef(&fout, "4 5 PQRST\n");
file_close(&fout);
test_equal(file_exists(&fout), (bool)true);
test_equal(file_open(&fin, OPEN_READ), (bool)true);
test_equal(file_version(&fin), 1);
test_equal(file_readf(&fin, "%u %ms\n", &i, &res), 2);
test_equal(i, 1);
test_equal(res, "ABCDE");
free(res);
test_equal(file_readf(&fin, "%u %m[^\n]\n", &i, &res), 2);
test_equal(i, 2);
test_equal(res, "FGHIJ KLMNO");
free(res);
test_equal(file_readf(&fin, "%u", &i), 1);
res = file_readl(&fin);
test_equal(i, 3);
test_equal(res, "");
free(res);
test_equal(file_readf(&fin, "%u %m[^\n]", &i, &res), 2);
test_equal(i, 4);
test_equal(res, "5 PQRST");
free(res);
file_close(&fin);
test_equal(file_version(&fin), 2);
}
/*static void test_versioning()
{
struct file fout = FILE_INIT("file.txt", 0, 0);
struct file fin = FILE_INIT("file.txt", 2, 1);
test_equal(file_open(&fout, OPEN_WRITE), (bool)true);
file_writef(&fout, "abcdefghijklmnopqrstuvwxyz");
file_close(&fout);
test_equal(file_exists(&fout), (bool)true);
test_equal(file_open(&fin, OPEN_READ), (bool)false);
test_equal((void *)fin.f_file, NULL);
}*/
static void test_cache()
{
struct cache_file file = CACHE_FILE_INIT("dir", "file.txt");
struct cache_file copy = CACHE_FILE_INIT("dir", "copy.txt");
gchar *basepath, *filepath, *writepath;
basepath = g_strjoin("/", g_get_user_cache_dir(), OCARINA_NAME, NULL);
filepath = g_strjoin("/", basepath, "dir", "file.txt", NULL);
writepath = g_strjoin("/", basepath, "dir", ".file.txt.tmp", NULL);
test_equal((void *)file.cf_file, NULL);
test_equal(file.cf_name, "file.txt");
test_equal(file.cf_subdir, "dir");
test_str_equal(cache_file_path(&file), filepath);
test_str_equal(cache_file_write_path(&file), writepath);
/* Test writing data to a cache file. */
test_equal(cache_file_exists(&file), (bool)false);
test_equal(cache_file_open(&file, OPEN_READ), (bool)false);
test_equal(cache_file_open(&file, OPEN_WRITE), (bool)true);
test_not_equal((void *)file.cf_file, NULL);
test_equal(cache_file_open(&file, OPEN_WRITE), (bool)false);
test_equal(cache_file_exists(&file), (bool)false);
test_equal(cache_file_write(&file, "abcde", 5), 5);
cache_file_close(&file);
test_equal((void *)file.cf_file, NULL);
test_equal(cache_file_exists(&file), (bool)true);
/* Test importing a file into the cache. */
test_equal(cache_file_exists(&copy), (bool)false);
test_equal(cache_file_import(&copy, filepath), (bool)false);
test_equal(cache_file_exists(&copy), (bool)false);
test_equal(cache_file_open(&copy, OPEN_WRITE), (bool)true);
test_equal(cache_file_import(&copy, NULL), (bool)false);
test_equal(cache_file_import(&copy, filepath), (bool)true);
test_equal(cache_file_exists(&copy), (bool)false);
cache_file_close(&copy);
test_equal(cache_file_exists(&copy), (bool)true);
}
DECLARE_UNIT_TESTS(
UNIT_TEST("File (Path = NULL)", test_null),
UNIT_TEST("File (Path = \"\")", test_empty),
UNIT_TEST("File (Path = \"file.txt\")", test_file),
UNIT_TEST("File I/O", test_io),
//UNIT_TEST("File Versioning", test_versioning),
UNIT_TEST("File Cache", test_cache),
);