#include "tableinfo.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "consts.h"
#include "crsqlite.h"
#include "util.h"
int crsql_close(sqlite3 *db);
static void testGetTableInfo() {
printf("GetTableInfo\n");
sqlite3 *db = 0;
crsql_TableInfo *tableInfo = 0;
char *errMsg = 0;
int rc = SQLITE_OK;
rc = sqlite3_open(":memory:", &db);
sqlite3_exec(db, "CREATE TABLE foo (a INT NOT NULL, b)", 0, 0, 0);
rc = crsql_getTableInfo(db, "foo", &tableInfo, &errMsg);
if (rc != SQLITE_OK) {
printf("err: %s %d\n", errMsg, rc);
sqlite3_free(errMsg);
crsql_close(db);
assert(0);
return;
}
assert(tableInfo->baseColsLen == 2);
assert(tableInfo->baseCols[0].cid == 0);
assert(strcmp(tableInfo->baseCols[0].name, "a") == 0);
assert(strcmp(tableInfo->baseCols[0].type, "INT") == 0);
assert(tableInfo->baseCols[0].notnull == 1);
assert(tableInfo->baseCols[0].pk == 0);
assert(tableInfo->pksLen == 0);
assert(tableInfo->pks == 0);
assert(tableInfo->nonPksLen == 2);
assert(tableInfo->nonPks[0].cid == 0);
assert(strcmp(tableInfo->nonPks[0].name, "a") == 0);
assert(strcmp(tableInfo->nonPks[0].type, "INT") == 0);
assert(tableInfo->nonPks[0].notnull == 1);
assert(tableInfo->nonPks[0].pk == 0);
crsql_freeTableInfo(tableInfo);
sqlite3_exec(db, "CREATE TABLE bar (a PRIMARY KEY, b)", 0, 0, 0);
rc = crsql_getTableInfo(db, "bar", &tableInfo, &errMsg);
if (rc != SQLITE_OK) {
printf("err: %s %d\n", errMsg, rc);
sqlite3_free(errMsg);
crsql_close(db);
assert(0);
return;
}
assert(tableInfo->baseColsLen == 2);
assert(tableInfo->baseCols[0].cid == 0);
assert(strcmp(tableInfo->baseCols[0].name, "a") == 0);
assert(strcmp(tableInfo->baseCols[0].type, "") == 0);
assert(tableInfo->baseCols[0].notnull == 0);
assert(tableInfo->baseCols[0].pk == 1);
assert(tableInfo->pksLen == 1);
assert(tableInfo->nonPksLen == 1);
crsql_freeTableInfo(tableInfo);
printf("\t\e[0;32mSuccess\e[0m\n");
crsql_close(db);
}
static void testFindTableInfo() {
printf("FindTableInfo\n");
crsql_TableInfo **tblInfos = sqlite3_malloc(3 * sizeof(crsql_TableInfo *));
for (int i = 0; i < 3; ++i) {
tblInfos[i] = sqlite3_malloc(sizeof(crsql_TableInfo));
tblInfos[i]->tblName = sqlite3_mprintf("%d", i);
}
assert(crsql_findTableInfo(tblInfos, 3, "0") == tblInfos[0]);
assert(crsql_findTableInfo(tblInfos, 3, "1") == tblInfos[1]);
assert(crsql_findTableInfo(tblInfos, 3, "2") == tblInfos[2]);
assert(crsql_findTableInfo(tblInfos, 3, "3") == 0);
for (int i = 0; i < 3; ++i) {
sqlite3_free(tblInfos[i]->tblName);
sqlite3_free(tblInfos[i]);
}
sqlite3_free(tblInfos);
printf("\t\e[0;32mSuccess\e[0m\n");
}
static void testIsTableCompatible() {
printf("IsTableCompatible\n");
sqlite3 *db = 0;
char *errmsg = 0;
int rc = SQLITE_OK;
rc = sqlite3_open(":memory:", &db);
rc += sqlite3_exec(db, "CREATE TABLE foo (a)", 0, 0, 0);
assert(rc == SQLITE_OK);
rc = crsql_isTableCompatible(db, "foo", &errmsg);
assert(rc == 0);
sqlite3_free(errmsg);
rc = sqlite3_exec(db, "CREATE TABLE bar (a primary key)", 0, 0, 0);
assert(rc == SQLITE_OK);
rc = crsql_isTableCompatible(db, "bar", &errmsg);
assert(rc == 1);
rc = sqlite3_exec(db, "CREATE TABLE baz (a primary key, b)", 0, 0, 0);
rc += sqlite3_exec(db, "CREATE INDEX bar_i ON baz (b)", 0, 0, 0);
assert(rc == SQLITE_OK);
rc = crsql_isTableCompatible(db, "bar", &errmsg);
assert(rc == 1);
rc = sqlite3_exec(db, "CREATE TABLE fuzz (a primary key, b)", 0, 0, 0);
rc += sqlite3_exec(db, "CREATE UNIQUE INDEX fuzz_i ON fuzz (b)", 0, 0, 0);
assert(rc == SQLITE_OK);
rc = crsql_isTableCompatible(db, "fuzz", &errmsg);
assert(rc == 0);
sqlite3_free(errmsg);
rc = sqlite3_exec(db, "CREATE TABLE buzz (a primary key, b NOT NULL)", 0, 0,
0);
assert(rc == SQLITE_OK);
rc = crsql_isTableCompatible(db, "buzz", &errmsg);
assert(rc == 0);
sqlite3_free(errmsg);
rc = sqlite3_exec(
db, "CREATE TABLE boom (a primary key, b NOT NULL DEFAULT 1)", 0, 0, 0);
assert(rc == SQLITE_OK);
rc = crsql_isTableCompatible(db, "boom", &errmsg);
assert(rc == 1);
rc = sqlite3_exec(
db,
"CREATE TABLE zoom (a primary key, b, FOREIGN KEY(b) REFERENCES foo(a))",
0, 0, 0);
assert(rc == SQLITE_OK);
rc = crsql_isTableCompatible(db, "zoom", &errmsg);
assert(rc == 0);
sqlite3_free(errmsg);
rc = sqlite3_exec(db, "CREATE TABLE atable (\"id\" TEXT PRIMARY KEY) STRICT",
0, 0, 0);
assert(rc == SQLITE_OK);
rc = crsql_isTableCompatible(db, "atable", &errmsg);
assert(rc == 1);
rc = sqlite3_exec(
db, "CREATE TABLE woom (a integer primary key autoincrement)", 0, 0, 0);
assert(rc == SQLITE_OK);
rc = crsql_isTableCompatible(db, "woom", &errmsg);
assert(rc == 0);
sqlite3_free(errmsg);
rc = sqlite3_exec(db, "CREATE TABLE loom (a integer primary key)", 0, 0, 0);
assert(rc == SQLITE_OK);
rc = crsql_isTableCompatible(db, "loom", &errmsg);
assert(rc == 1);
rc = sqlite3_exec(
db, "CREATE TABLE atable2 (\"id\" TEXT PRIMARY KEY, x TEXT) STRICT;", 0,
0, 0);
assert(rc == SQLITE_OK);
rc = crsql_isTableCompatible(db, "atable2", &errmsg);
assert(rc == 1);
rc = sqlite3_exec(db,
"CREATE TABLE ydoc (\
doc_id TEXT,\
yhash BLOB,\
yval BLOB,\
primary key (doc_id, yhash)\
) STRICT;",
0, 0, 0);
assert(rc == SQLITE_OK);
rc = crsql_isTableCompatible(db, "atable2", &errmsg);
assert(rc == 1);
printf("\t\e[0;32mSuccess\e[0m\n");
crsql_close(db);
}
static void testSlabRowid() {
printf("SlabRowid\n");
sqlite3 *db = 0;
char *errmsg = 0;
int rc = SQLITE_OK;
rc = sqlite3_open(":memory:", &db);
rc += sqlite3_exec(db, "CREATE TABLE foo (a PRIMARY KEY)", 0, 0, 0);
rc += sqlite3_exec(db, "CREATE TABLE bar (a PRIMARY KEY)", 0, 0, 0);
rc += sqlite3_exec(db, "CREATE TABLE baz (a PRIMARY KEY)", 0, 0, 0);
assert(rc == SQLITE_OK);
rc += sqlite3_exec(db, "SELECT crsql_as_crr('foo');", 0, 0, 0);
rc += sqlite3_exec(db, "SELECT crsql_as_crr('bar');", 0, 0, 0);
rc += sqlite3_exec(db, "SELECT crsql_as_crr('baz');", 0, 0, 0);
assert(rc == SQLITE_OK);
crsql_TableInfo **tblInfos = 0;
int tblInfosLen = 0;
rc = crsql_pullAllTableInfos(db, &tblInfos, &tblInfosLen, &errmsg);
assert(rc == SQLITE_OK);
sqlite3_int64 fooSlabRowid = crsql_slabRowid(0, 1);
sqlite3_int64 barSlabRowid = crsql_slabRowid(1, 2);
sqlite3_int64 bazSlabRowid = crsql_slabRowid(2, 3);
assert(fooSlabRowid == 1);
assert(barSlabRowid == 2 + ROWID_SLAB_SIZE);
assert(bazSlabRowid == 3 + ROWID_SLAB_SIZE * 2);
assert(crsql_slabRowid(0, ROWID_SLAB_SIZE) == 0);
assert(crsql_slabRowid(0, ROWID_SLAB_SIZE + 1) == 1);
fooSlabRowid = crsql_slabRowid(0, ROWID_SLAB_SIZE + 1);
barSlabRowid = crsql_slabRowid(1, ROWID_SLAB_SIZE + 2);
bazSlabRowid = crsql_slabRowid(2, ROWID_SLAB_SIZE * 2 + 3);
assert(fooSlabRowid == 1);
assert(barSlabRowid == 2 + ROWID_SLAB_SIZE);
assert(bazSlabRowid == 3 + ROWID_SLAB_SIZE * 2);
crsql_freeAllTableInfos(tblInfos, tblInfosLen);
crsql_close(db);
printf("\t\e[0;32mSuccess\e[0m\n");
}
void crsqlTableInfoTestSuite() {
printf("\e[47m\e[1;30mSuite: crsql_tableInfo\e[0m\n");
testGetTableInfo();
testFindTableInfo();
testIsTableCompatible();
testSlabRowid();
}