/****************************************************************************** * @file test_statement.c * @brief Tests du module DatabaseStatement. ******************************************************************************/ #include "database/database.h" #include "database/statement.h" #include #include #include #include /** * @brief Vérifie la préparation et la finalisation d'une requête valide. */ static void test_prepare_valid_statement(void) { Database *database = NULL; DatabaseStatement *statement = NULL; database = database_open(":memory:"); assert(database != NULL); statement = database_statement_prepare( database, "SELECT 1;" ); assert(statement != NULL); database_statement_finalize(statement); database_close(database); } /** * @brief Vérifie qu'une requête SQL invalide est refusée. */ static void test_prepare_invalid_statement(void) { Database *database = NULL; DatabaseStatement *statement = NULL; database = database_open(":memory:"); assert(database != NULL); statement = database_statement_prepare( database, "SELECT FROM;" ); assert(statement == NULL); database_close(database); } /** * @brief Vérifie le traitement des paramètres invalides. */ static void test_invalid_parameters(void) { Database *database = NULL; database = database_open(":memory:"); assert(database != NULL); assert( database_statement_prepare( NULL, "SELECT 1;" ) == NULL ); assert( database_statement_prepare( database, NULL ) == NULL ); assert( database_statement_prepare( database, "" ) == NULL ); /* * La fonction doit accepter NULL sans provoquer d'erreur. */ database_statement_finalize(NULL); database_close(database); } /** * @brief Vérifie la liaison valide d'un paramètre texte. */ static void test_bind_valid_text(void) { Database *database = NULL; DatabaseStatement *statement = NULL; database = database_open(":memory:"); assert(database != NULL); statement = database_statement_prepare( database, "SELECT ?;" ); assert(statement != NULL); assert( database_statement_bind_text( statement, 1, "Labfy Investigation" ) ); database_statement_finalize(statement); database_close(database); } /** * @brief Vérifie le refus des paramètres invalides. */ static void test_bind_invalid_text(void) { Database *database = NULL; DatabaseStatement *statement = NULL; database = database_open(":memory:"); assert(database != NULL); statement = database_statement_prepare( database, "SELECT ?;" ); assert(statement != NULL); assert( !database_statement_bind_text( NULL, 1, "test" ) ); assert( !database_statement_bind_text( statement, 0, "test" ) ); assert( !database_statement_bind_text( statement, 1, NULL ) ); /* * La requête ne possède qu'un seul paramètre. */ assert( !database_statement_bind_text( statement, 2, "hors limite" ) ); database_statement_finalize(statement); database_close(database); } /** * @brief Vérifie l'exécution d'une requête retournant une ligne. */ static void test_step_select_statement(void) { Database *database = NULL; DatabaseStatement *statement = NULL; database = database_open(":memory:"); assert(database != NULL); statement = database_statement_prepare( database, "SELECT 1;" ); assert(statement != NULL); assert( database_statement_step(statement) == DATABASE_STATEMENT_STEP_ROW ); assert( database_statement_step(statement) == DATABASE_STATEMENT_STEP_DONE ); database_statement_finalize(statement); database_close(database); } /** * @brief Vérifie l'exécution d'une requête sans ligne de résultat. */ static void test_step_non_query_statement(void) { Database *database = NULL; DatabaseStatement *statement = NULL; database = database_open(":memory:"); assert(database != NULL); statement = database_statement_prepare( database, "CREATE TABLE test_step" "(" " id INTEGER PRIMARY KEY" ");" ); assert(statement != NULL); assert( database_statement_step(statement) == DATABASE_STATEMENT_STEP_DONE ); database_statement_finalize(statement); database_close(database); } /** * @brief Vérifie le traitement d'une requête absente. */ static void test_step_invalid_statement(void) { assert( database_statement_step(NULL) == DATABASE_STATEMENT_STEP_ERROR ); } /** * @brief Vérifie qu'une requête peut être réexécutée après reset. */ static void test_reset_statement(void) { Database *database = NULL; DatabaseStatement *statement = NULL; database = database_open(":memory:"); assert(database != NULL); statement = database_statement_prepare( database, "SELECT ?;" ); assert(statement != NULL); assert( database_statement_bind_text( statement, 1, "Labfy Investigation" ) ); assert( database_statement_step(statement) == DATABASE_STATEMENT_STEP_ROW ); assert( database_statement_step(statement) == DATABASE_STATEMENT_STEP_DONE ); assert( database_statement_reset(statement) ); /* * Le paramètre texte est toujours lié après le reset. */ assert( database_statement_step(statement) == DATABASE_STATEMENT_STEP_ROW ); assert( database_statement_step(statement) == DATABASE_STATEMENT_STEP_DONE ); database_statement_finalize(statement); database_close(database); } /** * @brief Vérifie le refus d'une requête absente. */ static void test_reset_invalid_statement(void) { assert( !database_statement_reset(NULL) ); } /** * @brief Vérifie l'effacement des paramètres d'une requête préparée. */ static void test_clear_bindings(void) { Database *database = NULL; DatabaseStatement *statement = NULL; database = database_open(":memory:"); assert(database != NULL); statement = database_statement_prepare( database, "SELECT ?;" ); assert(statement != NULL); assert( database_statement_bind_text( statement, 1, "Première valeur" ) ); assert( database_statement_clear_bindings( statement ) ); /* * Le paramètre peut recevoir une nouvelle valeur après effacement. */ assert( database_statement_bind_text( statement, 1, "Nouvelle valeur" ) ); assert( database_statement_step(statement) == DATABASE_STATEMENT_STEP_ROW ); assert( database_statement_step(statement) == DATABASE_STATEMENT_STEP_DONE ); database_statement_finalize(statement); database_close(database); } /** * @brief Vérifie le refus d'une requête absente. */ static void test_clear_bindings_invalid_statement(void) { assert( !database_statement_clear_bindings(NULL) ); } /** * @brief Vérifie la détection des colonnes SQL NULL. */ static void test_column_is_null(void) { Database *database = NULL; DatabaseStatement *statement = NULL; bool is_null = false; database = database_open(":memory:"); assert(database != NULL); statement = database_statement_prepare( database, "SELECT NULL, 'Labfy Investigation';" ); assert(statement != NULL); assert( database_statement_step(statement) == DATABASE_STATEMENT_STEP_ROW ); assert( database_statement_column_is_null( statement, 0, &is_null ) ); assert(is_null); assert( database_statement_column_is_null( statement, 1, &is_null ) ); assert(!is_null); assert( !database_statement_column_is_null( NULL, 0, &is_null ) ); assert( !database_statement_column_is_null( statement, -1, &is_null ) ); assert( !database_statement_column_is_null( statement, 2, &is_null ) ); assert( !database_statement_column_is_null( statement, 0, NULL ) ); database_statement_finalize(statement); database_close(database); } /** * @brief Vérifie la lecture sécurisée des colonnes texte. */ static void test_column_text(void) { Database *database = NULL; DatabaseStatement *statement = NULL; char *value = NULL; database = database_open(":memory:"); assert(database != NULL); statement = database_statement_prepare( database, "SELECT 'Labfy Investigation', NULL;" ); assert(statement != NULL); assert( database_statement_step(statement) == DATABASE_STATEMENT_STEP_ROW ); assert( database_statement_column_text( statement, 0, &value ) ); assert(value != NULL); assert( g_strcmp0( value, "Labfy Investigation" ) == 0 ); g_free(value); value = NULL; /* * Une colonne SQL NULL produit un pointeur NULL, * mais la lecture reste valide. */ assert( database_statement_column_text( statement, 1, &value ) ); assert(value == NULL); assert( !database_statement_column_text( NULL, 0, &value ) ); assert( !database_statement_column_text( statement, -1, &value ) ); assert( !database_statement_column_text( statement, 2, &value ) ); assert( !database_statement_column_text( statement, 0, NULL ) ); database_statement_finalize(statement); database_close(database); } /** * @brief Vérifie la lecture stricte des colonnes entières. */ static void test_column_int64(void) { Database *database = NULL; DatabaseStatement *statement = NULL; int64_t value = INT64_C(0); database = database_open(":memory:"); assert(database != NULL); statement = database_statement_prepare( database, "SELECT 42, NULL, '42';" ); assert(statement != NULL); assert( database_statement_step(statement) == DATABASE_STATEMENT_STEP_ROW ); assert( database_statement_column_int64( statement, 0, &value ) ); assert(value == INT64_C(42)); /* * SQL NULL n'est pas un entier valide. */ assert( !database_statement_column_int64( statement, 1, &value ) ); /* * Le texte '42' n'est pas accepté comme entier. */ assert( !database_statement_column_int64( statement, 2, &value ) ); assert( !database_statement_column_int64( NULL, 0, &value ) ); assert( !database_statement_column_int64( statement, -1, &value ) ); assert( !database_statement_column_int64( statement, 3, &value ) ); assert( !database_statement_column_int64( statement, 0, NULL ) ); database_statement_finalize(statement); database_close(database); } /** * @brief Vérifie la conservation exacte d'un paramètre BLOB. */ static void test_bind_and_read_blob(void) { const guint8 expected_data[] = {0x00U, 0x41U, 0xFFU, 0x0AU}; Database *database = database_open(":memory:"); DatabaseStatement *statement = database_statement_prepare(database, "SELECT ?;"); GBytes *input = g_bytes_new_static(expected_data, sizeof(expected_data)); GBytes *output = NULL; gconstpointer output_data = NULL; gsize output_size = 0U; assert(database_statement_bind_blob(statement, 1, input)); assert(database_statement_step(statement) == DATABASE_STATEMENT_STEP_ROW); assert(database_statement_column_blob(statement, 0, &output)); output_data = g_bytes_get_data(output, &output_size); assert(output_size == sizeof(expected_data)); assert(memcmp(output_data, expected_data, sizeof(expected_data)) == 0); g_bytes_unref(output); g_bytes_unref(input); database_statement_finalize(statement); database_close(database); } int main(void) { test_prepare_valid_statement(); test_prepare_invalid_statement(); test_invalid_parameters(); test_bind_valid_text(); test_bind_invalid_text(); test_step_select_statement(); test_step_non_query_statement(); test_step_invalid_statement(); test_reset_statement(); test_reset_invalid_statement(); test_clear_bindings(); test_clear_bindings_invalid_statement(); test_column_is_null(); test_column_text(); test_column_int64(); test_bind_and_read_blob(); printf( "DatabaseStatement : tous les tests sont valides.\n" ); return 0; }