Files
ft/CodexOutput/upserver/KVGameplayLoopTests/Program.cs

41 lines
3.3 KiB
C#

using System.Reflection;
using System.Security.Cryptography;
using Newtonsoft.Json;
var root=Path.GetFullPath(Path.Combine("CodexOutput/upserver/KVGameplayLoopTests/runs",Guid.NewGuid().ToString("N")));
Directory.CreateDirectory(root);
int assertions=0;
void Check(bool yes,string why){assertions++;if(!yes)throw new Exception(why);}
try {
var type=Assembly.GetExecutingAssembly().GetType("game.PlayerDataStorage.PlayerKVLoopPermit");
Check(type!=null,"Missing approved loop permit validation");
object Load(string file)=>type.GetMethod("Read",BindingFlags.Static|BindingFlags.NonPublic).Invoke(null,new object[]{file});
void Reject(string file,string why){bool bad=false;try{Load(file);}catch(TargetInvocationException e){bad=e.InnerException is InvalidOperationException;}Check(bad,why);}
var backup=Path.Combine(root,"backup.json");File.WriteAllText(backup,JsonConvert.SerializeObject(new{playerId="101",api="http://s101.local:18080/",data=new Dictionary<string,string>{{"NewPlayerDataDic","{}"},{"k","v"}}}));
var digest=Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(backup)));
var permit=Path.Combine(root,"permit.json");
void Put(string id="101",string api="http://s101.local:18080/",string hash=null,string[] keys=null)=>File.WriteAllText(permit,JsonConvert.SerializeObject(new{Version=1,Enabled=true,PlayerId=id,Api=api,BackupPath=backup,BackupSha256=hash??digest,AllowedKeys=keys??new[]{"NewPlayerDataDic","k"}}));
Put();var value=Load(permit);Check(value!=null,"valid explicit permit");
Put(id:"102");Reject(permit,"backup account must match");
Put(id:"103");Reject(permit,"outside user-selected accounts");
Put(api:"http://elsewhere.invalid/");Reject(permit,"fixed formal API");
Put(hash:new string('0',64));Reject(permit,"backup integrity");
Put(keys:Array.Empty<string>());Reject(permit,"no empty permission");
Put(keys:new[]{"k"});Reject(permit,"core whole-save permission required");
Put(keys:new[]{"NewPlayerDataDic","new-unbacked-key"});Reject(permit,"no keys absent from backup without new reviewed fixture");
Put(keys:new[]{"NewPlayerDataDic","NewPlayerDataDic"});Reject(permit,"duplicate key permission rejected");
var originalBackup=File.ReadAllBytes(backup);
File.WriteAllText(backup,JsonConvert.SerializeObject(new{playerId="101",api="http://s101.local:18080/",data=new Dictionary<string,string>()}));
digest=Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(backup)));
Put(keys:new[]{"NewPlayerDataDic"});Reject(permit,"actual empty existing save cannot enable loop");
File.WriteAllBytes(backup,originalBackup);digest=Convert.ToHexString(SHA256.HashData(originalBackup));
Put();value=Load(permit);
var claim=type.GetMethod("Claim",BindingFlags.Static|BindingFlags.NonPublic);
string Claim(string instance)=>(string)claim.Invoke(null,new object[]{root,instance});
var marker=Claim("process-1");Check(File.Exists(marker),"durable claim");
bool denied=false;try{Claim("process-1");}catch(TargetInvocationException e){denied=e.InnerException is IOException;}Check(denied,"same process and reload rejected");
Check(File.Exists(Claim("process-2")),"new process can claim");
Check(File.Exists(marker),"old process mark retained");
Console.WriteLine($"PASS permit-and-process-claim assertions={assertions} root={root}");return 0;
}catch(Exception e){Console.WriteLine($"FAIL assertions={assertions} {e}");return 1;}