using Shouldly;
using Xunit;
namespace ZB.MOM.WW.OtOpcUa.Cluster.Tests;
public sealed class RoleParserTests
{
/// Verifies that empty input yields an empty array.
/// The raw input string to test (null, empty, or whitespace).
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData(" ")]
public void Empty_input_yields_empty_array(string? raw)
{
RoleParser.Parse(raw).ShouldBeEmpty();
}
/// Verifies that a single role 'admin' is parsed correctly.
[Fact]
public void Single_role_admin()
{
RoleParser.Parse("admin").ShouldBe(new[] { "admin" });
}
/// Verifies that two roles separated by comma are parsed correctly.
[Fact]
public void Two_roles_csv()
{
RoleParser.Parse("admin,driver").ShouldBe(new[] { "admin", "driver" });
}
/// Verifies that parser tolerates surrounding whitespace.
[Fact]
public void Whitespace_tolerant()
{
RoleParser.Parse(" admin , driver ").ShouldBe(new[] { "admin", "driver" });
}
/// Verifies that parser is case-insensitive and normalizes to lowercase.
[Fact]
public void Case_insensitive_normalizes_to_lower()
{
RoleParser.Parse("ADMIN,Driver").ShouldBe(new[] { "admin", "driver" });
}
/// Verifies that duplicate roles are removed.
[Fact]
public void Duplicate_roles_deduped()
{
RoleParser.Parse("admin,admin,driver").ShouldBe(new[] { "admin", "driver" });
}
/// Verifies that parser throws for unknown roles.
[Fact]
public void Unknown_role_throws()
{
Should.Throw(() => RoleParser.Parse("admin,master"));
}
/// Verifies that a single cluster-scoped role is accepted.
[Theory]
[InlineData("cluster-MAIN")]
[InlineData("cluster-SITE-A")]
public void Cluster_role_accepted(string role)
{
RoleParser.Parse(role).ShouldBe(new[] { role.ToLowerInvariant() });
}
/// Verifies that cluster roles mix freely with the fixed roles.
[Fact]
public void Fixed_and_cluster_roles_mix()
{
RoleParser.Parse("driver,cluster-SITE-A").ShouldBe(new[] { "driver", "cluster-site-a" });
}
/// Verifies that a cluster role with an empty ClusterId ("cluster-") is rejected.
[Fact]
public void Empty_cluster_id_throws()
{
Should.Throw(() => RoleParser.Parse("cluster-"));
}
/// Verifies IsClusterRole returns true for valid cluster roles and false otherwise.
[Theory]
[InlineData("cluster-MAIN", true)]
[InlineData("cluster-SITE-A", true)]
[InlineData("cluster-", false)]
[InlineData("driver", false)]
[InlineData("admin", false)]
[InlineData("clusterx", false)]
public void IsClusterRole_classifies_correctly(string role, bool expected)
{
RoleParser.IsClusterRole(role).ShouldBe(expected);
}
/// Verifies ClusterIdFromRole extracts the ClusterId suffix.
[Fact]
public void ClusterIdFromRole_extracts_suffix()
{
RoleParser.ClusterIdFromRole("cluster-SITE-A").ShouldBe("SITE-A");
}
/// Verifies the three well-known role constants match the historical literal values.
[Fact]
public void Well_known_role_constants()
{
RoleParser.Admin.ShouldBe("admin");
RoleParser.Driver.ShouldBe("driver");
RoleParser.Dev.ShouldBe("dev");
RoleParser.ClusterRolePrefix.ShouldBe("cluster-");
}
}