stasis-aries-wal/test/stasis/check_rangeTracker.c

445 lines
11 KiB
C

#include "../check_includes.h"
#include <stasis/transactional.h>
#include <stasis/io/rangeTracker.h>
#include <stasis/util/random.h>
#include <assert.h>
#include <sys/time.h>
#include <time.h>
#define LOG_NAME "check_rangeTracker.log"
#define QUANTIZATION 7
void rangeTrackerFreeRet(range ** ret) {
for(int i = 0; ret[i]; i++) {
free(ret[i]);
}
free(ret);
}
void printRT(rangeTracker * rt) {
const transition ** ts = rangeTrackerEnumerate(rt);
int i = 0;
printf("Range tracker:\n");
while(ts[i]) {
printf("%s\n", transitionToString(ts[i]));
i++;
}
free (ts);
}
void check_no_overlap(range * r, int * explicit_pins) {
for(int j = r->start; j < r->stop; j++) {
assert(!explicit_pins[j]);
}
}
void check_overlap(range * r, int * explicit_pins) {
assert(!(r->start % QUANTIZATION));
assert(!(r->stop % QUANTIZATION));
int overlap = 0;
for(int j = r->start; j < r->stop; j++) {
if(explicit_pins[j]) { overlap = 1; }
if(! (j+1 % QUANTIZATION)) {
assert(overlap);
overlap = 0;
}
}
}
START_TEST(rangeTracker_smokeTest) {
rangeTracker * rt = rangeTrackerInit(QUANTIZATION);
const transition ** ts = rangeTrackerEnumerate(rt);
assert(ts[0] == 0);
free(ts);
// printRT(rt);
range r;
r.start = 10;
r.stop = 100;
rangeTrackerFreeRet(rangeTrackerAdd(rt, &r));
// printRT(rt);
ts = rangeTrackerEnumerate(rt);
// 10 20 80 90 100
// | | | | |
// |1111|11111111111111|1111|111|
// | | | | |
assert(ts[0]->pos == 10 && ts[0]->delta == 1 && ts[0]->pins == 0 &&
ts[1]->pos == 100&& ts[1]->delta == -1 && ts[1]->pins == 1 && !ts[2]);
free(ts);
r.start = 20;
r.stop = 80;
rangeTrackerFreeRet(rangeTrackerRemove(rt, &r));
// printRT(rt);
ts = rangeTrackerEnumerate(rt);
// 10 20 80 90 100
// | | | | |
// |1111| |1111|111|
// | | | | |
assert(ts[0]->pos == 10 && ts[0]->delta == 1 && ts[0]->pins == 0 &&
ts[1]->pos == 20 && ts[1]->delta == -1 && ts[1]->pins == 1 &&
ts[2]->pos == 80 && ts[2]->delta == 1 && ts[2]->pins == 0 &&
ts[3]->pos == 100&& ts[3]->delta == -1 && ts[3]->pins == 1 && !ts[4]);
rangeTrackerFreeRet(rangeTrackerAdd(rt, &r));
// printRT(rt);
free(ts);
ts = rangeTrackerEnumerate(rt);
// 10 20 80 90 100
// | | | | |
// |1111|11111111111111|1111|111|
// | | | | |
assert(ts[0]->pos == 10 && ts[0]->delta == 1 && ts[0]->pins == 0 &&
ts[1]->pos == 100&& ts[1]->delta == -1 && ts[1]->pins == 1 && !ts[2]);
rangeTrackerFreeRet(rangeTrackerAdd(rt, &r));
// printRT(rt);
free(ts);
ts = rangeTrackerEnumerate(rt);
// 10 20 80 90 100
// | | | | |
// |1111|22222222222222|1111|111|
// | | | | |
assert(ts[0]->pos == 10 && ts[0]->delta == 1 && ts[0]->pins == 0 &&
ts[1]->pos == 20 && ts[1]->delta == 1 && ts[1]->pins == 1 &&
ts[2]->pos == 80 && ts[2]->delta == -1 && ts[2]->pins == 2 &&
ts[3]->pos == 100&& ts[3]->delta == -1 && ts[3]->pins == 1 && !ts[4]);
free(ts);
rangeTrackerFreeRet(rangeTrackerRemove(rt, &r));
ts = rangeTrackerEnumerate(rt);
// 10 20 80 90 100
// | | | | |
// |1111|11111111111111|1111|111|
// | | | | |
assert(ts[0]->pos == 10 && ts[0]->delta == 1 && ts[0]->pins == 0 &&
ts[1]->pos == 100&& ts[1]->delta == -1 && ts[1]->pins == 1 && !ts[2]);
free(ts);
rangeTrackerFreeRet(rangeTrackerRemove(rt, &r));
// printRT(rt);
ts = rangeTrackerEnumerate(rt);
// 10 20 80 90 100
// | | | | |
// |1111| |1111|111|
// | | | | |
assert(ts[0]->pos == 10 && ts[0]->delta == 1 && ts[0]->pins == 0 &&
ts[1]->pos == 20 && ts[1]->delta == -1 && ts[1]->pins == 1 &&
ts[2]->pos == 80 && ts[2]->delta == 1 && ts[2]->pins == 0 &&
ts[3]->pos == 100&& ts[3]->delta == -1 && ts[3]->pins == 1 && !ts[4]);
free(ts);
r.start = 80;
r.stop = 90;
rangeTrackerFreeRet(rangeTrackerAdd(rt, &r));
// printRT(rt);
ts = rangeTrackerEnumerate(rt);
// 10 20 80 90 100
// | | | | |
// |1111| |2222|111|
// | | | | |
assert(ts[0]->pos == 10 && ts[0]->delta == 1 && ts[0]->pins == 0 &&
ts[1]->pos == 20 && ts[1]->delta == -1 && ts[1]->pins == 1 &&
ts[2]->pos == 80 && ts[2]->delta == 2 && ts[2]->pins == 0 &&
ts[3]->pos == 90 && ts[3]->delta == -1 && ts[3]->pins == 2 &&
ts[4]->pos == 100&& ts[4]->delta == -1 && ts[4]->pins == 1 && !ts[5]);
free(ts);
r.start = 80;
r.stop = 100;
rangeTrackerFreeRet(rangeTrackerRemove(rt, &r));
// printRT(rt);
ts = rangeTrackerEnumerate(rt);
// 10 20 80 90 100
// | | | | |
// |1111| |1111| |
// | | | | |
assert(ts[0]->pos == 10 && ts[0]->delta == 1 && ts[0]->pins == 0 &&
ts[1]->pos == 20 && ts[1]->delta == -1 && ts[1]->pins == 1 &&
ts[2]->pos == 80 && ts[2]->delta == 1 && ts[2]->pins == 0 &&
ts[3]->pos == 90 && ts[3]->delta == -1 && ts[3]->pins == 1 && !ts[4]);
free(ts);
r.start = 10;
r.stop = 20;
rangeTrackerFreeRet(rangeTrackerRemove(rt, &r));
// printRT(rt);
ts = rangeTrackerEnumerate(rt);
// 10 20 80 90 100
// | | | | |
// | | |1111| |
// | | | | |
assert(ts[0]->pos == 80 && ts[0]->delta == 1 && ts[0]->pins == 0 &&
ts[1]->pos == 90 && ts[1]->delta == -1 && ts[1]->pins == 1 && !ts[2]);
free(ts);
r.start = 80;
r.stop = 90;
rangeTrackerFreeRet(rangeTrackerRemove(rt, &r));
// printRT(rt);
ts = rangeTrackerEnumerate(rt);
// 10 20 80 90 100
// | | | | |
// | | | | |
// | | | | |
assert(!ts[0]);
free(ts);
rangeTrackerDeinit(rt);
}
END_TEST
#define RANGE_SIZE 1000
#define ITERATIONS 10000 //1000
#define RANGE_COUNT 1000 // 100
void randomRange(range * r) {
long start = stasis_util_random64(RANGE_SIZE-1);
long len = 1+stasis_util_random64(RANGE_SIZE - start - 1);
r->start = start;
r->stop = start + len;
assert(r->start < RANGE_SIZE);
assert(r->stop < RANGE_SIZE);
}
void checkRangeTrackerConsistency(rangeTracker * rt) {
const transition ** t = rangeTrackerEnumerate(rt);
int pins = 0;
long pos = -1;
int i = 0;
while(t[i]) {
assert(pos < t[i]->pos);
assert(pins == t[i]->pins);
assert(pins >= 0);
assert(t[i]->delta);
pos = t[i]->pos;
pins += t[i]->delta;
i++;
}
assert(pins == 0);
free(t);
}
START_TEST (rangeTracker_randomTest) {
struct timeval time;
gettimeofday(&time,0);
int * explicit_pins = stasis_calloc(RANGE_SIZE, int);
long seed = time.tv_usec + time.tv_sec * 1000000; //1170807889195512; //time.tv_usec + time.tv_sec * 1000000; //1170729550013502; //time.tv_usec + time.tv_sec * 1000000;// 1170727703805787; // 1170810757441165; 1170811024737237; 1171329519584370;
printf("\nSeed = %ld\n", seed);
srandom(seed);
range ** r_arry;
range * ranges = stasis_malloc(RANGE_COUNT, range);
int * pins = stasis_calloc(RANGE_COUNT, int);
rangeTracker * rt = rangeTrackerInit(QUANTIZATION);
for(long i = 0; i < RANGE_COUNT; i++) {
randomRange(&(ranges[i]));
}
char * s;
for(long i = 0; i < ITERATIONS; i++) {
int range = stasis_util_random64(RANGE_COUNT);
switch(stasis_util_random64(3)) {
case 0: { // add range
s = rangeToString(&ranges[range]);
// printf("pin %s\n", s);
free(s);
r_arry = rangeTrackerAdd(rt, &ranges[range]);
for(int i = 0; r_arry[i]; i++) {
check_no_overlap(r_arry[i], explicit_pins);
}
for(int i = ranges[range].start; i < ranges[range].stop; i++) {
explicit_pins[i]++;
}
for(int i = 0; r_arry[i]; i++) {
s = rangeToString(r_arry[i]);
// printf(" add returned %s\n", s);
check_overlap(r_arry[i], explicit_pins);
assert(r_arry[i]->start >=
rangeTrackerRoundDown(ranges[range].start, QUANTIZATION));
assert(r_arry[i]->stop <=
rangeTrackerRoundUp(ranges[range].stop, QUANTIZATION));
free(s);
free(r_arry[i]);
}
free(r_arry);
pins[range]++;
checkRangeTrackerConsistency(rt);
break;
}
case 1: { // del range
if(pins[range]) {
s = rangeToString(&ranges[range]);
// printf("unpin %s\n", s);
free(s);
r_arry = rangeTrackerRemove(rt, &ranges[range]);
for(int i = 0; r_arry[i]; i++) {
check_overlap(r_arry[i], explicit_pins);
}
for(int i = ranges[range].start; i < ranges[range].stop; i++) {
explicit_pins[i]--;
assert(explicit_pins[i] >= 0);
}
// return value should no longer overlap pins.
for(int i = 0; r_arry[i]; i++) {
check_no_overlap(r_arry[i], explicit_pins);
// for(int j = r_arry[i]->start; j < r_arry[i]->stop; j++) {
// assert(!explicit_pins[j]);
// }
s = rangeToString(r_arry[i]);
assert(r_arry[i]->start >=
rangeTrackerRoundDown(ranges[range].start, QUANTIZATION));
assert(r_arry[i]->stop <=
rangeTrackerRoundUp(ranges[range].stop, QUANTIZATION));
// printf(" del returned %s\n", s);
free(s);
free(r_arry[i]);
}
free(r_arry);
pins[range]--;
}
checkRangeTrackerConsistency(rt);
break;
}
case 2: { // change range
if(!stasis_util_random64(100)) {
for(long i = 0; i < RANGE_COUNT; i++) {
if(!pins[i]) {
randomRange(&ranges[i]);
}
}
}
break;
}
default:
abort();
}
}
for(long i = 0; i < RANGE_COUNT; i++) {
while(pins[i]) {
s = rangeToString(&ranges[i]);
// printf("unpin %s\n", s);
free(s);
range ** r_arry = rangeTrackerRemove(rt, &ranges[i]);
for(int j = 0; r_arry[j]; j++) {
check_overlap(r_arry[j], explicit_pins);
}
for(int j = ranges[i].start; j < ranges[i].stop; j++) {
explicit_pins[j]--;
assert(explicit_pins[j] >= 0);
}
for(int j = 0; r_arry[j]; j++) {
s = rangeToString(r_arry[j]);
// printf(" del returned %s\n", s);
check_no_overlap(r_arry[j], explicit_pins);
free(s);
free(r_arry[j]);
}
free(r_arry);
pins[i]--;
}
}
for(int i =0 ; i < RANGE_SIZE; i++ ) {
assert(explicit_pins[i] == 0);
}
free (ranges);
free (pins);
rangeTrackerDeinit(rt);
} END_TEST
/**
Add suite declarations here
*/
Suite * check_suite(void) {
Suite *s = suite_create("rangeTracker");
/* Begin a new test */
TCase *tc = tcase_create("rangeTracker");
tcase_set_timeout(tc, 600); // ten minute timeout
/* Sub tests are added, one per line, here */
tcase_add_test(tc, rangeTracker_smokeTest);
tcase_add_test(tc, rangeTracker_randomTest);
/* --------------------------------------------- */
tcase_add_checked_fixture(tc, setup, teardown);
suite_add_tcase(s, tc);
return s;
}
#include "../check_setup.h"