feat(database): finalize database architecture v1

This commit is contained in:
grayTerminal-sh 2026-07-15 23:10:24 +02:00
parent fbe1cd11fb
commit 142088da87
16 changed files with 5287 additions and 56 deletions

View file

@ -62,12 +62,14 @@ $(TEST_TREE_BUILDER): \
$(TEST_PROJECT): \ $(TEST_PROJECT): \
tests/test_investigation_project.c \ tests/test_investigation_project.c \
src/core/investigation_project.c \ src/core/investigation_project.c \
src/database/database.c src/database/database.c \
src/database/schema.c
$(CC) $(TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS) -lsqlite3 $(CC) $(TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS) -lsqlite3
$(TEST_DATABASE): \ $(TEST_DATABASE): \
tests/test_database.c \ tests/test_database.c \
src/database/database.c src/database/database.c \
src/database/schema.c
$(CC) $(TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS) -lsqlite3 $(CC) $(TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS) -lsqlite3
test: \ test: \

View file

View file

1231
database/schema_v1.sql Normal file

File diff suppressed because it is too large Load diff

302
docs/CONVENTIONS.md Normal file
View file

@ -0,0 +1,302 @@
# Conventions de développement
Version : 1.0
---
# Philosophie
Labfy Investigation est développé comme un logiciel d'enquête numérique.
Les choix d'architecture privilégient :
- la lisibilité ;
- la maintenabilité ;
- la robustesse ;
- la traçabilité ;
- la simplicité.
Une solution simple et cohérente est toujours préférée à une solution
complexe.
---
# Langue
Le domaine métier est écrit en français.
Exemples :
- preuve
- entite
- personne
- source
- chronologie
- journal
- hypothese
- recherche
Les standards techniques conservent leur nom d'origine.
Exemples :
- uuid
- sha256
- mime_type
- sqlite
- created_at
- updated_at
- relative_path
---
# Architecture
Le projet est organisé par domaine métier.
Exemple :
```
preuve
preuve.h
preuve.c
entite
entite.h
entite.c
```
Chaque module possède une responsabilité unique.
---
# SQL
Une table représente un objet métier.
Une table importante possède :
- une structure C ;
- un module C ;
- des tests.
Les objets métier utilisent :
```
TEXT PRIMARY KEY
```
contenant un UUID.
Les tables de référence utilisent :
```
INTEGER PRIMARY KEY
```
---
# UUID
Tous les objets métier utilisent un UUID.
Exemple :
```
preuve
entite
personne
source
chronologie
journal
```
Il n'existe pas simultanément :
```
id
uuid
```
La colonne :
```
id
```
contient directement l'UUID.
---
# Dates
Toutes les dates sont enregistrées en UTC.
Format :
```
YYYY-MM-DDTHH:MM:SSZ
```
---
# Chemins
Les chemins sont toujours relatifs à la racine de l'enquête.
Autorisé :
```
01_Preuves_Originales/Documents/facture.pdf
```
Interdit :
```
/home/user/Documents/...
```
---
# Suppression
Les objets métier importants ne sont jamais supprimés immédiatement.
Une suppression est une modification d'état.
Exemple :
```
active
archived
deleted
```
Une purge physique éventuelle devra être explicite.
---
# Nommage
Le SQL utilise :
- snake_case
- minuscules
- aucun accent
- aucun espace
---
# Code C
Norme :
```
C17
```
Variables :
Toujours explicites.
Autorisé :
```c
relative_path
description
commentaire
created_at
```
Interdit :
```c
path
desc
comm
crt
```
Les fonctions utilisent le nom du module.
Exemple :
```c
preuve_create()
preuve_load()
preuve_update()
preuve_delete()
```
---
# Structures
Une structure représente un objet métier.
Exemple :
```c
typedef struct Preuve Preuve;
```
Les structures publiques sont opaques lorsque cela est possible.
---
# Tests
Toute nouvelle fonctionnalité importante possède un test.
Le développement suit toujours l'ordre :
```
Conception
Implémentation
Tests
Commit
```
---
# Git
Un ticket terminé correspond à un commit.
Le message de commit est rédigé en anglais.
Exemple :
```
feat(database): initialize investigation database
```
---
# Documentation
Les décisions importantes sont documentées.
Les changements de schéma SQLite sont précédés d'un audit.
Aucune décision importante ne doit exister uniquement dans le code.
---
# Objectif
Le projet doit rester compréhensible plusieurs années après sa création.
La priorité est donnée à la qualité du code plutôt qu'à la rapidité de
développement.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,643 @@
# Ticket #023
## Titre
Consolider le schéma métier initial de l'enquête.
---
## Objectif
Transformer le schéma SQLite préparé lors des premières phases du projet en
un schéma métier officiel, cohérent, documenté et testable.
La base existante sert de fondation.
Le travail ne consiste pas à repartir de zéro, mais à :
- conserver les concepts métier déjà définis ;
- corriger les incohérences ;
- renforcer les contraintes ;
- uniformiser les conventions ;
- intégrer le schéma au module `Database`.
---
## Base de travail
La base historique contient notamment les tables suivantes :
```text
preuves
entites
personnes
chronologie
sources
recherche
hypotheses
journal
tags
types_preuve
types_entite
types_source
types_outils
associations
personnes_entites
entite_tags
preuves_tag
```
Les tables créées au ticket #022 restent également obligatoires :
```text
metadata
investigation
```
Le schéma officiel doit donc préserver ces concepts tout en les consolidant.
---
## Architecture
```text
InvestigationProject
Database
Schéma SQLite versionné
├── Métadonnées
├── Enquête
├── Preuves
├── Entités
├── Personnes
├── Sources
├── Chronologie
├── Recherches
├── Hypothèses
├── Journal
└── Tags et relations
```
Le module `Database` reste le seul autorisé à exécuter du SQL.
---
## Décisions de conception à officialiser
### Identifiants
Les entités métier utiliseront des identifiants texte de type UUID.
Exemple :
```text
550e8400-e29b-41d4-a716-446655440000
```
Les identifiants sont générés par l'application avec :
```c
g_uuid_string_random()
```
Les tables de référence simples peuvent utiliser des identifiants entiers.
---
### Dates
Les dates techniques sont stockées en UTC au format ISO 8601 :
```text
YYYY-MM-DDTHH:MM:SSZ
```
Exemple :
```text
2026-07-15T08:42:17Z
```
---
### Nommage
Les noms SQL utilisent uniquement :
- des minuscules ;
- du `snake_case` ;
- aucun accent ;
- aucun espace.
Les noms des tables de liaison sont uniformisés.
Exemple :
```text
preuve_tags
entite_tags
personne_entites
```
Aucune forme singulier/pluriel incohérente ne doit subsister.
---
### Clés étrangères
Toutes les relations métier doivent utiliser des clés étrangères explicites.
Le module `Database` doit activer :
```sql
PRAGMA foreign_keys = ON;
```
à chaque ouverture de connexion.
Les comportements `ON DELETE` doivent être décidés pour chaque relation.
---
### Tables de liaison
Chaque table de liaison doit empêcher les doublons grâce à :
- une clé primaire composite ;
- ou une contrainte `UNIQUE`.
Exemple :
```sql
PRIMARY KEY (preuve_id, tag_id)
```
---
## Tables métier à consolider
### `preuves`
Responsabilité :
- représenter un élément de preuve ;
- mémoriser son nom ;
- son chemin relatif ;
- son type ;
- sa description ;
- ses dates ;
- son hash éventuel ;
- son statut.
Contraintes minimales :
- identifiant obligatoire ;
- nom obligatoire ;
- chemin relatif obligatoire ;
- type obligatoire ;
- date de création obligatoire ;
- chemin unique au sein d'une enquête.
---
### `entites`
Responsabilité :
- représenter une entité identifiée pendant l'enquête.
Exemples :
- adresse email ;
- compte bancaire ;
- profil social ;
- pseudonyme ;
- téléphone ;
- document d'identité.
Contraintes minimales :
- identifiant obligatoire ;
- type obligatoire ;
- valeur obligatoire ;
- date de création obligatoire.
---
### `personnes`
Responsabilité :
- représenter une personne physique ou un profil humain étudié.
Le modèle ne doit pas obliger à connaître l'identité civile complète.
Une personne peut n'avoir qu'un pseudonyme ou une désignation temporaire.
---
### `sources`
Responsabilité :
- représenter l'origine d'une information ou d'une preuve.
Exemples :
- site web ;
- email ;
- réseau social ;
- document ;
- témoignage ;
- outil OSINT.
---
### `chronologie`
Responsabilité :
- mémoriser les événements importants de l'enquête ;
- relier éventuellement un événement à une preuve, une entité ou une source.
---
### `recherches`
Responsabilité :
- documenter une opération de recherche ;
- mémoriser la requête ;
- l'outil employé ;
- la date ;
- le résultat ;
- les observations.
---
### `hypotheses`
Responsabilité :
- enregistrer une hypothèse de travail ;
- mémoriser son statut ;
- sa justification ;
- les éléments qui la soutiennent ou la contredisent.
---
### `journal`
Responsabilité :
- conserver la trace des actions significatives réalisées dans l'enquête.
Exemples :
- création d'une preuve ;
- modification d'une entité ;
- calcul d'un hash ;
- génération d'un rapport ;
- import d'un fichier.
---
### `tags`
Responsabilité :
- permettre une classification libre des preuves et des entités.
---
## Tables de référence
Les tables suivantes doivent être consolidées :
```text
types_preuve
types_entite
types_source
types_outils
```
Elles doivent comporter au minimum :
```sql
id INTEGER PRIMARY KEY
code TEXT NOT NULL UNIQUE
label TEXT NOT NULL
description TEXT
```
Les valeurs initiales sont insérées lors de la création de la base.
---
## Tables de liaison
Les relations suivantes doivent être prévues :
```text
preuve_tags
entite_tags
personne_entites
```
Le schéma existant contient également une table générique :
```text
associations
```
Cette table doit être auditée avant conservation.
Elle ne doit être gardée que si son rôle est clairement défini et ne fait pas
doublon avec des relations spécialisées.
---
## Audit obligatoire
Avant d'écrire le schéma définitif, chaque table de la base historique doit
être classée dans l'une des catégories suivantes :
```text
CONSERVER
MODIFIER
RENOMMER
FUSIONNER
SUPPRIMER
```
La décision doit être documentée dans :
```text
docs/database/SCHEMA_AUDIT_V1.md
```
Le document doit contenir au minimum :
```text
Nom historique
Décision
Nom final
Justification
Modifications prévues
```
---
## Organisation du module Database
Le code SQL est organisé par domaine métier.
```
include/
└── database/
├── database.h
├── schema.h
├── preuve.h
├── entite.h
├── personne.h
├── source.h
├── chronologie.h
├── recherche.h
├── hypothese.h
├── journal.h
├── tag.h
├── type_preuve.h
├── type_entite.h
├── type_source.h
└── type_outil.h
src/
└── database/
├── database.c
├── schema.c
├── preuve.c
├── entite.c
├── personne.c
├── source.c
├── chronologie.c
├── recherche.c
├── hypothese.c
├── journal.c
├── tag.c
├── type_preuve.c
├── type_entite.c
├── type_source.c
└── type_outil.c
database/
├── schema_v1.sql
├── indexes.sql
├── triggers.sql
└── reference_data.sql
```
---
### Responsabilités
`database.c`
- ouverture de SQLite ;
- fermeture ;
- transactions ;
- erreurs ;
- point d'entrée du module Database.
`schema.c`
- installation du schéma ;
- migrations ;
- exécution des scripts SQL.
Chaque module métier est responsable exclusivement de son objet métier.
Exemple :
```
preuve.c
```
gère uniquement :
- création ;
- lecture ;
- modification ;
- suppression logique ;
- gestion des tags de la preuve.
Les tables de liaison simples ne possèdent pas de module dédié.
Exemples :
```
preuve_tags
personne_entites
entite_tags
```
Leur manipulation est réalisée par le module métier correspondant.
---
## Intégration dans `Database`
Le module `database_initialize()` doit exécuter le schéma officiel contenu
dans :
```text
database/schema_v1.sql
```
Deux approches sont acceptables :
1. intégrer le schéma au binaire via une ressource GLib ;
2. générer une chaîne C depuis le fichier SQL lors de la compilation.
Le logiciel installé ne doit pas dépendre d'un chemin relatif fragile vers le
dépôt source.
---
## Principe d'organisation
Une table métier importante implique systématiquement :
- une structure C ;
- un module C ;
- des tests ;
- une documentation.
La correspondance est la suivante :
| SQL | C |
|-----|---|
| preuves | preuve.c |
| entites | entite.c |
| personnes | personne.c |
| sources | source.c |
| chronologie | chronologie.c |
| journal | journal.c |
| recherches | recherche.c |
| hypotheses | hypothese.c |
---
## Version du schéma
Le numéro de version reste :
```text
1
```
tant que Labfy Investigation n'a pas produit de base officiellement publiée.
Une fois le schéma V1 considéré comme stable et distribué, toute modification
incompatible nécessitera :
- une nouvelle version ;
- une migration dédiée ;
- une mise à jour de `schema_version`.
---
## Hors périmètre
Ce ticket ne doit pas :
- développer les fonctions CRUD ;
- créer les structures C `Preuve`, `Entite` ou `Personne` ;
- connecter les tables à GTK ;
- importer les anciennes données automatiquement ;
- créer les migrations V2 ;
- produire un rapport ;
- ajouter la recherche plein texte.
---
## Contraintes techniques
- C17 ;
- SQLite3 ;
- GLib ;
- aucune dépendance GTK ;
- toutes les tables utilisent des contraintes explicites ;
- toutes les clés étrangères sont documentées ;
- toutes les tables de liaison empêchent les doublons ;
- aucun SQL métier hors du module `Database` ;
- aucun identifiant généré par SQLite pour les objets métier en UUID ;
- compilation sans warning.
---
## Tests
Faire évoluer :
```text
tests/test_database.c
```
Les tests doivent vérifier :
- la présence de toutes les tables officielles ;
- la présence des tables de référence ;
- l'insertion des valeurs initiales ;
- l'activation des clés étrangères ;
- le refus d'une clé étrangère invalide ;
- le refus d'un doublon dans une table de liaison ;
- le refus des colonnes obligatoires manquantes ;
- l'unicité des codes des tables de référence ;
- la valeur `schema_version = 1` ;
- l'intégrité SQLite avec :
```sql
PRAGMA integrity_check;
```
---
## Critères d'acceptation
- [ ] Le schéma historique a été audité.
- [ ] Chaque table possède une décision documentée.
- [ ] Un schéma V1 officiel existe.
- [ ] Les conventions de nommage sont uniformes.
- [ ] Toutes les clés primaires sont explicites.
- [ ] Toutes les clés étrangères sont explicites.
- [ ] Les relations empêchent les doublons.
- [ ] Les colonnes obligatoires utilisent `NOT NULL`.
- [ ] Les tables de référence sont initialisées.
- [ ] `database_initialize()` installe le schéma complet.
- [ ] `PRAGMA integrity_check` retourne `ok`.
- [ ] Tous les tests restent valides.
- [ ] Aucune dépendance GTK.
---
## Livrables
```text
docs/database/SCHEMA_AUDIT_V1.md
database/schema_v1.sql
include/database/database.h
src/database/database.c
tests/test_database.c
```
---
## Commit attendu
```text
feat(database): consolidate initial investigation schema
```

