Files
MBN_STOCK_WEBVIEW/tests/MBN_STOCK_WEBVIEW.Infrastructure.Tests/LegacyIniDatabaseOptionsLoaderTests.cs

227 lines
8.1 KiB
C#

using System.Text;
using MBN_STOCK_WEBVIEW.Infrastructure;
using MMoneyCoderSharp.Data;
namespace MBN_STOCK_WEBVIEW.Infrastructure.Tests;
public sealed class LegacyIniDatabaseOptionsLoaderTests
{
private const string IntegrationPathEnvironmentVariable =
"MBN_STOCK_LEGACY_INI_INTEGRATION_PATH";
[Fact]
public void Load_Utf8LegacyFile_MapsBothProvidersAndKeepsLastValue()
{
using var file = TemporaryLegacyIni.Create(
Encoding.UTF8.GetBytes(
"""
[Oracle]
//ConnectionName=ignored.invalid:1/IGNORED
ConnectionName=oracle.dev.invalid:1522/DEVORA
ID=old-user
ID=oracle-user
Pass=oracle=password
[Maria]
ConnectionName=maria.dev.invalid:3307/dev_stock
ID=maria-user
Pass=maria=password
"""));
var loader = new LegacyIniDatabaseOptionsLoader(_ => null);
var options = loader.Load(file.Path);
Assert.True(options.IsConfigured(DataSourceKind.Oracle));
Assert.True(options.IsConfigured(DataSourceKind.MariaDb));
Assert.Equal("oracle.dev.invalid", options.Oracle.Host);
Assert.Equal(1522, options.Oracle.Port);
Assert.Equal("DEVORA", options.Oracle.Sid);
Assert.Null(options.Oracle.ServiceName);
Assert.Equal("oracle-user", options.Oracle.UserName);
Assert.Equal("oracle=password", options.Oracle.Password);
Assert.Equal("maria.dev.invalid", options.MariaDb.Host);
Assert.Equal(3307, options.MariaDb.Port);
Assert.Equal("dev_stock", options.MariaDb.Database);
Assert.Equal("maria-user", options.MariaDb.UserName);
Assert.Equal("maria=password", options.MariaDb.Password);
Assert.Equal(MariaDbTlsMode.Disabled, options.MariaDb.TlsMode);
}
[Fact]
public void Load_Cp949LegacyFile_PreservesKoreanValues()
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
var cp949 = Encoding.GetEncoding(
949,
EncoderFallback.ExceptionFallback,
DecoderFallback.ExceptionFallback);
using var file = TemporaryLegacyIni.Create(cp949.GetBytes(
"""
[Oracle]
ConnectionName=oracle.dev.invalid:1521/
ID=
Pass=
[Maria]
ConnectionName=maria.dev.invalid:3306/
ID=
Pass=2
"""));
var options = new LegacyIniDatabaseOptionsLoader(_ => null).Load(file.Path);
Assert.Equal("개발", options.Oracle.Sid);
Assert.Equal("오라클사용자", options.Oracle.UserName);
Assert.Equal("주식", options.MariaDb.Database);
Assert.Equal("마리아사용자", options.MariaDb.UserName);
}
[Fact]
public void Load_EnvironmentStillOverridesLegacyValues()
{
using var file = TemporaryLegacyIni.CreateValidUtf8();
var environment = new Dictionary<string, string>(StringComparer.Ordinal)
{
["MBN_STOCK_ORACLE_HOST"] = "override-oracle.invalid",
["MBN_STOCK_MARIADB_TLS_MODE"] = "Required"
};
var loader = new LegacyIniDatabaseOptionsLoader(
name => environment.TryGetValue(name, out var value) ? value : null);
var options = loader.Load(file.Path);
Assert.Equal("override-oracle.invalid", options.Oracle.Host);
Assert.Equal(MariaDbTlsMode.Required, options.MariaDb.TlsMode);
}
[Fact]
public void Load_InvalidFile_DoesNotExposeFileValues()
{
const string secret = "sensitive-password-sentinel";
using var file = TemporaryLegacyIni.Create(Encoding.UTF8.GetBytes(
$"[Oracle]\nConnectionName=invalid\nID=user\nPass={secret}"));
var exception = Assert.Throws<DatabaseConfigurationException>(
() => new LegacyIniDatabaseOptionsLoader(_ => null).Load(file.Path));
Assert.DoesNotContain(secret, exception.ToString(), StringComparison.Ordinal);
Assert.DoesNotContain(file.Path, exception.ToString(), StringComparison.Ordinal);
}
[Fact]
public void Runtime_PrefersExecutableResIni_AndFallsBackWhenAbsent()
{
using var directory = TemporaryDirectory.Create();
var res = Path.Combine(directory.Path, "Res");
Directory.CreateDirectory(res);
File.WriteAllBytes(
Path.Combine(res, "MmoneyCoder.ini"),
TemporaryLegacyIni.ValidUtf8Bytes());
var runtime = DatabaseRuntime.CreateLegacyExecutableDefault(
directory.Path,
Path.Combine(directory.Path, "missing.json"));
Assert.Equal("oracle.dev.invalid", runtime.Options.Oracle.Host);
File.Delete(Path.Combine(res, "MmoneyCoder.ini"));
var fallback = DatabaseRuntime.CreateLegacyExecutableDefault(
directory.Path,
Path.Combine(directory.Path, "missing.json"),
Path.Combine(directory.Path, "missing-legacy.ini"));
Assert.False(fallback.Options.IsConfigured(DataSourceKind.Oracle));
Assert.False(fallback.Options.IsConfigured(DataSourceKind.MariaDb));
}
[Fact]
public void Runtime_UsesLocalLegacyOverrideWhenPackageDoesNotContainCredentials()
{
using var directory = TemporaryDirectory.Create();
using var overrideFile = TemporaryLegacyIni.CreateValidUtf8();
var runtime = DatabaseRuntime.CreateLegacyExecutableDefault(
directory.Path,
Path.Combine(directory.Path, "missing.json"),
overrideFile.Path);
Assert.Equal("oracle.dev.invalid", runtime.Options.Oracle.Host);
Assert.Equal("maria.dev.invalid", runtime.Options.MariaDb.Host);
}
[Fact]
public void Load_OptionalRealLegacyIni_IsConfiguredWithoutPrintingValues()
{
var path = Environment.GetEnvironmentVariable(
IntegrationPathEnvironmentVariable);
if (string.IsNullOrWhiteSpace(path))
{
return;
}
var options = new LegacyIniDatabaseOptionsLoader().Load(path);
Assert.True(options.IsConfigured(DataSourceKind.Oracle));
Assert.True(options.IsConfigured(DataSourceKind.MariaDb));
}
private sealed class TemporaryLegacyIni : IDisposable
{
private TemporaryLegacyIni(string directory, string path)
{
Directory = directory;
Path = path;
}
public string Directory { get; }
public string Path { get; }
public static TemporaryLegacyIni CreateValidUtf8() =>
Create(ValidUtf8Bytes());
public static byte[] ValidUtf8Bytes() => Encoding.UTF8.GetBytes(
"""
[Oracle]
ConnectionName=oracle.dev.invalid:1521/DEVORA
ID=oracle-user
Pass=oracle-password
[Maria]
ConnectionName=maria.dev.invalid:3306/dev_stock
ID=maria-user
Pass=maria-password
""");
public static TemporaryLegacyIni Create(byte[] bytes)
{
var directory = System.IO.Path.Combine(
System.IO.Path.GetTempPath(),
Guid.NewGuid().ToString("N"));
System.IO.Directory.CreateDirectory(directory);
var path = System.IO.Path.Combine(directory, "MmoneyCoder.ini");
File.WriteAllBytes(path, bytes);
return new TemporaryLegacyIni(directory, path);
}
public void Dispose() =>
System.IO.Directory.Delete(Directory, recursive: true);
}
private sealed class TemporaryDirectory : IDisposable
{
private TemporaryDirectory(string path) => Path = path;
public string Path { get; }
public static TemporaryDirectory Create()
{
var path = System.IO.Path.Combine(
System.IO.Path.GetTempPath(),
Guid.NewGuid().ToString("N"));
System.IO.Directory.CreateDirectory(path);
return new TemporaryDirectory(path);
}
public void Dispose() =>
System.IO.Directory.Delete(Path, recursive: true);
}
}