diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index b0edd6b7..95a29b12 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,6 +1,10 @@
-### 0.9.16 June 17 2020 ####
-* [Bump Microsoft.NET.Test.Sdk from 16.5.0 to 16.6.1](https://github.com/akkadotnet/Hyperion/pull/174)
-* [Add deserialization support for ReadOnlyDictionary](https://github.com/akkadotnet/Hyperion/pull/177)
-* [Bump FluentAssertions from 5.10.2 to 5.10.3](https://github.com/akkadotnet/Hyperion/pull/171)
-* [Bump System.Collections.Immutable from 1.7.0 to 1.7.1](https://github.com/akkadotnet/Hyperion/pull/175)
-* [Bump BenchmarkDotNet from 0.12.0 to 0.12.1](https://github.com/akkadotnet/Hyperion/pull/172)
+### 0.9.17 March 25 2021 ####
+* [Bump Microsoft.NET.Test.Sdk from 16.6.1 to 16.7.1](https://github.com/akkadotnet/Hyperion/pull/182)
+* [Fix unit test problem](https://github.com/akkadotnet/Hyperion/pull/191)
+* [Bump FSharp.Core from 4.7.2 to 5.0.0](https://github.com/akkadotnet/Hyperion/pull/189)
+* [Fix issue #40 regarding partial streams](https://github.com/akkadotnet/Hyperion/pull/185)
+* [Fix Hyperion not using known serializers when defined](https://github.com/akkadotnet/Hyperion/pull/184)
+* [Bump Microsoft.NET.Test.Sdk from 16.7.1 to 16.8.3](https://github.com/akkadotnet/Hyperion/pull/196)
+* [Bump System.Collections.Immutable from 1.7.1 to 5.0.0](https://github.com/akkadotnet/Hyperion/pull/195)
+* [Bump FSharp.Core from 5.0.0 to 5.0.1](https://github.com/akkadotnet/Hyperion/pull/202)
+* [Update the cross framework spec to include complex POCO object, Type serialization, and support for netcoreapp3.1 and net5.0](https://github.com/akkadotnet/Hyperion/pull/204)
diff --git a/build-system/azure-pipeline.template.yaml b/build-system/azure-pipeline.template.yaml
index feba5487..38166d80 100644
--- a/build-system/azure-pipeline.template.yaml
+++ b/build-system/azure-pipeline.template.yaml
@@ -16,6 +16,15 @@ jobs:
clean: false # whether to fetch clean each time
submodules: recursive # set to 'true' for a single level of submodules or 'recursive' to get submodules of submodules
persistCredentials: true
+ - task: UseDotNet@2
+ displayName: 'Use .NET 5 SDK 5.0.101'
+ inputs:
+ version: 5.0.101
+ - task: UseDotNet@2
+ displayName: 'Use .NET Core Runtime 3.1.10'
+ inputs:
+ packageType: runtime
+ version: 3.1.10
# Linux or macOS
- task: Bash@3
displayName: Linux / OSX Build
diff --git a/build.fsx b/build.fsx
index 33ba702c..c3e5b00d 100644
--- a/build.fsx
+++ b/build.fsx
@@ -8,6 +8,7 @@ open System.Text
open Fake
open Fake.DotNetCli
open Fake.DocFxHelper
+open Fake.NuGet.Install
// Information about the project for Nuget and Assembly info files
let product = "Hyperion"
@@ -18,27 +19,42 @@ let signingName = "Hyperion"
let signingDescription = "A high performance polymorphic serializer for the .NET framework"
let signingUrl = ""
+// Directories
+let toolsDir = __SOURCE_DIRECTORY__ @@ "tools"
+let output = __SOURCE_DIRECTORY__ @@ "bin"
+let outputTests = __SOURCE_DIRECTORY__ @@ "TestResults"
+let outputPerfTests = __SOURCE_DIRECTORY__ @@ "PerfResults"
+let outputBinaries = output @@ "binaries"
+let outputBinariesNet461 = outputBinaries @@ "net461"
+let outputBinariesNetStandard = outputBinaries @@ "netstandard2.0"
+let outputBinariesNet = outputBinaries @@ "net5.0"
+let outputNuGet = output @@ "nuget"
// Read release notes and version
let solutionFile = FindFirstMatchingFile "*.sln" __SOURCE_DIRECTORY__ // dynamically look up the solution
let buildNumber = environVarOrDefault "BUILD_NUMBER" "0"
let hasTeamCity = (not (buildNumber = "0")) // check if we have the TeamCity environment variable for build # set
let preReleaseVersionSuffix = "beta" + (if (not (buildNumber = "0")) then (buildNumber) else DateTime.UtcNow.Ticks.ToString())
-let versionSuffix =
- match (getBuildParam "nugetprerelease") with
- | "dev" -> preReleaseVersionSuffix
- | _ -> ""
let releaseNotes =
- File.ReadLines "./RELEASE_NOTES.md"
+ File.ReadLines (__SOURCE_DIRECTORY__ @@ "RELEASE_NOTES.md")
|> ReleaseNotesHelper.parseReleaseNotes
-// Directories
-let toolsDir = __SOURCE_DIRECTORY__ @@ "tools"
-let output = __SOURCE_DIRECTORY__ @@ "bin"
-let outputTests = __SOURCE_DIRECTORY__ @@ "TestResults"
-let outputPerfTests = __SOURCE_DIRECTORY__ @@ "PerfResults"
-let outputNuGet = output @@ "nuget"
+let versionFromReleaseNotes =
+ match releaseNotes.SemVer.PreRelease with
+ | Some r -> r.Origin
+ | None -> ""
+
+let versionSuffix =
+ match (getBuildParam "nugetprerelease") with
+ | "dev" -> preReleaseVersionSuffix
+ | "" -> versionFromReleaseNotes
+ | str -> str
+
+// Configuration values for tests
+let testNetFrameworkVersion = "net461"
+let testNetCoreVersion = "netcoreapp3.1"
+let testNetVersion = "net5.0"
Target "Clean" (fun _ ->
ActivateFinalTarget "KillCreatedProcesses"
@@ -46,8 +62,15 @@ Target "Clean" (fun _ ->
CleanDir output
CleanDir outputTests
CleanDir outputPerfTests
+ CleanDir outputBinaries
CleanDir outputNuGet
+ CleanDir outputBinariesNet461
+ CleanDir outputBinariesNetStandard
+ CleanDir outputBinariesNet
CleanDir "docs/_site"
+
+ CleanDirs !! "./**/bin"
+ CleanDirs !! "./**/obj"
)
Target "AssemblyInfo" (fun _ ->
@@ -56,17 +79,20 @@ Target "AssemblyInfo" (fun _ ->
)
Target "Build" (fun _ ->
+ let additionalArgs = if versionSuffix.Length > 0 then [sprintf "/p:VersionSuffix=%s" versionSuffix] else []
DotNetCli.Build
(fun p ->
{ p with
Project = solutionFile
- Configuration = configuration }) // "Rebuild"
+ Configuration = configuration
+ AdditionalArgs = additionalArgs }) // "Rebuild"
)
//--------------------------------------------------------------------------------
// Tests targets
//--------------------------------------------------------------------------------
+
module internal ResultHandling =
let (|OK|Failure|) = function
| 0 -> OK
@@ -94,8 +120,32 @@ Target "RunTests" (fun _ ->
let runSingleProject project =
let arguments =
match (hasTeamCity) with
- | true -> (sprintf "test -c Release --no-build --logger:trx --logger:\"console;verbosity=normal\" --results-directory %s -- -parallel none -teamcity" (outputTests))
- | false -> (sprintf "test -c Release --no-build --logger:trx --logger:\"console;verbosity=normal\" --results-directory %s -- -parallel none" (outputTests))
+ | true -> (sprintf "test -c Release --no-build --logger:trx --logger:\"console;verbosity=normal\" --framework %s --results-directory \"%s\" -- -parallel none -teamcity" testNetFrameworkVersion outputTests)
+ | false -> (sprintf "test -c Release --no-build --logger:trx --logger:\"console;verbosity=normal\" --framework %s --results-directory \"%s\" -- -parallel none" testNetFrameworkVersion outputTests)
+
+ let result = ExecProcess(fun info ->
+ info.FileName <- "dotnet"
+ info.WorkingDirectory <- (Directory.GetParent project).FullName
+ info.Arguments <- arguments) (TimeSpan.FromMinutes 30.0)
+
+ ResultHandling.failBuildIfXUnitReportedError TestRunnerErrorLevel.Error result
+
+ CreateDir outputTests
+ projects |> Seq.iter (log)
+ projects |> Seq.iter (runSingleProject)
+)
+
+Target "RunTestsNetCore" (fun _ ->
+ let projects =
+ match (isWindows) with
+ | true -> !! "./src/**/*.Tests.csproj"
+ | _ -> !! "./src/**/*.Tests.csproj" // if you need to filter specs for Linux vs. Windows, do it here
+
+ let runSingleProject project =
+ let arguments =
+ match (hasTeamCity) with
+ | true -> (sprintf "test -c Release --no-build --logger:trx --logger:\"console;verbosity=normal\" --framework %s --results-directory \"%s\" -- -parallel none -teamcity" testNetCoreVersion outputTests)
+ | false -> (sprintf "test -c Release --no-build --logger:trx --logger:\"console;verbosity=normal\" --framework %s --results-directory \"%s\" -- -parallel none" testNetCoreVersion outputTests)
let result = ExecProcess(fun info ->
info.FileName <- "dotnet"
@@ -104,44 +154,64 @@ Target "RunTests" (fun _ ->
ResultHandling.failBuildIfXUnitReportedError TestRunnerErrorLevel.Error result
+ CreateDir outputTests
+ projects |> Seq.iter (log)
+ projects |> Seq.iter (runSingleProject)
+)
+
+Target "RunTestsNet" (fun _ ->
+ let projects =
+ match (isWindows) with
+ | true -> !! "./src/**/*.Tests.csproj"
+ | _ -> !! "./src/**/*.Tests.csproj" // if you need to filter specs for Linux vs. Windows, do it here
+
+ let runSingleProject project =
+ let arguments =
+ match (hasTeamCity) with
+ | true -> (sprintf "test -c Release --no-build --logger:trx --logger:\"console;verbosity=normal\" --framework %s --results-directory \"%s\" -- -parallel none -teamcity" testNetVersion outputTests)
+ | false -> (sprintf "test -c Release --no-build --logger:trx --logger:\"console;verbosity=normal\" --framework %s --results-directory \"%s\" -- -parallel none" testNetVersion outputTests)
+
+ let result = ExecProcess(fun info ->
+ info.FileName <- "dotnet"
+ info.WorkingDirectory <- (Directory.GetParent project).FullName
+ info.Arguments <- arguments) (TimeSpan.FromMinutes 30.0)
+
+ ResultHandling.failBuildIfXUnitReportedError TestRunnerErrorLevel.Error result
+
+ CreateDir outputTests
projects |> Seq.iter (log)
projects |> Seq.iter (runSingleProject)
)
Target "NBench" <| fun _ ->
- let nbenchTestPath = findToolInSubPath "NBench.Runner.exe" (toolsDir @@ "NBench.Runner*")
- printfn "Using NBench.Runner: %s" nbenchTestPath
-
- let nbenchTestAssemblies = !! "./src/**/bin/**/*Tests.Performance.dll" // doesn't support .NET Core at the moment
-
- let runNBench assembly =
- let includes = getBuildParam "include"
- let excludes = getBuildParam "exclude"
- let teamcityStr = (getBuildParam "teamcity")
- let enableTeamCity =
- match teamcityStr with
- | null -> false
- | "" -> false
- | _ -> bool.Parse teamcityStr
-
- let args = StringBuilder()
- |> append assembly
- |> append (sprintf "output-directory=\"%s\"" outputPerfTests)
- |> append (sprintf "concurrent=\"%b\"" true)
- |> append (sprintf "trace=\"%b\"" true)
- |> append (sprintf "teamcity=\"%b\"" enableTeamCity)
- |> appendIfNotNullOrEmpty includes "include="
- |> appendIfNotNullOrEmpty excludes "include="
+ ensureDirectory outputPerfTests
+ let projects =
+ match (isWindows) with
+ | true -> !! "./src/**/*Tests.Performance.csproj"
+ | _ -> !! "./src/**/*Tests.Performance.csproj" // if you need to filter specs for Linux vs. Windows, do it here
+
+ projects |> Seq.iter(fun project ->
+ let args = new StringBuilder()
+ |> append "run"
+ |> append "--no-build"
+ |> append "-c"
+ |> append configuration
+ |> append " -- "
+ |> append "--output"
+ |> append outputPerfTests
+ |> append "--concurrent"
+ |> append "true"
+ |> append "--trace"
+ |> append "true"
+ |> append "--diagnostic"
|> toText
- let result = ExecProcess(fun info ->
- info.FileName <- nbenchTestPath
- info.WorkingDirectory <- (Path.GetDirectoryName (FullName nbenchTestPath))
- info.Arguments <- args) (System.TimeSpan.FromMinutes 45.0) (* Reasonably long-running task. *)
-
- if result <> 0 then failwithf "NBench.Runner failed. %s %s" nbenchTestPath args
-
- nbenchTestAssemblies |> Seq.iter runNBench
+ let result = ExecProcess(fun info ->
+ info.FileName <- "dotnet"
+ info.WorkingDirectory <- (Directory.GetParent project).FullName
+ info.Arguments <- args) (System.TimeSpan.FromMinutes 15.0) (* Reasonably long-running task. *)
+ if result <> 0 then failwithf "NBench.Runner failed. %s %s" "dotnet" args
+ )
//--------------------------------------------------------------------------------
@@ -301,23 +371,30 @@ Target "Help" <| fun _ ->
Target "BuildRelease" DoNothing
Target "All" DoNothing
Target "Nuget" DoNothing
+Target "RunTestsFull" DoNothing
+Target "RunTestsNetCoreFull" DoNothing
// build dependencies
"Clean" ==> "AssemblyInfo" ==> "Build" ==> "BuildRelease"
// tests dependencies
"Build" ==> "RunTests"
+"Build" ==> "RunTestsNetCore"
+"Build" ==> "RunTestsNet"
+"Build" ==> "NBench"
// nuget dependencies
-"Clean" ==> "Build" ==> "CreateNuget"
+"BuildRelease" ==> "CreateNuget"
"CreateNuget" ==> "SignPackages" ==> "PublishNuget" ==> "Nuget"
// docs
-"Clean" ==> "BuildRelease" ==> "Docfx"
+"BuildRelease" ==> "Docfx"
// all
"BuildRelease" ==> "All"
"RunTests" ==> "All"
+"RunTestsNetCore" ==> "All"
+"RunTestsNet" ==> "All"
"NBench" ==> "All"
"Nuget" ==> "All"
diff --git a/build.ps1 b/build.ps1
index d2581ca4..953f4cc9 100644
--- a/build.ps1
+++ b/build.ps1
@@ -29,14 +29,11 @@ Param(
[string[]]$ScriptArgs
)
-$FakeVersion = "4.61.2"
-$DotNetChannel = "LTS";
-$DotNetVersion = "3.0.100";
-$DotNetInstallerUri = "https://dot.net/v1/dotnet-install.ps1";
-$NugetVersion = "4.1.0";
+$FakeVersion = "4.63.2"
+$NugetVersion = "5.8.0";
$NugetUrl = "https://dist.nuget.org/win-x86-commandline/v$NugetVersion/nuget.exe"
-$ProtobufVersion = "3.2.0"
-$DocfxVersion = "2.40.5"
+$ProtobufVersion = "3.13.0"
+$DocfxVersion = "2.48.1"
# Make sure tools folder exists
$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
@@ -46,51 +43,6 @@ if (!(Test-Path $ToolPath)) {
New-Item -Path $ToolPath -Type directory | out-null
}
-###########################################################################
-# INSTALL .NET CORE CLI
-###########################################################################
-
-Function Remove-PathVariable([string]$VariableToRemove)
-{
- $path = [Environment]::GetEnvironmentVariable("PATH", "User")
- if ($path -ne $null)
- {
- $newItems = $path.Split(';', [StringSplitOptions]::RemoveEmptyEntries) | Where-Object { "$($_)" -inotlike $VariableToRemove }
- [Environment]::SetEnvironmentVariable("PATH", [System.String]::Join(';', $newItems), "User")
- }
-
- $path = [Environment]::GetEnvironmentVariable("PATH", "Process")
- if ($path -ne $null)
- {
- $newItems = $path.Split(';', [StringSplitOptions]::RemoveEmptyEntries) | Where-Object { "$($_)" -inotlike $VariableToRemove }
- [Environment]::SetEnvironmentVariable("PATH", [System.String]::Join(';', $newItems), "Process")
- }
-}
-
-# Get .NET Core CLI path if installed.
-$FoundDotNetCliVersion = $null;
-if (Get-Command dotnet -ErrorAction SilentlyContinue) {
- $FoundDotNetCliVersion = dotnet --version;
- $env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
- $env:DOTNET_CLI_TELEMETRY_OPTOUT=1
-}
-
-if($FoundDotNetCliVersion -ne $DotNetVersion) {
- $InstallPath = Join-Path $PSScriptRoot ".dotnet"
- if (!(Test-Path $InstallPath)) {
- mkdir -Force $InstallPath | Out-Null;
- }
- (New-Object System.Net.WebClient).DownloadFile($DotNetInstallerUri, "$InstallPath\dotnet-install.ps1");
- & $InstallPath\dotnet-install.ps1 -Channel $DotNetChannel -Version $DotNetVersion -InstallDir $InstallPath -Architecture x64;
-
- Remove-PathVariable "$InstallPath"
- $env:PATH = "$InstallPath;$env:PATH"
- $env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
- $env:DOTNET_CLI_TELEMETRY_OPTOUT=1
- $env:DOTNET_ROOT=$InstallPath
-}
-
-
###########################################################################
# INSTALL NUGET
###########################################################################
diff --git a/build.sh b/build.sh
index 230cfe96..05d67196 100644
--- a/build.sh
+++ b/build.sh
@@ -41,23 +41,6 @@ if [ ! -d "$TOOLS_DIR" ]; then
mkdir "$TOOLS_DIR"
fi
-###########################################################################
-# INSTALL .NET CORE CLI
-###########################################################################
-
-echo "Installing .NET CLI..."
-if [ ! -d "$SCRIPT_DIR/.dotnet" ]; then
- mkdir "$SCRIPT_DIR/.dotnet"
-fi
-curl -Lsfo "$SCRIPT_DIR/.dotnet/dotnet-install.sh" $DOTNET_INSTALLER_URL
-bash "$SCRIPT_DIR/.dotnet/dotnet-install.sh" --version $DOTNET_VERSION --channel $DOTNET_CHANNEL --install-dir .dotnet --no-path
-export PATH="$SCRIPT_DIR/.dotnet":$PATH
-export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
-export DOTNET_CLI_TELEMETRY_OPTOUT=1
-chmod -R 0755 ".dotnet"
-"$SCRIPT_DIR/.dotnet/dotnet" --info
-
-
###########################################################################
# INSTALL NUGET
###########################################################################
diff --git a/src/Hyperion.Tests.FSharpData/Hyperion.Tests.FSharpData.fsproj b/src/Hyperion.Tests.FSharpData/Hyperion.Tests.FSharpData.fsproj
index 75179c29..ade9902c 100644
--- a/src/Hyperion.Tests.FSharpData/Hyperion.Tests.FSharpData.fsproj
+++ b/src/Hyperion.Tests.FSharpData/Hyperion.Tests.FSharpData.fsproj
@@ -9,7 +9,7 @@
-
+
diff --git a/src/Hyperion.Tests/Bugs.cs b/src/Hyperion.Tests/Bugs.cs
index a4ebe36c..ebd9f562 100644
--- a/src/Hyperion.Tests/Bugs.cs
+++ b/src/Hyperion.Tests/Bugs.cs
@@ -8,21 +8,31 @@
#endregion
using System;
+using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
+using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using FluentAssertions;
using Hyperion.Extensions;
using Xunit;
+using Xunit.Abstractions;
namespace Hyperion.Tests
{
public class Bugs
{
+ private readonly ITestOutputHelper _output;
+
+ public Bugs(ITestOutputHelper output)
+ {
+ _output = output;
+ }
+
#region issue 58
public enum TrustLevel { Unknown, Suspicious, Partial, Fully }
@@ -246,5 +256,224 @@ public Recover(SnapshotSelectionCriteria fromSnapshot, long toSequenceNr = long.
///
public long ReplayMax { get; private set; }
}
+
+ delegate int TestDelegate(int x, int y);
+
+ class Temp : IEquatable
+ {
+ public object[] SubArray { get; set; }
+ public int[] IntArray { get; set; }
+ public int[,] IntIntArray { get; set; }
+ public Poco Poco { get; set; }
+ public string String { get; set; }
+ public Dictionary Dictionary { get; set; }
+ public TestDelegate Delegate { get; set; }
+ public IEnumerable TestEnum { get; set; }
+ public Exception Exception { get; set; }
+ public ImmutableList ImmutableList { get; set; }
+ public ImmutableDictionary ImmutableDictionary { get; set; }
+
+ public bool Equals(Temp other)
+ {
+ if (other == null)
+ throw new Exception("Equals failed.");
+ if (ReferenceEquals(this, other))
+ throw new Exception("Equals failed.");
+ if (IntIntArray.Rank != other.IntIntArray.Rank)
+ throw new Exception("Equals failed.");
+
+ for (var i = 0; i < IntIntArray.Rank; ++i)
+ {
+ for (var j = 0; j < IntIntArray.GetLength(i); ++j)
+ {
+ if (IntIntArray[j, i] != other.IntIntArray[j, i])
+ throw new Exception("Equals failed.");
+ }
+ }
+
+ if (Exception.GetType() != other.Exception.GetType())
+ throw new Exception("Equals failed.");
+ if (Exception.Message != other.Exception.Message)
+ throw new Exception("Equals failed.");
+ if(Exception.InnerException != null
+ && Exception.InnerException.GetType() != other.Exception.InnerException.GetType())
+ throw new Exception("Equals failed.");
+
+ for (var i = 0; i < SubArray.Length; i++)
+ {
+ if (SubArray[i].GetType() != other.SubArray[i].GetType())
+ throw new Exception("Equals failed.");
+
+ if (SubArray[i] is Array arr)
+ {
+ var oArr = (Array)other.SubArray[i];
+ for (var j = 0; j < arr.Length; ++j)
+ {
+ if (!arr.GetValue(j).Equals(oArr.GetValue(j)))
+ throw new Exception("Equals failed.");
+ }
+ } else if (!SubArray[i].Equals(other.SubArray[i]))
+ throw new Exception("Equals failed.");
+ }
+
+ foreach (var key in Dictionary.Keys)
+ {
+ if (!Dictionary[key].Equals(other.Dictionary[key]))
+ throw new Exception("Equals failed.");
+ }
+
+ foreach (var key in ImmutableDictionary.Keys)
+ {
+ if (!ImmutableDictionary[key].Equals(other.ImmutableDictionary[key]))
+ throw new Exception("Equals failed.");
+ }
+
+ if (other.Delegate(2, 2) != 4)
+ throw new Exception("Equals failed.");
+
+ if(!IntArray.SequenceEqual(other.IntArray))
+ throw new Exception("Equals failed.");
+ if(!Equals(Poco, other.Poco))
+ throw new Exception("Equals failed.");
+ if (String != other.String)
+ throw new Exception("Equals failed.");
+ if(!TestEnum.SequenceEqual(other.TestEnum))
+ throw new Exception("Equals failed.");
+ if(!ImmutableList.SequenceEqual(other.ImmutableList))
+ throw new Exception("Equals failed.");
+
+ return true;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj == null) throw new Exception("Equals failed.");
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != this.GetType()) throw new Exception("Equals failed.");
+ return Equals((Temp) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = (SubArray != null ? SubArray.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (IntArray != null ? IntArray.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (IntIntArray != null ? IntIntArray.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (Poco != null ? Poco.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (String != null ? String.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (Dictionary != null ? Dictionary.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (Delegate != null ? Delegate.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (TestEnum != null ? TestEnum.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (Exception != null ? Exception.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (ImmutableList != null ? ImmutableList.GetHashCode() : 0);
+ return hashCode;
+ }
+ }
+ }
+
+ class Poco : IEquatable
+ {
+ public Poco()
+ { }
+
+ public Poco(int intValue, string stringValue)
+ {
+ Int = intValue;
+ String = stringValue;
+ }
+
+ public int Int { get; set; }
+ public string String { get; set; }
+
+ public bool Equals(Poco other)
+ {
+ if (ReferenceEquals(null, other))
+ throw new Exception("Equals failed.");
+ if (ReferenceEquals(this, other))
+ throw new Exception("Equals failed.");
+ if(Int != other.Int)
+ throw new Exception("Equals failed.");
+ if(String != other.String)
+ throw new Exception("Equals failed.");
+ return true;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) throw new Exception("Equals failed.");
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != this.GetType()) throw new Exception("Equals failed.");
+ return Equals((Poco) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return (Int * 397) ^ (String != null ? String.GetHashCode() : 0);
+ }
+ }
+ }
+
+ [Fact]
+ public void WritesManifestEvenIfKnown()
+ {
+ var stream = new MemoryStream();
+ var msg = new Temp
+ {
+ SubArray = new object[] { 1, (byte)2, new object[] { 3 } },
+ IntArray = new [] {1, 2, 3, 4, 5},
+ IntIntArray = new [,] {{1, 2}, {3,4}, {5,6}, {7,8}},
+ Poco = new Poco(999, "666"),
+ String = "huhu",
+ Dictionary = new Dictionary
+ {
+ { 666, "b" },
+ { 999, "testString" },
+ { 42, "iMaGiNe" }
+ },
+ Delegate = (x, y) => x * y,
+ TestEnum = new[]{4,8,9,3,2},
+ Exception = new ArgumentException("Test Exception", new IndexOutOfRangeException("-999")),
+ ImmutableList = new [] {9, 4, 6, 2, 5}.ToImmutableList(),
+ ImmutableDictionary = new Dictionary
+ {
+ { 666, "b" },
+ { 999, "testString" },
+ { 42, "iMaGiNe" }
+ }.ToImmutableDictionary(),
+ };
+ var serializer = new Serializer(new SerializerOptions(knownTypes: new[]
+ {
+ typeof(object[]),
+ typeof(int[]),
+ typeof(int[,]),
+ typeof(Dictionary),
+ typeof(DictionaryEntry),
+ typeof(KeyValuePair),
+ typeof(Temp),
+ typeof(TestDelegate),
+ typeof(Enumerable),
+ typeof(IEnumerable),
+ typeof(Exception),
+ typeof(ArgumentException),
+ typeof(IndexOutOfRangeException),
+ typeof(FieldInfo),
+ typeof(ImmutableList),
+ typeof(ImmutableList),
+ typeof(ImmutableDictionary),
+ typeof(MethodInfo),
+ typeof(PropertyInfo),
+ }));
+ serializer.Serialize(msg, stream);
+ stream.Position = 0;
+ var a = stream.ToArray();
+ var text = string.Join("", a.Select(x => x < 32 || x > 126 ? "" : ((char)x).ToString()));
+ _output.WriteLine(text);
+ var res = (Temp)serializer.Deserialize(stream);
+ Assert.DoesNotContain("System.Collections.Generic.Dictionary", text);
+ Assert.Equal(msg, res);
+ }
}
}
diff --git a/src/Hyperion.Tests/CrossFrameworkSerializationTests.cs b/src/Hyperion.Tests/CrossFrameworkSerializationTests.cs
index 69ba00fd..32e9d203 100644
--- a/src/Hyperion.Tests/CrossFrameworkSerializationTests.cs
+++ b/src/Hyperion.Tests/CrossFrameworkSerializationTests.cs
@@ -2,26 +2,39 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using FluentAssertions;
using Hyperion.Tests.Generator;
using Xunit;
+using Xunit.Abstractions;
namespace Hyperion.Tests
{
public class CrossFrameworkSerializationTests
{
+ private readonly ITestOutputHelper _log;
private readonly Serializer _serializer;
private readonly CrossFrameworkClass _originalObject;
+ private readonly CrossFrameworkMixedClass _originalMixedObject;
- public CrossFrameworkSerializationTests()
+ public CrossFrameworkSerializationTests(ITestOutputHelper log)
{
+ _log = log;
_serializer = new Serializer();
_originalObject = CrossFrameworkInitializer.Init();
+ _originalMixedObject = CrossFrameworkInitializer.InitMixed();
}
public static IEnumerable