Skip to content

Commit

Permalink
Merge branch 'dev' into dynamic
Browse files Browse the repository at this point in the history
  • Loading branch information
Aaronontheweb authored Jan 20, 2020
2 parents 7f3f2fb + 7f36823 commit d0a22fc
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 17 deletions.
4 changes: 2 additions & 2 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
### 0.9.10 October 15 2019 ####
### 0.9.11 November 13 2019 ####

Hyperion now [supports cross-framework communication between .NET Core and .NET Framework](https://github.com/akkadotnet/Hyperion/pull/116).
[Hyperion now targets .NET 4.5 again so it can be included inside Akka.NET v1.3.* releases](https://github.com/akkadotnet/Hyperion/pull/141).
68 changes: 68 additions & 0 deletions src/Hyperion.Tests/Bugs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using FluentAssertions;
using Hyperion.Extensions;
using Xunit;

namespace Hyperion.Tests
Expand Down Expand Up @@ -85,6 +90,69 @@ public void CanSerializeMessageWithByte()
var res = serializer.Deserialize(stream);
}

/// <summary>
/// Fix for https://github.com/akkadotnet/Hyperion/issues/144
/// </summary>
[Fact]
public void CanFindTypeByManifest_WhenManifestContainsUnknownAssemblyVersion()
{
var serializer = new Serializer(new SerializerOptions(versionTolerance: true, preserveObjectReferences: true));
var type = typeof(ByteMessage);

MemoryStream GetStreamForManifest(string manifest)
{
var stream = new MemoryStream();
stream.WriteLengthEncodedByteArray(manifest.ToUtf8Bytes(), serializer.GetSerializerSession());
stream.Position = 0;
return stream;
}

// This is used in serialized manifest, should be something like 'Hyperion.Tests.Bugs+ByteMessage, Hyperion.Tests'
var shortName = type.GetShortAssemblyQualifiedName();
var shortNameStream = GetStreamForManifest(shortName);
// Something like 'Hyperion.Tests.Bugs+ByteMessage, Hyperion.Tests, Version=0.9.11.0, Culture=neutral, PublicKeyToken=null'
var fullName = type.AssemblyQualifiedName;
var fullNameStream = GetStreamForManifest(fullName);
// Set bad assembly version to make deserialization fail
var fullNameWithUnknownVersion = fullName.Remove(fullName.IndexOf(", Version=")) + ", Version=999999, Culture=neutral, PublicKeyToken=null";
var fullNameWithUnknownVersionStream = GetStreamForManifest(fullNameWithUnknownVersion);

this.Invoking(_ => TypeEx.GetTypeFromManifestFull(shortNameStream, serializer.GetDeserializerSession()))
.Should().NotThrow("When assembly short name is specified in manifest, should work");
this.Invoking(_ => TypeEx.GetTypeFromManifestFull(fullNameStream, serializer.GetDeserializerSession()))
.Should().NotThrow("When assembly fully qualified name specified and name is correct, should work even before fix");
// This one was initially failing
this.Invoking(_ => TypeEx.GetTypeFromManifestFull(fullNameWithUnknownVersionStream, serializer.GetDeserializerSession()))
.Should().NotThrow("When assembly fully qualified name specified and unknown/wrong, type should be detected anyway");
}

[Fact]
public void TypeEx_ToQualifiedAssemblyName_should_strip_version_correctly_for_mscorlib_substitution()
{
var version = TypeEx.ToQualifiedAssemblyName(
"System.Collections.Immutable.ImmutableDictionary`2[[System.String, mscorlib,%core%],[System.Int32, mscorlib,%core%]]," +
" System.Collections.Immutable, Version=1.2.1.0, PublicKeyToken=b03f5f7f11d50a3a",
ignoreAssemblyVersion: true);

var coreAssemblyName = typeof(TypeEx).GetField("CoreAssemblyName", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null);
if (coreAssemblyName == null)
throw new Exception($"CoreAssemblyName private static field does not exist in {nameof(TypeEx)} class anymore");

version.Should().Be("System.Collections.Immutable.ImmutableDictionary`2" +
$"[[System.String, mscorlib{coreAssemblyName}],[System.Int32, mscorlib{coreAssemblyName}]], System.Collections.Immutable");
}

[Fact]
public void TypeEx_ToQualifiedAssemblyName_should_strip_version_correctly_for_multiple_versions_specified()
{
var version = TypeEx.ToQualifiedAssemblyName(
"System.Collections.Immutable.ImmutableList`1[[Foo.Bar, Foo, Version=2019.12.10.1]], " +
"System.Collections.Immutable, Version=1.2.2.0, PublicKeyToken=b03f5f7f11d50a3a",
ignoreAssemblyVersion: true);

version.Should().Be("System.Collections.Immutable.ImmutableList`1[[Foo.Bar, Foo]], System.Collections.Immutable");
}

[Fact]
public void CanSerialieCustomType_bug()
{
Expand Down
24 changes: 24 additions & 0 deletions src/Hyperion.Tests/CollectionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,30 @@ public void CanSerializeList()
Assert.Equal(expected, actual);
}

[Fact]
public void CanSerializeArrayList()
{
var expected = new ArrayList()
{
new Something
{
BoolProp = true,
Else = new Else
{
Name = "Yoho"
},
Int32Prop = 999,
StringProp = "Yesbox!"
},
"a", 123
};

Serialize(expected);
Reset();
var actual = Deserialize<ArrayList>();
Assert.Equal(expected, actual);
}

[Fact]
public void CanSerializeLinkedList()
{
Expand Down
3 changes: 2 additions & 1 deletion src/Hyperion.Tests/Hyperion.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FluentAssertions" Version="5.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
<PackageReference Include="System.Collections.Immutable" Version="1.6.0" />
<PackageReference Include="System.Collections.Immutable" Version="1.7.0" />
<PackageReference Include="xunit" Version="$(XunitVersion)" />
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitVersion)" />
</ItemGroup>
Expand Down
28 changes: 25 additions & 3 deletions src/Hyperion/Extensions/TypeEx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,26 @@ private static Type GetTypeFromManifestName(Stream stream, DeserializerSession s
shortName = shortName.Replace("mscorlib,%core%", "System.Private.CoreLib,%core%");
}
#endif
return LoadTypeByName(shortName);
});
}

