Files
BQP/srcs/RobotNet10/Tests/RobotNet10.ScriptEngine.Test/ScriptEngineTests.cs
2026-07-13 09:25:40 +07:00

231 lines
7.3 KiB
C#

using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Moq;
using RobotNet10.ScriptEngine;
using RobotNet10.ScriptEngine.Enums;
using RobotNet10.ScriptEngine.Helpers;
using RobotNet10.ScriptEngine.Hubs;
using RobotNet10.ScriptEngine.Models;
using RobotNet10.ScriptEngine.Shared;
using RobotNet10.ScriptEngine.Test.Helpers;
using RobotNet10.Shared;
namespace RobotNet10.ScriptEngine.Test;
[TestFixture]
public class ScriptEngineTests
{
private ScriptEngine _scriptEngine = null!;
private Mock<IScriptEngineResource> _mockResource = null!;
private FileManager _fileManager = null!;
private VariableManager _variableManager = null!;
private TaskManager _taskManager = null!;
private MissionManager _missionManager = null!;
private Mock<ILogger<ScriptEngine>> _mockLogger = null!;
private Mock<IConfiguration> _mockConfiguration = null!;
private Mock<IHubContext<ScriptManagerHub>> _mockHubContext = null!;
private string _testScriptPath = null!;
[SetUp]
public void SetUp()
{
_testScriptPath = Path.Combine(Path.GetTempPath(), "ScriptEngineTest", Guid.NewGuid().ToString());
Directory.CreateDirectory(_testScriptPath);
_mockResource = TestHelpers.CreateMockScriptResource();
_mockLogger = new Mock<ILogger<ScriptEngine>>();
_mockConfiguration = new Mock<IConfiguration>();
_mockHubContext = TestHelpers.CreateMockHubContext();
var mockConsoleHubContext = TestHelpers.CreateMockConsoleHubContext();
var mockLoggerGlobals = TestHelpers.CreateMockLogger();
var configuration = TestHelpers.CreateMockConfiguration();
var mockScopeFactory = Mock.Of<IServiceScopeFactory>();
_variableManager = new VariableManager();
_fileManager = new FileManager();
_fileManager.RootPath = _testScriptPath;
_taskManager = new TaskManager(
_variableManager,
_mockResource.Object,
mockLoggerGlobals.Object,
mockScopeFactory,
mockConsoleHubContext.Object,
configuration);
_missionManager = new MissionManager(
mockScopeFactory,
_variableManager,
_mockResource.Object,
mockLoggerGlobals.Object,
mockConsoleHubContext.Object,
configuration);
_scriptEngine = new ScriptEngine(
_mockResource.Object,
_mockConfiguration.Object,
_fileManager,
_variableManager,
_taskManager,
_missionManager,
_mockLogger.Object,
_mockHubContext.Object,
mockConsoleHubContext.Object);
}
[TearDown]
public void TearDown()
{
_scriptEngine?.Dispose();
_taskManager?.Dispose();
_missionManager?.Dispose();
if (Directory.Exists(_testScriptPath))
{
Directory.Delete(_testScriptPath, true);
}
}
[Test]
public void Constructor_ShouldInitializeToIdleState()
{
// Assert
Assert.That(_scriptEngine.State, Is.EqualTo(ScriptEngineState.Idle));
}
[Test]
public void Build_WithValidScript_ShouldTransitionToReady()
{
// Arrange
var scriptFile = Path.Combine(_testScriptPath, "test.cs");
File.WriteAllText(scriptFile, @"
using RobotNet10.Script;
public class DummyClass
{
[Variable]
public int TestVar = 42;
}
");
// Act
var result = _scriptEngine.Build();
// Assert
Assert.That(result.IsSuccess, Is.True);
// Wait a bit for async build to complete
Thread.Sleep(500);
Assert.That(_scriptEngine.State, Is.EqualTo(ScriptEngineState.Ready).Or.EqualTo(ScriptEngineState.Building));
}
[Test]
public void Build_WithInvalidScript_ShouldTransitionToBuildError()
{
// Arrange
var scriptFile = Path.Combine(_testScriptPath, "test.cs");
File.WriteAllText(scriptFile, "invalid syntax here");
// Act
var result = _scriptEngine.Build();
// Assert
Assert.That(result.IsSuccess, Is.True); // Build initiation succeeds
// Wait a bit for async build to complete
Thread.Sleep(500);
Assert.That(_scriptEngine.State, Is.EqualTo(ScriptEngineState.BuildError).Or.EqualTo(ScriptEngineState.Building));
}
[Test]
public void Build_WhenNotIdle_ShouldFail()
{
// Arrange
var scriptFile = Path.Combine(_testScriptPath, "test.cs");
File.WriteAllText(scriptFile, "public class DummyClass { }");
_scriptEngine.Build();
Thread.Sleep(500); // Wait for build to complete
_scriptEngine.Start();
Thread.Sleep(500); // Wait for start to complete
// Act
var result = _scriptEngine.Build();
// Assert
Assert.That(result.IsSuccess, Is.False);
}
[Test]
public void Start_WhenReady_ShouldTransitionToRunning()
{
// Arrange
var scriptFile = Path.Combine(_testScriptPath, "test.cs");
File.WriteAllText(scriptFile, "public class DummyClass { }");
_scriptEngine.Build();
Thread.Sleep(1000); // Wait for build to complete
// Act
var result = _scriptEngine.Start();
// Assert
Assert.That(result.IsSuccess, Is.True);
Thread.Sleep(500);
Assert.That(_scriptEngine.State, Is.EqualTo(ScriptEngineState.Running).Or.EqualTo(ScriptEngineState.Starting));
}
[Test]
public void Start_WhenNotReady_ShouldFail()
{
// Act
var result = _scriptEngine.Start();
// Assert
Assert.That(result.IsSuccess, Is.False);
}
[Test]
public void Stop_WhenRunning_ShouldTransitionToReady()
{
// Arrange
var scriptFile = Path.Combine(_testScriptPath, "test.cs");
File.WriteAllText(scriptFile, "public class DummyClass { }");
_scriptEngine.Build();
Thread.Sleep(1000);
_scriptEngine.Start();
Thread.Sleep(1000);
// Act
var result = _scriptEngine.Stop();
// Assert
Assert.That(result.IsSuccess, Is.True);
Thread.Sleep(2000); // Wait for stop to complete
Assert.That(_scriptEngine.State, Is.EqualTo(ScriptEngineState.Ready).Or.EqualTo(ScriptEngineState.Stopping));
}
[Test]
public void Reset_ShouldTransitionToIdle()
{
// Arrange
var scriptFile = Path.Combine(_testScriptPath, "test.cs");
File.WriteAllText(scriptFile, "public class DummyClass { }");
_scriptEngine.Build();
Thread.Sleep(1000);
// Act
var result = _scriptEngine.Reset();
// Assert
Assert.That(result.IsSuccess, Is.True);
Thread.Sleep(500);
Assert.That(_scriptEngine.State, Is.EqualTo(ScriptEngineState.Idle).Or.EqualTo(ScriptEngineState.Resetting));
}
[Test]
public void Dispose_ShouldCleanupResources()
{
// Act & Assert
Assert.DoesNotThrow(() => _scriptEngine.Dispose());
}
}