diff --git a/lib/db/jdb-iterator.c b/lib/db/jdb-iterator.c index df8c66919..a7ae51c87 100644 --- a/lib/db/jdb-iterator.c +++ b/lib/db/jdb-iterator.c @@ -56,8 +56,6 @@ j_db_iterator_new(JDBSchema* schema, JDBSelector* selector, GError** error) if (selector) { - j_db_selector_finalize(selector, error); - iterator->selector = j_db_selector_ref(selector); if (G_UNLIKELY(!iterator->selector)) diff --git a/meson.build b/meson.build index b4c686a4f..86e0f27d6 100644 --- a/meson.build +++ b/meson.build @@ -537,6 +537,9 @@ julea_test_srcs = files([ 'test/core/message.c', 'test/core/semantics.c', 'test/db/db.c', + 'test/db/db-entry.c', + 'test/db/db-schema.c', + 'test/db/db-selector.c', 'test/hdf5/hdf.c', 'test/hdf5/hdf-attribute.c', 'test/hdf5/hdf-dataset.c', diff --git a/test/core/semantics.c b/test/core/semantics.c index d59520598..f77f2b9a0 100644 --- a/test/core/semantics.c +++ b/test/core/semantics.c @@ -79,9 +79,39 @@ test_semantics_set_get(JSemantics** semantics, G_GNUC_UNUSED gconstpointer data) J_TEST_TRAP_END; } +static void +test_core_semantics_from_string(void) +{ + g_autoptr(JSemantics) semantics = NULL; + gint ret; + gchar semantics_string[] = "atomicity=operation,consistency=eventual,persistency=network,security=strict"; + + J_TEST_TRAP_START; + + semantics = j_semantics_new_from_string(NULL, semantics_string); + g_assert_nonnull(semantics); + if (g_test_failed()) + return; + + ret = j_semantics_get(semantics, J_SEMANTICS_ATOMICITY); + g_assert_cmpint(ret, ==, J_SEMANTICS_ATOMICITY_OPERATION); + + ret = j_semantics_get(semantics, J_SEMANTICS_CONSISTENCY); + g_assert_cmpint(ret, ==, J_SEMANTICS_CONSISTENCY_EVENTUAL); + + ret = j_semantics_get(semantics, J_SEMANTICS_PERSISTENCY); + g_assert_cmpint(ret, ==, J_SEMANTICS_PERSISTENCY_NETWORK); + + ret = j_semantics_get(semantics, J_SEMANTICS_SECURITY); + g_assert_cmpint(ret, ==, J_SEMANTICS_SECURITY_STRICT); + + J_TEST_TRAP_END; +} + void test_core_semantics(void) { g_test_add_func("/core/semantics/new_ref_unref", test_semantics_new_ref_unref); g_test_add("/core/semantics/set_get", JSemantics*, NULL, test_semantics_fixture_setup, test_semantics_set_get, test_semantics_fixture_teardown); + g_test_add_func("/core/semantics/from_string", test_core_semantics_from_string); } diff --git a/test/db/db-entry.c b/test/db/db-entry.c new file mode 100644 index 000000000..d6e05c2d0 --- /dev/null +++ b/test/db/db-entry.c @@ -0,0 +1,404 @@ +/* + * JULEA - Flexible storage framework + * Copyright (C) 2021 Timm Leon Erxleben + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include + +#include +#include + +#include +#include + +#include "test.h" + +#define EPS 1e-9 + +static void +test_db_entry_new_free(void) +{ + guint const n = 100000; + + J_TEST_TRAP_START; + + for (guint i = 0; i < n; i++) + { + g_autoptr(GError) error = NULL; + g_autoptr(JDBEntry) entry = NULL; + g_autoptr(JDBSchema) schema = NULL; + + schema = j_db_schema_new("test-ns", "test-schema", &error); + g_assert_nonnull(schema); + g_assert_no_error(error); + + entry = j_db_entry_new(schema, &error); + g_assert_nonnull(entry); + g_assert_no_error(error); + } + + J_TEST_TRAP_END; +} + +static void +test_db_entry_insert_update_delete(void) +{ + guint const n = 1000; + + gchar const* str = "demo.bp"; + gint32 si32 = -42; + guint32 ui32 = 42; + gint64 si64 = -84; + guint64 ui64 = 4; + gfloat fl32 = 1.337; + gdouble fl64 = 42.42; + guint8 blob[5] = { 1, 2, 3, 4, 5 }; + gpointer val; + JDBType type; + guint64 length; + + g_autoptr(GError) error = NULL; + g_autoptr(JBatch) batch = j_batch_new_for_template(J_SEMANTICS_TEMPLATE_DEFAULT); + g_autoptr(JDBEntry) delete_entry = NULL; + g_autoptr(JDBEntry) update_entry = NULL; + g_autoptr(JDBSchema) schema = NULL; + g_autoptr(JDBSelector) selector = NULL; + g_autoptr(JDBIterator) iterator = NULL; + gboolean ret; + + J_TEST_TRAP_START; + + schema = j_db_schema_new("test-ns", "test-schema", &error); + g_assert_nonnull(schema); + g_assert_no_error(error); + + ret = j_db_schema_add_field(schema, "string-0", J_DB_TYPE_STRING, &error); + g_assert_true(ret); + g_assert_no_error(error); + + ret = j_db_schema_add_field(schema, "sint32-0", J_DB_TYPE_SINT32, &error); + g_assert_true(ret); + g_assert_no_error(error); + + ret = j_db_schema_add_field(schema, "uint32-0", J_DB_TYPE_UINT32, &error); + g_assert_true(ret); + g_assert_no_error(error); + + ret = j_db_schema_add_field(schema, "sint64-0", J_DB_TYPE_SINT64, &error); + g_assert_true(ret); + g_assert_no_error(error); + + ret = j_db_schema_add_field(schema, "uint64-0", J_DB_TYPE_UINT64, &error); + g_assert_true(ret); + g_assert_no_error(error); + + ret = j_db_schema_add_field(schema, "float32-0", J_DB_TYPE_FLOAT32, &error); + g_assert_true(ret); + g_assert_no_error(error); + + ret = j_db_schema_add_field(schema, "float64-0", J_DB_TYPE_FLOAT64, &error); + g_assert_true(ret); + g_assert_no_error(error); + + ret = j_db_schema_add_field(schema, "blob-0", J_DB_TYPE_BLOB, &error); + g_assert_true(ret); + g_assert_no_error(error); + + ret = j_db_schema_create(schema, batch, &error); + g_assert_true(ret); + g_assert_no_error(error); + + ret = j_batch_execute(batch); + g_assert_true(ret); + g_assert_no_error(error); + + for (guint i = 0; i < n; i++) + { + g_autoptr(JDBEntry) entry = NULL; + + entry = j_db_entry_new(schema, &error); + g_assert_nonnull(entry); + g_assert_no_error(error); + + ret = j_db_entry_set_field(entry, "string-0", str, strlen(str), &error); + g_assert_true(ret); + g_assert_no_error(error); + + ret = j_db_entry_set_field(entry, "sint32-0", &si32, sizeof(si32), &error); + g_assert_true(ret); + g_assert_no_error(error); + + ret = j_db_entry_set_field(entry, "uint32-0", &ui32, sizeof(ui32), &error); + g_assert_true(ret); + g_assert_no_error(error); + + ret = j_db_entry_set_field(entry, "sint64-0", &si64, sizeof(si64), &error); + g_assert_true(ret); + g_assert_no_error(error); + + ret = j_db_entry_set_field(entry, "uint64-0", &ui64, sizeof(ui64), &error); + g_assert_true(ret); + g_assert_no_error(error); + + ret = j_db_entry_set_field(entry, "float32-0", &fl32, sizeof(fl32), &error); + g_assert_true(ret); + g_assert_no_error(error); + + ret = j_db_entry_set_field(entry, "float64-0", &fl64, sizeof(fl64), &error); + g_assert_true(ret); + g_assert_no_error(error); + + ret = j_db_entry_set_field(entry, "blob-0", blob, sizeof(blob), &error); + g_assert_true(ret); + g_assert_no_error(error); + + // FIXME Do not pass error, will not exist anymore when batch is executed + ret = j_db_entry_insert(entry, batch, NULL); + g_assert_true(ret); + } + + ret = j_batch_execute(batch); + g_assert_true(ret); + + // check all written values + + selector = j_db_selector_new(schema, J_DB_SELECTOR_MODE_AND, &error); + g_assert_nonnull(selector); + g_assert_no_error(error); + + ret = j_db_selector_add_field(selector, "string-0", J_DB_SELECTOR_OPERATOR_EQ, str, strlen(str), &error); + g_assert_true(ret); + g_assert_no_error(error); + + iterator = j_db_iterator_new(schema, selector, &error); + g_assert_nonnull(iterator); + g_assert_no_error(error); + + while (j_db_iterator_next(iterator, &error)) + { + g_assert_no_error(error); + + ret = j_db_iterator_get_field(iterator, schema, "string-0", &type, &val, &length, &error); + g_assert_true(ret); + g_assert_no_error(error); + g_assert_cmpstr((gchar*)val, ==, str); + g_assert_cmpint(type, ==, J_DB_TYPE_STRING); + g_free(val); + + ret = j_db_iterator_get_field(iterator, schema, "sint32-0", &type, &val, &length, &error); + g_assert_true(ret); + g_assert_no_error(error); + g_assert_cmpint(*(gint32*)val, ==, si32); + g_assert_cmpint(type, ==, J_DB_TYPE_SINT32); + g_free(val); + + ret = j_db_iterator_get_field(iterator, schema, "uint32-0", &type, &val, &length, &error); + g_assert_true(ret); + g_assert_no_error(error); + g_assert_cmpuint(*(guint32*)val, ==, ui32); + g_assert_cmpint(type, ==, J_DB_TYPE_UINT32); + g_free(val); + + ret = j_db_iterator_get_field(iterator, schema, "sint64-0", &type, &val, &length, &error); + g_assert_true(ret); + g_assert_no_error(error); + g_assert_cmpint(*(gint64*)val, ==, si64); + g_assert_cmpint(type, ==, J_DB_TYPE_SINT64); + g_free(val); + + ret = j_db_iterator_get_field(iterator, schema, "uint64-0", &type, &val, &length, &error); + g_assert_true(ret); + g_assert_no_error(error); + g_assert_cmpuint(*(guint64*)val, ==, ui64); + g_assert_cmpint(type, ==, J_DB_TYPE_UINT64); + g_free(val); + + ret = j_db_iterator_get_field(iterator, schema, "float32-0", &type, &val, &length, &error); + g_assert_true(ret); + g_assert_no_error(error); + g_assert_cmpfloat(fabs(*(gfloat*)val - fl32), <, EPS); + g_assert_cmpint(type, ==, J_DB_TYPE_FLOAT32); + g_free(val); + + ret = j_db_iterator_get_field(iterator, schema, "float64-0", &type, &val, &length, &error); + g_assert_true(ret); + g_assert_no_error(error); + g_assert_cmpfloat(fabs(*(gdouble*)val - fl64), <, EPS); + g_assert_cmpint(type, ==, J_DB_TYPE_FLOAT64); + g_free(val); + + ret = j_db_iterator_get_field(iterator, schema, "blob-0", &type, &val, &length, &error); + g_assert_true(ret); + g_assert_no_error(error); + g_assert_cmpmem((guint8*)val, length, blob, sizeof(blob)); + g_assert_cmpint(type, ==, J_DB_TYPE_BLOB); + g_free(val); + } + + g_error_free(error); + error = NULL; + + // update values + + update_entry = j_db_entry_new(schema, &error); + g_assert_nonnull(update_entry); + g_assert_no_error(error); + + ui32 = 3; + ret = j_db_entry_set_field(update_entry, "uint32-0", &ui32, sizeof(ui32), &error); + g_assert_true(ret); + g_assert_no_error(error); + + ret = j_db_entry_update(update_entry, selector, batch, &error); + g_assert_true(ret); + g_assert_no_error(error); + + ret = j_batch_execute(batch); + g_assert_true(ret); + g_assert_no_error(error); + + // delete new entry + + delete_entry = j_db_entry_new(schema, &error); + g_assert_nonnull(delete_entry); + g_assert_no_error(error); + + ret = j_db_entry_delete(delete_entry, selector, batch, &error); + g_assert_true(ret); + g_assert_no_error(error); + + ret = j_batch_execute(batch); + g_assert_true(ret); + g_assert_no_error(error); + + // delete schema + + ret = j_db_schema_delete(schema, batch, &error); + g_assert_true(ret); + g_assert_no_error(error); + + ret = j_batch_execute(batch); + g_assert_true(ret); + + J_TEST_TRAP_END; +} + +static void +test_db_entry_id(void) +{ + g_autoptr(JDBSchema) schema = NULL; + g_autoptr(JDBEntry) entry = NULL; + g_autoptr(JBatch) batch = NULL; + g_autoptr(GError) error = NULL; + gint64 val = 42; + g_autofree gpointer id = NULL; + guint64 len = 0; + gboolean res; + + J_TEST_TRAP_START; + + batch = j_batch_new_for_template(J_SEMANTICS_TEMPLATE_DEFAULT); + + schema = j_db_schema_new("test-ns", "test", NULL); + j_db_schema_add_field(schema, "test-si64", J_DB_TYPE_SINT64, NULL); + res = j_db_schema_create(schema, batch, &error); + g_assert_true(res); + + entry = j_db_entry_new(schema, NULL); + j_db_entry_set_field(entry, "test-si64", &val, sizeof(gint64), NULL); + + res = j_db_entry_insert(entry, batch, &error); + g_assert_true(res); + + res = j_batch_execute(batch); + g_assert_true(res); + g_assert_no_error(error); + + res = j_db_entry_get_id(entry, &id, &len, &error); + g_assert_true(res); + g_assert_no_error(error); + + res = j_db_schema_delete(schema, batch, &error); + g_assert_true(res); + + res = j_batch_execute(batch); + g_assert_true(res); + g_assert_no_error(error); + + J_TEST_TRAP_END; +} + +static void +test_db_entry_invalid_insert(void) +{ + g_autoptr(JDBSchema) schema = NULL; + g_autoptr(JDBEntry) entry = NULL; + g_autoptr(JBatch) batch = NULL; + g_autoptr(GError) error = NULL; + gboolean res; + gint64 val = 42; + + J_TEST_TRAP_START; + + batch = j_batch_new_for_template(J_SEMANTICS_TEMPLATE_DEFAULT); + + schema = j_db_schema_new("test-ns", "test", NULL); + j_db_schema_add_field(schema, "test-si64", J_DB_TYPE_SINT64, NULL); + + entry = j_db_entry_new(schema, NULL); + j_db_entry_set_field(entry, "test-si64", &val, sizeof(gint64), NULL); + + res = j_db_entry_insert(entry, batch, &error); + g_assert_true(res); + + res = j_batch_execute(batch); + g_assert_false(res); + g_assert_nonnull(error); + + J_TEST_TRAP_END; +} + +static void +test_db_entry_set_nonexistant(void) +{ + g_autoptr(JDBSchema) schema = NULL; + g_autoptr(JDBEntry) entry = NULL; + g_autoptr(GError) error = NULL; + gboolean res; + gint64 val = 42; + + J_TEST_TRAP_START; + + schema = j_db_schema_new("test-ns", "test", NULL); + j_db_schema_add_field(schema, "test-si64", J_DB_TYPE_SINT64, NULL); + entry = j_db_entry_new(schema, NULL); + + res = j_db_entry_set_field(entry, "not-existant", &val, sizeof(gint64), &error); + g_assert_false(res); + g_assert_nonnull(error); + + J_TEST_TRAP_END; +} + +void +test_db_entry(void) +{ + g_test_add_func("/db/entry/new_free", test_db_entry_new_free); + g_test_add_func("/db/entry/insert_update_delete", test_db_entry_insert_update_delete); + g_test_add_func("/db/entry/get_id", test_db_entry_id); + g_test_add_func("/db/entry/insert_in_local_schema", test_db_entry_invalid_insert); + g_test_add_func("/db/entry/set_non_existing_field", test_db_entry_set_nonexistant); +} diff --git a/test/db/db-schema.c b/test/db/db-schema.c new file mode 100644 index 000000000..a38a1cd8d --- /dev/null +++ b/test/db/db-schema.c @@ -0,0 +1,331 @@ +/* + * JULEA - Flexible storage framework + * Copyright (C) 2021 Timm Leon Erxleben + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include + +#include +#include + +#include +#include + +#include "test.h" + +static void +test_db_schema_new_free(void) +{ + guint const n = 100000; + + J_TEST_TRAP_START; + + for (guint i = 0; i < n; i++) + { + g_autoptr(GError) error = NULL; + g_autoptr(JDBSchema) schema = NULL; + + schema = j_db_schema_new("test-ns", "test-schema", &error); + g_assert_nonnull(schema); + g_assert_no_error(error); + } + + J_TEST_TRAP_END; +} + +static void +test_db_schema_create_delete(void) +{ + guint const n = 1000; + + g_autoptr(JBatch) batch = j_batch_new_for_template(J_SEMANTICS_TEMPLATE_DEFAULT); + gboolean ret; + + gchar const* idx_string[] = { "string-0", NULL }; + gchar const* idx_uint[] = { "uint-0", NULL }; + gchar const* idx_float[] = { "float-0", NULL }; + + J_TEST_TRAP_START; + + for (guint i = 0; i < n; i++) + { + g_autoptr(GError) error = NULL; + g_autoptr(JDBSchema) schema = NULL; + g_autofree gchar* name = NULL; + + name = g_strdup_printf("test-schema-%d", i); + schema = j_db_schema_new("test-ns", name, &error); + g_assert_nonnull(schema); + g_assert_no_error(error); + + ret = j_db_schema_add_field(schema, "string-0", J_DB_TYPE_STRING, &error); + g_assert_true(ret); + g_assert_no_error(error); + ret = j_db_schema_add_field(schema, "string-1", J_DB_TYPE_STRING, &error); + g_assert_true(ret); + g_assert_no_error(error); + ret = j_db_schema_add_field(schema, "uint-0", J_DB_TYPE_UINT64, &error); + g_assert_true(ret); + g_assert_no_error(error); + ret = j_db_schema_add_field(schema, "uint-1", J_DB_TYPE_UINT64, &error); + g_assert_true(ret); + g_assert_no_error(error); + ret = j_db_schema_add_field(schema, "float-0", J_DB_TYPE_FLOAT64, &error); + g_assert_true(ret); + g_assert_no_error(error); + ret = j_db_schema_add_field(schema, "float-1", J_DB_TYPE_FLOAT64, &error); + g_assert_true(ret); + g_assert_no_error(error); + + ret = j_db_schema_add_index(schema, idx_string, &error); + g_assert_true(ret); + g_assert_no_error(error); + ret = j_db_schema_add_index(schema, idx_uint, &error); + g_assert_true(ret); + g_assert_no_error(error); + ret = j_db_schema_add_index(schema, idx_float, &error); + g_assert_true(ret); + g_assert_no_error(error); + + // FIXME Do not pass error, will not exist anymore when batch is executed + ret = j_db_schema_create(schema, batch, NULL); + g_assert_true(ret); + + // FIXME Do not pass error, will not exist anymore when batch is executed + ret = j_db_schema_delete(schema, batch, NULL); + g_assert_true(ret); + } + + ret = j_batch_execute(batch); + g_assert_true(ret); + + J_TEST_TRAP_END; +} + +static void +test_db_invalid_schema_get(void) +{ + g_autoptr(JDBSchema) schema = NULL; + g_autoptr(JBatch) batch = NULL; + g_autoptr(GError) error = NULL; + gboolean res; + + J_TEST_TRAP_START; + + batch = j_batch_new_for_template(J_SEMANTICS_TEMPLATE_DEFAULT); + + schema = j_db_schema_new("test-ns", "non-existant", NULL); + + res = j_db_schema_get(schema, batch, &error); + g_assert_true(res); + + res = j_batch_execute(batch); + g_assert_false(res); + g_assert_nonnull(error); + + J_TEST_TRAP_END; +} + +static void +test_db_invalid_schema_delete(void) +{ + g_autoptr(JDBSchema) schema = NULL; + g_autoptr(JBatch) batch = NULL; + g_autoptr(GError) error = NULL; + bool ret; + + J_TEST_TRAP_START; + + schema = j_db_schema_new("test-ns", "test", NULL); + ret = j_db_schema_add_field(schema, "test-si64", J_DB_TYPE_SINT64, NULL); + g_assert_true(ret); + batch = j_batch_new_for_template(J_SEMANTICS_TEMPLATE_DEFAULT); + ret = j_db_schema_create(schema, batch, &error); + g_assert_true(ret); + + ret = j_batch_execute(batch); + g_assert_true(ret); + g_assert_no_error(error); + + j_db_schema_delete(schema, batch, &error); + ret = j_batch_execute(batch); + g_assert_true(ret); + g_assert_no_error(error); + + j_db_schema_delete(schema, batch, &error); + ret = j_batch_execute(batch); + g_assert_false(ret); + g_assert_nonnull(error); + + J_TEST_TRAP_END; + + g_test_incomplete("Known issue. Similar to #116"); +} + +static void +test_db_schema_equals_different_name(void) +{ + g_autoptr(JDBSchema) schema1 = NULL; + g_autoptr(JDBSchema) schema2 = NULL; + g_autoptr(GError) error = NULL; + gboolean res, equal; + + J_TEST_TRAP_START; + + schema1 = j_db_schema_new("equal", "same1", NULL); + schema2 = j_db_schema_new("equal", "same2", NULL); + + res = j_db_schema_equals(schema1, schema2, &equal, &error); + g_assert_true(res); + g_assert_false(equal); + g_assert_no_error(error); + + J_TEST_TRAP_END; +} + +static void +test_db_schema_equals_same_name_different_fields(void) +{ + g_autoptr(JDBSchema) schema1 = NULL; + g_autoptr(JDBSchema) schema2 = NULL; + g_autoptr(GRand) rnd = NULL; + g_autoptr(GError) error = NULL; + gboolean res, equal; + gchar field_name[] = "field_dd"; + + J_TEST_TRAP_START; + + schema1 = j_db_schema_new("equal", "same", NULL); + schema2 = j_db_schema_new("equal", "same", NULL); + + rnd = g_rand_new(); + + for (int i = 0; i <= g_rand_int_range(rnd, 1, 100); ++i) + { + g_snprintf(field_name, sizeof(field_name), "field_%i", i); + // generate some random type fields (excluding id type) + res = j_db_schema_add_field(schema1, field_name, g_rand_int_range(rnd, 0, 8), NULL); + g_assert_true(res); + res = j_db_schema_add_field(schema2, field_name, g_rand_int_range(rnd, 0, 8), NULL); + g_assert_true(res); + } + + res = j_db_schema_equals(schema1, schema2, &equal, &error); + g_assert_true(res); + g_assert_false(equal); + g_assert_no_error(error); + + J_TEST_TRAP_END; +} + +static void +test_db_schema_equals_same_name_same_fields(void) +{ + g_autoptr(JDBSchema) schema1 = NULL; + g_autoptr(JDBSchema) schema2 = NULL; + g_autoptr(GRand) rnd = NULL; + g_autoptr(GError) error = NULL; + gboolean res, equal; + gint field = 0; + gchar field_name[] = "field_dd"; + + J_TEST_TRAP_START; + + schema1 = j_db_schema_new("equal", "same", NULL); + schema2 = j_db_schema_new("equal", "same", NULL); + + rnd = g_rand_new(); + + for (int i = 0; i <= g_rand_int_range(rnd, 1, 100); ++i) + { + g_snprintf(field_name, sizeof(field_name), "field_%i", i); + // generate some random type fields (excluding id type) + field = g_rand_int_range(rnd, 0, 8); + res = j_db_schema_add_field(schema1, field_name, field, NULL); + g_assert_true(res); + res = j_db_schema_add_field(schema2, field_name, field, NULL); + g_assert_true(res); + } + + res = j_db_schema_equals(schema1, schema2, &equal, &error); + g_assert_true(res); + g_assert_true(equal); + g_assert_no_error(error); + + J_TEST_TRAP_END; +} + +static void +test_db_schema_get_all_fields(void) +{ + g_autoptr(JDBSchema) schema = NULL; + g_autoptr(GRand) rnd = NULL; + g_autoptr(GError) error = NULL; + g_autofree JDBType* res_types = NULL; + g_autofree gchar** res_names = NULL; + g_autofree JDBType* types = NULL; + g_autofree gchar** names = NULL; + gchar field_name[] = "field_dd"; + gint field = 0; + guint32 field_count; + guint32 res_field_count; + + J_TEST_TRAP_START; + + schema = j_db_schema_new("equal", "same", NULL); + rnd = g_rand_new(); + + field_count = g_rand_int_range(rnd, 1, 100); + types = g_new(JDBType, field_count); + names = g_new0(gchar*, field_count); + + for (guint32 i = 0; i < field_count; ++i) + { + g_snprintf(field_name, sizeof(field_name), "field_%i", i); + // generate some random type fields (excluding id type) + field = g_rand_int_range(rnd, 0, 8); + types[i] = field; + names[i] = g_strdup(field_name); + g_assert_true(j_db_schema_add_field(schema, field_name, field, NULL)); + } + + res_field_count = j_db_schema_get_all_fields(schema, &res_names, &res_types, &error); + g_assert_no_error(error); + g_assert_cmpint(res_field_count, ==, field_count); + + for (guint32 i = 0; i < field_count; ++i) + { + g_assert_cmpstr(names[i], ==, res_names[i]); + g_assert_cmpint(types[i], ==, res_types[i]); + g_free(names[i]); + g_free(res_names[i]); + } + + J_TEST_TRAP_END; +} + +void +test_db_schema(void) +{ + g_test_add_func("/db/schema/new_free", test_db_schema_new_free); + g_test_add_func("/db/schema/create_delete", test_db_schema_create_delete); + g_test_add_func("/db/schema/invalid_get", test_db_invalid_schema_get); + g_test_add_func("/db/schema/invalid_delete", test_db_invalid_schema_delete); + g_test_add_func("/db/schema/equals_different_name", test_db_schema_equals_different_name); + g_test_add_func("/db/schema/equals_same_name_different_fields", test_db_schema_equals_same_name_different_fields); + g_test_add_func("/db/schema/equals_same_name_same_fields", test_db_schema_equals_same_name_same_fields); + g_test_add_func("/db/schema/get_all_fields", test_db_schema_get_all_fields); +} diff --git a/test/db/db-selector.c b/test/db/db-selector.c new file mode 100644 index 000000000..ea97def90 --- /dev/null +++ b/test/db/db-selector.c @@ -0,0 +1,153 @@ +/* + * JULEA - Flexible storage framework + * Copyright (C) 2021 Timm Leon Erxleben + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include + +#include +#include + +#include +#include + +#include "test.h" + +static JDBSchema* +generate_test_schema(gchar const* name) +{ + g_autoptr(JDBSchema) schema = NULL; + gboolean res; + gchar field_name[] = "field_dd"; + + schema = j_db_schema_new("test-ns", name, NULL); + + for (int i = 0; i <= 99; ++i) + { + g_snprintf(field_name, sizeof(field_name), "field_%i", i); + res = j_db_schema_add_field(schema, field_name, i % 8, NULL); + g_assert_true(res); + } + + return j_db_schema_ref(schema); +} + +static void +test_db_selector_add_field(void) +{ + g_autoptr(JDBSchema) schema = generate_test_schema("selector-test"); + g_autoptr(JDBSelector) selector = NULL; + g_autoptr(GError) error = NULL; + gboolean ret; + gchar val[] = "some value"; + gchar field_name[] = "field_dd"; + + J_TEST_TRAP_START; + + selector = j_db_selector_new(schema, J_DB_SELECTOR_MODE_AND, &error); + g_assert_nonnull(selector); + g_assert_no_error(error); + + for (int i = 0; i < 8; ++i) + { + g_snprintf(field_name, sizeof(field_name), "field_%i", i); + ret = j_db_selector_add_field(selector, field_name, i % 6, val, sizeof(val), &error); + g_assert_true(ret); + g_assert_no_error(error); + if (g_test_failed()) + return; + } + + J_TEST_TRAP_END; +} + +static void +test_db_selector_add_non_existant_field(void) +{ + g_autoptr(JDBSchema) schema = generate_test_schema("selector-test"); + g_autoptr(JDBSelector) selector = NULL; + g_autoptr(GError) error = NULL; + gboolean ret; + gchar val[] = "some value"; + + J_TEST_TRAP_START; + + selector = j_db_selector_new(schema, J_DB_SELECTOR_MODE_AND, &error); + g_assert_nonnull(selector); + g_assert_no_error(error); + + ret = j_db_selector_add_field(selector, "field_100", J_DB_SELECTOR_OPERATOR_GT, val, sizeof(val), &error); + g_assert_false(ret); + g_assert_nonnull(error); + + J_TEST_TRAP_END; +} + +static void +test_db_selector_add_selector(void) +{ + g_autoptr(JDBSchema) schema = generate_test_schema("selector-test"); + g_autoptr(JDBSelector) selector1 = NULL; + g_autoptr(JDBSelector) selector2 = NULL; + g_autoptr(GError) error = NULL; + gboolean ret; + gchar val[] = "some value"; + gchar field_name[] = "field_dd"; + + J_TEST_TRAP_START; + + selector1 = j_db_selector_new(schema, J_DB_SELECTOR_MODE_AND, &error); + g_assert_nonnull(selector1); + g_assert_no_error(error); + + selector2 = j_db_selector_new(schema, J_DB_SELECTOR_MODE_OR, &error); + g_assert_nonnull(selector2); + g_assert_no_error(error); + + for (int i = 0; i < 8; ++i) + { + g_snprintf(field_name, sizeof(field_name), "field_%i", i); + ret = j_db_selector_add_field(selector1, field_name, i % 6, val, sizeof(val), &error); + g_assert_true(ret); + g_assert_no_error(error); + if (g_test_failed()) + return; + } + + for (int i = 8; i < 25; ++i) + { + g_snprintf(field_name, sizeof(field_name), "field_%i", i); + ret = j_db_selector_add_field(selector2, field_name, i % 6, val, sizeof(val), &error); + g_assert_true(ret); + g_assert_no_error(error); + if (g_test_failed()) + return; + } + + ret = j_db_selector_add_selector(selector1, selector2, &error); + g_assert_true(ret); + g_assert_no_error(error); + + J_TEST_TRAP_END; +} + +void +test_db_selector(void) +{ + g_test_add_func("/db/selector/add_field", test_db_selector_add_field); + g_test_add_func("/db/selector/add_non_existant_field", test_db_selector_add_non_existant_field); + g_test_add_func("/db/selector/add_selector", test_db_selector_add_selector); +} diff --git a/test/db/db.c b/test/db/db.c index 029801ba0..c117a6d3d 100644 --- a/test/db/db.c +++ b/test/db/db.c @@ -20,227 +20,14 @@ #include #include +#include #include #include #include "test.h" -static void -test_db_schema_new_free(void) -{ - guint const n = 100000; - - J_TEST_TRAP_START; - for (guint i = 0; i < n; i++) - { - g_autoptr(GError) error = NULL; - g_autoptr(JDBSchema) schema = NULL; - - schema = j_db_schema_new("test-ns", "test-schema", &error); - g_assert_nonnull(schema); - g_assert_no_error(error); - } - J_TEST_TRAP_END; -} - -static void -test_db_schema_create_delete(void) -{ - guint const n = 1000; - - g_autoptr(JBatch) batch = j_batch_new_for_template(J_SEMANTICS_TEMPLATE_DEFAULT); - gboolean ret; - - gchar const* idx_string[] = { "string-0", NULL }; - gchar const* idx_uint[] = { "uint-0", NULL }; - gchar const* idx_float[] = { "float-0", NULL }; - - J_TEST_TRAP_START; - for (guint i = 0; i < n; i++) - { - g_autoptr(GError) error = NULL; - g_autoptr(JDBSchema) schema = NULL; - g_autofree gchar* name = NULL; - - name = g_strdup_printf("test-schema-%d", i); - schema = j_db_schema_new("test-ns", name, &error); - g_assert_nonnull(schema); - g_assert_no_error(error); - - ret = j_db_schema_add_field(schema, "string-0", J_DB_TYPE_STRING, &error); - g_assert_true(ret); - g_assert_no_error(error); - ret = j_db_schema_add_field(schema, "string-1", J_DB_TYPE_STRING, &error); - g_assert_true(ret); - g_assert_no_error(error); - ret = j_db_schema_add_field(schema, "uint-0", J_DB_TYPE_UINT64, &error); - g_assert_true(ret); - g_assert_no_error(error); - ret = j_db_schema_add_field(schema, "uint-1", J_DB_TYPE_UINT64, &error); - g_assert_true(ret); - g_assert_no_error(error); - ret = j_db_schema_add_field(schema, "float-0", J_DB_TYPE_FLOAT64, &error); - g_assert_true(ret); - g_assert_no_error(error); - ret = j_db_schema_add_field(schema, "float-1", J_DB_TYPE_FLOAT64, &error); - g_assert_true(ret); - g_assert_no_error(error); - - ret = j_db_schema_add_index(schema, idx_string, &error); - g_assert_true(ret); - g_assert_no_error(error); - ret = j_db_schema_add_index(schema, idx_uint, &error); - g_assert_true(ret); - g_assert_no_error(error); - ret = j_db_schema_add_index(schema, idx_float, &error); - g_assert_true(ret); - g_assert_no_error(error); - - /// \todo Do not pass error, will not exist anymore when batch is executed - ret = j_db_schema_create(schema, batch, NULL); - g_assert_true(ret); - - /// \todo Do not pass error, will not exist anymore when batch is executed - ret = j_db_schema_delete(schema, batch, NULL); - g_assert_true(ret); - } - - ret = j_batch_execute(batch); - g_assert_true(ret); - J_TEST_TRAP_END; -} - -static void -test_db_entry_new_free(void) -{ - guint const n = 100000; - - J_TEST_TRAP_START; - for (guint i = 0; i < n; i++) - { - g_autoptr(GError) error = NULL; - g_autoptr(JDBEntry) entry = NULL; - g_autoptr(JDBSchema) schema = NULL; - - schema = j_db_schema_new("test-ns", "test-schema", &error); - g_assert_nonnull(schema); - g_assert_no_error(error); - - entry = j_db_entry_new(schema, &error); - g_assert_nonnull(entry); - g_assert_no_error(error); - } - J_TEST_TRAP_END; -} - -static void -test_db_entry_insert_update_delete(void) -{ - guint const n = 1000; - - gchar const* file = "demo.bp"; - guint64 dim = 4; - - g_autoptr(GError) error = NULL; - g_autoptr(JBatch) batch = j_batch_new_for_template(J_SEMANTICS_TEMPLATE_DEFAULT); - g_autoptr(JDBEntry) delete_entry = NULL; - g_autoptr(JDBEntry) update_entry = NULL; - g_autoptr(JDBSchema) schema = NULL; - g_autoptr(JDBSelector) selector = NULL; - gboolean ret; - - J_TEST_TRAP_START; - schema = j_db_schema_new("test-ns", "test-schema", &error); - g_assert_nonnull(schema); - g_assert_no_error(error); - - ret = j_db_schema_add_field(schema, "string-0", J_DB_TYPE_STRING, &error); - g_assert_true(ret); - g_assert_no_error(error); - - ret = j_db_schema_add_field(schema, "uint-0", J_DB_TYPE_UINT64, &error); - g_assert_true(ret); - g_assert_no_error(error); - - ret = j_db_schema_create(schema, batch, &error); - g_assert_true(ret); - g_assert_no_error(error); - - ret = j_batch_execute(batch); - g_assert_true(ret); - g_assert_no_error(error); - - for (guint i = 0; i < n; i++) - { - g_autoptr(JDBEntry) entry = NULL; - - entry = j_db_entry_new(schema, &error); - g_assert_nonnull(entry); - g_assert_no_error(error); - - ret = j_db_entry_set_field(entry, "string-0", file, strlen(file), &error); - g_assert_true(ret); - g_assert_no_error(error); - - ret = j_db_entry_set_field(entry, "uint-0", &dim, sizeof(dim), &error); - g_assert_true(ret); - g_assert_no_error(error); - - /// \todo Do not pass error, will not exist anymore when batch is executed - ret = j_db_entry_insert(entry, batch, NULL); - g_assert_true(ret); - } - - ret = j_batch_execute(batch); - g_assert_true(ret); - - selector = j_db_selector_new(schema, J_DB_SELECTOR_MODE_AND, &error); - g_assert_nonnull(selector); - g_assert_no_error(error); - - ret = j_db_selector_add_field(selector, "string-0", J_DB_SELECTOR_OPERATOR_EQ, file, strlen(file), &error); - g_assert_true(ret); - g_assert_no_error(error); - - update_entry = j_db_entry_new(schema, &error); - g_assert_nonnull(update_entry); - g_assert_no_error(error); - - dim = 3; - ret = j_db_entry_set_field(update_entry, "uint-0", &dim, sizeof(dim), &error); - g_assert_true(ret); - g_assert_no_error(error); - - ret = j_db_entry_update(update_entry, selector, batch, &error); - g_assert_true(ret); - g_assert_no_error(error); - - ret = j_batch_execute(batch); - g_assert_true(ret); - g_assert_no_error(error); - - delete_entry = j_db_entry_new(schema, &error); - g_assert_nonnull(delete_entry); - g_assert_no_error(error); - - ret = j_db_entry_delete(delete_entry, selector, batch, &error); - g_assert_true(ret); - g_assert_no_error(error); - - ret = j_batch_execute(batch); - g_assert_true(ret); - g_assert_no_error(error); - - ret = j_db_schema_delete(schema, batch, &error); - g_assert_true(ret); - g_assert_no_error(error); - - ret = j_batch_execute(batch); - g_assert_true(ret); - - J_TEST_TRAP_END; -} +#define EPS 1e-9 static void schema_create(void) @@ -425,6 +212,10 @@ entry_update(void) g_autoptr(JDBSelector) selector = NULL; g_autoptr(JDBEntry) entry = NULL; g_autoptr(JBatch) batch = j_batch_new_for_template(J_SEMANTICS_TEMPLATE_DEFAULT); + g_autoptr(JDBIterator) it = NULL; + gpointer val = NULL; + JDBType type; + guint64 val_length; gchar const* file = "demo.bp"; gchar const* name = "temperature"; @@ -464,6 +255,33 @@ entry_update(void) g_assert_no_error(error); success = j_batch_execute(batch); g_assert_true(success); + + // test if values were actually updated + + it = j_db_iterator_new(schema, selector, &error); + g_assert_nonnull(it); + g_assert_no_error(error); + + while (j_db_iterator_next(it, &error)) + { + g_assert_no_error(error); + success = j_db_iterator_get_field(it, schema, "min", &type, &val, &val_length, &error); + g_assert_true(success); + g_assert_no_error(error); + // g_assert_cmpfloat_with_epsilon(*(double*)val, 2.0, EPS); + g_assert_cmpfloat(fabs(*(double*)val - 2.0), <, EPS); + g_assert_cmpint(type, ==, J_DB_TYPE_FLOAT64); + g_assert_cmpuint(val_length, ==, sizeof(gdouble)); + g_free(val); + success = j_db_iterator_get_field(it, schema, "max", &type, &val, &val_length, &error); + g_assert_true(success); + g_assert_no_error(error); + g_assert_cmpfloat(fabs(*(double*)val - 22.0), <, EPS); + // g_assert_cmpfloat_with_epsilon(*(double*)val, 22.0, EPS); + g_assert_cmpint(type, ==, J_DB_TYPE_FLOAT64); + g_assert_cmpuint(val_length, ==, sizeof(gdouble)); + g_free(val); + } } static void @@ -546,10 +364,5 @@ test_db_all(void) void test_db_db(void) { - /// \todo add more tests - g_test_add_func("/db/schema/new_free", test_db_schema_new_free); - g_test_add_func("/db/schema/create_delete", test_db_schema_create_delete); - g_test_add_func("/db/entry/new_free", test_db_entry_new_free); - g_test_add_func("/db/entry/insert_update_delete", test_db_entry_insert_update_delete); g_test_add_func("/db/all", test_db_all); } diff --git a/test/test.c b/test/test.c index 6f598951a..a40966c15 100644 --- a/test/test.c +++ b/test/test.c @@ -66,6 +66,9 @@ main(int argc, char** argv) // DB client test_db_db(); + test_db_schema(); + test_db_entry(); + test_db_selector(); // Item client test_item_collection(); diff --git a/test/test.h b/test/test.h index c10a06535..060a2b8de 100644 --- a/test/test.h +++ b/test/test.h @@ -58,6 +58,9 @@ void test_kv_kv_iterator(void); void test_kv_parallel(void); void test_db_db(void); +void test_db_schema(void); +void test_db_entry(void); +void test_db_selector(void); void test_item_collection(void); void test_item_collection_iterator(void);