test(upserver): 归档存档迁移与玩法闭环回归工具

This commit is contained in:
Liubing\LB
2026-09-28 18:16:14 +08:00
parent c4ae02def9
commit a6f5e107f8
232 changed files with 12903 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
using System.Text.Json;
using game.Account;
using Microsoft.AspNetCore.SignalR.Client;
var endpoint = new Uri(JsonDocument.Parse(File.ReadAllText("CodexOutput/upserver/network-proxy-address.json")).RootElement.GetProperty("url").GetString());
if(endpoint.Host!="127.0.0.1")throw new Exception("Non-loopback fixture");
using var control = new HttpClient { Timeout=TimeSpan.FromSeconds(10) };
void Check(bool ok,string text){if(!ok)throw new Exception(text);}
async Task<JsonElement> Stats()=>JsonDocument.Parse(await control.GetStringAsync(new Uri(endpoint,"__status"))).RootElement;
using (var session = new S101AccountSession(endpoint))
{
foreach(var mode in new[]{"401","reset","timeout"})
{
await control.GetStringAsync(new Uri(endpoint,"__control?mode="+mode));
var started=DateTime.UtcNow;
var failed=await session.LoginAsync("102");
var elapsed=(DateTime.UtcNow-started).TotalSeconds;
var expected=mode=="401"?AccountLoginError.Http:mode=="reset"?AccountLoginError.Network:AccountLoginError.Timeout;
Check(failed.Error==expected&&!session.IsAuthenticated&&session.PlayerId==null&&session.InternalId==0,"Failure isolation "+mode+"/"+failed.Error);
Check(mode!="401"||failed.StatusCode==401,"Expected status401");
Check(mode!="timeout"||elapsed>=14,"Production timeout not reached");
var recovered=await session.LoginAsync("102");
Check(recovered.Success&&session.IsAuthenticated&&session.PlayerId=="102","Login recovery "+recovered.Error);
Check((await session.CheckAuthorizationAsync()).Success,"Recovery cookie rejected");
Console.WriteLine($"PASS real HTTP {mode}: {failed.Error}; seconds={elapsed:F1}; retry+authorized readonly Get=OK");
}
}
using var account=new S101AccountSession(endpoint);
var mgr=new CustomServerMgr(new Config(endpoint.AbsoluteUri));
var rt=new SignalRService(mgr,null);
try{
Check((await account.LoginAsync("102")).Success,"Hub account login");
mgr.UseAccountSession(account);
await rt.Connect();
Check(rt.IsConnected&&await rt.Publish("Test","acceptance","before")=="OK","Initial hub RPC");
var before=await Stats();
await control.GetStringAsync(new Uri(endpoint,"__control?mode=drop"));
bool observed=false;
var deadline=DateTime.UtcNow.AddSeconds(35);
while(DateTime.UtcNow<deadline){
if(!rt.IsConnected)observed=true;
if(observed&&rt.IsConnected)break;
await Task.Delay(50);
}
Check(observed&&rt.IsConnected,"Real socket automatic reconnect");
Check(await rt.Publish("Test","acceptance","after")=="OK","Post-reconnect RPC");
var after=await Stats();
Check(after.GetProperty("upgrades").GetInt32()>before.GetProperty("upgrades").GetInt32(),"No new real websocket upgrade");
Check(after.GetProperty("negotiate").GetInt32()==0,"Unexpected negotiate request");
Console.WriteLine("PASS real WebSocket dropped, disconnected observed, automatically recovered, Test=OK, negotiate=0");
await rt.ReleaseAsync();
await Task.Delay(500);
var released=await Stats();
await Task.Delay(2500);
var stable=await Stats();
Check(!rt.IsConnected&&stable.GetProperty("active").GetInt32()==0&&stable.GetProperty("upgrades").GetInt32()==released.GetProperty("upgrades").GetInt32(),"Release leaked or reconnected");
Console.WriteLine("PASS ReleaseAsync: active sockets=0, no late reconnect");
Console.WriteLine("SignalR DLL="+typeof(HubConnection).Assembly.GetName().Version);
Console.WriteLine("Fixture counters="+stable.GetRawText());
}finally{await rt.ReleaseAsync();mgr.ClearAccountSession();}