/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "testutil.h"
#include "apr.h"
#include "apu.h"
#include "apr_pools.h"
#include "apr_dbd.h"
#include "apr_strings.h"

static void test_dbd_init(abts_case *tc, void *data)
{
    apr_pool_t *pool = p;
    apr_status_t rv;

    rv = apr_dbd_init(pool);
    ABTS_ASSERT(tc, "failed to init apr_dbd", rv == APR_SUCCESS);
}

#if APU_HAVE_SQLITE2 || APU_HAVE_SQLITE3
static void test_statement(abts_case *tc, apr_dbd_t* handle, 
                           const apr_dbd_driver_t* driver, const char* sql)
{
    int nrows;
    apr_status_t rv;

    rv = apr_dbd_query(driver, handle, &nrows, sql);

    ABTS_ASSERT(tc, sql, rv == APR_SUCCESS);
}

static void create_table(abts_case *tc, apr_dbd_t* handle, 
                         const apr_dbd_driver_t* driver)
{
    const char *sql = "CREATE TABLE apr_dbd_test ("
                             "col1 varchar(40) not null,"
                             "col2 varchar(40),"
                             "col3 integer)";

    test_statement(tc, handle, driver, sql);
}

static void drop_table(abts_case *tc, apr_dbd_t* handle, 
                       const apr_dbd_driver_t* driver)
{
    const char *sql = "DROP TABLE apr_dbd_test";
    test_statement(tc, handle, driver, sql);
}

static void delete_rows(abts_case *tc, apr_dbd_t* handle, 
                        const apr_dbd_driver_t* driver)
{
    const char *sql = "DELETE FROM apr_dbd_test";
    test_statement(tc, handle, driver, sql);
}


static void insert_data(abts_case *tc, apr_dbd_t* handle, 
                        const apr_dbd_driver_t* driver, int count)
{
    apr_pool_t* pool = p;
    const char* sql = "INSERT INTO apr_dbd_test VALUES('%d', '%d', %d)";
    char* sqf = NULL;
    int i;
    int nrows;
    apr_status_t rv;

    for (i=0; i<count; i++) {
        sqf = apr_psprintf(pool, sql, i, i, i);
        rv = apr_dbd_query(driver, handle, &nrows, sqf);
        ABTS_ASSERT(tc, sqf, rv == APR_SUCCESS);
        ABTS_ASSERT(tc, sqf, 1 == nrows);
    }
}

static void select_rows(abts_case *tc, apr_dbd_t* handle, 
                        const apr_dbd_driver_t* driver, int count)
{
    apr_status_t rv;
    apr_pool_t* pool = p;
    apr_pool_t* tpool;
    const char* sql = "SELECT * FROM apr_dbd_test ORDER BY col1";
    apr_dbd_results_t *res = NULL;
    apr_dbd_row_t *row = NULL;
    int i;

    rv = apr_dbd_select(driver, pool, handle, &res, sql, 0);
    ABTS_ASSERT(tc, sql, rv == APR_SUCCESS);
    ABTS_PTR_NOTNULL(tc, res);

    apr_pool_create(&tpool, pool);
    i = count;
    while (i > 0) {
        row = NULL;
        rv = apr_dbd_get_row(driver, pool, res, &row, -1);
        ABTS_ASSERT(tc, sql, rv == APR_SUCCESS);
        ABTS_PTR_NOTNULL(tc, row);
        apr_pool_clear(tpool);
        i--;
    }
    ABTS_ASSERT(tc, "Missing Rows!", i == 0);

    res = NULL;
    i = count;

    rv = apr_dbd_select(driver, pool, handle, &res, sql, 1);
    ABTS_ASSERT(tc, sql, rv == APR_SUCCESS);
    ABTS_PTR_NOTNULL(tc, res);

    rv = apr_dbd_num_tuples(driver, res);
    ABTS_ASSERT(tc, "invalid row count", rv == count);

    while (i > 0) {
        row = NULL;
        rv = apr_dbd_get_row(driver, pool, res, &row, i);
        ABTS_ASSERT(tc, sql, rv == APR_SUCCESS);
        ABTS_PTR_NOTNULL(tc, row);
        apr_pool_clear(tpool);
        i--;
    }
    ABTS_ASSERT(tc, "Missing Rows!", i == 0);
    rv = apr_dbd_get_row(driver, pool, res, &row, count+100);
    ABTS_ASSERT(tc, "If we overseek, get_row should return -1", rv == -1);
}

