public void ValidateBasicObjectsRoundtrip(object obj, FormatterAssemblyStyle assemblyFormat, TypeFilterLevel filterLevel, FormatterTypeStyle typeFormat) { object clone = BinaryFormatterHelpers.Clone(obj, null, assemblyFormat, filterLevel, typeFormat); // string.Empty and DBNull are both singletons if (!ReferenceEquals(obj, string.Empty) && !(obj is DBNull)) { Assert.NotSame(obj, clone); } EqualityExtensions.CheckEquals(obj, clone, isSamePlatform: true); }
public void RegexExceptionSerializable() { try { new Regex("*"); // parsing "*" - Quantifier {x,y} following nothing. } catch (ArgumentException ex) { Assert.Equal(ex.GetType().Name, "RegexParseException"); ArgumentException clone = BinaryFormatterHelpers.Clone(ex); Assert.IsType <ArgumentException>(clone); } }
private static void ValidateAndRoundtrip(object obj, TypeSerializableValue[] blobs, bool isEqualityComparer) { if (obj == null) { throw new ArgumentNullException("The serializable object must not be null", nameof(obj)); } if (blobs == null || blobs.Length == 0) { throw new ArgumentOutOfRangeException($"Type {obj} has no blobs to deserialize and test equality against. Blob: " + BinaryFormatterHelpers.ToBase64String(obj, FormatterAssemblyStyle.Full)); } SanityCheckBlob(obj, blobs); // SqlException, ReflectionTypeLoadException and LicenseException aren't deserializable from Desktop --> Core. // Therefore we remove the second blob which is the one from Desktop. if (!PlatformDetection.IsFullFramework && (obj is SqlException || obj is ReflectionTypeLoadException || obj is LicenseException)) { var tmpList = new List <TypeSerializableValue>(blobs); tmpList.RemoveAt(1); int index = tmpList.FindIndex(b => b.Platform.IsNetfxPlatform()); if (index >= 0) { tmpList.RemoveAt(index); } blobs = tmpList.ToArray(); } // We store our framework blobs in index 1 int platformBlobIndex = blobs.GetPlatformIndex(); for (int i = 0; i < blobs.Length; i++) { // Check if the current blob is from the current running platform. bool isSamePlatform = i == platformBlobIndex; if (isEqualityComparer) { ValidateEqualityComparer(BinaryFormatterHelpers.FromBase64String(blobs[i].Base64Blob, FormatterAssemblyStyle.Simple)); ValidateEqualityComparer(BinaryFormatterHelpers.FromBase64String(blobs[i].Base64Blob, FormatterAssemblyStyle.Full)); } else { EqualityExtensions.CheckEquals(obj, BinaryFormatterHelpers.FromBase64String(blobs[i].Base64Blob, FormatterAssemblyStyle.Simple), isSamePlatform); EqualityExtensions.CheckEquals(obj, BinaryFormatterHelpers.FromBase64String(blobs[i].Base64Blob, FormatterAssemblyStyle.Full), isSamePlatform); } } }
// Used for updating blobs in BinaryFormatterTestData.cs //[Fact] public void UpdateBlobs() { string testDataFilePath = GetTestDataFilePath(); string[] coreTypeBlobs = SerializableEqualityComparers_MemberData() .Concat(SerializableObjects_MemberData()) .Select(record => BinaryFormatterHelpers.ToBase64String(record[0])) .ToArray(); var(numberOfBlobs, numberOfFoundBlobs, numberOfUpdatedBlobs) = UpdateCoreTypeBlobs(testDataFilePath, coreTypeBlobs); Console.WriteLine($"{numberOfBlobs} existing blobs" + $"{Environment.NewLine}{numberOfFoundBlobs} found blobs with regex search" + $"{Environment.NewLine}{numberOfUpdatedBlobs} updated blobs with regex replace"); }
public void ValidateDeserializationOfObjectWithDifferentAssemblyVersion() { // To generate this properly, change AssemblyVersion to a value which is unlikely to happen in production and generate base64(serialized-data) // For this test 9.98.7.987 is being used var obj = new SomeType() { SomeField = 7 }; string serializedObj = @"AAEAAAD/////AQAAAAAAAAAMAgAAAHNTeXN0ZW0uUnVudGltZS5TZXJpYWxpemF0aW9uLkZvcm1hdHRlcnMuVGVzdHMsIFZlcnNpb249OS45OC43Ljk4NywgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj05ZDc3Y2M3YWQzOWI2OGViBQEAAAA2U3lzdGVtLlJ1bnRpbWUuU2VyaWFsaXphdGlvbi5Gb3JtYXR0ZXJzLlRlc3RzLlNvbWVUeXBlAQAAAAlTb21lRmllbGQACAIAAAAHAAAACw=="; var deserialized = (SomeType)BinaryFormatterHelpers.FromBase64String(serializedObj, FormatterAssemblyStyle.Simple); Assert.Equal(obj, deserialized); }
public void SameObjectRepeatedInArray() { object o = new object(); object[] arr = new[] { o, o, o, o, o }; object[] result = BinaryFormatterHelpers.Clone(arr); Assert.Equal(arr.Length, result.Length); Assert.NotSame(arr, result); Assert.NotSame(arr[0], result[0]); for (int i = 1; i < result.Length; i++) { Assert.Same(result[0], result[i]); } }
public void RegexExceptionSerializable() { try { #pragma warning disable RE0001 // Regex issue: {0} new Regex("*"); // parsing "*" - Quantifier {x,y} following nothing. #pragma warning restore RE0001 // Regex issue: {0} } catch (ArgumentException ex) { Assert.Equal("RegexParseException", ex.GetType().Name); ArgumentException clone = BinaryFormatterHelpers.Clone(ex); Assert.IsType <ArgumentException>(clone); } }
public void SerializeNonSerializableTypeWithSurrogate() { var p = new NonSerializablePair <int, string>() { Value1 = 1, Value2 = "2" }; Assert.False(p.GetType().IsSerializable); Assert.Throws <SerializationException>(() => BinaryFormatterHelpers.Clone(p)); NonSerializablePair <int, string> result = BinaryFormatterHelpers.Clone(p, new NonSerializablePairSurrogate()); Assert.NotSame(p, result); Assert.Equal(p.Value1, result.Value1); Assert.Equal(p.Value2, result.Value2); }
public void ValidateDeserializationOfObjectWithGenericTypeWhichGenericArgumentHasDifferentAssemblyVersion() { // To generate this properly, change AssemblyVersion to a value which is unlikely to happen in production and generate base64(serialized-data) // For this test 9.98.7.987 is being used var obj = new GenericTypeWithArg <SomeType>() { Test = new SomeType() { SomeField = 9 } }; string serializedObj = @"AAEAAAD/////AQAAAAAAAAAMAgAAAHNTeXN0ZW0uUnVudGltZS5TZXJpYWxpemF0aW9uLkZvcm1hdHRlcnMuVGVzdHMsIFZlcnNpb249OS45OC43Ljk4NywgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj05ZDc3Y2M3YWQzOWI2OGViBQEAAADxAVN5c3RlbS5SdW50aW1lLlNlcmlhbGl6YXRpb24uRm9ybWF0dGVycy5UZXN0cy5HZW5lcmljVHlwZVdpdGhBcmdgMVtbU3lzdGVtLlJ1bnRpbWUuU2VyaWFsaXphdGlvbi5Gb3JtYXR0ZXJzLlRlc3RzLlNvbWVUeXBlLCBTeXN0ZW0uUnVudGltZS5TZXJpYWxpemF0aW9uLkZvcm1hdHRlcnMuVGVzdHMsIFZlcnNpb249OS45OC43Ljk4NywgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj05ZDc3Y2M3YWQzOWI2OGViXV0BAAAABFRlc3QENlN5c3RlbS5SdW50aW1lLlNlcmlhbGl6YXRpb24uRm9ybWF0dGVycy5UZXN0cy5Tb21lVHlwZQIAAAACAAAACQMAAAAFAwAAADZTeXN0ZW0uUnVudGltZS5TZXJpYWxpemF0aW9uLkZvcm1hdHRlcnMuVGVzdHMuU29tZVR5cGUBAAAACVNvbWVGaWVsZAAIAgAAAAkAAAAL"; var deserialized = (GenericTypeWithArg <SomeType>)BinaryFormatterHelpers.FromBase64String(serializedObj, FormatterAssemblyStyle.Simple); Assert.Equal(obj, deserialized); }
private static void SanityCheckBlob(object obj, TypeSerializableValue[] blobs) { // These types are unstable during serialization and produce different blobs. if (obj is WeakReference <Point> || obj is Collections.Specialized.HybridDictionary || obj is Color || obj.GetType().FullName == "System.Collections.SortedList+SyncSortedList") { return; } // The blobs aren't identical because of different implementations on Unix vs. Windows. if (obj is Bitmap || obj is Icon || obj is Metafile) { return; } // In most cases exceptions in Core have a different layout than in Desktop, // therefore we are skipping the string comparison of the blobs. if (obj is Exception) { return; } // Check if runtime generated blob is the same as the stored one int frameworkBlobNumber = blobs.GetPlatformIndex(); if (frameworkBlobNumber < blobs.Length) { string runtimeBlob = BinaryFormatterHelpers.ToBase64String(obj, FormatterAssemblyStyle.Full); string storedComparableBlob = CreateComparableBlobInfo(blobs[frameworkBlobNumber].Base64Blob); string runtimeComparableBlob = CreateComparableBlobInfo(runtimeBlob); Assert.True(storedComparableBlob == runtimeComparableBlob, $"The stored blob for type {obj.GetType().FullName} is outdated and needs to be updated.{Environment.NewLine}{Environment.NewLine}" + $"-------------------- Stored blob ---------------------{Environment.NewLine}" + $"Encoded: {blobs[frameworkBlobNumber].Base64Blob}{Environment.NewLine}" + $"Decoded: {storedComparableBlob}{Environment.NewLine}{Environment.NewLine}" + $"--------------- Runtime generated blob ---------------{Environment.NewLine}" + $"Encoded: {runtimeBlob}{Environment.NewLine}" + $"Decoded: {runtimeComparableBlob}"); } }
private static void ValidateAndRoundtrip(object obj, string[] blobs, bool isEqualityComparer) { if (obj == null) { throw new ArgumentNullException("The serializable object must not be null", nameof(obj)); } if (blobs == null || blobs.Length == 0) { throw new ArgumentOutOfRangeException($"Type {obj} has no blobs to deserialize and test equality against. Blob: " + BinaryFormatterHelpers.ToBase64String(obj, FormatterAssemblyStyle.Full)); } SanityCheckBlob(obj, blobs); // SqlException isn't deserializable from Desktop --> Core. // Therefore we remove the second blob which is the one from Desktop. if (!PlatformDetection.IsFullFramework && (obj is SqlException || obj is ReflectionTypeLoadException || obj is LicenseException)) { var tmpList = new List <string>(blobs); tmpList.RemoveAt(1); blobs = tmpList.ToArray(); } foreach (string blob in blobs) { if (isEqualityComparer) { ValidateEqualityComparer(BinaryFormatterHelpers.FromBase64String(blob, FormatterAssemblyStyle.Simple)); ValidateEqualityComparer(BinaryFormatterHelpers.FromBase64String(blob, FormatterAssemblyStyle.Full)); } else { CheckForAnyEquals(obj, BinaryFormatterHelpers.FromBase64String(blob, FormatterAssemblyStyle.Simple)); CheckForAnyEquals(obj, BinaryFormatterHelpers.FromBase64String(blob, FormatterAssemblyStyle.Full)); } } }
private static void SanityCheckBlob(object obj, string[] blobs) { // These types are unstable during serialization and produce different blobs. if (obj is WeakReference <Point> || obj is Collections.Specialized.HybridDictionary || obj is TimeZoneInfo.AdjustmentRule) { return; } // In most cases exceptions in Core have a different layout than in Desktop, // therefore we are skipping the string comparison of the blobs. if (obj is Exception) { return; } // Check if runtime generated blob is the same as the stored one int frameworkBlobNumber = PlatformDetection.IsFullFramework ? 1 : 0; if (frameworkBlobNumber < blobs.Length) { string runtimeBlob = BinaryFormatterHelpers.ToBase64String(obj, FormatterAssemblyStyle.Full); string storedComparableBlob = CreateComparableBlobInfo(blobs[frameworkBlobNumber]); string runtimeComparableBlob = CreateComparableBlobInfo(runtimeBlob); Assert.True(storedComparableBlob == runtimeComparableBlob, $"The stored blob for type {obj.GetType().FullName} is outdated and needs to be updated.{Environment.NewLine}{Environment.NewLine}" + $"-------------------- Stored blob ---------------------{Environment.NewLine}" + $"Encoded: {blobs[frameworkBlobNumber]}{Environment.NewLine}" + $"Decoded: {storedComparableBlob}{Environment.NewLine}{Environment.NewLine}" + $"--------------- Runtime generated blob ---------------{Environment.NewLine}" + $"Encoded: {runtimeBlob}{Environment.NewLine}" + $"Decoded: {runtimeComparableBlob}"); } }
public void Roundtrip_ArrayContainingArrayAtNonZeroLowerBound() { BinaryFormatterHelpers.Clone(Array.CreateInstance(typeof(uint[]), new[] { 5 }, new[] { 1 })); }
private static void ValidateAndRoundtrip(object obj, TypeSerializableValue[] blobs, bool isEqualityComparer) { if (obj == null) { throw new ArgumentNullException("The serializable object must not be null", nameof(obj)); } if (blobs == null || blobs.Length == 0) { throw new ArgumentOutOfRangeException($"Type {obj} has no blobs to deserialize and test equality against. Blob: " + BinaryFormatterHelpers.ToBase64String(obj, FormatterAssemblyStyle.Full)); } // Check if the passed in value in a serialization entry is assignable by the passed in type. if (obj is ISerializable customSerializableObj && HasObjectTypeIntegrity(customSerializableObj)) { CheckObjectTypeIntegrity(customSerializableObj); } // TimeZoneInfo objects have three properties (DisplayName, StandardName, DaylightName) // that are localized. Since the blobs were generated from the invariant culture, they // will have English strings embedded. Thus, we can only test them against English // language cultures or the invariant culture. if (obj is TimeZoneInfo && ( CultureInfo.CurrentUICulture.TwoLetterISOLanguageName != "en" || CultureInfo.CurrentUICulture.Name.Length != 0)) { return; } SanityCheckBlob(obj, blobs); // ReflectionTypeLoadException and LicenseException aren't deserializable from Desktop --> Core. // Therefore we remove the second blob which is the one from Desktop. if (!PlatformDetection.IsNetFramework && (obj is ReflectionTypeLoadException || obj is LicenseException)) { var tmpList = new List <TypeSerializableValue>(blobs); tmpList.RemoveAt(1); int index = tmpList.FindIndex(b => b.Platform.ToString().StartsWith("netfx")); if (index >= 0) { tmpList.RemoveAt(index); } blobs = tmpList.ToArray(); } // We store our framework blobs in index 1 int platformBlobIndex = blobs.GetPlatformIndex(); for (int i = 0; i < blobs.Length; i++) { // Check if the current blob is from the current running platform. bool isSamePlatform = i == platformBlobIndex; if (isEqualityComparer) { ValidateEqualityComparer(BinaryFormatterHelpers.FromBase64String(blobs[i].Base64Blob, FormatterAssemblyStyle.Simple)); ValidateEqualityComparer(BinaryFormatterHelpers.FromBase64String(blobs[i].Base64Blob, FormatterAssemblyStyle.Full)); } else { EqualityExtensions.CheckEquals(obj, BinaryFormatterHelpers.FromBase64String(blobs[i].Base64Blob, FormatterAssemblyStyle.Simple), isSamePlatform); EqualityExtensions.CheckEquals(obj, BinaryFormatterHelpers.FromBase64String(blobs[i].Base64Blob, FormatterAssemblyStyle.Full), isSamePlatform); } } }
public void Roundtrip_Exceptions(Exception expected) { BinaryFormatterHelpers.AssertRoundtrips(expected); }
public void NullableComparersRoundtrip(string expectedType, object obj) { string serialized = BinaryFormatterHelpers.ToBase64String(obj); Assert.Equal(expectedType, BinaryFormatterHelpers.FromBase64String(serialized).GetType().Name); }