208 lines
6.9 KiB
C#
208 lines
6.9 KiB
C#
using System.Text.Json;
|
|
using Omika.Core.Compatibility;
|
|
using Omika.Data.Connection;
|
|
using Omika.Data.HfSql.Connection;
|
|
using Omika.Data.SchemaDetection;
|
|
|
|
namespace Omika.Tests.Connection;
|
|
|
|
|
|
/// <summary>
|
|
/// Tests d'intégration OLE DB HFSQL réels.
|
|
///
|
|
/// Ces tests nécessitent un serveur HFSQL accessible et le provider OLE DB
|
|
/// <c>PCSOFT.HFSQL</c> installé. Ils sont ignorés automatiquement si la
|
|
/// configuration locale n'est pas disponible ou si le serveur est injoignable.
|
|
///
|
|
/// Aucun secret n'est affiché : les assertions portent uniquement sur les
|
|
/// modes d'accès observés.
|
|
/// </summary>
|
|
public class HfSqlOleDbIntegrationTests
|
|
{
|
|
private const string ConfigPath = @"D:\Avalonia\Omika\config\hfsql-test.local.json";
|
|
|
|
private sealed class TestConfig
|
|
{
|
|
public int Port { get; set; }
|
|
public string Server { get; set; } = "";
|
|
public string ProtectionPlusSecret { get; set; } = "";
|
|
public FilePasswordsConfig FilePasswords { get; set; } = new();
|
|
public DatabaseConfig Batik { get; set; } = new();
|
|
public DatabaseConfig Omika { get; set; } = new();
|
|
}
|
|
|
|
private sealed class FilePasswordsConfig
|
|
{
|
|
public string? ProtectionStd { get; set; }
|
|
public string? ProtectionPlus { get; set; }
|
|
}
|
|
|
|
private sealed class DatabaseConfig
|
|
{
|
|
public string Credential { get; set; } = "";
|
|
public string Database { get; set; } = "";
|
|
public string User { get; set; } = "";
|
|
public string? OriginalDatabaseName { get; set; }
|
|
}
|
|
|
|
private static TestConfig? LoadConfig()
|
|
{
|
|
if (!File.Exists(ConfigPath))
|
|
return null;
|
|
|
|
try
|
|
{
|
|
var json = File.ReadAllText(ConfigPath);
|
|
return JsonSerializer.Deserialize<TestConfig>(
|
|
json,
|
|
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private static HfSqlConnectionOptions BuildOptions(TestConfig config, DatabaseConfig db)
|
|
{
|
|
return new HfSqlConnectionOptions
|
|
{
|
|
Server = config.Server,
|
|
Port = config.Port,
|
|
Database = db.Database,
|
|
User = db.User,
|
|
Credential = db.Credential,
|
|
FilePasswords = new HfSqlFilePasswordOptions
|
|
{
|
|
ProtectionStd = config.FilePasswords.ProtectionStd,
|
|
ProtectionPlus = config.FilePasswords.ProtectionPlus
|
|
}
|
|
};
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ResolveAsync_Batik_Client_IsAccessible()
|
|
{
|
|
var config = LoadConfig();
|
|
if (config is null)
|
|
return; // config absente : test ignoré
|
|
|
|
var options = BuildOptions(config, config.Batik);
|
|
var factory = new HfSqlOleDbConnectionFactory();
|
|
var resolver = new HfSqlFileAccessResolver(factory, options);
|
|
|
|
var files = new List<HfSqlFileAccessProfile>
|
|
{
|
|
new() { LogicalFile = "Client", ExpectedGroup = "ProtectionStd" }
|
|
};
|
|
|
|
try
|
|
{
|
|
var result = await resolver.ResolveAsync(files);
|
|
Assert.True(result["Client"].IsAccessible,
|
|
$"Client Batik doit être accessible (mode observé : {result["Client"].ObservedAccess})");
|
|
}
|
|
catch (Exception ex) when (IsServerUnavailable(ex))
|
|
{
|
|
return; // serveur injoignable : test ignoré
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ResolveAsync_Omika_Client_IsAccessible()
|
|
{
|
|
var config = LoadConfig();
|
|
if (config is null)
|
|
return;
|
|
|
|
var options = BuildOptions(config, config.Omika);
|
|
var factory = new HfSqlOleDbConnectionFactory();
|
|
var resolver = new HfSqlFileAccessResolver(factory, options);
|
|
|
|
var files = new List<HfSqlFileAccessProfile>
|
|
{
|
|
new() { LogicalFile = "Client", ExpectedGroup = "ProtectionStd" }
|
|
};
|
|
|
|
try
|
|
{
|
|
var result = await resolver.ResolveAsync(files);
|
|
Assert.True(result["Client"].IsAccessible,
|
|
$"Client Omika doit être accessible (mode observé : {result["Client"].ObservedAccess})");
|
|
}
|
|
catch (Exception ex) when (IsServerUnavailable(ex))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
// --- Détection de schéma réelle (BATIK_TEST / OMIKA_TEST) -----------------
|
|
|
|
[Fact]
|
|
public async Task DetectAsync_BatikTest_ReturnsBatik()
|
|
{
|
|
var config = LoadConfig();
|
|
if (config is null)
|
|
return; // config absente : test ignoré
|
|
|
|
var options = BuildOptions(config, config.Batik);
|
|
var factory = new HfSqlOleDbConnectionFactory();
|
|
await using var connection = new HfSqlOleDbConnection(factory, options);
|
|
var detector = new DatabaseSchemaDetector(connection);
|
|
|
|
try
|
|
{
|
|
var result = await detector.DetectAsync();
|
|
Assert.True(result.IsSuccess,
|
|
$"La détection Batik a échoué : {string.Join("; ", result.Errors)}");
|
|
Assert.Equal(DatabaseSchemaVersion.Batik, result.Value);
|
|
}
|
|
catch (Exception ex) when (IsServerUnavailable(ex))
|
|
{
|
|
return; // serveur injoignable : test ignoré
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public async Task DetectAsync_OmikaTest_ReturnsOmika()
|
|
{
|
|
var config = LoadConfig();
|
|
if (config is null)
|
|
return; // config absente : test ignoré
|
|
|
|
var options = BuildOptions(config, config.Omika);
|
|
var factory = new HfSqlOleDbConnectionFactory();
|
|
await using var connection = new HfSqlOleDbConnection(factory, options);
|
|
var detector = new DatabaseSchemaDetector(connection);
|
|
|
|
try
|
|
{
|
|
var result = await detector.DetectAsync();
|
|
Assert.True(result.IsSuccess,
|
|
$"La détection Omika a échoué : {string.Join("; ", result.Errors)}");
|
|
Assert.Equal(DatabaseSchemaVersion.Omika, result.Value);
|
|
}
|
|
catch (Exception ex) when (IsServerUnavailable(ex))
|
|
{
|
|
return; // serveur injoignable : test ignoré
|
|
}
|
|
}
|
|
|
|
private static bool IsServerUnavailable(Exception ex)
|
|
{
|
|
// Le provider OLE DB peut lever des exceptions natives au teardown.
|
|
// On ignore les erreurs de connexion (serveur injoignable) mais on
|
|
// propage les erreurs de logique.
|
|
var message = ex.Message;
|
|
return message.Contains("provider", StringComparison.OrdinalIgnoreCase)
|
|
|| message.Contains("serveur", StringComparison.OrdinalIgnoreCase)
|
|
|| message.Contains("server", StringComparison.OrdinalIgnoreCase)
|
|
|| message.Contains("connexion", StringComparison.OrdinalIgnoreCase)
|
|
|| message.Contains("connection", StringComparison.OrdinalIgnoreCase)
|
|
|| message.Contains("E_FAIL", StringComparison.OrdinalIgnoreCase)
|
|
|| message.Contains("0x80004005", StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
}
|
|
|
|
|