-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP Communicate between framework mscorlib and core framework with Unit Tests #116
Conversation
@Aaronontheweb, @Horusiath We really need these changes, right now we are using our own package that forked from this project. We need not only for Akka projects but also for other projects where we use Hyperion as a serializer. See: If there are things you want me to change at this Pull Request, or if you think there are things that don't meet the standards of the project, I can make these changes quickly. @akselarzuman the person who opened the PR #119 is my collage. We love Hyperion as a company 😄 and we use it extensively, and we want to make contributions whenever it's possible. |
src/Hyperion/Extensions/TypeEx.cs
Outdated
@@ -125,6 +125,14 @@ private static Type GetTypeFromManifestName(Stream stream, DeserializerSession s | |||
return TypeNameLookup.GetOrAdd(byteArr, b => | |||
{ | |||
var shortName = StringEx.FromUtf8Bytes(b.Bytes, 0, b.Bytes.Length); | |||
if (shortName.Contains("System.Private.CoreLib,%core%") && CoreAssemblyQualifiedName.Contains("mscorlib, Version=")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this if/else statement something that could be replaced by compilation flags (iike #if NETCORE
)? I'm not sure if this check is something that we need to call at runtime for potentially every single type when we know that CoreAssemblyQualifiedName
will never change in the application lifetime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It isn't my commit but I'm not sure if we don't need runtime checks. Because the whole purpose of this PR is to provide interoperability between the .NET Framework and .NET Core, thus we might need runtime checks in case of serializing/deserializing between those two frameworks. As far as I understand Hyperion embeds the namespace into the serialized payload for types.
I'll check it and update the code if it's necessary. Thanks for pointing out.
@humhei fyi
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (shortName.Contains("System.Private.CoreLib,%core%") && CoreAssemblyQualifiedName.Contains("mscorlib, Version="))
The second predication can be replaced by etc #if NET461
But i more like define a global variable
private static readonly bool IsFullNetFramework = CoreAssemblyQualifiedName.Contains("mscorlib, Version="))
Then you can check it like
if (shortName.Contains("System.Private.CoreLib,%core%") && IsFullNetFramework
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason here is that we want to avoid unnecessary branches and operations. While it's quite possible that .NET Core 3.0 knows how to optimize static readonly checks, it's wasteful to defer checks, which result is known at compile time, back to the runtime for every type call. It's only a microoptimization, but it's also a sane practice to do.
A middle ground here is to make IsFullNetFramework
a const defined in #if/else pragmas and put it as a first segment of && expression - since consts cannot be changed by reflection (unlike readonly values), they are always optimized on every .NET platform.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your explanation
Fixed In Blind-Striker#1
#if NETSTANDARD
#if NET45
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, everything seems to be in order. I merged @humhei 's PR and pull the latest CI improvements from the dev branch (@Danthar fyi). All tests are passed.
After @akselarzuman's PR #119 merged I need to update test files (mentioned in #116 (comment)) for .NET Core 3.0 and run the tests again.
FullFramework or CoreNetFramework runtime check
# Conflicts: # src/Hyperion/Hyperion.csproj
…with netstandard1.6
# Conflicts: # src/Hyperion.Tests/Hyperion.Tests.csproj
@Danthar conflict resolved |
52772e8
to
e5cfd40
Compare
@Danthar I don't know why it failed, I have run build.ps1 on my local for all targets. The error message didn't specify anything :( |
@Danthar Would it be a problem if I change |
# Conflicts: # src/Hyperion.Tests/Hyperion.Tests.csproj
@Danthar we should change this in our templates across all projects. |
Update Windows vm image to windows-2019
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, looking at test output next to make sure what I've reviewed matches what is being tested...
@@ -2,7 +2,7 @@ | |||
# See https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema for reference | |||
|
|||
pool: | |||
vmImage: vs2017-win2016 | |||
vmImage: windows-2019 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
} | ||
|
||
[Fact] | ||
public void CanSerializeCrossFramework() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, this the only way to do it - have to actually load the sucker and work the payloads on both ends.
} | ||
} | ||
|
||
private bool Equals(CrossFrameworkStruct other) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM - validates that all of the primitives are covered.
<TargetFrameworks>net461;netcoreapp2.1;netcoreapp3.0</TargetFrameworks> | ||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> | ||
<LangVersion>latest</LangVersion> | ||
<StartupObject>Hyperion.Tests.Generator.Program</StartupObject> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fine with this - but I'll need to check the test output real fast to make sure everything is still there (pretty sure this PR would have exploded if it wasn't.)
@@ -118,11 +118,23 @@ private static Type GetTypeFromManifestName(Stream stream, DeserializerSession s | |||
return TypeNameLookup.GetOrAdd(byteArr, b => | |||
{ | |||
var shortName = StringEx.FromUtf8Bytes(b.Bytes, 0, b.Bytes.Length); | |||
#if NET45 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And this is where all of the heavy-lifting for working between frameworks occurs I take it...
Tests look good. |
Thanks @Aaronontheweb I couldn't make the test project work with .NET Core 2.2. I think it's about Azure VM. I have got the error below.
We can add the task below to install the latest .NET Core 2.2. But I didn't want to add that task without getting your opinion, and it also didn't feel like it was the right way to do this. Better wait for Microsoft to update their VM images. - task: UseDotNet@2
displayName: 'Install .net core 2.2'
inputs:
packageType: sdk
version: '2.2.402'
installationPath: $(Agent.ToolsDirectory)/dotnet But I'm pretty sure it's working because I have run the tests on my local and custom docker container with .NET Core 2.2. |
@Blind-Striker go ahead and add it.... Can we do something similar for the Linux images as well so we could get the test suite to run on that too? |
@Aaronontheweb We can actually. I already did something similar in my projects before. We can use a matrix strategy strategy:
matrix:
linux:
imageName: 'ubuntu-latest'
mac:
imageName: 'macos-10.13'
windows:
imageName: 'windows-2019' The only thing we need to do is add a condition to the task that checks the OS and run build.ps1 or build.sh according to that. Something like below - task: PowerShell@2
displayName: "Compile & Tests"
inputs:
targetType: filePath
filePath: ./build.ps1
condition: eq( variables['Agent.OS'], 'Windows_NT' )
- task: Bash@3
displayName: 'Compile & Tests'
inputs:
targetType: filePath
filePath: ./build.sh
condition: or(eq( variables['Agent.OS'], 'Darwin' ), eq( variables['Agent.OS'], 'Linux' )) The only drawback (it's not a drawback actually) of matrix strategy is you can't get separate build badges for each OS. So I always prefer to create separate YAML files per OS. But it's an aesthetic issue, not a technical one :) I'll do the necessary changes and open a new PR. |
@Blind-Striker thank you! We would really appreciate that. |
src/Hyperion/Hyperion.csproj
Outdated
@@ -20,11 +20,7 @@ | |||
<Reference Include="Microsoft.CSharp" /> | |||
</ItemGroup> | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#145
$(DefineConstants);NETSTANDARD
Maybe it is because The NETSTANDARD constrant is deleted here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tests should have failed on this case, I'll inform you after check it @DaniilSokolyuk @Aaronontheweb @humhei
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like the issue is specific to .NET Core 3+
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on what I've found with #151 thus far
ref #108, #112
In addition to the work done at #112, and according to the suggestion in #112 (comment), I have done followings:
Right now tests are working. In order to be sure, I reverted all of @humhei's changes and ran the tests again and observed that tests are not passed.
There is only one case where the tests are failing. When you serialize and deserialize exceptions that have extra property such as
ArgumentNullException
, these properties are being ignored. So instead of full compare, I just compared exception messages. I think this problem related toExceptionSerializerFactory
which a subject of another issue.Except that I'm pretty sure everything is working.