Premiere commit - Omika

This commit is contained in:
2026-10-23 18:46:50 +02:00
commit 8ea76c1b24
2155 changed files with 984301 additions and 0 deletions
+242
View File
@@ -0,0 +1,242 @@
// ============================================================
// EXÉCUTEUR DE TESTS MINIMAL (contournement du testhost bloqué par le bac à sable)
//
// Charge l'assembly de tests par réflexion et exécute les [Fact] / [Theory]
// en respectant Skip (comme le runner xunit). AUCUNE référence xunit à la
// compilation : les attributs sont reconnus par leur nom complet.
//
// USAGE : runner [--filter sous-chaine] [--list]
// ============================================================
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using System.Threading.Tasks;
string assemblyPath = Path.Combine(AppContext.BaseDirectory, "Omika.Tests.dll");
string? filtre = null;
bool listOnly = false;
for (int i = 0; i < args.Length; i++)
{
if (args[i] == "--filter" && i + 1 < args.Length)
{
filtre = args[++i];
}
else if (args[i] == "--list")
{
listOnly = true;
}
}
if (!File.Exists(assemblyPath))
{
Console.Error.WriteLine($"Assembly de tests introuvable : {assemblyPath}");
return 2;
}
Assembly tests = AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath);
int reussis = 0;
int echoues = 0;
int ignores = 0;
var echecs = new List<string>();
foreach (Type type in tests.GetTypes().OrderBy(t => t.FullName, StringComparer.Ordinal))
{
if (!type.IsClass || type.IsAbstract)
{
continue;
}
if (filtre is not null
&& !(type.FullName?.Contains(filtre, StringComparison.OrdinalIgnoreCase) ?? false))
{
continue;
}
MethodInfo[] methodes = type.GetMethods(BindingFlags.Public | BindingFlags.Instance)
.OrderBy(m => m.Name, StringComparer.Ordinal)
.ToArray();
if (!methodes.Any(m => EstTest(m)))
{
continue;
}
foreach (MethodInfo methode in methodes)
{
if (!EstTest(methode))
{
continue;
}
(bool estTest, string? raisonSkip) = DetailsTest(methode);
if (!estTest)
{
continue;
}
string nom = $"{type.FullName}.{methode.Name}";
if (listOnly)
{
Console.WriteLine(nom);
continue;
}
if (!string.IsNullOrWhiteSpace(raisonSkip))
{
ignores++;
continue;
}
foreach (object[]? arguments in ArgumentsTheorie(methode))
{
string etiquette = arguments is { Length: > 0 }
? $"{nom}({string.Join(", ", arguments.Select(a => a?.ToString() ?? "null"))})"
: nom;
try
{
object? instance = Activator.CreateInstance(type);
try
{
object? resultat = methode.Invoke(instance, arguments);
if (resultat is Task tache)
{
tache.GetAwaiter().GetResult();
}
}
finally
{
(instance as IDisposable)?.Dispose();
}
reussis++;
}
catch (Exception ex)
{
echoues++;
Exception reelle = ex is TargetInvocationException { InnerException: not null } invocation
? invocation.InnerException!
: ex;
string message = $"{etiquette} :: {reelle.GetType().Name} : {reelle.Message}";
if (reelle.Message.Contains("SKIP", StringComparison.Ordinal))
{
ignores++;
echoues--;
continue;
}
echecs.Add(message);
Console.WriteLine($"ECHEC {message}");
}
}
}
}
if (!listOnly)
{
Console.WriteLine();
Console.WriteLine($"Résultat : {reussis} réussis, {echoues} échoués, {ignores} ignorés.");
if (echecs.Count > 0)
{
Console.WriteLine();
Console.WriteLine("--- ÉCHECS ---");
foreach (string echec in echecs)
{
Console.WriteLine(echec);
}
}
}
return echoues == 0 ? 0 : 1;
static bool EstTest(MethodInfo methode) => DetailsTest(methode).EstTest;
static (bool EstTest, string? RaisonSkip) DetailsTest(MethodInfo methode)
{
foreach (object attribut in methode.GetCustomAttributes(inherit: true))
{
string? nom = attribut.GetType().FullName;
if (nom is "Xunit.FactAttribute" or "Xunit.TheoryAttribute")
{
string? skip = attribut.GetType().GetProperty("Skip")?.GetValue(attribut) as string;
return (true, skip);
}
}
return (false, null);
}
static IEnumerable<object[]?> ArgumentsTheorie(MethodInfo methode)
{
bool theorie = methode.GetCustomAttributes(inherit: true)
.Any(a => a.GetType().FullName == "Xunit.TheoryAttribute");
if (!theorie)
{
yield return null;
yield break;
}
bool auMoinsUn = false;
foreach (object attribut in methode.GetCustomAttributes(inherit: true))
{
// InlineData, MemberData et ClassData partagent la même entrée publique :
// DataAttribute.GetData(MethodInfo) énumère les lignes du cas de test.
MethodInfo? getData = attribut.GetType().GetMethod("GetData", [typeof(MethodInfo)]);
if (getData is null || getData.ReturnType == typeof(void))
{
continue;
}
object? lignesBrutes;
try
{
lignesBrutes = getData.Invoke(attribut, [methode]);
}
catch
{
continue;
}
if (lignesBrutes is not IEnumerable lignes)
{
continue;
}
foreach (object? ligne in lignes)
{
auMoinsUn = true;
if (ligne is object?[] tableau)
{
yield return tableau;
}
else if (methode.GetParameters().Length == 1)
{
// `[InlineData(null)]` : Roslyn passe la tableau params entier à
// null, xunit le relit comme UN argument nul (un seul paramètre).
yield return [ligne];
}
else
{
yield return methode.GetParameters().Select(p => ValeurParDefaut(p.ParameterType)).ToArray();
}
}
}
if (!auMoinsUn)
{
// Théorie sans source de données exploitable : exécutée avec ses valeurs
// par défaut, uniquement pour ne pas la perdre du total.
yield return methode.GetParameters().Select(p => ValeurParDefaut(p.ParameterType)).ToArray();
}
}
static object? ValeurParDefaut(Type type)
=> type.IsValueType ? Activator.CreateInstance(type) : null;
@@ -0,0 +1,8 @@
<!DOCTYPE html><html><head><meta charset="utf-8"><title>Signature EMAIL_ENVOI_1</title></head><body><p>--- corps du courriel ---</p><div><div><br></div>
</div>
</body></html>
@@ -0,0 +1 @@
<!DOCTYPE html><html><head><meta charset="utf-8"><title>Signature EMAIL_ENVOI_Perso_0</title></head><body><p>--- corps du courriel ---</p><p><font face="Segoe UI" size="3">Equipe Omika </font></p><p><strong><a href="mailto:omika.tech@applilogik.fr"><font color="#522a9b" face="Segoe UI">omika.tech@applilogik.fr</font></a></strong></p><p><font face="Segoe UI">07 61 00 19 21<p align="left"><br></p></font></p><p></p><strong><p><br></p></strong><p><strong><br></strong></p><p><strong><br></strong></p></body></html>
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
<!DOCTYPE html><html><head><meta charset="utf-8"><title>Signature EMAIL_ENVOI_Perso_0</title></head><body><p>--- corps du courriel ---</p>Signature : <br><br>Salvador Alexandre <br><font style="background-color: rgb(255, 255, 0);">Test applilogik Omika</font></body></html>
File diff suppressed because one or more lines are too long
Binary file not shown.