feat: add evidence metadata during import
This commit is contained in:
parent
6c34287feb
commit
18566280a7
12 changed files with 4469 additions and 18 deletions
8
.gitignore
vendored
8
.gitignore
vendored
|
|
@ -1,7 +1,13 @@
|
|||
# Build
|
||||
enquete-gui
|
||||
labfy-investigation
|
||||
*.o
|
||||
|
||||
# Executables de tests
|
||||
/tests/test_*
|
||||
|
||||
# Conserver les sources des tests
|
||||
!/tests/test_*.c
|
||||
|
||||
# SQLite temporaires
|
||||
*.sqlite-shm
|
||||
*.sqlite-wal
|
||||
|
|
|
|||
52
Makefile
52
Makefile
|
|
@ -24,6 +24,18 @@ TEST_CFLAGS = -std=c17 \
|
|||
TEST_LDFLAGS = $(shell $(PKG_CONFIG) --libs glib-2.0 gio-2.0)
|
||||
|
||||
EVIDENCE_RECORD_TEST_CFLAGS := $(TEST_CFLAGS) -Wpedantic
|
||||
EVIDENCE_TYPE_TEST_CFLAGS := $(TEST_CFLAGS) -Wpedantic
|
||||
EVIDENCE_TYPE_DAO_TEST_CFLAGS := $(TEST_CFLAGS) -Wpedantic
|
||||
EVIDENCE_IMPORT_DIALOG_TEST_CFLAGS := \
|
||||
-std=c17 \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-Werror \
|
||||
-Iinclude \
|
||||
$(shell $(PKG_CONFIG) --cflags gtk4)
|
||||
|
||||
EVIDENCE_IMPORT_DIALOG_TEST_LDFLAGS := \
|
||||
$(shell $(PKG_CONFIG) --libs gtk4)
|
||||
|
||||
SRC := $(shell find src -name "*.c")
|
||||
|
||||
|
|
@ -55,6 +67,9 @@ TEST_FILE_HASH := tests/test_file_hash
|
|||
TEST_EVIDENCE_COPY := tests/test_evidence_copy
|
||||
TEST_EVIDENCE_IMPORTER := tests/test_evidence_importer
|
||||
TEST_EVIDENCE_IMPORT_TASK := tests/test_evidence_import_task
|
||||
TEST_EVIDENCE_TYPE := tests/test_evidence_type
|
||||
TEST_EVIDENCE_TYPE_DAO := tests/test_evidence_type_dao
|
||||
TEST_EVIDENCE_IMPORT_DIALOG := tests/test_evidence_import_dialog
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
|
|
@ -265,6 +280,30 @@ $(TEST_EVIDENCE_IMPORT_TASK): \
|
|||
-DEVIDENCE_IMPORTER_ENABLE_TEST_HOOKS \
|
||||
$^ -o $@ $(TEST_LDFLAGS) -lsqlite3
|
||||
|
||||
$(TEST_EVIDENCE_TYPE): \
|
||||
tests/test_evidence_type.c \
|
||||
src/models/evidence_type.c
|
||||
$(CC) $(EVIDENCE_TYPE_TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS)
|
||||
|
||||
$(TEST_EVIDENCE_TYPE_DAO): \
|
||||
tests/test_evidence_type_dao.c \
|
||||
src/dao/evidence_type_dao.c \
|
||||
src/models/evidence_type.c \
|
||||
src/database/database.c \
|
||||
src/database/schema.c \
|
||||
src/database/statement.c \
|
||||
src/database/transaction.c \
|
||||
src/database/error.c
|
||||
$(CC) $(EVIDENCE_TYPE_DAO_TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS) -lsqlite3
|
||||
|
||||
$(TEST_EVIDENCE_IMPORT_DIALOG): \
|
||||
tests/test_evidence_import_dialog.c \
|
||||
src/views/evidence_import_dialog.c \
|
||||
src/models/evidence_type.c
|
||||
$(CC) $(EVIDENCE_IMPORT_DIALOG_TEST_CFLAGS) $^ \
|
||||
-o $@ \
|
||||
$(EVIDENCE_IMPORT_DIALOG_TEST_LDFLAGS)
|
||||
|
||||
test: \
|
||||
$(TEST_NODE) \
|
||||
$(TEST_TREE_MODEL) \
|
||||
|
|
@ -276,8 +315,10 @@ test: \
|
|||
$(TEST_ERROR) \
|
||||
$(TEST_INVESTIGATION_RECORD) \
|
||||
$(TEST_EVIDENCE_RECORD) \
|
||||
$(TEST_EVIDENCE_TYPE) \
|
||||
$(TEST_INVESTIGATION_DAO) \
|
||||
$(TEST_EVIDENCE_DAO) \
|
||||
$(TEST_EVIDENCE_TYPE_DAO) \
|
||||
$(TEST_INVESTIGATION_SESSION) \
|
||||
$(TEST_BACKGROUND_TASK) \
|
||||
$(TEST_TASK_MANAGER) \
|
||||
|
|
@ -289,7 +330,8 @@ test: \
|
|||
$(TEST_FILE_HASH) \
|
||||
$(TEST_EVIDENCE_COPY) \
|
||||
$(TEST_EVIDENCE_IMPORTER) \
|
||||
$(TEST_EVIDENCE_IMPORT_TASK)
|
||||
$(TEST_EVIDENCE_IMPORT_TASK) \
|
||||
$(TEST_EVIDENCE_IMPORT_DIALOG)
|
||||
@echo "Exécution des tests..."
|
||||
@./$(TEST_NODE)
|
||||
@./$(TEST_TREE_MODEL)
|
||||
|
|
@ -301,8 +343,10 @@ test: \
|
|||
@$(TEST_ERROR)
|
||||
@$(TEST_INVESTIGATION_RECORD)
|
||||
@$(TEST_EVIDENCE_RECORD)
|
||||
@$(TEST_EVIDENCE_TYPE)
|
||||
@$(TEST_INVESTIGATION_DAO)
|
||||
@$(TEST_EVIDENCE_DAO)
|
||||
@$(TEST_EVIDENCE_TYPE_DAO)
|
||||
@$(TEST_INVESTIGATION_SESSION)
|
||||
@$(TEST_BACKGROUND_TASK)
|
||||
@$(TEST_TASK_MANAGER)
|
||||
|
|
@ -315,6 +359,7 @@ test: \
|
|||
@$(TEST_EVIDENCE_COPY)
|
||||
@$(TEST_EVIDENCE_IMPORTER)
|
||||
@$(TEST_EVIDENCE_IMPORT_TASK)
|
||||
@$(TEST_EVIDENCE_IMPORT_DIALOG)
|
||||
@echo "Tous les tests sont valides."
|
||||
|
||||
%.o: %.c
|
||||
|
|
@ -335,6 +380,8 @@ clean:
|
|||
$(TEST_ERROR) \
|
||||
$(TEST_INVESTIGATION_RECORD) \
|
||||
$(TEST_EVIDENCE_RECORD) \
|
||||
$(TEST_EVIDENCE_TYPE) \
|
||||
$(TEST_EVIDENCE_TYPE_DAO) \
|
||||
$(TEST_INVESTIGATION_DAO) \
|
||||
$(TEST_EVIDENCE_DAO) \
|
||||
$(TEST_INVESTIGATION_SESSION) \
|
||||
|
|
@ -348,7 +395,8 @@ clean:
|
|||
$(TEST_FILE_HASH) \
|
||||
$(TEST_EVIDENCE_COPY) \
|
||||
$(TEST_EVIDENCE_IMPORTER) \
|
||||
$(TEST_EVIDENCE_IMPORT_TASK)
|
||||
$(TEST_EVIDENCE_IMPORT_TASK) \
|
||||
$(TEST_EVIDENCE_IMPORT_DIALOG)
|
||||
|
||||
|
||||
.PHONY: clean run test
|
||||
|
|
|
|||
121
include/dao/evidence_type_dao.h
Normal file
121
include/dao/evidence_type_dao.h
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/******************************************************************************
|
||||
* @file evidence_type_dao.h
|
||||
* @brief Lecture des types de preuve depuis SQLite.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef LABFY_INVESTIGATION_EVIDENCE_TYPE_DAO_H
|
||||
#define LABFY_INVESTIGATION_EVIDENCE_TYPE_DAO_H
|
||||
|
||||
#include "database/database.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* @brief DAO opaque donnant accès aux types de preuve.
|
||||
*
|
||||
* Le DAO emprunte la connexion Database reçue lors de sa création.
|
||||
*/
|
||||
typedef struct EvidenceTypeDao EvidenceTypeDao;
|
||||
|
||||
/**
|
||||
* @brief Catégories d’erreurs produites par EvidenceTypeDao.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/**
|
||||
* Un argument public est invalide.
|
||||
*/
|
||||
EVIDENCE_TYPE_DAO_ERROR_INVALID_ARGUMENT,
|
||||
|
||||
/**
|
||||
* L’allocation d’une ressource a échoué.
|
||||
*/
|
||||
EVIDENCE_TYPE_DAO_ERROR_MEMORY,
|
||||
|
||||
/**
|
||||
* La requête SQLite n’a pas pu être préparée.
|
||||
*/
|
||||
EVIDENCE_TYPE_DAO_ERROR_PREPARE,
|
||||
|
||||
/**
|
||||
* Une ligne SQLite n’a pas pu être lue.
|
||||
*/
|
||||
EVIDENCE_TYPE_DAO_ERROR_READ,
|
||||
|
||||
/**
|
||||
* Une ligne SQLite ne peut pas produire un EvidenceType valide.
|
||||
*/
|
||||
EVIDENCE_TYPE_DAO_ERROR_MODEL,
|
||||
|
||||
/**
|
||||
* La table ou le schéma attendu est absent ou invalide.
|
||||
*/
|
||||
EVIDENCE_TYPE_DAO_ERROR_SCHEMA
|
||||
} EvidenceTypeDaoError;
|
||||
|
||||
/**
|
||||
* @brief Domaine d’erreur du DAO des types de preuve.
|
||||
*/
|
||||
#define EVIDENCE_TYPE_DAO_ERROR \
|
||||
evidence_type_dao_error_quark()
|
||||
|
||||
/**
|
||||
* @brief Retourne le domaine d’erreur du DAO.
|
||||
*
|
||||
* @return Quark GLib associé à EvidenceTypeDao.
|
||||
*/
|
||||
GQuark evidence_type_dao_error_quark(void);
|
||||
|
||||
/**
|
||||
* @brief Crée un DAO utilisant une connexion Database existante.
|
||||
*
|
||||
* La connexion est empruntée. Elle doit rester valide pendant toute
|
||||
* la durée de vie du DAO.
|
||||
*
|
||||
* @param database Connexion SQLite ouverte.
|
||||
* @param error Emplacement facultatif recevant une erreur.
|
||||
*
|
||||
* @return Nouveau DAO, ou NULL en cas d’échec.
|
||||
*/
|
||||
EvidenceTypeDao *evidence_type_dao_new(
|
||||
Database *database,
|
||||
GError **error
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Libère le DAO.
|
||||
*
|
||||
* La connexion Database empruntée n’est pas fermée.
|
||||
* Cette fonction accepte NULL.
|
||||
*
|
||||
* @param evidence_type_dao DAO à libérer.
|
||||
*/
|
||||
void evidence_type_dao_free(
|
||||
EvidenceTypeDao *evidence_type_dao
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Charge tous les types de preuve.
|
||||
*
|
||||
* Les types sont triés par identifiant numérique croissant.
|
||||
*
|
||||
* Le tableau retourné appartient à l’appelant et utilise
|
||||
* evidence_type_free() comme fonction de destruction.
|
||||
*
|
||||
* Une table vide produit un tableau vide, sans erreur.
|
||||
*
|
||||
* @param evidence_type_dao DAO valide.
|
||||
* @param error Emplacement facultatif recevant une erreur.
|
||||
*
|
||||
* @return Nouveau GPtrArray, ou NULL en cas d’échec.
|
||||
*/
|
||||
GPtrArray *evidence_type_dao_list_all(
|
||||
EvidenceTypeDao *evidence_type_dao,
|
||||
GError **error
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
132
include/models/evidence_type.h
Normal file
132
include/models/evidence_type.h
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
/******************************************************************************
|
||||
* @file evidence_type.h
|
||||
* @brief Modèle représentant un type de preuve.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef LABFY_INVESTIGATION_EVIDENCE_TYPE_H
|
||||
#define LABFY_INVESTIGATION_EVIDENCE_TYPE_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* @brief Modèle opaque représentant un type de preuve.
|
||||
*/
|
||||
typedef struct EvidenceType EvidenceType;
|
||||
|
||||
/**
|
||||
* @brief Codes d’erreur produits par EvidenceType.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/**
|
||||
* Un argument général est invalide.
|
||||
*/
|
||||
EVIDENCE_TYPE_ERROR_INVALID_ARGUMENT,
|
||||
|
||||
/**
|
||||
* L’identifiant numérique est invalide.
|
||||
*/
|
||||
EVIDENCE_TYPE_ERROR_INVALID_IDENTIFIER,
|
||||
|
||||
/**
|
||||
* Le code métier est invalide.
|
||||
*/
|
||||
EVIDENCE_TYPE_ERROR_INVALID_CODE,
|
||||
|
||||
/**
|
||||
* Le libellé utilisateur est invalide.
|
||||
*/
|
||||
EVIDENCE_TYPE_ERROR_INVALID_LABEL
|
||||
} EvidenceTypeError;
|
||||
|
||||
/**
|
||||
* @brief Domaine d’erreur du modèle EvidenceType.
|
||||
*/
|
||||
#define EVIDENCE_TYPE_ERROR \
|
||||
evidence_type_error_quark()
|
||||
|
||||
/**
|
||||
* @brief Retourne le domaine d’erreur du modèle.
|
||||
*
|
||||
* @return Quark GLib associé à EvidenceType.
|
||||
*/
|
||||
GQuark evidence_type_error_quark(void);
|
||||
|
||||
/**
|
||||
* @brief Crée un type de preuve.
|
||||
*
|
||||
* Les chaînes sont copiées et appartiennent au nouvel objet.
|
||||
*
|
||||
* L’identifiant doit être strictement positif.
|
||||
*
|
||||
* Le code et le libellé sont obligatoires.
|
||||
* La description peut être NULL ou vide.
|
||||
*
|
||||
* @param identifier Identifiant numérique SQLite.
|
||||
* @param code Code métier du type.
|
||||
* @param label Libellé destiné à l’utilisateur.
|
||||
* @param description Description facultative.
|
||||
* @param error Emplacement facultatif recevant une erreur.
|
||||
*
|
||||
* @return Nouveau modèle, ou NULL lorsque les données sont invalides.
|
||||
*/
|
||||
EvidenceType *evidence_type_new(
|
||||
gint64 identifier,
|
||||
const char *code,
|
||||
const char *label,
|
||||
const char *description,
|
||||
GError **error
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Libère un modèle EvidenceType.
|
||||
*
|
||||
* Cette fonction accepte evidence_type == NULL.
|
||||
*
|
||||
* @param evidence_type Modèle à libérer.
|
||||
*/
|
||||
void evidence_type_free(
|
||||
EvidenceType *evidence_type
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne l’identifiant numérique du type.
|
||||
*
|
||||
* @return Identifiant, ou 0 lorsque evidence_type est NULL.
|
||||
*/
|
||||
gint64 evidence_type_get_identifier(
|
||||
const EvidenceType *evidence_type
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne le code métier du type.
|
||||
*
|
||||
* @return Chaîne empruntée, ou NULL.
|
||||
*/
|
||||
const char *evidence_type_get_code(
|
||||
const EvidenceType *evidence_type
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne le libellé utilisateur du type.
|
||||
*
|
||||
* @return Chaîne empruntée, ou NULL.
|
||||
*/
|
||||
const char *evidence_type_get_label(
|
||||
const EvidenceType *evidence_type
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne la description du type.
|
||||
*
|
||||
* @return Chaîne empruntée, ou NULL.
|
||||
*/
|
||||
const char *evidence_type_get_description(
|
||||
const EvidenceType *evidence_type
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
176
include/views/evidence_import_dialog.h
Normal file
176
include/views/evidence_import_dialog.h
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
/******************************************************************************
|
||||
* @file evidence_import_dialog.h
|
||||
* @brief Dialogue GTK de saisie des métadonnées d'une preuve.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef LABFY_INVESTIGATION_EVIDENCE_IMPORT_DIALOG_H
|
||||
#define LABFY_INVESTIGATION_EVIDENCE_IMPORT_DIALOG_H
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* @brief Résultat opaque produit par le dialogue d'import.
|
||||
*/
|
||||
typedef struct EvidenceImportDialogResult EvidenceImportDialogResult;
|
||||
|
||||
/**
|
||||
* @brief Codes d'erreur produits par EvidenceImportDialog.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/**
|
||||
* Un argument public est invalide.
|
||||
*/
|
||||
EVIDENCE_IMPORT_DIALOG_ERROR_INVALID_ARGUMENT,
|
||||
|
||||
/**
|
||||
* Aucun type de preuve n'est disponible.
|
||||
*/
|
||||
EVIDENCE_IMPORT_DIALOG_ERROR_EMPTY_TYPES,
|
||||
|
||||
/**
|
||||
* Une allocation ou la création du dialogue a échoué.
|
||||
*/
|
||||
EVIDENCE_IMPORT_DIALOG_ERROR_MEMORY,
|
||||
|
||||
/**
|
||||
* Les métadonnées saisies sont invalides.
|
||||
*/
|
||||
EVIDENCE_IMPORT_DIALOG_ERROR_INVALID_DATA
|
||||
} EvidenceImportDialogError;
|
||||
|
||||
/**
|
||||
* @brief Domaine d'erreur du dialogue d'import.
|
||||
*/
|
||||
#define EVIDENCE_IMPORT_DIALOG_ERROR \
|
||||
evidence_import_dialog_error_quark()
|
||||
|
||||
/**
|
||||
* @brief Callback appelé après la fermeture du dialogue.
|
||||
*
|
||||
* En cas de validation, result est non NULL et appartient au callback.
|
||||
* Il doit être libéré avec evidence_import_dialog_result_free().
|
||||
*
|
||||
* En cas d'annulation, result vaut NULL.
|
||||
*
|
||||
* @param result Résultat possédé par le callback, ou NULL.
|
||||
* @param user_data Données privées fournies lors de l'ouverture.
|
||||
*/
|
||||
typedef void (*EvidenceImportDialogCallback)(
|
||||
EvidenceImportDialogResult *result,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne le domaine d'erreur du dialogue.
|
||||
*
|
||||
* @return Quark GLib associé à EvidenceImportDialog.
|
||||
*/
|
||||
GQuark evidence_import_dialog_error_quark(void);
|
||||
|
||||
/**
|
||||
* @brief Présente le dialogue de saisie des métadonnées.
|
||||
*
|
||||
* Le chemin du fichier est affiché en lecture seule.
|
||||
*
|
||||
* evidence_types doit contenir des pointeurs EvidenceType valides.
|
||||
* Le dialogue copie les codes et les libellés dont il a besoin :
|
||||
* le tableau peut donc être libéré après le retour de cette fonction.
|
||||
*
|
||||
* Le type dont le code vaut "document" est sélectionné par défaut
|
||||
* lorsqu'il est disponible. Sinon, le premier type est sélectionné.
|
||||
*
|
||||
* @param parent Fenêtre GTK parente.
|
||||
* @param file_path Chemin du fichier sélectionné.
|
||||
* @param evidence_types Tableau de EvidenceType.
|
||||
* @param callback Fonction appelée après validation ou annulation.
|
||||
* @param user_data Données privées transmises au callback.
|
||||
* @param error Emplacement facultatif recevant une erreur immédiate.
|
||||
*
|
||||
* @return TRUE si le dialogue a été créé et présenté.
|
||||
*/
|
||||
gboolean evidence_import_dialog_present(
|
||||
GtkWindow *parent,
|
||||
const char *file_path,
|
||||
const GPtrArray *evidence_types,
|
||||
EvidenceImportDialogCallback callback,
|
||||
gpointer user_data,
|
||||
GError **error
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Valide les valeurs obligatoires d'un import.
|
||||
*
|
||||
* Cette fonction ne dépend pas de l'affichage du dialogue et peut être
|
||||
* testée sans ouvrir de fenêtre GTK.
|
||||
*
|
||||
* Le chemin doit désigner un fichier existant.
|
||||
* Le code du type doit être non vide.
|
||||
* La date doit être une date ISO 8601 valide comprenant un fuseau horaire.
|
||||
*
|
||||
* @param file_path Chemin du fichier à importer.
|
||||
* @param type_identifier Code métier du type de preuve.
|
||||
* @param collected_at Date de collecte au format ISO 8601.
|
||||
* @param error Emplacement facultatif recevant une erreur.
|
||||
*
|
||||
* @return TRUE lorsque les valeurs sont valides.
|
||||
*/
|
||||
gboolean evidence_import_dialog_validate_values(
|
||||
const char *file_path,
|
||||
const char *type_identifier,
|
||||
const char *collected_at,
|
||||
GError **error
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Libère le résultat produit par le dialogue.
|
||||
*
|
||||
* Cette fonction accepte NULL.
|
||||
*
|
||||
* @param result Résultat à libérer.
|
||||
*/
|
||||
void evidence_import_dialog_result_free(
|
||||
EvidenceImportDialogResult *result
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne le code du type sélectionné.
|
||||
*
|
||||
* @return Chaîne empruntée, ou NULL.
|
||||
*/
|
||||
const char *evidence_import_dialog_result_get_type_identifier(
|
||||
const EvidenceImportDialogResult *result
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne la date ISO 8601 de collecte.
|
||||
*
|
||||
* @return Chaîne empruntée, ou NULL.
|
||||
*/
|
||||
const char *evidence_import_dialog_result_get_collected_at(
|
||||
const EvidenceImportDialogResult *result
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne la source renseignée.
|
||||
*
|
||||
* @return Chaîne empruntée, ou NULL lorsque la source est vide.
|
||||
*/
|
||||
const char *evidence_import_dialog_result_get_source(
|
||||
const EvidenceImportDialogResult *result
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne la description renseignée.
|
||||
*
|
||||
* @return Chaîne empruntée, ou NULL lorsque la description est vide.
|
||||
*/
|
||||
const char *evidence_import_dialog_result_get_description(
|
||||
const EvidenceImportDialogResult *result
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
|
|
@ -21,6 +21,8 @@
|
|||
#include "views/file_dialog.h"
|
||||
#include "core/evidence_import_task.h"
|
||||
#include "models/evidence_record.h"
|
||||
#include "dao/evidence_type_dao.h"
|
||||
#include "views/evidence_import_dialog.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <errno.h>
|
||||
|
|
@ -36,12 +38,6 @@
|
|||
#define APPLICATION_EVIDENCE_DIRECTORY \
|
||||
"01_Preuves_Originales/Documents"
|
||||
|
||||
/**
|
||||
* @brief Type utilisé avant l’ajout du formulaire de métadonnées.
|
||||
*/
|
||||
#define APPLICATION_DEFAULT_EVIDENCE_TYPE \
|
||||
"document"
|
||||
|
||||
/**
|
||||
* @brief Erreurs produites lors du chargement d'une enquête.
|
||||
*/
|
||||
|
|
@ -96,6 +92,43 @@ typedef struct
|
|||
char *investigation_root_path;
|
||||
} ApplicationEvidenceImportContext;
|
||||
|
||||
/**
|
||||
* @brief Contexte conservé pendant le dialogue de métadonnées.
|
||||
*
|
||||
* Le chemin fourni par FileDialog n'est valide que pendant son callback.
|
||||
* Il doit donc être copié avant l'ouverture du second dialogue.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
Application *application;
|
||||
char *file_path;
|
||||
} ApplicationEvidenceDialogContext;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Libère le contexte du dialogue de métadonnées.
|
||||
*/
|
||||
static void application_evidence_dialog_context_free(
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
ApplicationEvidenceDialogContext *context =
|
||||
user_data;
|
||||
|
||||
if (context == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g_free(
|
||||
context->file_path
|
||||
);
|
||||
|
||||
g_free(
|
||||
context
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Libère le contexte d’un import asynchrone.
|
||||
*/
|
||||
|
|
@ -1115,7 +1148,11 @@ static void application_on_evidence_import_completed(
|
|||
*/
|
||||
static void application_start_evidence_import(
|
||||
Application *application,
|
||||
const char *file_path
|
||||
const char *file_path,
|
||||
const char *type_identifier,
|
||||
const char *collected_at,
|
||||
const char *source,
|
||||
const char *description
|
||||
)
|
||||
{
|
||||
const InvestigationProject *project = NULL;
|
||||
|
|
@ -1142,7 +1179,11 @@ static void application_start_evidence_import(
|
|||
application->session == NULL ||
|
||||
application->task_manager == NULL ||
|
||||
file_path == NULL ||
|
||||
file_path[0] == '\0')
|
||||
file_path[0] == '\0' ||
|
||||
type_identifier == NULL ||
|
||||
type_identifier[0] == '\0' ||
|
||||
collected_at == NULL ||
|
||||
collected_at[0] == '\0')
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -1301,11 +1342,16 @@ static void application_start_evidence_import(
|
|||
APPLICATION_EVIDENCE_DIRECTORY;
|
||||
|
||||
request.type_identifier =
|
||||
APPLICATION_DEFAULT_EVIDENCE_TYPE;
|
||||
type_identifier;
|
||||
|
||||
request.collected_at = NULL;
|
||||
request.source = NULL;
|
||||
request.description = NULL;
|
||||
request.collected_at =
|
||||
collected_at;
|
||||
|
||||
request.source =
|
||||
source;
|
||||
|
||||
request.description =
|
||||
description;
|
||||
|
||||
task =
|
||||
evidence_import_task_start(
|
||||
|
|
@ -1388,6 +1434,91 @@ static void application_start_evidence_import(
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Traite la validation ou l'annulation des métadonnées.
|
||||
*
|
||||
* @param result Résultat possédé par ce callback, ou NULL.
|
||||
* @param user_data Contexte ApplicationEvidenceDialogContext.
|
||||
*/
|
||||
static void application_on_evidence_metadata_completed(
|
||||
EvidenceImportDialogResult *result,
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
ApplicationEvidenceDialogContext *context =
|
||||
user_data;
|
||||
|
||||
Application *application = NULL;
|
||||
|
||||
if (context == NULL)
|
||||
{
|
||||
evidence_import_dialog_result_free(
|
||||
result
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
application =
|
||||
context->application;
|
||||
|
||||
if (application == NULL ||
|
||||
application->main_window == NULL)
|
||||
{
|
||||
evidence_import_dialog_result_free(
|
||||
result
|
||||
);
|
||||
|
||||
application_evidence_dialog_context_free(
|
||||
context
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Une annulation du dialogue ne doit lancer aucune tâche.
|
||||
*/
|
||||
if (result == NULL)
|
||||
{
|
||||
main_window_set_status(
|
||||
application->main_window,
|
||||
"Import de preuve annulé."
|
||||
);
|
||||
|
||||
application_evidence_dialog_context_free(
|
||||
context
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
application_start_evidence_import(
|
||||
application,
|
||||
context->file_path,
|
||||
evidence_import_dialog_result_get_type_identifier(
|
||||
result
|
||||
),
|
||||
evidence_import_dialog_result_get_collected_at(
|
||||
result
|
||||
),
|
||||
evidence_import_dialog_result_get_source(
|
||||
result
|
||||
),
|
||||
evidence_import_dialog_result_get_description(
|
||||
result
|
||||
)
|
||||
);
|
||||
|
||||
evidence_import_dialog_result_free(
|
||||
result
|
||||
);
|
||||
|
||||
application_evidence_dialog_context_free(
|
||||
context
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Traite le fichier de preuve sélectionné.
|
||||
*
|
||||
|
|
@ -1452,9 +1583,174 @@ static void application_on_evidence_file_selected(
|
|||
return;
|
||||
}
|
||||
|
||||
application_start_evidence_import(
|
||||
application,
|
||||
file_path
|
||||
Database *database = NULL;
|
||||
EvidenceTypeDao *evidence_type_dao = NULL;
|
||||
GPtrArray *evidence_types = NULL;
|
||||
|
||||
ApplicationEvidenceDialogContext *dialog_context =
|
||||
NULL;
|
||||
|
||||
GError *dialog_error = NULL;
|
||||
|
||||
database =
|
||||
investigation_session_get_database(
|
||||
application->session
|
||||
);
|
||||
|
||||
if (database == NULL)
|
||||
{
|
||||
application_present_error(
|
||||
application,
|
||||
"Import impossible",
|
||||
"La session ne fournit aucune connexion SQLite."
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
evidence_type_dao =
|
||||
evidence_type_dao_new(
|
||||
database,
|
||||
&dialog_error
|
||||
);
|
||||
|
||||
if (evidence_type_dao == NULL)
|
||||
{
|
||||
application_present_error(
|
||||
application,
|
||||
"Types de preuve indisponibles",
|
||||
dialog_error != NULL
|
||||
? dialog_error->message
|
||||
: "Impossible de créer le DAO des types de preuve."
|
||||
);
|
||||
|
||||
g_clear_error(
|
||||
&dialog_error
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
evidence_types =
|
||||
evidence_type_dao_list_all(
|
||||
evidence_type_dao,
|
||||
&dialog_error
|
||||
);
|
||||
|
||||
evidence_type_dao_free(
|
||||
evidence_type_dao
|
||||
);
|
||||
|
||||
if (evidence_types == NULL)
|
||||
{
|
||||
application_present_error(
|
||||
application,
|
||||
"Types de preuve indisponibles",
|
||||
dialog_error != NULL
|
||||
? dialog_error->message
|
||||
: "Impossible de lire les types de preuve."
|
||||
);
|
||||
|
||||
g_clear_error(
|
||||
&dialog_error
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (evidence_types->len == 0)
|
||||
{
|
||||
application_present_error(
|
||||
application,
|
||||
"Types de preuve indisponibles",
|
||||
"Aucun type de preuve n'est enregistré dans la base."
|
||||
);
|
||||
|
||||
g_ptr_array_unref(
|
||||
evidence_types
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
dialog_context =
|
||||
g_try_new0(
|
||||
ApplicationEvidenceDialogContext,
|
||||
1
|
||||
);
|
||||
|
||||
if (dialog_context == NULL)
|
||||
{
|
||||
application_present_error(
|
||||
application,
|
||||
"Import impossible",
|
||||
"Impossible d'allouer le contexte du dialogue."
|
||||
);
|
||||
|
||||
g_ptr_array_unref(
|
||||
evidence_types
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
dialog_context->application =
|
||||
application;
|
||||
|
||||
dialog_context->file_path =
|
||||
g_strdup(
|
||||
file_path
|
||||
);
|
||||
|
||||
if (dialog_context->file_path == NULL)
|
||||
{
|
||||
application_present_error(
|
||||
application,
|
||||
"Import impossible",
|
||||
"Impossible de conserver le chemin du fichier."
|
||||
);
|
||||
|
||||
application_evidence_dialog_context_free(
|
||||
dialog_context
|
||||
);
|
||||
|
||||
g_ptr_array_unref(
|
||||
evidence_types
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!evidence_import_dialog_present(
|
||||
main_window_get_window(
|
||||
application->main_window
|
||||
),
|
||||
dialog_context->file_path,
|
||||
evidence_types,
|
||||
application_on_evidence_metadata_completed,
|
||||
dialog_context,
|
||||
&dialog_error
|
||||
))
|
||||
{
|
||||
application_present_error(
|
||||
application,
|
||||
"Dialogue d'import impossible",
|
||||
dialog_error != NULL
|
||||
? dialog_error->message
|
||||
: "Le dialogue de métadonnées n'a pas pu être ouvert."
|
||||
);
|
||||
|
||||
g_clear_error(
|
||||
&dialog_error
|
||||
);
|
||||
|
||||
application_evidence_dialog_context_free(
|
||||
dialog_context
|
||||
);
|
||||
}
|
||||
|
||||
g_ptr_array_unref(
|
||||
evidence_types
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
498
src/dao/evidence_type_dao.c
Normal file
498
src/dao/evidence_type_dao.c
Normal file
|
|
@ -0,0 +1,498 @@
|
|||
/******************************************************************************
|
||||
* @file evidence_type_dao.c
|
||||
* @brief Lecture des types de preuve depuis SQLite.
|
||||
******************************************************************************/
|
||||
|
||||
#include "dao/evidence_type_dao.h"
|
||||
|
||||
#include "database/error.h"
|
||||
#include "database/statement.h"
|
||||
#include "models/evidence_type.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
/**
|
||||
* @brief Requête listant les types de preuve.
|
||||
*/
|
||||
static const char *const evidence_type_dao_list_all_sql =
|
||||
"SELECT "
|
||||
" id, "
|
||||
" code, "
|
||||
" label, "
|
||||
" description "
|
||||
"FROM types_preuve "
|
||||
"ORDER BY id ASC;";
|
||||
|
||||
/**
|
||||
* @struct EvidenceTypeDao
|
||||
* @brief Représentation interne du DAO.
|
||||
*/
|
||||
struct EvidenceTypeDao
|
||||
{
|
||||
Database *database;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Libère un EvidenceType contenu dans un GPtrArray.
|
||||
*/
|
||||
static void evidence_type_dao_destroy_type(
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
EvidenceType *evidence_type = user_data;
|
||||
|
||||
evidence_type_free(
|
||||
evidence_type
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Détermine si un message SQLite indique un schéma incompatible.
|
||||
*/
|
||||
static gboolean evidence_type_dao_is_schema_error(
|
||||
const char *database_message
|
||||
)
|
||||
{
|
||||
if (database_message == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return g_strstr_len(
|
||||
database_message,
|
||||
-1,
|
||||
"no such table"
|
||||
) != NULL ||
|
||||
g_strstr_len(
|
||||
database_message,
|
||||
-1,
|
||||
"no such column"
|
||||
) != NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enregistre une erreur de préparation SQL.
|
||||
*/
|
||||
static void evidence_type_dao_set_prepare_error(
|
||||
EvidenceTypeDao *evidence_type_dao,
|
||||
GError **error
|
||||
)
|
||||
{
|
||||
const char *database_message = NULL;
|
||||
EvidenceTypeDaoError error_code =
|
||||
EVIDENCE_TYPE_DAO_ERROR_PREPARE;
|
||||
|
||||
if (error == NULL ||
|
||||
*error != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (evidence_type_dao != NULL)
|
||||
{
|
||||
database_message =
|
||||
database_error_get_message(
|
||||
evidence_type_dao->database
|
||||
);
|
||||
}
|
||||
|
||||
if (evidence_type_dao_is_schema_error(
|
||||
database_message
|
||||
))
|
||||
{
|
||||
error_code =
|
||||
EVIDENCE_TYPE_DAO_ERROR_SCHEMA;
|
||||
}
|
||||
|
||||
g_set_error(
|
||||
error,
|
||||
EVIDENCE_TYPE_DAO_ERROR,
|
||||
error_code,
|
||||
"Impossible de préparer la lecture des types de preuve : %s",
|
||||
database_message != NULL
|
||||
? database_message
|
||||
: "erreur Database inconnue"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enregistre une erreur de lecture SQLite.
|
||||
*/
|
||||
static void evidence_type_dao_set_read_error(
|
||||
EvidenceTypeDao *evidence_type_dao,
|
||||
GError **error,
|
||||
const char *context
|
||||
)
|
||||
{
|
||||
const char *database_message = NULL;
|
||||
|
||||
if (error == NULL ||
|
||||
*error != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (evidence_type_dao != NULL)
|
||||
{
|
||||
database_message =
|
||||
database_error_get_message(
|
||||
evidence_type_dao->database
|
||||
);
|
||||
}
|
||||
|
||||
g_set_error(
|
||||
error,
|
||||
EVIDENCE_TYPE_DAO_ERROR,
|
||||
EVIDENCE_TYPE_DAO_ERROR_READ,
|
||||
"%s : %s",
|
||||
context != NULL
|
||||
? context
|
||||
: "Impossible de lire un type de preuve",
|
||||
database_message != NULL
|
||||
? database_message
|
||||
: "donnée SQLite invalide"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Construit un EvidenceType depuis la ligne SQLite courante.
|
||||
*/
|
||||
static EvidenceType *evidence_type_dao_read_current_row(
|
||||
EvidenceTypeDao *evidence_type_dao,
|
||||
DatabaseStatement *statement,
|
||||
GError **error
|
||||
)
|
||||
{
|
||||
EvidenceType *evidence_type = NULL;
|
||||
|
||||
int64_t identifier = 0;
|
||||
|
||||
char *code = NULL;
|
||||
char *label = NULL;
|
||||
char *description = NULL;
|
||||
|
||||
GError *model_error = NULL;
|
||||
|
||||
if (evidence_type_dao == NULL ||
|
||||
statement == NULL)
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
EVIDENCE_TYPE_DAO_ERROR,
|
||||
EVIDENCE_TYPE_DAO_ERROR_INVALID_ARGUMENT,
|
||||
"La ligne du type de preuve ne peut pas être lue."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!database_statement_column_int64(
|
||||
statement,
|
||||
0,
|
||||
&identifier
|
||||
))
|
||||
{
|
||||
evidence_type_dao_set_read_error(
|
||||
evidence_type_dao,
|
||||
error,
|
||||
"Impossible de lire l’identifiant du type de preuve"
|
||||
);
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!database_statement_column_text(
|
||||
statement,
|
||||
1,
|
||||
&code
|
||||
))
|
||||
{
|
||||
evidence_type_dao_set_read_error(
|
||||
evidence_type_dao,
|
||||
error,
|
||||
"Impossible de lire le code du type de preuve"
|
||||
);
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!database_statement_column_text(
|
||||
statement,
|
||||
2,
|
||||
&label
|
||||
))
|
||||
{
|
||||
evidence_type_dao_set_read_error(
|
||||
evidence_type_dao,
|
||||
error,
|
||||
"Impossible de lire le libellé du type de preuve"
|
||||
);
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!database_statement_column_text(
|
||||
statement,
|
||||
3,
|
||||
&description
|
||||
))
|
||||
{
|
||||
evidence_type_dao_set_read_error(
|
||||
evidence_type_dao,
|
||||
error,
|
||||
"Impossible de lire la description du type de preuve"
|
||||
);
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
evidence_type =
|
||||
evidence_type_new(
|
||||
(gint64) identifier,
|
||||
code,
|
||||
label,
|
||||
description,
|
||||
&model_error
|
||||
);
|
||||
|
||||
if (evidence_type == NULL)
|
||||
{
|
||||
g_set_error(
|
||||
error,
|
||||
EVIDENCE_TYPE_DAO_ERROR,
|
||||
EVIDENCE_TYPE_DAO_ERROR_MODEL,
|
||||
"Le type de preuve lu depuis SQLite est invalide : %s",
|
||||
model_error != NULL
|
||||
? model_error->message
|
||||
: "erreur de modèle inconnue"
|
||||
);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
g_clear_error(
|
||||
&model_error
|
||||
);
|
||||
|
||||
g_free(
|
||||
description
|
||||
);
|
||||
|
||||
g_free(
|
||||
label
|
||||
);
|
||||
|
||||
g_free(
|
||||
code
|
||||
);
|
||||
|
||||
return evidence_type;
|
||||
}
|
||||
|
||||
GQuark evidence_type_dao_error_quark(void)
|
||||
{
|
||||
return g_quark_from_static_string(
|
||||
"evidence-type-dao-error-quark"
|
||||
);
|
||||
}
|
||||
|
||||
EvidenceTypeDao *evidence_type_dao_new(
|
||||
Database *database,
|
||||
GError **error
|
||||
)
|
||||
{
|
||||
EvidenceTypeDao *evidence_type_dao = NULL;
|
||||
|
||||
g_return_val_if_fail(
|
||||
error == NULL || *error == NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (database == NULL)
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
EVIDENCE_TYPE_DAO_ERROR,
|
||||
EVIDENCE_TYPE_DAO_ERROR_INVALID_ARGUMENT,
|
||||
"La connexion Database est obligatoire."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
evidence_type_dao =
|
||||
g_try_new0(
|
||||
EvidenceTypeDao,
|
||||
1
|
||||
);
|
||||
|
||||
if (evidence_type_dao == NULL)
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
EVIDENCE_TYPE_DAO_ERROR,
|
||||
EVIDENCE_TYPE_DAO_ERROR_MEMORY,
|
||||
"Impossible d’allouer le DAO des types de preuve."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* La connexion reste possédée par la session ou le code appelant.
|
||||
*/
|
||||
evidence_type_dao->database =
|
||||
database;
|
||||
|
||||
return evidence_type_dao;
|
||||
}
|
||||
|
||||
void evidence_type_dao_free(
|
||||
EvidenceTypeDao *evidence_type_dao
|
||||
)
|
||||
{
|
||||
if (evidence_type_dao == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Database est empruntée et ne doit pas être fermée ici.
|
||||
*/
|
||||
evidence_type_dao->database = NULL;
|
||||
|
||||
g_free(
|
||||
evidence_type_dao
|
||||
);
|
||||
}
|
||||
|
||||
GPtrArray *evidence_type_dao_list_all(
|
||||
EvidenceTypeDao *evidence_type_dao,
|
||||
GError **error
|
||||
)
|
||||
{
|
||||
DatabaseStatement *statement = NULL;
|
||||
|
||||
GPtrArray *evidence_types = NULL;
|
||||
|
||||
DatabaseStatementStepResult step_result =
|
||||
DATABASE_STATEMENT_STEP_ERROR;
|
||||
|
||||
gboolean success = FALSE;
|
||||
|
||||
g_return_val_if_fail(
|
||||
error == NULL || *error == NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (evidence_type_dao == NULL ||
|
||||
evidence_type_dao->database == NULL)
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
EVIDENCE_TYPE_DAO_ERROR,
|
||||
EVIDENCE_TYPE_DAO_ERROR_INVALID_ARGUMENT,
|
||||
"Le DAO des types de preuve est invalide."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
evidence_types =
|
||||
g_ptr_array_new_with_free_func(
|
||||
evidence_type_dao_destroy_type
|
||||
);
|
||||
|
||||
if (evidence_types == NULL)
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
EVIDENCE_TYPE_DAO_ERROR,
|
||||
EVIDENCE_TYPE_DAO_ERROR_MEMORY,
|
||||
"Impossible d’allouer la liste des types de preuve."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
statement =
|
||||
database_statement_prepare(
|
||||
evidence_type_dao->database,
|
||||
evidence_type_dao_list_all_sql
|
||||
);
|
||||
|
||||
if (statement == NULL)
|
||||
{
|
||||
evidence_type_dao_set_prepare_error(
|
||||
evidence_type_dao,
|
||||
error
|
||||
);
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
EvidenceType *evidence_type = NULL;
|
||||
|
||||
step_result =
|
||||
database_statement_step(
|
||||
statement
|
||||
);
|
||||
|
||||
if (step_result ==
|
||||
DATABASE_STATEMENT_STEP_DONE)
|
||||
{
|
||||
success = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (step_result ==
|
||||
DATABASE_STATEMENT_STEP_ERROR)
|
||||
{
|
||||
evidence_type_dao_set_read_error(
|
||||
evidence_type_dao,
|
||||
error,
|
||||
"Impossible de parcourir les types de preuve"
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
evidence_type =
|
||||
evidence_type_dao_read_current_row(
|
||||
evidence_type_dao,
|
||||
statement,
|
||||
error
|
||||
);
|
||||
|
||||
if (evidence_type == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
g_ptr_array_add(
|
||||
evidence_types,
|
||||
evidence_type
|
||||
);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
database_statement_finalize(
|
||||
statement
|
||||
);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
g_ptr_array_unref(
|
||||
evidence_types
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return evidence_types;
|
||||
}
|
||||
266
src/models/evidence_type.c
Normal file
266
src/models/evidence_type.c
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
/******************************************************************************
|
||||
* @file evidence_type.c
|
||||
* @brief Implémentation du modèle représentant un type de preuve.
|
||||
******************************************************************************/
|
||||
|
||||
#include "models/evidence_type.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
/**
|
||||
* @struct EvidenceType
|
||||
* @brief Représentation interne d’un type de preuve.
|
||||
*/
|
||||
struct EvidenceType
|
||||
{
|
||||
gint64 identifier;
|
||||
char *code;
|
||||
char *label;
|
||||
char *description;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Copie une chaîne après suppression des espaces périphériques.
|
||||
*
|
||||
* @param value Chaîne à copier.
|
||||
*
|
||||
* @return Nouvelle chaîne normalisée, ou NULL lorsque value vaut NULL.
|
||||
*/
|
||||
static char *evidence_type_duplicate_trimmed(
|
||||
const char *value
|
||||
)
|
||||
{
|
||||
char *copy = NULL;
|
||||
|
||||
if (value == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
copy = g_strdup(
|
||||
value
|
||||
);
|
||||
|
||||
g_strstrip(
|
||||
copy
|
||||
);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie qu’une chaîne obligatoire contient du texte.
|
||||
*
|
||||
* @param value Chaîne déjà normalisée.
|
||||
*
|
||||
* @return TRUE lorsque la chaîne contient au moins un caractère.
|
||||
*/
|
||||
static gboolean evidence_type_required_value_is_valid(
|
||||
const char *value
|
||||
)
|
||||
{
|
||||
return value != NULL &&
|
||||
value[0] != '\0';
|
||||
}
|
||||
|
||||
GQuark evidence_type_error_quark(void)
|
||||
{
|
||||
return g_quark_from_static_string(
|
||||
"evidence-type-error-quark"
|
||||
);
|
||||
}
|
||||
|
||||
EvidenceType *evidence_type_new(
|
||||
gint64 identifier,
|
||||
const char *code,
|
||||
const char *label,
|
||||
const char *description,
|
||||
GError **error
|
||||
)
|
||||
{
|
||||
EvidenceType *evidence_type = NULL;
|
||||
|
||||
char *normalized_code = NULL;
|
||||
char *normalized_label = NULL;
|
||||
char *normalized_description = NULL;
|
||||
|
||||
g_return_val_if_fail(
|
||||
error == NULL || *error == NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (identifier <= 0)
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
EVIDENCE_TYPE_ERROR,
|
||||
EVIDENCE_TYPE_ERROR_INVALID_IDENTIFIER,
|
||||
"L’identifiant du type de preuve doit être strictement positif."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
normalized_code =
|
||||
evidence_type_duplicate_trimmed(
|
||||
code
|
||||
);
|
||||
|
||||
if (!evidence_type_required_value_is_valid(
|
||||
normalized_code
|
||||
))
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
EVIDENCE_TYPE_ERROR,
|
||||
EVIDENCE_TYPE_ERROR_INVALID_CODE,
|
||||
"Le code du type de preuve est obligatoire."
|
||||
);
|
||||
|
||||
g_free(
|
||||
normalized_code
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
normalized_label =
|
||||
evidence_type_duplicate_trimmed(
|
||||
label
|
||||
);
|
||||
|
||||
if (!evidence_type_required_value_is_valid(
|
||||
normalized_label
|
||||
))
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
EVIDENCE_TYPE_ERROR,
|
||||
EVIDENCE_TYPE_ERROR_INVALID_LABEL,
|
||||
"Le libellé du type de preuve est obligatoire."
|
||||
);
|
||||
|
||||
g_free(
|
||||
normalized_code
|
||||
);
|
||||
|
||||
g_free(
|
||||
normalized_label
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
normalized_description =
|
||||
evidence_type_duplicate_trimmed(
|
||||
description
|
||||
);
|
||||
|
||||
/*
|
||||
* Une description vide ou composée uniquement d’espaces
|
||||
* est représentée par NULL.
|
||||
*/
|
||||
if (normalized_description != NULL &&
|
||||
normalized_description[0] == '\0')
|
||||
{
|
||||
g_free(
|
||||
normalized_description
|
||||
);
|
||||
|
||||
normalized_description = NULL;
|
||||
}
|
||||
|
||||
evidence_type =
|
||||
g_new0(
|
||||
EvidenceType,
|
||||
1
|
||||
);
|
||||
|
||||
evidence_type->identifier =
|
||||
identifier;
|
||||
|
||||
evidence_type->code =
|
||||
normalized_code;
|
||||
|
||||
evidence_type->label =
|
||||
normalized_label;
|
||||
|
||||
evidence_type->description =
|
||||
normalized_description;
|
||||
|
||||
return evidence_type;
|
||||
}
|
||||
|
||||
void evidence_type_free(
|
||||
EvidenceType *evidence_type
|
||||
)
|
||||
{
|
||||
if (evidence_type == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g_free(
|
||||
evidence_type->code
|
||||
);
|
||||
|
||||
g_free(
|
||||
evidence_type->label
|
||||
);
|
||||
|
||||
g_free(
|
||||
evidence_type->description
|
||||
);
|
||||
|
||||
g_free(
|
||||
evidence_type
|
||||
);
|
||||
}
|
||||
|
||||
gint64 evidence_type_get_identifier(
|
||||
const EvidenceType *evidence_type
|
||||
)
|
||||
{
|
||||
if (evidence_type == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return evidence_type->identifier;
|
||||
}
|
||||
|
||||
const char *evidence_type_get_code(
|
||||
const EvidenceType *evidence_type
|
||||
)
|
||||
{
|
||||
if (evidence_type == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return evidence_type->code;
|
||||
}
|
||||
|
||||
const char *evidence_type_get_label(
|
||||
const EvidenceType *evidence_type
|
||||
)
|
||||
{
|
||||
if (evidence_type == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return evidence_type->label;
|
||||
}
|
||||
|
||||
const char *evidence_type_get_description(
|
||||
const EvidenceType *evidence_type
|
||||
)
|
||||
{
|
||||
if (evidence_type == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return evidence_type->description;
|
||||
}
|
||||
1705
src/views/evidence_import_dialog.c
Normal file
1705
src/views/evidence_import_dialog.c
Normal file
File diff suppressed because it is too large
Load diff
369
tests/test_evidence_import_dialog.c
Normal file
369
tests/test_evidence_import_dialog.c
Normal file
|
|
@ -0,0 +1,369 @@
|
|||
/******************************************************************************
|
||||
* @file test_evidence_import_dialog.c
|
||||
* @brief Tests de validation du dialogue d'import d'une preuve.
|
||||
******************************************************************************/
|
||||
|
||||
#include "views/evidence_import_dialog.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
/**
|
||||
* @brief Fichier temporaire utilisé par les tests.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char *directory_path;
|
||||
char *file_path;
|
||||
} TestEvidenceImportDialogFixture;
|
||||
|
||||
/**
|
||||
* @brief Crée un fichier ordinaire temporaire.
|
||||
*/
|
||||
static TestEvidenceImportDialogFixture
|
||||
test_evidence_import_dialog_fixture_create(void)
|
||||
{
|
||||
TestEvidenceImportDialogFixture fixture = {0};
|
||||
GError *error = NULL;
|
||||
|
||||
fixture.directory_path =
|
||||
g_dir_make_tmp(
|
||||
"labfy-evidence-import-dialog-test-XXXXXX",
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(error);
|
||||
g_assert_nonnull(fixture.directory_path);
|
||||
|
||||
fixture.file_path =
|
||||
g_build_filename(
|
||||
fixture.directory_path,
|
||||
"preuve.txt",
|
||||
NULL
|
||||
);
|
||||
|
||||
g_assert_nonnull(fixture.file_path);
|
||||
|
||||
g_file_set_contents(
|
||||
fixture.file_path,
|
||||
"preuve de test\n",
|
||||
-1,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(error);
|
||||
|
||||
return fixture;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Supprime les ressources temporaires.
|
||||
*/
|
||||
static void test_evidence_import_dialog_fixture_clear(
|
||||
TestEvidenceImportDialogFixture *fixture
|
||||
)
|
||||
{
|
||||
g_assert_nonnull(fixture);
|
||||
|
||||
g_assert_cmpint(
|
||||
g_remove(fixture->file_path),
|
||||
==,
|
||||
0
|
||||
);
|
||||
|
||||
g_assert_cmpint(
|
||||
g_rmdir(fixture->directory_path),
|
||||
==,
|
||||
0
|
||||
);
|
||||
|
||||
g_free(fixture->file_path);
|
||||
g_free(fixture->directory_path);
|
||||
|
||||
fixture->file_path = NULL;
|
||||
fixture->directory_path = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie une date UTC valide.
|
||||
*/
|
||||
static void test_evidence_import_dialog_validate_utc(void)
|
||||
{
|
||||
TestEvidenceImportDialogFixture fixture =
|
||||
test_evidence_import_dialog_fixture_create();
|
||||
|
||||
GError *error = NULL;
|
||||
|
||||
g_assert_true(
|
||||
evidence_import_dialog_validate_values(
|
||||
fixture.file_path,
|
||||
"document",
|
||||
"2026-07-20T08:30:00Z",
|
||||
&error
|
||||
)
|
||||
);
|
||||
|
||||
g_assert_no_error(error);
|
||||
|
||||
test_evidence_import_dialog_fixture_clear(
|
||||
&fixture
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie une date avec décalage horaire valide.
|
||||
*/
|
||||
static void test_evidence_import_dialog_validate_offset(void)
|
||||
{
|
||||
TestEvidenceImportDialogFixture fixture =
|
||||
test_evidence_import_dialog_fixture_create();
|
||||
|
||||
GError *error = NULL;
|
||||
|
||||
g_assert_true(
|
||||
evidence_import_dialog_validate_values(
|
||||
fixture.file_path,
|
||||
"photo",
|
||||
"2026-07-20T10:30:00+02:00",
|
||||
&error
|
||||
)
|
||||
);
|
||||
|
||||
g_assert_no_error(error);
|
||||
|
||||
test_evidence_import_dialog_fixture_clear(
|
||||
&fixture
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le refus d'un chemin absent.
|
||||
*/
|
||||
static void test_evidence_import_dialog_missing_path(void)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
g_assert_false(
|
||||
evidence_import_dialog_validate_values(
|
||||
NULL,
|
||||
"document",
|
||||
"2026-07-20T08:30:00Z",
|
||||
&error
|
||||
)
|
||||
);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
EVIDENCE_IMPORT_DIALOG_ERROR,
|
||||
EVIDENCE_IMPORT_DIALOG_ERROR_INVALID_DATA
|
||||
);
|
||||
|
||||
g_clear_error(&error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le refus d'un fichier inexistant.
|
||||
*/
|
||||
static void test_evidence_import_dialog_missing_file(void)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
g_assert_false(
|
||||
evidence_import_dialog_validate_values(
|
||||
"/tmp/labfy-file-that-does-not-exist",
|
||||
"document",
|
||||
"2026-07-20T08:30:00Z",
|
||||
&error
|
||||
)
|
||||
);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
EVIDENCE_IMPORT_DIALOG_ERROR,
|
||||
EVIDENCE_IMPORT_DIALOG_ERROR_INVALID_DATA
|
||||
);
|
||||
|
||||
g_clear_error(&error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le refus d'un type vide.
|
||||
*/
|
||||
static void test_evidence_import_dialog_missing_type(void)
|
||||
{
|
||||
TestEvidenceImportDialogFixture fixture =
|
||||
test_evidence_import_dialog_fixture_create();
|
||||
|
||||
GError *error = NULL;
|
||||
|
||||
g_assert_false(
|
||||
evidence_import_dialog_validate_values(
|
||||
fixture.file_path,
|
||||
" ",
|
||||
"2026-07-20T08:30:00Z",
|
||||
&error
|
||||
)
|
||||
);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
EVIDENCE_IMPORT_DIALOG_ERROR,
|
||||
EVIDENCE_IMPORT_DIALOG_ERROR_INVALID_DATA
|
||||
);
|
||||
|
||||
g_clear_error(&error);
|
||||
|
||||
test_evidence_import_dialog_fixture_clear(
|
||||
&fixture
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le refus d'une date absente.
|
||||
*/
|
||||
static void test_evidence_import_dialog_missing_date(void)
|
||||
{
|
||||
TestEvidenceImportDialogFixture fixture =
|
||||
test_evidence_import_dialog_fixture_create();
|
||||
|
||||
GError *error = NULL;
|
||||
|
||||
g_assert_false(
|
||||
evidence_import_dialog_validate_values(
|
||||
fixture.file_path,
|
||||
"document",
|
||||
NULL,
|
||||
&error
|
||||
)
|
||||
);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
EVIDENCE_IMPORT_DIALOG_ERROR,
|
||||
EVIDENCE_IMPORT_DIALOG_ERROR_INVALID_DATA
|
||||
);
|
||||
|
||||
g_clear_error(&error);
|
||||
|
||||
test_evidence_import_dialog_fixture_clear(
|
||||
&fixture
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le refus d'une date sans fuseau horaire.
|
||||
*/
|
||||
static void test_evidence_import_dialog_missing_timezone(void)
|
||||
{
|
||||
TestEvidenceImportDialogFixture fixture =
|
||||
test_evidence_import_dialog_fixture_create();
|
||||
|
||||
GError *error = NULL;
|
||||
|
||||
g_assert_false(
|
||||
evidence_import_dialog_validate_values(
|
||||
fixture.file_path,
|
||||
"document",
|
||||
"2026-07-20T08:30:00",
|
||||
&error
|
||||
)
|
||||
);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
EVIDENCE_IMPORT_DIALOG_ERROR,
|
||||
EVIDENCE_IMPORT_DIALOG_ERROR_INVALID_DATA
|
||||
);
|
||||
|
||||
g_clear_error(&error);
|
||||
|
||||
test_evidence_import_dialog_fixture_clear(
|
||||
&fixture
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le refus d'une date civile impossible.
|
||||
*/
|
||||
static void test_evidence_import_dialog_invalid_date(void)
|
||||
{
|
||||
TestEvidenceImportDialogFixture fixture =
|
||||
test_evidence_import_dialog_fixture_create();
|
||||
|
||||
GError *error = NULL;
|
||||
|
||||
g_assert_false(
|
||||
evidence_import_dialog_validate_values(
|
||||
fixture.file_path,
|
||||
"document",
|
||||
"2026-02-30T08:30:00+01:00",
|
||||
&error
|
||||
)
|
||||
);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
EVIDENCE_IMPORT_DIALOG_ERROR,
|
||||
EVIDENCE_IMPORT_DIALOG_ERROR_INVALID_DATA
|
||||
);
|
||||
|
||||
g_clear_error(&error);
|
||||
|
||||
test_evidence_import_dialog_fixture_clear(
|
||||
&fixture
|
||||
);
|
||||
}
|
||||
|
||||
int main(
|
||||
int argc,
|
||||
char **argv
|
||||
)
|
||||
{
|
||||
g_test_init(
|
||||
&argc,
|
||||
&argv,
|
||||
NULL
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-import-dialog/validate-utc",
|
||||
test_evidence_import_dialog_validate_utc
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-import-dialog/validate-offset",
|
||||
test_evidence_import_dialog_validate_offset
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-import-dialog/missing-path",
|
||||
test_evidence_import_dialog_missing_path
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-import-dialog/missing-file",
|
||||
test_evidence_import_dialog_missing_file
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-import-dialog/missing-type",
|
||||
test_evidence_import_dialog_missing_type
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-import-dialog/missing-date",
|
||||
test_evidence_import_dialog_missing_date
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-import-dialog/missing-timezone",
|
||||
test_evidence_import_dialog_missing_timezone
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-import-dialog/invalid-date",
|
||||
test_evidence_import_dialog_invalid_date
|
||||
);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
339
tests/test_evidence_type.c
Normal file
339
tests/test_evidence_type.c
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
/******************************************************************************
|
||||
* @file test_evidence_type.c
|
||||
* @brief Tests unitaires du modèle EvidenceType.
|
||||
******************************************************************************/
|
||||
|
||||
#include "models/evidence_type.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
/**
|
||||
* @brief Vérifie la création d’un type valide.
|
||||
*/
|
||||
static void test_evidence_type_new_valid(void)
|
||||
{
|
||||
EvidenceType *evidence_type = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
evidence_type = evidence_type_new(
|
||||
4,
|
||||
"document",
|
||||
"Document",
|
||||
"Document numérique ou numérisé.",
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(error);
|
||||
g_assert_nonnull(evidence_type);
|
||||
|
||||
g_assert_cmpint(
|
||||
evidence_type_get_identifier(evidence_type),
|
||||
==,
|
||||
4
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
evidence_type_get_code(evidence_type),
|
||||
==,
|
||||
"document"
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
evidence_type_get_label(evidence_type),
|
||||
==,
|
||||
"Document"
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
evidence_type_get_description(evidence_type),
|
||||
==,
|
||||
"Document numérique ou numérisé."
|
||||
);
|
||||
|
||||
evidence_type_free(evidence_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie la suppression des espaces périphériques.
|
||||
*/
|
||||
static void test_evidence_type_values_are_trimmed(void)
|
||||
{
|
||||
EvidenceType *evidence_type = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
evidence_type = evidence_type_new(
|
||||
1,
|
||||
" screenshot ",
|
||||
" Capture d’écran ",
|
||||
" Image capturée depuis un écran. ",
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(error);
|
||||
g_assert_nonnull(evidence_type);
|
||||
|
||||
g_assert_cmpstr(
|
||||
evidence_type_get_code(evidence_type),
|
||||
==,
|
||||
"screenshot"
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
evidence_type_get_label(evidence_type),
|
||||
==,
|
||||
"Capture d’écran"
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
evidence_type_get_description(evidence_type),
|
||||
==,
|
||||
"Image capturée depuis un écran."
|
||||
);
|
||||
|
||||
evidence_type_free(evidence_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie qu’une description absente reste facultative.
|
||||
*/
|
||||
static void test_evidence_type_description_is_optional(void)
|
||||
{
|
||||
EvidenceType *evidence_type = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
evidence_type = evidence_type_new(
|
||||
9,
|
||||
"other",
|
||||
"Autre",
|
||||
NULL,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(error);
|
||||
g_assert_nonnull(evidence_type);
|
||||
|
||||
g_assert_null(
|
||||
evidence_type_get_description(evidence_type)
|
||||
);
|
||||
|
||||
evidence_type_free(evidence_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie qu’une description vide est normalisée vers NULL.
|
||||
*/
|
||||
static void test_evidence_type_empty_description_becomes_null(void)
|
||||
{
|
||||
EvidenceType *evidence_type = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
evidence_type = evidence_type_new(
|
||||
8,
|
||||
"text",
|
||||
"Texte",
|
||||
" ",
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(error);
|
||||
g_assert_nonnull(evidence_type);
|
||||
|
||||
g_assert_null(
|
||||
evidence_type_get_description(evidence_type)
|
||||
);
|
||||
|
||||
evidence_type_free(evidence_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le refus d’un identifiant invalide.
|
||||
*/
|
||||
static void test_evidence_type_invalid_identifier(void)
|
||||
{
|
||||
EvidenceType *evidence_type = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
evidence_type = evidence_type_new(
|
||||
0,
|
||||
"document",
|
||||
"Document",
|
||||
NULL,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_null(evidence_type);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
EVIDENCE_TYPE_ERROR,
|
||||
EVIDENCE_TYPE_ERROR_INVALID_IDENTIFIER
|
||||
);
|
||||
|
||||
g_clear_error(&error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le refus d’un code absent.
|
||||
*/
|
||||
static void test_evidence_type_missing_code(void)
|
||||
{
|
||||
EvidenceType *evidence_type = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
evidence_type = evidence_type_new(
|
||||
4,
|
||||
NULL,
|
||||
"Document",
|
||||
NULL,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_null(evidence_type);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
EVIDENCE_TYPE_ERROR,
|
||||
EVIDENCE_TYPE_ERROR_INVALID_CODE
|
||||
);
|
||||
|
||||
g_clear_error(&error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le refus d’un code vide.
|
||||
*/
|
||||
static void test_evidence_type_empty_code(void)
|
||||
{
|
||||
EvidenceType *evidence_type = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
evidence_type = evidence_type_new(
|
||||
4,
|
||||
" ",
|
||||
"Document",
|
||||
NULL,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_null(evidence_type);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
EVIDENCE_TYPE_ERROR,
|
||||
EVIDENCE_TYPE_ERROR_INVALID_CODE
|
||||
);
|
||||
|
||||
g_clear_error(&error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le refus d’un libellé absent.
|
||||
*/
|
||||
static void test_evidence_type_missing_label(void)
|
||||
{
|
||||
EvidenceType *evidence_type = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
evidence_type = evidence_type_new(
|
||||
4,
|
||||
"document",
|
||||
NULL,
|
||||
NULL,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_null(evidence_type);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
EVIDENCE_TYPE_ERROR,
|
||||
EVIDENCE_TYPE_ERROR_INVALID_LABEL
|
||||
);
|
||||
|
||||
g_clear_error(&error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le comportement des getters avec NULL.
|
||||
*/
|
||||
static void test_evidence_type_null_getters(void)
|
||||
{
|
||||
g_assert_cmpint(
|
||||
evidence_type_get_identifier(NULL),
|
||||
==,
|
||||
0
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
evidence_type_get_code(NULL)
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
evidence_type_get_label(NULL)
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
evidence_type_get_description(NULL)
|
||||
);
|
||||
|
||||
evidence_type_free(NULL);
|
||||
}
|
||||
|
||||
int main(
|
||||
int argc,
|
||||
char **argv
|
||||
)
|
||||
{
|
||||
g_test_init(
|
||||
&argc,
|
||||
&argv,
|
||||
NULL
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-type/new-valid",
|
||||
test_evidence_type_new_valid
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-type/values-are-trimmed",
|
||||
test_evidence_type_values_are_trimmed
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-type/description-is-optional",
|
||||
test_evidence_type_description_is_optional
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-type/empty-description-becomes-null",
|
||||
test_evidence_type_empty_description_becomes_null
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-type/invalid-identifier",
|
||||
test_evidence_type_invalid_identifier
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-type/missing-code",
|
||||
test_evidence_type_missing_code
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-type/empty-code",
|
||||
test_evidence_type_empty_code
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-type/missing-label",
|
||||
test_evidence_type_missing_label
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-type/null-getters",
|
||||
test_evidence_type_null_getters
|
||||
);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
495
tests/test_evidence_type_dao.c
Normal file
495
tests/test_evidence_type_dao.c
Normal file
|
|
@ -0,0 +1,495 @@
|
|||
/******************************************************************************
|
||||
* @file test_evidence_type_dao.c
|
||||
* @brief Tests du DAO des types de preuve.
|
||||
******************************************************************************/
|
||||
|
||||
#include "dao/evidence_type_dao.h"
|
||||
|
||||
#include "database/database.h"
|
||||
#include "database/statement.h"
|
||||
#include "models/evidence_type.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
/**
|
||||
* @brief Ressources utilisées par un test EvidenceTypeDao.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char *temporary_directory;
|
||||
char *database_path;
|
||||
|
||||
Database *database;
|
||||
EvidenceTypeDao *evidence_type_dao;
|
||||
} TestEvidenceTypeDaoFixture;
|
||||
|
||||
/**
|
||||
* @brief Exécute une requête SQL ne retournant aucune ligne.
|
||||
*/
|
||||
static void test_evidence_type_dao_execute_sql(
|
||||
Database *database,
|
||||
const char *sql
|
||||
)
|
||||
{
|
||||
DatabaseStatement *statement = NULL;
|
||||
|
||||
g_assert_nonnull(database);
|
||||
g_assert_nonnull(sql);
|
||||
|
||||
statement =
|
||||
database_statement_prepare(
|
||||
database,
|
||||
sql
|
||||
);
|
||||
|
||||
g_assert_nonnull(statement);
|
||||
|
||||
g_assert_cmpint(
|
||||
database_statement_step(statement),
|
||||
==,
|
||||
DATABASE_STATEMENT_STEP_DONE
|
||||
);
|
||||
|
||||
database_statement_finalize(
|
||||
statement
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Crée une base temporaire contenant le schéma de l’application.
|
||||
*/
|
||||
static TestEvidenceTypeDaoFixture
|
||||
test_evidence_type_dao_fixture_create(void)
|
||||
{
|
||||
TestEvidenceTypeDaoFixture fixture = {0};
|
||||
|
||||
GError *error = NULL;
|
||||
|
||||
fixture.temporary_directory =
|
||||
g_dir_make_tmp(
|
||||
"labfy-evidence-type-dao-test-XXXXXX",
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(error);
|
||||
g_assert_nonnull(
|
||||
fixture.temporary_directory
|
||||
);
|
||||
|
||||
fixture.database_path =
|
||||
g_build_filename(
|
||||
fixture.temporary_directory,
|
||||
"Enquete.sqlite",
|
||||
NULL
|
||||
);
|
||||
|
||||
g_assert_nonnull(
|
||||
fixture.database_path
|
||||
);
|
||||
|
||||
g_assert_true(
|
||||
database_initialize(
|
||||
fixture.database_path,
|
||||
"Enquete_EvidenceTypeDao",
|
||||
fixture.temporary_directory
|
||||
)
|
||||
);
|
||||
|
||||
fixture.database =
|
||||
database_open(
|
||||
fixture.database_path
|
||||
);
|
||||
|
||||
g_assert_nonnull(
|
||||
fixture.database
|
||||
);
|
||||
|
||||
fixture.evidence_type_dao =
|
||||
evidence_type_dao_new(
|
||||
fixture.database,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(error);
|
||||
|
||||
g_assert_nonnull(
|
||||
fixture.evidence_type_dao
|
||||
);
|
||||
|
||||
return fixture;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Libère la fixture et supprime la base temporaire.
|
||||
*/
|
||||
static void test_evidence_type_dao_fixture_clear(
|
||||
TestEvidenceTypeDaoFixture *fixture
|
||||
)
|
||||
{
|
||||
g_assert_nonnull(fixture);
|
||||
|
||||
evidence_type_dao_free(
|
||||
fixture->evidence_type_dao
|
||||
);
|
||||
|
||||
database_close(
|
||||
fixture->database
|
||||
);
|
||||
|
||||
g_assert_cmpint(
|
||||
g_remove(fixture->database_path),
|
||||
==,
|
||||
0
|
||||
);
|
||||
|
||||
g_assert_cmpint(
|
||||
g_rmdir(fixture->temporary_directory),
|
||||
==,
|
||||
0
|
||||
);
|
||||
|
||||
g_free(
|
||||
fixture->database_path
|
||||
);
|
||||
|
||||
g_free(
|
||||
fixture->temporary_directory
|
||||
);
|
||||
|
||||
fixture->evidence_type_dao = NULL;
|
||||
fixture->database = NULL;
|
||||
fixture->database_path = NULL;
|
||||
fixture->temporary_directory = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le refus d’une connexion absente.
|
||||
*/
|
||||
static void test_evidence_type_dao_new_invalid_database(void)
|
||||
{
|
||||
EvidenceTypeDao *evidence_type_dao = NULL;
|
||||
|
||||
GError *error = NULL;
|
||||
|
||||
evidence_type_dao =
|
||||
evidence_type_dao_new(
|
||||
NULL,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
evidence_type_dao
|
||||
);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
EVIDENCE_TYPE_DAO_ERROR,
|
||||
EVIDENCE_TYPE_DAO_ERROR_INVALID_ARGUMENT
|
||||
);
|
||||
|
||||
g_clear_error(
|
||||
&error
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le chargement du catalogue initial.
|
||||
*/
|
||||
static void test_evidence_type_dao_list_all(void)
|
||||
{
|
||||
static const char *const expected_codes[] =
|
||||
{
|
||||
"screenshot",
|
||||
"photo",
|
||||
"video",
|
||||
"document",
|
||||
"email",
|
||||
"archive",
|
||||
"audio",
|
||||
"text",
|
||||
"other"
|
||||
};
|
||||
|
||||
static const char *const expected_labels[] =
|
||||
{
|
||||
"Capture d'écran",
|
||||
"Photographie",
|
||||
"Vidéo",
|
||||
"Document",
|
||||
"Courrier électronique",
|
||||
"Archive",
|
||||
"Audio",
|
||||
"Texte",
|
||||
"Autre"
|
||||
};
|
||||
|
||||
TestEvidenceTypeDaoFixture fixture =
|
||||
test_evidence_type_dao_fixture_create();
|
||||
|
||||
GPtrArray *evidence_types = NULL;
|
||||
|
||||
GError *error = NULL;
|
||||
|
||||
guint index = 0;
|
||||
|
||||
evidence_types =
|
||||
evidence_type_dao_list_all(
|
||||
fixture.evidence_type_dao,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(error);
|
||||
g_assert_nonnull(evidence_types);
|
||||
|
||||
g_assert_cmpuint(
|
||||
evidence_types->len,
|
||||
==,
|
||||
G_N_ELEMENTS(expected_codes)
|
||||
);
|
||||
|
||||
for (index = 0;
|
||||
index < evidence_types->len;
|
||||
index++)
|
||||
{
|
||||
const EvidenceType *evidence_type =
|
||||
g_ptr_array_index(
|
||||
evidence_types,
|
||||
index
|
||||
);
|
||||
|
||||
g_assert_nonnull(
|
||||
evidence_type
|
||||
);
|
||||
|
||||
/*
|
||||
* La requête utilise ORDER BY id ASC.
|
||||
*/
|
||||
g_assert_cmpint(
|
||||
evidence_type_get_identifier(
|
||||
evidence_type
|
||||
),
|
||||
==,
|
||||
(gint64) index + 1
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
evidence_type_get_code(
|
||||
evidence_type
|
||||
),
|
||||
==,
|
||||
expected_codes[index]
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
evidence_type_get_label(
|
||||
evidence_type
|
||||
),
|
||||
==,
|
||||
expected_labels[index]
|
||||
);
|
||||
}
|
||||
|
||||
g_ptr_array_unref(
|
||||
evidence_types
|
||||
);
|
||||
|
||||
test_evidence_type_dao_fixture_clear(
|
||||
&fixture
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie qu’une table vide retourne un tableau vide.
|
||||
*/
|
||||
static void test_evidence_type_dao_list_empty(void)
|
||||
{
|
||||
TestEvidenceTypeDaoFixture fixture =
|
||||
test_evidence_type_dao_fixture_create();
|
||||
|
||||
GPtrArray *evidence_types = NULL;
|
||||
|
||||
GError *error = NULL;
|
||||
|
||||
test_evidence_type_dao_execute_sql(
|
||||
fixture.database,
|
||||
"DELETE FROM types_preuve;"
|
||||
);
|
||||
|
||||
evidence_types =
|
||||
evidence_type_dao_list_all(
|
||||
fixture.evidence_type_dao,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(error);
|
||||
g_assert_nonnull(evidence_types);
|
||||
|
||||
g_assert_cmpuint(
|
||||
evidence_types->len,
|
||||
==,
|
||||
0
|
||||
);
|
||||
|
||||
g_ptr_array_unref(
|
||||
evidence_types
|
||||
);
|
||||
|
||||
test_evidence_type_dao_fixture_clear(
|
||||
&fixture
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le signalement d’une table absente.
|
||||
*/
|
||||
static void test_evidence_type_dao_missing_table(void)
|
||||
{
|
||||
Database *database = NULL;
|
||||
|
||||
EvidenceTypeDao *evidence_type_dao = NULL;
|
||||
|
||||
GPtrArray *evidence_types = NULL;
|
||||
|
||||
GError *error = NULL;
|
||||
|
||||
database =
|
||||
database_open(
|
||||
":memory:"
|
||||
);
|
||||
|
||||
g_assert_nonnull(database);
|
||||
|
||||
evidence_type_dao =
|
||||
evidence_type_dao_new(
|
||||
database,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(error);
|
||||
g_assert_nonnull(evidence_type_dao);
|
||||
|
||||
/*
|
||||
* DatabaseStatement journalise l’échec de préparation SQLite.
|
||||
*/
|
||||
g_test_expect_message(
|
||||
NULL,
|
||||
G_LOG_LEVEL_WARNING,
|
||||
"*Impossible de préparer la requête SQL*"
|
||||
);
|
||||
|
||||
evidence_types =
|
||||
evidence_type_dao_list_all(
|
||||
evidence_type_dao,
|
||||
&error
|
||||
);
|
||||
|
||||
g_test_assert_expected_messages();
|
||||
|
||||
g_assert_null(evidence_types);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
EVIDENCE_TYPE_DAO_ERROR,
|
||||
EVIDENCE_TYPE_DAO_ERROR_SCHEMA
|
||||
);
|
||||
|
||||
g_clear_error(
|
||||
&error
|
||||
);
|
||||
|
||||
evidence_type_dao_free(
|
||||
evidence_type_dao
|
||||
);
|
||||
|
||||
database_close(
|
||||
database
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le refus d’une ligne produisant un modèle invalide.
|
||||
*/
|
||||
static void test_evidence_type_dao_invalid_model(void)
|
||||
{
|
||||
TestEvidenceTypeDaoFixture fixture =
|
||||
test_evidence_type_dao_fixture_create();
|
||||
|
||||
GPtrArray *evidence_types = NULL;
|
||||
|
||||
GError *error = NULL;
|
||||
|
||||
/*
|
||||
* La contrainte SQLite interdit NULL mais pas une chaîne
|
||||
* uniquement composée d’espaces.
|
||||
*
|
||||
* EvidenceType doit normaliser puis refuser cette valeur.
|
||||
*/
|
||||
test_evidence_type_dao_execute_sql(
|
||||
fixture.database,
|
||||
"UPDATE types_preuve "
|
||||
"SET code = ' ' "
|
||||
"WHERE id = 1;"
|
||||
);
|
||||
|
||||
evidence_types =
|
||||
evidence_type_dao_list_all(
|
||||
fixture.evidence_type_dao,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_null(evidence_types);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
EVIDENCE_TYPE_DAO_ERROR,
|
||||
EVIDENCE_TYPE_DAO_ERROR_MODEL
|
||||
);
|
||||
|
||||
g_clear_error(
|
||||
&error
|
||||
);
|
||||
|
||||
test_evidence_type_dao_fixture_clear(
|
||||
&fixture
|
||||
);
|
||||
}
|
||||
|
||||
int main(
|
||||
int argc,
|
||||
char **argv
|
||||
)
|
||||
{
|
||||
g_test_init(
|
||||
&argc,
|
||||
&argv,
|
||||
NULL
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-type-dao/new-invalid-database",
|
||||
test_evidence_type_dao_new_invalid_database
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-type-dao/list-all",
|
||||
test_evidence_type_dao_list_all
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-type-dao/list-empty",
|
||||
test_evidence_type_dao_list_empty
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-type-dao/missing-table",
|
||||
test_evidence_type_dao_missing_table
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/evidence-type-dao/invalid-model",
|
||||
test_evidence_type_dao_invalid_model
|
||||
);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
Loading…
Reference in a new issue