288 lines
11 KiB
C
288 lines
11 KiB
C
#include "views/main_window.h"
|
||
#include "views/evidence_identity_ocr_dialog.h"
|
||
#include "widgets/workspace.h"
|
||
#include "models/evidence_record.h"
|
||
#include "models/entity_record.h"
|
||
#include "core/task_manager.h"
|
||
#include <glib/gstdio.h>
|
||
#include <gtk/gtk.h>
|
||
#include <string.h>
|
||
|
||
#define EVIDENCE_ID "11111111-1111-4111-8111-111111111111"
|
||
#define SHA "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
|
||
|
||
typedef struct {
|
||
GtkApplication *application;
|
||
MainWindow *main_window;
|
||
TaskManager *manager;
|
||
EvidenceRecord *evidence;
|
||
char *run_a;
|
||
char *run_b;
|
||
char *fixture_path;
|
||
IdentityOcrRun *review_run;
|
||
GtkWindow *review_dialog;
|
||
guint revisions;
|
||
guint reruns;
|
||
gboolean passed;
|
||
} TestContext;
|
||
|
||
static gboolean session_current(gpointer data)
|
||
{
|
||
return data != NULL;
|
||
}
|
||
|
||
static void review_saved(
|
||
EvidenceIdentityOcrDialogResult *result, gpointer data);
|
||
|
||
static GtkWidget *find_named(GtkWidget *widget, const char *name)
|
||
{
|
||
if (g_strcmp0(gtk_widget_get_name(widget), name) == 0) return widget;
|
||
for (GtkWidget *child = gtk_widget_get_first_child(widget);
|
||
child != NULL; child = gtk_widget_get_next_sibling(child)) {
|
||
GtkWidget *found = find_named(child, name);
|
||
if (found != NULL) return found;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
static char *text_view_text(GtkWidget *widget)
|
||
{
|
||
GtkTextBuffer *buffer =
|
||
gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
|
||
GtkTextIter start;
|
||
GtkTextIter end;
|
||
gtk_text_buffer_get_bounds(buffer, &start, &end);
|
||
return gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
|
||
}
|
||
|
||
static IdentityOcrRun *make_run(
|
||
const char *raw, const char *corrected, guint page)
|
||
{
|
||
IdentityOcrRun *run = identity_ocr_run_new(
|
||
EVIDENCE_ID, SHA, page == 1 ? "identity_card" : "passport",
|
||
page == 1 ? "front" : "identity_page", page, "fra", "none");
|
||
identity_ocr_run_set_outputs(run, "tesseract SPECIMEN", "fra",
|
||
"SPECIMEN", raw, "TSV SPECIMEN");
|
||
identity_ocr_run_set_corrected_transcription(
|
||
run, corrected, "2026-07-29T10:00:00Z");
|
||
identity_ocr_run_set_factual_notes(run,
|
||
page == 1 ? "NOTE WORKSPACE A" : "NOTE WORKSPACE B");
|
||
IdentitySourceBox box = {
|
||
.page = (gint) page, .x = 10, .y = 20,
|
||
.width = 100, .height = 30,
|
||
.image_width = 640, .image_height = 400, .available = TRUE
|
||
};
|
||
IdentityFieldObservation *field = identity_field_observation_new(
|
||
"surname", page == 1 ? "BRUT A" : "BRUT B", 90, &box, 0);
|
||
identity_field_observation_accept(field);
|
||
identity_ocr_run_add_field(run, field);
|
||
return run;
|
||
}
|
||
|
||
static void identity_requested(
|
||
const char *evidence_identifier, gboolean revise,
|
||
const char *run_identifier, gpointer data)
|
||
{
|
||
TestContext *context = data;
|
||
g_assert_cmpstr(evidence_identifier, ==, EVIDENCE_ID);
|
||
if (revise) {
|
||
g_assert_cmpstr(run_identifier, ==, context->run_a);
|
||
context->revisions++;
|
||
GPtrArray *persons = g_ptr_array_new_with_free_func(
|
||
(GDestroyNotify) entity_record_free);
|
||
GError *error = NULL;
|
||
EntityRecord *person = entity_record_new(
|
||
"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "person",
|
||
"PERSONNE SPECIMEN", "PERSONNE SPECIMEN", NULL, 0,
|
||
"2026-07-29T10:00:00Z", "2026-07-29T10:00:00Z",
|
||
ENTITY_STATUS_ACTIVE, &error);
|
||
g_assert_no_error(error);
|
||
g_ptr_array_add(persons, person);
|
||
g_assert_true(evidence_identity_ocr_dialog_present_review(
|
||
main_window_get_window(context->main_window),
|
||
context->fixture_path, persons,
|
||
"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
|
||
context->review_run, session_current,
|
||
review_saved,
|
||
context, NULL, &error));
|
||
g_assert_no_error(error);
|
||
g_ptr_array_unref(persons);
|
||
} else {
|
||
g_assert_null(run_identifier);
|
||
context->reruns++;
|
||
}
|
||
}
|
||
|
||
static GtkWindow *find_review_dialog(void)
|
||
{
|
||
GListModel *windows = gtk_window_get_toplevels();
|
||
for (guint index = 0; index < g_list_model_get_n_items(windows);
|
||
index++) {
|
||
GtkWindow *window = g_list_model_get_item(windows, index);
|
||
gboolean matches = g_strcmp0(gtk_window_get_title(window),
|
||
"Réviser l’analyse OCR") == 0;
|
||
if (matches) return window;
|
||
g_object_unref(window);
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
static gboolean finish_review(gpointer data)
|
||
{
|
||
TestContext *context = data;
|
||
evidence_identity_ocr_dialog_finish_import(
|
||
context->review_dialog, NULL);
|
||
g_clear_object(&context->review_dialog);
|
||
return G_SOURCE_REMOVE;
|
||
}
|
||
|
||
static void review_saved(
|
||
EvidenceIdentityOcrDialogResult *result, gpointer data)
|
||
{
|
||
TestContext *context = data;
|
||
GtkWindow *dialog =
|
||
evidence_identity_ocr_dialog_result_get_dialog(result);
|
||
IdentityOcrRun *run =
|
||
evidence_identity_ocr_dialog_result_steal_run(result);
|
||
GtkWidget *save = find_named(GTK_WIDGET(dialog),
|
||
"evidence-identity-continue-with-ocr");
|
||
GtkWidget *status = find_named(GTK_WIDGET(dialog),
|
||
"evidence-identity-ocr-status");
|
||
g_assert_false(gtk_widget_get_sensitive(save));
|
||
g_assert_nonnull(g_strstr_len(
|
||
gtk_label_get_text(GTK_LABEL(status)), -1,
|
||
"Enregistrement de la révision"));
|
||
g_assert_cmpstr(identity_ocr_run_get_identifier(run),
|
||
==, context->run_a);
|
||
context->review_dialog = g_object_ref(dialog);
|
||
identity_ocr_run_free(run);
|
||
evidence_identity_ocr_dialog_result_free(result);
|
||
g_idle_add(finish_review, context);
|
||
}
|
||
|
||
static gboolean drive(gpointer data)
|
||
{
|
||
TestContext *context = data;
|
||
GtkWidget *root = GTK_WIDGET(
|
||
main_window_get_window(context->main_window));
|
||
GtkWidget *analyze = find_named(root,
|
||
"workspace-analyze-identity");
|
||
GtkWidget *section = find_named(root,
|
||
"workspace-identity-ocr-section");
|
||
GtkDropDown *selector = GTK_DROP_DOWN(find_named(root,
|
||
"workspace-identity-ocr-selector"));
|
||
g_assert_nonnull(analyze);
|
||
g_assert_true(gtk_widget_get_sensitive(analyze));
|
||
g_assert_true(gtk_widget_get_visible(section));
|
||
g_assert_cmpuint(g_list_model_get_n_items(
|
||
gtk_drop_down_get_model(selector)), ==, 2);
|
||
if (context->revisions == 0) {
|
||
g_assert_cmpuint(gtk_drop_down_get_selected(selector), ==, 1);
|
||
char *raw = text_view_text(find_named(root,
|
||
"workspace-identity-ocr-raw"));
|
||
g_assert_cmpstr(raw, ==, "RUN B OCR BRUT");
|
||
g_free(raw);
|
||
gtk_drop_down_set_selected(selector, 0);
|
||
while (g_main_context_iteration(NULL, FALSE)) {}
|
||
raw = text_view_text(find_named(root,
|
||
"workspace-identity-ocr-raw"));
|
||
g_assert_cmpstr(raw, ==, "RUN A OCR BRUT");
|
||
g_free(raw);
|
||
g_signal_emit_by_name(find_named(root,
|
||
"workspace-revise-identity-ocr"), "clicked");
|
||
GtkWindow *dialog = find_review_dialog();
|
||
g_assert_nonnull(dialog);
|
||
GtkWidget *save = find_named(GTK_WIDGET(dialog),
|
||
"evidence-identity-continue-with-ocr");
|
||
GtkWidget *corrected = find_named(GTK_WIDGET(dialog),
|
||
"identity-corrected-transcription");
|
||
gtk_text_buffer_set_text(gtk_text_view_get_buffer(
|
||
GTK_TEXT_VIEW(corrected)), "RUN A RÉVISION SPECIMEN", -1);
|
||
g_signal_emit_by_name(save, "clicked");
|
||
g_signal_emit_by_name(save, "clicked");
|
||
g_object_unref(dialog);
|
||
g_timeout_add(20, drive, context);
|
||
return G_SOURCE_REMOVE;
|
||
}
|
||
GtkWindow *pending_dialog = find_review_dialog();
|
||
if (pending_dialog != NULL) {
|
||
g_object_unref(pending_dialog);
|
||
g_timeout_add(20, drive, context);
|
||
return G_SOURCE_REMOVE;
|
||
}
|
||
g_signal_emit_by_name(find_named(root,
|
||
"workspace-rerun-identity-ocr"), "clicked");
|
||
g_assert_cmpuint(context->revisions, ==, 1);
|
||
g_assert_cmpuint(context->reruns, ==, 1);
|
||
context->passed = TRUE;
|
||
g_application_quit(G_APPLICATION(context->application));
|
||
return G_SOURCE_REMOVE;
|
||
}
|
||
|
||
static void activate(GtkApplication *application, gpointer data)
|
||
{
|
||
TestContext *context = data;
|
||
GError *error = NULL;
|
||
context->main_window = main_window_new(application, context->manager);
|
||
main_window_set_identity_ocr_callback(
|
||
context->main_window, identity_requested, context);
|
||
context->evidence = evidence_record_new(
|
||
EVIDENCE_ID, "IDENTITE-SPECIMEN.jpeg",
|
||
"IDENTITE-SPECIMEN.jpeg", "01_Preuves_Originales/specimen.jpeg",
|
||
"document", 32, SHA, "2026-07-29T10:00:00Z", NULL,
|
||
NULL, NULL, EVIDENCE_INTEGRITY_STATUS_VALID, &error);
|
||
g_assert_no_error(error);
|
||
main_window_set_selected_evidence(
|
||
context->main_window, context->evidence);
|
||
GPtrArray *records = g_ptr_array_new_with_free_func(
|
||
(GDestroyNotify) workspace_identity_ocr_record_free);
|
||
IdentityOcrRun *run_a = make_run(
|
||
"RUN A OCR BRUT", "RUN A CORRIGÉ", 1);
|
||
IdentityOcrRun *run_b = make_run(
|
||
"RUN B OCR BRUT", "RUN B CORRIGÉ", 2);
|
||
context->run_a = g_strdup(identity_ocr_run_get_identifier(run_a));
|
||
context->review_run = identity_ocr_run_copy(run_a);
|
||
context->run_b = g_strdup(identity_ocr_run_get_identifier(run_b));
|
||
g_ptr_array_add(records, workspace_identity_ocr_record_new(
|
||
run_a, "PERSONNE A SPECIMEN", "2026-07-29T10:00:00Z",
|
||
"OCR/A.txt", SHA, "OCR/A.tsv", SHA));
|
||
g_ptr_array_add(records, workspace_identity_ocr_record_new(
|
||
run_b, "PERSONNE B SPECIMEN", "2026-07-29T11:00:00Z",
|
||
"OCR/B.txt", SHA, "OCR/B.tsv", SHA));
|
||
main_window_set_identity_ocr_runs(context->main_window, records);
|
||
main_window_present(context->main_window);
|
||
g_idle_add(drive, context);
|
||
}
|
||
|
||
int main(int argc, char **argv)
|
||
{
|
||
if (!gtk_init_check()) {
|
||
g_print("SKIP: aucun affichage GTK disponible.\n");
|
||
return 0;
|
||
}
|
||
TestContext context = {0};
|
||
context.fixture_path = g_strdup_printf(
|
||
"%s/labfy-workspace-identity-%u.jpeg",
|
||
g_get_tmp_dir(), g_random_int());
|
||
g_assert_true(g_file_set_contents(context.fixture_path,
|
||
"SPECIMEN JPEG", -1, NULL));
|
||
context.manager = task_manager_new();
|
||
context.application = gtk_application_new(
|
||
"com.labfytools.test.workspace.identity",
|
||
G_APPLICATION_NON_UNIQUE);
|
||
g_signal_connect(context.application, "activate",
|
||
G_CALLBACK(activate), &context);
|
||
int status = g_application_run(
|
||
G_APPLICATION(context.application), argc, argv);
|
||
g_assert_true(context.passed);
|
||
evidence_record_free(context.evidence);
|
||
main_window_free(context.main_window);
|
||
task_manager_free(context.manager);
|
||
g_object_unref(context.application);
|
||
g_free(context.run_a);
|
||
g_free(context.run_b);
|
||
identity_ocr_run_free(context.review_run);
|
||
g_remove(context.fixture_path);
|
||
g_free(context.fixture_path);
|
||
return status;
|
||
}
|