feat(core): create investigation project structure

This commit is contained in:
grayTerminal-sh 2026-07-14 19:44:53 +02:00
parent d5324f9573
commit e5f3479f71
10 changed files with 1197 additions and 2 deletions

View file

@ -32,6 +32,7 @@ TARGET = labfy-investigation
TEST_NODE = tests/test_investigation_node
TEST_TREE_MODEL = tests/test_investigation_tree_model
TEST_TREE_BUILDER = tests/test_investigation_tree_builder
TEST_PROJECT = tests/test_investigation_project
all: $(TARGET)
@ -57,11 +58,21 @@ $(TEST_TREE_BUILDER): \
$(CC) $(TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS) \
$(shell $(PKG_CONFIG) --libs gio-2.0)
test: $(TEST_NODE) $(TEST_TREE_MODEL) $(TEST_TREE_BUILDER)
$(TEST_PROJECT): \
tests/test_investigation_project.c \
src/core/investigation_project.c
$(CC) $(TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS)
test: \
$(TEST_NODE) \
$(TEST_TREE_MODEL) \
$(TEST_TREE_BUILDER) \
$(TEST_PROJECT)
@echo "Exécution des tests..."
@./$(TEST_NODE)
@./$(TEST_TREE_MODEL)
@./$(TEST_TREE_BUILDER)
@./$(TEST_PROJECT)
@echo "Tous les tests sont valides."
%.o: %.c
@ -74,6 +85,7 @@ clean:
rm -f $(OBJ) $(TARGET) \
$(TEST_NODE) \
$(TEST_TREE_MODEL) \
$(TEST_TREE_BUILDER)
$(TEST_TREE_BUILDER) \
@./$(TEST_PROJECT)
.PHONY: clean run test

View file

