using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text.RegularExpressions;
using Sandbox.ModAPI.Ingame;
using VRage.Game.ModAPI.Ingame.Utilities;
using VRageMath;
using Xunit;
using P = AutoMiningScript.Program;
namespace AutoMiningScript.Tests
{
public class ParameterCommandIntegrationTests
{
static bool Chinese { get { return P.L.Language == "zh-CN"; } }
static void Set(object instance, string name, object value)
{ instance.GetType().GetField(name, BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance, value); }
sealed class RecordingRole : P.RoleLogic
{
readonly Stub<IMyGridProgramRuntimeInfo> runtime;
public string Last = "";
public RecordingRole(P p, Stub<IMyGridProgramRuntimeInfo> r) : base(p) { runtime = r; }
public override void Command(string text) { Last = text; }
public override void Tick(double dt) { runtime.Set("CurrentInstructionCount", 40000); }
}
[Fact]
public void MainTranslatesChineseOperationButPreservesTargetSpelling()
{
if (!Chinese) return;
var p = TestRig.Program(); var runtime = new Stub<IMyGridProgramRuntimeInfo>().Set("MaxInstructionCount", 50000).Set("CurrentInstructionCount", 0);
TestRig.SetBase(p, "Runtime", runtime.Value); var role = new RecordingRole(p, runtime); Set(p, "role", role);
p.Main("返航 Deep Space 一号", UpdateType.Terminal);
Assert.Equal("return Deep Space 一号", role.Last);
}
[Theory]
[InlineData("")]
[InlineData("[Hardware]\nGroup=My Mining Rig\n")]
public void InitializationUsesLocalizedIdentityOnlyForNewEmptyConfiguration(string original)
{
var p = TestRig.Program(); var me = new Stub<IMyProgrammableBlock>().Set("EntityId", 42L).Set("CubeGrid", p.Me.CubeGrid)
.Set("CustomName", "Test PB").Set("CustomData", original).Set("WorldMatrix", MatrixD.Identity);
TestRig.SetBase(p, "Me", me.Value); TestRig.SetBase(p, "GridTerminalSystem", new Stub<IMyGridTerminalSystem>().Value);
// Missing game hardware may leave a self-test fault; parsed identity must still be stable.
typeof(P).GetMethod("Initialize", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(p, null);
Assert.Equal(original.Length == 0 ? P.Settings.DefaultId("miner", 42) : "miner-42", p.Config.Id);
if (original.Length > 0) Assert.Equal(original, me.Value.CustomData);
else Assert.Contains(P.Settings.DefaultFleetId, me.Value.CustomData);
}
[Fact]
public void ChineseMarkerAndDirectMarkingAcceptGpsWithoutTranslatingPayload()
{
if (!Chinese) return;
var p = TestRig.Program(); TestRig.SetBase(p, "GridTerminalSystem", new Stub<IMyGridTerminalSystem>().Value);
var packets = new List<P.Packet>(); var broadcast = new Stub<IMyBroadcastListener>(); var unicast = new Stub<IMyUnicastListener>();
var igc = new Stub<IMyIntergridCommunicationSystem>().Set("UnicastListener", unicast.Value)
.Method("RegisterBroadcastListener", a => broadcast.Value).Method("SendBroadcastMessage", a =>
{ P.Packet packet; Assert.True(P.Packet.TryDecode((string)a[1], "mining", out packet)); packets.Add(packet); return null; });
TestRig.SetBase(p, "IGC", igc.Value); p.Bus = new P.Wire(p);
const string command = "标点 12 6 40 GPS:Surface CASE:0:0:0: GPS:Inside CASE:0:0:-1:";
var mark = P.Marking.Parse(p, command); Assert.Equal(Vector3D.Zero, P.Data.ReadVector(mark, "mark", "Entry", Vector3D.One));
new P.MarkerController(p).Command(command);
var packet = Assert.Single(packets); Assert.Equal("MARK", packet.Kind);
Assert.Equal(12, P.Data.ReadNumber(packet.Body, "mark", "Width", 0));
Assert.Equal(Vector3D.Forward, P.Data.ReadVector(packet.Body, "mark", "Direction", Vector3D.Zero));
}
[Fact]
public void ChineseWatchdogCommandsUseExistingArmingHandshake()
{
if (!Chinese) return;
var p = TestRig.Program(); p.Now = 5;
TestRig.SetBase(p, "GridTerminalSystem", new Stub<IMyGridTerminalSystem>().Value);
var watchdog = new P.WatchdogController(p); watchdog.Command("布防");
Assert.Contains(p.Events, e => e.Contains(P.L.FleetWatchdogHeartbeatMissing));
Set(watchdog, "heartbeat", 5.0); watchdog.Command("布防");
Assert.Contains(P.L.FleetWatchdogArmed, watchdog.Diagnostics);
watchdog.Command("触发保护"); Assert.Contains(P.L.FleetWatchdogFault, watchdog.Diagnostics);
}
[Fact]
public void ChineseHelpResourcesNeverInstructEnglishUserCommandsOrConfigPaths()
{
if (!Chinese) return;
string[] commands = { "init", "diagnose", "calibrate", "mark", "survey", "start", "pause", "resume", "return", "release", "rescan", "arm", "trip", "page" };
foreach (var field in typeof(P.L).GetFields(BindingFlags.Static | BindingFlags.Public))
{
if (field.Name.StartsWith("Param", StringComparison.Ordinal)) continue;
string value = field.GetValue(null) as string; if (value == null) continue;
foreach (string command in commands)
Assert.DoesNotMatch("(?<![A-Za-z0-9_])" + command + "(?![A-Za-z0-9_-])", value);
Assert.DoesNotMatch("(?:Flight|Mining|Fleet|Hardware|Display|Cargo|Survey|Marker)\\.[A-Z][A-Za-z]+", value);
}
}
}
}
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text.RegularExpressions;
using Sandbox.ModAPI.Ingame;
using VRage.Game.ModAPI.Ingame.Utilities;
using VRageMath;
using Xunit;
using P = AutoMiningScript.Program;
namespace AutoMiningScript.Tests
{
public class ParameterCommandIntegrationTests
{
static bool Chinese { get { return P.L.Language == "zh-CN"; } }
static void Set(object instance, string name, object value)
{ instance.GetType().GetField(name, BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance, value); }
sealed class RecordingRole : P.RoleLogic
{
readonly Stub<IMyGridProgramRuntimeInfo> runtime;
public string Last = "";
public RecordingRole(P p, Stub<IMyGridProgramRuntimeInfo> r) : base(p) { runtime = r; }
public override void Command(string text) { Last = text; }
public override void Tick(double dt) { runtime.Set("CurrentInstructionCount", 40000); }
}
[Fact]
public void MainTranslatesChineseOperationButPreservesTargetSpelling()
{
if (!Chinese) return;
var p = TestRig.Program(); var runtime = new Stub<IMyGridProgramRuntimeInfo>().Set("MaxInstructionCount", 50000).Set("CurrentInstructionCount", 0);
TestRig.SetBase(p, "Runtime", runtime.Value); var role = new RecordingRole(p, runtime); Set(p, "role", role);
p.Main("返航 Deep Space 一号", UpdateType.Terminal);
Assert.Equal("return Deep Space 一号", role.Last);
}
[Theory]
[InlineData("")]
[InlineData("[Hardware]\nGroup=My Mining Rig\n")]
public void InitializationUsesLocalizedIdentityOnlyForNewEmptyConfiguration(string original)
{
var p = TestRig.Program(); var me = new Stub<IMyProgrammableBlock>().Set("EntityId", 42L).Set("CubeGrid", p.Me.CubeGrid)
.Set("CustomName", "Test PB").Set("CustomData", original).Set("WorldMatrix", MatrixD.Identity);
TestRig.SetBase(p, "Me", me.Value); TestRig.SetBase(p, "GridTerminalSystem", new Stub<IMyGridTerminalSystem>().Value);
// Missing game hardware may leave a self-test fault; parsed identity must still be stable.
typeof(P).GetMethod("Initialize", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(p, null);
Assert.Equal(original.Length == 0 ? P.Settings.DefaultId("miner", 42) : "miner-42", p.Config.Id);
if (original.Length > 0) Assert.Equal(original, me.Value.CustomData);
else Assert.Contains(P.Settings.DefaultFleetId, me.Value.CustomData);
}
[Fact]
public void ChineseMarkerAndDirectMarkingAcceptGpsWithoutTranslatingPayload()
{
if (!Chinese) return;
var p = TestRig.Program(); TestRig.SetBase(p, "GridTerminalSystem", new Stub<IMyGridTerminalSystem>().Value);
var packets = new List<P.Packet>(); var broadcast = new Stub<IMyBroadcastListener>(); var unicast = new Stub<IMyUnicastListener>();
var igc = new Stub<IMyIntergridCommunicationSystem>().Set("UnicastListener", unicast.Value)
.Method("RegisterBroadcastListener", a => broadcast.Value).Method("SendBroadcastMessage", a =>
{ P.Packet packet; Assert.True(P.Packet.TryDecode((string)a[1], "mining", out packet)); packets.Add(packet); return null; });
TestRig.SetBase(p, "IGC", igc.Value); p.Bus = new P.Wire(p);
const string command = "标点 12 6 40 GPS:Surface CASE:0:0:0: GPS:Inside CASE:0:0:-1:";
var mark = P.Marking.Parse(p, command); Assert.Equal(Vector3D.Zero, P.Data.ReadVector(mark, "mark", "Entry", Vector3D.One));
new P.MarkerController(p).Command(command);
var packet = Assert.Single(packets); Assert.Equal("MARK", packet.Kind);
Assert.Equal(12, P.Data.ReadNumber(packet.Body, "mark", "Width", 0));
Assert.Equal(Vector3D.Forward, P.Data.ReadVector(packet.Body, "mark", "Direction", Vector3D.Zero));
}
[Fact]
public void ChineseWatchdogCommandsUseExistingArmingHandshake()
{
if (!Chinese) return;
var p = TestRig.Program(); p.Now = 5;
TestRig.SetBase(p, "GridTerminalSystem", new Stub<IMyGridTerminalSystem>().Value);
var watchdog = new P.WatchdogController(p); watchdog.Command("布防");
Assert.Contains(p.Events, e => e.Contains(P.L.FleetWatchdogHeartbeatMissing));
Set(watchdog, "heartbeat", 5.0); watchdog.Command("布防");
Assert.Contains(P.L.FleetWatchdogArmed, watchdog.Diagnostics);
watchdog.Command("触发保护"); Assert.Contains(P.L.FleetWatchdogFault, watchdog.Diagnostics);
}
[Fact]
public void ChineseHelpResourcesNeverInstructEnglishUserCommandsOrConfigPaths()
{
if (!Chinese) return;
string[] commands = { "init", "diagnose", "calibrate", "mark", "survey", "start", "pause", "resume", "return", "release", "rescan", "arm", "trip", "page" };
foreach (var field in typeof(P.L).GetFields(BindingFlags.Static | BindingFlags.Public))
{
if (field.Name.StartsWith("Param", StringComparison.Ordinal)) continue;
string value = field.GetValue(null) as string; if (value == null) continue;
foreach (string command in commands)
Assert.DoesNotMatch("(?<![A-Za-z0-9_])" + command + "(?![A-Za-z0-9_-])", value);
Assert.DoesNotMatch("(?:Flight|Mining|Fleet|Hardware|Display|Cargo|Survey|Marker)\\.[A-Z][A-Za-z]+", value);
}
}
}
}