private static void SanityCheckBlob(object obj, TypeSerializableValue[] blobs) { // These types are unstable during serialization and produce different blobs. string name = obj.GetType().FullName; if (obj is WeakReference <Point> || obj is Collections.Specialized.HybridDictionary || obj is Color || name == "System.Collections.SortedList+SyncSortedList" || // Due to non-deterministic field ordering the types below will fail when using IL Emit-based Invoke. // The types above may also be failing for the same reason. // Remove these cases once https://github.com/dotnet/runtime/issues/46272 is fixed. name == "System.Collections.Comparer" || name == "System.Collections.Hashtable" || name == "System.Collections.SortedList" || name == "System.Collections.Specialized.ListDictionary" || name == "System.CultureAwareComparer" || name == "System.Globalization.CompareInfo" || name == "System.Net.Cookie" || name == "System.Net.CookieCollection" || name == "System.Net.CookieContainer") { 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); 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 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); } 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"); }
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(); } // We store our framework blobs in index 1 int platformBlobIndex = PlatformDetection.IsFullFramework ? 1 : 0; 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], FormatterAssemblyStyle.Simple)); ValidateEqualityComparer(BinaryFormatterHelpers.FromBase64String(blobs[i], FormatterAssemblyStyle.Full)); } else { EqualityExtensions.CheckEquals(obj, BinaryFormatterHelpers.FromBase64String(blobs[i], FormatterAssemblyStyle.Simple), isSamePlatform); EqualityExtensions.CheckEquals(obj, BinaryFormatterHelpers.FromBase64String(blobs[i], FormatterAssemblyStyle.Full), isSamePlatform); } } }
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}"); } }
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 NullableComparersRoundtrip(string expectedType, object obj) { string serialized = BinaryFormatterHelpers.ToBase64String(obj); Assert.Equal(expectedType, BinaryFormatterHelpers.FromBase64String(serialized).GetType().Name); }