0
0
mirror of https://github.com/tursodatabase/libsql.git synced 2025-02-12 10:48:38 +00:00
libsql/libsql-sqlite3/ext/crr/src/ext-data.test.c
2023-12-12 09:46:49 -05:00

250 lines
7.8 KiB
C

#include "ext-data.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "consts.h"
#include "crsqlite.h"
int crsql_close(sqlite3 *db);
static void textNewExtData() {
printf("NewExtData\n");
sqlite3 *db;
int rc = SQLITE_OK;
rc = sqlite3_open(":memory:", &db);
assert(rc == SQLITE_OK);
unsigned char *siteIdBuffer =
sqlite3_malloc(SITE_ID_LEN * sizeof *(siteIdBuffer));
crsql_ExtData *pExtData = crsql_newExtData(db, siteIdBuffer);
assert(pExtData->dbVersion == -1);
// statement used to determine schema version
assert(pExtData->pPragmaSchemaVersionStmt != 0);
// statement used to determine data version
assert(pExtData->pPragmaDataVersionStmt != 0);
// last schema version fetched -- none so -1
assert(pExtData->pragmaSchemaVersion == -1);
// same as above
assert(pExtData->pragmaSchemaVersionForTableInfos == -1);
// set in initSiteId
assert(pExtData->siteId != 0);
// no db version extraction yet
assert(pExtData->pDbVersionStmt == 0);
// table info allocated to an empty vec
assert(pExtData->tableInfos != 0);
// data version should have been fetched
assert(pExtData->pragmaDataVersion != -1);
crsql_finalize(pExtData);
crsql_freeExtData(pExtData);
crsql_close(db);
printf("\t\e[0;32mSuccess\e[0m\n");
}
// valgrind will let us know if we failed to free something
// mainly testing that we can finalize + free without error
static void testFreeExtData() {
printf("FreeExtData\n");
sqlite3 *db;
int rc;
rc = sqlite3_open(":memory:", &db);
assert(rc == SQLITE_OK);
unsigned char *siteIdBuffer = sqlite3_malloc(SITE_ID_LEN * sizeof(char *));
crsql_ExtData *pExtData = crsql_newExtData(db, siteIdBuffer);
crsql_finalize(pExtData);
crsql_freeExtData(pExtData);
crsql_close(db);
printf("\t\e[0;32mSuccess\e[0m\n");
}
static void testFinalize() {
printf("FinalizeExtData\n");
sqlite3 *db;
int rc;
rc = sqlite3_open(":memory:", &db);
assert(rc == SQLITE_OK);
unsigned char *siteIdBuffer = sqlite3_malloc(SITE_ID_LEN * sizeof(char *));
crsql_ExtData *pExtData = crsql_newExtData(db, siteIdBuffer);
crsql_finalize(pExtData);
assert(pExtData->pDbVersionStmt == 0);
assert(pExtData->pPragmaSchemaVersionStmt == 0);
// finalizing twice should be a no-op
crsql_finalize(pExtData);
crsql_freeExtData(pExtData);
crsql_close(db);
printf("\t\e[0;32mSuccess\e[0m\n");
}
static void testFetchPragmaSchemaVersion() {
printf("FetchPragmaSchemaVersion\n");
sqlite3 *db;
int rc;
int didChange = 0;
rc = sqlite3_open(":memory:", &db);
assert(rc == SQLITE_OK);
unsigned char *siteIdBuffer = sqlite3_malloc(SITE_ID_LEN * sizeof(char *));
crsql_ExtData *pExtData = crsql_newExtData(db, siteIdBuffer);
// fetch the schema info for db version update
didChange = crsql_fetchPragmaSchemaVersion(db, pExtData, 0);
assert(pExtData->pragmaSchemaVersion != -1);
assert(didChange == 1);
// fetch the schema info for table info
didChange = crsql_fetchPragmaSchemaVersion(db, pExtData, 1);
assert(didChange == 1);
assert(pExtData->pragmaSchemaVersionForTableInfos != -1);
// re-fetch both with no schema change, should be same value
int oldVersion = pExtData->pragmaSchemaVersion;
didChange = crsql_fetchPragmaSchemaVersion(db, pExtData, 0);
assert(oldVersion == pExtData->pragmaSchemaVersion);
assert(didChange == 0);
oldVersion = pExtData->pragmaSchemaVersionForTableInfos;
didChange = crsql_fetchPragmaSchemaVersion(db, pExtData, 1);
assert(oldVersion == pExtData->pragmaSchemaVersionForTableInfos);
assert(didChange == 0);
// now make a schema modification
sqlite3_exec(db, "CREATE TABLE foo (a)", 0, 0, 0);
oldVersion = pExtData->pragmaSchemaVersion;
didChange = crsql_fetchPragmaSchemaVersion(db, pExtData, 0);
assert(oldVersion != pExtData->pragmaSchemaVersion);
assert(didChange == 1);
oldVersion = pExtData->pragmaSchemaVersionForTableInfos;
didChange = crsql_fetchPragmaSchemaVersion(db, pExtData, 1);
assert(oldVersion != pExtData->pragmaSchemaVersionForTableInfos);
assert(didChange == 1);
// re-fetch both with no schema change again, should be same value
oldVersion = pExtData->pragmaSchemaVersion;
didChange = crsql_fetchPragmaSchemaVersion(db, pExtData, 0);
assert(oldVersion == pExtData->pragmaSchemaVersion);
assert(didChange == 0);
oldVersion = pExtData->pragmaSchemaVersionForTableInfos;
didChange = crsql_fetchPragmaSchemaVersion(db, pExtData, 1);
assert(oldVersion == pExtData->pragmaSchemaVersionForTableInfos);
assert(didChange == 0);
crsql_finalize(pExtData);
crsql_freeExtData(pExtData);
crsql_close(db);
printf("\t\e[0;32mSuccess\e[0m\n");
}
static void testFetchPragmaDataVersion() {
printf("FetchPragmaDataVersion\n");
remove("testFetchPragmaDataVersion.db");
sqlite3 *db1;
sqlite3 *db2;
int rc;
char *errmsg = 0;
rc = sqlite3_open("testFetchPragmaDataVersion.db", &db1);
assert(rc == SQLITE_OK);
rc = sqlite3_open("testFetchPragmaDataVersion.db", &db2);
assert(rc == SQLITE_OK);
rc = sqlite3_exec(db1, "CREATE TABLE fpdv (a)", 0, 0, &errmsg);
assert(rc == SQLITE_OK);
unsigned char *siteIdBuffer = sqlite3_malloc(SITE_ID_LEN * sizeof(char *));
crsql_ExtData *pExtData1 = crsql_newExtData(db1, siteIdBuffer);
siteIdBuffer = sqlite3_malloc(SITE_ID_LEN * sizeof(char *));
crsql_ExtData *pExtData2 = crsql_newExtData(db2, siteIdBuffer);
// should not change after init
rc = crsql_fetchPragmaDataVersion(db1, pExtData1);
assert(rc == 0);
rc = crsql_fetchPragmaDataVersion(db2, pExtData2);
assert(rc == 0);
// should not change if write was issued on its connection
rc = sqlite3_exec(db1, "INSERT INTO fpdv VALUES (1)", 0, 0, 0);
assert(rc == SQLITE_OK);
rc = crsql_fetchPragmaDataVersion(db1, pExtData1);
assert(rc == 0);
// should change if write was issued on another connection
rc = crsql_fetchPragmaDataVersion(db2, pExtData2);
assert(rc == 1);
// should not change after updating itself
rc = crsql_fetchPragmaDataVersion(db2, pExtData2);
assert(rc == 0);
// same test but in reverse direction
rc = sqlite3_exec(db2, "INSERT INTO fpdv VALUES (1)", 0, 0, 0);
assert(rc == SQLITE_OK);
rc = crsql_fetchPragmaDataVersion(db2, pExtData2);
assert(rc == 0);
rc = crsql_fetchPragmaDataVersion(db1, pExtData1);
assert(rc == 1);
// should not change after updating itself
rc = crsql_fetchPragmaDataVersion(db1, pExtData1);
assert(rc == 0);
crsql_finalize(pExtData1);
crsql_freeExtData(pExtData1);
crsql_close(db1);
crsql_finalize(pExtData2);
crsql_freeExtData(pExtData2);
crsql_close(db2);
remove("testFetchPragmaDataVersion.db");
printf("\t\e[0;32mSuccess\e[0m\n");
}
static void testRecreateDbVersionStmt() {
printf("RecreateDbVersionStmt\n");
sqlite3 *db;
int rc;
rc = sqlite3_open(":memory:", &db);
unsigned char *siteIdBuffer = sqlite3_malloc(SITE_ID_LEN * sizeof(char *));
crsql_ExtData *pExtData = crsql_newExtData(db, siteIdBuffer);
rc = crsql_recreate_db_version_stmt(db, pExtData);
// there are no clock tables yet. nothing to create.
assert(rc == -1);
assert(pExtData->pDbVersionStmt == 0);
sqlite3_exec(db, "CREATE TABLE foo (a primary key not null, b);", 0, 0, 0);
sqlite3_exec(db, "SELECT crsql_as_crr('foo')", 0, 0, 0);
rc = crsql_recreate_db_version_stmt(db, pExtData);
assert(rc == 0);
assert(pExtData->pDbVersionStmt != 0);
// recreating while a created statement exists isn't an error
rc = crsql_recreate_db_version_stmt(db, pExtData);
assert(rc == 0);
assert(pExtData->pDbVersionStmt != 0);
crsql_finalize(pExtData);
assert(pExtData->pDbVersionStmt == 0);
crsql_freeExtData(pExtData);
crsql_close(db);
printf("\t\e[0;32mSuccess\e[0m\n");
}
void crsqlExtDataTestSuite() {
printf("\e[47m\e[1;30mSuite: crsql_ExtData\e[0m\n");
textNewExtData();
testFreeExtData();
testFinalize();
testFetchPragmaSchemaVersion();
testRecreateDbVersionStmt();
testFetchPragmaDataVersion();
}