165 lines
4.6 KiB
C#
165 lines
4.6 KiB
C#
using System.Net;
|
|
using System.Text.Json;
|
|
using Flyshot.Core.Domain;
|
|
using Flyshot.Runtime.Common;
|
|
using Microsoft.AspNetCore.Mvc.Testing;
|
|
using Microsoft.AspNetCore.Hosting;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
|
|
|
namespace Flyshot.Server.IntegrationTests;
|
|
|
|
/// <summary>
|
|
/// 使用可控 fake runtime 启动测试宿主,避免集成测试访问真实 FANUC 控制器。
|
|
/// </summary>
|
|
public sealed class FlyshotServerFactory : WebApplicationFactory<Program>
|
|
{
|
|
/// <inheritdoc />
|
|
protected override void ConfigureWebHost(IWebHostBuilder builder)
|
|
{
|
|
builder.ConfigureServices(services =>
|
|
{
|
|
services.RemoveAll<IControllerRuntime>();
|
|
services.AddSingleton<IControllerRuntime, IntegrationFakeControllerRuntime>();
|
|
});
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 为 HTTP 集成测试提供不访问硬件的控制器运行时。
|
|
/// </summary>
|
|
internal sealed class IntegrationFakeControllerRuntime : IControllerRuntime
|
|
{
|
|
private RobotProfile? _robot;
|
|
private bool _connected;
|
|
private bool _enabled;
|
|
private double _speedRatio = 1.0;
|
|
private double[] _tcp = [0.0, 0.0, 0.0];
|
|
private double[] _joints = Array.Empty<double>();
|
|
private double[] _pose = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0];
|
|
|
|
/// <inheritdoc />
|
|
public void ResetRobot(RobotProfile robot, string robotName)
|
|
{
|
|
_robot = robot;
|
|
_connected = false;
|
|
_enabled = false;
|
|
_joints = new double[robot.DegreesOfFreedom];
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void Connect(string robotIp)
|
|
{
|
|
_ = _robot ?? throw new InvalidOperationException("Robot has not been setup.");
|
|
_connected = true;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void Disconnect()
|
|
{
|
|
_connected = false;
|
|
_enabled = false;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void EnableRobot(int bufferSize)
|
|
{
|
|
if (!_connected)
|
|
{
|
|
throw new InvalidOperationException("Controller has not been connected.");
|
|
}
|
|
|
|
_enabled = true;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void DisableRobot() => _enabled = false;
|
|
|
|
/// <inheritdoc />
|
|
public void StopMove()
|
|
{
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public double GetSpeedRatio() => _speedRatio;
|
|
|
|
/// <inheritdoc />
|
|
public void SetSpeedRatio(double ratio) => _speedRatio = ratio;
|
|
|
|
/// <inheritdoc />
|
|
public IReadOnlyList<double> GetTcp() => _tcp.ToArray();
|
|
|
|
/// <inheritdoc />
|
|
public void SetTcp(double x, double y, double z) => _tcp = [x, y, z];
|
|
|
|
/// <inheritdoc />
|
|
public bool GetIo(int port, string ioType) => false;
|
|
|
|
/// <inheritdoc />
|
|
public void SetIo(int port, bool value, string ioType)
|
|
{
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public IReadOnlyList<double> GetJointPositions() => _joints.ToArray();
|
|
|
|
/// <inheritdoc />
|
|
public IReadOnlyList<double> GetPose() => _pose.ToArray();
|
|
|
|
/// <inheritdoc />
|
|
public ControllerStateSnapshot GetSnapshot()
|
|
{
|
|
return new ControllerStateSnapshot(
|
|
DateTimeOffset.UtcNow,
|
|
_connected ? "Connected" : "Disconnected",
|
|
_enabled,
|
|
false,
|
|
_speedRatio,
|
|
_joints,
|
|
_pose,
|
|
Array.Empty<RuntimeAlarm>());
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void ExecuteTrajectory(TrajectoryResult result, IReadOnlyList<double> finalJointPositions)
|
|
{
|
|
if (!_enabled)
|
|
{
|
|
throw new InvalidOperationException("Robot has not been enabled.");
|
|
}
|
|
|
|
_joints = finalJointPositions.ToArray();
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void ExecuteCartesianTrajectory(TrajectoryResult result, IReadOnlyList<double> finalPose)
|
|
{
|
|
if (!_enabled)
|
|
{
|
|
throw new InvalidOperationException("Robot has not been enabled.");
|
|
}
|
|
|
|
_pose = [.. finalPose, 1.0];
|
|
}
|
|
}
|
|
|
|
public sealed class HealthEndpointTests(FlyshotServerFactory factory) : IClassFixture<FlyshotServerFactory>
|
|
{
|
|
[Fact]
|
|
public async Task GetHealthz_ReturnsOkPayload()
|
|
{
|
|
using var client = factory.CreateClient();
|
|
|
|
using var response = await client.GetAsync("/healthz");
|
|
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
|
|
await using var responseStream = await response.Content.ReadAsStreamAsync();
|
|
using var jsonDocument = await JsonDocument.ParseAsync(responseStream);
|
|
var root = jsonDocument.RootElement;
|
|
|
|
Assert.Equal("ok", root.GetProperty("status").GetString());
|
|
Assert.Equal("flyshot-server-host", root.GetProperty("service").GetString());
|
|
}
|
|
}
|