@ -0,0 +1,257 @@
# Ticket #020
## Titre
Créer une nouvelle enquête.
---
## Objectif
Ajouter la capacité de créer automatiquement une nouvelle enquête dans un dossier choisi par l'utilisateur.
La création doit produire une arborescence standard et préparer l'emplacement de la future base SQLite.
Ce ticket ne crée pas encore le schéma SQL complet.
---
## Architecture
```text
Application
InvestigationProject
FileSystem
```
Le module `InvestigationProject` devient le point d'entrée métier pour la création d'une enquête.
La GUI ne doit jamais créer directement les dossiers.
---
## Responsabilités
### InvestigationProject
Le module doit :
- recevoir le chemin du dossier parent ;
- recevoir le nom de la nouvelle enquête ;
- créer le dossier racine de l'enquête ;
- créer l'arborescence standard ;
- créer le dossier `00_BaseDeDonnees` ;
- créer un fichier SQLite vide nommé `Enquete.sqlite` ;
- nettoyer ce qui a été créé en cas d'échec partiel ;
- retourner le chemin complet de l'enquête créée.
---
## Arborescence à créer
```text
NomEnquete/
├── 00_BaseDeDonnees/
│ └── Enquete.sqlite
├── 01_Preuves_Originales/
│ ├── Captures_Ecran/
│ ├── Conversations/
│ ├── Documents/
│ ├── Emails/
│ ├── Photos/
│ └── Videos/
├── 02_Preuves_Traitees/
│ ├── Annotations/
│ ├── Extractions/
│ ├── OCR/
│ └── Redactions/
├── 03_Chronologie/
├── 04_Entites/
│ ├── Adresses_Email/
│ ├── Comptes_Bancaires/
│ ├── Comptes_Facebook/
│ ├── Comptes_Instagram/
│ ├── Documents_Identite/
│ ├── IBAN/
│ ├── Personnes/
│ ├── Pseudonymes/
│ ├── Telephones/
│ └── Autres/
├── 05_Rapports/
├── 06_Exports/
├── 07_Notes/
├── 08_Sources/
└── 09_Hash/
```
Les noms de dossiers ne doivent pas contenir d'accents.
---
## Interface publique attendue
Créer :
```text
include/core/investigation_project.h
src/core/investigation_project.c
```
Avec :
```c
char *investigation_project_create(
const char *parent_directory,
const char *investigation_name
);
```
---
## Contrat de propriété
En cas de succès, la fonction retourne une nouvelle chaîne allouée contenant le chemin complet du dossier d'enquête.
Le code appelant devient propriétaire de cette chaîne et doit la libérer avec :
```c
g_free(investigation_path);
```
En cas d'échec, la fonction retourne :
```c
NULL
```
---
## Règles de validation
La fonction doit refuser :
- `parent_directory == NULL` ;
- un chemin parent vide ;
- `investigation_name == NULL` ;
- un nom vide ;
- un dossier parent inexistant ;
- un chemin parent qui n'est pas un dossier ;
- un dossier d'enquête qui existe déjà ;
- un nom contenant `/`.
---
## Gestion des erreurs
Si une étape échoue après la création partielle :
- tous les fichiers créés par la fonction doivent être supprimés ;
- tous les dossiers créés par la fonction doivent être supprimés ;
- aucun dossier partiel ne doit rester sur le disque ;
- la fonction retourne `NULL`.
La fonction ne doit jamais supprimer un dossier qui existait avant son appel.
---
## Création de `Enquete.sqlite`
Pour ce ticket, le fichier doit seulement être créé.
Le schéma SQLite sera initialisé dans le ticket #022.
Le fichier attendu est :
```text
00_BaseDeDonnees/Enquete.sqlite
```
---
## Hors périmètre
Ce ticket ne doit pas :
- créer les tables SQLite ;
- générer un UUID ;
- créer les métadonnées ;
- importer une enquête existante ;
- modifier l'interface GTK ;
- ouvrir automatiquement l'enquête créée ;
- créer un rapport ;
- copier des preuves.
---
## Dépendances
- C17 ;
- GLib ;
- GIO autorisé.
Aucune dépendance GTK ou SQLite requise dans ce ticket.
---
## Contraintes techniques
- structure modulaire ;
- aucun état global ;
- aucune logique de création dans `Application` ;
- aucune logique de création dans les widgets ;
- documentation Doxygen ;
- compilation sans warning ;
- nettoyage complet en cas d'erreur ;
- noms de fonctions préfixés par `investigation_project_`.
---
## Tests
Créer :
```text
tests/test_investigation_project.c
```
Le test doit :
- créer un dossier temporaire ;
- créer une enquête valide ;
- vérifier chaque dossier attendu ;
- vérifier la présence de `Enquete.sqlite` ;
- vérifier que la fonction retourne le bon chemin ;
- vérifier le refus des paramètres `NULL` ;
- vérifier le refus des chaînes vides ;
- vérifier le refus d'un nom contenant `/` ;
- vérifier le refus si le dossier existe déjà ;
- supprimer complètement l'enquête de test ;
- vérifier qu'aucun résidu ne reste.
---
## Critères d'acceptation
- [ ] Le projet compile sans warning.
- [ ] `make test` reste valide.
- [ ] Une enquête complète peut être créée.
- [ ] Tous les dossiers attendus existent.
- [ ] `Enquete.sqlite` existe.
- [ ] Aucun dossier partiel ne reste en cas d'échec.
- [ ] Un dossier existant n'est jamais écrasé.
- [ ] Le chemin retourné est correct.
- [ ] Aucune dépendance GTK.
- [ ] Aucun code SQLite métier.
- [ ] Le nouveau test est intégré à `make test`.
---
## Commit attendu
```text
feat(core): create investigation project structure
```

View file

@ -0,0 +1,39 @@
/******************************************************************************
* @file investigation_project.h
* @brief Interface publique de gestion d'un projet d'enquête.
******************************************************************************/
#ifndef LABFY_INVESTIGATION_INVESTIGATION_PROJECT_H
#define LABFY_INVESTIGATION_INVESTIGATION_PROJECT_H
/**
* @brief Crée une nouvelle enquête dans un dossier parent.
*
* La fonction crée :
*
* - le dossier racine de l'enquête ;
* - l'arborescence standard ;
* - le fichier vide 00_BaseDeDonnees/Enquete.sqlite.
*
* Le dossier parent doit déjà exister.
*
* Le nom de l'enquête ne doit pas être vide et ne doit pas contenir
* de séparateur de chemin.
*
* En cas d'échec, les éléments créés pendant l'appel sont supprimés.
* Aucun dossier existant avant l'appel ne doit être supprimé.
*
* La chaîne retournée appartient au code appelant et doit être libérée
* avec g_free().
*
* @param parent_directory Chemin du dossier parent.
* @param investigation_name Nom de la nouvelle enquête.
*
* @return Le chemin complet de l'enquête créée, ou NULL en cas d'échec.
*/
char *investigation_project_create(
const char *parent_directory,
const char *investigation_name
);
#endif

