Files
lmxopcua/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting.Tests/ScriptSandboxBuildTests.cs
T
Joseph Doherty 64e3fbe035
v2-ci / build (push) Failing after 1m43s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped
docs: backfill XML documentation across 756 files
Adds <summary>, <param>, <typeparam>, and <inheritdoc/> tags to public
members surfaced by commentchecker — resolves 5,847 of 5,869 issues
(99.6%) across three /fixdocs passes.
2026-05-28 08:10:17 -04:00

61 lines
2.8 KiB
C#

using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Core.Scripting;
namespace ZB.MOM.WW.OtOpcUa.Core.Scripting.Tests;
/// <summary>
/// Covers the <see cref="ScriptSandbox.Build"/> argument-validation guards. The
/// guards are the only call-site protection against a typo / mis-wired context
/// type silently producing a sandbox missing the concrete context's assembly
/// reference; without coverage, the guards could be deleted by a refactor without
/// any test failing. (Core.Scripting-011.)
/// </summary>
[Trait("Category", "Unit")]
public sealed class ScriptSandboxBuildTests
{
/// <summary>Verifies that a null context type throws ArgumentNullException.</summary>
[Fact]
public void Null_context_type_throws_ArgumentNullException()
{
Should.Throw<ArgumentNullException>(() => ScriptSandbox.Build(null!));
}
/// <summary>Verifies that a non-ScriptContext type throws ArgumentException.</summary>
[Fact]
public void Non_ScriptContext_type_throws_ArgumentException()
{
// ScriptSandbox must reject types that don't derive from ScriptContext —
// ScriptGlobals<TContext> is constrained where TContext : ScriptContext, so
// sneaking a non-derived type past Build would later blow up inside Roslyn.
Should.Throw<ArgumentException>(() => ScriptSandbox.Build(typeof(string)))
.ParamName.ShouldBe("contextType");
}
/// <summary>Verifies that the abstract ScriptContext base type is accepted by the sandbox builder.</summary>
[Fact]
public void Abstract_ScriptContext_base_type_is_accepted()
{
// The base ScriptContext type satisfies the IsAssignableFrom check, so the
// factory must not reject it even though it cannot be instantiated directly.
// Callers wiring a base-typed sandbox up for diagnostics rely on this.
var options = ScriptSandbox.Build(typeof(ScriptContext));
options.ShouldNotBeNull();
}
/// <summary>Verifies that a concrete subclass is accepted and its assembly is referenced in the sandbox.</summary>
[Fact]
public void Concrete_subclass_is_accepted_and_its_assembly_referenced()
{
// The concrete context type's assembly must end up in the allow-listed
// references — otherwise Roslyn cannot resolve ScriptGlobals<TContext> at
// compile. We can't easily inspect the ScriptOptions metadata references
// by-assembly cross-version, so we exercise the end-to-end path instead: a
// script compiled against FakeScriptContext must successfully reach a
// FakeScriptContext member.
var evaluator = ScriptEvaluator<FakeScriptContext, double>.Compile(
"""return (double)ctx.GetTag("X").Value;""");
evaluator.ShouldNotBeNull();
}
}