feat(core): create investigation tree model
This commit is contained in:
parent
40fdcd837b
commit
3a2fbd260d
6 changed files with 419 additions and 0 deletions
|
|
@ -639,6 +639,41 @@ Lorsque plusieurs solutions existent, la préférence est donnée à celle qui f
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Gestion de la mémoire
|
||||||
|
|
||||||
|
Le projet applique une règle unique concernant la propriété des ressources.
|
||||||
|
|
||||||
|
> Le propriétaire crée.
|
||||||
|
> Le propriétaire détruit.
|
||||||
|
|
||||||
|
Lorsqu'une ressource est transmise à un objet qui en devient propriétaire, le code appelant ne doit plus la libérer.
|
||||||
|
|
||||||
|
Chaque module est responsable uniquement des ressources qu'il possède.
|
||||||
|
|
||||||
|
Cette règle s'applique à toutes les structures du projet.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bibliothèques autorisées
|
||||||
|
|
||||||
|
Le projet privilégie les bibliothèques éprouvées plutôt que des réimplémentations.
|
||||||
|
|
||||||
|
### Couche Core
|
||||||
|
|
||||||
|
Autorisé :
|
||||||
|
|
||||||
|
- Langage C17
|
||||||
|
- GLib
|
||||||
|
- SQLite
|
||||||
|
|
||||||
|
Interdit :
|
||||||
|
|
||||||
|
- GTK
|
||||||
|
|
||||||
|
Les structures de données fournies par GLib (GPtrArray, GHashTable, GList, etc.) doivent être privilégiées lorsqu'elles répondent au besoin du projet.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
# Branche principale
|
# Branche principale
|
||||||
|
|
||||||
La branche `main` est toujours stable.
|
La branche `main` est toujours stable.
|
||||||
|
|
|
||||||
158
docs/tickets/closed/TICKET-008.md
Normal file
158
docs/tickets/closed/TICKET-008.md
Normal file
|
|
@ -0,0 +1,158 @@
|
||||||
|
# Ticket #008
|
||||||
|
|
||||||
|
## Titre
|
||||||
|
|
||||||
|
Créer le module `InvestigationTreeModel`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Objectif
|
||||||
|
|
||||||
|
Créer une structure métier représentant le modèle de l'arborescence d'une enquête.
|
||||||
|
|
||||||
|
Le modèle sera propriétaire du nœud racine et servira de base au futur explorateur d'enquête.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Responsabilités
|
||||||
|
|
||||||
|
Le module `InvestigationTreeModel` doit :
|
||||||
|
|
||||||
|
- posséder un nœud racine ;
|
||||||
|
- gérer le cycle de vie du modèle ;
|
||||||
|
- exposer le nœud racine en lecture seule.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hors périmètre
|
||||||
|
|
||||||
|
Ce ticket ne doit pas :
|
||||||
|
|
||||||
|
- parcourir le système de fichiers ;
|
||||||
|
- créer les enfants d'un nœud ;
|
||||||
|
- afficher une interface GTK ;
|
||||||
|
- communiquer avec SQLite ;
|
||||||
|
- charger une enquête.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```text
|
||||||
|
Investigation
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
InvestigationTreeModel
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
InvestigationNode
|
||||||
|
```
|
||||||
|
|
||||||
|
Le module appartient à la couche **Core**.
|
||||||
|
|
||||||
|
Aucune dépendance vers GTK.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Principe de propriété
|
||||||
|
|
||||||
|
Le module est **propriétaire** du nœud racine.
|
||||||
|
|
||||||
|
À partir du moment où un `InvestigationNode` est transmis au constructeur :
|
||||||
|
|
||||||
|
```c
|
||||||
|
investigation_tree_model_new(root_node);
|
||||||
|
```
|
||||||
|
|
||||||
|
le modèle devient responsable de sa destruction.
|
||||||
|
|
||||||
|
Le code appelant ne doit plus appeler :
|
||||||
|
|
||||||
|
```c
|
||||||
|
investigation_node_free(root_node);
|
||||||
|
```
|
||||||
|
|
||||||
|
La destruction du modèle doit automatiquement détruire son nœud racine.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Fichiers concernés
|
||||||
|
|
||||||
|
```text
|
||||||
|
include/core/investigation_tree_model.h
|
||||||
|
src/core/investigation_tree_model.c
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Interface publique attendue
|
||||||
|
|
||||||
|
```c
|
||||||
|
InvestigationTreeModel *investigation_tree_model_new(
|
||||||
|
InvestigationNode *root_node
|
||||||
|
);
|
||||||
|
|
||||||
|
void investigation_tree_model_free(
|
||||||
|
InvestigationTreeModel *tree_model
|
||||||
|
);
|
||||||
|
|
||||||
|
const InvestigationNode *investigation_tree_model_get_root(
|
||||||
|
const InvestigationTreeModel *tree_model
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Comportement attendu
|
||||||
|
|
||||||
|
Le modèle contient uniquement un nœud racine.
|
||||||
|
|
||||||
|
Exemple :
|
||||||
|
|
||||||
|
```text
|
||||||
|
Template
|
||||||
|
```
|
||||||
|
|
||||||
|
Les enfants seront ajoutés dans un ticket ultérieur.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contraintes techniques
|
||||||
|
|
||||||
|
- C17
|
||||||
|
- Structure opaque
|
||||||
|
- Aucun état global
|
||||||
|
- Aucune dépendance GTK
|
||||||
|
- Documentation Doxygen
|
||||||
|
- Compilation sans warning
|
||||||
|
- Respect des conventions du projet
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Critères d'acceptation
|
||||||
|
|
||||||
|
- [ ] Le projet compile sans warning.
|
||||||
|
- [ ] Le modèle est opaque.
|
||||||
|
- [ ] Le modèle possède un nœud racine.
|
||||||
|
- [ ] Le getter retourne le nœud racine.
|
||||||
|
- [ ] La destruction du modèle détruit également le nœud racine.
|
||||||
|
- [ ] Aucun code GTK.
|
||||||
|
- [ ] Aucun code SQLite.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
- création d'un modèle valide ;
|
||||||
|
- lecture du nœud racine ;
|
||||||
|
- destruction du modèle ;
|
||||||
|
- création avec un nœud NULL ;
|
||||||
|
- destruction avec NULL.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Commit attendu
|
||||||
|
|
||||||
|
```text
|
||||||
|
feat(core): create investigation tree model
|
||||||
|
```
|
||||||
60
labfy-investigation/include/core/investigation_tree_model.h
Normal file
60
labfy-investigation/include/core/investigation_tree_model.h
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file investigation_tree_model.h
|
||||||
|
* @brief Interface publique du modèle d'arborescence d'une enquête.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef LABFY_INVESTIGATION_INVESTIGATION_TREE_MODEL_H
|
||||||
|
#define LABFY_INVESTIGATION_INVESTIGATION_TREE_MODEL_H
|
||||||
|
|
||||||
|
#include "core/investigation_node.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Représentation opaque du modèle d'arborescence.
|
||||||
|
*
|
||||||
|
* La structure réelle est définie dans investigation_tree_model.c.
|
||||||
|
* Les autres modules manipulent uniquement un pointeur vers
|
||||||
|
* InvestigationTreeModel.
|
||||||
|
*/
|
||||||
|
typedef struct InvestigationTreeModel InvestigationTreeModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Crée un nouveau modèle d'arborescence.
|
||||||
|
*
|
||||||
|
* Le modèle devient propriétaire de root_node après cet appel.
|
||||||
|
* Le code appelant ne doit donc plus libérer root_node directement.
|
||||||
|
*
|
||||||
|
* @param root_node Nœud racine transféré au modèle.
|
||||||
|
*
|
||||||
|
* @return Un nouveau modèle, ou NULL si root_node vaut NULL
|
||||||
|
* ou si la création échoue.
|
||||||
|
*/
|
||||||
|
InvestigationTreeModel *investigation_tree_model_new(
|
||||||
|
InvestigationNode *root_node
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Libère le modèle et le nœud racine qu'il possède.
|
||||||
|
*
|
||||||
|
* Cette fonction accepte NULL.
|
||||||
|
*
|
||||||
|
* @param tree_model Modèle à libérer.
|
||||||
|
*/
|
||||||
|
void investigation_tree_model_free(
|
||||||
|
InvestigationTreeModel *tree_model
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le nœud racine du modèle.
|
||||||
|
*
|
||||||
|
* Le pointeur retourné appartient toujours au modèle.
|
||||||
|
* Il ne doit être ni modifié ni libéré par le code appelant.
|
||||||
|
*
|
||||||
|
* @param tree_model Modèle à consulter.
|
||||||
|
*
|
||||||
|
* @return Nœud racine en lecture seule, ou NULL si tree_model vaut NULL.
|
||||||
|
*/
|
||||||
|
const InvestigationNode *investigation_tree_model_get_root(
|
||||||
|
const InvestigationTreeModel *tree_model
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif
|
||||||
76
labfy-investigation/src/core/investigation_tree_model.c
Normal file
76
labfy-investigation/src/core/investigation_tree_model.c
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file investigation_tree_model.c
|
||||||
|
* @brief Implémentation du modèle d'arborescence d'une enquête.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "core/investigation_tree_model.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct InvestigationTreeModel
|
||||||
|
* @brief Représentation interne du modèle.
|
||||||
|
*/
|
||||||
|
struct InvestigationTreeModel
|
||||||
|
{
|
||||||
|
InvestigationNode *root_node;
|
||||||
|
};
|
||||||
|
|
||||||
|
InvestigationTreeModel *investigation_tree_model_new(
|
||||||
|
InvestigationNode *root_node
|
||||||
|
)
|
||||||
|
{
|
||||||
|
InvestigationTreeModel *tree_model = NULL;
|
||||||
|
|
||||||
|
if (root_node == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tree_model = g_new0(
|
||||||
|
InvestigationTreeModel,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
if (tree_model == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ownership transferred.
|
||||||
|
*
|
||||||
|
* Le modèle devient propriétaire du nœud racine.
|
||||||
|
*/
|
||||||
|
tree_model->root_node = root_node;
|
||||||
|
|
||||||
|
return tree_model;
|
||||||
|
}
|
||||||
|
|
||||||
|
void investigation_tree_model_free(
|
||||||
|
InvestigationTreeModel *tree_model
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (tree_model == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
investigation_node_free(
|
||||||
|
tree_model->root_node
|
||||||
|
);
|
||||||
|
|
||||||
|
g_free(tree_model);
|
||||||
|
}
|
||||||
|
|
||||||
|
const InvestigationNode *investigation_tree_model_get_root(
|
||||||
|
const InvestigationTreeModel *tree_model
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (tree_model == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tree_model->root_node;
|
||||||
|
}
|
||||||
BIN
labfy-investigation/tests/test_investigation_tree_model
Executable file
BIN
labfy-investigation/tests/test_investigation_tree_model
Executable file
Binary file not shown.
90
labfy-investigation/tests/test_investigation_tree_model.c
Normal file
90
labfy-investigation/tests/test_investigation_tree_model.c
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file test_investigation_tree_model.c
|
||||||
|
* @brief Tests du module InvestigationTreeModel.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "core/investigation_node.h"
|
||||||
|
#include "core/investigation_tree_model.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vérifie la création d'un modèle valide.
|
||||||
|
*/
|
||||||
|
static void test_tree_model_creation(void)
|
||||||
|
{
|
||||||
|
InvestigationNode *root_node = NULL;
|
||||||
|
InvestigationTreeModel *tree_model = NULL;
|
||||||
|
const InvestigationNode *returned_node = NULL;
|
||||||
|
|
||||||
|
root_node = investigation_node_new(
|
||||||
|
"Template",
|
||||||
|
INVESTIGATION_NODE_DIRECTORY
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(root_node != NULL);
|
||||||
|
|
||||||
|
tree_model = investigation_tree_model_new(root_node);
|
||||||
|
|
||||||
|
assert(tree_model != NULL);
|
||||||
|
|
||||||
|
returned_node = investigation_tree_model_get_root(tree_model);
|
||||||
|
|
||||||
|
assert(returned_node != NULL);
|
||||||
|
|
||||||
|
assert(
|
||||||
|
strcmp(
|
||||||
|
investigation_node_get_name(returned_node),
|
||||||
|
"Template"
|
||||||
|
) == 0
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(
|
||||||
|
investigation_node_get_type(returned_node) ==
|
||||||
|
INVESTIGATION_NODE_DIRECTORY
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tree_model est propriétaire de root_node.
|
||||||
|
*/
|
||||||
|
investigation_tree_model_free(tree_model);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vérifie les paramètres invalides.
|
||||||
|
*/
|
||||||
|
static void test_invalid_parameters(void)
|
||||||
|
{
|
||||||
|
assert(
|
||||||
|
investigation_tree_model_new(NULL) == NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(
|
||||||
|
investigation_tree_model_get_root(NULL) == NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vérifie que free(NULL) est accepté.
|
||||||
|
*/
|
||||||
|
static void test_null_free(void)
|
||||||
|
{
|
||||||
|
investigation_tree_model_free(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
test_tree_model_creation();
|
||||||
|
|
||||||
|
test_invalid_parameters();
|
||||||
|
|
||||||
|
test_null_free();
|
||||||
|
|
||||||
|
printf(
|
||||||
|
"InvestigationTreeModel : tous les tests sont valides.\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue