sources/run_test_client.c (1,322 lines of code) (raw):
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <setjmp.h>
#include "cqlrt.h"
#include "run_test.h"
#include "alloca.h"
cql_code test_c_rowsets(sqlite3 *db);
cql_code test_rowset_same(sqlite3 *db);
cql_code test_bytebuf_growth(sqlite3 *db);
cql_code test_cql_finalize_on_error(sqlite3 *db);
cql_code test_blob_rowsets(sqlite3 *db);
cql_code test_sparse_blob_rowsets(sqlite3 *db);
cql_code test_c_one_row_result(sqlite3 *db);
cql_code test_ref_comparisons(sqlite3 *db);
cql_code test_all_column_fetchers(sqlite3 *db);
cql_code test_error_case_rowset(sqlite3 *db);
cql_code test_autodrop_rowset(sqlite3 *db);
cql_code test_one_row_result(sqlite3 *db);
cql_code test_cql_bytebuf_open(sqlite3 *db);
cql_code test_cql_bytebuf_alloc_within_bytebuf_exp_growth_cap(sqlite3 *db);
cql_code test_cql_bytebuf_alloc_over_bytebuf_exp_growth_cap(sqlite3 *db);
cql_code test_all_column_encoded_fetchers(sqlite3 *db);
cql_code test_all_column_encoded_with_context_fetchers(sqlite3 *db);
cql_code test_all_column_encoded_cursor(sqlite3 *db);
cql_code test_all_column_encoded_out_union(sqlite3 *db);
cql_code test_all_column_encoded_multi_out_union(sqlite3 *db);
cql_code test_all_column_some_encoded_field(sqlite3 *db);
cql_code test_all_column_some_encoded_field_with_encode_context(sqlite3 *db);
cql_code test_all_column_encoded_runtime_turn_on_off(sqlite3 *db);
cql_code test_cql_contract_argument_notnull_tripwires(sqlite3 *db);
extern cql_int32 get_blob_byte(cql_blob_ref b, cql_int32 i);
extern cql_int32 get_blob_size(cql_blob_ref b);
static int32_t steps_until_fail = 0;
static int32_t trace_received = 0;
#undef sqlite3_step
#define _VA_ARG_COUNT__(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _count, ...) _count
#define _VA_ARG_COUNT_(...) _VA_ARG_COUNT__(__VA_ARGS__, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define _VA_ARG_COUNT(...) _VA_ARG_COUNT_(0, ##__VA_ARGS__)
#define _VA_ARG_FIRST(_first, ...) _first
#define _E(cond_, rc_, ...) { \
expectations++; \
if (!(cond_)) { \
fails++; \
if (_VA_ARG_COUNT(__VA_ARGS__) != 0 && (_VA_ARG_FIRST(__VA_ARGS__)) != NULL) { \
printf(__VA_ARGS__); \
} \
return rc_; \
} \
}
#define E(cond_, ...) _E(cond_, SQLITE_ERROR, __VA_ARGS__)
#define SQL_E(rc_) { \
cql_code __saved_rc_ = (rc_); \
_E(SQLITE_OK == __saved_rc_, __saved_rc_, "failed return code %s:%d %s\n", __FILE__, __LINE__, #rc_); \
}
cql_code mockable_sqlite3_step(sqlite3_stmt *stmt) {
if (steps_until_fail) {
if (0 == --steps_until_fail) {
return SQLITE_ERROR;
}
}
return sqlite3_step(stmt);
}
cql_code run_client(sqlite3 *db) {
E(longs__one == 1L, "long_enum case 1");
E(longs__big == 0x100000000L, "long_enum case 2");
E(floats__one == 1.0, "float_enum case 1");
E(floats__two == 2.0, "float_enum case 2");
E(fails_because_bogus_table(db) != SQLITE_OK, "procedure should have returned an error\n");
E(trace_received == 1, "failure proc did not trigger a trace\n");
E(!cql_outstanding_refs, "outstanding refs in fails_because_bogus_table: %d\n", cql_outstanding_refs);
SQL_E(test_c_rowsets(db));
E(!cql_outstanding_refs, "outstanding refs in test_c_rowsets: %d\n", cql_outstanding_refs);
SQL_E(test_rowset_same(db));
E(!cql_outstanding_refs, "outstanding refs in test_rowset_same: %d\n", cql_outstanding_refs);
SQL_E(test_blob_rowsets(db));
E(!cql_outstanding_refs, "outstanding refs in test_blob_rowsets: %d\n", cql_outstanding_refs);
SQL_E(test_ref_comparisons(db));
E(!cql_outstanding_refs, "outstanding refs in test_ref_comparisons: %d\n", cql_outstanding_refs);
SQL_E(test_sparse_blob_rowsets(db));
E(!cql_outstanding_refs, "outstanding refs in test_sparse_blob_rowsets: %d\n", cql_outstanding_refs);
SQL_E(test_bytebuf_growth(db));
E(!cql_outstanding_refs, "outstanding refs in test bytebuf growth: %d\n", cql_outstanding_refs);
SQL_E(test_cql_finalize_on_error(db));
E(!cql_outstanding_refs, "outstanding refs in test finalize on error: %d\n", cql_outstanding_refs);
SQL_E(test_c_one_row_result(db));
E(!cql_outstanding_refs, "outstanding refs in test_c_one_row_result: %d\n", cql_outstanding_refs);
SQL_E(test_all_column_fetchers(db));
E(!cql_outstanding_refs, "outstanding refs in test_all_column_fetchers: %d\n", cql_outstanding_refs);
SQL_E(test_all_column_encoded_fetchers(db));
E(!cql_outstanding_refs, "outstanding refs in test_all_column_encoded_fetchers: %d\n", cql_outstanding_refs);
SQL_E(test_all_column_encoded_with_context_fetchers(db));
E(!cql_outstanding_refs, "outstanding refs in test_all_column_encoded_with_context_fetchers: %d\n", cql_outstanding_refs);
SQL_E(test_all_column_encoded_cursor(db));
E(!cql_outstanding_refs, "outstanding refs in test_all_column_encoded_cursor: %d\n", cql_outstanding_refs);
SQL_E(test_all_column_encoded_out_union(db));
E(!cql_outstanding_refs, "outstanding refs in test_all_column_encoded_out_union: %d\n", cql_outstanding_refs);
SQL_E(test_all_column_encoded_multi_out_union(db));
E(!cql_outstanding_refs, "outstanding refs in test_all_column_encoded_multi_out_union: %d\n", cql_outstanding_refs);
SQL_E(test_all_column_encoded_runtime_turn_on_off(db));
E(!cql_outstanding_refs, "outstanding refs in test_all_column_encoded_runtime_turn_on_off: %d\n", cql_outstanding_refs);
SQL_E(test_all_column_some_encoded_field(db));
E(!cql_outstanding_refs, "outstanding refs in test_all_column_some_encoded_field: %d\n", cql_outstanding_refs);
SQL_E(test_all_column_some_encoded_field_with_encode_context(db));
E(!cql_outstanding_refs, "outstanding refs in test_all_column_some_encoded_field_with_encode_context: %d\n", cql_outstanding_refs);
SQL_E(test_error_case_rowset(db));
E(!cql_outstanding_refs, "outstanding refs in test_error_case_rowset: %d\n", cql_outstanding_refs);
SQL_E(test_autodrop_rowset(db));
E(!cql_outstanding_refs, "outstanding refs in test_autodrop_rowset (run 1): %d\n", cql_outstanding_refs);
SQL_E(test_autodrop_rowset(db));
E(!cql_outstanding_refs, "outstanding refs in test_autodrop_rowset (run 2): %d\n", cql_outstanding_refs);
SQL_E(test_one_row_result(db));
E(!cql_outstanding_refs, "outstanding refs in one_row_result: %d\n", cql_outstanding_refs);
SQL_E(test_cql_bytebuf_open(db));
E(!cql_outstanding_refs, "outstanding refs in test_cql_bytebuf_open: %d\n", cql_outstanding_refs);
SQL_E(test_cql_bytebuf_alloc_within_bytebuf_exp_growth_cap(db));
E(!cql_outstanding_refs,
"outstanding refs in test_cql_bytebuf_alloc_within_bytebuf_exp_growth_cap: %d\n",
cql_outstanding_refs);
SQL_E(test_cql_bytebuf_alloc_over_bytebuf_exp_growth_cap(db));
E(!cql_outstanding_refs,
"outstanding refs in test_cql_bytebuf_alloc_over_bytebuf_exp_growth_cap: %d\n",
cql_outstanding_refs);
SQL_E(test_cql_contract_argument_notnull_tripwires(db));
E(!cql_outstanding_refs,
"outstanding refs in test_cql_contract_argument_notnull_tripwires: %d\n",
cql_outstanding_refs);
return SQLITE_OK;
}
void run_test_trace_callback(const char *proc, const char *file, int32_t line) {
if (strcmp(proc, "fails_because_bogus_table")) {
printf("failure trace not recieved on correct proc\n");
return;
}
if (!file || strlen(file) < 8) {
printf("callback file not a reasonable value\n");
return;
}
if (line < 1000) {
printf("line number in callback not a reasonable value\n");
return;
}
trace_received++;
}
cql_code test_c_rowsets(sqlite3 *db) {
printf("Running C client test\n");
tests++;
// we haven't created the table yet
SQL_E(drop_mixed(db));
get_mixed_result_set_ref result_set;
E(SQLITE_OK != get_mixed_fetch_results(db, &result_set, 100), "table didn't exist, yet there was data...\n");
SQL_E(make_mixed(db));
SQL_E(load_mixed_with_nulls(db));
SQL_E(get_mixed_fetch_results(db, &result_set, 100));
cql_int32 count = get_mixed_result_count(result_set);
E(count == 4, "expected 4 rows from mixed\n");
cql_bool b_is_null;
cql_bool b;
cql_bool code_is_null;
cql_int64 code;
cql_string_ref name;
b_is_null = get_mixed_get_flag_is_null(result_set, 0);
b = get_mixed_get_flag_value(result_set, 0);
code_is_null = get_mixed_get_code_is_null(result_set, 0);
code = get_mixed_get_code_value(result_set, 0);
name = get_mixed_get_name(result_set, 0);
E(b_is_null == 0, "first mixed row has unexpected b_is_null value\n");
E(b == 1, "first mixed row has unexpected b value\n");
E(code_is_null == 0, "first mixed row has unexpected code_is_null value\n");
E(code == 12, "first mixed row has unexpected code value\n");
E(strcmp("a name", name->ptr) == 0, "first mixed row has unexpected name value\n");
b_is_null = get_mixed_get_flag_is_null(result_set, 1);
b = get_mixed_get_flag_value(result_set, 1);
code_is_null = get_mixed_get_code_is_null(result_set, 1);
code = get_mixed_get_code_value(result_set, 1);
name = get_mixed_get_name(result_set, 1);
E(b_is_null == 0, "second mixed row has unexpected b_is_null value\n");
E(b == 1, "second mixed row has unexpected b value\n");
E(code_is_null == 0, "second mixed row has unexpected code_is_null value\n");
E(code == 14, "second mixed row has unexpected code value\n");
E(strcmp("another name", name->ptr) == 0, "second mixed row has unexpected name value\n");
// don't get b_value and code_value, as that will assert, since they are NULL
b_is_null = get_mixed_get_flag_is_null(result_set, 2);
code_is_null = get_mixed_get_code_is_null(result_set, 2);
name = get_mixed_get_name(result_set, 2);
E(b_is_null == 1, "third mixed row has unexpected b_is_null value\n");
E(code_is_null == 1, "third mixed row has unexpected code_is_null value\n");
E(name == NULL, "third mixed row has unexpected name value\n");
b_is_null = get_mixed_get_flag_is_null(result_set, 3);
b = get_mixed_get_flag_value(result_set, 3);
code_is_null = get_mixed_get_code_is_null(result_set, 3);
code = get_mixed_get_code_value(result_set, 3);
name = get_mixed_get_name(result_set, 3);
E(b_is_null == 0, "fourth mixed row has unexpected b_is_null value\n");
E(b == 0, "fourth mixed row has unexpected b value\n");
E(code_is_null == 0, "fourth mixed row has unexpected code_is_null value\n");
E(code == 16, "fourth mixed row has unexpected code value\n");
E(strcmp("last name", name->ptr) == 0, "fourth mixed row has unexpected name value\n");
cql_int32 copy_index = 1;
cql_int32 copy_count = 2;
get_mixed_result_set_ref result_set_copy;
get_mixed_copy(result_set, &result_set_copy, copy_index, copy_count);
for (cql_int32 i = 0; i < copy_count; ++i) {
// Check that the row hashes are equal from the source to the copy
E(get_mixed_row_hash(result_set, i + copy_index) == get_mixed_row_hash(result_set_copy, i),
"copied row %d hash not equal to the expected source row %d\n", i, i + copy_index);
// Check that the rows are equal from the source to the copy
E(get_mixed_row_equal(result_set, i + copy_index, result_set_copy, i),
"copied row %d not equal to the expected source row %d\n", i, i + copy_index);
}
for (cql_int32 i = 0; i < count - 1; ++i) {
// Check that the wrong rows are not equal
E(!get_mixed_row_equal(result_set, i, result_set, i + 1), "row %d should not be equal to row %d\n", i, i + 1);
// Check that strings are not equal
E(!cql_string_equal(get_mixed_get_name(result_set, i), get_mixed_get_name(result_set, i + 1)),
"row %d name should not be equal to row %d name\n", i, i + 1);
}
cql_result_set_release(result_set);
cql_result_set_release(result_set_copy);
tests_passed++;
return SQLITE_OK;
}
static cql_nullable_int64 make_nullable_code(cql_bool is_null, cql_int64 value) {
cql_nullable_int64 code;
cql_set_nullable(code, is_null, value);
return code;
}
static cql_nullable_int64 get_nullable_code(get_mixed_result_set_ref result_set, int32_t row) {
return make_nullable_code(get_mixed_get_code_is_null(result_set, row), get_mixed_get_code_value(result_set, row));
}
cql_code test_rowset_same(sqlite3 *db) {
printf("Running cql_row_same client test\n");
tests++;
get_mixed_result_set_ref result_set;
get_mixed_result_set_ref result_set_updated;
cql_string_ref updated_name = string_create();
cql_blob_ref updated_bl = blob_from_string(updated_name);
SQL_E(drop_mixed(db));
SQL_E(make_mixed(db));
SQL_E(load_mixed_with_nulls(db));
SQL_E(get_mixed_fetch_results(db, &result_set, 100));
// Update row 0 with just a new name, so the identity columns should still match the previous result set
SQL_E(update_mixed(db,
get_mixed_get_id(result_set, 0),
updated_name,
get_nullable_code(result_set, 0),
get_mixed_get_bl(result_set, 0)));
// Update row 1 with just a new code, so only 1 of the identity columns should not match the previous result set
SQL_E(update_mixed(db,
get_mixed_get_id(result_set, 1),
get_mixed_get_name(result_set, 1),
make_nullable_code(0, 1234),
get_mixed_get_bl(result_set, 1)));
// Update row 2 with just a new bl, so a ref type identity column should not match the previous result set
// This also is testing that the last column in the identity columns is properly tested.
SQL_E(update_mixed(db,
get_mixed_get_id(result_set, 2),
get_mixed_get_name(result_set, 2),
get_nullable_code(result_set, 2),
updated_bl));
// Get the updated result set
SQL_E(get_mixed_fetch_results(db, &result_set_updated, 100));
E(get_mixed_row_same(result_set, 0, result_set_updated, 0),
"updated row 0 should be the same as original row 0 (identity column check)\n");
E(!get_mixed_row_same(result_set, 1, result_set_updated, 1),
"updated row 1 should NOT be the same as original row 1 (identity column check)\n");
E(!get_mixed_row_same(result_set, 2, result_set_updated, 2),
"updated row 2 should NOT be the same as original row 2 (identity column check)\n");
E(!get_mixed_row_same(result_set, 0, result_set_updated, 1),
"updated row 1 should NOT be the same as original row 0 (identity column check)\n");
cql_result_set_release(result_set);
cql_result_set_release(result_set_updated);
cql_string_release(updated_name);
cql_blob_release(updated_bl);
tests_passed++;
return SQLITE_OK;
}
cql_code test_ref_comparisons(sqlite3 *db) {
printf("Running ref comparison test\n");
tests++;
// we haven't created the table yet
get_mixed_result_set_ref result_set;
SQL_E(load_mixed_dupes(db));
SQL_E(get_mixed_fetch_results(db, &result_set, 100));
E(get_mixed_result_count(result_set) == 6, "expected 6 rows from mixed\n");
// Check that the row hashes are equal from the source to the copy
E(get_mixed_row_hash(result_set, 0) == get_mixed_row_hash(result_set, 1), "row %d hash not equal to row %d\n", 0, 1);
E(get_mixed_row_hash(result_set, 2) == get_mixed_row_hash(result_set, 3), "row %d hash not equal to row %d\n", 2, 3);
E(get_mixed_row_equal(result_set, 0, result_set, 1), "row %d should be equal to row %d\n", 0, 1);
E(get_mixed_row_equal(result_set, 2, result_set, 3), "row %d should be equal to row %d\n", 2, 3);
E(!get_mixed_row_equal(result_set, 0, result_set, 2), "row %d should be not equal to row %d\n", 0, 2);
E(!get_mixed_row_equal(result_set, 1, result_set, 3), "row %d should not be equal to row %d\n", 1, 3);
E(!get_mixed_row_equal(result_set, 0, result_set, 4), "row %d should not be equal to row %d\n", 0, 4);
E(!get_mixed_row_equal(result_set, 1, result_set, 5), "row %d should not be equal to row %d\n", 0, 4);
cql_result_set_release(result_set);
tests_passed++;
return SQLITE_OK;
}
cql_code test_bytebuf_growth(sqlite3 *db) {
tests++;
printf("Running C client test with huge number of rows\n");
SQL_E(bulk_load_mixed(db, 10000));
get_mixed_result_set_ref result_set;
SQL_E(get_mixed_fetch_results(db, &result_set, 100000));
E(get_mixed_result_count(result_set) == 10000, "expected 10000 rows from mixed\n");
cql_result_set_release(result_set);
tests_passed++;
return SQLITE_OK;
}
cql_code test_cql_finalize_on_error(sqlite3 *db) {
printf("Running cql finalize on error test\n");
tests++;
expectations++;
SQL_E(load_mixed(db));
sqlite3_stmt *stmt = NULL;
SQL_E(sqlite3_prepare_v2(db, "select * from sqlite_master", -1, &stmt, NULL));
cql_finalize_on_error(SQLITE_ERROR,&stmt);
E(stmt == NULL, "expected statement to be finalized\n");
tests_passed++;
return SQLITE_OK;
}
cql_string_ref _Nullable string_create()
{
return cql_string_ref_new("Hello, world.");
}
cql_int32 run_test_math(cql_int32 int1, cql_nullable_int32 *_Nonnull int2)
{
int2->is_null = 0;
int2->value = int1 * 5;
return int1 * 7;
}
// dumbest set ever
#define MAX_STRINGS 16
typedef struct set_payload
{
int count;
cql_string_ref strings[MAX_STRINGS];
} set_payload;
static void set_finalize(cql_type_ref _Nonnull ref)
{
cql_object_ref obj = (cql_object_ref)ref;
set_payload *payload = (set_payload *)obj->ptr;
for (int i = 0; i < payload->count; i++) {
cql_set_string_ref(&payload->strings[i], NULL);
}
free(payload);
obj->ptr = NULL;
}
cql_object_ref _Nonnull set_create()
{
cql_object_ref obj = (cql_object_ref)calloc(sizeof(cql_object), 1);
obj->base.type = CQL_C_TYPE_OBJECT;
obj->base.ref_count = 1;
obj->base.finalize = set_finalize;
obj->ptr = calloc(sizeof(set_payload), 1);
cql_outstanding_refs++;
return obj;
}
cql_bool set_contains(cql_object_ref _Nonnull _set, cql_string_ref _Nonnull _key)
{
set_payload *payload = (set_payload *)_set->ptr;
for (int i = 0; i < payload->count; i++) {
if (!strcmp(_key->ptr, payload->strings[i]->ptr)) {
return cql_true;
}
}
return cql_false;
}
cql_bool set_add(cql_object_ref _Nonnull _set, cql_string_ref _Nonnull _key)
{
if (set_contains(_set, _key)) {
return cql_false;
}
set_payload *payload = (set_payload *)_set->ptr;
if (payload->count >= MAX_STRINGS) {
return cql_false;
}
cql_set_string_ref(&payload->strings[payload->count], _key);
payload->count++;
return cql_true;
}
int get_outstanding_refs()
{
return cql_outstanding_refs;
}
cql_blob_ref _Nonnull blob_from_string(cql_string_ref str)
{
if (str) {
return cql_blob_ref_new(str->ptr, strlen(str->ptr));
}
else {
return cql_blob_ref_new("", 1);
}
}
cql_string_ref _Nonnull string_from_blob(cql_blob_ref b)
{
if (b) {
char *buf = alloca(b->size+1);
memcpy(buf, b->ptr, b->size);
buf[b->size] = 0;
return cql_string_ref_new(buf);
}
else {
return cql_string_ref_new("");
}
}
cql_code test_blob_rowsets(sqlite3 *db) {
printf("Running blob rowset test\n");
tests++;
SQL_E(load_blobs(db));
get_blob_table_result_set_ref result_set;
SQL_E(get_blob_table_fetch_results(db, &result_set));
E(get_blob_table_result_count(result_set) == 20, "expected 20 rows from blob table\n");
cql_int32 id;
cql_blob_ref b1;
cql_blob_ref b2;
for (cql_int32 i = 0; i < 20; i++) {
id = get_blob_table_get_id(result_set, i);
b1 = get_blob_table_get_b1(result_set, i);
b2 = get_blob_table_get_b2(result_set, i);
E(i == id, "id %d did not match %d\n", id, i);
char buf1[100];
char buf2[100];
sprintf(buf1, "nullable blob %d", i);
sprintf(buf2, "not nullable blob %d", i);
cql_string_ref b1_ref = string_from_blob(b1);
cql_string_ref b2_ref = string_from_blob(b2);
E(strcmp(buf1, b1_ref->ptr) == 0, "nullable blob %d did not match %s\n", i, buf1);
E(strcmp(buf2, b2_ref->ptr) == 0, "nullable blob %d did not match %s\n", i, buf2);
cql_string_release(b1_ref);
cql_string_release(b2_ref);
}
cql_result_set_release(result_set);
cql_string_ref str_ref = cql_string_ref_new("123");
cql_blob_ref blob_ref = blob_from_string(str_ref);
cql_string_ref str_ref_1 = string_from_blob(blob_ref);
cql_blob_ref blob_ref_1 = blob_from_string(str_ref_1);
E(cql_string_equal(str_ref, str_ref_1), "string \"%s\" should equal to \"%s\"", str_ref->ptr, str_ref_1->ptr);
E(cql_blob_equal(blob_ref, blob_ref_1), "blob \"%d\" should be equal to \"%d\"", blob_ref->size, blob_ref_1->size);
cql_string_release(str_ref);
cql_string_release(str_ref_1);
cql_blob_release(blob_ref);
cql_blob_release(blob_ref_1);
tests_passed++;
return SQLITE_OK;
}
cql_code test_sparse_blob_rowsets(sqlite3 *db) {
printf("Running sparse blob rowset test\n");
tests++;
SQL_E(load_sparse_blobs(db));
get_blob_table_result_set_ref result_set;
SQL_E(get_blob_table_fetch_results(db, &result_set));
E(get_blob_table_result_count(result_set) == 20, "expected 20 rows from blob table\n");
cql_int32 id;
cql_blob_ref b1;
cql_blob_ref b2;
cql_hash_code prev = -1;
for (cql_int32 i = 0; i < 20; i++) {
id = get_blob_table_get_id(result_set, i);
b1 = get_blob_table_get_b1(result_set, i);
b2 = get_blob_table_get_b2(result_set, i);
cql_hash_code h = get_blob_table_row_hash(result_set, i);
E(h != prev, "hash codes really shouldn't collide so easily (row %d)\n", i);
prev = h;
E(i == id, "id %d did not match %d\n", id, i);
char buf1[100];
char buf2[100];
sprintf(buf1, "nullable blob %d", i);
sprintf(buf2, "not nullable blob %d", i);
cql_string_ref b1_ref = string_from_blob(b1);
if (i % 2 == 0) {
E(strcmp(buf1, b1_ref->ptr) == 0, "nullable blob %d did not match %s\n", i, buf1);
} else {
E(!b1, "nullable blob %d should have been null\n", i);
}
cql_string_ref b2_ref = string_from_blob(b2);
E(strcmp(buf2, b2_ref->ptr) == 0, "nullable blob %d did not match %s\n", i, buf2);
cql_string_release(b1_ref);
cql_string_release(b2_ref);
}
cql_result_set_release(result_set);
tests_passed++;
return SQLITE_OK;
}
cql_code test_c_one_row_result(sqlite3 *db) {
printf("Running C one row result set test\n");
tests++;
SQL_E(drop_mixed(db));
// we haven't created the table yet
get_one_from_mixed_result_set_ref result_set;
E(SQLITE_OK != get_one_from_mixed_fetch_results(db, &result_set, 1), "table didn't exist, yet there was data...\n");
SQL_E(make_mixed(db));
SQL_E(load_mixed_with_nulls(db));
SQL_E(get_one_from_mixed_fetch_results(db, &result_set, 1));
E(get_one_from_mixed_result_count(result_set) == 1, "expected 1 rows from mixed\n");
cql_bool b_is_null;
cql_bool b;
cql_bool code_is_null;
cql_int64 code;
cql_string_ref name;
b_is_null = get_one_from_mixed_get_flag_is_null(result_set);
b = get_one_from_mixed_get_flag_value(result_set);
code_is_null = get_one_from_mixed_get_code_is_null(result_set);
code = get_one_from_mixed_get_code_value(result_set);
name = get_one_from_mixed_get_name(result_set);
E(b_is_null == 0, "mixed row has unexpected b_is_null value\n");
E(b == 1, "mixed row has unexpected b value\n");
E(code_is_null == 0, "mixed row has unexpected code_is_null value\n");
E(code == 12, "mixed row has unexpected code value\n");
E(strcmp("a name", name->ptr) == 0, "mixed row has unexpected name value\n");
// Compare to a result from a row with different values
get_one_from_mixed_result_set_ref result_set2;
SQL_E(get_one_from_mixed_fetch_results(db, &result_set2, 2));
E(get_one_from_mixed_result_count(result_set2) == 1, "expected 1 rows from mixed\n");
cql_bool b_is_null2;
cql_bool b2;
cql_bool code_is_null2;
cql_int64 code2;
cql_string_ref name2;
b_is_null2 = get_one_from_mixed_get_flag_is_null(result_set2);
b2 = get_one_from_mixed_get_flag_value(result_set2);
code_is_null2 = get_one_from_mixed_get_code_is_null(result_set2);
code2 = get_one_from_mixed_get_code_value(result_set2);
name2 = get_one_from_mixed_get_name(result_set2);
E(b_is_null2 == 0, "mixed row 2 has unexpected b_is_null value\n");
E(b2 == 1, "mixed row 2 has unexpected b value\n");
E(code_is_null2 == 0, "mixed row 2 has unexpected code_is_null value\n");
E(code2 == 14, "mixed row 2 has unexpected code value\n");
E(strcmp("another name", name2->ptr) == 0, "mixed row 2 has unexpected name value\n");
E(!get_one_from_mixed_equal(result_set, result_set2), "mismatched result sets are equal\n");
E(get_one_from_mixed_hash(result_set) != get_one_from_mixed_hash(result_set2),
"mismatched result sets have the same hashes\n");
cql_result_set_release(result_set2);
// Exercise single-row copy and compare copied results
get_one_from_mixed_copy(result_set, &result_set2);
E(get_one_from_mixed_equal(result_set, result_set2), "result set copies are not equal\n");
E(get_one_from_mixed_hash(result_set) == get_one_from_mixed_hash(result_set2),
"result set copies do not have the same hashes\n");
cql_result_set_release(result_set2);
// Compare results fetched from the same row
SQL_E(get_one_from_mixed_fetch_results(db, &result_set2, 1));
E(get_one_from_mixed_equal(result_set, result_set2), "result sets for same row are not equal\n");
E(get_one_from_mixed_hash(result_set) == get_one_from_mixed_hash(result_set2),
"result sets for same row do not have the same hashes\n");
cql_result_set_release(result_set);
cql_result_set_release(result_set2);
SQL_E(get_one_from_mixed_fetch_results(db, &result_set, 999));
E(get_one_from_mixed_result_count(result_set) == 0, "expected 0 rows from mixed\n");
cql_result_set_release(result_set);
tests_passed++;
return SQLITE_OK;
}
cql_code test_all_column_encoded_fetchers(sqlite3 *db) {
printf("Running column encoded fetchers test\n");
tests++;
cql_object_ref encoder = cql_copy_encoder(db);
load_encoded_table_result_set_ref result_set;
SQL_E(load_encoded_table_fetch_results(db, &result_set));
E(load_encoded_table_result_count(result_set) == 1, "expected 1 rows from result table\n");
E(cql_result_set_get_meta(result_set)->columnCount == 12, "expected 12 columns from result table\n");
load_encoded_table_result_set_ref rs = (load_encoded_table_result_set_ref)result_set;
cql_bool b0 = load_encoded_table_get_b0_value(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 0), "expected b0 is encoded\n");
cql_bool b0_exp = cql_decode_bool(encoder, b0, -1, NULL);
E(b0_exp == 0, "expected b0 is 0, value %d\n", b0_exp);
cql_int32 i0 = load_encoded_table_get_i0_value(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 1), "expected i0 is encoded\n");
cql_int32 i0_exp = cql_decode_int32(encoder, i0, -1, NULL);
E(i0_exp == 0, "expected i0 is 0, value %d\n", i0_exp);
cql_int64 l0 = load_encoded_table_get_l0_value(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 2), "expected l0 is encoded\n");
cql_int64 l0_exp = cql_decode_int64(encoder, l0, -1, NULL);
E(l0_exp == 0, "expected l0 is 0, value %lld\n", l0_exp);
cql_double d0 = load_encoded_table_get_d0_value(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 3), "expected d0 is encoded\n");
cql_double d0_exp = cql_decode_double(encoder, d0, -1, NULL);
E(d0_exp == 0.0, "expected d0 is 0.0, value %lf\n", d0_exp);
cql_string_ref s0 = load_encoded_table_get_s0(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 4), "expected s0 is encoded\n");
cql_string_ref s0_decode = cql_decode_string_ref_new(encoder, s0, -1, NULL);
cql_string_ref s0_exp = cql_string_ref_new("0");
E(cql_string_equal(s0_decode, s0_exp), "expected s0 is 0, value %s\n", s0_decode->ptr);
cql_string_release(s0_decode);
cql_string_release(s0_exp);
cql_blob_ref bl0 = load_encoded_table_get_bl0(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 5), "expected bl0 is encoded\n");
cql_blob_ref bl0_decode = cql_decode_blob_ref_new(encoder, bl0, -1, NULL);
cql_blob_ref bl0_exp = cql_blob_ref_new("0", 1);
E(cql_blob_equal(bl0_decode, bl0_exp), "expected bl0 is \"0\", value %s\n", (const char*)bl0_decode->ptr);
cql_blob_release(bl0_decode);
cql_blob_release(bl0_exp);
cql_bool b1 = load_encoded_table_get_b1(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 6), "expected b1 is encoded\n");
cql_bool b1_exp = cql_decode_bool(encoder, b1, -1, NULL);
E(b1_exp == 1, "expected b1 is 1, value %d\n", b1_exp);
cql_int32 i1 = load_encoded_table_get_i1(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 7), "expected i1 is encoded\n");
cql_int32 i1_exp = cql_decode_int32(encoder, i1, -1, NULL);
E(i1_exp == 1, "expected i1 is 1, value %d\n", i1_exp);
cql_int64 l1 = load_encoded_table_get_l1(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 8), "expected l1 is encoded\n");
cql_int64 l1_exp = cql_decode_int64(encoder, l1, -1, NULL);
E(l1_exp == 1, "expected l1 is 1, value %lld\n", l1_exp);
cql_double d1 = load_encoded_table_get_d1(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 9), "expected d1 is encoded\n");
cql_double d1_exp = cql_decode_double(encoder, d1, -1, NULL);
E(d1_exp == 1.1, "expected d1 is 1.1, value %lf\n", d1_exp);
cql_string_ref s1 = load_encoded_table_get_s1(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 10), "expected s1 is encoded\n");
cql_string_ref s1_decode = cql_decode_string_ref_new(encoder, s1, -1, NULL);
cql_string_ref s1_exp = cql_string_ref_new("1");
E(cql_string_equal(s1_decode, s1_exp), "expected s1 is 1, value %s\n", s1_decode->ptr);
cql_string_release(s1_decode);
cql_string_release(s1_exp);
cql_blob_ref bl1 = load_encoded_table_get_bl1(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 11), "expected bl1 is encoded\n");
cql_blob_ref bl1_decode = cql_decode_blob_ref_new(encoder, bl1, -1, NULL);
cql_blob_ref bl1_exp = cql_blob_ref_new("1", 1);
E(cql_blob_equal(bl1_decode, bl1_exp), "expected bl1 is \"1\", value %s\n", (const char*)bl1_decode->ptr);
cql_blob_release(bl1_decode);
cql_blob_release(bl1_exp);
cql_result_set_release(result_set);
cql_object_release(encoder);
tests_passed++;
return SQLITE_OK;
}
cql_code test_all_column_encoded_with_context_fetchers(sqlite3 *db) {
printf("Running column encoded with context fetchers test\n");
tests++;
cql_object_ref encoder = cql_copy_encoder(db);
load_encoded_with_context_table_result_set_ref result_set;
SQL_E(load_encoded_with_context_table_fetch_results(db, &result_set));
E(load_encoded_with_context_table_result_count(result_set) == 1, "expected 1 rows from result table\n");
E(cql_result_set_get_meta(result_set)->columnCount == 13, "expected 13 columns from result table\n");
load_encoded_with_context_table_result_set_ref rs = (load_encoded_with_context_table_result_set_ref)result_set;
cql_string_ref context_value = load_encoded_with_context_table_get_context(rs, 0);
char* context = (char *)&context_value;
cql_bool b0 = load_encoded_with_context_table_get_b0_value(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 0), "expected b0 is encoded\n");
cql_bool b0_exp = cql_decode_bool(encoder, b0, CQL_DATA_TYPE_STRING, context);
E(b0_exp == 0, "expected b0 is 0, value %d\n", b0_exp);
cql_int32 i0 = load_encoded_with_context_table_get_i0_value(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 1), "expected i0 is encoded\n");
cql_int32 i0_exp = cql_decode_int32(encoder, i0, CQL_DATA_TYPE_STRING, context);
E(i0_exp == 0, "expected i0 is 0, value %d\n", i0_exp);
cql_int64 l0 = load_encoded_with_context_table_get_l0_value(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 2), "expected l0 is encoded\n");
cql_int64 l0_exp = cql_decode_int64(encoder, l0, CQL_DATA_TYPE_STRING, context);
E(l0_exp == 0, "expected l0 is 0, value %lld\n", l0_exp);
cql_double d0 = load_encoded_with_context_table_get_d0_value(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 3), "expected d0 is encoded\n");
cql_double d0_exp = cql_decode_double(encoder, d0, CQL_DATA_TYPE_STRING, context);
E(d0_exp == 0.0, "expected d0 is 0.0, value %lf\n", d0_exp);
cql_string_ref s0 = load_encoded_with_context_table_get_s0(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 4), "expected s0 is encoded\n");
cql_string_ref s0_decode = cql_decode_string_ref_new(encoder, s0, CQL_DATA_TYPE_STRING, context);
cql_string_ref s0_exp = cql_string_ref_new("0");
E(cql_string_equal(s0_decode, s0_exp), "expected s0 is 0, value %s\n", s0_decode->ptr);
cql_string_release(s0_decode);
cql_string_release(s0_exp);
cql_blob_ref bl0 = load_encoded_with_context_table_get_bl0(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 5), "expected bl0 is encoded\n");
cql_blob_ref bl0_decode = cql_decode_blob_ref_new(encoder, bl0, CQL_DATA_TYPE_STRING, context);
cql_blob_ref bl0_exp = cql_blob_ref_new("0", 1);
E(cql_blob_equal(bl0_decode, bl0_exp), "expected bl0 is \"0\", value %s\n", (const char*)bl0_decode->ptr);
cql_blob_release(bl0_decode);
cql_blob_release(bl0_exp);
cql_bool b1 = load_encoded_with_context_table_get_b1(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 6), "expected b1 is encoded\n");
cql_bool b1_exp = cql_decode_bool(encoder, b1, CQL_DATA_TYPE_STRING, context);
E(b1_exp == 1, "expected b1 is 1, value %d\n", b1_exp);
cql_int32 i1 = load_encoded_with_context_table_get_i1(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 7), "expected i1 is encoded\n");
cql_int32 i1_exp = cql_decode_int32(encoder, i1, CQL_DATA_TYPE_STRING, context);
E(i1_exp == 1, "expected i1 is 1, value %d\n", i1_exp);
cql_int64 l1 = load_encoded_with_context_table_get_l1(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 8), "expected l1 is encoded\n");
cql_int64 l1_exp = cql_decode_int64(encoder, l1, CQL_DATA_TYPE_STRING, context);
E(l1_exp == 1, "expected l1 is 1, value %lld\n", l1_exp);
cql_double d1 = load_encoded_with_context_table_get_d1(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 9), "expected d1 is encoded\n");
cql_double d1_exp = cql_decode_double(encoder, d1, CQL_DATA_TYPE_STRING, context);
E(d1_exp == 1.1, "expected d1 is 1.1, value %lf\n", d1_exp);
cql_string_ref s1 = load_encoded_with_context_table_get_s1(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 10), "expected s1 is encoded\n");
cql_string_ref s1_decode = cql_decode_string_ref_new(encoder, s1, CQL_DATA_TYPE_STRING, context);
cql_string_ref s1_exp = cql_string_ref_new("1");
E(cql_string_equal(s1_decode, s1_exp), "expected s1 is 1, value %s\n", s1_decode->ptr);
cql_string_release(s1_decode);
cql_string_release(s1_exp);
cql_blob_ref bl1 = load_encoded_with_context_table_get_bl1(rs, 0);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 11), "expected bl1 is encoded\n");
cql_blob_ref bl1_decode = cql_decode_blob_ref_new(encoder, bl1, CQL_DATA_TYPE_STRING, context);
cql_blob_ref bl1_exp = cql_blob_ref_new("1", 1);
E(cql_blob_equal(bl1_decode, bl1_exp), "expected bl1 is \"1\", value %s\n", (const char*)bl1_decode->ptr);
cql_blob_release(bl1_decode);
cql_blob_release(bl1_exp);
cql_result_set_release(result_set);
cql_object_release(encoder);
tests_passed++;
return SQLITE_OK;
}
cql_code test_all_column_encoded_cursor(sqlite3 *db) {
printf("Running column encoded cursor fetchers test\n");
tests++;
cql_object_ref encoder = cql_copy_encoder(db);
load_encoded_cursor_result_set_ref result_set;
SQL_E(load_encoded_cursor_fetch_results(db, &result_set));
E(load_encoded_cursor_result_count(result_set) == 1, "expected 1 rows from result table\n");
E(cql_result_set_get_meta(result_set)->columnCount == 12, "expected 12 columns from result table\n");
load_encoded_cursor_result_set_ref rs = (load_encoded_cursor_result_set_ref)result_set;
cql_bool b0 = load_encoded_cursor_get_b0_value(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 0), "expected b0 is encoded\n");
cql_bool b0_exp = cql_decode_bool(encoder, b0, -1, NULL);
E(b0_exp == 0, "expected b0 is 0, value %d\n", b0_exp);
cql_int32 i0 = load_encoded_cursor_get_i0_value(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 1), "expected i0 is encoded\n");
cql_int32 i0_exp = cql_decode_int32(encoder, i0, -1, NULL);
E(i0_exp == 0, "expected i0 is 0, value %d\n", i0_exp);
cql_int64 l0 = load_encoded_cursor_get_l0_value(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 2), "expected l0 is encoded\n");
cql_int64 l0_exp = cql_decode_int64(encoder, l0, -1, NULL);
E(l0_exp == 0, "expected l0 is 0, value %lld\n", l0_exp);
cql_double d0 = load_encoded_cursor_get_d0_value(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 3), "expected d0 is encoded\n");
cql_double d0_exp = cql_decode_double(encoder, d0, -1, NULL);
E(d0_exp == 0.0, "expected d0 is 0.0, value %lf\n", d0_exp);
cql_string_ref s0 = load_encoded_cursor_get_s0(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 4), "expected s0 is encoded\n");
cql_string_ref s0_decode = cql_decode_string_ref_new(encoder, s0, -1, NULL);
cql_string_ref s0_exp = cql_string_ref_new("0");
E(cql_string_equal(s0_decode, s0_exp), "expected s0 is 0, value %s\n", s0_decode->ptr);
cql_string_release(s0_decode);
cql_string_release(s0_exp);
cql_blob_ref bl0 = load_encoded_cursor_get_bl0(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 5), "expected bl0 is encoded\n");
cql_blob_ref bl0_decode = cql_decode_blob_ref_new(encoder, bl0, -1, NULL);
cql_blob_ref bl0_exp = cql_blob_ref_new("0", 1);
E(cql_blob_equal(bl0_decode, bl0_exp), "expected bl0 is \"0\", value %s\n", (const char*)bl0_decode->ptr);
cql_blob_release(bl0_decode);
cql_blob_release(bl0_exp);
cql_bool b1 = load_encoded_cursor_get_b1(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 6), "expected b1 is encoded\n");
cql_bool b1_exp = cql_decode_bool(encoder, b1, -1, NULL);
E(b1_exp == 1, "expected b1 is 1, value %d\n", b1_exp);
cql_int32 i1 = load_encoded_cursor_get_i1(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 7), "expected i1 is encoded\n");
cql_int32 i1_exp = cql_decode_int32(encoder, i1, -1, NULL);
E(i1_exp == 1, "expected i1 is 1, value %d\n", i1_exp);
cql_int64 l1 = load_encoded_cursor_get_l1(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 8), "expected l1 is encoded\n");
cql_int64 l1_exp = cql_decode_int64(encoder, l1, -1, NULL);
E(l1_exp == 1, "expected l1 is 1, value %lld\n", l1_exp);
cql_double d1 = load_encoded_cursor_get_d1(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 9), "expected d1 is encoded\n");
cql_double d1_exp = cql_decode_double(encoder, d1, -1, NULL);
E(d1_exp == 1.1, "expected d1 is 1.1, value %lf\n", d1_exp);
cql_string_ref s1 = load_encoded_cursor_get_s1(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 10), "expected s1 is encoded\n");
cql_string_ref s1_decode = cql_decode_string_ref_new(encoder, s1, -1, NULL);
cql_string_ref s1_exp = cql_string_ref_new("1");
E(cql_string_equal(s1_decode, s1_exp), "expected s1 is 1, value %s\n", s1_decode->ptr);
cql_string_release(s1_decode);
cql_string_release(s1_exp);
cql_blob_ref bl1 = load_encoded_cursor_get_bl1(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 11), "expected bl1 is encoded\n");
cql_blob_ref bl1_decode = cql_decode_blob_ref_new(encoder, bl1, -1, NULL);
cql_blob_ref bl1_exp = cql_blob_ref_new("1", 1);
E(cql_blob_equal(bl1_decode, bl1_exp), "expected bl1 is \"1\", value %s\n", (const char*)bl1_decode->ptr);
cql_blob_release(bl1_decode);
cql_blob_release(bl1_exp);
cql_result_set_release(result_set);
cql_object_release(encoder);
tests_passed++;
return SQLITE_OK;
}
cql_code test_all_column_encoded_out_union(sqlite3 *db) {
printf("Running column encoded out union fetchers test\n");
tests++;
cql_object_ref encoder = cql_copy_encoder(db);
load_decoded_out_union_result_set_ref result_set;
SQL_E(load_decoded_out_union_fetch_results(db, &result_set));
E(load_decoded_out_union_result_count(result_set) == 1, "expected 1 row from result table\n");
E(cql_result_set_get_meta(result_set)->columnCount == 12, "expected 12 columns from result table\n");
load_decoded_out_union_result_set_ref rs = (load_decoded_out_union_result_set_ref)result_set;
cql_bool b0 = load_decoded_out_union_get_b0_value(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 0), "expected b0 is encoded\n");
cql_bool b0_exp = cql_decode_bool(encoder, b0, -1, NULL);
E(b0_exp == 0, "expected b0 is 0, value %d\n", b0_exp);
cql_int32 i0 = load_decoded_out_union_get_i0_value(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 1), "expected i0 is encoded\n");
cql_int32 i0_exp = cql_decode_int32(encoder, i0, -1, NULL);
E(i0_exp == 0, "expected i0 is 0, value %d\n", i0_exp);
cql_int64 l0 = load_decoded_out_union_get_l0_value(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 2), "expected l0 is encoded\n");
cql_int64 l0_exp = cql_decode_int64(encoder, l0, -1, NULL);
E(l0_exp == 0, "expected l0 is 0, value %lld\n", l0_exp);
cql_double d0 = load_decoded_out_union_get_d0_value(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 3), "expected d0 is encoded\n");
cql_double d0_exp = cql_decode_double(encoder, d0, -1, NULL);
E(d0_exp == 0.0, "expected d0 is 0.0, value %lf\n", d0_exp);
cql_string_ref s0 = load_decoded_out_union_get_s0(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 4), "expected s0 is encoded\n");
cql_string_ref s0_decode = cql_decode_string_ref_new(encoder, s0, -1, NULL);
cql_string_ref s0_exp = cql_string_ref_new("0");
E(cql_string_equal(s0_decode, s0_exp), "expected s0 is 0, value %s\n", s0_decode->ptr);
cql_string_release(s0_decode);
cql_string_release(s0_exp);
cql_blob_ref bl0 = load_decoded_out_union_get_bl0(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 5), "expected bl0 is encoded\n");
cql_blob_ref bl0_decode = cql_decode_blob_ref_new(encoder, bl0, -1, NULL);
cql_blob_ref bl0_exp = cql_blob_ref_new("0", 1);
E(cql_blob_equal(bl0_decode, bl0_exp), "expected bl0 is \"0\", value %s\n", (const char *)bl0_decode->ptr);
cql_blob_release(bl0_decode);
cql_blob_release(bl0_exp);
cql_bool b1 = load_decoded_out_union_get_b1(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 6), "expected b1 is encoded\n");
cql_bool b1_exp = cql_decode_bool(encoder, b1, -1, NULL);
E(b1_exp == 1, "expected b1 is 1, value %d\n", b1_exp);
cql_int32 i1 = load_decoded_out_union_get_i1(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 7), "expected i1 is encoded\n");
cql_int32 i1_exp = cql_decode_int32(encoder, i1, -1, NULL);
E(i1_exp == 1, "expected i1 is 1, value %d\n", i1_exp);
cql_int64 l1 = load_decoded_out_union_get_l1(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 8), "expected l1 is encoded\n");
cql_int64 l1_exp = cql_decode_int64(encoder, l1, -1, NULL);
E(l1_exp == 1, "expected l1 is 1, value %lld\n", l1_exp);
cql_double d1 = load_decoded_out_union_get_d1(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 9), "expected d1 is encoded\n");
cql_double d1_exp = cql_decode_double(encoder, d1, -1, NULL);
E(d1_exp == 1.1, "expected d1 is 1.1, value %lf\n", d1_exp);
cql_string_ref s1 = load_decoded_out_union_get_s1(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 10), "expected s1 is encoded\n");
cql_string_ref s1_decode = cql_decode_string_ref_new(encoder, s1, -1, NULL);
cql_string_ref s1_exp = cql_string_ref_new("1");
E(cql_string_equal(s1_decode, s1_exp), "expected s1 is 1, value %s\n", s1_decode->ptr);
cql_string_release(s1_decode);
cql_string_release(s1_exp);
cql_blob_ref bl1 = load_decoded_out_union_get_bl1(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 11), "expected bl1 is encoded\n");
cql_blob_ref bl1_decode = cql_decode_blob_ref_new(encoder, bl1, -1, NULL);
cql_blob_ref bl1_exp = cql_blob_ref_new("1", 1);
E(cql_blob_equal(bl1_decode, bl1_exp), "expected bl1 is \"1\", value %s\n", (const char *)bl1_decode->ptr);
cql_blob_release(bl1_decode);
cql_blob_release(bl1_exp);
cql_result_set_release(result_set);
cql_object_release(encoder);
tests_passed++;
return SQLITE_OK;
}
cql_code test_all_column_encoded_runtime_turn_on_off(sqlite3 *db) {
printf("Running column encoded turn off fetchers test\n");
tests++;
cql_object_ref encoder = cql_copy_encoder(db);
load_decoded_multi_out_union_result_set_ref result_set;
SQL_E(load_decoded_multi_out_union_fetch_results(db, &result_set));
E(load_decoded_multi_out_union_result_count(result_set) == 2, "expected 2 rows from result table\n");
E(cql_result_set_get_meta(result_set)->columnCount == 12, "expected 12 columns from result table\n");
load_decoded_multi_out_union_result_set_ref rs = (load_decoded_multi_out_union_result_set_ref)result_set;
cql_bool b0 = load_decoded_multi_out_union_get_b0_value(rs, 1);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 0), "expected b0 is encoded\n");
cql_bool b0_exp = cql_decode_bool(encoder, b0, -1, NULL);
E(b0_exp == 0, "expected b0 is 0, value %d\n", b0_exp);
cql_result_set_release(result_set);
load_decoded_multi_out_union_set_encoding(0, false);
SQL_E(load_decoded_multi_out_union_fetch_results(db, &result_set));
rs = (load_decoded_multi_out_union_result_set_ref)result_set;
b0 = load_decoded_multi_out_union_get_b0_value(rs, 1);
E(!cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 0), "expected b0 is encoded\n");
E(b0 == 0, "expected b0 is 0, value %d\n", b0);
cql_result_set_release(result_set);
load_decoded_multi_out_union_set_encoding(0, true);
SQL_E(load_decoded_multi_out_union_fetch_results(db, &result_set));
rs = (load_decoded_multi_out_union_result_set_ref)result_set;
b0 = load_decoded_multi_out_union_get_b0_value(rs, 1);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 0), "expected b0 is encoded\n");
b0_exp = cql_decode_bool(encoder, b0, -1, NULL);
E(b0_exp == 0, "expected b0 is 0, value %d\n", b0_exp);
cql_result_set_release(result_set);
cql_object_release(encoder);
tests_passed++;
return SQLITE_OK;
}
cql_code test_all_column_encoded_multi_out_union(sqlite3 *db) {
printf("Running column encoded multi out union fetchers test\n");
tests++;
cql_object_ref encoder = cql_copy_encoder(db);
load_decoded_multi_out_union_result_set_ref result_set;
SQL_E(load_decoded_multi_out_union_fetch_results(db, &result_set));
E(load_decoded_multi_out_union_result_count(result_set) == 2, "expected 2 rows from result table\n");
E(cql_result_set_get_meta(result_set)->columnCount == 12, "expected 12 columns from result table\n");
load_decoded_multi_out_union_result_set_ref rs = (load_decoded_multi_out_union_result_set_ref)result_set;
cql_bool b0 = load_decoded_multi_out_union_get_b0_value(rs, 1);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 0), "expected b0 is encoded\n");
E(load_decoded_multi_out_union_get_b0_is_encoded(rs), "expected b0 is encoded\n");
cql_bool b0_exp = cql_decode_bool(encoder, b0, -1, NULL);
E(b0_exp == 0, "expected b0 is 0, value %d\n", b0_exp);
cql_int32 i0 = load_decoded_multi_out_union_get_i0_value(rs, 1);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 1), "expected i0 is encoded\n");
cql_int32 i0_exp = cql_decode_int32(encoder, i0, -1, NULL);
E(i0_exp == 0, "expected i0 is 0, value %d\n", i0_exp);
cql_int64 l0 = load_decoded_multi_out_union_get_l0_value(rs, 1);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 2), "expected l0 is encoded\n");
cql_int64 l0_exp = cql_decode_int64(encoder, l0, -1, NULL);
E(l0_exp == 0, "expected l0 is 0, value %lld\n", l0_exp);
cql_double d0 = load_decoded_multi_out_union_get_d0_value(rs, 1);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 3), "expected dd0 is encoded\n");
cql_double d0_exp = cql_decode_double(encoder, d0, -1, NULL);
E(d0_exp == 0.0, "expected d0 is 0.0, value %lf\n", d0_exp);
cql_string_ref s0 = load_decoded_multi_out_union_get_s0(rs, 1);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 4), "expected s0 is encoded\n");
cql_string_ref s0_decode = cql_decode_string_ref_new(encoder, s0, -1, NULL);
cql_string_ref s0_exp = cql_string_ref_new("0");
E(cql_string_equal(s0_decode, s0_exp), "expected s0 is 0, value %s\n", s0_decode->ptr);
cql_string_release(s0_decode);
cql_string_release(s0_exp);
cql_blob_ref bl0 = load_decoded_multi_out_union_get_bl0(rs, 1);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 5), "expected bl0 is encoded\n");
cql_blob_ref bl0_decode = cql_decode_blob_ref_new(encoder, bl0, -1, NULL);
cql_blob_ref bl0_exp = cql_blob_ref_new("0", 1);
E(cql_blob_equal(bl0_decode, bl0_exp), "expected bl0 is \"0\", value \"%s\"\n", (const char *)bl0_decode->ptr);
cql_blob_release(bl0_decode);
cql_blob_release(bl0_exp);
cql_bool b1 = load_decoded_multi_out_union_get_b1(rs, 1);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 6), "expected b1 is encoded\n");
cql_bool b1_exp = cql_decode_bool(encoder, b1, -1, NULL);
E(b1_exp == 1, "expected b1 is 1, value %d\n", b1_exp);
cql_int32 i1 = load_decoded_multi_out_union_get_i1(rs, 1);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 7), "expected i1 is encoded\n");
cql_int32 i1_exp = cql_decode_int32(encoder, i1, -1, NULL);
E(i1_exp == 1, "expected i1 is 1, value %d\n", i1_exp);
cql_int64 l1 = load_decoded_multi_out_union_get_l1(rs, 1);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 8), "expected l1 is encoded\n");
cql_int64 l1_exp = cql_decode_int64(encoder, l1, -1, NULL);
E(l1_exp == 1, "expected l1 is 1, value %lld\n", l1_exp);
cql_double d1 = load_decoded_multi_out_union_get_d1(rs, 1);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 9), "expected d1 is encoded\n");
cql_double d1_exp = cql_decode_double(encoder, d1, -1, NULL);
E(d1_exp == 1.1, "expected d1 is 1.1, value %lf\n", d1_exp);
cql_string_ref s1 = load_decoded_multi_out_union_get_s1(rs, 1);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 10), "expected s1 is encoded\n");
cql_string_ref s1_decode = cql_decode_string_ref_new(encoder, s1, -1, NULL);
cql_string_ref s1_exp = cql_string_ref_new("1");
E(cql_string_equal(s1_decode, s1_exp), "expected s1 is 1, value %s\n", s1_decode->ptr);
cql_string_release(s1_decode);
cql_string_release(s1_exp);
cql_blob_ref bl1 = load_decoded_multi_out_union_get_bl1(rs, 1);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 11), "expected bl1 is encoded\n");
cql_blob_ref bl1_decode = cql_decode_blob_ref_new(encoder, bl1, -1, NULL);
cql_blob_ref bl1_exp = cql_blob_ref_new("1", 1);
E(cql_blob_equal(bl1_decode, bl1_exp), "expected bl1 is \"1\", value \"%s\"\n", (const char *)bl1_decode->ptr);
cql_blob_release(bl1_decode);
cql_blob_release(bl1_exp);
cql_result_set_release(result_set);
cql_object_release(encoder);
tests_passed++;
return SQLITE_OK;
}
cql_code test_all_column_some_encoded_field(sqlite3 *db) {
printf("Running column some encoded field fetchers test\n");
tests++;
cql_object_ref encoder = cql_copy_encoder(db);
load_some_encoded_field_result_set_ref result_set;
SQL_E(load_some_encoded_field_fetch_results(db, &result_set));
E(load_some_encoded_field_result_count(result_set) == 1, "expected 1 rows from result table\n");
E(cql_result_set_get_meta(result_set)->columnCount == 2, "expected 2 columns from result table\n");
load_some_encoded_field_result_set_ref rs = (load_some_encoded_field_result_set_ref)result_set;
cql_int32 x = load_some_encoded_field_get_x_value(rs);
E(!cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 0), "expected x is not encoded\n");
E(x == 66, "expected x is 66, value %d\n", x);
cql_string_ref y = load_some_encoded_field_get_y(rs);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 1), "expected y is encoded\n");
cql_string_ref y_decode = cql_decode_string_ref_new(encoder, y, -1, NULL);
cql_string_ref y_exp = cql_string_ref_new("bogus");
E(cql_string_equal(y_decode, y_exp), "expected y is \"bogus\", value %s\n", y_decode->ptr);
cql_string_release(y_decode);
cql_string_release(y_exp);
cql_result_set_release(result_set);
cql_object_release(encoder);
tests_passed++;
return SQLITE_OK;
}
cql_code test_all_column_some_encoded_field_with_encode_context(sqlite3 *db) {
printf("Running column some encoded field with encode context fetchers test\n");
tests++;
cql_object_ref encoder = cql_copy_encoder(db);
load_some_encoded_field_with_encode_context_result_set_ref result_set;
SQL_E(load_some_encoded_field_with_encode_context_fetch_results(db, &result_set));
E(load_some_encoded_field_with_encode_context_result_count(result_set) == 1, "expected 1 rows from result table\n");
E(cql_result_set_get_meta(result_set)->columnCount == 3, "expected 3 columns from result table\n");
load_some_encoded_field_with_encode_context_result_set_ref rs = (load_some_encoded_field_with_encode_context_result_set_ref)result_set;
cql_string_ref y = load_some_encoded_field_with_encode_context_get_y(rs);
cql_string_ref y_encoded_exp = cql_string_ref_new("bogus#context");
E(cql_string_equal(y, y_encoded_exp), "expected y is \"bogus#context\", value %s\n", y->ptr);
cql_string_release(y_encoded_exp);
E(cql_result_set_get_is_encoded_col((cql_result_set_ref)rs, 1), "expected y is encoded\n");
cql_string_ref z = load_some_encoded_field_with_encode_context_get_z(rs);
cql_string_ref y_decode = cql_decode_string_ref_new(encoder, y, CQL_DATA_TYPE_STRING, (char *)&z);
cql_string_ref y_exp = cql_string_ref_new("bogus");
E(cql_string_equal(y_decode, y_exp), "expected y is \"bogus\", value %s\n", y_decode->ptr);
cql_string_release(y_decode);
cql_string_release(y_exp);
cql_result_set_release(result_set);
cql_object_release(encoder);
tests_passed++;
return SQLITE_OK;
}
cql_code test_all_column_fetchers(sqlite3 *db) {
printf("Running column fetchers test\n");
tests++;
// test object
cql_object_ref set = set_create();
emit_object_result_set_result_set_ref object_result_set;
emit_object_result_set_fetch_results(&object_result_set, set);
E(emit_object_result_set_result_count(object_result_set) == 2, "expected 2 rows from the object union\n");
for (int32_t row = 0; row <= 1; row++) {
for (int32_t col = 0; col < 1; col++) {
cql_bool is_null = cql_result_set_get_is_null_col((cql_result_set_ref)object_result_set, row, col);
cql_bool is_null_expected = (row == 1) && col == 0;
E(is_null == is_null_expected, "expected is_null did not match seed data, row %d, col %d\n", row, col);
}
}
cql_object_ref _Nullable object = cql_result_set_get_object_col((cql_result_set_ref)object_result_set, 1, 0);
E(!object, "expected object to be null\n");
cql_object_ref new_set = set_create();
cql_result_set_set_object_col((cql_result_set_ref)object_result_set, 1, 0, new_set);
object = cql_result_set_get_object_col((cql_result_set_ref)object_result_set, 1, 0);
E(object, "expected not null object\n");
cql_result_set_set_object_col((cql_result_set_ref)object_result_set, 1, 0, NULL);
cql_object_release(set);
cql_object_release(new_set);
cql_result_set_release(object_result_set);
load_all_types_table_result_set_ref result_set;
SQL_E(load_all_types_table_fetch_results(db, &result_set));
E(load_all_types_table_result_count(result_set) == 2, "expected 2 rows from result table\n");
E(cql_result_set_get_meta(result_set)->columnCount == 12, "expected 12 columns from result table\n");
cql_result_set_ref rs = (cql_result_set_ref)result_set;
for (int32_t row = 0; row <= 1; row++) {
for (int32_t col = 0; col < 12; col++) {
cql_bool is_null = cql_result_set_get_is_null_col(rs, row, col);
cql_bool is_null_expected = (row == 0) && col < 6;
E(is_null == is_null_expected, "expected is_null did not match seed data, row %d, col %d\n", row, col);
}
}
for (int32_t row = 0; row <= 1; row++) {
for (int32_t col = 0; col < 12; col++) {
cql_bool is_null_expected = (row == 0) && col < 6;
if (is_null_expected) {
continue;
}
switch (col % 6) {
case 0: {
// bool
E(cql_result_set_get_bool_col(rs, row, col) == row,
"expected bool did not match seed data, row %d, col %d\n", row, col);
cql_nullable_bool new_value;
cql_set_notnull(new_value, !row);
cql_result_set_set_bool_col(rs, row, col, new_value);
E(cql_result_set_get_bool_col(rs, row, col) == !row,
"expected bool did not match seed data, row %d, col %d\n", !row, col);
cql_result_set_set_bool_col_not_null(rs, row, col, row);
E(cql_result_set_get_bool_col(rs, row, col) == row,
"expected bool did not match seed data, row %d, col %d\n", row, col);
break;
}
case 1: {
// int32
E(cql_result_set_get_int32_col(rs, row, col) == row,
"expected int32 did not match seed data, row %d, col %d\n", row, col);
cql_nullable_int32 new_value;
cql_set_notnull(new_value, row + 19);
cql_result_set_set_int32_col(rs, row, col, new_value);
E(cql_result_set_get_int32_col(rs, row, col) == row + 19,
"expected int32 did not match seed data, row %d, col %d\n", row + 19, col);
cql_result_set_set_int32_col_not_null(rs, row, col, row + 20);
E(cql_result_set_get_int32_col(rs, row, col) == row + 20,
"expected int32 did not match seed data, row %d, col %d\n", row + 20, col);
break;
}
case 2: {
// int64
E(cql_result_set_get_int64_col(rs, row, col) == row,
"expected int64 did not match seed data, row %d, col %d\n", row, col);
cql_nullable_int64 new_value;
cql_set_notnull(new_value, row + 29);
cql_result_set_set_int64_col(rs, row, col, new_value);
E(cql_result_set_get_int64_col(rs, row, col) == row + 29,
"expected int64 did not match seed data, row %d, col %d\n", row + 29, col);
cql_result_set_set_int64_col_not_null(rs, row, col, row + 30);
E(cql_result_set_get_int64_col(rs, row, col) == row + 30,
"expected int64 did not match seed data, row %d, col %d\n", row + 30, col);
break;
}
case 3: {
// double
E(cql_result_set_get_double_col(rs, row, col) == row,
"expected double did not match seed data, row %d, col %d\n", row, col);
cql_nullable_double new_value;
cql_set_notnull(new_value, row + 39);
cql_result_set_set_double_col(rs, row, col, new_value);
E(cql_result_set_get_double_col(rs, row, col) == row + 39,
"expected double did not match seed data, row %d, col %d\n", row + 39, col);
cql_result_set_set_double_col_not_null(rs, row, col, row + 40);
E(cql_result_set_get_double_col(rs, row, col) == row + 40,
"expected double did not match seed data, row %d, col %d\n", row + 40, col);
break;
}
case 4: {
// string
// expected results:
// s1_0 (row 0) (s0 will be null)
// s0_1 (row 1)
// s1_1 (row 1)
cql_string_ref str = cql_result_set_get_string_col(rs, row, col);
const char *expected = row == 0 ? "s1_0" : col < 6 ? "s0_1" : "s1_1";
E(strcmp(str->ptr, expected) == 0, "expected string did not match seed data, row %d, col %d\n", row, col);
cql_string_ref updated = string_create();
cql_result_set_set_string_col(rs, row, col, updated);
str = cql_result_set_get_string_col(rs, row, col);
E(strcmp(str->ptr, updated->ptr) == 0, "expected string did not match seed data, row %d, col %d\n", row, col);
cql_string_release(updated);
cql_result_set_set_string_col(rs, row, col, NULL);
cql_string_ref _Nullable nullable_str = cql_result_set_get_string_col(rs, row, col);
E(nullable_str == NULL, "expected string to be nil");
break;
}
case 5: {
// blob
// expected results (size, data)
// 5, bl1_0
// 5, bl0_1
// 5, bl1_1
cql_blob_ref bl = cql_result_set_get_blob_col(rs, row, col);
const char *expected = row == 0 ? "bl1_0" : col < 6 ? "bl0_1" : "bl1_1";
E(bl->size == 5 && memcmp(bl->ptr, expected, 5) == 0,
"expected blob did not match seed data, row %d, col %d\n", row, col);
cql_string_ref str_blob = string_create();
cql_blob_ref updated_bl = blob_from_string(str_blob);
cql_result_set_set_blob_col(rs, row, col, updated_bl);
bl = cql_result_set_get_blob_col(rs, row, col);
E(bl->size == 13 && memcmp(bl->ptr, "Hello, world.", 13) == 0,
"expected blob did not match seed data, row %d, col %d\n", row, col);
cql_string_release(str_blob);
cql_blob_release(updated_bl);
break;
}
}
}
}
// check nullability setters
cql_int32 row = 0;
// bool
E(load_all_types_table_get_b0_is_null(result_set, row) == true, "b0 expected to be null at 0\n");
load_all_types_table_set_b0_value(result_set, row, true);
E(load_all_types_table_get_b0_is_null(result_set, row) == false, "b0 expected not to be null at 0\n");
load_all_types_table_set_b0_to_null(result_set, row);
E(load_all_types_table_get_b0_is_null(result_set, row) == true, "b0 expected to be null after _to_null\n");
// int32
cql_int32 new_int32 = 10;
E(load_all_types_table_get_i0_is_null(result_set, row) == true, "i0 expected to be null at 0\n");
load_all_types_table_set_i0_value(result_set, row, new_int32);
E(load_all_types_table_get_i0_is_null(result_set, row) == false, "i0 expected not to be null at 0\n");
load_all_types_table_set_i0_to_null(result_set, row);
E(load_all_types_table_get_i0_is_null(result_set, row) == true, "i0 expected to be null after _to_null\n");
// int64
cql_int64 new_int64 = 99;
E(load_all_types_table_get_l0_is_null(result_set, row) == true, "l0 expected to be null at 0\n");
load_all_types_table_set_l0_value(result_set, row, new_int64);
E(load_all_types_table_get_l0_is_null(result_set, row) == false, "l0 expected not to be null at 0\n");
load_all_types_table_set_l0_to_null(result_set, row);
E(load_all_types_table_get_l0_is_null(result_set, row) == true, "l0 expected to be null after _to_null\n");
// double
cql_double new_double = 200;
E(load_all_types_table_get_d0_is_null(result_set, row) == true, "d0 expected to be null at 0\n");
load_all_types_table_set_d0_value(result_set, row, new_double);
E(load_all_types_table_get_d0_is_null(result_set, row) == false, "d0 expected not to be null at 0\n");
load_all_types_table_set_d0_to_null(result_set, row);
E(load_all_types_table_get_d0_is_null(result_set, row) == true, "d0 expected to be null after _to_null\n");
cql_result_set_release(result_set);
tests_passed++;
return SQLITE_OK;
}
cql_code test_error_case_rowset(sqlite3 *db) {
printf("Running error case rowset test\n");
tests++;
SQL_E(load_sparse_blobs(db));
steps_until_fail = 5;
get_blob_table_result_set_ref result_set;
E(SQLITE_OK != get_blob_table_fetch_results(db, &result_set), "blob table error case failed\n");
E(!result_set, "expected null result set for blob table");
tests_passed++;
return SQLITE_OK;
}
int32_t autodrop_count = 1;
cql_code test_autodrop_rowset(sqlite3 *db) {
// this test runs twice to ensure it cleans up after itself including the tables being dropped
printf("Running autodrop rowset test (pass %d)\n", autodrop_count++);
tests++;
read_three_tables_and_autodrop_result_set_ref result_set;
SQL_E(SQLITE_OK != read_three_tables_and_autodrop_fetch_results(db, &result_set));
for (cql_int32 i = 0; i < 3; i++) {
int32_t id = read_three_tables_and_autodrop_get_id(result_set, i);
E(i+1 == id, "id %d did not match %d\n", id, i+1);
}
cql_result_set_release(result_set);
tests_passed++;
return SQLITE_OK;
}
cql_code test_one_row_result(sqlite3 *db) {
// this test runs twice to ensure it cleans up after itself including the tables being dropped
printf("Running autodrop rowset test (pass %d)\n", autodrop_count++);
tests++;
simple_cursor_proc_result_set_ref result_set;
simple_cursor_proc_fetch_results(&result_set);
int32_t id = simple_cursor_proc_get_id(result_set);
E(1 == id, "id %d did not match %d\n", id, 1);
cql_result_set_release(result_set);
tests_passed++;
return SQLITE_OK;
}
cql_code test_cql_bytebuf_open(sqlite3 *db) {
printf("Running cql_bytebuf_open test\n");
tests++;
cql_bytebuf b;
cql_bytebuf_open(&b);
int32_t max = b.max;
int32_t used = b.used;
cql_bytebuf_close(&b);
E(max == BYTEBUF_GROWTH_SIZE,
"max %d did not match expected value %d\n",
max,
BYTEBUF_GROWTH_SIZE);
E(used == 0, "used %d did not match expected value %d\n", used, 0);
tests_passed++;
return SQLITE_OK;
}
cql_code test_cql_bytebuf_alloc_within_bytebuf_exp_growth_cap(sqlite3 *db) {
printf("Running cql_bytebuf_alloc_within_bytebuf_exp_growth_cap test\n");
tests++;
cql_bytebuf b;
cql_bytebuf_open(&b);
int32_t init_size = b.max;
int32_t init_used = b.used;
int32_t needed = init_size + 10;
cql_bytebuf_alloc(&b, needed);
int32_t max = b.max;
int32_t used = b.used;
cql_bytebuf_close(&b);
E(max == 2 * init_size + needed,
"max %d did not match expected value %d\n",
max,
2 * init_size + needed);
E(used == init_used + needed,
"used %d did not match expected value %d\n",
used,
init_used + needed);
tests_passed++;
return SQLITE_OK;
}
cql_code test_cql_bytebuf_alloc_over_bytebuf_exp_growth_cap(sqlite3 *db) {
printf("Running cql_bytebuf_alloc_over_bytebuf_exp_growth_cap test\n");
tests++;
cql_bytebuf b;
cql_bytebuf_open(&b);
int32_t init_size = b.max;
int32_t init_used = b.used;
int32_t needed = BYTEBUF_EXP_GROWTH_CAP;
cql_bytebuf_alloc(&b, needed);
E(b.max == needed + 2 * init_size,
"max %d did not match expected value %d\n",
b.max,
needed + 2 * init_size);
E(b.used == init_used + needed,
"used %d did not match expected value %d\n",
b.used,
init_used + needed);
init_size = b.max;
init_used = b.used;
needed = 2 * BYTEBUF_GROWTH_SIZE + 10;
cql_bytebuf_alloc(&b, needed);
int32_t max = b.max;
int32_t used = b.used;
cql_bytebuf_close(&b);
E(max == init_size + needed + BYTEBUF_GROWTH_SIZE_AFTER_CAP,
"max %d did not match expected value %d\n",
max,
init_size + needed + BYTEBUF_GROWTH_SIZE_AFTER_CAP);
E(used == init_used + needed,
"used %d did not match expected value %d\n",
used,
init_used + needed);
tests_passed++;
return SQLITE_OK;
}
// Verify that we hit a tripwire in all of the appropriate cases and avoid them
// otherwise.
cql_code test_cql_contract_argument_notnull_tripwires(sqlite3 *db) {
printf("Running cql_contract_argument_notnull_tripwires test\n");
tests++;
jmp_buf tripwire_jmp_buf;
// This causes `cql_contract_argument_notnull` (and its `_when_dereferenced`
// variant) to longjmp instead of calling `cql_tripwire`.
cql_contract_argument_notnull_tripwire_jmp_buf = &tripwire_jmp_buf;
// Used for IN TEXT NOT NULL and INOUT TEXT NOT NULL arguments.
cql_string_ref string = string_create();
// Used for OUT NOT NULL arguments and bogus INOUT NOT NULL arguments.
cql_string_ref null_string = NULL;
// Test passing NULL when we're not supposed to. We do this one argument at a
// time to exercise all possible code paths.
for (int32_t position = 1; position <= 12; position++) {
// `position_failed` will hold the position of the argument that failed,
// counting from 1.
int position_failed = 0;
if (!(position_failed = setjmp(tripwire_jmp_buf))) {
proc_with_notnull_args(
// Arguments 1-8 have dedicated contract functions. Each case gets
// tested twice just to pad us out to the 9-or-greater case. INOUT can
// fail two different ways so we test both.
position == 1 ? NULL : string, // IN
position == 2 ? NULL : string, // IN
position == 3 ? NULL : &null_string, // OUT
position == 4 ? NULL : &null_string, // OUT
position == 5 ? NULL : &string, // INOUT
position == 6 ? NULL : &string, // INOUT
position == 7 ? &null_string : &string, // INOUT
position == 8 ? &null_string : &string, // INOUT
position == 9 ? NULL : string, // IN
position == 10 ? NULL : &null_string, // OUT
position == 11 ? NULL : &string, // INOUT
position == 12 ? &null_string : &string // INOUT
);
}
E(position != 0, "expected tripwire but did not hit one\n");
E(position == position_failed,
"expected tripwire for position %d but hit one for %d\n",
position,
position_failed);
}
// Allow `cql_contract_argument_notnull` to call `cql_tripwire` again.
cql_contract_argument_notnull_tripwire_jmp_buf = NULL;
cql_string_release(string);
tests_passed++;
return SQLITE_OK;
}
cql_code some_integers_fetch(
sqlite3 *_Nonnull _db_,
cql_object_ref _Nullable *_Nonnull rs,
cql_int32 start,
cql_int32 stop) {
return some_integers_fetch_results(_db_, (some_integers_result_set_ref _Nullable *_Nonnull)rs, start, stop);
}
// get the indexed character and return it as an integer for CQL consumpsion
cql_int32 get_blob_byte(cql_blob_ref b, cql_int32 i) {
return (cql_int32)(((uint8_t *)cql_get_blob_bytes(b))[i]);
}
// This is lossy but that's ok, this is only a test helper
// we can't test blobs > 2G with this but that's not what
// we use this for anyway.
cql_int32 get_blob_size(cql_blob_ref b) {
return (cql_int32)cql_get_blob_size(b);
}
// for making buffers that are broken
cql_blob_ref create_truncated_blob(cql_blob_ref b, cql_int32 new_size) {
cql_int32 existing_size = cql_get_blob_size(b);
cql_contract(new_size <= existing_size);
return cql_blob_ref_new(cql_get_blob_bytes(b), new_size);
}
static int32_t rand_state = 0;
// to ensure we can get the same series again (this is public)
void rand_reset() {
rand_state = 0;
}
// This random number generator doesn't have to be very good
// but I can't use anything that looks standard because of who
// knows what copyright issues I might face for daring to use the same
// integers in linear congruence math. So for this lame thing I picked my
// own constants out of thin air and I have no idea if they are any good
// but they are my own and really we just don't care that much.
static int32_t seriously_lousy_rand() {
rand_state = (rand_state * 1302475243 + 21493) & 0x7fffffff;
return rand_state;
}
// We are about to break all the rules to corrupt this blob
// mutating the blob in place because we know how.
void corrupt_blob_with_invalid_shenanigans(cql_blob_ref b) {
cql_int32 size = cql_get_blob_size(b);
uint8_t *bytes = (uint8_t *)cql_get_blob_bytes(b);
for (int32_t i = 0; i < 20; i++) {
uint32_t index = seriously_lousy_rand() % size;
uint8_t byte = seriously_lousy_rand() & 0xff;
// smash
bytes[index] = byte;
}
}