]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-sql: Add initial unit tests
authorAki Tuomi <aki.tuomi@open-xchange.com>
Fri, 17 Sep 2021 06:58:04 +0000 (09:58 +0300)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Mon, 17 Jan 2022 11:52:09 +0000 (13:52 +0200)
src/lib-sql/Makefile.am
src/lib-sql/test-sql-sqlite.c [new file with mode: 0644]
src/lib-sql/test-sql.c [new file with mode: 0644]

index aeddec11ec923dcf3334099a067f8c401dc60373..06c971094ac488d3ad26394e1380b4356a7be1ef 100644 (file)
@@ -1,4 +1,4 @@
-noinst_LTLIBRARIES = libsql.la libdriver_test.la
+noinst_LTLIBRARIES = libdriver_test.la libsql.la
 
 SQL_DRIVER_PLUGINS =
 
@@ -36,6 +36,7 @@ sql_drivers = @sql_drivers@
 
 AM_CPPFLAGS = \
        -I$(top_srcdir)/src/lib \
+       -I$(top_srcdir)/src/lib-test \
        -I$(top_srcdir)/src/lib-settings \
        $(SQL_CFLAGS)
 
@@ -141,3 +142,29 @@ install-exec-local:
          done; \
        done
 endif
+
+test_libs = \
+       $(noinst_LTLIBRARIES) \
+       ../lib-settings/libsettings.la \
+       ../lib-test/libtest.la \
+       ../lib/liblib.la
+
+check_PROGRAMS = test-sql
+
+test_sql_SOURCES = test-sql.c
+test_sql_LDADD =  $(test_libs)
+test_sql_DEPENDENCIES = $(test_libs)
+
+if BUILD_SQLITE
+check_PROGRAMS += test-sql-sqlite
+test_sql_sqlite_SOURCES = test-sql-sqlite.c
+test_sql_sqlite_LDADD = $(SQLITE_LIB) $(pkglib_LTLIBRARIES) $(test_libs)
+test_sql_sqlite_DEPENDENCIES = $(SQLITE_LIB) $(pkglib_LTLIBRARIES) $(test_libs)
+endif
+
+noinst_PROGRAMS = $(check_PROGRAMS)
+
+check-local:
+       for bin in $(check_PROGRAMS); do \
+         if ! $(RUN_TEST) ./$$bin; then exit 1; fi; \
+       done
diff --git a/src/lib-sql/test-sql-sqlite.c b/src/lib-sql/test-sql-sqlite.c
new file mode 100644 (file)
index 0000000..2ad3ab9
--- /dev/null
@@ -0,0 +1,75 @@
+/* Copyright (c) 2021 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "sql-api-private.h"
+#include "test-common.h"
+#include "sql-api.h"
+
+void driver_sqlite_init(void);
+void driver_sqlite_deinit(void);
+
+static const char sql_create_db[] =
+"CREATE TABLE bar(\n"
+"  foo VARCHAR(255)\n"
+");\n";
+
+static void setup_database(struct sql_db *sql)
+{
+       sql_disconnect(sql);
+       i_unlink_if_exists("test-database.db");
+       sql_exec(sql, sql_create_db);
+}
+
+static void test_sql_sqlite(void)
+{
+       test_begin("test sql api");
+
+       const struct sql_settings set = {
+               .driver = "sqlite",
+               .connect_string = "test-database.db journal_mode=wal",
+       };
+       struct sql_db *sql = NULL;
+       const char *error = NULL;
+
+       sql_drivers_init();
+       driver_sqlite_init();
+
+       test_assert(sql_init_full(&set, &sql, &error) == 0 &&
+                   sql != NULL &&
+                   error == NULL);
+       setup_database(sql);
+
+       /* insert data */
+       struct sql_transaction_context *t = sql_transaction_begin(sql);
+       sql_update(t, "INSERT INTO bar VALUES(\"value1\")");
+       sql_update(t, "INSERT INTO bar VALUES(\"value2\")");
+       test_assert(sql_transaction_commit_s(&t, &error) == 0);
+
+       struct sql_result *cursor = sql_query_s(sql, "SELECT foo FROM bar");
+
+       test_assert(sql_result_next_row(cursor) == SQL_RESULT_NEXT_OK);
+       test_assert_ucmp(sql_result_get_fields_count(cursor), ==, 1);
+       test_assert_strcmp(sql_result_get_field_name(cursor, 0), "foo");
+       test_assert_strcmp(sql_result_get_field_value(cursor, 0), "value1");
+       test_assert(sql_result_next_row(cursor) == SQL_RESULT_NEXT_OK);
+       test_assert_ucmp(sql_result_get_fields_count(cursor), ==, 1);
+       test_assert_strcmp(sql_result_get_field_name(cursor, 0), "foo");
+       test_assert_strcmp(sql_result_get_field_value(cursor, 0), "value2");
+       test_assert(sql_result_next_row(cursor) == SQL_RESULT_NEXT_LAST);
+
+       sql_result_unref(cursor);
+       sql_unref(&sql);
+
+       driver_sqlite_deinit();
+       sql_drivers_deinit();
+
+       test_end();
+}
+
+int main(void) {
+       static void (*const test_functions[])(void) = {
+               test_sql_sqlite,
+               NULL
+       };
+       return test_run(test_functions);
+}
diff --git a/src/lib-sql/test-sql.c b/src/lib-sql/test-sql.c
new file mode 100644 (file)
index 0000000..9dcaaaa
--- /dev/null
@@ -0,0 +1,139 @@
+/* Copyright (c) 2021 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "test-common.h"
+#include "sql-api.h"
+#include "driver-test.h"
+
+static struct sql_db *setup_sql(void)
+{
+       const struct sql_settings set = {
+               .driver = "sqlite",
+               .connect_string = "",
+       };
+       struct sql_db *sql = NULL;
+       const char *error = NULL;
+
+       sql_drivers_init();
+       sql_driver_test_register();
+
+       test_assert(sql_init_full(&set, &sql, &error) == 0 &&
+                   sql != NULL &&
+                   error == NULL);
+
+       test_assert(sql_connect(sql) == 0);
+       sql_disconnect(sql);
+       return sql;
+}
+
+static void deinit_sql(struct sql_db **_sql)
+{
+       struct sql_db *sql = *_sql;
+       if (sql == NULL)
+               return;
+       *_sql = NULL;
+
+       sql_driver_test_clear_expected_results(sql);
+       sql_unref(&sql);
+
+       sql_driver_test_unregister();
+       sql_drivers_deinit();
+}
+
+#define setup_result_1(sql) \
+       struct test_driver_result_set rset_1 = { \
+               .rows = 2, \
+               .cols = 1, \
+               .col_names = (const char *[]){"foo", NULL}, \
+               .row_data = (const char **[]){ \
+                       (const char*[]){"value1", NULL}, \
+                       (const char*[]){"value2", NULL}, \
+               }, \
+       }; \
+       struct test_driver_result result_1 = { \
+               .nqueries = 1, \
+               .queries = (const char *[]){"SELECT foo FROM bar"}, \
+               .result = &rset_1 \
+       }; \
+       sql_driver_test_add_expected_result(sql, &result_1);
+
+static void test_result_1(struct sql_result *cursor)
+{
+       test_assert(sql_result_next_row(cursor) == SQL_RESULT_NEXT_OK);
+       test_assert_ucmp(sql_result_get_fields_count(cursor), ==, 1);
+       test_assert_strcmp(sql_result_get_field_name(cursor, 0), "foo");
+       test_assert_strcmp(sql_result_get_field_value(cursor, 0), "value1");
+       test_assert(sql_result_next_row(cursor) == SQL_RESULT_NEXT_OK);
+       test_assert_ucmp(sql_result_get_fields_count(cursor), ==, 1);
+       test_assert_strcmp(sql_result_get_field_name(cursor, 0), "foo");
+       test_assert_strcmp(sql_result_get_field_value(cursor, 0), "value2");
+       test_assert(sql_result_next_row(cursor) == SQL_RESULT_NEXT_LAST);
+}
+
+static void test_sql_api(void)
+{
+       test_begin("sql api");
+
+       struct sql_db *sql = setup_sql();
+       setup_result_1(sql);
+       struct sql_result *cursor = sql_query_s(sql, "SELECT foo FROM bar");
+
+       test_result_1(cursor);
+
+       sql_result_unref(cursor);
+
+       deinit_sql(&sql);
+
+       test_end();
+}
+
+static void test_sql_stmt_api(void)
+{
+       test_begin("sql statement api");
+
+       struct sql_db *sql = setup_sql();
+       setup_result_1(sql);
+
+       struct sql_statement *stmt =
+               sql_statement_init(sql, "SELECT foo FROM bar");
+       struct sql_result *cursor = sql_statement_query_s(&stmt);
+
+       test_result_1(cursor);
+
+       sql_result_unref(cursor);
+
+       deinit_sql(&sql);
+       test_end();
+}
+
+static void test_sql_stmt_prepared_api(void)
+{
+       test_begin("sql prepared statement api");
+
+       struct sql_db *sql = setup_sql();
+       setup_result_1(sql);
+
+       struct sql_prepared_statement *prep_stmt =
+               sql_prepared_statement_init(sql, "SELECT foo FROM bar");
+       struct sql_statement *stmt =
+               sql_statement_init_prepared(prep_stmt);
+       sql_prepared_statement_unref(&prep_stmt);
+       struct sql_result *cursor = sql_statement_query_s(&stmt);
+
+       test_result_1(cursor);
+
+       sql_result_unref(cursor);
+
+       deinit_sql(&sql);
+       test_end();
+}
+
+int main(void) {
+       static void (*const test_functions[])(void) = {
+               test_sql_api,
+               test_sql_stmt_api,
+               test_sql_stmt_prepared_api,
+               NULL
+       };
+       return test_run(test_functions);
+}