您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
358 行
14 KiB
358 行
14 KiB
using System.Collections;
|
|
using Unity.Collections;
|
|
using NUnit.Framework;
|
|
using UnityEngine.TestTools;
|
|
using UnityEngine;
|
|
using Unity.Networking.Transport;
|
|
using Unity.Networking.Transport.Protocols;
|
|
|
|
namespace Tests
|
|
{
|
|
public class ServerAndClientTests
|
|
{
|
|
NetworkDriver server_driver;
|
|
NetworkConnection connectionToClient;
|
|
|
|
NetworkDriver client_driver;
|
|
NetworkConnection clientToServerConnection;
|
|
|
|
NetworkEvent.Type ev;
|
|
DataStreamReader stream;
|
|
|
|
private const string backend = "baselib";
|
|
|
|
NetworkEvent.Type PollDriverAndFindDataEvent(ref NetworkDriver driver, NetworkConnection connection, NetworkEvent.Type eventType, int maxRetryCount=10)
|
|
{
|
|
for (int retry = 0; retry < maxRetryCount; ++retry)
|
|
{
|
|
driver.ScheduleUpdate().Complete();
|
|
ev = driver.PopEventForConnection(connection, out stream);
|
|
if (ev == eventType || ev != NetworkEvent.Type.Empty)
|
|
{
|
|
return ev;
|
|
}
|
|
}
|
|
return NetworkEvent.Type.Empty;
|
|
}
|
|
|
|
public void SetupServerAndClientAndConnectThem(int bufferSize)
|
|
{
|
|
//setup server
|
|
server_driver = NetworkDriver.Create(new NetworkDataStreamParameter { size = bufferSize });
|
|
NetworkEndPoint server_endpoint = NetworkEndPoint.LoopbackIpv4;
|
|
server_endpoint.Port = 1337;
|
|
var ret = server_driver.Bind(server_endpoint);
|
|
int maxRetry = 10;
|
|
while (ret != 0 && --maxRetry > 0)
|
|
{
|
|
server_endpoint.Port += 17;
|
|
ret = server_driver.Bind(server_endpoint);
|
|
};
|
|
Assert.AreEqual(ret, 0, "Failed to bind the socket");
|
|
server_driver.Listen();
|
|
|
|
//setup client
|
|
client_driver = NetworkDriver.Create(new NetworkDataStreamParameter { size = bufferSize });
|
|
clientToServerConnection = client_driver.Connect(server_endpoint);
|
|
|
|
//update drivers
|
|
client_driver.ScheduleUpdate().Complete();
|
|
|
|
for (int i = 0; i < 10; ++i)
|
|
{
|
|
server_driver.ScheduleUpdate().Complete();
|
|
//accept connection
|
|
connectionToClient = server_driver.Accept();
|
|
if (connectionToClient.IsCreated)
|
|
break;
|
|
}
|
|
Assert.IsTrue(connectionToClient.IsCreated, "Failed to accept the connection");
|
|
|
|
ev = PollDriverAndFindDataEvent(ref server_driver, connectionToClient, NetworkEvent.Type.Empty);
|
|
Assert.IsTrue(ev == NetworkEvent.Type.Empty, $"Not empty NetworkEvent on the server appeared, got {ev} using {backend}");
|
|
|
|
ev = PollDriverAndFindDataEvent(ref client_driver, clientToServerConnection, NetworkEvent.Type.Connect);
|
|
Assert.IsTrue(ev == NetworkEvent.Type.Connect, $"NetworkEvent should have Type.Connect on the client, but got {ev} using {backend}");
|
|
}
|
|
|
|
public void DisconnectAndCleanup()
|
|
{
|
|
clientToServerConnection.Close(client_driver);
|
|
|
|
//update drivers
|
|
client_driver.ScheduleUpdate().Complete();
|
|
ev = PollDriverAndFindDataEvent(ref server_driver, connectionToClient, NetworkEvent.Type.Disconnect);
|
|
Assert.IsTrue(ev == NetworkEvent.Type.Disconnect, "NetworkEvent.Type.Disconnect was expected to appear, but " + ev + " appeared");
|
|
|
|
server_driver.Dispose();
|
|
client_driver.Dispose();
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator ServerAndClient_Connect_Successfully()
|
|
{
|
|
SetupServerAndClientAndConnectThem(0);
|
|
DisconnectAndCleanup();
|
|
yield return null;
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator ServerAnd5Clients_Connect_Successfully()
|
|
{
|
|
int numberOfClients = 5;
|
|
NativeArray<NetworkConnection> connectionToClientArray;
|
|
NetworkDriver[] client_driversArray = new NetworkDriver[numberOfClients];
|
|
NativeArray<NetworkConnection> clientToServerConnectionsArray;
|
|
|
|
//setup server
|
|
connectionToClientArray = new NativeArray<NetworkConnection>(numberOfClients, Allocator.Persistent);
|
|
server_driver = NetworkDriver.Create(new NetworkDataStreamParameter { size = 0 });
|
|
NetworkEndPoint server_endpoint = NetworkEndPoint.LoopbackIpv4;
|
|
server_endpoint.Port = 1337;
|
|
server_driver.Bind(server_endpoint);
|
|
server_driver.Listen();
|
|
|
|
//setup clients
|
|
clientToServerConnectionsArray = new NativeArray<NetworkConnection>(numberOfClients, Allocator.Persistent);
|
|
|
|
for (int i = 0; i < numberOfClients; i++)
|
|
{
|
|
client_driversArray[i] = NetworkDriver.Create(new NetworkDataStreamParameter { size = 0 });
|
|
clientToServerConnectionsArray[i] = client_driversArray[i].Connect(server_endpoint);
|
|
}
|
|
|
|
//update drivers
|
|
for (int i = 0; i < numberOfClients; i++)
|
|
client_driversArray[i].ScheduleUpdate().Complete();
|
|
server_driver.ScheduleUpdate().Complete();
|
|
|
|
//accept connections
|
|
for (int i = 0; i < numberOfClients; i++)
|
|
{
|
|
connectionToClientArray[i] = server_driver.Accept();
|
|
ev = PollDriverAndFindDataEvent(ref server_driver, connectionToClientArray[i], NetworkEvent.Type.Empty);
|
|
Assert.IsTrue(ev == NetworkEvent.Type.Empty, "Not empty NetworkEvent on the server appeared");
|
|
ev = PollDriverAndFindDataEvent(ref client_driversArray[i], clientToServerConnectionsArray[i], NetworkEvent.Type.Connect);
|
|
Assert.IsTrue(ev == NetworkEvent.Type.Connect, "NetworkEvent should have Type.Connect on the client");
|
|
}
|
|
//close connections
|
|
for (int i = 0; i < numberOfClients; i++)
|
|
{
|
|
clientToServerConnectionsArray[i].Close(client_driversArray[i]);
|
|
|
|
//update drivers
|
|
client_driversArray[i].ScheduleUpdate().Complete();
|
|
ev = PollDriverAndFindDataEvent(ref server_driver, connectionToClientArray[i], NetworkEvent.Type.Disconnect);
|
|
Assert.IsTrue(ev == NetworkEvent.Type.Disconnect, "NetworkEvent.Type.Disconnect was expected to appear, but " + ev + " appeared");
|
|
}
|
|
|
|
server_driver.Dispose();
|
|
for (int i = 0; i < numberOfClients; i++)
|
|
{
|
|
client_driversArray[i].Dispose();
|
|
}
|
|
connectionToClientArray.Dispose();
|
|
clientToServerConnectionsArray.Dispose();
|
|
|
|
yield return null;
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator ServerAndClient_PingPong_Successfully()
|
|
{
|
|
SetupServerAndClientAndConnectThem(0);
|
|
|
|
//send data from client
|
|
if (client_driver.BeginSend(clientToServerConnection, out var m_OutStream) == 0)
|
|
{
|
|
m_OutStream.Clear();
|
|
m_OutStream.WriteBytes(new NativeArray<byte>(SharedConstants.ping, Allocator.Temp));
|
|
client_driver.EndSend(m_OutStream);
|
|
}
|
|
client_driver.ScheduleFlushSend(default).Complete();
|
|
|
|
//handle sent data
|
|
ev = PollDriverAndFindDataEvent(ref server_driver, connectionToClient, NetworkEvent.Type.Data);
|
|
Assert.IsTrue(ev == NetworkEvent.Type.Data, "Expected to get Type.Data");
|
|
var msg = new NativeArray<byte>(stream.Length, Allocator.Temp);
|
|
stream.ReadBytes(msg);
|
|
if (msg.Length == SharedConstants.ping.Length)
|
|
{
|
|
for (var i = 0; i < msg.Length; i++)
|
|
{
|
|
if (SharedConstants.ping[i] != msg[i])
|
|
{
|
|
Assert.Fail("Data reading error");
|
|
}
|
|
}
|
|
}
|
|
|
|
client_driver.ScheduleUpdate().Complete();
|
|
|
|
//send data from server
|
|
if (server_driver.BeginSend(connectionToClient, out m_OutStream) == 0)
|
|
{
|
|
m_OutStream.WriteBytes(new NativeArray<byte>(SharedConstants.pong, Allocator.Temp));
|
|
server_driver.EndSend(m_OutStream);
|
|
}
|
|
|
|
//handle sent data
|
|
server_driver.ScheduleUpdate().Complete();
|
|
|
|
ev = PollDriverAndFindDataEvent(ref client_driver, clientToServerConnection, NetworkEvent.Type.Data);
|
|
Assert.IsTrue(ev == NetworkEvent.Type.Data, "Expected to get Type.Data");
|
|
msg = new NativeArray<byte>(stream.Length, Allocator.Temp);
|
|
stream.ReadBytes(msg);
|
|
if (msg.Length == SharedConstants.pong.Length)
|
|
{
|
|
for (var i = 0; i < msg.Length; i++)
|
|
{
|
|
if (SharedConstants.pong[i] != msg[i])
|
|
{
|
|
Assert.Fail("Data reading error");
|
|
}
|
|
}
|
|
}
|
|
|
|
DisconnectAndCleanup();
|
|
yield return null;
|
|
}
|
|
|
|
//test for buffer overflow
|
|
[UnityTest, UnityPlatform (RuntimePlatform.LinuxEditor, RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor)]
|
|
public IEnumerator ServerAndClient_SendBigMessage_OverflowsIncomingDriverBuffer()
|
|
{
|
|
SetupServerAndClientAndConnectThem(8);
|
|
|
|
//send data from client
|
|
if (client_driver.BeginSend(clientToServerConnection, out var m_OutStream) == 0)
|
|
{
|
|
m_OutStream.Clear();
|
|
m_OutStream.WriteBytes(new NativeArray<byte>(SharedConstants.ping, Allocator.Temp));
|
|
client_driver.EndSend(m_OutStream);
|
|
}
|
|
client_driver.ScheduleFlushSend(default).Complete();
|
|
|
|
LogAssert.Expect(LogType.Error, "Error on receive, errorCode = 10040");
|
|
|
|
//handle sent data
|
|
server_driver.ScheduleUpdate().Complete();
|
|
client_driver.ScheduleUpdate().Complete();
|
|
|
|
Assert.AreEqual(10040, server_driver.ReceiveErrorCode);
|
|
|
|
DisconnectAndCleanup();
|
|
yield return null;
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator ServerAndClient_SendMessageWithMaxLength_SentAndReceivedWithoutErrors()
|
|
{
|
|
SetupServerAndClientAndConnectThem(0);
|
|
|
|
int messageLength = 1400-UdpCHeader.Length;
|
|
var messageToSend = new NativeArray<byte>(messageLength, Allocator.Temp);
|
|
for (int i = 0; i < messageLength; i++)
|
|
{
|
|
messageToSend[i] = (byte)(33 + (i % 93));
|
|
}
|
|
//send data from client
|
|
if (client_driver.BeginSend(clientToServerConnection, out var m_OutStream) == 0)
|
|
{
|
|
m_OutStream.WriteBytes(messageToSend);
|
|
client_driver.EndSend(m_OutStream);
|
|
}
|
|
|
|
client_driver.ScheduleFlushSend(default).Complete();
|
|
|
|
ev = PollDriverAndFindDataEvent(ref server_driver, connectionToClient, NetworkEvent.Type.Data);
|
|
Assert.IsTrue(ev == NetworkEvent.Type.Data, "Expected to get Type.Data");
|
|
var msg = new NativeArray<byte>(stream.Length, Allocator.Temp);
|
|
stream.ReadBytes(msg);
|
|
Assert.IsTrue(msg.Length == messageLength, "Lenghts of sent and received messages are different");
|
|
|
|
DisconnectAndCleanup();
|
|
yield return null;
|
|
}
|
|
|
|
[UnityTest, UnityPlatform (RuntimePlatform.LinuxEditor, RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor)]
|
|
public IEnumerator ServerAndClient_SendMessageWithMoreThenMaxLength_OverflowsIncomingDriverBuffer()
|
|
{
|
|
SetupServerAndClientAndConnectThem(0);
|
|
|
|
//send data from client
|
|
|
|
if (client_driver.BeginSend(clientToServerConnection, out var m_OutStream) == 0)
|
|
{
|
|
m_OutStream.Clear();
|
|
int messageLength = 1401-UdpCHeader.Length;
|
|
var messageToSend = new NativeArray<byte>(messageLength, Allocator.Temp);
|
|
for (int i = 0; i < messageLength; i++)
|
|
{
|
|
messageToSend[i] = (byte)(33 + (i % 93));
|
|
}
|
|
|
|
Assert.IsFalse(m_OutStream.WriteBytes(messageToSend));
|
|
Assert.AreEqual(0, client_driver.EndSend(m_OutStream));
|
|
}
|
|
client_driver.ScheduleFlushSend(default).Complete();
|
|
|
|
//handle sent data
|
|
client_driver.ScheduleUpdate().Complete();
|
|
ev = PollDriverAndFindDataEvent(ref server_driver, connectionToClient, NetworkEvent.Type.Data);
|
|
Assert.IsTrue(ev == NetworkEvent.Type.Data, "Expected to get Type.Empty");
|
|
Assert.IsFalse(stream.IsCreated);
|
|
|
|
DisconnectAndCleanup();
|
|
yield return null;
|
|
}
|
|
|
|
[UnityTest, UnityPlatform (RuntimePlatform.LinuxEditor, RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor)]
|
|
public IEnumerator ServerAndClient_SendMessageWithoutReadingIt_GivesErrorOnDriverUpdate()
|
|
{
|
|
SetupServerAndClientAndConnectThem(0);
|
|
|
|
//send data from client
|
|
if (client_driver.BeginSend(clientToServerConnection, out var m_OutStream) == 0)
|
|
{
|
|
m_OutStream.WriteBytes(new NativeArray<byte>(SharedConstants.ping, Allocator.Temp));
|
|
client_driver.EndSend(m_OutStream);
|
|
}
|
|
client_driver.ScheduleFlushSend(default).Complete();
|
|
|
|
server_driver.ScheduleUpdate().Complete();
|
|
client_driver.ScheduleUpdate().Complete();
|
|
|
|
LogAssert.Expect(LogType.Error, "Resetting event queue with pending events (Count=1, ConnectionID=0) Listening: 1");
|
|
server_driver.ScheduleUpdate().Complete();
|
|
|
|
DisconnectAndCleanup();
|
|
yield return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
public class SharedConstants
|
|
{
|
|
public static byte[] ping = {
|
|
(byte)'f',
|
|
(byte)'r',
|
|
(byte)'o',
|
|
(byte)'m',
|
|
(byte)'s',
|
|
(byte)'e',
|
|
(byte)'r',
|
|
(byte)'v',
|
|
(byte)'e',
|
|
(byte)'r'
|
|
};
|
|
|
|
public static byte[] pong = {
|
|
(byte)'c',
|
|
(byte)'l',
|
|
(byte)'i',
|
|
(byte)'e',
|
|
(byte)'n',
|
|
(byte)'t'
|
|
};
|
|
}
|