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
+276
View File
@@ -0,0 +1,276 @@
using Omika.HfSqlProbe;
namespace Omika.Tests.Tools;
/// <summary>
/// Tests unitaires du probe HFSQL ODBC — appelle les VRAIES classes
/// du projet <c>Omika.HfSqlProbe</c>. Aucune connexion réelle.
/// </summary>
public class HfSqlProbeTests
{
// =========================================================================
// SqlIdentifierValidator
// =========================================================================
[Theory]
[InlineData("Client")]
[InlineData("ProbeTest")]
[InlineData("CL_PKID")]
[InlineData("Marker")]
[InlineData("a")]
[InlineData("A")]
[InlineData("_")]
[InlineData("_test")]
[InlineData("Client123")]
[InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_____")]
public void ValidateSqlIdentifier_ValidNames_Accepted(string name)
{
Assert.True(SqlIdentifierValidator.IsValid(name),
$"Valid identifier rejected: '{name}'");
_ = SqlIdentifierValidator.Validate(name);
}
[Theory]
[InlineData("")]
[InlineData(" ")]
[InlineData("123Client")] // starts with digit
[InlineData("Client;DROP TABLE")]
[InlineData("Client--")]
[InlineData("Client/*x*/")]
[InlineData("Client x")]
[InlineData("Client\t")]
[InlineData("Client\n")]
[InlineData("Client\r")]
[InlineData("Client\r\n")]
[InlineData("Client\nDROP")]
[InlineData("Client'")]
[InlineData("Client\"")]
[InlineData("[Client]")]
[InlineData("`Client`")]
[InlineData("Client.Name")]
[InlineData("Client\\Name")]
[InlineData("C lien")]
[InlineData("C;DROP")]
public void ValidateSqlIdentifier_InvalidNames_Rejected(string name)
{
Assert.False(SqlIdentifierValidator.IsValid(name),
$"Invalid identifier accepted: '{name}'");
Assert.Throws<ArgumentException>(() => SqlIdentifierValidator.Validate(name));
}
// =========================================================================
// ConnectionStringRedactor
// =========================================================================
[Fact]
public void Redact_RemovesPWD()
{
string input = "DSN=Test;PWD=MySecret123;UID=admin;Database=TestDB";
string result = ConnectionStringRedactor.Redact(input);
Assert.DoesNotContain("MySecret123", result);
Assert.Contains("PWD=***", result);
}
[Fact]
public void Redact_RemovesUID()
{
string input = "DSN=Test;UID=admin123;PWD=pass";
string result = ConnectionStringRedactor.Redact(input);
Assert.DoesNotContain("admin123", result);
Assert.Contains("UID=***", result);
}
[Fact]
public void Redact_RemovesPasswordKey()
{
string input = "DSN=Test;Password=SuperSecret;Server=localhost";
string result = ConnectionStringRedactor.Redact(input);
Assert.DoesNotContain("SuperSecret", result);
}
[Fact]
public void Redact_PreservesNonCredentials()
{
string input = "DSN=HFSQL_Test;Server=localhost;Database=TestDB";
string result = ConnectionStringRedactor.Redact(input);
Assert.Contains("DSN=HFSQL_Test", result);
Assert.Contains("Server=localhost", result);
Assert.Contains("Database=TestDB", result);
}
[Fact]
public void Redact_CaseInsensitive()
{
string input = "DSN=X;pwd=secret123";
string result = ConnectionStringRedactor.Redact(input);
Assert.DoesNotContain("secret123", result);
Assert.Contains("PWD=***", result);
}
[Fact]
public void Redact_SpecialCharsInPassword()
{
string input = "DSN=X;Password=aB12!@#$";
string result = ConnectionStringRedactor.Redact(input);
Assert.DoesNotContain("aB12!@#$", result);
}
[Fact]
public void Redact_EmptyPassword_Works()
{
string input = "DSN=X;PWD=;Server=Y";
string result = ConnectionStringRedactor.Redact(input);
Assert.Contains("PWD=***", result);
}
// =========================================================================
// ProbeArgumentParser
// =========================================================================
[Theory]
[InlineData("capabilities")]
[InlineData("CAPABILITIES")]
[InlineData("Capabilities")]
public void NormalizeCommand_RecognizesCapabilities(string cmd)
{
Assert.Equal("capabilities", ProbeArgumentParser.NormalizeCommand([cmd]));
}
[Fact]
public void NormalizeCommand_EmptyArgs_ReturnsEmpty()
{
Assert.Equal("", ProbeArgumentParser.NormalizeCommand([]));
}
[Theory]
[InlineData("")]
[InlineData("unknown")]
public void IsValidCommand_RejectsUnknown(string cmd)
{
Assert.False(ProbeArgumentParser.IsValidCommand(cmd));
}
[Theory]
[InlineData("capabilities")]
[InlineData("transaction")]
[InlineData("returning")]
[InlineData("omika-guid")]
[InlineData("--help")]
public void IsValidCommand_AcceptsKnown(string cmd)
{
Assert.True(ProbeArgumentParser.IsValidCommand(cmd));
}
[Fact]
public void Parse_ParsesConnectionStringOption()
{
var options = ProbeArgumentParser.Parse(
["--connection-string", "DSN=Test;UID=u;PWD=p"]);
Assert.Equal("DSN=Test;UID=u;PWD=p", options.ConnectionString);
}
[Fact]
public void Parse_ParsesAllowWriteProbeFlag()
{
var options = ProbeArgumentParser.Parse(["--allow-write-probe"]);
Assert.True(options.AllowWriteProbe);
}
[Fact]
public void Parse_ParsesTableAndIdColumn()
{
var options = ProbeArgumentParser.Parse(
["--table", "MyTable", "--id-column", "PKID"]);
Assert.Equal("MyTable", options.Table);
Assert.Equal("PKID", options.IdColumn);
}
[Fact]
public void Parse_ParsesSchema()
{
var options = ProbeArgumentParser.Parse(["--schema", "batik"]);
Assert.Equal("batik", options.Schema);
}
[Fact]
public void Parse_DoesNotSetAllowWriteProbeByDefault()
{
var options = ProbeArgumentParser.Parse([]);
Assert.False(options.AllowWriteProbe);
}
// =========================================================================
// Write gate
// =========================================================================
[Theory]
[InlineData("transaction")]
[InlineData("returning")]
public void IsWriteCommand_WriteCommandsRequireGate(string cmd)
{
Assert.True(ProbeArgumentParser.IsWriteCommand(cmd),
$"'{cmd}' must require --allow-write-probe.");
}
[Theory]
[InlineData("capabilities")]
[InlineData("")]
[InlineData("unknown")]
public void IsWriteCommand_ReadCommandsDoNotRequireGate(string cmd)
{
Assert.False(ProbeArgumentParser.IsWriteCommand(cmd));
}
// =========================================================================
// ProbeSqlBuilder
// =========================================================================
[Fact]
public void SqlBuilder_InsertReturning_ValidatesAllIdentifiers()
{
string sql = ProbeSqlBuilder.BuildInsertReturning("TestTable", "TestPKID", "Marker");
Assert.Contains("INSERT INTO TestTable", sql);
Assert.Contains("VALUES (?)", sql);
Assert.Contains("RETURNING TestPKID", sql);
Assert.DoesNotContain("'", sql);
}
[Fact]
public void SqlBuilder_RejectsInvalidTable()
{
var ex = Assert.Throws<ArgumentException>(
() => ProbeSqlBuilder.BuildInsertReturning("Bad;DROP", "PKID", "Marker"));
Assert.Contains("Bad;DROP", ex.Message);
}
[Fact]
public void SqlBuilder_RejectsInvalidMarkerColumn()
{
Assert.Throws<ArgumentException>(
() => ProbeSqlBuilder.BuildInsertMarker("Table", "x y"));
}
[Fact]
public void SqlBuilder_RejectsInvalidIdColumn()
{
Assert.Throws<ArgumentException>(
() => ProbeSqlBuilder.BuildInsertReturning("Table", "PKID--", "M"));
}
[Fact]
public void SqlBuilder_CountByMarker_Parameterized()
{
string sql = ProbeSqlBuilder.BuildCountByMarker("TestTable", "Marker");
Assert.Contains("SELECT COUNT(*)", sql);
Assert.Contains("WHERE Marker = ?", sql);
Assert.DoesNotContain("'", sql);
}
[Fact]
public void SqlBuilder_InsertMarker_Parameterized()
{
string sql = ProbeSqlBuilder.BuildInsertMarker("T", "Col");
Assert.Contains("INSERT INTO T (Col)", sql);
Assert.Contains("VALUES (?)", sql);
}
}