test(upserver): 归档存档迁移与玩法闭环回归工具
This commit is contained in:
1
CodexOutput/upserver/MapExitTests/MapExitTests.csproj
Normal file
1
CodexOutput/upserver/MapExitTests/MapExitTests.csproj
Normal file
@@ -0,0 +1 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net9.0</TargetFramework><ImplicitUsings>enable</ImplicitUsings><RestoreConfigFile>$(MSBuildThisFileDirectory)../MinimalLoginTests/NuGet.Config</RestoreConfigFile></PropertyGroup></Project>
|
||||
62
CodexOutput/upserver/MapExitTests/Program.cs
Normal file
62
CodexOutput/upserver/MapExitTests/Program.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
void Check(bool value,string m){if(!value)throw new Exception(m);}
|
||||
foreach(var scenario in new[]{"normal","logout","destroy"}){
|
||||
GContext.container=new Container();Addressables.Pending=new();Addressables.Released.Clear();
|
||||
var subject=new Subject();var task=subject.Run();Check(!task.IsCompleted,"missing controlled load");
|
||||
if(scenario=="logout")GContext.container.User.Lifetime.Cancel();
|
||||
if(scenario=="destroy")subject.Destroyed=true;
|
||||
var asset=new GameObject();Addressables.Pending.SetResult(asset);await task;
|
||||
Check(subject.Applied==(scenario=="normal"),"stale map applied");
|
||||
Check(Addressables.Released.Contains(asset)==(scenario!="normal"),"late asset ownership incorrect");
|
||||
Console.WriteLine("PASS actual LoadMapByCurID resource boundary: "+scenario);
|
||||
}
|
||||
var ik=new IkSubject();ik.SetIKTarget(new Transform());
|
||||
ik.RodBehaviour=new Rod();ik.SetIKTarget(new Transform());
|
||||
var target=new Transform();ik.RodBehaviour.cCDIK=new IK();ik.SetIKTarget(target);
|
||||
Check(ReferenceEquals(ik.RodBehaviour.cCDIK.solver.target,target),"valid IK behavior changed");
|
||||
Console.WriteLine("PASS actual SetIKTarget: no rod, no IK, normal target");
|
||||
foreach(var scenario in new[]{"normal","cancelled-error","destroyed-error","stopped-error","active-error"}){
|
||||
var stage=new StageSubject();var task=stage.Run();
|
||||
if(scenario=="normal")stage.Gate.SetResult(true);
|
||||
else{
|
||||
if(scenario=="cancelled-error")stage.Lifetime.Cancel();
|
||||
if(scenario=="destroyed-error")stage.Destroyed=true;
|
||||
if(scenario=="stopped-error")stage.stopping=true;
|
||||
stage.Gate.SetException(new InvalidOperationException("released handle"));
|
||||
}
|
||||
if(scenario=="active-error"){
|
||||
try{await task;throw new Exception("active startup error swallowed");}catch(InvalidOperationException){}
|
||||
}else await task;
|
||||
Check(stage.Completed==(scenario=="normal"),"wrong stage continuation");
|
||||
Console.WriteLine("PASS actual FishingStage startup boundary: "+scenario);
|
||||
}
|
||||
public partial class Subject{
|
||||
public bool Destroyed,Applied;public GameObject mapObjPrefab,_mapObj;public object fishingBehavior;public MapData _curMapData=new();
|
||||
public void DestroyImmediate(GameObject go){}
|
||||
public static bool operator ==(Subject a,Subject b)=>ReferenceEquals(b,null)?ReferenceEquals(a,null)||a.Destroyed:ReferenceEquals(a,b);
|
||||
public static bool operator !=(Subject a,Subject b)=>!(a==b);
|
||||
public override bool Equals(object other)=>ReferenceEquals(this,other);public override int GetHashCode()=>base.GetHashCode();
|
||||
}
|
||||
public class MapData{public string EnvName="test";}
|
||||
public class GameObject{public static implicit operator bool(GameObject value)=>value is not null;}
|
||||
public class Transform{}
|
||||
public static class GContext{public static Container container=new();}
|
||||
public class Container{public User User=new();public T Resolve<T>()=>(T)(object)User;}
|
||||
public interface IUserService{CancellationToken LoginLifetime{get;}}
|
||||
public class User:IUserService{public CancellationTokenSource Lifetime=new();public CancellationToken LoginLifetime=>Lifetime.Token;}
|
||||
public static class Addressables{
|
||||
public static TaskCompletionSource<GameObject> Pending;public static List<GameObject> Released=new();
|
||||
public static Handle LoadAssetAsync<T>(string path)=>new();public static void Release(GameObject value)=>Released.Add(value);
|
||||
}
|
||||
public class Handle{public Task<GameObject> Task=>Addressables.Pending.Task;}
|
||||
public partial class IkSubject{public Rod RodBehaviour;}
|
||||
public class Rod{public IK cCDIK;}
|
||||
public class IK{public Solver solver=new();public static implicit operator bool(IK value)=>value is not null;}
|
||||
public class Solver{public Transform target;}
|
||||
public class StageBase{public TaskCompletionSource<bool> Gate=new();public Task StartAsync()=>Gate.Task;}
|
||||
public partial class StageSubject{
|
||||
public CancellationTokenSource Lifetime=new();public bool Completed,Destroyed,stopping;
|
||||
public static bool operator ==(StageSubject a,StageSubject b)=>ReferenceEquals(b,null)?ReferenceEquals(a,null)||a.Destroyed:ReferenceEquals(a,b);
|
||||
public static bool operator !=(StageSubject a,StageSubject b)=>!(a==b);
|
||||
public override bool Equals(object other)=>ReferenceEquals(this,other);public override int GetHashCode()=>base.GetHashCode();
|
||||
}
|
||||
public static class Debug{public static void LogWarning(string message){}}
|
||||
16
CodexOutput/upserver/MapExitTests/generate.py
Normal file
16
CodexOutput/upserver/MapExitTests/generate.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from pathlib import Path
|
||||
s=Path('Client/Assets/Scripts/Stages/FishingAct.cs').read_text(encoding='utf-8-sig')
|
||||
start=s.index('async System.Threading.Tasks.Task LoadMapByCurID()')
|
||||
end=s.index('mapObjPrefab = loadedMapPrefab;',start)+len('mapObjPrefab = loadedMapPrefab;')
|
||||
prefix=s[start:end].replace('async System.Threading.Tasks.Task LoadMapByCurID()', 'public async Task Run()')
|
||||
code='using System;using System.Threading.Tasks;public partial class Subject {\n'+prefix+'\nApplied=true; }\n}\n'
|
||||
s=Path('Client/Assets/Scripts/GampPlay/FishingB/FishingBehaviorB.cs').read_text(encoding='utf-8-sig')
|
||||
start=s.index('void SetIKTarget(Transform target)');a=s.index('{',start);n=1;end=a+1
|
||||
while n:
|
||||
n+=(s[end]=='{')-(s[end]=='}');end+=1
|
||||
code+='public partial class IkSubject {public '+s[start:end]+'\n}\n'
|
||||
s=Path('Client/Assets/Scripts/Stages/FishingStage.cs').read_text(encoding='utf-8-sig')
|
||||
start=s.index('try { await base.StartAsync(); }')
|
||||
end=s.index('//静默加载后续场景',start)
|
||||
code+='public partial class StageSubject : StageBase { public async Task Run(){ var loginLifetime=Lifetime.Token;\n'+s[start:end]+'\nCompleted=true; } }\n'
|
||||
Path('CodexOutput/upserver/MapExitTests/Generated.cs').write_text(code,encoding='utf-8')
|
||||
Reference in New Issue
Block a user