using System; using NUnit.Framework; using NcProgramManager.Cnc.Models; using NcProgramManager.Cnc.Siemens; using NcProgramManager.Tests.Integration.Stubs; namespace NcProgramManager.Tests.Integration { [TestFixture] [Category("Integration")] public class SiemensMachineIntegrationTests { private FtpServerStub _stub; private SiemensMachine _machine; private const string ProgramDir = "/_N_MPF_DIR/"; [SetUp] public void SetUp() { _stub = new FtpServerStub(); var config = new SiemensConnectionConfig { Name = "SiemensIntegration", IpAddress = "127.0.0.1", Port = _stub.Port, Username = "user", Password = "pass", ProgramDirectory = ProgramDir, RequestTimeout = TimeSpan.FromSeconds(5) }; _machine = new SiemensMachine(config); } [TearDown] public void TearDown() { _machine?.Dispose(); _stub?.Dispose(); } [Test] public void ConnectAsync_StubListens_ResultOk() { var result = _machine.ConnectAsync().GetAwaiter().GetResult(); Assert.That(result.Success, Is.True); Assert.That(_machine.State, Is.EqualTo(ConnectionState.Connected)); } [Test] public void WriteThenRead_ProgramRoundTrips() { _machine.ConnectAsync().GetAwaiter().GetResult(); // Siemens: name must end with .MPF; no semicolons; no lowercase string content = "G0 X0 Y0\nM30"; var prog = new CncProgram { Name = "O1234.MPF", Content = content }; var writeResult = _machine.WriteProgramAsync(ProgramDir, prog).GetAwaiter().GetResult(); Assert.That(writeResult.Success, Is.True); // Determine where SiemensMachine stored the file string storedPath = ProgramDir + "O1234.MPF"; var readResult = _machine.ReadProgramAsync(storedPath).GetAwaiter().GetResult(); Assert.That(readResult.Success, Is.True); Assert.That(readResult.Value, Is.EqualTo(content)); } [Test] public void DeleteProgramAsync_FileExistsInStub_RemovedFromStub() { _machine.ConnectAsync().GetAwaiter().GetResult(); string path = ProgramDir + "O5678.MPF"; _stub.Files[path] = "SOME_CONTENT"; var result = _machine.DeleteProgramAsync(path).GetAwaiter().GetResult(); Assert.That(result.Success, Is.True); Assert.That(_stub.Files.ContainsKey(path), Is.False); } [Test] public void ReadProgramAsync_FileNotInStub_ResultFail() { _machine.ConnectAsync().GetAwaiter().GetResult(); var result = _machine.ReadProgramAsync(ProgramDir + "DOESNOTEXIST.MPF").GetAwaiter().GetResult(); Assert.That(result.Success, Is.False); } [Test] public void WriteProgramAsync_InvalidName_ValidationFails() { _machine.ConnectAsync().GetAwaiter().GetResult(); // Siemens requires .MPF extension — validator rejects before any FTP call var prog = new CncProgram { Name = "INVALID", Content = "G00 X10\nM30" }; var result = _machine.WriteProgramAsync(ProgramDir, prog).GetAwaiter().GetResult(); Assert.That(result.Success, Is.False); } [Test] [Category("Hardware")] public void Hardware_ConnectAsync_RealMachine() { string ip = HardwareTestHelper.GetIpOrSkip("SIEMENS_IP"); var config = new SiemensConnectionConfig { Name = "SiemensHardware", IpAddress = ip, Port = 21, Username = Environment.GetEnvironmentVariable("SIEMENS_USER") ?? "user", Password = Environment.GetEnvironmentVariable("SIEMENS_PASS") ?? "pass", ProgramDirectory = "/_N_MPF_DIR/", RequestTimeout = TimeSpan.FromSeconds(10) }; using (var machine = new SiemensMachine(config)) { var result = machine.ConnectAsync().GetAwaiter().GetResult(); Assert.That(result.Success, Is.True, "ConnectAsync failed: " + result.Error); } } } }