using System; using NUnit.Framework; using NcProgramManager.Cnc.Models; using NcProgramManager.Cnc.Fagor; using NcProgramManager.Tests.Integration.Stubs; namespace NcProgramManager.Tests.Integration { [TestFixture] [Category("Integration")] public class FagorMachineIntegrationTests { private FtpServerStub _stub; private FagorMachine _machine; private const string ProgramDir = "/Users/Prg/"; [SetUp] public void SetUp() { _stub = new FtpServerStub(); var config = new FagorConnectionConfig { Name = "FagorIntegration", IpAddress = "127.0.0.1", Port = _stub.Port, Username = "user", Password = "pass", ProgramDirectory = ProgramDir, ProgramExtension = ".nc", RequestTimeout = TimeSpan.FromSeconds(5) }; _machine = new FagorMachine(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(); string content = "G0 X0 Y0\nM30"; var prog = new CncProgram { Name = "PROG1", Content = content }; var writeResult = _machine.WriteProgramAsync(ProgramDir, prog).GetAwaiter().GetResult(); Assert.That(writeResult.Success, Is.True); // ProgramExtension ".nc" applied by FagorMachine string storedPath = ProgramDir + "PROG1.nc"; 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 + "PROG2.nc"; _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.nc").GetAwaiter().GetResult(); Assert.That(result.Success, Is.False); } [Test] public void WriteProgramAsync_InvalidName_ValidationFails() { _machine.ConnectAsync().GetAwaiter().GetResult(); // Fagor name max 24 chars — 25 'A' triggers validator failure var prog = new CncProgram { Name = new string('A', 25), 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("FAGOR_TEST_IP"); var config = new FagorConnectionConfig { Name = "FagorHardware", IpAddress = ip, Port = 21, Username = Environment.GetEnvironmentVariable("FAGOR_USER") ?? "user", Password = Environment.GetEnvironmentVariable("FAGOR_PASS") ?? "pass", ProgramDirectory = "/Users/Prg/", ProgramExtension = ".nc", RequestTimeout = TimeSpan.FromSeconds(10) }; using (var machine = new FagorMachine(config)) { var result = machine.ConnectAsync().GetAwaiter().GetResult(); Assert.That(result.Success, Is.True, "ConnectAsync failed: " + result.Error); } } } }