var typename = ToQualifiedAssemblyName(shortName);
public static Type LoadTypeByName(string name)
{
try
{
// Try to load type name using strict version to avoid possible conflicts
// i.e. if there are different version available in GAC and locally
var typename = ToQualifiedAssemblyName(name, ignoreAssemblyVersion: false);
return Type.GetType(typename, true);
});
}
catch (FileLoadException)
{
var typename = ToQualifiedAssemblyName(name, ignoreAssemblyVersion: true);
return Type.GetType(typename, true);
}
}

public static Type GetTypeFromManifestFull(Stream stream, DeserializerSession session)
{
var type = GetTypeFromManifestName(stream, session);
Expand Down Expand Up @@ -228,9 +243,16 @@ public static string GetShortAssemblyQualifiedName(this Type self)
return name;
}

public static string ToQualifiedAssemblyName(string shortName)
public static string ToQualifiedAssemblyName(string shortName, bool ignoreAssemblyVersion)
{
// Strip out assembly version, if specified
if (ignoreAssemblyVersion)
{
shortName = cleanAssemblyVersionRegex.Replace(shortName, string.Empty);
}

var res = shortName.Replace(",%core%", CoreAssemblyName);

return res;
}

Expand Down
17 changes: 11 additions & 6 deletions src/Hyperion/Hyperion.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,31 @@
<PropertyGroup>
<AssemblyTitle>Hyperion</AssemblyTitle>
<Description>Hyperion, fast binary POCO serializer</Description>
<TargetFrameworks>netstandard1.6;netstandard2.0;net452</TargetFrameworks>
<TargetFrameworks>netstandard1.6;netstandard2.0;net45</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PackageTags>serialization;poco</PackageTags>
</PropertyGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.6' ">
<PackageReference Include="System.Reflection.TypeExtensions" Version="4.6.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.6.0" />
<PackageReference Include="System.Reflection.TypeExtensions" Version="4.7.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="System.Runtime" Version="4.3.1" />
<PackageReference Include="Microsoft.CSharp" Version="4.6.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net452' ">
<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>

