feat(core): create investigation node
This commit is contained in:
parent
b1f931d8f2
commit
1686194c1a
6 changed files with 443 additions and 0 deletions
184
docs/tickets/closed/TICKET-007.md
Normal file
184
docs/tickets/closed/TICKET-007.md
Normal file
|
|
@ -0,0 +1,184 @@
|
||||||
|
# Ticket #007
|
||||||
|
|
||||||
|
## Titre
|
||||||
|
|
||||||
|
Créer le module `InvestigationNode`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Objectif
|
||||||
|
|
||||||
|
Créer une structure métier représentant un élément de l'arborescence d'une enquête.
|
||||||
|
|
||||||
|
Un nœud peut représenter :
|
||||||
|
|
||||||
|
- un dossier ;
|
||||||
|
- un fichier.
|
||||||
|
|
||||||
|
Ce module servira de base au futur modèle d'arborescence.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Responsabilités
|
||||||
|
|
||||||
|
Le module `InvestigationNode` doit :
|
||||||
|
|
||||||
|
- mémoriser le nom d'un élément ;
|
||||||
|
- mémoriser son type ;
|
||||||
|
- gérer sa propre mémoire ;
|
||||||
|
- exposer ses informations en lecture seule.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hors périmètre
|
||||||
|
|
||||||
|
Ce ticket ne doit pas :
|
||||||
|
|
||||||
|
- parcourir le système de fichiers ;
|
||||||
|
- construire une arborescence complète ;
|
||||||
|
- stocker des enfants ;
|
||||||
|
- afficher quoi que ce soit avec GTK ;
|
||||||
|
- communiquer avec SQLite ;
|
||||||
|
- ouvrir une enquête.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```text
|
||||||
|
InvestigationTreeModel
|
||||||
|
│
|
||||||
|
└── InvestigationNode
|
||||||
|
```
|
||||||
|
|
||||||
|
Le module appartient à la couche `core`.
|
||||||
|
|
||||||
|
Il ne doit contenir aucune dépendance vers GTK.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Fichiers concernés
|
||||||
|
|
||||||
|
```text
|
||||||
|
include/core/investigation_node.h
|
||||||
|
src/core/investigation_node.c
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Type attendu
|
||||||
|
|
||||||
|
```c
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
INVESTIGATION_NODE_DIRECTORY,
|
||||||
|
INVESTIGATION_NODE_FILE
|
||||||
|
} InvestigationNodeType;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Interface publique attendue
|
||||||
|
|
||||||
|
```c
|
||||||
|
InvestigationNode *investigation_node_new(
|
||||||
|
const char *name,
|
||||||
|
InvestigationNodeType type
|
||||||
|
);
|
||||||
|
|
||||||
|
void investigation_node_free(
|
||||||
|
InvestigationNode *node
|
||||||
|
);
|
||||||
|
|
||||||
|
const char *investigation_node_get_name(
|
||||||
|
const InvestigationNode *node
|
||||||
|
);
|
||||||
|
|
||||||
|
InvestigationNodeType investigation_node_get_type(
|
||||||
|
const InvestigationNode *node
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Comportement attendu
|
||||||
|
|
||||||
|
Exemple d'utilisation :
|
||||||
|
|
||||||
|
```c
|
||||||
|
InvestigationNode *node = NULL;
|
||||||
|
|
||||||
|
node = investigation_node_new(
|
||||||
|
"01_Preuves_Originales",
|
||||||
|
INVESTIGATION_NODE_DIRECTORY
|
||||||
|
);
|
||||||
|
|
||||||
|
if (node == NULL)
|
||||||
|
{
|
||||||
|
/* Gestion de l'erreur */
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *name = investigation_node_get_name(node);
|
||||||
|
InvestigationNodeType type = investigation_node_get_type(node);
|
||||||
|
|
||||||
|
investigation_node_free(node);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Cas à gérer
|
||||||
|
|
||||||
|
- nom valide ;
|
||||||
|
- nom vide ;
|
||||||
|
- pointeur `NULL` ;
|
||||||
|
- type dossier ;
|
||||||
|
- type fichier ;
|
||||||
|
- libération avec `NULL`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contraintes techniques
|
||||||
|
|
||||||
|
- C17 ;
|
||||||
|
- structure opaque ;
|
||||||
|
- aucun état global ;
|
||||||
|
- aucune dépendance GTK ;
|
||||||
|
- documentation Doxygen ;
|
||||||
|
- compilation sans warning ;
|
||||||
|
- noms conformes à `DEVELOPMENT.md`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Critères d'acceptation
|
||||||
|
|
||||||
|
- [ ] Le projet compile sans warning.
|
||||||
|
- [ ] La structure `InvestigationNode` est opaque.
|
||||||
|
- [ ] Un nœud peut représenter un fichier.
|
||||||
|
- [ ] Un nœud peut représenter un dossier.
|
||||||
|
- [ ] Le nom est copié et possédé par le nœud.
|
||||||
|
- [ ] Les getters retournent des données en lecture seule.
|
||||||
|
- [ ] `investigation_node_free(NULL)` est accepté.
|
||||||
|
- [ ] Aucun code GTK.
|
||||||
|
- [ ] Aucun code SQLite.
|
||||||
|
- [ ] Les fonctions publiques sont documentées avec Doxygen.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
- créer un nœud dossier ;
|
||||||
|
- créer un nœud fichier ;
|
||||||
|
- lire le nom ;
|
||||||
|
- lire le type ;
|
||||||
|
- tester un nom vide ;
|
||||||
|
- tester un nom `NULL` ;
|
||||||
|
- libérer un nœud valide ;
|
||||||
|
- appeler `investigation_node_free(NULL)`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Commit attendu
|
||||||
|
|
||||||
|
```text
|
||||||
|
feat(core): create investigation node
|
||||||
|
```
|
||||||
80
labfy-investigation/include/core/investigation_node.h
Normal file
80
labfy-investigation/include/core/investigation_node.h
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file investigation_node.h
|
||||||
|
* @brief Interface publique d'un nœud de l'arborescence d'une enquête.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef LABFY_INVESTIGATION_INVESTIGATION_NODE_H
|
||||||
|
#define LABFY_INVESTIGATION_INVESTIGATION_NODE_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Représentation opaque d'un nœud d'enquête.
|
||||||
|
*
|
||||||
|
* La structure réelle est définie dans investigation_node.c.
|
||||||
|
* Les autres modules manipulent uniquement un pointeur vers
|
||||||
|
* InvestigationNode.
|
||||||
|
*/
|
||||||
|
typedef struct InvestigationNode InvestigationNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type d'un nœud de l'arborescence.
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
INVESTIGATION_NODE_DIRECTORY,
|
||||||
|
INVESTIGATION_NODE_FILE
|
||||||
|
} InvestigationNodeType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Crée un nouveau nœud d'enquête.
|
||||||
|
*
|
||||||
|
* Le nom fourni est copié. Le code appelant peut donc modifier ou libérer
|
||||||
|
* sa chaîne après l'appel sans affecter le nœud.
|
||||||
|
*
|
||||||
|
* @param name Nom du fichier ou du dossier.
|
||||||
|
* @param type Type du nœud.
|
||||||
|
*
|
||||||
|
* @return Un nouveau nœud, ou NULL si le nom est invalide ou si la création
|
||||||
|
* échoue.
|
||||||
|
*/
|
||||||
|
InvestigationNode *investigation_node_new(
|
||||||
|
const char *name,
|
||||||
|
InvestigationNodeType type
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Libère les ressources associées à un nœud.
|
||||||
|
*
|
||||||
|
* Cette fonction accepte NULL.
|
||||||
|
*
|
||||||
|
* @param node Nœud à libérer.
|
||||||
|
*/
|
||||||
|
void investigation_node_free(
|
||||||
|
InvestigationNode *node
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le nom du nœud.
|
||||||
|
*
|
||||||
|
* La chaîne retournée appartient au nœud et ne doit pas être modifiée
|
||||||
|
* ni libérée par le code appelant.
|
||||||
|
*
|
||||||
|
* @param node Nœud à consulter.
|
||||||
|
*
|
||||||
|
* @return Le nom en lecture seule, ou NULL si node vaut NULL.
|
||||||
|
*/
|
||||||
|
const char *investigation_node_get_name(
|
||||||
|
const InvestigationNode *node
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le type du nœud.
|
||||||
|
*
|
||||||
|
* @param node Nœud à consulter.
|
||||||
|
*
|
||||||
|
* @return Le type du nœud.
|
||||||
|
*/
|
||||||
|
InvestigationNodeType investigation_node_get_type(
|
||||||
|
const InvestigationNode *node
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif
|
||||||
Binary file not shown.
91
labfy-investigation/src/core/investigation_node.c
Normal file
91
labfy-investigation/src/core/investigation_node.c
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file investigation_node.c
|
||||||
|
* @brief Implémentation d'un nœud d'enquête.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "core/investigation_node.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct InvestigationNode
|
||||||
|
* @brief Représentation interne d'un nœud.
|
||||||
|
*/
|
||||||
|
struct InvestigationNode
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
InvestigationNodeType type;
|
||||||
|
};
|
||||||
|
|
||||||
|
InvestigationNode *investigation_node_new(
|
||||||
|
const char *name,
|
||||||
|
InvestigationNodeType type
|
||||||
|
)
|
||||||
|
{
|
||||||
|
InvestigationNode *node = NULL;
|
||||||
|
|
||||||
|
if (name == NULL || name[0] == '\0')
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = g_new0(
|
||||||
|
InvestigationNode,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
if (node == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
node->name = g_strdup(name);
|
||||||
|
|
||||||
|
if (node->name == NULL)
|
||||||
|
{
|
||||||
|
investigation_node_free(node);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
node->type = type;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void investigation_node_free(
|
||||||
|
InvestigationNode *node
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (node == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(node->name);
|
||||||
|
|
||||||
|
g_free(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *investigation_node_get_name(
|
||||||
|
const InvestigationNode *node
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (node == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
InvestigationNodeType investigation_node_get_type(
|
||||||
|
const InvestigationNode *node
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (node == NULL)
|
||||||
|
{
|
||||||
|
return INVESTIGATION_NODE_FILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node->type;
|
||||||
|
}
|
||||||
BIN
labfy-investigation/tests/test_investigation_node
Executable file
BIN
labfy-investigation/tests/test_investigation_node
Executable file
Binary file not shown.
88
labfy-investigation/tests/test_investigation_node.c
Normal file
88
labfy-investigation/tests/test_investigation_node.c
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file test_investigation_node.c
|
||||||
|
* @brief Tests du module InvestigationNode.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "core/investigation_node.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static void test_directory_node(void)
|
||||||
|
{
|
||||||
|
InvestigationNode *node = NULL;
|
||||||
|
|
||||||
|
node = investigation_node_new(
|
||||||
|
"01_Preuves_Originales",
|
||||||
|
INVESTIGATION_NODE_DIRECTORY
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(node != NULL);
|
||||||
|
assert(strcmp(
|
||||||
|
investigation_node_get_name(node),
|
||||||
|
"01_Preuves_Originales"
|
||||||
|
) == 0);
|
||||||
|
assert(
|
||||||
|
investigation_node_get_type(node) ==
|
||||||
|
INVESTIGATION_NODE_DIRECTORY
|
||||||
|
);
|
||||||
|
|
||||||
|
investigation_node_free(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_file_node(void)
|
||||||
|
{
|
||||||
|
InvestigationNode *node = NULL;
|
||||||
|
|
||||||
|
node = investigation_node_new(
|
||||||
|
"Chronologie.md",
|
||||||
|
INVESTIGATION_NODE_FILE
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(node != NULL);
|
||||||
|
assert(strcmp(
|
||||||
|
investigation_node_get_name(node),
|
||||||
|
"Chronologie.md"
|
||||||
|
) == 0);
|
||||||
|
assert(
|
||||||
|
investigation_node_get_type(node) ==
|
||||||
|
INVESTIGATION_NODE_FILE
|
||||||
|
);
|
||||||
|
|
||||||
|
investigation_node_free(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_invalid_names(void)
|
||||||
|
{
|
||||||
|
assert(
|
||||||
|
investigation_node_new(
|
||||||
|
NULL,
|
||||||
|
INVESTIGATION_NODE_FILE
|
||||||
|
) == NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(
|
||||||
|
investigation_node_new(
|
||||||
|
"",
|
||||||
|
INVESTIGATION_NODE_FILE
|
||||||
|
) == NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_null_free(void)
|
||||||
|
{
|
||||||
|
investigation_node_free(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
test_directory_node();
|
||||||
|
test_file_node();
|
||||||
|
test_invalid_names();
|
||||||
|
test_null_free();
|
||||||
|
|
||||||
|
printf("InvestigationNode : tous les tests sont valides.\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue