/*
 * Copyright (C) 2022-2025 Seagull Developers
 *
 * Seagull is the legal property of its developers, whose names are too
 * numerous to list here. Please refer to the AUTHORS file distributed
 * with this source distribution
 *
 * This library 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 2.1 of the License, or (at your option) any later version.
 *
 * This library 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 library; if not, see <https://www.gnu.org/licenses/>.
 */

#include <sqlite3.h>

#include <seagull.h>

/******************************************************************************
 * Tests
 *****************************************************************************/
static void
test_seagull_db_new_in_memory(void) {
	SeagullSqlite3 *db = NULL;
	GError *error = NULL;
	gboolean result = FALSE;

	db = seagull_db_new_in_memory(&error);
	g_assert_no_error(error);
	g_assert_nonnull(db);

	result = seagull_db_close(db, &error);
	g_assert_no_error(error);
	g_assert_true(result);
}

static void
test_seagull_db_new_from_uri(void) {
	SeagullSqlite3 *db = NULL;
	GError *error = NULL;
	gboolean result = FALSE;

	db = seagull_db_new_from_uri("file:file.db?mode=memory", &error);
	g_assert_no_error(error);
	g_assert_nonnull(db);

	result = seagull_db_close(db, &error);
	g_assert_no_error(error);
	g_assert_true(result);
}

static void
test_seagull_db_new_from_uri_failed(void) {
	SeagullSqlite3 *db = NULL;
	GError *error = NULL;

	db = seagull_db_new_from_uri("file:file.db?mode=rw", &error);
	g_assert_error(error,
	               SEAGULL_DB_ERROR,
	               SEAGULL_DB_ERROR_NEW_FAILED);
	g_clear_error(&error);
	g_assert_null(db);
}

static void
test_seagull_db_close_null(void) {
	GError *error = NULL;
	gboolean result = FALSE;

	result = seagull_db_close(NULL, &error);
	g_assert_no_error(error);
	g_assert_true(result);
}

static void
test_seagull_db_close_in_use(void) {
	SeagullSqlite3 *db = NULL;
	sqlite3_stmt *statement = NULL;
	GError *error = NULL;
	int rc = SQLITE_OK;
	gboolean result = FALSE;

	db = seagull_db_new_in_memory(&error);
	g_assert_no_error(error);
	g_assert_nonnull(db);

	/* Create a prepared statement to make the close fail. */
	rc = sqlite3_prepare_v2(db, "SELECT 1", -1, &statement, NULL);
	g_assert_nonnull(statement);
	g_assert_cmpint(rc, ==, SQLITE_OK);

	/* Verify that the close failed. */
	result = seagull_db_close(db, &error);
	g_assert_error(error,
	               SEAGULL_DB_ERROR,
	               SEAGULL_DB_ERROR_CLOSE_FAILED);
	g_clear_error(&error);
	g_assert_false(result);

	/* Finish our statement. */
	rc = sqlite3_finalize(statement);
	g_assert_cmpint(rc, ==, SQLITE_OK);

	/* Close the database successfully. */
	result = seagull_db_close(db, &error);
	g_assert_no_error(error);
	g_assert_true(result);
}

/******************************************************************************
 * Main
 *****************************************************************************/
int
main(int argc, char *argv[]) {
	g_test_init(&argc, &argv, NULL);

	g_test_add_func("/db/new/in-memory", test_seagull_db_new_in_memory);
	g_test_add_func("/db/new/from-uri", test_seagull_db_new_from_uri);
	g_test_add_func("/db/new/from-uri-failed",
	                test_seagull_db_new_from_uri_failed);

	g_test_add_func("/db/close/null", test_seagull_db_close_null);
	g_test_add_func("/db/close/in-use", test_seagull_db_close_in_use);

	return g_test_run();
}