<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>Hyperion.Tests</_Parameter1>
</AssemblyAttribute>
</ItemGroup>

<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.6' ">
<DefineConstants>$(DefineConstants);NETSTANDARD16</DefineConstants>
Expand All @@ -33,7 +38,7 @@
<DefineConstants>$(DefineConstants);NETSTANDARD20</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition=" '$(TargetFramework)' == 'net452' ">
<PropertyGroup Condition=" '$(TargetFramework)' == 'net45' ">
<DefineConstants>$(DefineConstants);SERIALIZATION;UNSAFE;NET45</DefineConstants>
</PropertyGroup>

Expand Down
11 changes: 11 additions & 0 deletions src/Hyperion/SerializerFactories/EnumerableSerializerFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ private static Type GetEnumerableType(Type type)
private static ConstructorInfo GetEnumerableConstructor(Type type)
{
var enumerableType = GetEnumerableType(type);

/*
* In the event that we're serializing a non-generic IEnumerable such as an ArrayList,
* there aren't any generic parameters and the type returned will just be System.Object.
*
* The GetEnumerableType method extracts the generic argument from the IEnumerable<T> and uses that
* by default, however it will return null only for a non-generic implementation thus we use the
* null-coalescing operator to specify the return type as System.Object in order to serialize ArrayList
* types without errors.
*/
enumerableType = enumerableType ?? typeof(object);
var iEnumerableType = typeof(IEnumerable<>).MakeGenericType(enumerableType);
return enumerableType != null
? type.GetTypeInfo()
Expand Down
3 changes: 1 addition & 2 deletions src/Hyperion/ValueSerializers/TypeSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ public override object ReadValue(Stream stream, DeserializerSession session)
if (shortname == null)
return null;

var name = TypeEx.ToQualifiedAssemblyName(shortname);
var type = Type.GetType(name,true);
var type = TypeEx.LoadTypeByName(shortname);

//add the deserialized type to lookup
if (session.Serializer.Options.PreserveObjectReferences)
Expand Down
6 changes: 3 additions & 3 deletions src/common.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
<PropertyGroup>
<Copyright>Copyright © 2016-2017 Akka.NET Team</Copyright>
<Authors>Akka.NET Team</Authors>
<VersionPrefix>0.9.10</VersionPrefix>
<PackageReleaseNotes>Hyperion now [supports cross-framework communication between .NET Core and .NET Framework](https://github.com/akkadotnet/Hyperion/pull/116).</PackageReleaseNotes>
<VersionPrefix>0.9.11</VersionPrefix>
<PackageReleaseNotes>[Hyperion now targets .NET 4.5 again so it can be included inside Akka.NET v1.3.* releases](https://github.com/akkadotnet/Hyperion/pull/141).</PackageReleaseNotes>
<PackageIconUrl>http://getakka.net/images/akkalogo.png</PackageIconUrl>
<PackageProjectUrl>https://github.com/akkadotnet/Hyperion</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/akkadotnet/Hyperion/blob/master/LICENSE</PackageLicenseUrl>
<NoWarn>$(NoWarn);CS1591</NoWarn>
</PropertyGroup>
<PropertyGroup>
<XunitVersion>2.4.1</XunitVersion>
<TestSdkVersion>16.3.0</TestSdkVersion>
<TestSdkVersion>16.4.0</TestSdkVersion>
<NBenchVersion>1.2.2</NBenchVersion>
</PropertyGroup>
</Project>

0 comments on commit d0a22fc

Please sign in to comment.