using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Serialization;
using Sandbox.ModAPI.Ingame;
using VRage.Game.ModAPI.Ingame;
using VRageMath;
using P=AutoMiningScript.Program;
namespace AutoMiningScript.Tests
{
// Interface proxies exercise the real production code against controlled game observations.
// These are not physics simulators and are not included in any PB artifact.
public sealed class Stub<T> : RealProxy where T:class
{
public readonly Dictionary<string,object> Values=new Dictionary<string,object>();
public readonly Dictionary<string,Func<object[],object>> Methods=new Dictionary<string,Func<object[],object>>();
public readonly T Value;
public Stub():base(typeof(T)) {Value=(T)GetTransparentProxy();}
public Stub<T> Set(string name,object value) {Values[name]=value;return this;}
public Stub<T> Method(string name,Func<object[],object> method) {Methods[name]=method;return this;}
public override IMessage Invoke(IMessage message)
{
var call=(IMethodCallMessage)message;var method=(MethodInfo)call.MethodBase;object result=null;
try
{
if(call.MethodName.StartsWith("set_"))Values[call.MethodName.Substring(4)]=call.Args[0];
else if(call.MethodName.StartsWith("get_") && Values.ContainsKey(call.MethodName.Substring(4)))result=Values[call.MethodName.Substring(4)];
else if(Methods.ContainsKey(call.MethodName))result=Methods[call.MethodName](call.Args);
if(result==null && method.ReturnType!=typeof(void) && method.ReturnType.IsValueType)result=Activator.CreateInstance(method.ReturnType);
return new ReturnMessage(result,call.Args,call.ArgCount,call.LogicalCallContext,call);
}
catch(Exception e) {return new ReturnMessage(e,call);}
}
}
public static class TestRig
{
public static P Program(string config="")
{
var p=(P)FormatterServices.GetUninitializedObject(typeof(P));
p.Config=new P.Settings(config,"miner","test");
typeof(P).GetField("Events").SetValue(p,new Queue<string>());
var grid=new Stub<IMyCubeGrid>().Set("EntityId",10L).Set("GridSize",2.5f);
var me=new Stub<IMyProgrammableBlock>().Set("CubeGrid",grid.Value).Set("EntityId",20L).Set("WorldMatrix",MatrixD.Identity).Method("GetPosition",a=>Vector3D.Zero);
SetBase(p,"Me",me.Value);
var runtime=new Stub<IMyGridProgramRuntimeInfo>().Set("MaxInstructionCount",100000).Set("CurrentInstructionCount",0);
SetBase(p,"Runtime",runtime.Value);
SetBase(p,"Echo",(Action<string>)(s=>{}));
return p;
}
public static void SetBase(P p,string name,object value)
{
if(name=="IGC")
{
typeof(MyGridProgram).GetField("m_IGC_ContextGetter",BindingFlags.Instance|BindingFlags.NonPublic).SetValue(p,(Func<IMyIntergridCommunicationSystem>)(()=> (IMyIntergridCommunicationSystem)value));return;
}
var property=typeof(MyGridProgram).GetProperty(name,BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
if(property!=null && property.GetSetMethod(true)!=null) {property.GetSetMethod(true).Invoke(p,new[]{value});return;}
var field=typeof(MyGridProgram).GetField("<"+name+">k__BackingField",BindingFlags.Instance|BindingFlags.NonPublic);
if(field==null)
{
throw new Exception("Cannot inject game property "+name);
}
field.SetValue(p,value);
}
public static Stub<IMyBatteryBlock> Battery(P p,float stored,float capacity)
{
return new Stub<IMyBatteryBlock>().Set("CubeGrid",p.Me.CubeGrid).Set("IsFunctional",true).Set("CurrentStoredPower",stored).Set("MaxStoredPower",capacity).Set("CurrentInput",0f).Set("CurrentOutput",0.01f);
}
public static Stub<IMyShipConnector> Connector(P p,bool connected)
{
return new Stub<IMyShipConnector>().Set("CubeGrid",p.Me.CubeGrid).Set("Status",connected?MyShipConnectorStatus.Connected:MyShipConnectorStatus.Unconnected).Set("IsFunctional",true);
}
}
}
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Serialization;
using Sandbox.ModAPI.Ingame;
using VRage.Game.ModAPI.Ingame;
using VRageMath;
using P=AutoMiningScript.Program;
namespace AutoMiningScript.Tests
{
// Interface proxies exercise the real production code against controlled game observations.
// These are not physics simulators and are not included in any PB artifact.
public sealed class Stub<T> : RealProxy where T:class
{
public readonly Dictionary<string,object> Values=new Dictionary<string,object>();
public readonly Dictionary<string,Func<object[],object>> Methods=new Dictionary<string,Func<object[],object>>();
public readonly T Value;
public Stub():base(typeof(T)) {Value=(T)GetTransparentProxy();}
public Stub<T> Set(string name,object value) {Values[name]=value;return this;}
public Stub<T> Method(string name,Func<object[],object> method) {Methods[name]=method;return this;}
public override IMessage Invoke(IMessage message)
{
var call=(IMethodCallMessage)message;var method=(MethodInfo)call.MethodBase;object result=null;
try
{
if(call.MethodName.StartsWith("set_"))Values[call.MethodName.Substring(4)]=call.Args[0];
else if(call.MethodName.StartsWith("get_") && Values.ContainsKey(call.MethodName.Substring(4)))result=Values[call.MethodName.Substring(4)];
else if(Methods.ContainsKey(call.MethodName))result=Methods[call.MethodName](call.Args);
if(result==null && method.ReturnType!=typeof(void) && method.ReturnType.IsValueType)result=Activator.CreateInstance(method.ReturnType);
return new ReturnMessage(result,call.Args,call.ArgCount,call.LogicalCallContext,call);
}
catch(Exception e) {return new ReturnMessage(e,call);}
}
}
public static class TestRig
{
public static P Program(string config="")
{
var p=(P)FormatterServices.GetUninitializedObject(typeof(P));
p.Config=new P.Settings(config,"miner","test");
typeof(P).GetField("Events").SetValue(p,new Queue<string>());
var grid=new Stub<IMyCubeGrid>().Set("EntityId",10L).Set("GridSize",2.5f);
var me=new Stub<IMyProgrammableBlock>().Set("CubeGrid",grid.Value).Set("EntityId",20L).Set("WorldMatrix",MatrixD.Identity).Method("GetPosition",a=>Vector3D.Zero);
SetBase(p,"Me",me.Value);
var runtime=new Stub<IMyGridProgramRuntimeInfo>().Set("MaxInstructionCount",100000).Set("CurrentInstructionCount",0);
SetBase(p,"Runtime",runtime.Value);
SetBase(p,"Echo",(Action<string>)(s=>{}));
return p;
}
public static void SetBase(P p,string name,object value)
{
if(name=="IGC")
{
typeof(MyGridProgram).GetField("m_IGC_ContextGetter",BindingFlags.Instance|BindingFlags.NonPublic).SetValue(p,(Func<IMyIntergridCommunicationSystem>)(()=> (IMyIntergridCommunicationSystem)value));return;
}
var property=typeof(MyGridProgram).GetProperty(name,BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
if(property!=null && property.GetSetMethod(true)!=null) {property.GetSetMethod(true).Invoke(p,new[]{value});return;}
var field=typeof(MyGridProgram).GetField("<"+name+">k__BackingField",BindingFlags.Instance|BindingFlags.NonPublic);
if(field==null)
{
throw new Exception("Cannot inject game property "+name);
}
field.SetValue(p,value);
}
public static Stub<IMyBatteryBlock> Battery(P p,float stored,float capacity)
{
return new Stub<IMyBatteryBlock>().Set("CubeGrid",p.Me.CubeGrid).Set("IsFunctional",true).Set("CurrentStoredPower",stored).Set("MaxStoredPower",capacity).Set("CurrentInput",0f).Set("CurrentOutput",0.01f);
}
public static Stub<IMyShipConnector> Connector(P p,bool connected)
{
return new Stub<IMyShipConnector>().Set("CubeGrid",p.Me.CubeGrid).Set("Status",connected?MyShipConnectorStatus.Connected:MyShipConnectorStatus.Unconnected).Set("IsFunctional",true);
}
}
}