437 lines
13 KiB
C
437 lines
13 KiB
C
|
/*
|
||
|
|
||
|
Copy Right FourTech LLC, 2016
|
||
|
All Rights Are Reserved
|
||
|
|
||
|
A test bed for a cross platform file tracking reliability layer.
|
||
|
Developed for the use cases in 4coder, but I anticipate that this
|
||
|
will be a general problem for me. - Allen Webster
|
||
|
|
||
|
Created on: 20.07.2016
|
||
|
|
||
|
*/
|
||
|
|
||
|
// TOP
|
||
|
|
||
|
#define FILE_TRACK_MAIN
|
||
|
|
||
|
#include "4tech_file_track.h"
|
||
|
#include "4tech_file_track_win32.c"
|
||
|
|
||
|
#include "filetrack_test.c"
|
||
|
|
||
|
#include <stdint.h>
|
||
|
#include <assert.h>
|
||
|
#include <string.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
|
||
|
#define FILE_TRACK_TEST_DIR1 "w:/filetrack/data/"
|
||
|
#define FILE_TRACK_TEST_DIR2 "w:/filetrack/data2/"
|
||
|
|
||
|
#define FAKE_TRACK_TEST_DIR "w:/filetrack/data1000/"
|
||
|
|
||
|
#define ALT_NAME_TEST_DIR1 "c:/work/filetrack/data/"
|
||
|
#define ALT_NAME_TEST_DIR2 "c:/work/filetrack/data2/"
|
||
|
|
||
|
static char * test_files[] = {
|
||
|
FILE_TRACK_TEST_DIR1"autotab.cpp",
|
||
|
FILE_TRACK_TEST_DIR1"basic.cpp",
|
||
|
FILE_TRACK_TEST_DIR1"basic.txt",
|
||
|
FILE_TRACK_TEST_DIR1"cleanme.cpp",
|
||
|
FILE_TRACK_TEST_DIR1"emptyfile.txt",
|
||
|
FILE_TRACK_TEST_DIR1"lexer_test.cpp",
|
||
|
FILE_TRACK_TEST_DIR1"lexer_test2.cpp",
|
||
|
FILE_TRACK_TEST_DIR1"lexer_test3.cpp",
|
||
|
FILE_TRACK_TEST_DIR1"saveas.txt",
|
||
|
FILE_TRACK_TEST_DIR1"test_large.cpp",
|
||
|
|
||
|
FILE_TRACK_TEST_DIR2"autotab.cpp",
|
||
|
FILE_TRACK_TEST_DIR2"basic.cpp",
|
||
|
FILE_TRACK_TEST_DIR2"basic.txt",
|
||
|
FILE_TRACK_TEST_DIR2"cleanme.cpp",
|
||
|
FILE_TRACK_TEST_DIR2"emptyfile.txt",
|
||
|
FILE_TRACK_TEST_DIR2"lexer_test.cpp",
|
||
|
FILE_TRACK_TEST_DIR2"lexer_test2.cpp",
|
||
|
FILE_TRACK_TEST_DIR2"lexer_test3.cpp",
|
||
|
FILE_TRACK_TEST_DIR2"saveas.txt",
|
||
|
FILE_TRACK_TEST_DIR2"test_large.cpp",
|
||
|
};
|
||
|
|
||
|
static char * test_alt_files[] = {
|
||
|
ALT_NAME_TEST_DIR1"autotab.cpp",
|
||
|
ALT_NAME_TEST_DIR1"basic.cpp",
|
||
|
ALT_NAME_TEST_DIR1"basic.txt",
|
||
|
ALT_NAME_TEST_DIR1"cleanme.cpp",
|
||
|
ALT_NAME_TEST_DIR1"emptyfile.txt",
|
||
|
ALT_NAME_TEST_DIR1"lexer_test.cpp",
|
||
|
ALT_NAME_TEST_DIR1"lexer_test2.cpp",
|
||
|
ALT_NAME_TEST_DIR1"lexer_test3.cpp",
|
||
|
ALT_NAME_TEST_DIR1"saveas.txt",
|
||
|
ALT_NAME_TEST_DIR1"test_large.cpp",
|
||
|
|
||
|
ALT_NAME_TEST_DIR2"autotab.cpp",
|
||
|
ALT_NAME_TEST_DIR2"basic.cpp",
|
||
|
ALT_NAME_TEST_DIR2"basic.txt",
|
||
|
ALT_NAME_TEST_DIR2"cleanme.cpp",
|
||
|
ALT_NAME_TEST_DIR2"emptyfile.txt",
|
||
|
ALT_NAME_TEST_DIR2"lexer_test.cpp",
|
||
|
ALT_NAME_TEST_DIR2"lexer_test2.cpp",
|
||
|
ALT_NAME_TEST_DIR2"lexer_test3.cpp",
|
||
|
ALT_NAME_TEST_DIR2"saveas.txt",
|
||
|
ALT_NAME_TEST_DIR2"test_large.cpp",
|
||
|
};
|
||
|
|
||
|
static char * fake_files[] = {
|
||
|
FAKE_TRACK_TEST_DIR"autotab.cpp",
|
||
|
FAKE_TRACK_TEST_DIR"basic.cpp",
|
||
|
FAKE_TRACK_TEST_DIR"basic.txt",
|
||
|
FAKE_TRACK_TEST_DIR"cleanme.cpp",
|
||
|
FAKE_TRACK_TEST_DIR"emptyfile.txt",
|
||
|
FAKE_TRACK_TEST_DIR"lexer_test.cpp",
|
||
|
FAKE_TRACK_TEST_DIR"lexer_test2.cpp",
|
||
|
FAKE_TRACK_TEST_DIR"lexer_test3.cpp",
|
||
|
FAKE_TRACK_TEST_DIR"saveas.txt",
|
||
|
FAKE_TRACK_TEST_DIR"test_large.cpp",
|
||
|
};
|
||
|
|
||
|
#define ArrayCount(a) ((sizeof(a))/(sizeof(*a)))
|
||
|
|
||
|
typedef struct{
|
||
|
File_Index unique_file_index;
|
||
|
File_Time time;
|
||
|
} MyFileThing;
|
||
|
|
||
|
void test_body_A(int32_t size1, int32_t size2){
|
||
|
void *mem1 = malloc(size1);
|
||
|
void *mem2 = malloc(size2);
|
||
|
memset(mem1, 0, size1);
|
||
|
|
||
|
File_Track_System track = {0};
|
||
|
int32_t result = init_track_system(&track,
|
||
|
mem1, size1,
|
||
|
mem2, size2);
|
||
|
assert(result == FileTrack_Good);
|
||
|
|
||
|
MyFileThing my_file_things[1000];
|
||
|
memset(my_file_things, 0, sizeof(my_file_things));
|
||
|
|
||
|
// NOTE(allen): track in all the test files
|
||
|
for (int32_t i = 0;
|
||
|
i < ArrayCount(test_files);
|
||
|
++i){
|
||
|
char *filename = test_files[i];
|
||
|
|
||
|
File_Index new_file = zero_file_index();
|
||
|
File_Time new_time = 0;
|
||
|
int32_t result = begin_tracking_file(&track, filename, &new_file, &new_time);
|
||
|
while (result != FileTrack_Good){
|
||
|
|
||
|
switch (result){
|
||
|
case FileTrack_OutOfTableMemory:
|
||
|
{
|
||
|
int32_t new_mem_size = size1*2;
|
||
|
void *new_mem = malloc(new_mem_size);
|
||
|
|
||
|
memset(new_mem, 0, new_mem_size);
|
||
|
move_track_system(&track, new_mem, new_mem_size);
|
||
|
|
||
|
free(mem1);
|
||
|
size1 = new_mem_size;
|
||
|
mem1 = new_mem;
|
||
|
}break;
|
||
|
|
||
|
case FileTrack_OutOfListenerMemory:
|
||
|
{
|
||
|
size2 *= 2;
|
||
|
void *new_mem = malloc(size2);
|
||
|
memset(new_mem, 0, size2);
|
||
|
expand_track_system_listeners(&track, new_mem, size2);
|
||
|
}break;
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
Assert(result == FileTrack_Good);
|
||
|
}break;
|
||
|
}
|
||
|
|
||
|
result = begin_tracking_file(&track, filename, &new_file, &new_time);
|
||
|
}
|
||
|
|
||
|
my_file_things[i].unique_file_index = new_file;
|
||
|
my_file_things[i].time = new_time;
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): track in fake directories
|
||
|
for (int32_t i = 0;
|
||
|
i < ArrayCount(fake_files);
|
||
|
++i){
|
||
|
File_Index new_file = zero_file_index();
|
||
|
File_Time new_time = 0;
|
||
|
|
||
|
char *filename = fake_files[i];
|
||
|
|
||
|
int32_t result = begin_tracking_file(&track, filename, &new_file, &new_time);
|
||
|
assert(result == FileTrack_FileNotFound);
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): track in already tracked files
|
||
|
for (int32_t i = 0;
|
||
|
i < ArrayCount(test_files);
|
||
|
++i){
|
||
|
File_Index new_file = zero_file_index();
|
||
|
File_Time new_time = 0;
|
||
|
|
||
|
char *filename = test_files[i];
|
||
|
|
||
|
int32_t result = begin_tracking_file(&track, filename, &new_file, &new_time);
|
||
|
assert(result == FileTrack_FileAlreadyTracked);
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): track in already tracked files via alt-names
|
||
|
for (int32_t i = 0;
|
||
|
i < ArrayCount(test_alt_files);
|
||
|
++i){
|
||
|
File_Index new_file = zero_file_index();
|
||
|
File_Time new_time = 0;
|
||
|
|
||
|
char *filename = test_alt_files[i];
|
||
|
|
||
|
int32_t result = begin_tracking_file(&track, filename, &new_file, &new_time);
|
||
|
assert(result == FileTrack_FileAlreadyTracked);
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): each file is still up to date
|
||
|
for (int32_t i = 0;
|
||
|
i < ArrayCount(test_files);
|
||
|
++i){
|
||
|
File_Time time = 0;
|
||
|
File_Index index = my_file_things[i].unique_file_index;
|
||
|
|
||
|
get_tracked_file_time(&track, index, &time);
|
||
|
|
||
|
assert(time == my_file_things[i].time);
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): can still get index from file name
|
||
|
for (int32_t i = 0;
|
||
|
i < ArrayCount(test_files);
|
||
|
++i){
|
||
|
File_Index index = my_file_things[i].unique_file_index;
|
||
|
|
||
|
File_Index result_index1 = zero_file_index();
|
||
|
char *filename1 = test_files[i];
|
||
|
get_tracked_file_index(&track, filename1, &result_index1);
|
||
|
|
||
|
File_Index result_index2 = zero_file_index();
|
||
|
char *filename2 = test_alt_files[i];
|
||
|
get_tracked_file_index(&track, filename2, &result_index2);
|
||
|
|
||
|
assert(file_index_eq(result_index1, index));
|
||
|
assert(file_index_eq(result_index2, index));
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): rewrite all of the files
|
||
|
for (int32_t i = 0;
|
||
|
i < ArrayCount(test_files);
|
||
|
++i){
|
||
|
char *filename = test_files[i];
|
||
|
|
||
|
test_rewrite_file_in_child_proc(filename);
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): each file is behind
|
||
|
for (int32_t i = 0;
|
||
|
i < ArrayCount(test_files);
|
||
|
++i){
|
||
|
File_Time time = 0;
|
||
|
File_Index index = my_file_things[i].unique_file_index;
|
||
|
|
||
|
get_tracked_file_time(&track, index, &time);
|
||
|
|
||
|
assert(my_file_things[i].time < time);
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): poll the tracking system for changed files
|
||
|
for (;;){
|
||
|
File_Index index = zero_file_index();
|
||
|
File_Time time = 0;
|
||
|
|
||
|
int32_t result = get_change_event(&track, &index);
|
||
|
|
||
|
if (result == FileTrack_NoMoreEvents){
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
result = get_tracked_file_time(&track, index, &time);
|
||
|
|
||
|
for (int32_t i = 0;
|
||
|
i < ArrayCount(test_files);
|
||
|
++i){
|
||
|
File_Index my_index = my_file_things[i].unique_file_index;
|
||
|
if (file_index_eq(my_index, index)){
|
||
|
my_file_things[i].time = time;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): each file is still up to date (episode 2)
|
||
|
for (int32_t i = 0;
|
||
|
i < ArrayCount(test_files);
|
||
|
++i){
|
||
|
File_Time time = 0;
|
||
|
File_Index index = my_file_things[i].unique_file_index;
|
||
|
|
||
|
get_tracked_file_time(&track, index, &time);
|
||
|
|
||
|
assert(time == my_file_things[i].time);
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): rewrite each file myself
|
||
|
for (int32_t i = 0;
|
||
|
i < ArrayCount(test_files);
|
||
|
++i){
|
||
|
File_Index index = my_file_things[i].unique_file_index;
|
||
|
File_Time time = test_rewrite_file(&track, index);
|
||
|
|
||
|
my_file_things[i].time = time;
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): check there are no changed file events
|
||
|
{
|
||
|
File_Index index = zero_file_index();
|
||
|
|
||
|
int32_t result = get_change_event(&track, &index);
|
||
|
assert(result == FileTrack_NoMoreEvents);
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): rewrite half of the files twice
|
||
|
int32_t mid_point = ArrayCount(test_files) / 2;
|
||
|
for (int32_t i = 0;
|
||
|
i < mid_point;
|
||
|
++i){
|
||
|
char *filename = test_files[i];
|
||
|
|
||
|
test_rewrite_file_in_child_proc(filename);
|
||
|
}
|
||
|
|
||
|
for (int32_t i = 0;
|
||
|
i < mid_point;
|
||
|
++i){
|
||
|
char *filename = test_files[i];
|
||
|
|
||
|
test_rewrite_file_in_child_proc(filename);
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): check number of events equals mid_point
|
||
|
int32_t count = 0;
|
||
|
for (;;){
|
||
|
File_Index index = zero_file_index();
|
||
|
File_Time time = 0;
|
||
|
|
||
|
int32_t result = get_change_event(&track, &index);
|
||
|
|
||
|
if (result == FileTrack_NoMoreEvents){
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
result = get_tracked_file_time(&track, index, &time);
|
||
|
|
||
|
++count;
|
||
|
|
||
|
for (int32_t i = 0;
|
||
|
i < ArrayCount(test_files);
|
||
|
++i){
|
||
|
File_Index my_index = my_file_things[i].unique_file_index;
|
||
|
if (file_index_eq(my_index, index)){
|
||
|
my_file_things[i].time = time;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
assert(count == mid_point);
|
||
|
|
||
|
// NOTE(allen): untrack half of the files
|
||
|
for (int32_t i = 0;
|
||
|
i < mid_point;
|
||
|
++i){
|
||
|
File_Index stop_file = my_file_things[i].unique_file_index;
|
||
|
stop_tracking_file(&track, stop_file);
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): untrack the same files again
|
||
|
for (int32_t i = 0;
|
||
|
i < mid_point;
|
||
|
++i){
|
||
|
File_Index stop_file = my_file_things[i].unique_file_index;
|
||
|
int32_t result = stop_tracking_file(&track, stop_file);
|
||
|
assert(result == FileTrack_FileNotTracked);
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): make sure the number of remaining files is correct
|
||
|
{
|
||
|
int32_t track_count = 0;
|
||
|
count_tracked_files(&track, &track_count);
|
||
|
assert(track_count == (ArrayCount(test_files) - mid_point));
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): untrack the rest of the files
|
||
|
for (int32_t i = mid_point;
|
||
|
i < ArrayCount(test_files);
|
||
|
++i){
|
||
|
File_Index stop_file = my_file_things[i].unique_file_index;
|
||
|
stop_tracking_file(&track, stop_file);
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): make sure the system is empty
|
||
|
{
|
||
|
int32_t track_count = 0;
|
||
|
count_tracked_files(&track, &track_count);
|
||
|
assert(track_count == 0);
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): finish using the track system
|
||
|
{
|
||
|
int32_t result = shut_down_track_system(&track);
|
||
|
assert(result == FileTrack_Good);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// NOTE(allen): test basic tracking logic
|
||
|
void test_1(void){
|
||
|
int32_t size1 = (16 << 10);
|
||
|
int32_t size2 = (16 << 10);
|
||
|
test_body_A(size1, size2);
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): test memory expansion system for tables
|
||
|
void test_2(void){
|
||
|
int32_t size1 = (1 << 10);
|
||
|
int32_t size2 = (16 << 10);
|
||
|
test_body_A(size1, size2);
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): test memory expansion system for listening nodes
|
||
|
void test_3(void){
|
||
|
int32_t size1 = (16 << 10);
|
||
|
int32_t size2 = (5 << 10);
|
||
|
test_body_A(size1, size2);
|
||
|
}
|
||
|
|
||
|
// NOTE(allen): test both memory expansion systems
|
||
|
void test_4(void){
|
||
|
int32_t size1 = (1 << 10);
|
||
|
int32_t size2 = (5 << 10);
|
||
|
test_body_A(size1, size2);
|
||
|
}
|
||
|
|
||
|
int main(int argc, char **argv){
|
||
|
test_4();
|
||
|
return(0);
|
||
|
}
|
||
|
|
||
|
// BOTTOM
|
||
|
|