From cf8282ebaf32deb6b53a65b9103ba42aff337f0f Mon Sep 17 00:00:00 2001 From: Tanya Solyanik Date: Tue, 15 Apr 2025 14:02:32 -0700 Subject: [PATCH] renamed a test input class, added exception message verification and did a minor clean up --- .../System.Windows.Forms/ResourceStrings.cs | 18 ++++ .../System/Windows/Forms/ClipboardTests.cs | 94 ++++++++++--------- .../Forms/NativeToWinFormsAdapterTests.cs | 41 ++++---- .../Data/ManagedAndRuntimeDataObject.cs | 2 +- .../Data/TypedDataObject.cs | 2 +- ...agedDataObject.cs => UntypedDataObject.cs} | 2 +- 6 files changed, 85 insertions(+), 74 deletions(-) create mode 100644 src/test/unit/System.Windows.Forms/ResourceStrings.cs rename src/test/util/System.Windows.Forms/Data/{ManagedDataObject.cs => UntypedDataObject.cs} (96%) diff --git a/src/test/unit/System.Windows.Forms/ResourceStrings.cs b/src/test/unit/System.Windows.Forms/ResourceStrings.cs new file mode 100644 index 00000000000..a8fee19de26 --- /dev/null +++ b/src/test/unit/System.Windows.Forms/ResourceStrings.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Text.RegularExpressions; + +namespace System.Windows.Forms.Tests; + +internal static partial class ResourceStrings +{ + [GeneratedRegex(@"{[0-9]}")] + private static partial Regex PlaceholdersPattern(); + + internal static string InvalidTypeFormatCombinationMessage => + PlaceholdersPattern().Replace(SR.ClipboardOrDragDrop_InvalidFormatTypeCombination, "*"); + internal static string TypeRequiresResolver => PlaceholdersPattern().Replace(SR.ClipboardOrDragDrop_InvalidType, "*"); + internal static string UseTryGetDataWithResolver => PlaceholdersPattern().Replace(SR.ClipboardOrDragDrop_UseTypedAPI, "*"); + internal static string TypedInterfaceNotImplemented => PlaceholdersPattern().Replace(SR.ITypeDataObject_Not_Implemented, "*"); +} diff --git a/src/test/unit/System.Windows.Forms/System/Windows/Forms/ClipboardTests.cs b/src/test/unit/System.Windows.Forms/System/Windows/Forms/ClipboardTests.cs index 83457c4e083..7529336445c 100644 --- a/src/test/unit/System.Windows.Forms/System/Windows/Forms/ClipboardTests.cs +++ b/src/test/unit/System.Windows.Forms/System/Windows/Forms/ClipboardTests.cs @@ -566,13 +566,13 @@ public unsafe void GetReturnsProxy() PInvokeCore.OleGetClipboard(proxy).Succeeded.Should().BeTrue(); ((nint)proxy.Value).Should().NotBe((nint)dataScope.Value); - using var dataUnknown = dataScope.Query(); - using var proxyUnknown = proxy.Query(); + using var dataUnknown = dataScope.Query(); + using var proxyUnknown = proxy.Query(); ((nint)proxyUnknown.Value).Should().NotBe((nint)dataUnknown.Value); // The proxy does not know about this interface, it should give back the real pointer. - using var realDataPointer = proxy.Query(); - using var realDataPointerUnknown = realDataPointer.Query(); + using var realDataPointer = proxy.Query(); + using var realDataPointerUnknown = realDataPointer.Query(); ((nint)proxyUnknown.Value).Should().NotBe((nint)realDataPointerUnknown.Value); ((nint)dataUnknown.Value).Should().Be((nint)realDataPointerUnknown.Value); } @@ -1311,52 +1311,19 @@ public void RoundTrip_TypedDataObject_SupportsTypedInterface(bool copy) => [WinFormsTheory] [BoolData] - public void RoundTrip_ManagedDataObject_SupportsTypedInterface(bool copy) => - CustomDataObject_RoundTrip_SupportsTypedInterface(copy); - - [WinFormsTheory] - [BoolData] - public void RoundTrip_Object_SupportsTypedInterface(bool copy) - { - SerializableTestData data = new(); - string format = typeof(SerializableTestData).FullName!; - - // Opt-in into access to the binary formatted stream. - using BinaryFormatterInClipboardDragDropScope clipboardScope = new(enable: copy); - - // We need the BinaryFormatter to flush the data from the managed object to the HGLOBAL - // and to write data to HGLOBAL as a binary formatted stream now if it hadn't been flushed. - using BinaryFormatterScope scope = new(enable: copy); - - Clipboard.SetDataObject(data, copy); - - DataObject received = Clipboard.GetDataObject().Should().BeAssignableTo().Subject; - - received.TryGetData( - format, - name => name.FullName == typeof(SerializableTestData).FullName ? typeof(SerializableTestData) : null, - autoConvert: false, - out SerializableTestData? result).Should().BeTrue(); - - result.Should().BeEquivalentTo(data); - - Clipboard.TryGetData( - format, - (TypeName name) => name.FullName == typeof(SerializableTestData).FullName ? typeof(SerializableTestData) : null, - out result).Should().BeTrue(); - - result.Should().BeEquivalentTo(data); - } + public void RoundTrip_UntypedDataObject_SupportsTypedInterface(bool copy) => + CustomDataObject_RoundTrip_SupportsTypedInterface(copy); private static void CustomDataObject_RoundTrip_SupportsTypedInterface(bool copy) where T : IDataObject, new() { SerializableTestData data = new(); T testDataObject = new(); - string format = ManagedDataObject.s_format; + string format = UntypedDataObject.s_format; testDataObject.SetData(format, data); // Opt-in into access the binary formatted stream. using BinaryFormatterInClipboardDragDropScope clipboardScope = new(enable: copy); + // We need the BinaryFormatter to flush the data from the managed object to the HGLOBAL. using (BinaryFormatterScope scope = new(enable: copy)) { @@ -1371,7 +1338,7 @@ public void RoundTrip_Object_SupportsTypedInterface(bool copy) using BinaryFormatterScope scope = new(enable: copy); ITypedDataObject received = Clipboard.GetDataObject().Should().BeAssignableTo().Subject; - // Need an explict resolver to hit the BinaryFormatter path if the data was copied out. + // Need an explicit resolver to hit the BinaryFormatter path if the data was copied out. received.TryGetData(format, out SerializableTestData? result).Should().Be(!copy); if (copy) { @@ -1384,7 +1351,7 @@ public void RoundTrip_Object_SupportsTypedInterface(bool copy) received.TryGetData( format, - (TypeName name) => name.FullName == typeof(SerializableTestData).FullName ? typeof(SerializableTestData) : null, + name => name.FullName == typeof(SerializableTestData).FullName ? typeof(SerializableTestData) : null, autoConvert: false, out result).Should().BeTrue(); @@ -1402,7 +1369,7 @@ public void RoundTrip_Object_SupportsTypedInterface(bool copy) Clipboard.TryGetData( format, - (TypeName name) => name.FullName == typeof(SerializableTestData).FullName ? typeof(SerializableTestData) : null, + name => name.FullName == typeof(SerializableTestData).FullName ? typeof(SerializableTestData) : null, out result).Should().BeTrue(); result.Should().BeEquivalentTo(data); @@ -1411,12 +1378,47 @@ public void RoundTrip_Object_SupportsTypedInterface(bool copy) { T received = Clipboard.GetDataObject().Should().BeOfType().Subject; received.Should().Be(testDataObject); - // When we are not flushing the data to the HGLOBAL, we are reading from our DataStore or the managed test data object. + // When we are not flushing the data to the HGLOBAL, we are reading from our managed test data object, + // which might not support the types interface. Action tryGetData = () => received.TryGetData(format, out SerializableTestData? result); - tryGetData.Should().Throw(); + tryGetData.Should().Throw() + .WithMessage(expectedWildcardPattern: ResourceStrings.TypedInterfaceNotImplemented); } } + [WinFormsTheory] + [BoolData] + public void RoundTrip_Object_SupportsTypedInterface(bool copy) + { + SerializableTestData data = new(); + string format = typeof(SerializableTestData).FullName!; + + // Opt-in into access to the binary formatted stream. + using BinaryFormatterInClipboardDragDropScope clipboardScope = new(enable: copy); + + // We need the BinaryFormatter to flush the data from the managed object to the HGLOBAL. + using BinaryFormatterScope scope = new(enable: copy); + + Clipboard.SetDataObject(data, copy); + + DataObject received = Clipboard.GetDataObject().Should().BeAssignableTo().Subject; + + received.TryGetData( + format, + name => name.FullName == typeof(SerializableTestData).FullName ? typeof(SerializableTestData) : null, + autoConvert: false, + out SerializableTestData? result).Should().BeTrue(); + + result.Should().BeEquivalentTo(data); + + Clipboard.TryGetData( + format, + name => name.FullName == typeof(SerializableTestData).FullName ? typeof(SerializableTestData) : null, + out result).Should().BeTrue(); + + result.Should().BeEquivalentTo(data); + } + [WinFormsFact] public unsafe void OleGetClipboard_ProxyBehavior() { diff --git a/src/test/unit/System.Windows.Forms/System/Windows/Forms/NativeToWinFormsAdapterTests.cs b/src/test/unit/System.Windows.Forms/System/Windows/Forms/NativeToWinFormsAdapterTests.cs index a346339452a..6cd91b62fa7 100644 --- a/src/test/unit/System.Windows.Forms/System/Windows/Forms/NativeToWinFormsAdapterTests.cs +++ b/src/test/unit/System.Windows.Forms/System/Windows/Forms/NativeToWinFormsAdapterTests.cs @@ -1,9 +1,8 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Drawing; using System.Reflection.Metadata; -using System.Text.RegularExpressions; using System.Windows.Forms.TestUtilities; using Com = Windows.Win32.System.Com; @@ -11,14 +10,6 @@ namespace System.Windows.Forms.Tests; public unsafe partial class NativeToWinFormsAdapterTests { - [GeneratedRegex(@"{[0-9]}")] - private static partial Regex PlaceholdersPattern(); - - private static string InvalidTypeFormatCombinationMessage => - PlaceholdersPattern().Replace(SR.ClipboardOrDragDrop_InvalidFormatTypeCombination, "*"); - private static string TypeRequiresResolverMessage => PlaceholdersPattern().Replace(SR.ClipboardOrDragDrop_InvalidType, "*"); - private static string UseTryGetDataWithResolver => PlaceholdersPattern().Replace(SR.ClipboardOrDragDrop_UseTypedAPI, "*"); - private const string FormatterDisabledMessage = "BinaryFormatter serialization and deserialization are disabled within this application. See https://aka.ms/binaryformatter for more information."; @@ -58,7 +49,7 @@ public void TryGetData_AsObject_Primitive_RequiresResolver(string format) DataObject dataObject = new(comDataObject.Value); Action tryGetData = () => dataObject.TryGetData(format, out object? value); - tryGetData.Should().Throw().WithMessage(expectedWildcardPattern: TypeRequiresResolverMessage); + tryGetData.Should().Throw().WithMessage(expectedWildcardPattern: ResourceStrings.TypeRequiresResolver); dataObject.TryGetData(format, Resolver, autoConvert: false, out object? value).Should().BeTrue(); value.Should().Be(1); @@ -79,7 +70,7 @@ public void TryGetData_AsObject_Primitive_InvalidTypeFormatCombination(string fo // Throw when validating arguments, as these formats allow exactly strings or bitmaps only. Action tryGetData = () => dataObject.TryGetData(format, out object? _); tryGetData.Should().Throw() - .WithMessage(expectedWildcardPattern: InvalidTypeFormatCombinationMessage); + .WithMessage(expectedWildcardPattern: ResourceStrings.InvalidTypeFormatCombinationMessage); } private static (DataObject dataObject, TestData value) SetDataObject(string format) @@ -101,7 +92,7 @@ public void TryGetData_AsObject_Custom_RequiresResolver(string format) (DataObject dataObject, TestData _) = SetDataObject(format); Action tryGetData = () => dataObject.TryGetData(format, out object? _); - tryGetData.Should().Throw().WithMessage(expectedWildcardPattern: TypeRequiresResolverMessage); + tryGetData.Should().Throw().WithMessage(expectedWildcardPattern: ResourceStrings.TypeRequiresResolver); } [WinFormsTheory] @@ -114,7 +105,7 @@ public void TryGetData_AsObject_Custom_FormatterEnabled_RequiresResolver(string using BinaryFormatterScope scope = new(enable: true); using BinaryFormatterInClipboardDragDropScope clipboardScope = new(enable: true); - tryGetData.Should().Throw().WithMessage(expectedWildcardPattern: TypeRequiresResolverMessage); + tryGetData.Should().Throw().WithMessage(expectedWildcardPattern: ResourceStrings.TypeRequiresResolver); } [WinFormsTheory] @@ -127,7 +118,7 @@ public void TryGetData_AsObject_Custom_InvalidTypeFormatCombination(string forma // Type-Format combination is validated before the we attempt to serialize data. tryGetData.Should().Throw() - .WithMessage(expectedWildcardPattern: InvalidTypeFormatCombinationMessage); + .WithMessage(expectedWildcardPattern: ResourceStrings.InvalidTypeFormatCombinationMessage); } [WinFormsTheory] @@ -180,7 +171,7 @@ public void TryGetData_AsInterface_ListOfPrimitives_RequiresResolver(string form // Theoretically we don't require a resolver here, but this is an exception. In the more common cases resolver // is required to instantiate non-concrete types. Action tryGetData = () => dataObject.TryGetData(format, out IList? _); - tryGetData.Should().Throw().WithMessage(expectedWildcardPattern: TypeRequiresResolverMessage); + tryGetData.Should().Throw().WithMessage(expectedWildcardPattern: ResourceStrings.TypeRequiresResolver); } [WinFormsTheory] @@ -196,7 +187,7 @@ public void TryGetData_AsInterface_ListOfPrimitives_InvalidTypeFormatCombination Action tryGetData = () => dataObject.TryGetData(format, out IList? _); tryGetData.Should().Throw() - .WithMessage(expectedWildcardPattern: InvalidTypeFormatCombinationMessage); + .WithMessage(expectedWildcardPattern: ResourceStrings.InvalidTypeFormatCombinationMessage); } [WinFormsTheory] @@ -227,7 +218,7 @@ public void TryGetData_AsConcreteType_ListOfPrimitives_InvalidTypeFormatCombinat Action tryGetData = () => dataObject.TryGetData(format, out List? _); tryGetData.Should().Throw() - .WithMessage(expectedWildcardPattern: InvalidTypeFormatCombinationMessage); + .WithMessage(expectedWildcardPattern: ResourceStrings.InvalidTypeFormatCombinationMessage); } [WinFormsTheory] @@ -277,7 +268,7 @@ public void TryGetData_AsConcreteType_Custom_InvalidTypeFormatCombination(string Action tryGetData = () => dataObject.TryGetData(format, out TestData? _); tryGetData.Should().Throw() - .WithMessage(expectedWildcardPattern: InvalidTypeFormatCombinationMessage); + .WithMessage(expectedWildcardPattern: ResourceStrings.InvalidTypeFormatCombinationMessage); } [WinFormsTheory] @@ -302,7 +293,7 @@ public void TryGetData_WithResolver_AsConcreteType_Custom_InvalidTypeFormatCombi Action tryGetData = () => dataObject.TryGetData(format, TestData.Resolver, autoConvert: true, out TestData? _); tryGetData.Should().Throw() - .WithMessage(expectedWildcardPattern: InvalidTypeFormatCombinationMessage); + .WithMessage(expectedWildcardPattern: ResourceStrings.InvalidTypeFormatCombinationMessage); } [WinFormsTheory] @@ -317,7 +308,7 @@ public void TryGetData_WithResolver_AsConcreteType_Custom_FormatterEnabled_Inval using BinaryFormatterInClipboardDragDropScope clipboardScope = new(enable: true); tryGetData.Should().Throw() - .WithMessage(expectedWildcardPattern: InvalidTypeFormatCombinationMessage); + .WithMessage(expectedWildcardPattern: ResourceStrings.InvalidTypeFormatCombinationMessage); } [WinFormsTheory] @@ -354,7 +345,7 @@ public void TryGetData_AsAbstract_Custom_InvalidTypeFormatCombination(string for Action tryGetData = () => dataObject.TryGetData(format, out AbstractBase? _); tryGetData.Should().Throw() - .WithMessage(expectedWildcardPattern: InvalidTypeFormatCombinationMessage); + .WithMessage(expectedWildcardPattern: ResourceStrings.InvalidTypeFormatCombinationMessage); } [WinFormsTheory] @@ -364,7 +355,7 @@ public void TryGetData_AsAbstract_Custom_RequiresResolver(string format) (DataObject dataObject, TestData _) = SetDataObject(format); Action tryGetData = () => dataObject.TryGetData(format, out AbstractBase? _); - tryGetData.Should().Throw().WithMessage(expectedWildcardPattern: TypeRequiresResolverMessage); + tryGetData.Should().Throw().WithMessage(expectedWildcardPattern: ResourceStrings.TypeRequiresResolver); dataObject.TryGetData(format, out NotSupportedException? ex).Should().BeTrue(); ex.Should().BeOfType().Which.Message.Should().Be(FormatterDisabledMessage); @@ -380,7 +371,7 @@ public void TryGetData_AsAbstract_Custom_FormatterEnabled_RequiresResolver(strin using BinaryFormatterScope scope = new(enable: true); using BinaryFormatterInClipboardDragDropScope clipboardScope = new(enable: true); - tryGetData.Should().Throw().WithMessage(expectedWildcardPattern: TypeRequiresResolverMessage); + tryGetData.Should().Throw().WithMessage(expectedWildcardPattern: ResourceStrings.TypeRequiresResolver); } [WinFormsTheory] @@ -420,7 +411,7 @@ public void TryGetData_WithResolver_AsAbstract_Custom_InvalidTypeFormatCombinati // Nothing is written to HGLOBAL in this test because format-type combination is invalid. Action tryGetData = () => dataObject.TryGetData(format, TestData.Resolver, autoConvert: true, out AbstractBase? _); tryGetData.Should().Throw() - .WithMessage(expectedWildcardPattern: InvalidTypeFormatCombinationMessage); + .WithMessage(expectedWildcardPattern: ResourceStrings.InvalidTypeFormatCombinationMessage); } [WinFormsTheory] diff --git a/src/test/util/System.Windows.Forms/Data/ManagedAndRuntimeDataObject.cs b/src/test/util/System.Windows.Forms/Data/ManagedAndRuntimeDataObject.cs index a235b4b5c0a..efc97476c26 100644 --- a/src/test/util/System.Windows.Forms/Data/ManagedAndRuntimeDataObject.cs +++ b/src/test/util/System.Windows.Forms/Data/ManagedAndRuntimeDataObject.cs @@ -7,7 +7,7 @@ namespace System.Windows.Forms.TestUtilities; -internal class ManagedAndRuntimeDataObject : ManagedDataObject, ComTypes.IDataObject +internal class ManagedAndRuntimeDataObject : UntypedDataObject, ComTypes.IDataObject { public int DAdvise(ref ComTypes.FORMATETC pFormatetc, ComTypes.ADVF advf, ComTypes.IAdviseSink adviseSink, out int connection) => throw new NotImplementedException(); public void DUnadvise(int connection) => throw new NotImplementedException(); diff --git a/src/test/util/System.Windows.Forms/Data/TypedDataObject.cs b/src/test/util/System.Windows.Forms/Data/TypedDataObject.cs index 313f149b05a..8eda290edc4 100644 --- a/src/test/util/System.Windows.Forms/Data/TypedDataObject.cs +++ b/src/test/util/System.Windows.Forms/Data/TypedDataObject.cs @@ -8,7 +8,7 @@ namespace System.Windows.Forms.TestUtilities; -internal class TypedDataObject : ManagedDataObject, ITypedDataObject +internal class TypedDataObject : UntypedDataObject, ITypedDataObject { public bool TryGetData<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>([MaybeNullWhen(false), NotNullWhen(true)] out T data) => throw new NotImplementedException(); diff --git a/src/test/util/System.Windows.Forms/Data/ManagedDataObject.cs b/src/test/util/System.Windows.Forms/Data/UntypedDataObject.cs similarity index 96% rename from src/test/util/System.Windows.Forms/Data/ManagedDataObject.cs rename to src/test/util/System.Windows.Forms/Data/UntypedDataObject.cs index e0bbc772e9f..9f301258d8b 100644 --- a/src/test/util/System.Windows.Forms/Data/ManagedDataObject.cs +++ b/src/test/util/System.Windows.Forms/Data/UntypedDataObject.cs @@ -5,7 +5,7 @@ namespace System.Windows.Forms.TestUtilities; -internal class ManagedDataObject : IDataObject +internal class UntypedDataObject : IDataObject { public static string s_format = nameof(SerializableTestData); protected SerializableTestData? _data;