-noinst_LTLIBRARIES = libsql.la libdriver_test.la
+noinst_LTLIBRARIES = libdriver_test.la libsql.la
SQL_DRIVER_PLUGINS =
AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib \
+ -I$(top_srcdir)/src/lib-test \
-I$(top_srcdir)/src/lib-settings \
$(SQL_CFLAGS)
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
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}