Files
ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.Host.Tests/SerilogSinkConfigTests.cs
T
Joseph Doherty 7b0b9c7365 refactor: rename ScadaLink → ZB.MOM.WW.ScadaBridge (code + projects + namespaces)
Solution + 23 src projects + 26 test projects renamed; folders, csproj,
namespaces, and ScadaLinkDbContext/ScadaBridgeDbContext class updated.
ActorSystem "scadalink" → "scadabridge", Akka seed-node URLs migrated.
SQL roles/logins, LDAP domains, CLI command name, and CLI config dir
(~/.scadalink → ~/.scadabridge) also renamed.

Build green; 5 Host.Tests fail awaiting SQL login rename in next commit.
Pre-existing StaleTagMonitor timing flakes unchanged.

Rename script committed at tools/rename-to-scadabridge.sh.
2026-05-28 09:37:45 -04:00

94 lines
3.7 KiB
C#

using System.Reflection;
using System.Text.Json;
using Microsoft.Extensions.Configuration;
namespace ZB.MOM.WW.ScadaBridge.Host.Tests;
/// <summary>
/// Host-014 regression: REQ-HOST-8 requires the Host's Serilog sinks
/// (console and file at minimum) to be <em>configuration-driven</em>. The sinks
/// must be defined in a <c>Serilog</c> section in <c>appsettings.json</c> and
/// applied via <c>ReadFrom.Configuration</c> — they must not be hard-coded in
/// <c>Program.cs</c>, so an operator can change the file path, rolling interval or
/// output template without recompiling.
/// </summary>
public class SerilogSinkConfigTests
{
private static string FindHostProjectDirectory()
{
var assemblyDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
var dir = new DirectoryInfo(assemblyDir);
while (dir != null)
{
var hostPath = Path.Combine(dir.FullName, "src", "ZB.MOM.WW.ScadaBridge.Host");
if (Directory.Exists(hostPath))
return hostPath;
dir = dir.Parent;
}
throw new DirectoryNotFoundException("Could not locate src/ZB.MOM.WW.ScadaBridge.Host");
}
[Fact]
public void ShippedAppSettings_HasSerilogSection_WithConsoleAndFileSinks()
{
var path = Path.Combine(FindHostProjectDirectory(), "appsettings.json");
using var doc = JsonDocument.Parse(File.ReadAllText(path));
Assert.True(
doc.RootElement.TryGetProperty("Serilog", out var serilog),
"appsettings.json must contain a `Serilog` section so ReadFrom.Configuration " +
"drives the sinks (REQ-HOST-8 / Host-014).");
Assert.True(
serilog.TryGetProperty("WriteTo", out var writeTo),
"the `Serilog` section must contain a `WriteTo` array defining the sinks.");
var sinkNames = writeTo.EnumerateArray()
.Select(e => e.TryGetProperty("Name", out var n) ? n.GetString() : null)
.ToList();
Assert.Contains("Console", sinkNames);
Assert.Contains("File", sinkNames);
}
[Fact]
public void LoggerConfigurationFactory_AppliesConfiguredFileSink()
{
// A `Serilog` section in configuration must actually reach the built logger
// via ReadFrom.Configuration — proving the sink set is configuration-driven.
var logDir = Path.Combine(Path.GetTempPath(), "scadabridge-host014-" + Guid.NewGuid().ToString("N"));
var logPath = Path.Combine(logDir, "test-.log");
try
{
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>
{
["Serilog:Using:0"] = "Serilog.Sinks.File",
["Serilog:WriteTo:0:Name"] = "File",
["Serilog:WriteTo:0:Args:path"] = logPath,
["Serilog:WriteTo:0:Args:rollingInterval"] = "Day",
})
.Build();
var logger = LoggerConfigurationFactory
.Build(configuration, "Central", "central", "node1")
.CreateLogger();
logger.Information("host-014 configured-sink probe");
logger.Dispose();
Assert.True(Directory.Exists(logDir), "the configured file sink must have created its directory.");
var written = Directory.GetFiles(logDir, "test-*.log");
Assert.NotEmpty(written);
Assert.Contains(
"host-014 configured-sink probe",
File.ReadAllText(written[0]));
}
finally
{
if (Directory.Exists(logDir))
Directory.Delete(logDir, recursive: true);
}
}
}