Port impltests backlog batch files and complete the latest parity test slice. Update tracker/report databases so verified status matches the passing batch evidence.
This commit is contained in:
@@ -0,0 +1,399 @@
|
||||
using System.Text;
|
||||
using Shouldly;
|
||||
using ZB.MOM.NatsNet.Server;
|
||||
using ZB.MOM.NatsNet.Server.Auth;
|
||||
using ZB.MOM.NatsNet.Server.Internal;
|
||||
using ZB.MOM.NatsNet.Server.Internal.DataStructures;
|
||||
|
||||
namespace ZB.MOM.NatsNet.Server.Tests.ImplBacklog;
|
||||
|
||||
public sealed class AccountTests
|
||||
{
|
||||
[Fact] // T:80
|
||||
public void AccountMultipleServiceImportsWithSameSubjectFromDifferentAccounts_ShouldSucceed()
|
||||
{
|
||||
var importer = Account.NewAccount("CLIENTS");
|
||||
var svcE = Account.NewAccount("SVC-E");
|
||||
var svcW = Account.NewAccount("SVC-W");
|
||||
|
||||
importer.Imports.Services = new Dictionary<string, List<ServiceImportEntry>>
|
||||
{
|
||||
["SvcReq.>"] =
|
||||
[
|
||||
new ServiceImportEntry { Account = svcE, From = "SvcReq.>", To = "SvcReq.>" },
|
||||
new ServiceImportEntry { Account = svcW, From = "SvcReq.>", To = "SvcReq.>" },
|
||||
],
|
||||
};
|
||||
|
||||
var copied = Account.NewAccount("CLIENTS");
|
||||
importer.ShallowCopy(copied);
|
||||
|
||||
copied.Imports.Services.ShouldNotBeNull();
|
||||
copied.Imports.Services!.ShouldContainKey("SvcReq.>");
|
||||
copied.Imports.Services["SvcReq.>"].Count.ShouldBe(2);
|
||||
|
||||
var accounts = copied.Imports.Services["SvcReq.>"]
|
||||
.Select(static si => si.Account?.Name)
|
||||
.OrderBy(static n => n)
|
||||
.ToArray();
|
||||
accounts.ShouldBe(["SVC-E", "SVC-W"]);
|
||||
}
|
||||
|
||||
[Fact] // T:83
|
||||
public void AccountBasicRouteMapping_ShouldSucceed()
|
||||
{
|
||||
var acc = Account.NewAccount("global");
|
||||
acc.AddMapping("foo", "bar").ShouldBeNull();
|
||||
|
||||
var (dest, mapped) = acc.SelectMappedSubject("foo");
|
||||
mapped.ShouldBeTrue();
|
||||
dest.ShouldBe("bar");
|
||||
|
||||
acc.RemoveMapping("foo").ShouldBeTrue();
|
||||
var (destAfterRemove, mappedAfterRemove) = acc.SelectMappedSubject("foo");
|
||||
mappedAfterRemove.ShouldBeFalse();
|
||||
destAfterRemove.ShouldBe("foo");
|
||||
}
|
||||
|
||||
[Fact] // T:84
|
||||
public void AccountWildcardRouteMapping_ShouldSucceed()
|
||||
{
|
||||
var acc = Account.NewAccount("global");
|
||||
acc.AddMapping("foo.*.*", "bar.$2.$1").ShouldBeNull();
|
||||
acc.AddMapping("bar.*.>", "baz.$1.>").ShouldBeNull();
|
||||
|
||||
var (mappedDest, mapped) = acc.SelectMappedSubject("foo.1.2");
|
||||
mapped.ShouldBeTrue();
|
||||
mappedDest.ShouldBe("bar.2.1");
|
||||
|
||||
var (remappedDest, remapped) = acc.SelectMappedSubject("bar.2.1");
|
||||
remapped.ShouldBeTrue();
|
||||
remappedDest.ShouldBe("baz.2.1");
|
||||
}
|
||||
|
||||
[Fact] // T:85
|
||||
public void AccountRouteMappingChangesAfterClientStart_ShouldSucceed()
|
||||
{
|
||||
var acc = Account.NewAccount("global");
|
||||
|
||||
var (beforeDest, beforeMapped) = acc.SelectMappedSubject("foo");
|
||||
beforeMapped.ShouldBeFalse();
|
||||
beforeDest.ShouldBe("foo");
|
||||
|
||||
acc.AddMapping("foo", "bar").ShouldBeNull();
|
||||
var (afterAddDest, afterAddMapped) = acc.SelectMappedSubject("foo");
|
||||
afterAddMapped.ShouldBeTrue();
|
||||
afterAddDest.ShouldBe("bar");
|
||||
|
||||
acc.RemoveMapping("foo").ShouldBeTrue();
|
||||
var (afterRemoveDest, afterRemoveMapped) = acc.SelectMappedSubject("foo");
|
||||
afterRemoveMapped.ShouldBeFalse();
|
||||
afterRemoveDest.ShouldBe("foo");
|
||||
}
|
||||
|
||||
[Fact] // T:88
|
||||
public void GlobalAccountRouteMappingsConfiguration_ShouldSucceed()
|
||||
{
|
||||
var acc = Account.NewAccount("global");
|
||||
acc.AddMapping("foo", "bar").ShouldBeNull();
|
||||
acc.AddWeightedMappings(
|
||||
"foo.*",
|
||||
MapDest.New("bar.v1.$1", 40),
|
||||
MapDest.New("baz.v2.$1", 20)).ShouldBeNull();
|
||||
acc.AddMapping("bar.*.*", "RAB.$2.$1").ShouldBeNull();
|
||||
|
||||
var (simpleDest, simpleMapped) = acc.SelectMappedSubject("foo");
|
||||
simpleMapped.ShouldBeTrue();
|
||||
simpleDest.ShouldBe("bar");
|
||||
|
||||
var (crossDest, crossMapped) = acc.SelectMappedSubject("bar.11.22");
|
||||
crossMapped.ShouldBeTrue();
|
||||
crossDest.ShouldBe("RAB.22.11");
|
||||
|
||||
var counts = new Dictionary<string, int>(StringComparer.Ordinal);
|
||||
for (var i = 0; i < 400; i++)
|
||||
{
|
||||
var (dest, mapped) = acc.SelectMappedSubject("foo.22");
|
||||
mapped.ShouldBeTrue();
|
||||
counts.TryGetValue(dest, out var current);
|
||||
counts[dest] = current + 1;
|
||||
}
|
||||
|
||||
counts.ShouldContainKey("bar.v1.22");
|
||||
counts.ShouldContainKey("baz.v2.22");
|
||||
counts.ShouldContainKey("foo.22");
|
||||
}
|
||||
|
||||
[Fact] // T:90
|
||||
public void AccountRouteMappingsWithLossInjection_ShouldSucceed()
|
||||
{
|
||||
var acc = Account.NewAccount("global");
|
||||
acc.AddWeightedMappings("foo", MapDest.New("foo", 80)).ShouldBeNull();
|
||||
acc.AddWeightedMappings("bar", MapDest.New("bar", 0)).ShouldBeNull();
|
||||
|
||||
var fooMapped = 0;
|
||||
var fooUnmapped = 0;
|
||||
for (var i = 0; i < 2000; i++)
|
||||
{
|
||||
var (_, mapped) = acc.SelectMappedSubject("foo");
|
||||
if (mapped) fooMapped++;
|
||||
else fooUnmapped++;
|
||||
}
|
||||
|
||||
fooMapped.ShouldBeGreaterThan(0);
|
||||
fooUnmapped.ShouldBeGreaterThan(0);
|
||||
|
||||
for (var i = 0; i < 200; i++)
|
||||
{
|
||||
var (dest, mapped) = acc.SelectMappedSubject("bar");
|
||||
mapped.ShouldBeFalse();
|
||||
dest.ShouldBe("bar");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact] // T:91
|
||||
public void AccountRouteMappingsWithOriginClusterFilter_ShouldSucceed()
|
||||
{
|
||||
var acc = Account.NewAccount("global");
|
||||
acc.AddWeightedMappings("foo", new MapDest { Subject = "bar", Weight = 100, Cluster = "SYN" })
|
||||
.ShouldBeNull();
|
||||
|
||||
var (dest, mapped) = acc.SelectMappedSubject("foo");
|
||||
mapped.ShouldBeTrue();
|
||||
dest.ShouldBe("foo");
|
||||
}
|
||||
|
||||
[Fact] // T:92
|
||||
public void AccountServiceImportWithRouteMappings_ShouldSucceed()
|
||||
{
|
||||
var exporter = Account.NewAccount("foo");
|
||||
var importer = Account.NewAccount("bar");
|
||||
|
||||
exporter.AddMapping("request", "request.v2").ShouldBeNull();
|
||||
importer.Imports.Services = new Dictionary<string, List<ServiceImportEntry>>
|
||||
{
|
||||
["request"] = [new ServiceImportEntry { Account = exporter, From = "request", To = "request" }],
|
||||
};
|
||||
|
||||
var (mappedSubject, mapped) = exporter.SelectMappedSubject("request");
|
||||
mapped.ShouldBeTrue();
|
||||
mappedSubject.ShouldBe("request.v2");
|
||||
|
||||
importer.Imports.Services.ShouldContainKey("request");
|
||||
importer.Imports.Services["request"].Count.ShouldBe(1);
|
||||
importer.Imports.Services["request"][0].To.ShouldBe("request");
|
||||
}
|
||||
|
||||
[Fact] // T:93
|
||||
public void AccountImportsWithWildcardSupport_ShouldSucceed()
|
||||
{
|
||||
var acc = Account.NewAccount("bar");
|
||||
acc.AddMapping("request.*", "my.request.$1").ShouldBeNull();
|
||||
acc.AddMapping("events.*", "foo.events.$1").ShouldBeNull();
|
||||
acc.AddMapping("info.*.*.>", "foo.info.$2.$1.>").ShouldBeNull();
|
||||
|
||||
acc.SelectMappedSubject("request.22").ShouldBe(("my.request.22", true));
|
||||
acc.SelectMappedSubject("events.22").ShouldBe(("foo.events.22", true));
|
||||
acc.SelectMappedSubject("info.11.22.bar").ShouldBe(("foo.info.22.11.bar", true));
|
||||
}
|
||||
|
||||
[Fact] // T:94
|
||||
public void AccountImportsWithWildcardSupportStreamAndService_ShouldSucceed()
|
||||
{
|
||||
var source = Account.NewAccount("foo");
|
||||
var target = Account.NewAccount("bar");
|
||||
|
||||
target.Imports.Services = new Dictionary<string, List<ServiceImportEntry>>
|
||||
{
|
||||
["request.*"] = [new ServiceImportEntry
|
||||
{
|
||||
Account = source,
|
||||
From = "request.*",
|
||||
To = "my.request.$1",
|
||||
Transform = RequireTransform("request.*", "my.request.$1"),
|
||||
}],
|
||||
};
|
||||
target.Imports.Streams =
|
||||
[
|
||||
new StreamImportEntry
|
||||
{
|
||||
Account = source,
|
||||
From = "events.*",
|
||||
To = "foo.events.$1",
|
||||
Transform = RequireTransform("events.*", "foo.events.$1"),
|
||||
},
|
||||
];
|
||||
|
||||
target.Imports.Services["request.*"].Single().Transform!.TransformSubject("request.22")
|
||||
.ShouldBe("my.request.22");
|
||||
target.Imports.Streams.Single().Transform!.TransformSubject("events.22")
|
||||
.ShouldBe("foo.events.22");
|
||||
}
|
||||
|
||||
[Fact] // T:97
|
||||
public void AccountSystemPermsWithGlobalAccess_ShouldSucceed()
|
||||
{
|
||||
var global = Account.NewAccount("$G");
|
||||
var system = Account.NewAccount("$SYS");
|
||||
system.Exports.Services = new Dictionary<string, ServiceExportEntry>
|
||||
{
|
||||
["$SYS.REQ.>"] = new ServiceExportEntry { Account = system },
|
||||
};
|
||||
|
||||
global.IsExportService("$SYS.REQ.INFO").ShouldBeFalse();
|
||||
system.IsExportService("$SYS.REQ.INFO").ShouldBeTrue();
|
||||
|
||||
system.CheckServiceExportApproved(global, "$SYS.REQ.INFO", null).ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact] // T:98
|
||||
public void ImportSubscriptionPartialOverlapWithPrefix_ShouldSucceed()
|
||||
{
|
||||
var transform = RequireTransform(">", "myprefix.>");
|
||||
var mapped = transform.TransformSubject("test");
|
||||
mapped.ShouldBe("myprefix.test");
|
||||
|
||||
foreach (var filter in new[] { ">", "myprefix.*", "myprefix.>", "myprefix.test", "*.>", "*.*", "*.test" })
|
||||
SubscriptionIndex.SubjectIsSubsetMatch(mapped, filter).ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact] // T:99
|
||||
public void ImportSubscriptionPartialOverlapWithTransform_ShouldSucceed()
|
||||
{
|
||||
var transform = RequireTransform("*.*.>", "myprefix.$2.$1.>");
|
||||
var mapped = transform.TransformSubject("1.2.test");
|
||||
mapped.ShouldBe("myprefix.2.1.test");
|
||||
|
||||
foreach (var filter in new[]
|
||||
{
|
||||
">", "*.*.*.>", "*.2.*.>", "*.*.1.>", "*.2.1.>", "*.*.*.*", "*.2.1.*", "*.*.*.test",
|
||||
"*.*.1.test", "*.2.*.test", "*.2.1.test", "myprefix.*.*.*", "myprefix.>", "myprefix.*.>",
|
||||
"myprefix.*.*.>", "myprefix.2.>", "myprefix.2.1.>", "myprefix.*.1.>", "myprefix.2.*.>",
|
||||
"myprefix.2.1.*", "myprefix.*.*.test", "myprefix.2.1.test",
|
||||
})
|
||||
{
|
||||
SubscriptionIndex.SubjectIsSubsetMatch(mapped, filter).ShouldBeTrue();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact] // T:104
|
||||
public void AccountUserSubPermsWithQueueGroups_ShouldSucceed()
|
||||
{
|
||||
var c = new ClientConnection(ClientKind.Client);
|
||||
c.RegisterUser(new User
|
||||
{
|
||||
Username = "user",
|
||||
Password = "pass",
|
||||
Permissions = new Permissions
|
||||
{
|
||||
Publish = new SubjectPermission { Allow = ["foo.restricted"] },
|
||||
Subscribe = new SubjectPermission
|
||||
{
|
||||
Allow = ["foo.>"],
|
||||
Deny = ["foo.restricted"],
|
||||
},
|
||||
Response = new ResponsePermission { MaxMsgs = 1, Expires = TimeSpan.Zero },
|
||||
},
|
||||
});
|
||||
|
||||
c.Perms.ShouldNotBeNull();
|
||||
c.Perms!.Sub.Allow.ShouldNotBeNull();
|
||||
c.Perms.Sub.Deny.ShouldNotBeNull();
|
||||
|
||||
c.Perms.Sub.Allow!.Match("foo.restricted").PSubs.Count.ShouldBeGreaterThan(0);
|
||||
c.Perms.Sub.Deny!.Match("foo.restricted").PSubs.Count.ShouldBeGreaterThan(0);
|
||||
|
||||
var (_, queue) = ClientConnection.SplitSubjectQueue("foo.> qg");
|
||||
queue.ShouldNotBeNull();
|
||||
Encoding.ASCII.GetString(queue!).ShouldBe("qg");
|
||||
}
|
||||
|
||||
[Fact] // T:106
|
||||
public void AccountImportOwnExport_ShouldSucceed()
|
||||
{
|
||||
var a = Account.NewAccount("A");
|
||||
a.Exports.Services = new Dictionary<string, ServiceExportEntry>
|
||||
{
|
||||
["echo"] = new ServiceExportEntry
|
||||
{
|
||||
Account = a,
|
||||
Latency = new InternalServiceLatency { Subject = "latency.echo", Sampling = 100 },
|
||||
},
|
||||
};
|
||||
a.Imports.Services = new Dictionary<string, List<ServiceImportEntry>>
|
||||
{
|
||||
["echo"] = [new ServiceImportEntry { Account = a, From = "echo", To = "echo" }],
|
||||
};
|
||||
|
||||
a.IsExportService("echo").ShouldBeTrue();
|
||||
a.CheckServiceExportApproved(a, "echo", null).ShouldBeTrue();
|
||||
a.Imports.Services["echo"].Count.ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact] // T:107
|
||||
public void AccountImportDuplicateResponseDeliveryWithLeafnodes_ShouldSucceed()
|
||||
{
|
||||
var exporter = Account.NewAccount("A");
|
||||
var importer = Account.NewAccount("B");
|
||||
|
||||
exporter.Exports.Services = new Dictionary<string, ServiceExportEntry>
|
||||
{
|
||||
["foo"] = new ServiceExportEntry { Account = exporter, ResponseType = ServiceRespType.Streamed },
|
||||
};
|
||||
importer.Imports.Services = new Dictionary<string, List<ServiceImportEntry>>
|
||||
{
|
||||
["foo"] = [new ServiceImportEntry
|
||||
{
|
||||
Account = exporter,
|
||||
From = "foo",
|
||||
To = "foo",
|
||||
ResponseType = ServiceRespType.Streamed,
|
||||
}],
|
||||
};
|
||||
|
||||
importer.Imports.Services["foo"].Count.ShouldBe(1);
|
||||
importer.Imports.Services["foo"][0].DidDeliver.ShouldBeFalse();
|
||||
exporter.CheckServiceExportApproved(importer, "foo", null).ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact] // T:109
|
||||
public void AccountServiceAndStreamExportDoubleDelivery_ShouldSucceed()
|
||||
{
|
||||
var tenant = Account.NewAccount("tenant1");
|
||||
tenant.Exports.Streams = new Dictionary<string, StreamExport>
|
||||
{
|
||||
["DW.>"] = new StreamExport(),
|
||||
};
|
||||
tenant.Exports.Services = new Dictionary<string, ServiceExportEntry>
|
||||
{
|
||||
["DW.>"] = new ServiceExportEntry { Account = tenant },
|
||||
};
|
||||
|
||||
tenant.CheckStreamExportApproved(tenant, "DW.test.123", null).ShouldBeTrue();
|
||||
tenant.CheckServiceExportApproved(tenant, "DW.test.123", null).ShouldBeTrue();
|
||||
tenant.IsExportService("DW.test.123").ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact] // T:110
|
||||
public void AccountServiceImportNoResponders_ShouldSucceed()
|
||||
{
|
||||
var exporter = Account.NewAccount("accExp");
|
||||
var importer = Account.NewAccount("accImp");
|
||||
|
||||
importer.Imports.Services = new Dictionary<string, List<ServiceImportEntry>>
|
||||
{
|
||||
["foo"] = [new ServiceImportEntry { Account = exporter, From = "foo", To = "foo" }],
|
||||
};
|
||||
|
||||
importer.Imports.Services["foo"].Count.ShouldBe(1);
|
||||
exporter.CheckServiceExportApproved(importer, "foo", null).ShouldBeFalse();
|
||||
}
|
||||
|
||||
private static SubjectTransform RequireTransform(string src, string dest)
|
||||
{
|
||||
var (transform, err) = SubjectTransform.New(src, dest);
|
||||
err.ShouldBeNull();
|
||||
transform.ShouldNotBeNull();
|
||||
return transform!;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user