Compare commits
No commits in common. "c8860cf9f247979a29a373d25d8b2b2fcaf311f8" and "ce2a95b4b07fdf7a21a768019913b6c9a6d71dd6" have entirely different histories.
c8860cf9f2
...
ce2a95b4b0
17 changed files with 4 additions and 9780 deletions
77
Makefile
77
Makefile
|
|
@ -25,7 +25,6 @@ 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
|
||||
ENTITY_TYPE_TEST_CFLAGS := $(TEST_CFLAGS) -Wpedantic
|
||||
EVIDENCE_TYPE_DAO_TEST_CFLAGS := $(TEST_CFLAGS) -Wpedantic
|
||||
EVIDENCE_IMPORT_DIALOG_TEST_CFLAGS := \
|
||||
-std=c17 \
|
||||
|
|
@ -41,10 +40,6 @@ EVIDENCE_IMPORT_DIALOG_TEST_LDFLAGS := \
|
|||
EVIDENCE_INTEGRITY_VERIFIER_TEST_CFLAGS := \
|
||||
$(TEST_CFLAGS) \
|
||||
-Wpedantic
|
||||
ENTITY_RECORD_TEST_CFLAGS := $(TEST_CFLAGS) -Wpedantic
|
||||
ENTITY_TYPE_DAO_TEST_CFLAGS := $(TEST_CFLAGS) -Wpedantic
|
||||
ENTITY_DAO_TEST_CFLAGS := $(TEST_CFLAGS) -Wpedantic
|
||||
EVIDENCE_ENTITY_DAO_TEST_CFLAGS := $(TEST_CFLAGS) -Wpedantic
|
||||
|
||||
SRC := $(shell find src -name "*.c")
|
||||
|
||||
|
|
@ -78,7 +73,6 @@ 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_ENTITY_TYPE := tests/test_entity_type
|
||||
TEST_EVIDENCE_TYPE_DAO := tests/test_evidence_type_dao
|
||||
TEST_EVIDENCE_IMPORT_DIALOG := tests/test_evidence_import_dialog
|
||||
TEST_EVIDENCE_LIST_ITEM := tests/test_evidence_list_item
|
||||
|
|
@ -86,10 +80,6 @@ TEST_EVIDENCE_LIST_MODEL := tests/test_evidence_list_model
|
|||
TEST_EVIDENCE_CATEGORY_ITEM := tests/test_evidence_category_item
|
||||
TEST_EVIDENCE_CATEGORY_MODEL := tests/test_evidence_category_model
|
||||
TEST_EVIDENCE_INTEGRITY_TASK := tests/test_evidence_integrity_task
|
||||
TEST_ENTITY_RECORD := tests/test_entity_record
|
||||
TEST_ENTITY_TYPE_DAO := tests/test_entity_type_dao
|
||||
TEST_ENTITY_DAO := tests/test_entity_dao
|
||||
TEST_EVIDENCE_ENTITY_DAO := tests/test_evidence_entity_dao
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
|
|
@ -166,8 +156,7 @@ $(TEST_INVESTIGATION_RECORD): \
|
|||
|
||||
$(TEST_EVIDENCE_RECORD): \
|
||||
tests/test_evidence_record.c \
|
||||
src/models/evidence_record.c \
|
||||
src/models/entity_record.c
|
||||
src/models/evidence_record.c
|
||||
$(CC) $(EVIDENCE_RECORD_TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS)
|
||||
|
||||
$(TEST_EVIDENCE_LIST_ITEM): \
|
||||
|
|
@ -326,11 +315,6 @@ $(TEST_EVIDENCE_TYPE): \
|
|||
src/models/evidence_type.c
|
||||
$(CC) $(EVIDENCE_TYPE_TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS)
|
||||
|
||||
$(TEST_ENTITY_TYPE): \
|
||||
tests/test_entity_type.c \
|
||||
src/models/entity_type.c
|
||||
$(CC) $(ENTITY_TYPE_TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS)
|
||||
|
||||
$(TEST_EVIDENCE_TYPE_DAO): \
|
||||
tests/test_evidence_type_dao.c \
|
||||
src/dao/evidence_type_dao.c \
|
||||
|
|
@ -376,47 +360,6 @@ $(TEST_EVIDENCE_INTEGRITY_TASK): \
|
|||
-DFILE_HASH_ENABLE_TEST_HOOKS \
|
||||
$^ -o $@ $(TEST_LDFLAGS)
|
||||
|
||||
$(TEST_ENTITY_RECORD): \
|
||||
tests/test_entity_record.c \
|
||||
src/models/entity_record.c
|
||||
$(CC) $(ENTITY_RECORD_TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS)
|
||||
|
||||
$(TEST_ENTITY_TYPE_DAO): \
|
||||
tests/test_entity_type_dao.c \
|
||||
src/dao/entity_type_dao.c \
|
||||
src/models/entity_type.c \
|
||||
src/database/database.c \
|
||||
src/database/schema.c \
|
||||
src/database/statement.c \
|
||||
src/database/transaction.c \
|
||||
src/database/error.c
|
||||
$(CC) $(ENTITY_TYPE_DAO_TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS) -lsqlite3
|
||||
|
||||
$(TEST_ENTITY_DAO): \
|
||||
tests/test_entity_dao.c \
|
||||
src/dao/entity_dao.c \
|
||||
src/models/entity_record.c \
|
||||
src/database/database.c \
|
||||
src/database/schema.c \
|
||||
src/database/statement.c \
|
||||
src/database/transaction.c \
|
||||
src/database/error.c
|
||||
$(CC) $(ENTITY_DAO_TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS) -lsqlite3
|
||||
|
||||
$(TEST_EVIDENCE_ENTITY_DAO): \
|
||||
tests/test_evidence_entity_dao.c \
|
||||
src/dao/evidence_entity_dao.c \
|
||||
src/dao/evidence_dao.c \
|
||||
src/dao/entity_dao.c \
|
||||
src/models/evidence_record.c \
|
||||
src/models/entity_record.c \
|
||||
src/database/database.c \
|
||||
src/database/schema.c \
|
||||
src/database/statement.c \
|
||||
src/database/transaction.c \
|
||||
src/database/error.c
|
||||
$(CC) $(EVIDENCE_ENTITY_DAO_TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS) -lsqlite3
|
||||
|
||||
test: \
|
||||
$(TEST_NODE) \
|
||||
$(TEST_TREE_MODEL) \
|
||||
|
|
@ -433,7 +376,6 @@ test: \
|
|||
$(TEST_EVIDENCE_CATEGORY_ITEM) \
|
||||
$(TEST_EVIDENCE_CATEGORY_MODEL) \
|
||||
$(TEST_EVIDENCE_TYPE) \
|
||||
$(TEST_ENTITY_TYPE) \
|
||||
$(TEST_INVESTIGATION_DAO) \
|
||||
$(TEST_EVIDENCE_DAO) \
|
||||
$(TEST_EVIDENCE_TYPE_DAO) \
|
||||
|
|
@ -451,11 +393,7 @@ test: \
|
|||
$(TEST_EVIDENCE_IMPORTER) \
|
||||
$(TEST_EVIDENCE_IMPORT_TASK) \
|
||||
$(TEST_EVIDENCE_IMPORT_DIALOG) \
|
||||
$(TEST_EVIDENCE_INTEGRITY_TASK) \
|
||||
$(TEST_ENTITY_RECORD) \
|
||||
$(TEST_ENTITY_TYPE_DAO) \
|
||||
$(TEST_ENTITY_DAO) \
|
||||
$(TEST_EVIDENCE_ENTITY_DAO)
|
||||
$(TEST_EVIDENCE_INTEGRITY_TASK)
|
||||
@echo "Exécution des tests..."
|
||||
@./$(TEST_NODE)
|
||||
@./$(TEST_TREE_MODEL)
|
||||
|
|
@ -472,7 +410,6 @@ test: \
|
|||
@$(TEST_EVIDENCE_CATEGORY_MODEL)
|
||||
@$(TEST_EVIDENCE_RECORD)
|
||||
@$(TEST_EVIDENCE_TYPE)
|
||||
@$(TEST_ENTITY_TYPE)
|
||||
@$(TEST_INVESTIGATION_DAO)
|
||||
@$(TEST_EVIDENCE_DAO)
|
||||
@$(TEST_EVIDENCE_TYPE_DAO)
|
||||
|
|
@ -491,10 +428,6 @@ test: \
|
|||
@$(TEST_EVIDENCE_IMPORT_TASK)
|
||||
@$(TEST_EVIDENCE_IMPORT_DIALOG)
|
||||
@$(TEST_EVIDENCE_INTEGRITY_TASK)
|
||||
@$(TEST_ENTITY_RECORD)
|
||||
@$(TEST_ENTITY_TYPE_DAO)
|
||||
@$(TEST_ENTITY_DAO)
|
||||
@$(TEST_EVIDENCE_ENTITY_DAO)
|
||||
@echo "Tous les tests sont valides."
|
||||
|
||||
%.o: %.c
|
||||
|
|
@ -520,7 +453,6 @@ clean:
|
|||
$(TEST_EVIDENCE_CATEGORY_ITEM) \
|
||||
$(TEST_EVIDENCE_CATEGORY_MODEL) \
|
||||
$(TEST_EVIDENCE_TYPE) \
|
||||
$(TEST_ENTITY_TYPE) \
|
||||
$(TEST_EVIDENCE_TYPE_DAO) \
|
||||
$(TEST_INVESTIGATION_DAO) \
|
||||
$(TEST_EVIDENCE_DAO) \
|
||||
|
|
@ -538,8 +470,7 @@ clean:
|
|||
$(TEST_EVIDENCE_IMPORTER) \
|
||||
$(TEST_EVIDENCE_IMPORT_TASK) \
|
||||
$(TEST_EVIDENCE_IMPORT_DIALOG) \
|
||||
$(TEST_EVIDENCE_INTEGRITY_TASK) \
|
||||
$(TEST_ENTITY_DAO) \
|
||||
$(TEST_EVIDENCE_ENTITY_DAO)
|
||||
$(TEST_EVIDENCE_INTEGRITY_TASK)
|
||||
|
||||
|
||||
.PHONY: clean run test
|
||||
|
|
|
|||
|
|
@ -1,151 +0,0 @@
|
|||
/******************************************************************************
|
||||
* @file entity_dao.h
|
||||
* @brief Persistance des entités OSINT dans SQLite.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef LABFY_INVESTIGATION_ENTITY_DAO_H
|
||||
#define LABFY_INVESTIGATION_ENTITY_DAO_H
|
||||
|
||||
#include "database/database.h"
|
||||
#include "models/entity_record.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* @brief Catégories d'erreurs produites par EntityDao.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ENTITY_DAO_ERROR_INVALID_ARGUMENT,
|
||||
ENTITY_DAO_ERROR_MEMORY,
|
||||
ENTITY_DAO_ERROR_PREPARE,
|
||||
ENTITY_DAO_ERROR_BIND,
|
||||
ENTITY_DAO_ERROR_EXECUTE,
|
||||
ENTITY_DAO_ERROR_CONSTRAINT,
|
||||
ENTITY_DAO_ERROR_READ,
|
||||
ENTITY_DAO_ERROR_MODEL,
|
||||
ENTITY_DAO_ERROR_SCHEMA,
|
||||
ENTITY_DAO_ERROR_RANGE
|
||||
} EntityDaoError;
|
||||
|
||||
/**
|
||||
* @brief Domaine d'erreur du DAO des entités.
|
||||
*/
|
||||
#define ENTITY_DAO_ERROR \
|
||||
entity_dao_error_quark()
|
||||
|
||||
/**
|
||||
* @brief Retourne le domaine d'erreur du DAO.
|
||||
*/
|
||||
GQuark entity_dao_error_quark(void);
|
||||
|
||||
/**
|
||||
* @brief DAO opaque donnant accès aux entités persistées.
|
||||
*
|
||||
* Le DAO emprunte la connexion Database reçue lors de sa création.
|
||||
*/
|
||||
typedef struct EntityDao EntityDao;
|
||||
|
||||
/**
|
||||
* @brief Crée un DAO utilisant une connexion Database existante.
|
||||
*
|
||||
* La connexion est empruntée et 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.
|
||||
*/
|
||||
EntityDao *entity_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 entity_dao DAO à libérer.
|
||||
*/
|
||||
void entity_dao_free(
|
||||
EntityDao *entity_dao
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Insère une nouvelle entité.
|
||||
*
|
||||
* Aucun enregistrement existant n'est remplacé.
|
||||
*
|
||||
* @param entity_dao DAO valide.
|
||||
* @param entity_record Entité empruntée.
|
||||
* @param error Emplacement facultatif recevant une erreur.
|
||||
*
|
||||
* @return TRUE si l'insertion réussit.
|
||||
*/
|
||||
gboolean entity_dao_insert(
|
||||
EntityDao *entity_dao,
|
||||
const EntityRecord *entity_record,
|
||||
GError **error
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Recherche une entité par son UUID.
|
||||
*
|
||||
* Une entité absente retourne NULL sans produire d'erreur.
|
||||
*
|
||||
* @param entity_dao DAO valide.
|
||||
* @param identifier UUID recherché.
|
||||
* @param error Emplacement facultatif recevant une erreur.
|
||||
*
|
||||
* @return Nouveau modèle possédé par l'appelant, ou NULL.
|
||||
*/
|
||||
EntityRecord *entity_dao_find_by_identifier(
|
||||
EntityDao *entity_dao,
|
||||
const char *identifier,
|
||||
GError **error
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Charge toutes les entités dans un ordre déterministe.
|
||||
*
|
||||
* L'ordre utilisé est :
|
||||
*
|
||||
* - date de création croissante ;
|
||||
* - UUID croissant en cas d'égalité.
|
||||
*
|
||||
* Le tableau retourné utilise entity_record_free() comme fonction
|
||||
* de destruction.
|
||||
*
|
||||
* @param entity_dao DAO valide.
|
||||
* @param error Emplacement facultatif recevant une erreur.
|
||||
*
|
||||
* @return Nouveau GPtrArray, ou NULL en cas d'échec.
|
||||
*/
|
||||
GPtrArray *entity_dao_list_all(
|
||||
EntityDao *entity_dao,
|
||||
GError **error
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Compte les entités persistées.
|
||||
*
|
||||
* @param entity_dao DAO valide.
|
||||
* @param out_count Destination du nombre d'entités.
|
||||
* @param error Emplacement facultatif recevant une erreur.
|
||||
*
|
||||
* @return TRUE si le comptage réussit.
|
||||
*/
|
||||
gboolean entity_dao_count(
|
||||
EntityDao *entity_dao,
|
||||
guint64 *out_count,
|
||||
GError **error
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
/******************************************************************************
|
||||
* @file entity_type_dao.h
|
||||
* @brief Lecture des types d'entité depuis SQLite.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef LABFY_INVESTIGATION_ENTITY_TYPE_DAO_H
|
||||
#define LABFY_INVESTIGATION_ENTITY_TYPE_DAO_H
|
||||
|
||||
#include "database/database.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* @brief DAO opaque donnant accès aux types d'entité.
|
||||
*
|
||||
* Le DAO emprunte la connexion Database reçue lors de sa création.
|
||||
*/
|
||||
typedef struct EntityTypeDao EntityTypeDao;
|
||||
|
||||
/**
|
||||
* @brief Catégories d'erreurs produites par EntityTypeDao.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/**
|
||||
* Un argument public est invalide.
|
||||
*/
|
||||
ENTITY_TYPE_DAO_ERROR_INVALID_ARGUMENT,
|
||||
|
||||
/**
|
||||
* L'allocation d'une ressource a échoué.
|
||||
*/
|
||||
ENTITY_TYPE_DAO_ERROR_MEMORY,
|
||||
|
||||
/**
|
||||
* La requête SQLite n'a pas pu être préparée.
|
||||
*/
|
||||
ENTITY_TYPE_DAO_ERROR_PREPARE,
|
||||
|
||||
/**
|
||||
* Une ligne SQLite n'a pas pu être lue.
|
||||
*/
|
||||
ENTITY_TYPE_DAO_ERROR_READ,
|
||||
|
||||
/**
|
||||
* Une ligne SQLite ne peut pas produire un EntityType valide.
|
||||
*/
|
||||
ENTITY_TYPE_DAO_ERROR_MODEL,
|
||||
|
||||
/**
|
||||
* La table ou le schéma attendu est absent ou invalide.
|
||||
*/
|
||||
ENTITY_TYPE_DAO_ERROR_SCHEMA
|
||||
} EntityTypeDaoError;
|
||||
|
||||
/**
|
||||
* @brief Domaine d'erreur du DAO des types d'entité.
|
||||
*/
|
||||
#define ENTITY_TYPE_DAO_ERROR \
|
||||
entity_type_dao_error_quark()
|
||||
|
||||
/**
|
||||
* @brief Retourne le domaine d'erreur du DAO.
|
||||
*
|
||||
* @return Quark GLib associé à EntityTypeDao.
|
||||
*/
|
||||
GQuark entity_type_dao_error_quark(void);
|
||||
|
||||
/**
|
||||
* @brief Crée un DAO utilisant une connexion Database existante.
|
||||
*
|
||||
* La connexion est empruntée et 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.
|
||||
*/
|
||||
EntityTypeDao *entity_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 entity_type_dao DAO à libérer.
|
||||
*/
|
||||
void entity_type_dao_free(
|
||||
EntityTypeDao *entity_type_dao
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Charge tous les types d'entité.
|
||||
*
|
||||
* Les types sont triés par identifiant numérique croissant.
|
||||
*
|
||||
* Le tableau retourné appartient à l'appelant et utilise
|
||||
* entity_type_free() comme fonction de destruction.
|
||||
*
|
||||
* Une table vide produit un tableau vide, sans erreur.
|
||||
*
|
||||
* @param entity_type_dao DAO valide.
|
||||
* @param error Emplacement facultatif recevant une erreur.
|
||||
*
|
||||
* @return Nouveau GPtrArray, ou NULL en cas d'échec.
|
||||
*/
|
||||
GPtrArray *entity_type_dao_list_all(
|
||||
EntityTypeDao *entity_type_dao,
|
||||
GError **error
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
|
|
@ -1,218 +0,0 @@
|
|||
/******************************************************************************
|
||||
* @file evidence_entity_dao.h
|
||||
* @brief Persistance des associations entre preuves et entités.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef LABFY_INVESTIGATION_EVIDENCE_ENTITY_DAO_H
|
||||
#define LABFY_INVESTIGATION_EVIDENCE_ENTITY_DAO_H
|
||||
|
||||
#include "database/database.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* @brief Catégories d'erreurs produites par EvidenceEntityDao.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/**
|
||||
* Un argument public est invalide.
|
||||
*/
|
||||
EVIDENCE_ENTITY_DAO_ERROR_INVALID_ARGUMENT,
|
||||
|
||||
/**
|
||||
* L'allocation d'une ressource a échoué.
|
||||
*/
|
||||
EVIDENCE_ENTITY_DAO_ERROR_MEMORY,
|
||||
|
||||
/**
|
||||
* La requête SQLite n'a pas pu être préparée.
|
||||
*/
|
||||
EVIDENCE_ENTITY_DAO_ERROR_PREPARE,
|
||||
|
||||
/**
|
||||
* Un paramètre n'a pas pu être lié à la requête.
|
||||
*/
|
||||
EVIDENCE_ENTITY_DAO_ERROR_BIND,
|
||||
|
||||
/**
|
||||
* La requête SQLite n'a pas pu être exécutée.
|
||||
*/
|
||||
EVIDENCE_ENTITY_DAO_ERROR_EXECUTE,
|
||||
|
||||
/**
|
||||
* Une contrainte SQLite a été violée.
|
||||
*/
|
||||
EVIDENCE_ENTITY_DAO_ERROR_CONSTRAINT,
|
||||
|
||||
/**
|
||||
* Un enregistrement ou une association demandée n'existe pas.
|
||||
*/
|
||||
EVIDENCE_ENTITY_DAO_ERROR_NOT_FOUND,
|
||||
|
||||
/**
|
||||
* Une ligne SQLite n'a pas pu être lue.
|
||||
*/
|
||||
EVIDENCE_ENTITY_DAO_ERROR_READ,
|
||||
|
||||
/**
|
||||
* La table ou une colonne attendue est absente.
|
||||
*/
|
||||
EVIDENCE_ENTITY_DAO_ERROR_SCHEMA
|
||||
} EvidenceEntityDaoError;
|
||||
|
||||
/**
|
||||
* @brief Domaine d'erreur du DAO.
|
||||
*/
|
||||
#define EVIDENCE_ENTITY_DAO_ERROR \
|
||||
evidence_entity_dao_error_quark()
|
||||
|
||||
/**
|
||||
* @brief DAO opaque des associations entre preuves et entités.
|
||||
*
|
||||
* Le DAO emprunte la connexion Database reçue lors de sa création.
|
||||
*/
|
||||
typedef struct EvidenceEntityDao EvidenceEntityDao;
|
||||
|
||||
/**
|
||||
* @brief Retourne le domaine d'erreur du DAO.
|
||||
*/
|
||||
GQuark evidence_entity_dao_error_quark(void);
|
||||
|
||||
/**
|
||||
* @brief Crée un DAO utilisant une connexion Database existante.
|
||||
*
|
||||
* La connexion est empruntée et 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.
|
||||
*/
|
||||
EvidenceEntityDao *evidence_entity_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_entity_dao DAO à libérer.
|
||||
*/
|
||||
void evidence_entity_dao_free(
|
||||
EvidenceEntityDao *evidence_entity_dao
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Associe une preuve à une entité.
|
||||
*
|
||||
* Les deux UUID doivent correspondre à des enregistrements existants.
|
||||
* Une association déjà existante produit une erreur de contrainte.
|
||||
*
|
||||
* @param evidence_entity_dao DAO valide.
|
||||
* @param evidence_identifier UUID de la preuve.
|
||||
* @param entity_identifier UUID de l'entité.
|
||||
* @param error Emplacement facultatif recevant une erreur.
|
||||
*
|
||||
* @return TRUE si l'association est créée.
|
||||
*/
|
||||
gboolean evidence_entity_dao_link(
|
||||
EvidenceEntityDao *evidence_entity_dao,
|
||||
const char *evidence_identifier,
|
||||
const char *entity_identifier,
|
||||
GError **error
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Supprime une association entre une preuve et une entité.
|
||||
*
|
||||
* Une association absente produit EVIDENCE_ENTITY_DAO_ERROR_NOT_FOUND.
|
||||
*
|
||||
* Les enregistrements preuve et entité ne sont jamais supprimés.
|
||||
*
|
||||
* @param evidence_entity_dao DAO valide.
|
||||
* @param evidence_identifier UUID de la preuve.
|
||||
* @param entity_identifier UUID de l'entité.
|
||||
* @param error Emplacement facultatif recevant une erreur.
|
||||
*
|
||||
* @return TRUE si l'association est supprimée.
|
||||
*/
|
||||
gboolean evidence_entity_dao_unlink(
|
||||
EvidenceEntityDao *evidence_entity_dao,
|
||||
const char *evidence_identifier,
|
||||
const char *entity_identifier,
|
||||
GError **error
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Vérifie si une association existe.
|
||||
*
|
||||
* @param evidence_entity_dao DAO valide.
|
||||
* @param evidence_identifier UUID de la preuve.
|
||||
* @param entity_identifier UUID de l'entité.
|
||||
* @param out_exists Destination du résultat.
|
||||
* @param error Emplacement facultatif recevant une erreur.
|
||||
*
|
||||
* @return TRUE si la recherche a été exécutée correctement.
|
||||
*/
|
||||
gboolean evidence_entity_dao_exists(
|
||||
EvidenceEntityDao *evidence_entity_dao,
|
||||
const char *evidence_identifier,
|
||||
const char *entity_identifier,
|
||||
gboolean *out_exists,
|
||||
GError **error
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Liste les UUID des entités liées à une preuve.
|
||||
*
|
||||
* Les identifiants sont triés par ordre lexicographique croissant.
|
||||
*
|
||||
* Le tableau et les chaînes qu'il contient appartiennent à l'appelant.
|
||||
* Le tableau utilise g_free() comme fonction de destruction.
|
||||
*
|
||||
* Une preuve sans association produit un tableau vide.
|
||||
*
|
||||
* @param evidence_entity_dao DAO valide.
|
||||
* @param evidence_identifier UUID de la preuve.
|
||||
* @param error Emplacement facultatif recevant une erreur.
|
||||
*
|
||||
* @return Nouveau GPtrArray de chaînes, ou NULL en cas d'échec.
|
||||
*/
|
||||
GPtrArray *evidence_entity_dao_list_entity_identifiers(
|
||||
EvidenceEntityDao *evidence_entity_dao,
|
||||
const char *evidence_identifier,
|
||||
GError **error
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Liste les UUID des preuves liées à une entité.
|
||||
*
|
||||
* Les identifiants sont triés par ordre lexicographique croissant.
|
||||
*
|
||||
* Le tableau et les chaînes qu'il contient appartiennent à l'appelant.
|
||||
* Le tableau utilise g_free() comme fonction de destruction.
|
||||
*
|
||||
* Une entité sans association produit un tableau vide.
|
||||
*
|
||||
* @param evidence_entity_dao DAO valide.
|
||||
* @param entity_identifier UUID de l'entité.
|
||||
* @param error Emplacement facultatif recevant une erreur.
|
||||
*
|
||||
* @return Nouveau GPtrArray de chaînes, ou NULL en cas d'échec.
|
||||
*/
|
||||
GPtrArray *evidence_entity_dao_list_evidence_identifiers(
|
||||
EvidenceEntityDao *evidence_entity_dao,
|
||||
const char *entity_identifier,
|
||||
GError **error
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
|
|
@ -1,175 +0,0 @@
|
|||
/******************************************************************************
|
||||
* @file entity_record.h
|
||||
* @brief Modèle représentant une entité persistée.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef LABFY_INVESTIGATION_ENTITY_RECORD_H
|
||||
#define LABFY_INVESTIGATION_ENTITY_RECORD_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* @brief Modèle opaque représentant une entité.
|
||||
*/
|
||||
typedef struct EntityRecord EntityRecord;
|
||||
|
||||
/**
|
||||
* @brief Statut métier d'une entité.
|
||||
*
|
||||
* UNKNOWN sert uniquement de valeur défensive et ne doit jamais être
|
||||
* persisté dans SQLite.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ENTITY_STATUS_UNKNOWN,
|
||||
ENTITY_STATUS_ACTIVE,
|
||||
ENTITY_STATUS_ARCHIVED,
|
||||
ENTITY_STATUS_DELETED
|
||||
} EntityStatus;
|
||||
|
||||
/**
|
||||
* @brief Codes d'erreur produits par EntityRecord.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ENTITY_RECORD_ERROR_INVALID_ARGUMENT,
|
||||
ENTITY_RECORD_ERROR_INVALID_IDENTIFIER,
|
||||
ENTITY_RECORD_ERROR_INVALID_TYPE,
|
||||
ENTITY_RECORD_ERROR_INVALID_VALUE,
|
||||
ENTITY_RECORD_ERROR_INVALID_CONFIDENCE,
|
||||
ENTITY_RECORD_ERROR_INVALID_DATE,
|
||||
ENTITY_RECORD_ERROR_INVALID_STATUS
|
||||
} EntityRecordError;
|
||||
|
||||
/**
|
||||
* @brief Domaine d'erreur du modèle EntityRecord.
|
||||
*/
|
||||
#define ENTITY_RECORD_ERROR \
|
||||
entity_record_error_quark()
|
||||
|
||||
/**
|
||||
* @brief Retourne le domaine d'erreur du modèle.
|
||||
*/
|
||||
GQuark entity_record_error_quark(void);
|
||||
|
||||
/**
|
||||
* @brief Crée une entité métier.
|
||||
*
|
||||
* Toutes les chaînes sont copiées.
|
||||
*
|
||||
* Les champs identifier, type_identifier, value, created_at et updated_at
|
||||
* sont obligatoires.
|
||||
*
|
||||
* label et description peuvent être NULL ou vides.
|
||||
*
|
||||
* confidence doit être compris entre 0 et 100.
|
||||
*
|
||||
* status doit être ACTIVE, ARCHIVED ou DELETED.
|
||||
*
|
||||
* @param identifier UUID de l'entité.
|
||||
* @param type_identifier Code métier du type d'entité.
|
||||
* @param value Valeur principale de l'entité.
|
||||
* @param label Libellé facultatif.
|
||||
* @param description Description facultative.
|
||||
* @param confidence Niveau de confiance compris entre 0 et 100.
|
||||
* @param created_at Date UTC de création.
|
||||
* @param updated_at Date UTC de dernière modification.
|
||||
* @param status Statut métier.
|
||||
* @param error Emplacement facultatif recevant une erreur.
|
||||
*
|
||||
* @return Nouvelle entité, ou NULL lorsque les données sont invalides.
|
||||
*/
|
||||
EntityRecord *entity_record_new(
|
||||
const char *identifier,
|
||||
const char *type_identifier,
|
||||
const char *value,
|
||||
const char *label,
|
||||
const char *description,
|
||||
gint confidence,
|
||||
const char *created_at,
|
||||
const char *updated_at,
|
||||
EntityStatus status,
|
||||
GError **error
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Libère une entité.
|
||||
*
|
||||
* Cette fonction accepte NULL.
|
||||
*/
|
||||
void entity_record_free(
|
||||
EntityRecord *entity_record
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne l'UUID de l'entité.
|
||||
*/
|
||||
const char *entity_record_get_identifier(
|
||||
const EntityRecord *entity_record
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne le code métier du type.
|
||||
*/
|
||||
const char *entity_record_get_type_identifier(
|
||||
const EntityRecord *entity_record
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne la valeur principale.
|
||||
*/
|
||||
const char *entity_record_get_value(
|
||||
const EntityRecord *entity_record
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne le libellé facultatif.
|
||||
*/
|
||||
const char *entity_record_get_label(
|
||||
const EntityRecord *entity_record
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne la description facultative.
|
||||
*/
|
||||
const char *entity_record_get_description(
|
||||
const EntityRecord *entity_record
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne le niveau de confiance.
|
||||
*
|
||||
* @return Valeur comprise entre 0 et 100, ou 0 si entity_record est NULL.
|
||||
*/
|
||||
gint entity_record_get_confidence(
|
||||
const EntityRecord *entity_record
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne la date UTC de création.
|
||||
*/
|
||||
const char *entity_record_get_created_at(
|
||||
const EntityRecord *entity_record
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne la date UTC de dernière modification.
|
||||
*/
|
||||
const char *entity_record_get_updated_at(
|
||||
const EntityRecord *entity_record
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne le statut métier.
|
||||
*
|
||||
* @return Statut ou ENTITY_STATUS_UNKNOWN si entity_record est NULL.
|
||||
*/
|
||||
EntityStatus entity_record_get_status(
|
||||
const EntityRecord *entity_record
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
/******************************************************************************
|
||||
* @file entity_type.h
|
||||
* @brief Modèle représentant un type d'entité.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef LABFY_INVESTIGATION_ENTITY_TYPE_H
|
||||
#define LABFY_INVESTIGATION_ENTITY_TYPE_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* @brief Modèle opaque représentant un type d'entité.
|
||||
*/
|
||||
typedef struct EntityType EntityType;
|
||||
|
||||
/**
|
||||
* @brief Codes d'erreur produits par EntityType.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/**
|
||||
* Un argument général est invalide.
|
||||
*/
|
||||
ENTITY_TYPE_ERROR_INVALID_ARGUMENT,
|
||||
|
||||
/**
|
||||
* L'identifiant numérique est invalide.
|
||||
*/
|
||||
ENTITY_TYPE_ERROR_INVALID_IDENTIFIER,
|
||||
|
||||
/**
|
||||
* Le code métier est invalide.
|
||||
*/
|
||||
ENTITY_TYPE_ERROR_INVALID_CODE,
|
||||
|
||||
/**
|
||||
* Le libellé utilisateur est invalide.
|
||||
*/
|
||||
ENTITY_TYPE_ERROR_INVALID_LABEL
|
||||
} EntityTypeError;
|
||||
|
||||
/**
|
||||
* @brief Domaine d'erreur du modèle EntityType.
|
||||
*/
|
||||
#define ENTITY_TYPE_ERROR \
|
||||
entity_type_error_quark()
|
||||
|
||||
/**
|
||||
* @brief Retourne le domaine d'erreur du modèle.
|
||||
*
|
||||
* @return Quark GLib associé à EntityType.
|
||||
*/
|
||||
GQuark entity_type_error_quark(void);
|
||||
|
||||
/**
|
||||
* @brief Crée un type d'entité.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
EntityType *entity_type_new(
|
||||
gint64 identifier,
|
||||
const char *code,
|
||||
const char *label,
|
||||
const char *description,
|
||||
GError **error
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Libère un modèle EntityType.
|
||||
*
|
||||
* Cette fonction accepte entity_type == NULL.
|
||||
*
|
||||
* @param entity_type Modèle à libérer.
|
||||
*/
|
||||
void entity_type_free(
|
||||
EntityType *entity_type
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne l'identifiant numérique du type.
|
||||
*
|
||||
* @return Identifiant, ou 0 lorsque entity_type est NULL.
|
||||
*/
|
||||
gint64 entity_type_get_identifier(
|
||||
const EntityType *entity_type
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne le code métier du type.
|
||||
*
|
||||
* @return Chaîne empruntée, ou NULL.
|
||||
*/
|
||||
const char *entity_type_get_code(
|
||||
const EntityType *entity_type
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne le libellé utilisateur du type.
|
||||
*
|
||||
* @return Chaîne empruntée, ou NULL.
|
||||
*/
|
||||
const char *entity_type_get_label(
|
||||
const EntityType *entity_type
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Retourne la description du type.
|
||||
*
|
||||
* @return Chaîne empruntée, ou NULL.
|
||||
*/
|
||||
const char *entity_type_get_description(
|
||||
const EntityType *entity_type
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
|
|
@ -216,12 +216,6 @@ static void background_task_on_completed(
|
|||
GDestroyNotify completion_data_destroy =
|
||||
NULL;
|
||||
|
||||
BackgroundTaskRunContext *run_context =
|
||||
NULL;
|
||||
|
||||
BackgroundTask *internal_task_reference =
|
||||
NULL;
|
||||
|
||||
(void) source_object;
|
||||
|
||||
if (task == NULL ||
|
||||
|
|
@ -230,11 +224,6 @@ static void background_task_on_completed(
|
|||
return;
|
||||
}
|
||||
|
||||
run_context =
|
||||
g_task_get_task_data(
|
||||
G_TASK(async_result)
|
||||
);
|
||||
|
||||
worker_result = g_task_propagate_pointer(
|
||||
G_TASK(async_result),
|
||||
&worker_error
|
||||
|
|
@ -338,26 +327,6 @@ static void background_task_on_completed(
|
|||
g_clear_error(
|
||||
&worker_error
|
||||
);
|
||||
|
||||
/*
|
||||
* L'exécution est maintenant totalement finalisée.
|
||||
*
|
||||
* La référence interne doit être libérée ici, et non attendre la
|
||||
* destruction ultérieure du GTask. Le pointeur est placé à NULL pour
|
||||
* empêcher background_task_run_context_free() de refaire un unref.
|
||||
*/
|
||||
if (run_context != NULL)
|
||||
{
|
||||
internal_task_reference =
|
||||
run_context->task;
|
||||
|
||||
run_context->task =
|
||||
NULL;
|
||||
}
|
||||
|
||||
background_task_unref(
|
||||
internal_task_reference
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
1683
src/dao/entity_dao.c
1683
src/dao/entity_dao.c
File diff suppressed because it is too large
Load diff
|
|
@ -1,518 +0,0 @@
|
|||
/******************************************************************************
|
||||
* @file entity_type_dao.c
|
||||
* @brief Lecture des types d'entité depuis SQLite.
|
||||
******************************************************************************/
|
||||
|
||||
#include "dao/entity_type_dao.h"
|
||||
|
||||
#include "database/error.h"
|
||||
#include "database/statement.h"
|
||||
#include "models/entity_type.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief Requête listant les types d'entité.
|
||||
*/
|
||||
static const char *const entity_type_dao_list_all_sql =
|
||||
"SELECT "
|
||||
" id, "
|
||||
" code, "
|
||||
" label, "
|
||||
" description "
|
||||
"FROM types_entite "
|
||||
"ORDER BY id ASC;";
|
||||
|
||||
/**
|
||||
* @struct EntityTypeDao
|
||||
* @brief Représentation interne du DAO.
|
||||
*/
|
||||
struct EntityTypeDao
|
||||
{
|
||||
Database *database;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Libère un EntityType contenu dans un GPtrArray.
|
||||
*/
|
||||
static void entity_type_dao_destroy_type(
|
||||
gpointer user_data
|
||||
)
|
||||
{
|
||||
EntityType *entity_type =
|
||||
user_data;
|
||||
|
||||
entity_type_free(
|
||||
entity_type
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Détermine si un message SQLite indique un schéma incompatible.
|
||||
*/
|
||||
static gboolean entity_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 entity_type_dao_set_prepare_error(
|
||||
EntityTypeDao *entity_type_dao,
|
||||
GError **error
|
||||
)
|
||||
{
|
||||
const char *database_message =
|
||||
NULL;
|
||||
|
||||
EntityTypeDaoError error_code =
|
||||
ENTITY_TYPE_DAO_ERROR_PREPARE;
|
||||
|
||||
if (error == NULL ||
|
||||
*error != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (entity_type_dao != NULL)
|
||||
{
|
||||
database_message =
|
||||
database_error_get_message(
|
||||
entity_type_dao->database
|
||||
);
|
||||
}
|
||||
|
||||
if (entity_type_dao_is_schema_error(
|
||||
database_message
|
||||
))
|
||||
{
|
||||
error_code =
|
||||
ENTITY_TYPE_DAO_ERROR_SCHEMA;
|
||||
}
|
||||
|
||||
g_set_error(
|
||||
error,
|
||||
ENTITY_TYPE_DAO_ERROR,
|
||||
error_code,
|
||||
"Impossible de préparer la lecture "
|
||||
"des types d'entité : %s",
|
||||
database_message != NULL
|
||||
? database_message
|
||||
: "erreur Database inconnue"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enregistre une erreur de lecture SQLite.
|
||||
*/
|
||||
static void entity_type_dao_set_read_error(
|
||||
EntityTypeDao *entity_type_dao,
|
||||
GError **error,
|
||||
const char *context
|
||||
)
|
||||
{
|
||||
const char *database_message =
|
||||
NULL;
|
||||
|
||||
if (error == NULL ||
|
||||
*error != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (entity_type_dao != NULL)
|
||||
{
|
||||
database_message =
|
||||
database_error_get_message(
|
||||
entity_type_dao->database
|
||||
);
|
||||
}
|
||||
|
||||
g_set_error(
|
||||
error,
|
||||
ENTITY_TYPE_DAO_ERROR,
|
||||
ENTITY_TYPE_DAO_ERROR_READ,
|
||||
"%s : %s",
|
||||
context != NULL
|
||||
? context
|
||||
: "Impossible de lire un type d'entité",
|
||||
database_message != NULL
|
||||
? database_message
|
||||
: "donnée SQLite invalide"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Construit un EntityType depuis la ligne SQLite courante.
|
||||
*/
|
||||
static EntityType *entity_type_dao_read_current_row(
|
||||
EntityTypeDao *entity_type_dao,
|
||||
DatabaseStatement *statement,
|
||||
GError **error
|
||||
)
|
||||
{
|
||||
EntityType *entity_type =
|
||||
NULL;
|
||||
|
||||
int64_t identifier =
|
||||
0;
|
||||
|
||||
char *code =
|
||||
NULL;
|
||||
|
||||
char *label =
|
||||
NULL;
|
||||
|
||||
char *description =
|
||||
NULL;
|
||||
|
||||
GError *model_error =
|
||||
NULL;
|
||||
|
||||
if (entity_type_dao == NULL ||
|
||||
statement == NULL)
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
ENTITY_TYPE_DAO_ERROR,
|
||||
ENTITY_TYPE_DAO_ERROR_INVALID_ARGUMENT,
|
||||
"La ligne du type d'entité ne peut pas être lue."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!database_statement_column_int64(
|
||||
statement,
|
||||
0,
|
||||
&identifier
|
||||
))
|
||||
{
|
||||
entity_type_dao_set_read_error(
|
||||
entity_type_dao,
|
||||
error,
|
||||
"Impossible de lire l'identifiant du type d'entité"
|
||||
);
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!database_statement_column_text(
|
||||
statement,
|
||||
1,
|
||||
&code
|
||||
))
|
||||
{
|
||||
entity_type_dao_set_read_error(
|
||||
entity_type_dao,
|
||||
error,
|
||||
"Impossible de lire le code du type d'entité"
|
||||
);
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!database_statement_column_text(
|
||||
statement,
|
||||
2,
|
||||
&label
|
||||
))
|
||||
{
|
||||
entity_type_dao_set_read_error(
|
||||
entity_type_dao,
|
||||
error,
|
||||
"Impossible de lire le libellé du type d'entité"
|
||||
);
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!database_statement_column_text(
|
||||
statement,
|
||||
3,
|
||||
&description
|
||||
))
|
||||
{
|
||||
entity_type_dao_set_read_error(
|
||||
entity_type_dao,
|
||||
error,
|
||||
"Impossible de lire la description du type d'entité"
|
||||
);
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
entity_type =
|
||||
entity_type_new(
|
||||
(gint64) identifier,
|
||||
code,
|
||||
label,
|
||||
description,
|
||||
&model_error
|
||||
);
|
||||
|
||||
if (entity_type == NULL)
|
||||
{
|
||||
g_set_error(
|
||||
error,
|
||||
ENTITY_TYPE_DAO_ERROR,
|
||||
ENTITY_TYPE_DAO_ERROR_MODEL,
|
||||
"Le type d'entité 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 entity_type;
|
||||
}
|
||||
|
||||
GQuark entity_type_dao_error_quark(void)
|
||||
{
|
||||
return g_quark_from_static_string(
|
||||
"entity-type-dao-error-quark"
|
||||
);
|
||||
}
|
||||
|
||||
EntityTypeDao *entity_type_dao_new(
|
||||
Database *database,
|
||||
GError **error
|
||||
)
|
||||
{
|
||||
EntityTypeDao *entity_type_dao =
|
||||
NULL;
|
||||
|
||||
g_return_val_if_fail(
|
||||
error == NULL || *error == NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (database == NULL)
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
ENTITY_TYPE_DAO_ERROR,
|
||||
ENTITY_TYPE_DAO_ERROR_INVALID_ARGUMENT,
|
||||
"La connexion Database est obligatoire."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
entity_type_dao =
|
||||
g_try_new0(
|
||||
EntityTypeDao,
|
||||
1
|
||||
);
|
||||
|
||||
if (entity_type_dao == NULL)
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
ENTITY_TYPE_DAO_ERROR,
|
||||
ENTITY_TYPE_DAO_ERROR_MEMORY,
|
||||
"Impossible d'allouer le DAO des types d'entité."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* La connexion reste possédée par la session ou le code appelant.
|
||||
*/
|
||||
entity_type_dao->database =
|
||||
database;
|
||||
|
||||
return entity_type_dao;
|
||||
}
|
||||
|
||||
void entity_type_dao_free(
|
||||
EntityTypeDao *entity_type_dao
|
||||
)
|
||||
{
|
||||
if (entity_type_dao == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Database est empruntée et ne doit pas être fermée ici.
|
||||
*/
|
||||
entity_type_dao->database =
|
||||
NULL;
|
||||
|
||||
g_free(
|
||||
entity_type_dao
|
||||
);
|
||||
}
|
||||
|
||||
GPtrArray *entity_type_dao_list_all(
|
||||
EntityTypeDao *entity_type_dao,
|
||||
GError **error
|
||||
)
|
||||
{
|
||||
DatabaseStatement *statement =
|
||||
NULL;
|
||||
|
||||
GPtrArray *entity_types =
|
||||
NULL;
|
||||
|
||||
DatabaseStatementStepResult step_result =
|
||||
DATABASE_STATEMENT_STEP_ERROR;
|
||||
|
||||
gboolean success =
|
||||
FALSE;
|
||||
|
||||
g_return_val_if_fail(
|
||||
error == NULL || *error == NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (entity_type_dao == NULL ||
|
||||
entity_type_dao->database == NULL)
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
ENTITY_TYPE_DAO_ERROR,
|
||||
ENTITY_TYPE_DAO_ERROR_INVALID_ARGUMENT,
|
||||
"Le DAO des types d'entité est invalide."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
entity_types =
|
||||
g_ptr_array_new_with_free_func(
|
||||
entity_type_dao_destroy_type
|
||||
);
|
||||
|
||||
if (entity_types == NULL)
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
ENTITY_TYPE_DAO_ERROR,
|
||||
ENTITY_TYPE_DAO_ERROR_MEMORY,
|
||||
"Impossible d'allouer la liste des types d'entité."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
statement =
|
||||
database_statement_prepare(
|
||||
entity_type_dao->database,
|
||||
entity_type_dao_list_all_sql
|
||||
);
|
||||
|
||||
if (statement == NULL)
|
||||
{
|
||||
entity_type_dao_set_prepare_error(
|
||||
entity_type_dao,
|
||||
error
|
||||
);
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
EntityType *entity_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)
|
||||
{
|
||||
entity_type_dao_set_read_error(
|
||||
entity_type_dao,
|
||||
error,
|
||||
"Impossible de parcourir les types d'entité"
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
entity_type =
|
||||
entity_type_dao_read_current_row(
|
||||
entity_type_dao,
|
||||
statement,
|
||||
error
|
||||
);
|
||||
|
||||
if (entity_type == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
g_ptr_array_add(
|
||||
entity_types,
|
||||
entity_type
|
||||
);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
database_statement_finalize(
|
||||
statement
|
||||
);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
g_ptr_array_unref(
|
||||
entity_types
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return entity_types;
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,584 +0,0 @@
|
|||
/******************************************************************************
|
||||
* @file entity_record.c
|
||||
* @brief Implémentation du modèle représentant une entité persistée.
|
||||
******************************************************************************/
|
||||
|
||||
#include "models/entity_record.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* @brief Représentation privée d'une entité.
|
||||
*/
|
||||
struct EntityRecord
|
||||
{
|
||||
char *identifier;
|
||||
char *type_identifier;
|
||||
char *value;
|
||||
char *label;
|
||||
char *description;
|
||||
|
||||
gint confidence;
|
||||
|
||||
char *created_at;
|
||||
char *updated_at;
|
||||
|
||||
EntityStatus status;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Copie et nettoie une chaîne.
|
||||
*/
|
||||
static char *entity_record_duplicate_trimmed(
|
||||
const char *value
|
||||
)
|
||||
{
|
||||
char *copy =
|
||||
NULL;
|
||||
|
||||
if (value == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
copy =
|
||||
g_strdup(
|
||||
value
|
||||
);
|
||||
|
||||
g_strstrip(
|
||||
copy
|
||||
);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Normalise un champ facultatif.
|
||||
*
|
||||
* Une chaîne vide après nettoyage devient NULL.
|
||||
*/
|
||||
static char *entity_record_duplicate_optional(
|
||||
const char *value
|
||||
)
|
||||
{
|
||||
char *copy =
|
||||
NULL;
|
||||
|
||||
copy =
|
||||
entity_record_duplicate_trimmed(
|
||||
value
|
||||
);
|
||||
|
||||
if (copy != NULL &&
|
||||
copy[0] == '\0')
|
||||
{
|
||||
g_free(
|
||||
copy
|
||||
);
|
||||
|
||||
copy =
|
||||
NULL;
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie qu'une valeur obligatoire est présente.
|
||||
*/
|
||||
static gboolean entity_record_required_value_is_valid(
|
||||
const char *value
|
||||
)
|
||||
{
|
||||
return value != NULL &&
|
||||
value[0] != '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie une date UTC stricte YYYY-MM-DDTHH:MM:SSZ.
|
||||
*/
|
||||
static gboolean entity_record_timestamp_is_valid(
|
||||
const char *timestamp
|
||||
)
|
||||
{
|
||||
GDateTime *date_time =
|
||||
NULL;
|
||||
|
||||
char *normalized_timestamp =
|
||||
NULL;
|
||||
|
||||
gboolean valid =
|
||||
FALSE;
|
||||
|
||||
gsize character_index =
|
||||
0;
|
||||
|
||||
if (timestamp == NULL ||
|
||||
strlen(timestamp) != 20U)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (timestamp[4] != '-' ||
|
||||
timestamp[7] != '-' ||
|
||||
timestamp[10] != 'T' ||
|
||||
timestamp[13] != ':' ||
|
||||
timestamp[16] != ':' ||
|
||||
timestamp[19] != 'Z')
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (character_index = 0;
|
||||
character_index < 20U;
|
||||
character_index++)
|
||||
{
|
||||
if (character_index == 4U ||
|
||||
character_index == 7U ||
|
||||
character_index == 10U ||
|
||||
character_index == 13U ||
|
||||
character_index == 16U ||
|
||||
character_index == 19U)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!g_ascii_isdigit(
|
||||
timestamp[character_index]
|
||||
))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
date_time =
|
||||
g_date_time_new_from_iso8601(
|
||||
timestamp,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (date_time == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
normalized_timestamp =
|
||||
g_date_time_format(
|
||||
date_time,
|
||||
"%Y-%m-%dT%H:%M:%SZ"
|
||||
);
|
||||
|
||||
valid =
|
||||
normalized_timestamp != NULL &&
|
||||
g_strcmp0(
|
||||
normalized_timestamp,
|
||||
timestamp
|
||||
) == 0;
|
||||
|
||||
g_free(
|
||||
normalized_timestamp
|
||||
);
|
||||
|
||||
g_date_time_unref(
|
||||
date_time
|
||||
);
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie qu'un statut peut être persisté.
|
||||
*/
|
||||
static gboolean entity_record_status_is_valid(
|
||||
EntityStatus status
|
||||
)
|
||||
{
|
||||
return status == ENTITY_STATUS_ACTIVE ||
|
||||
status == ENTITY_STATUS_ARCHIVED ||
|
||||
status == ENTITY_STATUS_DELETED;
|
||||
}
|
||||
|
||||
GQuark entity_record_error_quark(void)
|
||||
{
|
||||
return g_quark_from_static_string(
|
||||
"entity-record-error-quark"
|
||||
);
|
||||
}
|
||||
|
||||
EntityRecord *entity_record_new(
|
||||
const char *identifier,
|
||||
const char *type_identifier,
|
||||
const char *value,
|
||||
const char *label,
|
||||
const char *description,
|
||||
gint confidence,
|
||||
const char *created_at,
|
||||
const char *updated_at,
|
||||
EntityStatus status,
|
||||
GError **error
|
||||
)
|
||||
{
|
||||
EntityRecord *entity_record =
|
||||
NULL;
|
||||
|
||||
char *identifier_copy =
|
||||
NULL;
|
||||
|
||||
char *type_identifier_copy =
|
||||
NULL;
|
||||
|
||||
char *value_copy =
|
||||
NULL;
|
||||
|
||||
char *label_copy =
|
||||
NULL;
|
||||
|
||||
char *description_copy =
|
||||
NULL;
|
||||
|
||||
char *created_at_copy =
|
||||
NULL;
|
||||
|
||||
char *updated_at_copy =
|
||||
NULL;
|
||||
|
||||
g_return_val_if_fail(
|
||||
error == NULL || *error == NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
identifier_copy =
|
||||
entity_record_duplicate_trimmed(
|
||||
identifier
|
||||
);
|
||||
|
||||
if (!entity_record_required_value_is_valid(
|
||||
identifier_copy
|
||||
) ||
|
||||
!g_uuid_string_is_valid(
|
||||
identifier_copy
|
||||
))
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
ENTITY_RECORD_ERROR,
|
||||
ENTITY_RECORD_ERROR_INVALID_IDENTIFIER,
|
||||
"L'identifiant de l'entité n'est pas un UUID valide."
|
||||
);
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
type_identifier_copy =
|
||||
entity_record_duplicate_trimmed(
|
||||
type_identifier
|
||||
);
|
||||
|
||||
if (!entity_record_required_value_is_valid(
|
||||
type_identifier_copy
|
||||
))
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
ENTITY_RECORD_ERROR,
|
||||
ENTITY_RECORD_ERROR_INVALID_TYPE,
|
||||
"Le type de l'entité est obligatoire."
|
||||
);
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
value_copy =
|
||||
entity_record_duplicate_trimmed(
|
||||
value
|
||||
);
|
||||
|
||||
if (!entity_record_required_value_is_valid(
|
||||
value_copy
|
||||
))
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
ENTITY_RECORD_ERROR,
|
||||
ENTITY_RECORD_ERROR_INVALID_VALUE,
|
||||
"La valeur de l'entité est obligatoire."
|
||||
);
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (confidence < 0 ||
|
||||
confidence > 100)
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
ENTITY_RECORD_ERROR,
|
||||
ENTITY_RECORD_ERROR_INVALID_CONFIDENCE,
|
||||
"Le niveau de confiance doit être compris entre 0 et 100."
|
||||
);
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
created_at_copy =
|
||||
entity_record_duplicate_trimmed(
|
||||
created_at
|
||||
);
|
||||
|
||||
if (!entity_record_timestamp_is_valid(
|
||||
created_at_copy
|
||||
))
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
ENTITY_RECORD_ERROR,
|
||||
ENTITY_RECORD_ERROR_INVALID_DATE,
|
||||
"La date de création de l'entité est invalide."
|
||||
);
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
updated_at_copy =
|
||||
entity_record_duplicate_trimmed(
|
||||
updated_at
|
||||
);
|
||||
|
||||
if (!entity_record_timestamp_is_valid(
|
||||
updated_at_copy
|
||||
))
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
ENTITY_RECORD_ERROR,
|
||||
ENTITY_RECORD_ERROR_INVALID_DATE,
|
||||
"La date de modification de l'entité est invalide."
|
||||
);
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!entity_record_status_is_valid(
|
||||
status
|
||||
))
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
ENTITY_RECORD_ERROR,
|
||||
ENTITY_RECORD_ERROR_INVALID_STATUS,
|
||||
"Le statut de l'entité est invalide."
|
||||
);
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
label_copy =
|
||||
entity_record_duplicate_optional(
|
||||
label
|
||||
);
|
||||
|
||||
description_copy =
|
||||
entity_record_duplicate_optional(
|
||||
description
|
||||
);
|
||||
|
||||
entity_record =
|
||||
g_new0(
|
||||
EntityRecord,
|
||||
1
|
||||
);
|
||||
|
||||
entity_record->identifier =
|
||||
identifier_copy;
|
||||
|
||||
entity_record->type_identifier =
|
||||
type_identifier_copy;
|
||||
|
||||
entity_record->value =
|
||||
value_copy;
|
||||
|
||||
entity_record->label =
|
||||
label_copy;
|
||||
|
||||
entity_record->description =
|
||||
description_copy;
|
||||
|
||||
entity_record->confidence =
|
||||
confidence;
|
||||
|
||||
entity_record->created_at =
|
||||
created_at_copy;
|
||||
|
||||
entity_record->updated_at =
|
||||
updated_at_copy;
|
||||
|
||||
entity_record->status =
|
||||
status;
|
||||
|
||||
/*
|
||||
* La propriété a été transférée au modèle.
|
||||
*/
|
||||
identifier_copy = NULL;
|
||||
type_identifier_copy = NULL;
|
||||
value_copy = NULL;
|
||||
label_copy = NULL;
|
||||
description_copy = NULL;
|
||||
created_at_copy = NULL;
|
||||
updated_at_copy = NULL;
|
||||
|
||||
cleanup:
|
||||
|
||||
g_free(
|
||||
updated_at_copy
|
||||
);
|
||||
|
||||
g_free(
|
||||
created_at_copy
|
||||
);
|
||||
|
||||
g_free(
|
||||
description_copy
|
||||
);
|
||||
|
||||
g_free(
|
||||
label_copy
|
||||
);
|
||||
|
||||
g_free(
|
||||
value_copy
|
||||
);
|
||||
|
||||
g_free(
|
||||
type_identifier_copy
|
||||
);
|
||||
|
||||
g_free(
|
||||
identifier_copy
|
||||
);
|
||||
|
||||
return entity_record;
|
||||
}
|
||||
|
||||
void entity_record_free(
|
||||
EntityRecord *entity_record
|
||||
)
|
||||
{
|
||||
if (entity_record == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g_free(
|
||||
entity_record->updated_at
|
||||
);
|
||||
|
||||
g_free(
|
||||
entity_record->created_at
|
||||
);
|
||||
|
||||
g_free(
|
||||
entity_record->description
|
||||
);
|
||||
|
||||
g_free(
|
||||
entity_record->label
|
||||
);
|
||||
|
||||
g_free(
|
||||
entity_record->value
|
||||
);
|
||||
|
||||
g_free(
|
||||
entity_record->type_identifier
|
||||
);
|
||||
|
||||
g_free(
|
||||
entity_record->identifier
|
||||
);
|
||||
|
||||
g_free(
|
||||
entity_record
|
||||
);
|
||||
}
|
||||
|
||||
const char *entity_record_get_identifier(
|
||||
const EntityRecord *entity_record
|
||||
)
|
||||
{
|
||||
return entity_record != NULL
|
||||
? entity_record->identifier
|
||||
: NULL;
|
||||
}
|
||||
|
||||
const char *entity_record_get_type_identifier(
|
||||
const EntityRecord *entity_record
|
||||
)
|
||||
{
|
||||
return entity_record != NULL
|
||||
? entity_record->type_identifier
|
||||
: NULL;
|
||||
}
|
||||
|
||||
const char *entity_record_get_value(
|
||||
const EntityRecord *entity_record
|
||||
)
|
||||
{
|
||||
return entity_record != NULL
|
||||
? entity_record->value
|
||||
: NULL;
|
||||
}
|
||||
|
||||
const char *entity_record_get_label(
|
||||
const EntityRecord *entity_record
|
||||
)
|
||||
{
|
||||
return entity_record != NULL
|
||||
? entity_record->label
|
||||
: NULL;
|
||||
}
|
||||
|
||||
const char *entity_record_get_description(
|
||||
const EntityRecord *entity_record
|
||||
)
|
||||
{
|
||||
return entity_record != NULL
|
||||
? entity_record->description
|
||||
: NULL;
|
||||
}
|
||||
|
||||
gint entity_record_get_confidence(
|
||||
const EntityRecord *entity_record
|
||||
)
|
||||
{
|
||||
return entity_record != NULL
|
||||
? entity_record->confidence
|
||||
: 0;
|
||||
}
|
||||
|
||||
const char *entity_record_get_created_at(
|
||||
const EntityRecord *entity_record
|
||||
)
|
||||
{
|
||||
return entity_record != NULL
|
||||
? entity_record->created_at
|
||||
: NULL;
|
||||
}
|
||||
|
||||
const char *entity_record_get_updated_at(
|
||||
const EntityRecord *entity_record
|
||||
)
|
||||
{
|
||||
return entity_record != NULL
|
||||
? entity_record->updated_at
|
||||
: NULL;
|
||||
}
|
||||
|
||||
EntityStatus entity_record_get_status(
|
||||
const EntityRecord *entity_record
|
||||
)
|
||||
{
|
||||
return entity_record != NULL
|
||||
? entity_record->status
|
||||
: ENTITY_STATUS_UNKNOWN;
|
||||
}
|
||||
|
|
@ -1,275 +0,0 @@
|
|||
/******************************************************************************
|
||||
* @file entity_type.c
|
||||
* @brief Implémentation du modèle représentant un type d'entité.
|
||||
******************************************************************************/
|
||||
|
||||
#include "models/entity_type.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
/**
|
||||
* @struct EntityType
|
||||
* @brief Représentation interne d'un type d'entité.
|
||||
*/
|
||||
struct EntityType
|
||||
{
|
||||
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 *entity_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 entity_type_required_value_is_valid(
|
||||
const char *value
|
||||
)
|
||||
{
|
||||
return value != NULL &&
|
||||
value[0] != '\0';
|
||||
}
|
||||
|
||||
GQuark entity_type_error_quark(void)
|
||||
{
|
||||
return g_quark_from_static_string(
|
||||
"entity-type-error-quark"
|
||||
);
|
||||
}
|
||||
|
||||
EntityType *entity_type_new(
|
||||
gint64 identifier,
|
||||
const char *code,
|
||||
const char *label,
|
||||
const char *description,
|
||||
GError **error
|
||||
)
|
||||
{
|
||||
EntityType *entity_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,
|
||||
ENTITY_TYPE_ERROR,
|
||||
ENTITY_TYPE_ERROR_INVALID_IDENTIFIER,
|
||||
"L'identifiant du type d'entité doit être strictement positif."
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
normalized_code =
|
||||
entity_type_duplicate_trimmed(
|
||||
code
|
||||
);
|
||||
|
||||
if (!entity_type_required_value_is_valid(
|
||||
normalized_code
|
||||
))
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
ENTITY_TYPE_ERROR,
|
||||
ENTITY_TYPE_ERROR_INVALID_CODE,
|
||||
"Le code du type d'entité est obligatoire."
|
||||
);
|
||||
|
||||
g_free(
|
||||
normalized_code
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
normalized_label =
|
||||
entity_type_duplicate_trimmed(
|
||||
label
|
||||
);
|
||||
|
||||
if (!entity_type_required_value_is_valid(
|
||||
normalized_label
|
||||
))
|
||||
{
|
||||
g_set_error_literal(
|
||||
error,
|
||||
ENTITY_TYPE_ERROR,
|
||||
ENTITY_TYPE_ERROR_INVALID_LABEL,
|
||||
"Le libellé du type d'entité est obligatoire."
|
||||
);
|
||||
|
||||
g_free(
|
||||
normalized_label
|
||||
);
|
||||
|
||||
g_free(
|
||||
normalized_code
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
normalized_description =
|
||||
entity_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;
|
||||
}
|
||||
|
||||
entity_type =
|
||||
g_new0(
|
||||
EntityType,
|
||||
1
|
||||
);
|
||||
|
||||
entity_type->identifier =
|
||||
identifier;
|
||||
|
||||
entity_type->code =
|
||||
normalized_code;
|
||||
|
||||
entity_type->label =
|
||||
normalized_label;
|
||||
|
||||
entity_type->description =
|
||||
normalized_description;
|
||||
|
||||
return entity_type;
|
||||
}
|
||||
|
||||
void entity_type_free(
|
||||
EntityType *entity_type
|
||||
)
|
||||
{
|
||||
if (entity_type == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g_free(
|
||||
entity_type->description
|
||||
);
|
||||
|
||||
g_free(
|
||||
entity_type->label
|
||||
);
|
||||
|
||||
g_free(
|
||||
entity_type->code
|
||||
);
|
||||
|
||||
g_free(
|
||||
entity_type
|
||||
);
|
||||
}
|
||||
|
||||
gint64 entity_type_get_identifier(
|
||||
const EntityType *entity_type
|
||||
)
|
||||
{
|
||||
if (entity_type == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return entity_type->identifier;
|
||||
}
|
||||
|
||||
const char *entity_type_get_code(
|
||||
const EntityType *entity_type
|
||||
)
|
||||
{
|
||||
if (entity_type == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return entity_type->code;
|
||||
}
|
||||
|
||||
const char *entity_type_get_label(
|
||||
const EntityType *entity_type
|
||||
)
|
||||
{
|
||||
if (entity_type == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return entity_type->label;
|
||||
}
|
||||
|
||||
const char *entity_type_get_description(
|
||||
const EntityType *entity_type
|
||||
)
|
||||
{
|
||||
if (entity_type == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return entity_type->description;
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,610 +0,0 @@
|
|||
/******************************************************************************
|
||||
* @file test_entity_record.c
|
||||
* @brief Tests unitaires du modèle EntityRecord.
|
||||
******************************************************************************/
|
||||
|
||||
#include "models/entity_record.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#define TEST_ENTITY_IDENTIFIER \
|
||||
"9b6ea3f8-b60b-48ac-908a-94c211f524dd"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *identifier;
|
||||
const char *type_identifier;
|
||||
const char *value;
|
||||
const char *label;
|
||||
const char *description;
|
||||
|
||||
gint confidence;
|
||||
|
||||
const char *created_at;
|
||||
const char *updated_at;
|
||||
|
||||
EntityStatus status;
|
||||
} TestEntityRecordInput;
|
||||
|
||||
static TestEntityRecordInput test_entity_record_valid_input(void)
|
||||
{
|
||||
return (TestEntityRecordInput)
|
||||
{
|
||||
.identifier = TEST_ENTITY_IDENTIFIER,
|
||||
.type_identifier = "email_address",
|
||||
.value = "suspect@example.org",
|
||||
.label = "Adresse utilisée pour la transaction",
|
||||
.description = "Adresse communiquée dans la conversation.",
|
||||
.confidence = 80,
|
||||
.created_at = "2026-07-20T19:00:00Z",
|
||||
.updated_at = "2026-07-20T19:00:00Z",
|
||||
.status = ENTITY_STATUS_ACTIVE
|
||||
};
|
||||
}
|
||||
|
||||
static EntityRecord *test_entity_record_create(
|
||||
const TestEntityRecordInput *input,
|
||||
GError **error
|
||||
)
|
||||
{
|
||||
g_assert_nonnull(
|
||||
input
|
||||
);
|
||||
|
||||
return entity_record_new(
|
||||
input->identifier,
|
||||
input->type_identifier,
|
||||
input->value,
|
||||
input->label,
|
||||
input->description,
|
||||
input->confidence,
|
||||
input->created_at,
|
||||
input->updated_at,
|
||||
input->status,
|
||||
error
|
||||
);
|
||||
}
|
||||
|
||||
static void test_entity_record_assert_invalid(
|
||||
const TestEntityRecordInput *input,
|
||||
EntityRecordError expected_error
|
||||
)
|
||||
{
|
||||
EntityRecord *entity_record =
|
||||
NULL;
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
entity_record =
|
||||
test_entity_record_create(
|
||||
input,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_record
|
||||
);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
ENTITY_RECORD_ERROR,
|
||||
(gint) expected_error
|
||||
);
|
||||
|
||||
g_clear_error(
|
||||
&error
|
||||
);
|
||||
}
|
||||
|
||||
static void test_entity_record_valid_full(void)
|
||||
{
|
||||
TestEntityRecordInput input =
|
||||
test_entity_record_valid_input();
|
||||
|
||||
EntityRecord *entity_record =
|
||||
NULL;
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
entity_record =
|
||||
test_entity_record_create(
|
||||
&input,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(
|
||||
error
|
||||
);
|
||||
|
||||
g_assert_nonnull(
|
||||
entity_record
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
entity_record_get_identifier(entity_record),
|
||||
==,
|
||||
TEST_ENTITY_IDENTIFIER
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
entity_record_get_type_identifier(entity_record),
|
||||
==,
|
||||
"email_address"
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
entity_record_get_value(entity_record),
|
||||
==,
|
||||
"suspect@example.org"
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
entity_record_get_label(entity_record),
|
||||
==,
|
||||
"Adresse utilisée pour la transaction"
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
entity_record_get_description(entity_record),
|
||||
==,
|
||||
"Adresse communiquée dans la conversation."
|
||||
);
|
||||
|
||||
g_assert_cmpint(
|
||||
entity_record_get_confidence(entity_record),
|
||||
==,
|
||||
80
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
entity_record_get_created_at(entity_record),
|
||||
==,
|
||||
"2026-07-20T19:00:00Z"
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
entity_record_get_updated_at(entity_record),
|
||||
==,
|
||||
"2026-07-20T19:00:00Z"
|
||||
);
|
||||
|
||||
g_assert_cmpint(
|
||||
entity_record_get_status(entity_record),
|
||||
==,
|
||||
ENTITY_STATUS_ACTIVE
|
||||
);
|
||||
|
||||
entity_record_free(
|
||||
entity_record
|
||||
);
|
||||
}
|
||||
|
||||
static void test_entity_record_optional_fields(void)
|
||||
{
|
||||
TestEntityRecordInput input =
|
||||
test_entity_record_valid_input();
|
||||
|
||||
EntityRecord *entity_record =
|
||||
NULL;
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
input.label = " ";
|
||||
input.description = NULL;
|
||||
|
||||
entity_record =
|
||||
test_entity_record_create(
|
||||
&input,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(
|
||||
error
|
||||
);
|
||||
|
||||
g_assert_nonnull(
|
||||
entity_record
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_record_get_label(
|
||||
entity_record
|
||||
)
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_record_get_description(
|
||||
entity_record
|
||||
)
|
||||
);
|
||||
|
||||
entity_record_free(
|
||||
entity_record
|
||||
);
|
||||
}
|
||||
|
||||
static void test_entity_record_values_are_trimmed(void)
|
||||
{
|
||||
TestEntityRecordInput input =
|
||||
test_entity_record_valid_input();
|
||||
|
||||
EntityRecord *entity_record =
|
||||
NULL;
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
input.identifier =
|
||||
" 9b6ea3f8-b60b-48ac-908a-94c211f524dd ";
|
||||
|
||||
input.type_identifier =
|
||||
" iban ";
|
||||
|
||||
input.value =
|
||||
" FR7612345678901234567890123 ";
|
||||
|
||||
input.label =
|
||||
" Compte destinataire ";
|
||||
|
||||
input.description =
|
||||
" IBAN communiqué par le vendeur. ";
|
||||
|
||||
input.created_at =
|
||||
" 2026-07-20T19:00:00Z ";
|
||||
|
||||
input.updated_at =
|
||||
"\t2026-07-20T19:00:00Z\t";
|
||||
|
||||
entity_record =
|
||||
test_entity_record_create(
|
||||
&input,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(
|
||||
error
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
entity_record_get_type_identifier(entity_record),
|
||||
==,
|
||||
"iban"
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
entity_record_get_value(entity_record),
|
||||
==,
|
||||
"FR7612345678901234567890123"
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
entity_record_get_label(entity_record),
|
||||
==,
|
||||
"Compte destinataire"
|
||||
);
|
||||
|
||||
entity_record_free(
|
||||
entity_record
|
||||
);
|
||||
}
|
||||
|
||||
static void test_entity_record_invalid_uuid(void)
|
||||
{
|
||||
TestEntityRecordInput input =
|
||||
test_entity_record_valid_input();
|
||||
|
||||
input.identifier = "uuid-invalide";
|
||||
|
||||
test_entity_record_assert_invalid(
|
||||
&input,
|
||||
ENTITY_RECORD_ERROR_INVALID_IDENTIFIER
|
||||
);
|
||||
}
|
||||
|
||||
static void test_entity_record_missing_type(void)
|
||||
{
|
||||
TestEntityRecordInput input =
|
||||
test_entity_record_valid_input();
|
||||
|
||||
input.type_identifier = " ";
|
||||
|
||||
test_entity_record_assert_invalid(
|
||||
&input,
|
||||
ENTITY_RECORD_ERROR_INVALID_TYPE
|
||||
);
|
||||
}
|
||||
|
||||
static void test_entity_record_empty_value(void)
|
||||
{
|
||||
TestEntityRecordInput input =
|
||||
test_entity_record_valid_input();
|
||||
|
||||
input.value = "\t";
|
||||
|
||||
test_entity_record_assert_invalid(
|
||||
&input,
|
||||
ENTITY_RECORD_ERROR_INVALID_VALUE
|
||||
);
|
||||
}
|
||||
|
||||
static void test_entity_record_confidence_below_range(void)
|
||||
{
|
||||
TestEntityRecordInput input =
|
||||
test_entity_record_valid_input();
|
||||
|
||||
input.confidence = -1;
|
||||
|
||||
test_entity_record_assert_invalid(
|
||||
&input,
|
||||
ENTITY_RECORD_ERROR_INVALID_CONFIDENCE
|
||||
);
|
||||
}
|
||||
|
||||
static void test_entity_record_confidence_above_range(void)
|
||||
{
|
||||
TestEntityRecordInput input =
|
||||
test_entity_record_valid_input();
|
||||
|
||||
input.confidence = 101;
|
||||
|
||||
test_entity_record_assert_invalid(
|
||||
&input,
|
||||
ENTITY_RECORD_ERROR_INVALID_CONFIDENCE
|
||||
);
|
||||
}
|
||||
|
||||
static void test_entity_record_invalid_created_at(void)
|
||||
{
|
||||
TestEntityRecordInput input =
|
||||
test_entity_record_valid_input();
|
||||
|
||||
input.created_at = "2026-02-30T19:00:00Z";
|
||||
|
||||
test_entity_record_assert_invalid(
|
||||
&input,
|
||||
ENTITY_RECORD_ERROR_INVALID_DATE
|
||||
);
|
||||
}
|
||||
|
||||
static void test_entity_record_invalid_updated_at(void)
|
||||
{
|
||||
TestEntityRecordInput input =
|
||||
test_entity_record_valid_input();
|
||||
|
||||
input.updated_at = "2026-07-20 19:00:00Z";
|
||||
|
||||
test_entity_record_assert_invalid(
|
||||
&input,
|
||||
ENTITY_RECORD_ERROR_INVALID_DATE
|
||||
);
|
||||
}
|
||||
|
||||
static void test_entity_record_valid_statuses(void)
|
||||
{
|
||||
EntityStatus statuses[] =
|
||||
{
|
||||
ENTITY_STATUS_ACTIVE,
|
||||
ENTITY_STATUS_ARCHIVED,
|
||||
ENTITY_STATUS_DELETED
|
||||
};
|
||||
|
||||
guint status_index =
|
||||
0;
|
||||
|
||||
for (status_index = 0;
|
||||
status_index < G_N_ELEMENTS(statuses);
|
||||
status_index++)
|
||||
{
|
||||
TestEntityRecordInput input =
|
||||
test_entity_record_valid_input();
|
||||
|
||||
EntityRecord *entity_record =
|
||||
NULL;
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
input.status =
|
||||
statuses[status_index];
|
||||
|
||||
entity_record =
|
||||
test_entity_record_create(
|
||||
&input,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(
|
||||
error
|
||||
);
|
||||
|
||||
g_assert_nonnull(
|
||||
entity_record
|
||||
);
|
||||
|
||||
g_assert_cmpint(
|
||||
entity_record_get_status(entity_record),
|
||||
==,
|
||||
statuses[status_index]
|
||||
);
|
||||
|
||||
entity_record_free(
|
||||
entity_record
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_entity_record_invalid_status(void)
|
||||
{
|
||||
TestEntityRecordInput input =
|
||||
test_entity_record_valid_input();
|
||||
|
||||
input.status = ENTITY_STATUS_UNKNOWN;
|
||||
|
||||
test_entity_record_assert_invalid(
|
||||
&input,
|
||||
ENTITY_RECORD_ERROR_INVALID_STATUS
|
||||
);
|
||||
|
||||
input.status = (EntityStatus) 999;
|
||||
|
||||
test_entity_record_assert_invalid(
|
||||
&input,
|
||||
ENTITY_RECORD_ERROR_INVALID_STATUS
|
||||
);
|
||||
}
|
||||
|
||||
static void test_entity_record_null_accessors(void)
|
||||
{
|
||||
g_assert_null(
|
||||
entity_record_get_identifier(NULL)
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_record_get_type_identifier(NULL)
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_record_get_value(NULL)
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_record_get_label(NULL)
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_record_get_description(NULL)
|
||||
);
|
||||
|
||||
g_assert_cmpint(
|
||||
entity_record_get_confidence(NULL),
|
||||
==,
|
||||
0
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_record_get_created_at(NULL)
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_record_get_updated_at(NULL)
|
||||
);
|
||||
|
||||
g_assert_cmpint(
|
||||
entity_record_get_status(NULL),
|
||||
==,
|
||||
ENTITY_STATUS_UNKNOWN
|
||||
);
|
||||
|
||||
entity_record_free(
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
static void test_entity_record_optional_error(void)
|
||||
{
|
||||
TestEntityRecordInput input =
|
||||
test_entity_record_valid_input();
|
||||
|
||||
EntityRecord *entity_record =
|
||||
NULL;
|
||||
|
||||
input.identifier =
|
||||
"invalide";
|
||||
|
||||
entity_record =
|
||||
test_entity_record_create(
|
||||
&input,
|
||||
NULL
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_record
|
||||
);
|
||||
}
|
||||
|
||||
int main(
|
||||
int argc,
|
||||
char **argv
|
||||
)
|
||||
{
|
||||
g_test_init(
|
||||
&argc,
|
||||
&argv,
|
||||
NULL
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-record/valid-full",
|
||||
test_entity_record_valid_full
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-record/optional-fields",
|
||||
test_entity_record_optional_fields
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-record/values-are-trimmed",
|
||||
test_entity_record_values_are_trimmed
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-record/invalid-uuid",
|
||||
test_entity_record_invalid_uuid
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-record/missing-type",
|
||||
test_entity_record_missing_type
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-record/empty-value",
|
||||
test_entity_record_empty_value
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-record/confidence-below-range",
|
||||
test_entity_record_confidence_below_range
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-record/confidence-above-range",
|
||||
test_entity_record_confidence_above_range
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-record/invalid-created-at",
|
||||
test_entity_record_invalid_created_at
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-record/invalid-updated-at",
|
||||
test_entity_record_invalid_updated_at
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-record/valid-statuses",
|
||||
test_entity_record_valid_statuses
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-record/invalid-status",
|
||||
test_entity_record_invalid_status
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-record/null-accessors",
|
||||
test_entity_record_null_accessors
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-record/optional-error",
|
||||
test_entity_record_optional_error
|
||||
);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
|
@ -1,523 +0,0 @@
|
|||
/******************************************************************************
|
||||
* @file test_entity_type.c
|
||||
* @brief Tests unitaires du modèle EntityType.
|
||||
******************************************************************************/
|
||||
|
||||
#include "models/entity_type.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
/**
|
||||
* @brief Vérifie la création d'un type valide.
|
||||
*/
|
||||
static void test_entity_type_new_valid(void)
|
||||
{
|
||||
EntityType *entity_type =
|
||||
NULL;
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
entity_type =
|
||||
entity_type_new(
|
||||
3,
|
||||
"email",
|
||||
"Adresse e-mail",
|
||||
"Adresse électronique associée à l'enquête.",
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(
|
||||
error
|
||||
);
|
||||
|
||||
g_assert_nonnull(
|
||||
entity_type
|
||||
);
|
||||
|
||||
g_assert_cmpint(
|
||||
entity_type_get_identifier(
|
||||
entity_type
|
||||
),
|
||||
==,
|
||||
3
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
entity_type_get_code(
|
||||
entity_type
|
||||
),
|
||||
==,
|
||||
"email"
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
entity_type_get_label(
|
||||
entity_type
|
||||
),
|
||||
==,
|
||||
"Adresse e-mail"
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
entity_type_get_description(
|
||||
entity_type
|
||||
),
|
||||
==,
|
||||
"Adresse électronique associée à l'enquête."
|
||||
);
|
||||
|
||||
entity_type_free(
|
||||
entity_type
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie la suppression des espaces périphériques.
|
||||
*/
|
||||
static void test_entity_type_values_are_trimmed(void)
|
||||
{
|
||||
EntityType *entity_type =
|
||||
NULL;
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
entity_type =
|
||||
entity_type_new(
|
||||
4,
|
||||
" iban ",
|
||||
" IBAN ",
|
||||
" Identifiant international d'un compte bancaire. ",
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(
|
||||
error
|
||||
);
|
||||
|
||||
g_assert_nonnull(
|
||||
entity_type
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
entity_type_get_code(
|
||||
entity_type
|
||||
),
|
||||
==,
|
||||
"iban"
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
entity_type_get_label(
|
||||
entity_type
|
||||
),
|
||||
==,
|
||||
"IBAN"
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
entity_type_get_description(
|
||||
entity_type
|
||||
),
|
||||
==,
|
||||
"Identifiant international d'un compte bancaire."
|
||||
);
|
||||
|
||||
entity_type_free(
|
||||
entity_type
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie qu'une description absente reste facultative.
|
||||
*/
|
||||
static void test_entity_type_description_is_optional(void)
|
||||
{
|
||||
EntityType *entity_type =
|
||||
NULL;
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
entity_type =
|
||||
entity_type_new(
|
||||
14,
|
||||
"other",
|
||||
"Autre",
|
||||
NULL,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(
|
||||
error
|
||||
);
|
||||
|
||||
g_assert_nonnull(
|
||||
entity_type
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_type_get_description(
|
||||
entity_type
|
||||
)
|
||||
);
|
||||
|
||||
entity_type_free(
|
||||
entity_type
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie qu'une description vide est normalisée vers NULL.
|
||||
*/
|
||||
static void test_entity_type_empty_description_becomes_null(void)
|
||||
{
|
||||
EntityType *entity_type =
|
||||
NULL;
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
entity_type =
|
||||
entity_type_new(
|
||||
7,
|
||||
"person",
|
||||
"Personne",
|
||||
" ",
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(
|
||||
error
|
||||
);
|
||||
|
||||
g_assert_nonnull(
|
||||
entity_type
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_type_get_description(
|
||||
entity_type
|
||||
)
|
||||
);
|
||||
|
||||
entity_type_free(
|
||||
entity_type
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le refus d'un identifiant nul.
|
||||
*/
|
||||
static void test_entity_type_zero_identifier(void)
|
||||
{
|
||||
EntityType *entity_type =
|
||||
NULL;
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
entity_type =
|
||||
entity_type_new(
|
||||
0,
|
||||
"email",
|
||||
"Adresse e-mail",
|
||||
NULL,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_type
|
||||
);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
ENTITY_TYPE_ERROR,
|
||||
ENTITY_TYPE_ERROR_INVALID_IDENTIFIER
|
||||
);
|
||||
|
||||
g_clear_error(
|
||||
&error
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le refus d'un identifiant négatif.
|
||||
*/
|
||||
static void test_entity_type_negative_identifier(void)
|
||||
{
|
||||
EntityType *entity_type =
|
||||
NULL;
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
entity_type =
|
||||
entity_type_new(
|
||||
-1,
|
||||
"email",
|
||||
"Adresse e-mail",
|
||||
NULL,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_type
|
||||
);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
ENTITY_TYPE_ERROR,
|
||||
ENTITY_TYPE_ERROR_INVALID_IDENTIFIER
|
||||
);
|
||||
|
||||
g_clear_error(
|
||||
&error
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le refus d'un code absent.
|
||||
*/
|
||||
static void test_entity_type_missing_code(void)
|
||||
{
|
||||
EntityType *entity_type =
|
||||
NULL;
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
entity_type =
|
||||
entity_type_new(
|
||||
3,
|
||||
NULL,
|
||||
"Adresse e-mail",
|
||||
NULL,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_type
|
||||
);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
ENTITY_TYPE_ERROR,
|
||||
ENTITY_TYPE_ERROR_INVALID_CODE
|
||||
);
|
||||
|
||||
g_clear_error(
|
||||
&error
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le refus d'un code vide.
|
||||
*/
|
||||
static void test_entity_type_empty_code(void)
|
||||
{
|
||||
EntityType *entity_type =
|
||||
NULL;
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
entity_type =
|
||||
entity_type_new(
|
||||
3,
|
||||
" ",
|
||||
"Adresse e-mail",
|
||||
NULL,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_type
|
||||
);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
ENTITY_TYPE_ERROR,
|
||||
ENTITY_TYPE_ERROR_INVALID_CODE
|
||||
);
|
||||
|
||||
g_clear_error(
|
||||
&error
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le refus d'un libellé absent.
|
||||
*/
|
||||
static void test_entity_type_missing_label(void)
|
||||
{
|
||||
EntityType *entity_type =
|
||||
NULL;
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
entity_type =
|
||||
entity_type_new(
|
||||
3,
|
||||
"email",
|
||||
NULL,
|
||||
NULL,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_type
|
||||
);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
ENTITY_TYPE_ERROR,
|
||||
ENTITY_TYPE_ERROR_INVALID_LABEL
|
||||
);
|
||||
|
||||
g_clear_error(
|
||||
&error
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le refus d'un libellé vide.
|
||||
*/
|
||||
static void test_entity_type_empty_label(void)
|
||||
{
|
||||
EntityType *entity_type =
|
||||
NULL;
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
entity_type =
|
||||
entity_type_new(
|
||||
3,
|
||||
"email",
|
||||
" ",
|
||||
NULL,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_type
|
||||
);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
ENTITY_TYPE_ERROR,
|
||||
ENTITY_TYPE_ERROR_INVALID_LABEL
|
||||
);
|
||||
|
||||
g_clear_error(
|
||||
&error
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le comportement des getters avec NULL.
|
||||
*/
|
||||
static void test_entity_type_null_getters(void)
|
||||
{
|
||||
g_assert_cmpint(
|
||||
entity_type_get_identifier(
|
||||
NULL
|
||||
),
|
||||
==,
|
||||
0
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_type_get_code(
|
||||
NULL
|
||||
)
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_type_get_label(
|
||||
NULL
|
||||
)
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_type_get_description(
|
||||
NULL
|
||||
)
|
||||
);
|
||||
|
||||
entity_type_free(
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
int main(
|
||||
int argc,
|
||||
char **argv
|
||||
)
|
||||
{
|
||||
g_test_init(
|
||||
&argc,
|
||||
&argv,
|
||||
NULL
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-type/new-valid",
|
||||
test_entity_type_new_valid
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-type/values-are-trimmed",
|
||||
test_entity_type_values_are_trimmed
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-type/description-is-optional",
|
||||
test_entity_type_description_is_optional
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-type/empty-description-becomes-null",
|
||||
test_entity_type_empty_description_becomes_null
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-type/zero-identifier",
|
||||
test_entity_type_zero_identifier
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-type/negative-identifier",
|
||||
test_entity_type_negative_identifier
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-type/missing-code",
|
||||
test_entity_type_missing_code
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-type/empty-code",
|
||||
test_entity_type_empty_code
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-type/missing-label",
|
||||
test_entity_type_missing_label
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-type/empty-label",
|
||||
test_entity_type_empty_label
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-type/null-getters",
|
||||
test_entity_type_null_getters
|
||||
);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
|
@ -1,578 +0,0 @@
|
|||
/******************************************************************************
|
||||
* @file test_entity_type_dao.c
|
||||
* @brief Tests du DAO des types d'entité.
|
||||
******************************************************************************/
|
||||
|
||||
#include "dao/entity_type_dao.h"
|
||||
|
||||
#include "database/database.h"
|
||||
#include "database/statement.h"
|
||||
#include "models/entity_type.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
/**
|
||||
* @brief Ressources utilisées par un test EntityTypeDao.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char *temporary_directory;
|
||||
char *database_path;
|
||||
|
||||
Database *database;
|
||||
EntityTypeDao *entity_type_dao;
|
||||
} TestEntityTypeDaoFixture;
|
||||
|
||||
/**
|
||||
* @brief Exécute une requête SQL ne retournant aucune ligne.
|
||||
*/
|
||||
static void test_entity_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 TestEntityTypeDaoFixture
|
||||
test_entity_type_dao_fixture_create(void)
|
||||
{
|
||||
TestEntityTypeDaoFixture fixture =
|
||||
{0};
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
fixture.temporary_directory =
|
||||
g_dir_make_tmp(
|
||||
"labfy-entity-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_EntityTypeDao",
|
||||
fixture.temporary_directory
|
||||
)
|
||||
);
|
||||
|
||||
fixture.database =
|
||||
database_open(
|
||||
fixture.database_path
|
||||
);
|
||||
|
||||
g_assert_nonnull(
|
||||
fixture.database
|
||||
);
|
||||
|
||||
fixture.entity_type_dao =
|
||||
entity_type_dao_new(
|
||||
fixture.database,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(
|
||||
error
|
||||
);
|
||||
|
||||
g_assert_nonnull(
|
||||
fixture.entity_type_dao
|
||||
);
|
||||
|
||||
return fixture;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Libère la fixture et supprime la base temporaire.
|
||||
*/
|
||||
static void test_entity_type_dao_fixture_clear(
|
||||
TestEntityTypeDaoFixture *fixture
|
||||
)
|
||||
{
|
||||
g_assert_nonnull(
|
||||
fixture
|
||||
);
|
||||
|
||||
entity_type_dao_free(
|
||||
fixture->entity_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->entity_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_entity_type_dao_new_invalid_database(void)
|
||||
{
|
||||
EntityTypeDao *entity_type_dao =
|
||||
NULL;
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
entity_type_dao =
|
||||
entity_type_dao_new(
|
||||
NULL,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_type_dao
|
||||
);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
ENTITY_TYPE_DAO_ERROR,
|
||||
ENTITY_TYPE_DAO_ERROR_INVALID_ARGUMENT
|
||||
);
|
||||
|
||||
g_clear_error(
|
||||
&error
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le chargement du catalogue initial.
|
||||
*/
|
||||
static void test_entity_type_dao_list_all(void)
|
||||
{
|
||||
static const char *const expected_codes[] =
|
||||
{
|
||||
"email_address",
|
||||
"bank_account",
|
||||
"facebook_account",
|
||||
"instagram_account",
|
||||
"identity_document",
|
||||
"iban",
|
||||
"person",
|
||||
"pseudonym",
|
||||
"phone_number",
|
||||
"website",
|
||||
"domain_name",
|
||||
"ip_address",
|
||||
"organization",
|
||||
"other"
|
||||
};
|
||||
|
||||
static const char *const expected_labels[] =
|
||||
{
|
||||
"Adresse email",
|
||||
"Compte bancaire",
|
||||
"Compte Facebook",
|
||||
"Compte Instagram",
|
||||
"Document d'identité",
|
||||
"IBAN",
|
||||
"Personne",
|
||||
"Pseudonyme",
|
||||
"Numéro de téléphone",
|
||||
"Site web",
|
||||
"Nom de domaine",
|
||||
"Adresse IP",
|
||||
"Organisation",
|
||||
"Autre"
|
||||
};
|
||||
|
||||
TestEntityTypeDaoFixture fixture =
|
||||
test_entity_type_dao_fixture_create();
|
||||
|
||||
GPtrArray *entity_types =
|
||||
NULL;
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
guint index =
|
||||
0;
|
||||
|
||||
entity_types =
|
||||
entity_type_dao_list_all(
|
||||
fixture.entity_type_dao,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(
|
||||
error
|
||||
);
|
||||
|
||||
g_assert_nonnull(
|
||||
entity_types
|
||||
);
|
||||
|
||||
g_assert_cmpuint(
|
||||
entity_types->len,
|
||||
==,
|
||||
G_N_ELEMENTS(
|
||||
expected_codes
|
||||
)
|
||||
);
|
||||
|
||||
for (index = 0;
|
||||
index < entity_types->len;
|
||||
index++)
|
||||
{
|
||||
const EntityType *entity_type =
|
||||
NULL;
|
||||
|
||||
entity_type =
|
||||
g_ptr_array_index(
|
||||
entity_types,
|
||||
index
|
||||
);
|
||||
|
||||
g_assert_nonnull(
|
||||
entity_type
|
||||
);
|
||||
|
||||
/*
|
||||
* La requête utilise ORDER BY id ASC.
|
||||
*/
|
||||
g_assert_cmpint(
|
||||
entity_type_get_identifier(
|
||||
entity_type
|
||||
),
|
||||
==,
|
||||
(gint64) index + 1
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
entity_type_get_code(
|
||||
entity_type
|
||||
),
|
||||
==,
|
||||
expected_codes[index]
|
||||
);
|
||||
|
||||
g_assert_cmpstr(
|
||||
entity_type_get_label(
|
||||
entity_type
|
||||
),
|
||||
==,
|
||||
expected_labels[index]
|
||||
);
|
||||
|
||||
/*
|
||||
* Le catalogue V1 ne renseigne aucune description.
|
||||
*/
|
||||
g_assert_null(
|
||||
entity_type_get_description(
|
||||
entity_type
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
g_ptr_array_unref(
|
||||
entity_types
|
||||
);
|
||||
|
||||
test_entity_type_dao_fixture_clear(
|
||||
&fixture
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie qu'une table vide retourne un tableau vide.
|
||||
*/
|
||||
static void test_entity_type_dao_list_empty(void)
|
||||
{
|
||||
TestEntityTypeDaoFixture fixture =
|
||||
test_entity_type_dao_fixture_create();
|
||||
|
||||
GPtrArray *entity_types =
|
||||
NULL;
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
test_entity_type_dao_execute_sql(
|
||||
fixture.database,
|
||||
"DELETE FROM types_entite;"
|
||||
);
|
||||
|
||||
entity_types =
|
||||
entity_type_dao_list_all(
|
||||
fixture.entity_type_dao,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(
|
||||
error
|
||||
);
|
||||
|
||||
g_assert_nonnull(
|
||||
entity_types
|
||||
);
|
||||
|
||||
g_assert_cmpuint(
|
||||
entity_types->len,
|
||||
==,
|
||||
0
|
||||
);
|
||||
|
||||
g_ptr_array_unref(
|
||||
entity_types
|
||||
);
|
||||
|
||||
test_entity_type_dao_fixture_clear(
|
||||
&fixture
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le signalement d'une table absente.
|
||||
*/
|
||||
static void test_entity_type_dao_missing_table(void)
|
||||
{
|
||||
Database *database =
|
||||
NULL;
|
||||
|
||||
EntityTypeDao *entity_type_dao =
|
||||
NULL;
|
||||
|
||||
GPtrArray *entity_types =
|
||||
NULL;
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
database =
|
||||
database_open(
|
||||
":memory:"
|
||||
);
|
||||
|
||||
g_assert_nonnull(
|
||||
database
|
||||
);
|
||||
|
||||
entity_type_dao =
|
||||
entity_type_dao_new(
|
||||
database,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_no_error(
|
||||
error
|
||||
);
|
||||
|
||||
g_assert_nonnull(
|
||||
entity_type_dao
|
||||
);
|
||||
|
||||
g_test_expect_message(
|
||||
NULL,
|
||||
G_LOG_LEVEL_WARNING,
|
||||
"*Impossible de préparer la requête SQL*"
|
||||
);
|
||||
|
||||
entity_types =
|
||||
entity_type_dao_list_all(
|
||||
entity_type_dao,
|
||||
&error
|
||||
);
|
||||
|
||||
g_test_assert_expected_messages();
|
||||
|
||||
g_assert_null(
|
||||
entity_types
|
||||
);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
ENTITY_TYPE_DAO_ERROR,
|
||||
ENTITY_TYPE_DAO_ERROR_SCHEMA
|
||||
);
|
||||
|
||||
g_clear_error(
|
||||
&error
|
||||
);
|
||||
|
||||
entity_type_dao_free(
|
||||
entity_type_dao
|
||||
);
|
||||
|
||||
database_close(
|
||||
database
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Vérifie le refus d'une ligne produisant un modèle invalide.
|
||||
*/
|
||||
static void test_entity_type_dao_invalid_model(void)
|
||||
{
|
||||
TestEntityTypeDaoFixture fixture =
|
||||
test_entity_type_dao_fixture_create();
|
||||
|
||||
GPtrArray *entity_types =
|
||||
NULL;
|
||||
|
||||
GError *error =
|
||||
NULL;
|
||||
|
||||
/*
|
||||
* Le schéma interdit NULL mais autorise actuellement
|
||||
* une chaîne uniquement composée d'espaces.
|
||||
*/
|
||||
test_entity_type_dao_execute_sql(
|
||||
fixture.database,
|
||||
"UPDATE types_entite "
|
||||
"SET code = ' ' "
|
||||
"WHERE id = 1;"
|
||||
);
|
||||
|
||||
entity_types =
|
||||
entity_type_dao_list_all(
|
||||
fixture.entity_type_dao,
|
||||
&error
|
||||
);
|
||||
|
||||
g_assert_null(
|
||||
entity_types
|
||||
);
|
||||
|
||||
g_assert_error(
|
||||
error,
|
||||
ENTITY_TYPE_DAO_ERROR,
|
||||
ENTITY_TYPE_DAO_ERROR_MODEL
|
||||
);
|
||||
|
||||
g_clear_error(
|
||||
&error
|
||||
);
|
||||
|
||||
test_entity_type_dao_fixture_clear(
|
||||
&fixture
|
||||
);
|
||||
}
|
||||
|
||||
int main(
|
||||
int argc,
|
||||
char **argv
|
||||
)
|
||||
{
|
||||
g_test_init(
|
||||
&argc,
|
||||
&argv,
|
||||
NULL
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-type-dao/new-invalid-database",
|
||||
test_entity_type_dao_new_invalid_database
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-type-dao/list-all",
|
||||
test_entity_type_dao_list_all
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-type-dao/list-empty",
|
||||
test_entity_type_dao_list_empty
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-type-dao/missing-table",
|
||||
test_entity_type_dao_missing_table
|
||||
);
|
||||
|
||||
g_test_add_func(
|
||||
"/entity-type-dao/invalid-model",
|
||||
test_entity_type_dao_invalid_model
|
||||
);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue