保存独立KV用户服务、固定会话存档与原业务接线,以及C3d资料缓存和C3e本人统计写。 保留原PF/AGG路线、业务公式和时序;榜单读取、好友资料、公告、匹配及首场景闸仍待完成。 验证:ServiceHost两条件各33组646断言;Unity CLI Loop编译0错误269警告。 包含相关方案、评审裁决、测试及状态文档。未操作服务器、正式账号或打包。
52 lines
2.8 KiB
C#
52 lines
2.8 KiB
C#
using System.Reflection;
|
|
|
|
static partial class Tests
|
|
{
|
|
static async Task RunCP2ARuntimeSelectionTests()
|
|
{
|
|
await Run("CP2A-backend-capture-and-approved-existing-cohort", CP2ASelection);
|
|
}
|
|
|
|
static Task CP2ASelection()
|
|
{
|
|
// A wrong branch, a widened cohort, or a mutable backend would break this boundary.
|
|
var selectionType = typeof(Tests).Assembly.GetType("game.PlayerDataStorage.PlayerKVRuntimeSelection");
|
|
Check(selectionType != null, "formal runtime selection must exist in the real production assembly");
|
|
var capture = selectionType.GetMethod("Capture", BindingFlags.Static | BindingFlags.NonPublic);
|
|
Check(capture != null, "capture API");
|
|
object Take(string backend, string api, bool agg) => capture.Invoke(null, new object[] { backend, api, agg });
|
|
var pf = Take(null, "http://unused.invalid/", false);
|
|
Check((bool)selectionType.GetProperty("IsKV", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(pf) == false,
|
|
"missing backend keeps PF default without applying KV URL rules");
|
|
var kv = Take("kv", "http://s101.local:18080/", false);
|
|
Check((bool)selectionType.GetProperty("IsKV", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(kv),
|
|
"exact KV backend and address admitted");
|
|
var admit = selectionType.GetMethod("TryAdmitPlayer", BindingFlags.Instance | BindingFlags.NonPublic);
|
|
Check(admit != null, "cohort admission API");
|
|
bool Allowed(string id, out string canonical)
|
|
{
|
|
var args = new object[] { id, null };
|
|
var accepted = (bool)admit.Invoke(kv, args);
|
|
canonical = (string)args[1];
|
|
return accepted;
|
|
}
|
|
Check(Allowed("00101", out var first) && first == "101", "101 uses canonical decimal identity");
|
|
Check(Allowed("102", out var second) && second == "102", "102 admitted");
|
|
foreach (var id in new[] { "100", "103", "0", "-101", "+101", " 101", "", "9223372036854775808" })
|
|
Check(!Allowed(id, out _), "unapproved or malformed account denied: " + id);
|
|
foreach (var bad in new[] {
|
|
new object[] { "KV", "http://s101.local:18080/", false },
|
|
new object[] { "other", "http://s101.local:18080/", false },
|
|
new object[] { "kv", "http://s101.local:18080", false },
|
|
new object[] { "kv", "http://other.local:18080/", false },
|
|
new object[] { "kv", "http://s101.local:18080/", true }
|
|
})
|
|
{
|
|
try { capture.Invoke(null, bad); throw new InvalidOperationException("invalid capture accepted"); }
|
|
catch (TargetInvocationException ex) when (ex.InnerException is ArgumentException or InvalidOperationException)
|
|
{ Check(true, "invalid capture rejected"); }
|
|
}
|
|
return Task.CompletedTask;
|
|
}
|
|
}
|