static void test_escape(abts_case *tc, apr_dbd_t *handle,
                        const apr_dbd_driver_t *driver)
{
  const char *escaped = apr_dbd_escape(driver, p, "foo'bar", handle);

  ABTS_STR_EQUAL(tc, "foo''bar", escaped);
}

static void test_dbd_generic(abts_case *tc, apr_dbd_t* handle, 
                             const apr_dbd_driver_t* driver)
{
    void* native;
    apr_pool_t *pool = p;
    apr_status_t rv;

    native = apr_dbd_native_handle(driver, handle);
    ABTS_PTR_NOTNULL(tc, native);

    rv = apr_dbd_check_conn(driver, pool, handle);

    create_table(tc, handle, driver);
    select_rows(tc, handle, driver, 0);
    insert_data(tc, handle, driver, 5);
    select_rows(tc, handle, driver, 5);
    delete_rows(tc, handle, driver);
    select_rows(tc, handle, driver, 0);
    drop_table(tc, handle, driver);

    test_escape(tc, handle, driver);

    rv = apr_dbd_close(driver, handle);
    ABTS_ASSERT(tc, "failed to close database", rv == APR_SUCCESS);
}
#endif

#if APU_HAVE_SQLITE2
static void test_dbd_sqlite2(abts_case *tc, void *data)
{
    apr_pool_t *pool = p;
    apr_status_t rv;
    const apr_dbd_driver_t* driver = NULL;
    apr_dbd_t* handle = NULL;

    rv = apr_dbd_get_driver(pool, "sqlite2", &driver);
    ABTS_ASSERT(tc, "failed to fetch driver", rv == APR_SUCCESS);
    ABTS_PTR_NOTNULL(tc, driver);

    ABTS_STR_EQUAL(tc, apr_dbd_name(driver), "sqlite2");

    rv = apr_dbd_open(driver, pool, "data/sqlite2.db:600", &handle);
    ABTS_ASSERT(tc, "failed to open database", rv == APR_SUCCESS);
    ABTS_PTR_NOTNULL(tc, handle);

    test_dbd_generic(tc, handle, driver);
}
#endif

#if APU_HAVE_SQLITE3
static void test_dbd_sqlite3(abts_case *tc, void *data)
{
    apr_pool_t *pool = p;
    apr_status_t rv;
    const apr_dbd_driver_t* driver = NULL;
    apr_dbd_t* handle = NULL;

    rv = apr_dbd_get_driver(pool, "sqlite3", &driver);
    ABTS_ASSERT(tc, "failed to fetch driver", rv == APR_SUCCESS);
    ABTS_PTR_NOTNULL(tc, driver);

    ABTS_STR_EQUAL(tc, apr_dbd_name(driver), "sqlite3");

    rv = apr_dbd_open(driver, pool, "data/sqlite3.db", &handle);
    ABTS_ASSERT(tc, "failed to open database", rv == APR_SUCCESS);
    ABTS_PTR_NOTNULL(tc, handle);

    test_dbd_generic(tc, handle, driver);
}
#endif

abts_suite *testdbd(abts_suite *suite)
{
    suite = ADD_SUITE(suite);


    abts_run_test(suite, test_dbd_init, NULL);

#if APU_HAVE_SQLITE2
    abts_run_test(suite, test_dbd_sqlite2, NULL);
#endif

#if APU_HAVE_SQLITE3
    abts_run_test(suite, test_dbd_sqlite3, NULL);
#endif
    return suite;
}