Binary file not shown.

View file

@ -0,0 +1,424 @@
/******************************************************************************
* @file investigation_project.c
* @brief Création et gestion de la structure d'un projet d'enquête.
******************************************************************************/
#include "core/investigation_project.h"
#include <errno.h>
#include <string.h>
#include <glib.h>
#include <glib/gstdio.h>
/**
* @brief Liste des dossiers relatifs composant une enquête.
*
* L'ordre est important : les dossiers parents doivent apparaître avant
* leurs sous-dossiers.
*/
static const char *const investigation_project_directories[] =
{
"00_BaseDeDonnees",
"01_Preuves_Originales",
"01_Preuves_Originales/Captures_Ecran",
"01_Preuves_Originales/Conversations",
"01_Preuves_Originales/Documents",
"01_Preuves_Originales/Emails",
"01_Preuves_Originales/Photos",
"01_Preuves_Originales/Videos",
"02_Preuves_Traitees",
"02_Preuves_Traitees/Annotations",
"02_Preuves_Traitees/Extractions",
"02_Preuves_Traitees/OCR",
"02_Preuves_Traitees/Redactions",
"03_Chronologie",
"04_Entites",
"04_Entites/Adresses_Email",
"04_Entites/Comptes_Bancaires",
"04_Entites/Comptes_Facebook",
"04_Entites/Comptes_Instagram",
"04_Entites/Documents_Identite",
"04_Entites/IBAN",
"04_Entites/Personnes",
"04_Entites/Pseudonymes",
"04_Entites/Telephones",
"04_Entites/Autres",
"05_Rapports",
"06_Exports",
"07_Notes",
"08_Sources",
"09_Hash"
};
/**
* @brief Nombre de dossiers présents dans la table de création.
*/
#define INVESTIGATION_PROJECT_DIRECTORY_COUNT \
G_N_ELEMENTS(investigation_project_directories)
/**
* @brief Vérifie que les paramètres nécessaires à la création sont valides.
*
* @param parent_directory Dossier dans lequel créer l'enquête.
* @param investigation_name Nom de la nouvelle enquête.
*
* @return TRUE si les paramètres sont valides, sinon FALSE.
*/
static gboolean investigation_project_validate_create_parameters(
const char *parent_directory,
const char *investigation_name
)
{
if (parent_directory == NULL ||
parent_directory[0] == '\0')
{
return FALSE;
}
if (investigation_name == NULL ||
investigation_name[0] == '\0')
{
return FALSE;
}
/*
* Le nom doit représenter un seul composant de chemin.
*
* On refuse par exemple :
*
* Enquetes/Test
*/
if (strchr(investigation_name, G_DIR_SEPARATOR) != NULL)
{
return FALSE;
}
if (!g_file_test(
parent_directory,
G_FILE_TEST_EXISTS
))
{
return FALSE;
}
if (!g_file_test(
parent_directory,
G_FILE_TEST_IS_DIR
))
{
return FALSE;
}
return TRUE;
}
/**
* @brief Supprime les fichiers et dossiers créés pendant une tentative.
*
* Les chemins sont parcourus dans l'ordre inverse afin de supprimer :
*
* 1. les fichiers ;
* 2. les sous-dossiers ;
* 3. le dossier racine.
*
* Cette fonction ne reçoit que des chemins créés par le module pendant
* l'appel courant.
*
* @param created_paths Tableau contenant les chemins créés.
*/
static void investigation_project_cleanup_created_paths(
GPtrArray *created_paths
)
{
if (created_paths == NULL)
{
return;
}
for (gsize index = created_paths->len; index > 0; --index)
{
const char *path = NULL;
path = g_ptr_array_index(
created_paths,
index - 1
);
if (path == NULL)
{
continue;
}
if (g_file_test(path, G_FILE_TEST_IS_DIR))
{
if (g_rmdir(path) != 0)
{
g_warning(
"Impossible de supprimer le dossier temporaire '%s' : %s",
path,
g_strerror(errno)
);
}
}
else if (g_file_test(path, G_FILE_TEST_EXISTS))
{
if (g_remove(path) != 0)
{
g_warning(
"Impossible de supprimer le fichier temporaire '%s' : %s",
path,
g_strerror(errno)
);
}
}
}
}
/**
* @brief Crée un dossier et mémorise son chemin pour un éventuel nettoyage.
*
* La fonction prend possession de directory_path uniquement si la création
* réussit et que le chemin est ajouté au tableau.
*
* @param directory_path Chemin alloué du dossier à créer.
* @param created_paths Tableau des éléments créés.
*
* @return TRUE si le dossier a é créé, sinon FALSE.
*/
static gboolean investigation_project_create_directory(
char *directory_path,
GPtrArray *created_paths
)
{
if (directory_path == NULL || created_paths == NULL)
{
g_free(directory_path);
return FALSE;
}
if (g_mkdir(directory_path, 0700) != 0)
{
g_warning(
"Impossible de créer le dossier '%s' : %s",
directory_path,
g_strerror(errno)
);
g_free(directory_path);
return FALSE;
}
/*
* Le tableau devient propriétaire de directory_path.
*/
g_ptr_array_add(
created_paths,
directory_path
);
return TRUE;
}
char *investigation_project_create(
const char *parent_directory,
const char *investigation_name
)
{
char *investigation_path = NULL;
char *directory_path = NULL;
char *database_path = NULL;
GPtrArray *created_paths = NULL;
GError *error = NULL;
if (!investigation_project_validate_create_parameters(
parent_directory,
investigation_name
))
{
return NULL;
}
investigation_path = g_build_filename(
parent_directory,
investigation_name,
NULL
);
if (investigation_path == NULL)
{
return NULL;
}
/*
* Une enquête existante ne doit jamais être écrasée.
*/
if (g_file_test(
investigation_path,
G_FILE_TEST_EXISTS
))
{
g_free(investigation_path);
return NULL;
}
/*
* Le tableau conserve tous les chemins créés.
*
* Ses chaînes seront libérées automatiquement par g_ptr_array_free().
*/
created_paths = g_ptr_array_new_with_free_func(
g_free
);
if (created_paths == NULL)
{
g_free(investigation_path);
return NULL;
}
/*
* On crée d'abord le dossier racine.
*
* Une copie est placée dans created_paths, car investigation_path
* doit être retourné au code appelant en cas de succès.
*/
directory_path = g_strdup(investigation_path);
if (!investigation_project_create_directory(
directory_path,
created_paths
))
{
g_ptr_array_free(created_paths, TRUE);
g_free(investigation_path);
return NULL;
}
/*
* Création de toute l'arborescence déclarée dans la table.
*/
for (gsize index = 0;
index < INVESTIGATION_PROJECT_DIRECTORY_COUNT;
++index)
{
directory_path = g_build_filename(
investigation_path,
investigation_project_directories[index],
NULL
);
if (!investigation_project_create_directory(
directory_path,
created_paths
))
{
investigation_project_cleanup_created_paths(
created_paths
);
g_ptr_array_free(
created_paths,
TRUE
);
g_free(investigation_path);
return NULL;
}
}
database_path = g_build_filename(
investigation_path,
"00_BaseDeDonnees",
"Enquete.sqlite",
NULL
);
if (database_path == NULL)
{
investigation_project_cleanup_created_paths(
created_paths
);
g_ptr_array_free(
created_paths,
TRUE
);
g_free(investigation_path);
return NULL;
}
/*
* Pour ce ticket, on crée seulement un fichier vide.
*
* Le schéma SQLite sera ajouté dans un prochain ticket.
*/
if (!g_file_set_contents(
database_path,
"",
0,
&error
))
{
if (error != NULL)
{
g_warning(
"Impossible de créer '%s' : %s",
database_path,
error->message
);
g_clear_error(&error);
}
g_free(database_path);
investigation_project_cleanup_created_paths(
created_paths
);
g_ptr_array_free(
created_paths,
TRUE
);
g_free(investigation_path);
return NULL;
}
/*
* Le fichier doit également être supprimé avant ses dossiers
* si une évolution future ajoute une étape pouvant encore échouer.
*
* Le tableau devient propriétaire de database_path.
*/
g_ptr_array_add(
created_paths,
database_path
);
/*
* Tout est créé avec succès.
*
* On libère seulement le tableau et ses copies de chemins.
* Les fichiers et dossiers restent sur le disque.
*/
g_ptr_array_free(
created_paths,
TRUE
);
return investigation_path;
}