View file

@ -11,19 +11,10 @@
/** /**
* @brief Initialise la base SQLite d'une enquête. * @brief Initialise la base SQLite d'une enquête.
* *
* La fonction crée ou ouvre le fichier SQLite indiqué, puis initialise * La fonction crée ou ouvre le fichier SQLite indiqué, installe le schéma
* transactionnellement le schéma minimal de l'enquête. * courant, puis enregistre les métadonnées de l'enquête.
* *
* Les informations suivantes sont enregistrées : * Aucun handle SQLite n'est exposé au code appelant.
*
* - version du schéma ;
* - nom de l'application ;
* - date de création UTC ;
* - UUID de l'enquête ;
* - nom de l'enquête ;
* - chemin racine de l'enquête.
*
* Aucun handle sqlite3 n'est exposé au code appelant.
* *
* @param database_path * @param database_path
* Chemin complet du fichier Enquete.sqlite. * Chemin complet du fichier Enquete.sqlite.

34
include/database/schema.h Normal file
View file

@ -0,0 +1,34 @@
/******************************************************************************
* @file schema.h
* @brief Interface interne d'installation du schéma SQLite.
******************************************************************************/
#ifndef LABFY_INVESTIGATION_SCHEMA_H
#define LABFY_INVESTIGATION_SCHEMA_H
#include <stdbool.h>
#include <sqlite3.h>
/**
* @brief Installe le schéma SQLite V1 dans une base ouverte.
*
* La connexion doit être valide et une transaction doit déjà être active.
*
* Cette fonction crée :
*
* - les tables ;
* - les index ;
* - les valeurs de référence.
*
* Elle ne réalise ni COMMIT ni ROLLBACK.
*
* @param database Connexion SQLite ouverte.
*
* @return true si le schéma a é correctement installé, sinon false.
*/
bool schema_install_v1(
sqlite3 *database
);
#endif

