Skip to content

Commit

Permalink
Fixed issue when a generic message type would cause a different type …
Browse files Browse the repository at this point in the history
…hash if imported via two different assemblies or assembly versions (e.g. Game.Shared.dll 1.0.1 vs Game.Shared.dll 1.0.2, or DLL vs assembly definition)
  • Loading branch information
leonidumanskiy committed Jun 24, 2024
1 parent 2e8ac91 commit 1d79247
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 4 deletions.
23 changes: 23 additions & 0 deletions source/Fenrir.Multiplayer.Tests.External/ExternalFixtures.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace Fenrir.Multiplayer.Tests
{
// Type with the same structure, Name and Namespace as one in the Fenrir.Multiplayer.Tests assembly
// This file is included in both assemblies: Fenrir.Multiplayer.Tests and Fenrir.Multiplayer.Tests.External
public class TestExternalClass : IByteStreamSerializable
{
public string Value;

public void Deserialize(IByteStreamReader reader)
{
Value = reader.ReadString();
}

public void Serialize(IByteStreamWriter writer)
{
writer.Write(Value);
}

public TestExternalClass()
{
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Fenrir.Multiplayer\Fenrir.Multiplayer.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@
<PackageReference Include="coverlet.collector" Version="1.2.0" />
</ItemGroup>


<ItemGroup>
<Compile Include="..\Fenrir.Multiplayer.Tests.External\*.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Fenrir.Multiplayer.Tests.External\Fenrir.Multiplayer.Tests.External.csproj" >
<Aliases>External</Aliases>
</ProjectReference>
<ProjectReference Include="..\Fenrir.Multiplayer\Fenrir.Multiplayer.csproj" />
</ItemGroup>

Expand Down
112 changes: 112 additions & 0 deletions source/Fenrir.Multiplayer.Tests/Integration/IntegrationTests.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
extern alias External;
using Fenrir.Multiplayer.LiteNet;
using Fenrir.Multiplayer.Tests.Fixtures;
using Microsoft.VisualStudio.TestTools.UnitTesting;
Expand All @@ -6,7 +7,10 @@
using System;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using TestExternalClass2 = External::Fenrir.Multiplayer.Tests.TestExternalClass;


namespace Fenrir.Multiplayer.Tests
{
Expand Down Expand Up @@ -319,6 +323,62 @@ public async Task NetworkClient_SendRequest_SendsRequest()
Assert.AreEqual(request.Value, "test_value");
}


[TestMethod, Timeout(TestTimeout)]
public async Task NetworkClient_SendRequest_SendsGenericRequest()
{
using var logger = new TestLogger();
using var networkServer = new NetworkServer(logger);

TaskCompletionSource<TestGenericValueTypeRequest<TestStruct>> requestTcs = new TaskCompletionSource<TestGenericValueTypeRequest<TestStruct>>();
networkServer.AddRequestHandler(new TcsRequestHandler<TestGenericValueTypeRequest<TestStruct>>(requestTcs));

networkServer.Start();

Assert.AreEqual(ServerStatus.Running, networkServer.Status, "server is not running");

using var networkClient = new NetworkClient(logger);
var connectionResponse = await networkClient.Connect("http://127.0.0.1:27016");

Assert.AreEqual(ConnectionState.Connected, networkClient.State, "client is connected");
Assert.IsTrue(connectionResponse.Success, "connection rejected");

networkClient.Peer.SendRequest(new TestGenericValueTypeRequest<TestStruct>() { Data = new TestStruct() { Value = "test_value" } });

TestGenericValueTypeRequest<TestStruct> request = await requestTcs.Task;

Assert.AreEqual(request.Data.Value, "test_value");
}


[TestMethod, Timeout(TestTimeout)]
public async Task NetworkClient_SendRequest_SendsGenericRequest_WithExtenralAssemblyType()
{
// This test checks if requests still work if client and server use the same type, defined in two different assemblies (e.g. Client.csproj and Server.csproj)

using var logger = new TestLogger();
using var networkServer = new NetworkServer(logger);

TaskCompletionSource<TestGenericTypeRequest<TestExternalClass>> requestTcs = new TaskCompletionSource<TestGenericTypeRequest<TestExternalClass>>();
networkServer.AddRequestHandler(new TcsRequestHandler<TestGenericTypeRequest<TestExternalClass>>(requestTcs));

networkServer.Start();

Assert.AreEqual(ServerStatus.Running, networkServer.Status, "server is not running");

using var networkClient = new NetworkClient(logger);
var connectionResponse = await networkClient.Connect("http://127.0.0.1:27016");

Assert.AreEqual(ConnectionState.Connected, networkClient.State, "client is connected");
Assert.IsTrue(connectionResponse.Success, "connection rejected");

networkClient.Peer.SendRequest(new TestGenericTypeRequest<TestExternalClass2>() { Data = new TestExternalClass2() { Value = "test_value" } });

TestGenericTypeRequest<TestExternalClass> request = await requestTcs.Task;

Assert.AreEqual(request.Data.Value, "test_value");
}

[TestMethod, Timeout(TestTimeout)]
public async Task NetworkClient_SendRequest_SendsRequest_WithRequestTypeFactory()
{
Expand Down Expand Up @@ -930,6 +990,58 @@ public void Serialize(IByteStreamWriter writer)
}
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct TestStruct : IByteStreamSerializable
{
public string Value;

public void Deserialize(IByteStreamReader reader)
{
Value = reader.ReadString();
}

public void Serialize(IByteStreamWriter writer)
{
writer.Write(Value);
}
}

class TestGenericTypeRequest<T> : IRequest, IByteStreamSerializable
where T : IByteStreamSerializable, new()
{
public T Data;

public void Deserialize(IByteStreamReader reader)
{
Data = new T();
Data.Deserialize(reader);
}

public void Serialize(IByteStreamWriter writer)
{
Data.Serialize(writer);
}
}


class TestGenericValueTypeRequest<T> : IRequest, IByteStreamSerializable
where T : struct, IByteStreamSerializable
{
public T Data;

public void Deserialize(IByteStreamReader reader)
{
Data = new T();
Data.Deserialize(reader);
}

public void Serialize(IByteStreamWriter writer)
{
Data.Serialize(writer);
}
}


class TestResponse : IResponse, IByteStreamSerializable
{
public string Value;
Expand Down
10 changes: 8 additions & 2 deletions source/Fenrir.Multiplayer.sln
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30002.166
# Visual Studio Version 17
VisualStudioVersion = 17.8.34309.116
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Fenrir.Multiplayer", "Fenrir.Multiplayer\Fenrir.Multiplayer.csproj", "{0D167B4F-D88A-442E-91C5-645D7D66434B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Fenrir.Multiplayer.Tests", "Fenrir.Multiplayer.Tests\Fenrir.Multiplayer.Tests.csproj", "{74CB5DED-9A49-4AD1-A0E9-FAE4ACE3AE70}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Fenrir.Multiplayer.Tests.External", "Fenrir.Multiplayer.Tests.External\Fenrir.Multiplayer.Tests.External.csproj", "{642F9319-7D63-483E-9727-522C2AFDDE55}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -21,6 +23,10 @@ Global
{74CB5DED-9A49-4AD1-A0E9-FAE4ACE3AE70}.Debug|Any CPU.Build.0 = Debug|Any CPU
{74CB5DED-9A49-4AD1-A0E9-FAE4ACE3AE70}.Release|Any CPU.ActiveCfg = Release|Any CPU
{74CB5DED-9A49-4AD1-A0E9-FAE4ACE3AE70}.Release|Any CPU.Build.0 = Release|Any CPU
{642F9319-7D63-483E-9727-522C2AFDDE55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{642F9319-7D63-483E-9727-522C2AFDDE55}.Debug|Any CPU.Build.0 = Debug|Any CPU
{642F9319-7D63-483E-9727-522C2AFDDE55}.Release|Any CPU.ActiveCfg = Release|Any CPU
{642F9319-7D63-483E-9727-522C2AFDDE55}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
2 changes: 1 addition & 1 deletion source/Fenrir.Multiplayer/Fenrir.Multiplayer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Description>Fenrir Multiplayer Library</Description>
<Version>1.0.24</Version>
<Version>1.0.25</Version>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>

Expand Down
2 changes: 1 addition & 1 deletion source/UnityPackage/Assets/Runtime/Network/TypeHashMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ public bool HasTypeHash<T>()
/// <returns>Deterministic type hash</returns>
private ulong CalculateTypeHash(Type type)
{
return DeterministicHashUtility.CalculateHash(type.FullName);
return DeterministicHashUtility.CalculateHash(type.ToString());
}
}
}

0 comments on commit 1d79247

Please sign in to comment.