BIN
tests/test_investigation_node Executable file

Binary file not shown.

BIN
tests/test_investigation_project Executable file

Binary file not shown.

View file

@ -0,0 +1,463 @@
/******************************************************************************
* @file test_investigation_project.c
* @brief Tests d'intégration du module InvestigationProject.
******************************************************************************/
#include "core/investigation_project.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <glib.h>
#include <glib/gstdio.h>
/**
* @brief Liste des dossiers attendus dans une enquête.
*
* Cette liste doit rester cohérente avec la structure créée par
* investigation_project_create().
*/
static const char *const expected_directories[] =
{
"00_BaseDeDonnees",
"01_Preuves_Originales",
"01_Preuves_Originales/Captures_Ecran",
"01_Preuves_Originales/Conversations",
"01_Preuves_Originales/Documents",
"01_Preuves_Originales/Emails",
"01_Preuves_Originales/Photos",
"01_Preuves_Originales/Videos",
"02_Preuves_Traitees",
"02_Preuves_Traitees/Annotations",
"02_Preuves_Traitees/Extractions",
"02_Preuves_Traitees/OCR",
"02_Preuves_Traitees/Redactions",
"03_Chronologie",
"04_Entites",
"04_Entites/Adresses_Email",
"04_Entites/Comptes_Bancaires",
"04_Entites/Comptes_Facebook",
"04_Entites/Comptes_Instagram",
"04_Entites/Documents_Identite",
"04_Entites/IBAN",
"04_Entites/Personnes",
"04_Entites/Pseudonymes",
"04_Entites/Telephones",
"04_Entites/Autres",
"05_Rapports",
"06_Exports",
"07_Notes",
"08_Sources",
"09_Hash"
};
#define EXPECTED_DIRECTORY_COUNT \
G_N_ELEMENTS(expected_directories)
/**
* @brief Supprime récursivement un fichier ou un dossier de test.
*
* Cette fonction est réservée au nettoyage des répertoires temporaires créés
* par les tests.
*
* @param path Chemin à supprimer.
*
* @return TRUE si le chemin a é supprimé ou n'existait pas, sinon FALSE.
*/
static gboolean test_remove_path_recursively(
const char *path
)
{
GDir *directory = NULL;
const char *entry_name = NULL;
GError *error = NULL;
if (path == NULL)
{
return FALSE;
}
if (!g_file_test(path, G_FILE_TEST_EXISTS))
{
return TRUE;
}
if (!g_file_test(path, G_FILE_TEST_IS_DIR))
{
return g_remove(path) == 0;
}
directory = g_dir_open(
path,
0,
&error
);
if (directory == NULL)
{
if (error != NULL)
{
g_printerr(
"Impossible d'ouvrir '%s' pendant le nettoyage : %s\n",
path,
error->message
);
g_clear_error(&error);
}
return FALSE;
}
while ((entry_name = g_dir_read_name(directory)) != NULL)
{
char *entry_path = NULL;
gboolean removal_success = FALSE;
entry_path = g_build_filename(
path,
entry_name,
NULL
);
assert(entry_path != NULL);
removal_success = test_remove_path_recursively(
entry_path
);
g_free(entry_path);
if (!removal_success)
{
g_dir_close(directory);
return FALSE;
}
}
g_dir_close(directory);
return g_rmdir(path) == 0;
}
/**
* @brief Vérifie qu'un chemin désigne un dossier existant.
*/
static void test_assert_directory_exists(
const char *root_path,
const char *relative_path
)
{
char *directory_path = NULL;
assert(root_path != NULL);
assert(relative_path != NULL);
directory_path = g_build_filename(
root_path,
relative_path,
NULL
);
assert(directory_path != NULL);
assert(
g_file_test(
directory_path,
G_FILE_TEST_IS_DIR
)
);
g_free(directory_path);
}
/**
* @brief Vérifie la création complète d'une enquête.
*/
static void test_create_valid_investigation(void)
{
char *temporary_parent = NULL;
char *investigation_path = NULL;
char *expected_path = NULL;
char *database_path = NULL;
GError *error = NULL;
temporary_parent = g_dir_make_tmp(
"labfy-investigation-project-test-XXXXXX",
&error
);
assert(temporary_parent != NULL);
assert(error == NULL);
investigation_path = investigation_project_create(
temporary_parent,
"Enquete_Test"
);
assert(investigation_path != NULL);
expected_path = g_build_filename(
temporary_parent,
"Enquete_Test",
NULL
);
assert(expected_path != NULL);
/*
* Le chemin retourné doit être exactement celui de la nouvelle enquête.
*/
assert(strcmp(investigation_path, expected_path) == 0);
/*
* Le dossier racine doit exister.
*/
assert(
g_file_test(
investigation_path,
G_FILE_TEST_IS_DIR
)
);
/*
* Vérification de tous les dossiers attendus.
*/
for (gsize index = 0;
index < EXPECTED_DIRECTORY_COUNT;
++index)
{
test_assert_directory_exists(
investigation_path,
expected_directories[index]
);
}
database_path = g_build_filename(
investigation_path,
"00_BaseDeDonnees",
"Enquete.sqlite",
NULL
);
assert(database_path != NULL);
/*
* Enquete.sqlite doit exister et être un fichier régulier.
*/
assert(
g_file_test(
database_path,
G_FILE_TEST_EXISTS
)
);
assert(
g_file_test(
database_path,
G_FILE_TEST_IS_REGULAR
)
);
/*
* Une deuxième création au même endroit doit être refusée.
*/
assert(
investigation_project_create(
temporary_parent,
"Enquete_Test"
) == NULL
);
/*
* Nettoyage complet.
*/
assert(
test_remove_path_recursively(
temporary_parent
)
);
assert(
!g_file_test(
temporary_parent,
G_FILE_TEST_EXISTS
)
);
g_free(database_path);
g_free(expected_path);
g_free(investigation_path);
g_free(temporary_parent);
}
/**
* @brief Vérifie les paramètres NULL et les chaînes vides.
*/
static void test_invalid_parameters(void)
{
char *temporary_parent = NULL;
GError *error = NULL;
temporary_parent = g_dir_make_tmp(
"labfy-investigation-invalid-test-XXXXXX",
&error
);
assert(temporary_parent != NULL);
assert(error == NULL);
assert(
investigation_project_create(
NULL,
"Enquete"
) == NULL
);
assert(
investigation_project_create(
"",
"Enquete"
) == NULL
);
assert(
investigation_project_create(
temporary_parent,
NULL
) == NULL
);
assert(
investigation_project_create(
temporary_parent,
""
) == NULL
);
assert(
test_remove_path_recursively(
temporary_parent
)
);
g_free(temporary_parent);
}
/**
* @brief Vérifie le refus d'un nom contenant un séparateur de chemin.
*/
static void test_invalid_investigation_name(void)
{
char *temporary_parent = NULL;
GError *error = NULL;
temporary_parent = g_dir_make_tmp(
"labfy-investigation-name-test-XXXXXX",
&error
);
assert(temporary_parent != NULL);
assert(error == NULL);
assert(
investigation_project_create(
temporary_parent,
"Enquetes/Test"
) == NULL
);
assert(
test_remove_path_recursively(
temporary_parent
)
);
g_free(temporary_parent);
}
/**
* @brief Vérifie le refus d'un dossier parent inexistant.
*/
static void test_missing_parent_directory(void)
{
assert(
investigation_project_create(
"/tmp/labfy-parent-directory-that-does-not-exist",
"Enquete"
) == NULL
);
}
/**
* @brief Vérifie le refus d'un chemin parent représentant un fichier.
*/
static void test_parent_is_file(void)
{
char *temporary_directory = NULL;
char *temporary_file = NULL;
GError *error = NULL;
temporary_directory = g_dir_make_tmp(
"labfy-investigation-parent-file-test-XXXXXX",
&error
);
assert(temporary_directory != NULL);
assert(error == NULL);
temporary_file = g_build_filename(
temporary_directory,
"parent.txt",
NULL
);
assert(temporary_file != NULL);
assert(
g_file_set_contents(
temporary_file,
"test\n",
-1,
&error
)
);
assert(error == NULL);
assert(
investigation_project_create(
temporary_file,
"Enquete"
) == NULL
);
assert(
test_remove_path_recursively(
temporary_directory
)
);
g_free(temporary_file);
g_free(temporary_directory);
}
int main(void)
{
test_create_valid_investigation();
test_invalid_parameters();
test_invalid_investigation_name();
test_missing_parent_directory();
test_parent_is_file();
printf(
"InvestigationProject : tous les tests sont valides.\n"
);
return 0;
}

Binary file not shown.

Binary file not shown.