Binary file not shown.

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/com/labfytools/investigation/database">
<file alias="schema_v1.sql">
../database/schema_v1.sql
</file>
</gresource>
</gresources>

View file

@ -4,6 +4,7 @@
******************************************************************************/ ******************************************************************************/
#include "database/database.h" #include "database/database.h"
#include "database/schema.h"
#include <glib.h> #include <glib.h>
#include <sqlite3.h> #include <sqlite3.h>
@ -18,28 +19,6 @@
*/ */
#define DATABASE_APPLICATION_NAME "Labfy Investigation" #define DATABASE_APPLICATION_NAME "Labfy Investigation"
/**
* @brief Crée la table contenant les métadonnées de l'enquête.
*/
static const char *const database_create_metadata_table_sql =
"CREATE TABLE metadata"
"("
" key TEXT PRIMARY KEY,"
" value TEXT NOT NULL"
");";
/**
* @brief Crée la table représentant l'enquête courante.
*/
static const char *const database_create_investigation_table_sql =
"CREATE TABLE investigation"
"("
" id INTEGER PRIMARY KEY CHECK (id = 1),"
" name TEXT NOT NULL,"
" root_path TEXT NOT NULL,"
" created_at TEXT NOT NULL"
");";
/** /**
* @brief Requête d'insertion d'une métadonnée. * @brief Requête d'insertion d'une métadonnée.
*/ */
@ -55,11 +34,13 @@ static const char *const database_insert_investigation_sql =
" id," " id,"
" name," " name,"
" root_path," " root_path,"
" created_at" " created_at,"
" updated_at"
")" ")"
"VALUES" "VALUES"
"(" "("
" 1," " ?,"
" ?,"
" ?," " ?,"
" ?," " ?,"
" ?" " ?"
@ -319,6 +300,7 @@ static bool database_insert_all_metadata(
*/ */
static bool database_insert_investigation( static bool database_insert_investigation(
sqlite3 *database, sqlite3 *database,
const char *investigation_uuid,
const char *investigation_name, const char *investigation_name,
const char *investigation_root_path, const char *investigation_root_path,
const char *created_at const char *created_at
@ -329,6 +311,7 @@ static bool database_insert_investigation(
bool success = false; bool success = false;
if (database == NULL || if (database == NULL ||
investigation_uuid == NULL ||
investigation_name == NULL || investigation_name == NULL ||
investigation_root_path == NULL || investigation_root_path == NULL ||
created_at == NULL) created_at == NULL)
@ -357,7 +340,7 @@ static bool database_insert_investigation(
result = sqlite3_bind_text( result = sqlite3_bind_text(
statement, statement,
1, 1,
investigation_name, investigation_uuid,
-1, -1,
SQLITE_TRANSIENT SQLITE_TRANSIENT
); );
@ -370,7 +353,7 @@ static bool database_insert_investigation(
result = sqlite3_bind_text( result = sqlite3_bind_text(
statement, statement,
2, 2,
investigation_root_path, investigation_name,
-1, -1,
SQLITE_TRANSIENT SQLITE_TRANSIENT
); );
@ -383,6 +366,32 @@ static bool database_insert_investigation(
result = sqlite3_bind_text( result = sqlite3_bind_text(
statement, statement,
3, 3,
investigation_root_path,
-1,
SQLITE_TRANSIENT
);
if (result != SQLITE_OK)
{
goto cleanup;
}
result = sqlite3_bind_text(
statement,
4,
created_at,
-1,
SQLITE_TRANSIENT
);
if (result != SQLITE_OK)
{
goto cleanup;
}
result = sqlite3_bind_text(
statement,
5,
created_at, created_at,
-1, -1,
SQLITE_TRANSIENT SQLITE_TRANSIENT
@ -530,18 +539,7 @@ bool database_initialize(
transaction_started = true; transaction_started = true;
if (!database_execute_sql( if (!schema_install_v1(database))
database,
database_create_metadata_table_sql
))
{
goto rollback;
}
if (!database_execute_sql(
database,
database_create_investigation_table_sql
))
{ {
goto rollback; goto rollback;
} }
@ -557,6 +555,7 @@ bool database_initialize(
if (!database_insert_investigation( if (!database_insert_investigation(
database, database,
investigation_uuid,
investigation_name, investigation_name,
investigation_root_path, investigation_root_path,
created_at created_at

91
src/database/schema.c Normal file
View file

@ -0,0 +1,91 @@
/******************************************************************************
* @file schema.c
* @brief Installation du schéma SQLite de Labfy Investigation.
******************************************************************************/
#include "database/schema.h"
#include <glib.h>
/**
* @brief Charge le schéma SQL V1 depuis les ressources intégrées.
*
* @return Une nouvelle chaîne terminée par zéro, à libérer avec g_free(),
* ou NULL en cas d'échec.
*/
static char *schema_load_v1_sql(void)
{
char *schema_sql = NULL;
GError *error = NULL;
if (!g_file_get_contents(
"database/schema_v1.sql",
&schema_sql,
NULL,
&error
))
{
g_warning(
"Impossible de charger database/schema_v1.sql : %s",
error != NULL
? error->message
: "erreur inconnue"
);
g_clear_error(&error);
return NULL;
}
return schema_sql;
}
bool schema_install_v1(
sqlite3 *database
)
{
char *schema_sql = NULL;
char *error_message = NULL;
int result = SQLITE_ERROR;
if (database == NULL)
{
return false;
}
schema_sql = schema_load_v1_sql();
if (schema_sql == NULL)
{
return false;
}
result = sqlite3_exec(
database,
schema_sql,
NULL,
NULL,
&error_message
);
g_free(schema_sql);
if (result != SQLITE_OK)
{
g_warning(
"Impossible d'installer le schéma SQLite V1 : %s",
error_message != NULL
? error_message
: sqlite3_errmsg(database)
);
sqlite3_free(error_message);
return false;
}
sqlite3_free(error_message);
return true;
}

Binary file not shown.

View file

@ -131,6 +131,8 @@ static void test_database_initialize_valid_database(void)
char *investigation_name = NULL; char *investigation_name = NULL;
char *investigation_root_path = NULL; char *investigation_root_path = NULL;
char *investigation_created_at = NULL; char *investigation_created_at = NULL;
char *investigation_id = NULL;
char *investigation_count = NULL;
sqlite3 *database = NULL; sqlite3 *database = NULL;
GError *error = NULL; GError *error = NULL;
@ -214,19 +216,31 @@ static void test_database_initialize_valid_database(void)
investigation_name = test_database_read_single_text( investigation_name = test_database_read_single_text(
database, database,
"SELECT name FROM investigation " "SELECT name FROM investigation "
"WHERE id = 1;" "LIMIT 1;"
); );
investigation_root_path = test_database_read_single_text( investigation_root_path = test_database_read_single_text(
database, database,
"SELECT root_path FROM investigation " "SELECT root_path FROM investigation "
"WHERE id = 1;" "LIMIT 1;"
); );
investigation_created_at = test_database_read_single_text( investigation_created_at = test_database_read_single_text(
database, database,
"SELECT created_at FROM investigation " "SELECT created_at FROM investigation "
"WHERE id = 1;" "LIMIT 1;"
);
investigation_id = test_database_read_single_text(
database,
"SELECT id FROM investigation "
"LIMIT 1;"
);
investigation_count = test_database_read_single_text(
database,
"SELECT CAST(COUNT(*) AS TEXT) "
"FROM investigation;"
); );
assert(strcmp(schema_version, "1") == 0); assert(strcmp(schema_version, "1") == 0);
@ -246,6 +260,11 @@ static void test_database_initialize_valid_database(void)
assert(g_remove(database_path) == 0); assert(g_remove(database_path) == 0);
assert(g_rmdir(temporary_directory) == 0); assert(g_rmdir(temporary_directory) == 0);
assert(investigation_id[0] != '\0');
assert(g_uuid_string_is_valid(investigation_id));
assert(strcmp(investigation_count, "1") == 0);
g_free(investigation_created_at); g_free(investigation_created_at);
g_free(investigation_root_path); g_free(investigation_root_path);
g_free(investigation_name); g_free(investigation_name);
@ -255,6 +274,8 @@ static void test_database_initialize_valid_database(void)
g_free(schema_version); g_free(schema_version);
g_free(database_path); g_free(database_path);
g_free(temporary_directory); g_free(temporary_directory);
g_free(investigation_id);
g_free(investigation_count);
} }
/** /**

Binary file not shown.