/* * sophia database * sphia.org * * Copyright (c) Dmitry Simonenko * BSD License */ #include #include "test.h" static char *dbrep = "./rep"; static inline int cmp(char *a, size_t asz, char *b, size_t bsz, void *arg) { register uint32_t av = *(uint32_t*)a; register uint32_t bv = *(uint32_t*)b; if (av == bv) return 0; return (av > bv) ? 1 : -1; } static void recover_log_set_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 1; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); size_t vsize = 0; void *vp = NULL; k = 1; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == v ); free(vp); k = 2; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == v ); free(vp); k = 3; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == v ); free(vp); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_log_replace_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 1; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); v = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); size_t vsize = 0; void *vp = NULL; k = 1; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 3 ); free(vp); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_log_set_get_replace_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 1; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); size_t vsize = 0; void *vp = NULL; k = 1; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 1 ); free(vp); v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); vsize = 0; vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 2 ); free(vp); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); vsize = 0; vp = NULL; k = 1; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 2 ); free(vp); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_log_delete_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 1; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_delete(db, &k, sizeof(k)) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); size_t vsize = 0; void *vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_log_delete_set_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 1; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_delete(db, &k, sizeof(k)) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); size_t vsize = 0; void *vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 0 ); v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); vsize = 0; vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 2 ); free(vp); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_log_fetch_gte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); void *cur = sp_cursor(db, SPGTE, NULL, 0); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_log_fetch_lte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); void *cur = sp_cursor(db, SPLTE, NULL, 0); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_log_fetch_kgte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 2; void *cur = sp_cursor(db, SPGTE, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_log_fetch_kgt(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 2; void *cur = sp_cursor(db, SPGT, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_log_fetch_klte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 2; void *cur = sp_cursor(db, SPLTE, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_log_fetch_klt(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 2; void *cur = sp_cursor(db, SPLT, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_keysize(cur) == 0 ); t( sp_key(cur) == NULL ); t( sp_valuesize(cur) == 0 ); t( sp_value(cur) == NULL ); t( sp_fetch(cur) == 0 ); t( sp_keysize(cur) == 0 ); t( sp_key(cur) == NULL ); t( sp_valuesize(cur) == 0 ); t( sp_value(cur) == NULL ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_log_n_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 0, v; while (k < 12) { v = k; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k++; } t( sp_destroy(db) == 0 ); t( exists(dbrep, 1, "log") == 1 ); db = sp_open(env); t( db != NULL ); k = 0; while (k < 12) { size_t vsize = 0; void *vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == k ); free(vp); k++; } t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_log_n_replace(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( exists(dbrep, 1, "log.incomplete") == 1 ); t( db != NULL ); uint32_t k = 0, v = 1; while (k < 12) { t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k++; } k = 0; v = 2; while (k < 12) { t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k++; } t( sp_destroy(db) == 0 ); t( exists(dbrep, 1, "log") == 1 ); db = sp_open(env); t( exists(dbrep, 1, "log") == 1 ); t( exists(dbrep, 2, "log.incomplete") == 1 ); t( db != NULL ); k = 0; while (k < 12) { size_t vsize = 0; void *vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 2 ); free(vp); k++; } t( sp_destroy(db) == 0 ); t( exists(dbrep, 1, "log") == 1 ); t( exists(dbrep, 2, "log") == 0 ); t( exists(dbrep, 2, "log.incomplete") == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_page_set_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 1; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( exists(dbrep, 1, "log.incomplete") == 0 ); t( exists(dbrep, 1, "log") == 0 ); t( exists(dbrep, 1, "db") == 1 ); t( exists(dbrep, 2, "log.incomplete") == 1 ); t( sp_destroy(db) == 0 ); t( exists(dbrep, 1, "db") == 1 ); t( exists(dbrep, 2, "log") == 0 ); t( exists(dbrep, 2, "log.incomplete") == 0 ); db = sp_open(env); t( db != NULL ); size_t vsize = 0; void *vp = NULL; k = 1; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == v ); free(vp); k = 2; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == v ); free(vp); k = 3; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == v ); free(vp); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_page_replace_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 1; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); v = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( exists(dbrep, 1, "log.incomplete") == 0 ); t( exists(dbrep, 1, "log") == 0 ); t( exists(dbrep, 2, "log.incomplete") == 1 ); t( exists(dbrep, 2, "log") == 0 ); t( exists(dbrep, 1, "db") == 1 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); size_t vsize = 0; void *vp = NULL; k = 1; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 3 ); free(vp); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_page_set_get_replace_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 1; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); v = 8; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); size_t vsize = 0; void *vp = NULL; k = 1; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 8 ); free(vp); v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k = 2; v = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); vsize = 0; vp = NULL; t( sp_ctl(db, SPMERGEFORCE) == 0 ); k = 1; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 2 ); free(vp); k = 2; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 3 ); free(vp); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); vsize = 0; vp = NULL; k = 1; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 2 ); free(vp); k = 2; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 3 ); free(vp); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_page_delete_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 1; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_delete(db, &k, sizeof(k)) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( exists(dbrep, 1, "log.incomplete") == 0 ); t( exists(dbrep, 1, "log") == 0 ); t( exists(dbrep, 1, "db.incomplete") == 0 ); t( exists(dbrep, 1, "db") == 0 ); t( exists(dbrep, 2, "log.incomplete") == 1 ); t( exists(dbrep, 2, "log") == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); size_t vsize = 0; void *vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_page_delete_set_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 1; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_delete(db, &k, sizeof(k)) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( exists(dbrep, 1, "log.incomplete") == 0 ); t( exists(dbrep, 1, "log") == 0 ); t( exists(dbrep, 1, "db.incomplete") == 0 ); t( exists(dbrep, 1, "db") == 0 ); t( exists(dbrep, 2, "log.incomplete") == 1 ); t( exists(dbrep, 2, "log") == 0 ); t( sp_destroy(db) == 0 ); t( exists(dbrep, 1, "log.incomplete") == 0 ); t( exists(dbrep, 1, "log") == 0 ); t( exists(dbrep, 1, "db.incomplete") == 0 ); t( exists(dbrep, 1, "db") == 0 ); t( exists(dbrep, 2, "log.incomplete") == 0 ); t( exists(dbrep, 2, "log") == 0 ); db = sp_open(env); t( db != NULL ); size_t vsize = 0; void *vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 0 ); t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_delete(db, &k, sizeof(k)) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( exists(dbrep, 1, "log.incomplete") == 0 ); t( exists(dbrep, 1, "log") == 0 ); t( exists(dbrep, 1, "db.incomplete") == 0 ); t( exists(dbrep, 1, "db") == 1 ); t( exists(dbrep, 2, "log.incomplete") == 1 ); t( exists(dbrep, 2, "log") == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); vsize = 0; vp = NULL; k = 1; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 1 ); free(vp); k = 2; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_page_fetch_gte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); void *cur = sp_cursor(db, SPGTE, NULL, 0); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_page_fetch_lte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); void *cur = sp_cursor(db, SPLTE, NULL, 0); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_page_fetch_kgte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 2; void *cur = sp_cursor(db, SPGTE, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_page_fetch_kgt(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 2; void *cur = sp_cursor(db, SPGT, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_page_fetch_klte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 2; void *cur = sp_cursor(db, SPLTE, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_page_fetch_klt(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 2; void *cur = sp_cursor(db, SPLT, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_page_n_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 0, v; while (k < 12) { v = k; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k++; } t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_destroy(db) == 0 ); t( exists(dbrep, 1, "db") == 1 ); t( exists(dbrep, 1, "log.incomplete") == 0 ); t( exists(dbrep, 1, "log") == 0 ); db = sp_open(env); t( db != NULL ); k = 0; while (k < 12) { size_t vsize = 0; void *vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == k ); free(vp); k++; } t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_page_n_replace(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 0, v = 1; while (k < 12) { t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k++; } t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( exists(dbrep, 1, "db") == 1 ); k = 0; v = 2; while (k < 12) { t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k++; } t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_destroy(db) == 0 ); t( exists(dbrep, 2, "db") == 1 ); t( exists(dbrep, 1, "log") == 0 ); t( exists(dbrep, 2, "log") == 0 ); db = sp_open(env); t( db != NULL ); k = 0; while (k < 12) { size_t vsize = 0; void *vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 2 ); free(vp); k++; } t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_page_log_fetch_gte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); k = 4; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 5; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 6; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); void *cur = sp_cursor(db, SPGTE, NULL, 0); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 4 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 5 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 6 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_page_log_fetch_lte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); k = 4; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 5; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 6; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); void *cur = sp_cursor(db, SPLTE, NULL, 0); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 6 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 5 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 4 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_page_log_fetch_kgte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); k = 4; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 5; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 6; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 2; void *cur = sp_cursor(db, SPGTE, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 4 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 5 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 6 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_page_log_fetch_kgt(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); k = 4; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 5; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 6; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 2; void *cur = sp_cursor(db, SPGT, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 4 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 5 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 6 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_page_log_fetch_klte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); k = 4; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 5; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 6; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 4; void *cur = sp_cursor(db, SPLTE, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 4 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_page_log_fetch_klt(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); k = 4; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 5; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 6; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 4; void *cur = sp_cursor(db, SPLT, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void recover_page_log_n_replace(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); uint32_t k = 0, v = 1; while (k < 12) { t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); if (k > 0 && k % 3 == 0) t( sp_ctl(db, SPMERGEFORCE) == 0 ); k++; } k = 0; v = 2; while (k < 12) { t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k++; } t( sp_destroy(db) == 0 ); t( exists(dbrep, 1, "db") == 1 ); t( exists(dbrep, 2, "db") == 1 ); t( exists(dbrep, 3, "db") == 1 ); t( exists(dbrep, 4, "log") == 1 ); db = sp_open(env); t( db != NULL ); k = 0; while (k < 12) { size_t vsize = 0; void *vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 2 ); free(vp); k++; } t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( exists(dbrep, 5, "db") == 1 ); t( exists(dbrep, 5, "log") == 0 ); t( exists(dbrep, 5, "log.incomplete") == 0 ); t( exists(dbrep, 6, "log.incomplete") == 1 ); k = 0; while (k < 12) { size_t vsize = 0; void *vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 2 ); free(vp); k++; } t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_log_set_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 1; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); size_t vsize = 0; void *vp = NULL; k = 1; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == v ); free(vp); k = 2; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == v ); free(vp); k = 3; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == v ); free(vp); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_log_replace_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 1; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); v = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); size_t vsize = 0; void *vp = NULL; k = 1; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 3 ); free(vp); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_log_set_get_replace_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 1; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); size_t vsize = 0; void *vp = NULL; k = 1; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 1 ); free(vp); v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); vsize = 0; vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 2 ); free(vp); t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); vsize = 0; vp = NULL; k = 1; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 2 ); free(vp); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_log_delete_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 1; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_delete(db, &k, sizeof(k)) == 0 ); t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); size_t vsize = 0; void *vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_log_delete_set_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 1; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_delete(db, &k, sizeof(k)) == 0 ); t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); size_t vsize = 0; void *vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 0 ); v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); vsize = 0; vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 2 ); free(vp); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_log_fetch_gte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); void *cur = sp_cursor(db, SPGTE, NULL, 0); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_log_fetch_lte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); void *cur = sp_cursor(db, SPLTE, NULL, 0); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_log_fetch_kgte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 2; void *cur = sp_cursor(db, SPGTE, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_log_fetch_kgt(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 2; void *cur = sp_cursor(db, SPGT, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_log_fetch_klte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 2; void *cur = sp_cursor(db, SPLTE, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_log_fetch_klt(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 2; void *cur = sp_cursor(db, SPLT, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_keysize(cur) == 0 ); t( sp_key(cur) == NULL ); t( sp_valuesize(cur) == 0 ); t( sp_value(cur) == NULL ); t( sp_fetch(cur) == 0 ); t( sp_keysize(cur) == 0 ); t( sp_key(cur) == NULL ); t( sp_valuesize(cur) == 0 ); t( sp_value(cur) == NULL ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_log_n_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 0, v; while (k < 12) { v = k; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k++; } t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); t( exists(dbrep, 1, "log") == 1 ); db = sp_open(env); t( db != NULL ); k = 0; while (k < 12) { size_t vsize = 0; void *vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == k ); free(vp); k++; } t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_log_n_replace(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( exists(dbrep, 1, "log.incomplete") == 1 ); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 0, v = 1; while (k < 12) { t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k++; } k = 0; v = 2; while (k < 12) { t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k++; } t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); t( exists(dbrep, 1, "log") == 1 ); db = sp_open(env); t( exists(dbrep, 1, "log") == 1 ); t( exists(dbrep, 2, "log.incomplete") == 1 ); t( db != NULL ); k = 0; while (k < 12) { size_t vsize = 0; void *vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 2 ); free(vp); k++; } t( sp_destroy(db) == 0 ); t( exists(dbrep, 1, "log") == 1 ); t( exists(dbrep, 2, "log") == 0 ); t( exists(dbrep, 2, "log.incomplete") == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_page_set_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 1; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( exists(dbrep, 1, "log.incomplete") == 0 ); t( exists(dbrep, 1, "log") == 0 ); t( exists(dbrep, 1, "db") == 1 ); t( exists(dbrep, 2, "log.incomplete") == 1 ); t( sp_destroy(db) == 0 ); t( exists(dbrep, 1, "db") == 1 ); t( exists(dbrep, 2, "log") == 0 ); t( exists(dbrep, 2, "log.incomplete") == 0 ); db = sp_open(env); t( db != NULL ); size_t vsize = 0; void *vp = NULL; k = 1; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == v ); free(vp); k = 2; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == v ); free(vp); k = 3; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == v ); free(vp); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_page_replace_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 1; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); v = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( exists(dbrep, 1, "log.incomplete") == 0 ); t( exists(dbrep, 1, "log") == 0 ); t( exists(dbrep, 2, "log.incomplete") == 1 ); t( exists(dbrep, 2, "log") == 0 ); t( exists(dbrep, 1, "db") == 1 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); size_t vsize = 0; void *vp = NULL; k = 1; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 3 ); free(vp); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_page_set_get_replace_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 1; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); v = 8; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); size_t vsize = 0; void *vp = NULL; k = 1; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 8 ); free(vp); v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k = 2; v = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); vsize = 0; vp = NULL; t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); k = 1; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 2 ); free(vp); k = 2; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 3 ); free(vp); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); vsize = 0; vp = NULL; k = 1; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 2 ); free(vp); k = 2; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 3 ); free(vp); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_page_delete_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 1; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_delete(db, &k, sizeof(k)) == 0 ); t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( exists(dbrep, 1, "log.incomplete") == 0 ); t( exists(dbrep, 1, "log") == 0 ); t( exists(dbrep, 1, "db.incomplete") == 0 ); t( exists(dbrep, 1, "db") == 0 ); t( exists(dbrep, 2, "log.incomplete") == 1 ); t( exists(dbrep, 2, "log") == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); size_t vsize = 0; void *vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_page_delete_set_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 1; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_delete(db, &k, sizeof(k)) == 0 ); t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( exists(dbrep, 1, "log.incomplete") == 0 ); t( exists(dbrep, 1, "log") == 0 ); t( exists(dbrep, 1, "db.incomplete") == 0 ); t( exists(dbrep, 1, "db") == 0 ); t( exists(dbrep, 2, "log.incomplete") == 1 ); t( exists(dbrep, 2, "log") == 0 ); t( sp_destroy(db) == 0 ); t( exists(dbrep, 1, "log.incomplete") == 0 ); t( exists(dbrep, 1, "log") == 0 ); t( exists(dbrep, 1, "db.incomplete") == 0 ); t( exists(dbrep, 1, "db") == 0 ); t( exists(dbrep, 2, "log.incomplete") == 0 ); t( exists(dbrep, 2, "log") == 0 ); db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); size_t vsize = 0; void *vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 0 ); t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_delete(db, &k, sizeof(k)) == 0 ); t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( exists(dbrep, 1, "log.incomplete") == 0 ); t( exists(dbrep, 1, "log") == 0 ); t( exists(dbrep, 1, "db.incomplete") == 0 ); t( exists(dbrep, 1, "db") == 1 ); t( exists(dbrep, 2, "log.incomplete") == 1 ); t( exists(dbrep, 2, "log") == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); vsize = 0; vp = NULL; k = 1; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 1 ); free(vp); k = 2; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_page_fetch_gte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); void *cur = sp_cursor(db, SPGTE, NULL, 0); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_page_fetch_lte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); void *cur = sp_cursor(db, SPLTE, NULL, 0); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_page_fetch_kgte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 2; void *cur = sp_cursor(db, SPGTE, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_page_fetch_kgt(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 2; void *cur = sp_cursor(db, SPGT, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_page_fetch_klte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 2; void *cur = sp_cursor(db, SPLTE, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_page_fetch_klt(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 2; void *cur = sp_cursor(db, SPLT, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_page_n_get(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 0, v; while (k < 12) { v = k; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k++; } t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_destroy(db) == 0 ); t( exists(dbrep, 1, "db") == 1 ); t( exists(dbrep, 1, "log.incomplete") == 0 ); t( exists(dbrep, 1, "log") == 0 ); db = sp_open(env); t( db != NULL ); k = 0; while (k < 12) { size_t vsize = 0; void *vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == k ); free(vp); k++; } t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_page_n_replace(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 0, v = 1; while (k < 12) { t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k++; } t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_begin(db) == 0 ); t( exists(dbrep, 1, "db") == 1 ); k = 0; v = 2; while (k < 12) { t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k++; } t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_destroy(db) == 0 ); t( exists(dbrep, 2, "db") == 1 ); t( exists(dbrep, 1, "log") == 0 ); t( exists(dbrep, 2, "log") == 0 ); db = sp_open(env); t( db != NULL ); k = 0; while (k < 12) { size_t vsize = 0; void *vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 2 ); free(vp); k++; } t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_page_log_fetch_gte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_begin(db) == 0 ); k = 4; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 5; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 6; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); void *cur = sp_cursor(db, SPGTE, NULL, 0); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 4 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 5 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 6 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_page_log_fetch_lte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_begin(db) == 0 ); k = 4; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 5; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 6; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); void *cur = sp_cursor(db, SPLTE, NULL, 0); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 6 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 5 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 4 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_page_log_fetch_kgte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_begin(db) == 0 ); k = 4; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 5; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 6; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 2; void *cur = sp_cursor(db, SPGTE, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 4 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 5 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 6 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_page_log_fetch_kgt(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_begin(db) == 0 ); k = 4; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 5; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 6; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 2; void *cur = sp_cursor(db, SPGT, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 4 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 5 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 6 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_page_log_fetch_klte(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_begin(db) == 0 ); k = 4; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 5; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 6; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 4; void *cur = sp_cursor(db, SPLTE, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 4 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_page_log_fetch_klt(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 1, v = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 2; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 3; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_begin(db) == 0 ); k = 4; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 5; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); k = 6; t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0 ); t( sp_commit(db) == 0 ); t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); k = 4; void *cur = sp_cursor(db, SPLT, &k, sizeof(k)); t( cur != NULL ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 3 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 2 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 1 ); t( *(uint32_t*)sp_key(cur) == 1 ); t( sp_keysize(cur) == sizeof(k) ); t( *(uint32_t*)sp_value(cur) == 2 ); t( sp_valuesize(cur) == sizeof(v) ); t( sp_fetch(cur) == 0 ); t( sp_fetch(cur) == 0 ); t( sp_destroy(cur) == 0 ); t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } static void txn_recover_page_log_n_replace(void) { void *env = sp_env(); t( env != NULL ); t( sp_ctl(env, SPDIR, SPO_CREAT|SPO_RDWR, dbrep) == 0 ); t( sp_ctl(env, SPCMP, cmp, NULL) == 0 ); t( sp_ctl(env, SPGC, 0) == 0 ); t( sp_ctl(env, SPMERGE, 0) == 0 ); void *db = sp_open(env); t( db != NULL ); t( sp_begin(db) == 0 ); uint32_t k = 0, v = 1; while (k < 12) { t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); if (k > 0 && k % 3 == 0) { t( sp_commit(db) == 0 ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( sp_begin(db) == 0 ); } k++; } t( sp_commit(db) == 0 ); k = 0; v = 2; while (k < 12) { t( sp_set(db, &k, sizeof(k), &v, sizeof(v)) == 0); k++; } t( sp_destroy(db) == 0 ); t( exists(dbrep, 1, "db") == 1 ); t( exists(dbrep, 2, "db") == 1 ); t( exists(dbrep, 3, "db") == 1 ); t( exists(dbrep, 4, "log") == 1 ); db = sp_open(env); t( db != NULL ); k = 0; while (k < 12) { size_t vsize = 0; void *vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 2 ); free(vp); k++; } t( sp_destroy(db) == 0 ); db = sp_open(env); t( db != NULL ); t( sp_ctl(db, SPMERGEFORCE) == 0 ); t( exists(dbrep, 5, "db") == 1 ); t( exists(dbrep, 5, "log") == 0 ); t( exists(dbrep, 5, "log.incomplete") == 0 ); t( exists(dbrep, 6, "log.incomplete") == 1 ); k = 0; while (k < 12) { size_t vsize = 0; void *vp = NULL; t( sp_get(db, &k, sizeof(k), &vp, &vsize) == 1 ); t( vsize == sizeof(v) ); t( *(uint32_t*)vp == 2 ); free(vp); k++; } t( sp_destroy(db) == 0 ); t( sp_destroy(env) == 0 ); t( rmrf(dbrep) == 0 ); } int main(int argc, char *argv[]) { rmrf(dbrep); test(recover_log_set_get); test(recover_log_replace_get); test(recover_log_set_get_replace_get); test(recover_log_delete_get); test(recover_log_delete_set_get); test(recover_log_fetch_gte); test(recover_log_fetch_lte); test(recover_log_fetch_kgte); test(recover_log_fetch_kgt); test(recover_log_fetch_klte); test(recover_log_fetch_klt); test(recover_log_n_get); test(recover_log_n_replace); test(recover_page_set_get); test(recover_page_replace_get); test(recover_page_set_get_replace_get); test(recover_page_delete_get); test(recover_page_delete_set_get); test(recover_page_fetch_gte); test(recover_page_fetch_lte); test(recover_page_fetch_kgte); test(recover_page_fetch_kgt); test(recover_page_fetch_klte); test(recover_page_fetch_klt); test(recover_page_n_get); test(recover_page_n_replace); test(recover_page_log_fetch_gte); test(recover_page_log_fetch_lte); test(recover_page_log_fetch_kgte); test(recover_page_log_fetch_kgt); test(recover_page_log_fetch_klte); test(recover_page_log_fetch_klt); test(recover_page_log_n_replace); test(txn_recover_log_set_get); test(txn_recover_log_replace_get); test(txn_recover_log_set_get_replace_get); test(txn_recover_log_delete_get); test(txn_recover_log_delete_set_get); test(txn_recover_log_fetch_gte); test(txn_recover_log_fetch_lte); test(txn_recover_log_fetch_kgte); test(txn_recover_log_fetch_kgt); test(txn_recover_log_fetch_klte); test(txn_recover_log_fetch_klt); test(txn_recover_log_n_get); test(txn_recover_log_n_replace); test(txn_recover_page_set_get); test(txn_recover_page_replace_get); test(txn_recover_page_set_get_replace_get); test(txn_recover_page_delete_get); test(txn_recover_page_delete_set_get); test(txn_recover_page_fetch_gte); test(txn_recover_page_fetch_lte); test(txn_recover_page_fetch_kgte); test(txn_recover_page_fetch_kgt); test(txn_recover_page_fetch_klte); test(txn_recover_page_fetch_klt); test(txn_recover_page_n_get); test(txn_recover_page_n_replace); test(txn_recover_page_log_fetch_gte); test(txn_recover_page_log_fetch_lte); test(txn_recover_page_log_fetch_kgte); test(txn_recover_page_log_fetch_kgt); test(txn_recover_page_log_fetch_klte); test(txn_recover_page_log_fetch_klt); test(txn_recover_page_log_n_replace); return 0; }