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
|
||||
|
||||
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