add test solution and try to fix get id code bug
This commit is contained in:
		@@ -10,3 +10,7 @@ publish: _show-dir
 | 
			
		||||
[working-directory: "server"]
 | 
			
		||||
run-server: _show-dir
 | 
			
		||||
  dotnet run
 | 
			
		||||
  
 | 
			
		||||
[working-directory: "server.test"]
 | 
			
		||||
test-server: _show-dir
 | 
			
		||||
  dotnet test
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								server.test/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								server.test/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
bin
 | 
			
		||||
obj
 | 
			
		||||
							
								
								
									
										36
									
								
								server.test/UDPServerTest.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								server.test/UDPServerTest.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
namespace server.test.UDPServer;
 | 
			
		||||
 | 
			
		||||
public class UnitTest1
 | 
			
		||||
{
 | 
			
		||||
    [Fact]
 | 
			
		||||
    public void UDPDataDeepClone()
 | 
			
		||||
    {
 | 
			
		||||
        var udpData = new UDPData()
 | 
			
		||||
        {
 | 
			
		||||
            DateTime = DateTime.Now,
 | 
			
		||||
            Address = "127.0.0.1",
 | 
			
		||||
            Port = 1234,
 | 
			
		||||
            Data = new byte[] { 0xf0, 00, 00, 00 },
 | 
			
		||||
            HasRead = false
 | 
			
		||||
        };
 | 
			
		||||
        var cloneUdpData = udpData.DeepClone();
 | 
			
		||||
 | 
			
		||||
        Assert.Equal(udpData.DateTime, cloneUdpData.DateTime);
 | 
			
		||||
        Assert.Equal(udpData.Address, cloneUdpData.Address);
 | 
			
		||||
        Assert.Equal(udpData.Port, cloneUdpData.Port);
 | 
			
		||||
        Assert.Equal(udpData.Data, cloneUdpData.Data);
 | 
			
		||||
        Assert.Equal(udpData.HasRead, cloneUdpData.HasRead);
 | 
			
		||||
 | 
			
		||||
        udpData.DateTime = DateTime.Now;
 | 
			
		||||
        udpData.Address = "192.168.1.1";
 | 
			
		||||
        udpData.Port = 33000;
 | 
			
		||||
        udpData.Data = new byte[] { 0x0f, 00, 00, 00 };
 | 
			
		||||
        udpData.HasRead = true;
 | 
			
		||||
 | 
			
		||||
        Assert.NotEqual(udpData.DateTime, cloneUdpData.DateTime);
 | 
			
		||||
        Assert.NotEqual(udpData.Address, cloneUdpData.Address);
 | 
			
		||||
        Assert.NotEqual(udpData.Port, cloneUdpData.Port);
 | 
			
		||||
        Assert.NotEqual(udpData.Data, cloneUdpData.Data);
 | 
			
		||||
        Assert.NotEqual(udpData.HasRead, cloneUdpData.HasRead);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								server.test/server.test.csproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								server.test/server.test.csproj
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
<Project Sdk="Microsoft.NET.Sdk">
 | 
			
		||||
 | 
			
		||||
  <PropertyGroup>
 | 
			
		||||
    <TargetFramework>net9.0</TargetFramework>
 | 
			
		||||
    <ImplicitUsings>enable</ImplicitUsings>
 | 
			
		||||
    <Nullable>enable</Nullable>
 | 
			
		||||
    <IsPackable>false</IsPackable>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <PackageReference Include="coverlet.collector" Version="6.0.2" />
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.4" />
 | 
			
		||||
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
 | 
			
		||||
    <PackageReference Include="xunit" Version="2.9.2" />
 | 
			
		||||
    <PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Using Include="Xunit" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <ProjectReference Include="..\server\server.csproj" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
</Project>
 | 
			
		||||
@@ -79,8 +79,6 @@ try
 | 
			
		||||
 | 
			
		||||
    // Setup Program
 | 
			
		||||
    MsgBus.Init();
 | 
			
		||||
    // if (app.Environment.IsDevelopment()) MsgBus.UDPServer.EnableDebugMode = true;
 | 
			
		||||
    MsgBus.UDPServer.EnableDebugMode = true;
 | 
			
		||||
 | 
			
		||||
    // Router
 | 
			
		||||
    // API Get
 | 
			
		||||
 
 | 
			
		||||
@@ -60,6 +60,11 @@
 | 
			
		||||
        "finalMinLevel": "Info",
 | 
			
		||||
        "writeTo": "Console"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "logger": "server",
 | 
			
		||||
        "finalMinLevel": "Trace",
 | 
			
		||||
        "writeTo": "EachFile"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "logger": "server.*",
 | 
			
		||||
        "finalMinLevel": "Trace",
 | 
			
		||||
 
 | 
			
		||||
@@ -50,14 +50,14 @@ namespace Common
 | 
			
		||||
            {
 | 
			
		||||
                for (var i = 0; i < len; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    num += Convert.ToUInt64(bytes[len - 1 - i] << (i << 3));
 | 
			
		||||
                    num += Convert.ToUInt64((UInt64)bytes[len - 1 - i] << (i << 3));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                for (var i = 0; i < len; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    num += Convert.ToUInt64(bytes[i] << ((int)(len - 1 - i) << 3));
 | 
			
		||||
                    num += Convert.ToUInt64((UInt64)bytes[i] << ((int)(len - 1 - i) << 3));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -245,7 +245,7 @@ class Jtag
 | 
			
		||||
        ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
 | 
			
		||||
        if (!ret) throw new Exception("Send Address Package Failed!");
 | 
			
		||||
 | 
			
		||||
        // Wait for Ack
 | 
			
		||||
        // Wait for Read Ack
 | 
			
		||||
        if (!MsgBus.IsRunning)
 | 
			
		||||
            throw new Exception("Message Bus not Working!");
 | 
			
		||||
 | 
			
		||||
@@ -261,7 +261,7 @@ class Jtag
 | 
			
		||||
        if (retPackLen != 4)
 | 
			
		||||
            throw new Exception($"RecvDataPackage BodyData Length not Equal to 4: Total {retPackLen} bytes");
 | 
			
		||||
 | 
			
		||||
        return (uint)(NumberProcessor.BytesToNumber(retPackOpts.Data));
 | 
			
		||||
        return Convert.ToUInt32(NumberProcessor.BytesToNumber(retPackOpts.Data).Value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async ValueTask<Result<RecvDataPackage>> RunCommand(uint devAddr, uint command)
 | 
			
		||||
@@ -279,6 +279,11 @@ class Jtag
 | 
			
		||||
        opts.IsWrite = true;
 | 
			
		||||
        ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
 | 
			
		||||
        if (!ret) throw new Exception("Send 1st address package failed!");
 | 
			
		||||
        // Send Data Package
 | 
			
		||||
        ret = await UDPClientPool.SendDataPackAsync(ep,
 | 
			
		||||
                new SendDataPackage(NumberProcessor.NumberToBytes(command, 4).Value));
 | 
			
		||||
        if (!ret) throw new Exception("Send data package failed!");
 | 
			
		||||
 | 
			
		||||
        // Check Msg Bus
 | 
			
		||||
        if (!MsgBus.IsRunning)
 | 
			
		||||
            throw new Exception("Message bus not working!");
 | 
			
		||||
@@ -288,10 +293,6 @@ class Jtag
 | 
			
		||||
            if (!udpResp.IsSuccessful || !udpResp.Value.IsSuccessful)
 | 
			
		||||
                throw new Exception("Send address package failed");
 | 
			
		||||
        }
 | 
			
		||||
        // Send Data Package
 | 
			
		||||
        ret = await UDPClientPool.SendDataPackAsync(ep,
 | 
			
		||||
                new SendDataPackage(NumberProcessor.NumberToBytes(command, 4).Value));
 | 
			
		||||
        if (!ret) throw new Exception("Send data package failed!");
 | 
			
		||||
 | 
			
		||||
        // Read Jtag State Register
 | 
			
		||||
        opts.IsWrite = false;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
using System.Net;
 | 
			
		||||
using System.Net.Sockets;
 | 
			
		||||
using System.Runtime.CompilerServices;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using DotNext;
 | 
			
		||||
using DotNext.Threading;
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
@@ -30,6 +30,24 @@ public class UDPData
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public required bool HasRead { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 深度拷贝对象
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <returns>UDPData</returns>
 | 
			
		||||
    public UDPData DeepClone()
 | 
			
		||||
    {
 | 
			
		||||
        var cloneData = new byte[this.Data.Length];
 | 
			
		||||
        Buffer.BlockCopy(this.Data, 0, cloneData, 0, this.Data.Length);
 | 
			
		||||
        return new UDPData()
 | 
			
		||||
        {
 | 
			
		||||
            DateTime = this.DateTime,
 | 
			
		||||
            Address = new string(this.Address),
 | 
			
		||||
            Port = this.Port,
 | 
			
		||||
            Data = cloneData,
 | 
			
		||||
            HasRead = this.HasRead
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 将UDP Data 转化为Json 格式字符串
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -56,11 +74,6 @@ public class UDPServer
 | 
			
		||||
    private Dictionary<string, List<UDPData>> udpData = new Dictionary<string, List<UDPData>>();
 | 
			
		||||
    private AsyncReaderWriterLock udpDataLock = new AsyncReaderWriterLock(1);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 是否开启Debug模式
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public bool EnableDebugMode { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Construct a udp server with fixed port
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -90,11 +103,18 @@ public class UDPServer
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="ipAddr"> IP Address</param>
 | 
			
		||||
    /// <param name="timeout"> Read and Write Wait for Milliseconds </param>
 | 
			
		||||
    /// <param name="callerName">调用函数名称</param>
 | 
			
		||||
    /// <param name="callerLineNum">调用函数位置</param>
 | 
			
		||||
    /// <returns>UDP Data</returns>
 | 
			
		||||
    public Optional<UDPData> FindData(string ipAddr, int timeout = 1000)
 | 
			
		||||
    public Optional<UDPData> FindData(
 | 
			
		||||
         string ipAddr, int timeout = 1000,
 | 
			
		||||
         [CallerMemberName] string callerName = "",
 | 
			
		||||
         [CallerLineNumber] int callerLineNum = 0)
 | 
			
		||||
    {
 | 
			
		||||
        UDPData? data = null;
 | 
			
		||||
 | 
			
		||||
        logger.Debug($"Caller \"{callerName}|{callerLineNum}\": Try to find {ipAddr} UDP Data");
 | 
			
		||||
 | 
			
		||||
        var startTime = DateTime.Now;
 | 
			
		||||
        var isTimeout = false;
 | 
			
		||||
        var timeleft = TimeSpan.FromMilliseconds(timeout);
 | 
			
		||||
@@ -105,7 +125,7 @@ public class UDPServer
 | 
			
		||||
            {
 | 
			
		||||
                if (udpData.ContainsKey(ipAddr) && udpData[ipAddr].Count > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    data = udpData[ipAddr][0];
 | 
			
		||||
                    data = udpData[ipAddr][0].DeepClone();
 | 
			
		||||
                    udpData[ipAddr].RemoveAt(0);
 | 
			
		||||
                    logger.Debug($"Find UDP Data: {data.ToString()}");
 | 
			
		||||
                    break;
 | 
			
		||||
@@ -132,15 +152,22 @@ public class UDPServer
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="ipAddr"> 目标IP地址 </param>
 | 
			
		||||
    /// <param name="timeout">超时时间</param>
 | 
			
		||||
    /// <param name="callerName">调用函数名称</param>
 | 
			
		||||
    /// <param name="callerLineNum">调用函数位置</param>
 | 
			
		||||
    /// <returns>
 | 
			
		||||
    /// 异步Optional 数据包:
 | 
			
		||||
    /// Optional 为空时,表明找不到数据;
 | 
			
		||||
    /// Optional 存在时,为最先收到的数据
 | 
			
		||||
    /// </returns>
 | 
			
		||||
    public async ValueTask<Optional<UDPData>> FindDataAsync(string ipAddr, int timeout = 1000)
 | 
			
		||||
    public async ValueTask<Optional<UDPData>> FindDataAsync(
 | 
			
		||||
         string ipAddr, int timeout = 1000,
 | 
			
		||||
         [CallerMemberName] string callerName = "",
 | 
			
		||||
         [CallerLineNumber] int callerLineNum = 0)
 | 
			
		||||
    {
 | 
			
		||||
        UDPData? data = null;
 | 
			
		||||
 | 
			
		||||
        logger.Debug($"Caller \"{callerName}|{callerLineNum}\": Try to find {ipAddr} UDP Data");
 | 
			
		||||
 | 
			
		||||
        var startTime = DateTime.Now;
 | 
			
		||||
        var isTimeout = false;
 | 
			
		||||
        var timeleft = TimeSpan.FromMilliseconds(timeout);
 | 
			
		||||
@@ -151,7 +178,7 @@ public class UDPServer
 | 
			
		||||
            {
 | 
			
		||||
                if (udpData.ContainsKey(ipAddr) && udpData[ipAddr].Count > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    data = udpData[ipAddr][0];
 | 
			
		||||
                    data = udpData[ipAddr][0].DeepClone();
 | 
			
		||||
                    udpData[ipAddr].RemoveAt(0);
 | 
			
		||||
                    logger.Debug($"Find UDP Data: {data.ToString()}");
 | 
			
		||||
                    break;
 | 
			
		||||
@@ -215,7 +242,7 @@ public class UDPServer
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 异步等待读响应或写响应
 | 
			
		||||
    /// 异步等待写响应
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="address">IP地址</param>
 | 
			
		||||
    /// <param name="port">UDP 端口</param>
 | 
			
		||||
@@ -266,6 +293,7 @@ public class UDPServer
 | 
			
		||||
 | 
			
		||||
    private void ReceiveHandler(IAsyncResult res)
 | 
			
		||||
    {
 | 
			
		||||
        logger.Trace("Enter handler");
 | 
			
		||||
        var remoteEP = new IPEndPoint(IPAddress.Any, listenPort);
 | 
			
		||||
        byte[] bytes = listener.EndReceive(res, ref remoteEP);
 | 
			
		||||
 | 
			
		||||
@@ -278,67 +306,13 @@ public class UDPServer
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // If enable Debug mode, exec Debug handler
 | 
			
		||||
        if (EnableDebugMode)
 | 
			
		||||
        {
 | 
			
		||||
            DebugHandler(new IPEndPoint(IPAddress.Parse("127.0.0.1"), this.listenPort), bytes);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            // Handle Package
 | 
			
		||||
            PrintData(RecordUDPData(bytes, remoteEP));
 | 
			
		||||
        }
 | 
			
		||||
        // Handle Package
 | 
			
		||||
        PrintData(RecordUDPData(bytes, remoteEP));
 | 
			
		||||
 | 
			
		||||
    BEGIN_RECEIVE:
 | 
			
		||||
        listener.BeginReceive(new AsyncCallback(ReceiveHandler), null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void DebugHandler(IPEndPoint ep, byte[] bytes)
 | 
			
		||||
    {
 | 
			
		||||
        // Print Receive Data
 | 
			
		||||
        var data = new UDPData()
 | 
			
		||||
        {
 | 
			
		||||
            Address = ep.Address.ToString(),
 | 
			
		||||
            Port = ep.Port,
 | 
			
		||||
            Data = bytes,
 | 
			
		||||
            DateTime = DateTime.Now,
 | 
			
		||||
            HasRead = false,
 | 
			
		||||
        };
 | 
			
		||||
        PrintData(data);
 | 
			
		||||
 | 
			
		||||
        // Handle Pack Type
 | 
			
		||||
        var sign = bytes[0];
 | 
			
		||||
        if (sign == (byte)WebProtocol.PackSign.SendAddr)
 | 
			
		||||
        {
 | 
			
		||||
            var resData = WebProtocol.SendAddrPackage.FromBytes(bytes);
 | 
			
		||||
            if (!resData.IsSuccessful)
 | 
			
		||||
            {
 | 
			
		||||
                logger.Warn("DebugHandler: Convert to SendAddrPackage failed");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (resData.Value.Options.IsWrite)
 | 
			
		||||
            {
 | 
			
		||||
                var pack = new WebProtocol.RecvRespPackage(resData.Value.Options.CommandID, true);
 | 
			
		||||
                SendBytes(ep, pack.ToBytes());
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                var pack = new WebProtocol.RecvDataPackage(resData.Value.Options.CommandID, true, [0, 0, 0, 0]);
 | 
			
		||||
                SendBytes(ep, pack.ToBytes());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (sign == (byte)WebProtocol.PackSign.SendData)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            SendString(ep, "DebugHandler: Receive Data");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        logger.Trace("DebugHandler: send pack successfully");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private bool SendBytes(IPEndPoint endPoint, byte[] buf)
 | 
			
		||||
    {
 | 
			
		||||
        var sendLen = listener.Send(buf, endPoint);
 | 
			
		||||
@@ -380,7 +354,9 @@ public class UDPServer
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                udpData.Add(remoteAddress, new List<UDPData>([data]));
 | 
			
		||||
                var list = new List<UDPData>();
 | 
			
		||||
                list.Add(data);
 | 
			
		||||
                udpData.Add(remoteAddress, list);
 | 
			
		||||
                logger.Trace("Receive data from new client");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -478,7 +478,7 @@ namespace WebProtocol
 | 
			
		||||
        {
 | 
			
		||||
            if (bytes[0] != (byte)PackSign.RecvResp)
 | 
			
		||||
                throw new ArgumentException(
 | 
			
		||||
                    "The sign of bytes is not RecvData Package!",
 | 
			
		||||
                    "The sign of bytes is not RecvResp Package!",
 | 
			
		||||
                    nameof(bytes)
 | 
			
		||||
                );
 | 
			
		||||
            return new RecvRespPackage(bytes[1], bytes[2]);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user