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.
This commit is contained in:
+86
@@ -0,0 +1,86 @@
|
||||
using ZB.MOM.WW.ScadaBridge.CentralUI.ScriptAnalysis;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.CentralUI.Tests.ScriptAnalysis;
|
||||
|
||||
/// <summary>
|
||||
/// Regression tests for the <c>SandboxConsoleCapture</c> writer that the Test Run
|
||||
/// sandbox installs on <c>Console.Out</c>/<c>Console.Error</c>. CentralUI-030
|
||||
/// surfaced an intra-script concurrency hazard: a sandboxed script can fan out
|
||||
/// work with <c>Task.WhenAll</c> / <c>Task.Run</c> and every child task inherits
|
||||
/// the capture <c>StringWriter</c> via <c>AsyncLocal</c>; <c>StringWriter</c> is
|
||||
/// not thread-safe, so concurrent writes could corrupt the buffer. These tests
|
||||
/// drive the writer the same way Roslyn-hosted user code does.
|
||||
/// </summary>
|
||||
public class SandboxConsoleCaptureTests
|
||||
{
|
||||
/// <summary>
|
||||
/// CentralUI-030: a capture scope shared across <c>Task.WhenAll</c> child
|
||||
/// tasks must serialise writes so the resulting transcript contains exactly
|
||||
/// the expected number of lines without character-level interleaving.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task BeginCapture_ConcurrentWritesFromTasks_DoNotCorruptBuffer()
|
||||
{
|
||||
// The static install routes Console.Out through the singleton sandbox
|
||||
// capture writer for the test process — this is idempotent and matches
|
||||
// the way ScriptAnalysisService bootstraps the sandbox in production.
|
||||
var (capture, _) = SandboxConsoleCapture.Install();
|
||||
|
||||
var buffer = new StringWriter();
|
||||
const int taskCount = 32;
|
||||
const int linesPerTask = 50;
|
||||
const int expectedLines = taskCount * linesPerTask;
|
||||
|
||||
using (capture.BeginCapture(buffer))
|
||||
{
|
||||
// AsyncLocal flows the capture scope into each Task.Run, mirroring
|
||||
// a sandboxed script doing `await Task.WhenAll(...)` over Tasks
|
||||
// that each `Console.WriteLine`.
|
||||
var tasks = Enumerable.Range(0, taskCount).Select(i => Task.Run(() =>
|
||||
{
|
||||
for (var j = 0; j < linesPerTask; j++)
|
||||
{
|
||||
Console.WriteLine($"task-{i}-line-{j}");
|
||||
}
|
||||
}));
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
|
||||
var captured = buffer.ToString();
|
||||
// Without the lock, concurrent StringWriter.WriteLine can drop or
|
||||
// interleave characters and produce malformed lines / a wrong count.
|
||||
// We assert the exact line count and that every emitted token is
|
||||
// present on a line of its own — both fail under the unprotected
|
||||
// implementation.
|
||||
var lines = captured.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries);
|
||||
Assert.Equal(expectedLines, lines.Length);
|
||||
|
||||
for (var i = 0; i < taskCount; i++)
|
||||
{
|
||||
for (var j = 0; j < linesPerTask; j++)
|
||||
{
|
||||
Assert.Contains($"task-{i}-line-{j}", lines);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sanity check: the most basic capture happy-path still works after the
|
||||
/// CentralUI-030 lock was introduced.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void BeginCapture_SingleThreadedWrites_AreCaptured()
|
||||
{
|
||||
var (capture, _) = SandboxConsoleCapture.Install();
|
||||
var buffer = new StringWriter();
|
||||
|
||||
using (capture.BeginCapture(buffer))
|
||||
{
|
||||
Console.WriteLine("hello");
|
||||
Console.Write("world");
|
||||
}
|
||||
|
||||
Assert.Contains("hello", buffer.ToString());
|
||||
Assert.Contains("world", buffer.ToString());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user