labfy-investigation/tests/fake_document_tool.c
fy59 d65f9559e6 chore(checkpoint): preserve local investigation workbench
Preserve the local graph-first investigation stack through macro V1.

Include reviewed source, tests, contracts, documentation and synthetic assets.

Retain the standalone financial V21 test foundation without runtime migration.

Runtime remains V20; operational JobStore remains V3.

Local experimental checkpoint, not a stable release.
2026-09-27 08:34:46 +02:00

237 lines
7.8 KiB
C

/******************************************************************************
* @file fake_document_tool.c
* @brief Faux outil documentaire synthétique, sans shell.
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <poll.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
static int has_argument(int argc, char **argv, const char *value)
{
for (int index = 1; index < argc; index++)
if (strcmp(argv[index], value) == 0)
return 1;
return 0;
}
static const char *find_pdf_path(int argc, char **argv)
{
for (int index = 1; index < argc; index++)
if (strstr(argv[index], ".pdf") != NULL)
return argv[index];
return "";
}
static long argument_long(
int argc,
char **argv,
const char *name,
long fallback
)
{
for (int index = 1; index + 1 < argc; index++)
if (strcmp(argv[index], name) == 0)
return strtol(argv[index + 1], NULL, 10);
return fallback;
}
static const char *argument_value(int argc, char **argv, const char *name)
{
for (int index = 1; index + 1 < argc; index++)
if (strcmp(argv[index], name) == 0) return argv[index + 1];
return NULL;
}
static void write_repeated(FILE *stream, char value, long count)
{
char block[1024];
memset(block, value, sizeof(block));
while (count > 0)
{
size_t amount = (size_t) (count > (long) sizeof(block)
? (long) sizeof(block) : count);
if (fwrite(block, 1, amount, stream) != amount)
return;
fflush(stream);
count -= (long) amount;
}
}
int main(int argc, char **argv)
{
if (has_argument(argc, argv, "--inspect-runner"))
{
int inherited_fd = (int) argument_long(argc, argv, "--fd", -1);
char byte = 0;
int readable = inherited_fd >= 0 && read(inherited_fd, &byte, 1) == 1;
int stdout_flags = fcntl(STDOUT_FILENO, F_GETFL);
int stderr_flags = fcntl(STDERR_FILENO, F_GETFL);
printf("inherited=%d stdout_nonblocking=%d stderr_nonblocking=%d\n",
readable, (stdout_flags & O_NONBLOCK) != 0,
(stderr_flags & O_NONBLOCK) != 0);
return 0;
}
if (has_argument(argc, argv, "--binary"))
{
const unsigned char value[] = {'A', 0, 0xff, 'B'};
return fwrite(value, 1, sizeof(value), stdout) == sizeof(value) ? 0 : 3;
}
if (has_argument(argc, argv, "--signal"))
{
raise(SIGUSR1);
return 4;
}
if (has_argument(argc, argv, "--sleep"))
{
const char *started = argument_value(argc, argv, "--started-file");
if (started != NULL) {
FILE *marker = fopen(started, "wb");
if (marker == NULL) return 8;
fputs("started\n", marker); fclose(marker);
}
if (has_argument(argc, argv, "--ignore-term")) signal(SIGTERM, SIG_IGN);
sleep(10);
return 0;
}
if (has_argument(argc, argv, "--descendant-pipe"))
{
pid_t child = fork();
if (child < 0) return 5;
if (child == 0) { sleep(10); _exit(0); }
puts("parent-finished");
return 0;
}
if (has_argument(argc, argv, "--list-langs"))
{
puts("List of available languages in synthetic fixture (2):");
puts("eng");
puts("fra");
return 0;
}
if (has_argument(argc, argv, "--emit"))
{
long stdout_size = argument_long(
argc, argv, "--stdout-size", 0);
long stderr_size = argument_long(
argc, argv, "--stderr-size", 0);
long chunks = argument_long(argc, argv, "--chunks", 1);
int exit_status = (int) argument_long(
argc, argv, "--exit-status", 0);
if (chunks < 1)
chunks = 1;
for (long index = 0; index < chunks; index++)
{
write_repeated(stdout, 'O', stdout_size / chunks);
write_repeated(stderr, 'E', stderr_size / chunks);
if (has_argument(argc, argv, "--slow"))
(void) poll(NULL, 0, 20);
}
return exit_status;
}
if (has_argument(argc, argv, "-ver"))
{
puts("13.00");
return 0;
}
if (has_argument(argc, argv, "--version"))
{
puts("tesseract 5.0.0-synthetic");
return 0;
}
if (has_argument(argc, argv, "-j"))
{
if (strstr(argv[argc - 1], "slow") != NULL)
sleep(2);
if (strstr(argv[argc - 1], "large") != NULL)
{
fputs("[{\"File:MIMEType\":\"image/png\",\"Padding\":\"", stdout);
write_repeated(stdout, 'X', 8192);
return 0;
}
puts("[{\"File:MIMEType\":\"image/png\","
"\"File:FileSize\":42,\"EXIF:ImageWidth\":10,"
"\"EXIF:GPSLatitude\":48.5,\"EXIF:GPSLongitude\":2.2,"
"\"EXIF:SyntheticBoolean\":true}]");
return 0;
}
if (has_argument(argc, argv, "-enc"))
{
const char *path = find_pdf_path(argc, argv);
if (strstr(path, "slow-text") != NULL)
sleep(2);
if (strstr(path, "native") != NULL)
{
puts("Texte synthétique suffisamment long pour être considéré "
"comme exploitable dans cette fixture.\fDeuxième page.");
}
return 0;
}
if (has_argument(argc, argv, "-singlefile"))
{
const char *pdf_path = find_pdf_path(argc, argv);
if (strstr(pdf_path, "slow-render") != NULL)
sleep(2);
if (strstr(pdf_path, "slow-page-2") != NULL &&
strcmp(argv[2], "2") == 0)
sleep(2);
const char *prefix = argv[argc - 1];
char path[4096];
if (snprintf(path, sizeof(path), "%s.png", prefix) < 0)
return 2;
FILE *file = fopen(path, "wb");
if (file == NULL)
return 3;
fputs("synthetic-image", file);
fclose(file);
return 0;
}
if (has_argument(argc, argv, "stdout"))
{
if (strstr(argv[1], "sleep") != NULL ||
strstr(argv[1], "slow-ocr") != NULL)
sleep(2);
if (strstr(argv[1], "large") != NULL)
{
write_repeated(stdout, 'T', 8192);
return 0;
}
if (getenv("LABFY_FAKE_IDENTITY_OCR") != NULL &&
has_argument(argc, argv, "tsv"))
{
puts("level\tpage_num\tblock_num\tpar_num\tline_num\tword_num\t"
"left\ttop\twidth\theight\tconf\ttext");
puts("5\t1\t1\t1\t1\t1\t10\t10\t80\t20\t95\tNOM");
puts("5\t1\t1\t1\t1\t2\t100\t10\t120\t20\t94\tSPECIMEN");
puts("5\t1\t1\t1\t2\t1\t10\t40\t100\t20\t93\tPRENOM");
puts("5\t1\t1\t1\t2\t2\t120\t40\t100\t20\t92\tALICE");
puts("5\t1\t1\t1\t3\t1\t10\t70\t100\t20\t91\tNUMERO");
puts("5\t1\t1\t1\t3\t2\t120\t70\t100\t20\t90\tABC123");
puts("5\t1\t1\t1\t4\t1\t10\t100\t110\t20\t89\tNATIONALITE");
puts("5\t1\t1\t1\t4\t2\t130\t100\t120\t20\t88\tFRANCAIS");
}
else if (getenv("LABFY_FAKE_IDENTITY_OCR") != NULL &&
strstr(argv[1], "page-2") != NULL)
puts("NOM : PAGEDEUX\nNOM : SPECIMEN\nNOM : PAGE2");
else if (getenv("LABFY_FAKE_IDENTITY_OCR") != NULL)
puts("NOM : SPECIMEN\nNOM : ALICE\nNOM : ABC123\n"
"NATIONALITÉ : FRANCAIS");
else if (strstr(argv[1], "page-2") != NULL)
puts("Texte OCR synthétique page deux.");
else
puts("Texte OCR synthétique page une.");
return 0;
}
const char *path = find_pdf_path(argc, argv);
if (strstr(path, "slow-info") != NULL)
sleep(2);
if (strstr(path, "encrypted") != NULL)
puts("Pages: 2\nEncrypted: yes");
else
puts("Pages: 2\nEncrypted: no");
return 0;
}