|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Specialized;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Runtime.Serialization;
using Moq;
using Windows.Win32.System.Ole;
using Com = Windows.Win32.System.Com;
using IComDataObject = System.Runtime.InteropServices.ComTypes.IDataObject;
using Point = System.Drawing.Point;
namespace System.Windows.Forms.Tests;
// NB: doesn't require thread affinity
public partial class DataObjectTests
{
private static readonly string[] s_restrictedClipboardFormats =
[
DataFormats.CommaSeparatedValue,
DataFormats.Dib,
DataFormats.Dif,
DataFormats.PenData,
DataFormats.Riff,
DataFormats.Tiff,
DataFormats.WaveAudio,
DataFormats.SymbolicLink,
DataFormats.StringFormat,
DataFormats.Bitmap,
DataFormats.EnhancedMetafile,
DataFormats.FileDrop,
DataFormats.Html,
DataFormats.MetafilePict,
DataFormats.OemText,
DataFormats.Palette,
DataFormats.Rtf,
DataFormats.Text,
DataFormats.UnicodeText,
"FileName",
"FileNameW",
"System.Drawing.Bitmap",
" ", // the last 3 return null and don't process the payload.
string.Empty,
null
];
private static readonly string[] s_unboundedClipboardFormats =
[
DataFormats.Serializable,
"something custom"
];
[Fact]
public void DataObject_ContainsAudio_InvokeDefault_ReturnsFalse()
{
DataObject dataObject = new();
dataObject.ContainsAudio().Should().BeFalse();
}
[Theory]
[BoolData]
public void DataObject_ContainsAudio_InvokeMocked_CallsGetDataPresent(bool result)
{
Mock<DataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.ContainsAudio())
.CallBase();
mockDataObject
.Setup(o => o.GetDataPresent(DataFormats.WaveAudio, false))
.Returns(result)
.Verifiable();
mockDataObject.Object.ContainsAudio().Should().Be(result);
mockDataObject.Verify(o => o.GetDataPresent(DataFormats.WaveAudio, false), Times.Once());
}
[Fact]
public void DataObject_ContainsFileDropList_InvokeDefault_ReturnsFalse()
{
DataObject dataObject = new();
dataObject.ContainsFileDropList().Should().BeFalse();
}
[Theory]
[BoolData]
public void DataObject_ContainsFileDropList_InvokeMocked_CallsGetDataPresent(bool result)
{
Mock<DataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.ContainsFileDropList())
.CallBase();
mockDataObject
.Setup(o => o.GetDataPresent(DataFormats.FileDrop, true))
.Returns(result)
.Verifiable();
mockDataObject.Object.ContainsFileDropList().Should().Be(result);
mockDataObject.Verify(o => o.GetDataPresent(DataFormats.FileDrop, true), Times.Once());
}
[Fact]
public void DataObject_ContainsImage_InvokeDefault_ReturnsFalse()
{
DataObject dataObject = new();
dataObject.ContainsImage().Should().BeFalse();
}
[Theory]
[BoolData]
public void DataObject_ContainsImage_InvokeMocked_CallsGetDataPresent(bool result)
{
Mock<DataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.ContainsImage())
.CallBase();
mockDataObject
.Setup(o => o.GetDataPresent(DataFormats.Bitmap, true))
.Returns(result)
.Verifiable();
mockDataObject.Object.ContainsImage().Should().Be(result);
mockDataObject.Verify(o => o.GetDataPresent(DataFormats.Bitmap, true), Times.Once());
}
[Fact]
public void DataObject_ContainsText_InvokeDefault_ReturnsFalse()
{
DataObject dataObject = new();
dataObject.ContainsText().Should().BeFalse();
}
[Theory]
[BoolData]
public void DataObject_ContainsText_InvokeMocked_CallsGetDataPresent(bool result)
{
Mock<DataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.ContainsText())
.CallBase();
mockDataObject
.Setup(o => o.ContainsText(TextDataFormat.UnicodeText))
.Returns(result)
.Verifiable();
mockDataObject.Object.ContainsText().Should().Be(result);
mockDataObject.Verify(o => o.ContainsText(TextDataFormat.UnicodeText), Times.Once());
}
[Theory]
[EnumData<TextDataFormat>]
public void DataObject_ContainsText_InvokeTextDataFormat_ReturnsFalse(TextDataFormat format)
{
DataObject dataObject = new();
dataObject.ContainsText(format).Should().BeFalse();
}
public static TheoryData<TextDataFormat, string, bool> ContainsText_TextDataFormat_TheoryData()
{
TheoryData<TextDataFormat, string, bool> theoryData = [];
foreach (bool result in new bool[] { true, false })
{
theoryData.Add(TextDataFormat.Text, DataFormats.UnicodeText, result);
theoryData.Add(TextDataFormat.UnicodeText, DataFormats.UnicodeText, result);
theoryData.Add(TextDataFormat.Rtf, DataFormats.Rtf, result);
theoryData.Add(TextDataFormat.Html, DataFormats.Html, result);
theoryData.Add(TextDataFormat.CommaSeparatedValue, DataFormats.CommaSeparatedValue, result);
}
return theoryData;
}
[Theory]
[MemberData(nameof(ContainsText_TextDataFormat_TheoryData))]
public void DataObject_ContainsText_InvokeTextDataFormatMocked_CallsGetDataPresent(TextDataFormat format, string expectedFormat, bool result)
{
Mock<DataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.ContainsText(format))
.CallBase();
mockDataObject
.Setup(o => o.GetDataPresent(expectedFormat, false))
.Returns(result)
.Verifiable();
mockDataObject.Object.ContainsText(format).Should().Be(result);
mockDataObject.Verify(o => o.GetDataPresent(expectedFormat, false), Times.Once());
}
[Theory]
[InvalidEnumData<TextDataFormat>]
public void DataObject_ContainsText_InvokeInvalidTextDataFormat_ThrowsInvalidEnumArgumentException(TextDataFormat format)
{
DataObject dataObject = new();
((Action)(() => dataObject.ContainsText(format))).Should().Throw<InvalidEnumArgumentException>().WithParameterName("format");
}
[Fact]
public void DataObject_GetAudioStream_InvokeDefault_ReturnsNull()
{
DataObject dataObject = new();
dataObject.GetAudioStream().Should().BeNull();
}
public static TheoryData<object, Stream> GetAudioStream_TheoryData()
{
TheoryData<object, Stream> theoryData = new()
{
{ null, null },
{ new(), null }
};
MemoryStream stream = new();
theoryData.Add(stream, stream);
return theoryData;
}
[Theory]
[MemberData(nameof(GetAudioStream_TheoryData))]
public void DataObject_GetAudioStream_InvokeWithData_ReturnsExpected(object result, Stream expected)
{
DataObject dataObject = new();
dataObject.SetData(DataFormats.WaveAudio, result);
dataObject.GetAudioStream().Should().BeSameAs(expected);
}
[Theory]
[MemberData(nameof(GetAudioStream_TheoryData))]
public void DataObject_GetAudioStream_InvokeMocked_ReturnsExpected(object result, Stream expected)
{
Mock<DataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.GetAudioStream())
.CallBase();
mockDataObject
.Setup(o => o.GetData(DataFormats.WaveAudio, false))
.Returns(result)
.Verifiable();
mockDataObject.Object.GetAudioStream().Should().BeSameAs(expected);
mockDataObject.Verify(o => o.GetData(DataFormats.WaveAudio, false), Times.Once());
}
public static TheoryData<string> GetData_String_TheoryData() => s_restrictedClipboardFormats.ToTheoryData();
public static TheoryData<string> GetData_String_UnboundedFormat_TheoryData() => s_unboundedClipboardFormats.ToTheoryData();
[Theory]
[MemberData(nameof(GetData_String_TheoryData))]
[MemberData(nameof(GetData_String_UnboundedFormat_TheoryData))]
public void DataObject_GetData_InvokeStringDefault_ReturnsNull(string format)
{
DataObject dataObject = new();
dataObject.GetData(format).Should().BeNull();
}
public static TheoryData<string, object> GetData_InvokeStringMocked_TheoryData()
{
TheoryData<string, object> theoryData = [];
foreach (object result in new object[] { new(), null })
{
theoryData.Add("format", result);
theoryData.Add(" ", result);
theoryData.Add(string.Empty, result);
theoryData.Add(null, result);
}
return theoryData;
}
[Theory]
[MemberData(nameof(GetData_InvokeStringMocked_TheoryData))]
public void DataObject_GetData_InvokeStringMocked_CallsGetData(string format, object result)
{
Mock<DataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.GetData(format))
.CallBase();
mockDataObject
.Setup(o => o.GetData(format, true))
.Returns(result)
.Verifiable();
mockDataObject.Object.GetData(format).Should().BeSameAs(result);
mockDataObject.Verify(o => o.GetData(format, true), Times.Once());
}
[Theory]
[MemberData(nameof(GetData_InvokeStringMocked_TheoryData))]
public void DataObject_GetData_InvokeStringIDataObject_ReturnsExpected(string format, object result)
{
Mock<IDataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.GetData(format, true))
.Returns(result)
.Verifiable();
DataObject dataObject = new(mockDataObject.Object);
dataObject.GetData(format).Should().BeSameAs(result);
mockDataObject.Verify(o => o.GetData(format, true), Times.Once());
}
public static TheoryData<string, bool, object> GetData_StringBoolIDataObject_TheoryData()
{
TheoryData<string, bool, object> theoryData = [];
foreach (bool autoConvert in new bool[] { true, false })
{
foreach (object result in new object[] { new(), null })
{
theoryData.Add("format", autoConvert, result);
theoryData.Add(" ", autoConvert, result);
theoryData.Add(string.Empty, autoConvert, result);
theoryData.Add(null, autoConvert, result);
}
}
return theoryData;
}
[Theory]
[MemberData(nameof(GetData_StringBoolIDataObject_TheoryData))]
public void DataObject_GetData_InvokeStringBoolIDataObject_ReturnsExpected(string format, bool autoConvert, object result)
{
Mock<IDataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.GetData(format, autoConvert))
.Returns(result)
.Verifiable();
DataObject dataObject = new(mockDataObject.Object);
dataObject.GetData(format, autoConvert).Should().BeSameAs(result);
mockDataObject.Verify(o => o.GetData(format, autoConvert), Times.Once());
}
[Theory]
[InlineData(typeof(int))]
[InlineData(null)]
public void DataObject_GetData_InvokeTypeDefault_ReturnsNull(Type format)
{
DataObject dataObject = new();
dataObject.GetData(format).Should().BeNull();
}
public static TheoryData<Type, object, int, object> GetData_InvokeTypeMocked_TheoryData()
{
TheoryData<Type, object, int, object> theoryData = new();
foreach (object result in new object[] { new(), null })
{
theoryData.Add(typeof(int), result, 1, result);
theoryData.Add(null, result, 0, null);
}
return theoryData;
}
[Theory]
[MemberData(nameof(GetData_InvokeTypeMocked_TheoryData))]
public void DataObject_GetData_InvokeTypeMocked_CallsGetData(Type format, object result, int expectedCallCount, object expectedResult)
{
Mock<DataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.GetData(It.IsAny<Type>()))
.CallBase();
string formatName = format?.FullName ?? "(null)";
mockDataObject
.Setup(o => o.GetData(formatName))
.Returns(result)
.Verifiable();
mockDataObject.Object.GetData(format).Should().BeSameAs(expectedResult);
mockDataObject.Verify(o => o.GetData(formatName), Times.Exactly(expectedCallCount));
}
[Theory]
[MemberData(nameof(GetData_String_TheoryData))]
[MemberData(nameof(GetData_String_UnboundedFormat_TheoryData))]
public void DataObject_GetDataPresent_InvokeStringDefault_ReturnsFalse(string format)
{
DataObject dataObject = new();
dataObject.GetDataPresent(format).Should().BeFalse();
}
public static TheoryData<string, bool> GetDataPresent_StringMocked_TheoryData()
{
TheoryData<string, bool> theoryData = [];
foreach (bool result in new bool[] { true, false })
{
theoryData.Add("format", result);
theoryData.Add(" ", result);
theoryData.Add(string.Empty, result);
theoryData.Add(null, result);
}
return theoryData;
}
[Theory]
[MemberData(nameof(GetDataPresent_StringMocked_TheoryData))]
public void DataObject_GetDataPresent_InvokeStringMocked_CallsGetDataPresent(string format, bool result)
{
Mock<DataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.GetDataPresent(format))
.CallBase();
mockDataObject
.Setup(o => o.GetDataPresent(format, true))
.Returns(result)
.Verifiable();
mockDataObject.Object.GetDataPresent(format).Should().Be(result);
mockDataObject.Verify(o => o.GetDataPresent(format, true), Times.Once());
}
[Theory]
[MemberData(nameof(GetDataPresent_StringMocked_TheoryData))]
public void DataObject_GetDataPresent_InvokeStringIDataObject_ReturnsExpected(string format, bool result)
{
Mock<IDataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.GetDataPresent(format, true))
.Returns(result)
.Verifiable();
DataObject dataObject = new(mockDataObject.Object);
dataObject.GetDataPresent(format).Should().Be(result);
mockDataObject.Verify(o => o.GetDataPresent(format, true), Times.Once());
}
public static TheoryData<string, bool, bool> GetDataPresent_StringBoolIDataObject_TheoryData()
{
TheoryData<string, bool, bool> theoryData = [];
foreach (bool autoConvert in new bool[] { true, false })
{
foreach (bool result in new bool[] { true, false })
{
theoryData.Add("format", autoConvert, result);
theoryData.Add(" ", autoConvert, result);
theoryData.Add(string.Empty, autoConvert, result);
theoryData.Add(null, autoConvert, result);
}
}
return theoryData;
}
[Theory]
[MemberData(nameof(GetDataPresent_StringBoolIDataObject_TheoryData))]
public void DataObject_GetDataPresent_InvokeStringBoolIDataObject_ReturnsExpected(string format, bool autoConvert, bool result)
{
Mock<IDataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.GetDataPresent(format, autoConvert))
.Returns(result)
.Verifiable();
DataObject dataObject = new(mockDataObject.Object);
dataObject.GetDataPresent(format, autoConvert).Should().Be(result);
mockDataObject.Verify(o => o.GetDataPresent(format, autoConvert), Times.Once());
}
[Theory]
[InlineData(typeof(int))]
[InlineData(null)]
public void DataObject_GetDataPresentPresent_InvokeTypeDefault_ReturnsFalse(Type format)
{
DataObject dataObject = new();
dataObject.GetDataPresent(format).Should().BeFalse();
}
public static TheoryData<Type, bool, int, bool, string> GetDataPresent_InvokeTypeMocked_TheoryData()
{
TheoryData<Type, bool, int, bool, string> theoryData = [];
foreach (bool result in new bool[] { true, false })
{
theoryData.Add(typeof(int), result, 1, result, typeof(int).FullName);
theoryData.Add(null, result, 0, false, "(null)");
}
return theoryData;
}
[Theory]
[MemberData(nameof(GetDataPresent_InvokeTypeMocked_TheoryData))]
public void DataObject_GetDataPresent_InvokeTypeMocked_CallsGetDataPresent(Type format, bool result, int expectedCallCount, bool expectedResult, string expectedFormatName)
{
Mock<DataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.GetDataPresent(It.IsAny<Type>()))
.CallBase();
mockDataObject
.Setup(o => o.GetDataPresent(expectedFormatName))
.Returns(result)
.Verifiable();
mockDataObject.Object.GetDataPresent(format).Should().Be(expectedResult);
mockDataObject.Verify(o => o.GetDataPresent(expectedFormatName), Times.Exactly(expectedCallCount));
}
[Fact]
public void DataObject_GetFileDropList_InvokeDefault_ReturnsEmpty()
{
DataObject dataObject = new();
dataObject.GetFileDropList().Cast<string>().Should().BeEmpty();
}
public static TheoryData<object, string[]> GetFileDropList_TheoryData()
{
TheoryData<object, string[]> theoryData = [];
theoryData.Add(null, Array.Empty<string>());
theoryData.Add(new(), Array.Empty<string>());
string[] list = ["a", " ", string.Empty, null];
theoryData.Add(list, list);
return theoryData;
}
[Theory]
[MemberData(nameof(GetFileDropList_TheoryData))]
public void DataObject_GetFileDropList_InvokeWithData_ReturnsExpected(object result, string[] expected)
{
DataObject dataObject = new();
dataObject.SetData(DataFormats.FileDrop, result);
dataObject.GetFileDropList().Cast<string>().Should().BeEquivalentTo(expected);
}
[Theory]
[MemberData(nameof(GetFileDropList_TheoryData))]
public void DataObject_GetFileDropList_InvokeMocked_ReturnsExpected(object result, string[] expected)
{
Mock<DataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.GetFileDropList())
.CallBase();
mockDataObject
.Setup(o => o.GetData(DataFormats.FileDrop, true))
.Returns(result)
.Verifiable();
mockDataObject.Object.GetFileDropList().Cast<string>().Should().BeEquivalentTo(expected);
mockDataObject.Verify(o => o.GetData(DataFormats.FileDrop, true), Times.Once());
}
[Fact]
public void DataObject_GetFormats_InvokeDefault_ReturnsEmpty()
{
DataObject dataObject = new();
dataObject.GetFormats().Cast<string>().Should().BeEmpty();
}
[WinFormsFact]
public void DataObject_GetFormats_InvokeWithValues_ReturnsExpected()
{
DataObject dataObject = new();
dataObject.SetData("format1", "data1");
dataObject.GetFormats().Should().Equal(["format1"]);
dataObject.SetText("data2");
dataObject.GetFormats().Should().Equal(["format1", "UnicodeText"]);
using Bitmap bitmap1 = new(10, 10);
dataObject.SetData("format2", bitmap1);
dataObject.GetFormats().OrderBy(s => s).Should().Equal(["format1", "format2", "UnicodeText"]);
using Bitmap bitmap2 = new(10, 10);
dataObject.SetData(bitmap2);
dataObject.GetFormats().OrderBy(s => s).Should().Equal(["Bitmap", "format1", "format2", "System.Drawing.Bitmap", "UnicodeText", "WindowsForms10PersistentObject"]);
}
public static TheoryData<string[]> GetFormats_Mocked_TheoryData() => new()
{
{ null },
{ Array.Empty<string>() },
{ new string[] { "a", " ", string.Empty, null } }
};
[Theory]
[MemberData(nameof(GetFormats_Mocked_TheoryData))]
public void DataObject_GetFormats_InvokeMocked_ReturnsExpected(string[] result)
{
Mock<DataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.GetFormats())
.CallBase();
mockDataObject
.Setup(o => o.GetFormats(true))
.Returns(result)
.Verifiable();
mockDataObject.Object.GetFormats().Should().BeSameAs(result);
mockDataObject.Verify(o => o.GetFormats(true), Times.Once());
}
public static TheoryData<string[]> GetFormats_IDataObject_TheoryData() => new()
{
{ null },
{ Array.Empty<string>() },
{ new string[] { "a", string.Empty, null } },
{ new string[] { "a", " ", string.Empty, null } }
};
[Theory]
[MemberData(nameof(GetFormats_IDataObject_TheoryData))]
public void DataObject_GetFormats_InvokeIDataObject_ReturnsExpected(string[] result)
{
Mock<IDataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.GetFormats(true))
.Returns(result)
.Verifiable();
DataObject dataObject = new(mockDataObject.Object);
dataObject.GetFormats().Should().BeSameAs(result);
mockDataObject.Verify(o => o.GetFormats(true), Times.Once());
}
[Theory]
[BoolData]
public void DataObject_GetFormats_InvokeBoolDefault_ReturnsEmpty(bool autoConvert)
{
DataObject dataObject = new();
dataObject.GetFormats(autoConvert).Should().BeEmpty();
}
[WinFormsFact]
public void DataObject_GetFormats_InvokeBoolWithValues_ReturnsExpected()
{
DataObject dataObject = new();
dataObject.SetData("format1", "data1");
dataObject.GetFormats(autoConvert: true).Should().Equal(["format1"]);
dataObject.GetFormats(autoConvert: false).Should().Equal(["format1"]);
dataObject.SetText("data2");
dataObject.GetFormats(autoConvert: true).Should().Equal(["format1", "UnicodeText"]);
dataObject.GetFormats(autoConvert: false).Should().Equal(["format1", "UnicodeText"]);
using Bitmap bitmap1 = new(10, 10);
dataObject.SetData("format2", bitmap1);
dataObject.GetFormats(autoConvert: true).OrderBy(s => s).Should().Equal(["format1", "format2", "UnicodeText"]);
dataObject.GetFormats(autoConvert: false).OrderBy(s => s).Should().Equal(["format1", "format2", "UnicodeText"]);
using Bitmap bitmap2 = new(10, 10);
dataObject.SetData(bitmap2);
dataObject.GetFormats(autoConvert: true).OrderBy(s => s).Should().Equal(["Bitmap", "format1", "format2", "System.Drawing.Bitmap", "UnicodeText", "WindowsForms10PersistentObject"]);
dataObject.GetFormats(autoConvert: false).OrderBy(s => s).Should().Equal(["format1", "format2", "System.Drawing.Bitmap", "UnicodeText", "WindowsForms10PersistentObject"]);
}
public static TheoryData<bool, string[]> GetFormats_BoolIDataObject_TheoryData() => new()
{
{ true, null },
{ true, Array.Empty<string>() },
{ true, new string[] { "a", " ", string.Empty, null } },
{ false, null },
{ false, Array.Empty<string>() },
{ false, new string[] { "a", " ", string.Empty, null } }
};
[Theory]
[MemberData(nameof(GetFormats_BoolIDataObject_TheoryData))]
public void DataObject_GetFormats_InvokeBoolIDataObject_ReturnsExpected(bool autoConvert, string[] result)
{
Mock<IDataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.GetFormats(autoConvert))
.Returns(result)
.Verifiable();
DataObject dataObject = new(mockDataObject.Object);
dataObject.GetFormats(autoConvert).Should().BeSameAs(result);
mockDataObject.Verify(o => o.GetFormats(autoConvert), Times.Once());
}
[Fact]
public void DataObject_GetImage_InvokeDefault_ReturnsNull()
{
DataObject dataObject = new();
dataObject.GetImage().Should().BeNull();
}
public static TheoryData<object, Image> GetImage_TheoryData()
{
TheoryData<object, Image> theoryData = [];
theoryData.Add(null, null);
theoryData.Add(new(), null);
// This bitmap is not backed up by the GDI handle, we don't have to dispose it.
Bitmap image = new(10, 10);
theoryData.Add(image, image);
return theoryData;
}
[Theory]
[MemberData(nameof(GetImage_TheoryData))]
public void DataObject_GetImage_InvokeWithData_ReturnsExpected(object result, Image expected)
{
DataObject dataObject = new();
dataObject.SetData(DataFormats.Bitmap, result);
dataObject.GetImage().Should().Be(expected);
}
[Theory]
[MemberData(nameof(GetImage_TheoryData))]
public void DataObject_GetImage_InvokeMocked_ReturnsExpected(object result, Image expected)
{
Mock<DataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.GetImage())
.CallBase();
mockDataObject
.Setup(o => o.GetData(DataFormats.Bitmap, true))
.Returns(result)
.Verifiable();
mockDataObject.Object.GetImage().Should().BeSameAs(expected);
mockDataObject.Verify(o => o.GetData(DataFormats.Bitmap, true), Times.Once());
}
[Fact]
public void DataObject_GetText_InvokeDefault_ReturnsEmpty()
{
DataObject dataObject = new();
dataObject.GetText().Should().BeEmpty();
}
public static TheoryData<string, string> GetText_TheoryData() => new()
{
{ null, string.Empty},
{ string.Empty, string.Empty},
{ " ", " "},
{ "a", "a"}
};
[Theory]
[MemberData(nameof(GetText_TheoryData))]
public void DataObject_GetText_InvokeWithData_ReturnsExpected(string result, string expected)
{
DataObject dataObject = new();
dataObject.SetData(DataFormats.UnicodeText, result);
dataObject.GetText().Should().Be(expected);
}
[Theory]
[StringWithNullData]
public void DataObject_GetText_InvokeMocked_ReturnsExpected(string result)
{
Mock<DataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.GetText())
.CallBase();
mockDataObject
.Setup(o => o.GetText(TextDataFormat.UnicodeText))
.Returns(result)
.Verifiable();
mockDataObject.Object.GetText().Should().BeSameAs(result);
mockDataObject.Verify(o => o.GetText(TextDataFormat.UnicodeText), Times.Once());
}
[Theory]
[EnumData<TextDataFormat>]
public void DataObject_GetText_InvokeTextDataFormatDefault_ReturnsEmpty(TextDataFormat format)
{
DataObject dataObject = new();
dataObject.GetText(format).Should().BeEmpty();
}
public static TheoryData<TextDataFormat, string, object, string> GetText_TextDataFormat_TheoryData() => new()
{
{ TextDataFormat.Text, DataFormats.UnicodeText, null, string.Empty },
{ TextDataFormat.Text, DataFormats.UnicodeText, new(), string.Empty },
{ TextDataFormat.Text, DataFormats.UnicodeText, string.Empty, string.Empty },
{ TextDataFormat.Text, DataFormats.UnicodeText, " ", " " },
{ TextDataFormat.Text, DataFormats.UnicodeText, "a", "a" },
//
{ TextDataFormat.UnicodeText, DataFormats.UnicodeText, null, string.Empty },
{ TextDataFormat.UnicodeText, DataFormats.UnicodeText, new(), string.Empty },
{ TextDataFormat.UnicodeText, DataFormats.UnicodeText, string.Empty, string.Empty },
{ TextDataFormat.UnicodeText, DataFormats.UnicodeText, " ", " " },
{ TextDataFormat.UnicodeText, DataFormats.UnicodeText, "a", "a" },
//
{ TextDataFormat.Rtf, DataFormats.Rtf, null, string.Empty },
{ TextDataFormat.Rtf, DataFormats.Rtf, new(), string.Empty },
{ TextDataFormat.Rtf, DataFormats.Rtf, string.Empty, string.Empty },
{ TextDataFormat.Rtf, DataFormats.Rtf, " ", " " },
{ TextDataFormat.Rtf, DataFormats.Rtf, "a", "a" },
//
{ TextDataFormat.Html, DataFormats.Html, null, string.Empty },
{ TextDataFormat.Html, DataFormats.Html, new(), string.Empty },
{ TextDataFormat.Html, DataFormats.Html, string.Empty, string.Empty },
{ TextDataFormat.Html, DataFormats.Html, " ", " " },
{ TextDataFormat.Html, DataFormats.Html, "a", "a" },
//
{ TextDataFormat.CommaSeparatedValue, DataFormats.CommaSeparatedValue, null, string.Empty },
{ TextDataFormat.CommaSeparatedValue, DataFormats.CommaSeparatedValue, new(), string.Empty },
{ TextDataFormat.CommaSeparatedValue, DataFormats.CommaSeparatedValue, string.Empty, string.Empty },
{ TextDataFormat.CommaSeparatedValue, DataFormats.CommaSeparatedValue, " ", " " },
{ TextDataFormat.CommaSeparatedValue, DataFormats.CommaSeparatedValue, "a", "a" },
};
[Theory]
[MemberData(nameof(GetText_TextDataFormat_TheoryData))]
public void DataObject_GetText_InvokeTextDataFormatWithData_ReturnsExpected(TextDataFormat format, string expectedFormat, object result, string expected)
{
DataObject dataObject = new();
dataObject.SetData(expectedFormat, result);
dataObject.GetText(format).Should().BeSameAs(expected);
}
[Theory]
[MemberData(nameof(GetText_TextDataFormat_TheoryData))]
public void DataObject_GetText_InvokeTextDataFormatMocked_ReturnsExpected(TextDataFormat format, string expectedFormat, object result, string expected)
{
Mock<DataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.GetText(format))
.CallBase();
mockDataObject
.Setup(o => o.GetData(expectedFormat, false))
.Returns(result)
.Verifiable();
mockDataObject.Object.GetText(format).Should().BeSameAs(expected);
mockDataObject.Verify(o => o.GetData(expectedFormat, false), Times.Once());
}
[Theory]
[InvalidEnumData<TextDataFormat>]
public void DataObject_GetText_InvokeInvalidFormat_ThrowsInvalidEnumArgumentException(TextDataFormat format)
{
DataObject dataObject = new();
Action action = () => dataObject.GetText(format);
action.Should().Throw<InvalidEnumArgumentException>().WithParameterName("format");
}
public static TheoryData<byte[]> SetAudio_ByteArray_TheoryData() => new()
{
{ Array.Empty<byte>() },
{ new byte[] { 1, 2, 3 } }
};
[Theory]
[MemberData(nameof(SetAudio_ByteArray_TheoryData))]
public void DataObject_SetAudio_InvokeByteArray_GetReturnsExpected(byte[] audioBytes)
{
DataObject dataObject = new();
dataObject.SetAudio(audioBytes);
dataObject.GetAudioStream().Should().BeOfType<MemoryStream>().Subject.ToArray().Should().BeEquivalentTo(audioBytes);
dataObject.GetData(DataFormats.WaveAudio, autoConvert: true).Should().BeOfType<MemoryStream>().Subject.ToArray().Should().Equal(audioBytes);
dataObject.GetData(DataFormats.WaveAudio, autoConvert: false).Should().BeOfType<MemoryStream>().Subject.ToArray().Should().Equal(audioBytes);
dataObject.ContainsAudio().Should().BeTrue();
dataObject.GetDataPresent(DataFormats.WaveAudio, autoConvert: true).Should().BeTrue();
dataObject.GetDataPresent(DataFormats.WaveAudio, autoConvert: false).Should().BeTrue();
}
[Theory]
[MemberData(nameof(SetAudio_ByteArray_TheoryData))]
public void DataObject_SetAudio_InvokeByteArrayMocked_CallsSetAudio(byte[] audioBytes)
{
Mock<DataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.SetAudio(audioBytes))
.CallBase();
mockDataObject
.Setup(o => o.SetAudio(It.IsAny<MemoryStream>()))
.Verifiable();
mockDataObject.Object.SetAudio(audioBytes);
mockDataObject.Verify(o => o.SetAudio(It.IsAny<MemoryStream>()), Times.Once());
}
[Theory]
[MemberData(nameof(SetAudio_ByteArray_TheoryData))]
public void DataObject_SetAudio_InvokeByteArrayIDataObject_CallsSetData(byte[] audioBytes)
{
Mock<IDataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.SetData(DataFormats.WaveAudio, false, It.IsAny<MemoryStream>()))
.Verifiable();
DataObject dataObject = new(mockDataObject.Object);
dataObject.SetAudio(audioBytes);
mockDataObject.Verify(o => o.SetData(DataFormats.WaveAudio, false, It.IsAny<MemoryStream>()), Times.Once());
}
[Fact]
public void DataObject_SetAudio_NullAudioBytes_ThrowsArgumentNullException()
{
DataObject dataObject = new();
Action action = () => dataObject.SetAudio((byte[])null);
action.Should().Throw<ArgumentNullException>().WithParameterName("audioBytes");
}
public static TheoryData<MemoryStream> SetAudio_Stream_TheoryData() => new()
{
{ new MemoryStream(Array.Empty<byte>()) },
{ new MemoryStream([1, 2, 3]) }
};
[Theory]
[MemberData(nameof(SetAudio_Stream_TheoryData))]
public void DataObject_SetAudio_InvokeStream_GetReturnsExpected(MemoryStream audioStream)
{
DataObject dataObject = new();
dataObject.SetAudio(audioStream);
dataObject.GetAudioStream().Should().BeSameAs(audioStream);
dataObject.GetData(DataFormats.WaveAudio, autoConvert: true).Should().BeSameAs(audioStream);
dataObject.GetData(DataFormats.WaveAudio, autoConvert: false).Should().BeSameAs(audioStream);
dataObject.ContainsAudio().Should().BeTrue();
dataObject.GetDataPresent(DataFormats.WaveAudio, autoConvert: true).Should().BeTrue();
dataObject.GetDataPresent(DataFormats.WaveAudio, autoConvert: false).Should().BeTrue();
}
[Theory]
[MemberData(nameof(SetAudio_Stream_TheoryData))]
public void DataObject_SetAudio_InvokeStreamMocked_CallsSetAudio(MemoryStream audioStream)
{
Mock<DataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.SetAudio(audioStream))
.CallBase();
mockDataObject
.Setup(o => o.SetData(DataFormats.WaveAudio, false, audioStream))
.Verifiable();
mockDataObject.Object.SetAudio(audioStream);
mockDataObject.Verify(o => o.SetData(DataFormats.WaveAudio, false, audioStream), Times.Once());
}
[Theory]
[MemberData(nameof(SetAudio_Stream_TheoryData))]
public void DataObject_SetAudio_InvokeStreamIDataObject_CallsSetData(MemoryStream audioStream)
{
Mock<IDataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.SetData(DataFormats.WaveAudio, false, audioStream))
.Verifiable();
DataObject dataObject = new(mockDataObject.Object);
dataObject.SetAudio(audioStream);
mockDataObject.Verify(o => o.SetData(DataFormats.WaveAudio, false, audioStream), Times.Once());
}
[Fact]
public void DataObject_SetAudio_NullAudioStream_ThrowsArgumentNullException()
{
DataObject dataObject = new();
Action action = () => dataObject.SetAudio((Stream)null);
action.Should().Throw<ArgumentNullException>().WithParameterName("audioStream");
}
public static TheoryData<object, string> SetData_Object_TheoryData() => new()
{
{ new(), typeof(object).FullName },
{ new Bitmap(10, 10), typeof(Bitmap).FullName },
{ new Mock<ISerializable>(MockBehavior.Strict).Object, DataFormats.Serializable }
};
[Theory]
[MemberData(nameof(SetData_Object_TheoryData))]
public void DataObject_SetData_Object_GetDataReturnsExpected(object data, string format)
{
DataObject dataObject = new();
dataObject.SetData(data);
dataObject.GetData(format, autoConvert: false).Should().BeSameAs(data);
dataObject.GetData(format, autoConvert: true).Should().BeSameAs(data);
dataObject.GetDataPresent(format, autoConvert: false).Should().BeTrue();
dataObject.GetDataPresent(format, autoConvert: true).Should().BeTrue();
}
[Fact]
public void DataObject_SetData_MultipleNonSerializable_GetDataReturnsExpected()
{
object data1 = new();
object data2 = new();
DataObject dataObject = new();
dataObject.SetData(data1);
dataObject.SetData(data2);
string format = data1.GetType().FullName;
dataObject.GetData(format, autoConvert: false).Should().Be(data2);
dataObject.GetData(format, autoConvert: true).Should().Be(data2);
dataObject.GetDataPresent(format, autoConvert: false).Should().BeTrue();
dataObject.GetDataPresent(format, autoConvert: true).Should().BeTrue();
}
[Fact]
public void DataObject_SetData_MultipleSerializable_GetDataReturnsExpected()
{
var data1 = new Mock<ISerializable>(MockBehavior.Strict).Object;
var data2 = new Mock<ISerializable>(MockBehavior.Strict).Object;
DataObject dataObject = new();
dataObject.SetData(data1);
dataObject.SetData(data2);
dataObject.GetData(DataFormats.Serializable, autoConvert: false).Should().Be(data1);
dataObject.GetData(DataFormats.Serializable, autoConvert: true).Should().Be(data1);
dataObject.GetData(data2.GetType().FullName, autoConvert: false).Should().Be(data2);
dataObject.GetData(data2.GetType().FullName, autoConvert: true).Should().Be(data2);
dataObject.GetDataPresent(DataFormats.Serializable, autoConvert: false).Should().BeTrue();
dataObject.GetDataPresent(DataFormats.Serializable, autoConvert: true).Should().BeTrue();
dataObject.GetDataPresent(data2.GetType().FullName, autoConvert: false).Should().BeTrue();
dataObject.GetDataPresent(data2.GetType().FullName, autoConvert: true).Should().BeTrue();
}
public static TheoryData<object> SetData_ObjectIDataObject_TheoryData() => new()
{
{ new() },
{ null }
};
[Theory]
[MemberData(nameof(SetData_ObjectIDataObject_TheoryData))]
public void DataObject_SetData_InvokeObjectIDataObject_CallsSetData(object data)
{
Mock<IDataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.SetData(data))
.Verifiable();
DataObject dataObject = new(mockDataObject.Object);
dataObject.SetData(data);
mockDataObject.Verify(o => o.SetData(data), Times.Once());
}
[Fact]
public void DataObject_SetData_NullData_ThrowsArgumentNullException()
{
DataObject dataObject = new();
((Action)(() => dataObject.SetData(null))).Should().Throw<ArgumentNullException>().WithParameterName("data");
}
[Theory]
[InlineData(DataFormats.SerializableConstant, null)]
[InlineData(DataFormats.SerializableConstant, "input")]
[InlineData("something custom", null)]
[InlineData("something custom", "input")]
private void DataObject_SetData_InvokeStringObject_Unbounded_GetReturnsExpected(string format, string input)
{
DataObject dataObject = new();
dataObject.SetData(format, input);
dataObject.GetDataPresent(format).Should().BeTrue();
dataObject.GetDataPresent(format, autoConvert: false).Should().BeTrue();
dataObject.GetDataPresent(format, autoConvert: true).Should().BeTrue();
dataObject.GetData(format).Should().Be(input);
dataObject.GetData(format, autoConvert: false).Should().Be(input);
dataObject.GetData(format, autoConvert: true).Should().Be(input);
dataObject.ContainsAudio().Should().BeFalse();
dataObject.ContainsFileDropList().Should().BeFalse();
dataObject.ContainsImage().Should().BeFalse();
dataObject.ContainsText().Should().BeFalse();
dataObject.ContainsText(TextDataFormat.Text).Should().BeFalse();
dataObject.ContainsText(TextDataFormat.UnicodeText).Should().BeFalse();
dataObject.ContainsText(TextDataFormat.Rtf).Should().BeFalse();
dataObject.ContainsText(TextDataFormat.Html).Should().BeFalse();
dataObject.ContainsText(TextDataFormat.CommaSeparatedValue).Should().BeFalse();
}
[Fact]
public void DataObject_SetData_InvokeStringObjectDibBitmapAutoConvert_GetDataReturnsExpected()
{
using Bitmap image = new(10, 10);
DataObject dataObject = new();
dataObject.SetData(DataFormats.Dib, autoConvert: true, image);
dataObject.GetImage().Should().BeSameAs(image);
dataObject.GetData(DataFormats.Bitmap, autoConvert: true).Should().BeSameAs(image);
dataObject.GetData(DataFormats.Bitmap, autoConvert: false).Should().BeSameAs(image);
dataObject.GetData(typeof(Bitmap).FullName, autoConvert: true).Should().BeSameAs(image);
dataObject.GetData(typeof(Bitmap).FullName, autoConvert: false).Should().BeNull();
dataObject.GetData(DataFormats.Dib, autoConvert: true).Should().BeNull();
dataObject.GetData(DataFormats.Dib, autoConvert: false).Should().BeNull();
dataObject.ContainsImage().Should().BeTrue();
dataObject.GetDataPresent(DataFormats.Bitmap, autoConvert: true).Should().BeTrue();
dataObject.GetDataPresent(DataFormats.Bitmap, autoConvert: false).Should().BeTrue();
dataObject.GetDataPresent(typeof(Bitmap).FullName, autoConvert: true).Should().BeTrue();
dataObject.GetDataPresent(typeof(Bitmap).FullName, autoConvert: false).Should().BeFalse();
dataObject.GetDataPresent(DataFormats.Dib, autoConvert: true).Should().BeFalse();
dataObject.GetDataPresent(DataFormats.Dib, autoConvert: false).Should().BeFalse();
}
public static TheoryData<string, object> SetData_StringObjectIDataObject_TheoryData()
{
TheoryData<string, object> theoryData = [];
foreach (string format in new string[] { "format", " ", string.Empty, null })
{
theoryData.Add(format, null);
theoryData.Add(format, new());
}
return theoryData;
}
[Theory]
[MemberData(nameof(SetData_StringObjectIDataObject_TheoryData))]
public void DataObject_SetData_InvokeStringObjectIDataObject_CallsSetData(string format, object data)
{
Mock<IDataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.SetData(format, data))
.Verifiable();
DataObject dataObject = new(mockDataObject.Object);
dataObject.SetData(format, data);
mockDataObject.Verify(o => o.SetData(format, data), Times.Once());
}
[Theory]
[InlineData("something custom", false, "input")]
[InlineData("something custom", false, null)]
[InlineData("something custom", true, "input")]
[InlineData("something custom", true, null)]
[InlineData(DataFormats.SerializableConstant, false, "input")]
[InlineData(DataFormats.SerializableConstant, false, null)]
[InlineData(DataFormats.SerializableConstant, true, "input")]
[InlineData(DataFormats.SerializableConstant, true, null)]
private void DataObject_SetData_InvokeStringBoolObject_Unbounded_GetReturnsExpected(string format, bool autoConvert, string input)
{
DataObject dataObject = new();
dataObject.SetData(format, autoConvert, input);
dataObject.GetData(format, autoConvert: false).Should().Be(input);
dataObject.GetData(format, autoConvert: true).Should().Be(input);
dataObject.GetDataPresent(format, autoConvert: true).Should().BeTrue();
dataObject.GetDataPresent(format, autoConvert: false).Should().BeTrue();
dataObject.ContainsAudio().Should().Be(format == DataFormats.WaveAudio);
dataObject.ContainsFileDropList().Should().BeFalse();
dataObject.ContainsImage().Should().BeFalse();
dataObject.ContainsText().Should().BeFalse();
dataObject.ContainsText(TextDataFormat.Text).Should().BeFalse();
dataObject.ContainsText(TextDataFormat.UnicodeText).Should().BeFalse();
dataObject.ContainsText(TextDataFormat.Rtf).Should().BeFalse();
dataObject.ContainsText(TextDataFormat.Html).Should().BeFalse();
dataObject.ContainsText(TextDataFormat.CommaSeparatedValue).Should().BeFalse();
}
[Fact]
public void DataObject_SetData_InvokeStringBoolObjectDibBitmapAutoConvert_GetDataReturnsExpected()
{
using Bitmap image = new(10, 10);
DataObject dataObject = new();
dataObject.SetData(DataFormats.Dib, autoConvert: true, image);
dataObject.GetImage().Should().BeSameAs(image);
dataObject.GetData(DataFormats.Bitmap, autoConvert: true).Should().BeSameAs(image);
dataObject.GetData(DataFormats.Bitmap, autoConvert: false).Should().BeSameAs(image);
dataObject.GetData(typeof(Bitmap).FullName, autoConvert: true).Should().BeSameAs(image);
dataObject.GetData(typeof(Bitmap).FullName, autoConvert: false).Should().BeNull();
dataObject.GetData(DataFormats.Dib, autoConvert: true).Should().BeNull();
dataObject.GetData(DataFormats.Dib, autoConvert: false).Should().BeNull();
dataObject.ContainsImage().Should().BeTrue();
dataObject.GetDataPresent(DataFormats.Bitmap, autoConvert: true).Should().BeTrue();
dataObject.GetDataPresent(DataFormats.Bitmap, autoConvert: false).Should().BeTrue();
dataObject.GetDataPresent(typeof(Bitmap).FullName, autoConvert: true).Should().BeTrue();
dataObject.GetDataPresent(typeof(Bitmap).FullName, autoConvert: false).Should().BeFalse();
dataObject.GetDataPresent(DataFormats.Dib, autoConvert: true).Should().BeFalse();
dataObject.GetDataPresent(DataFormats.Dib, autoConvert: false).Should().BeFalse();
}
public static TheoryData<string, bool, object> SetData_StringBoolObjectIDataObject_TheoryData()
{
TheoryData<string, bool, object> theoryData = [];
foreach (string format in new string[] { "format", " ", string.Empty, null })
{
foreach (bool autoConvert in new bool[] { true, false })
{
theoryData.Add(format, autoConvert, null);
theoryData.Add(format, autoConvert, new());
}
}
return theoryData;
}
[Theory]
[MemberData(nameof(SetData_StringBoolObjectIDataObject_TheoryData))]
public void DataObject_SetData_InvokeStringBoolObjectIDataObject_CallsSetData(string format, bool autoConvert, object data)
{
Mock<IDataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.SetData(format, autoConvert, data))
.Verifiable();
DataObject dataObject = new(mockDataObject.Object);
dataObject.SetData(format, autoConvert, data);
mockDataObject.Verify(o => o.SetData(format, autoConvert, data), Times.Once());
}
public static TheoryData<Type, object> SetData_TypeObjectIDataObject_TheoryData()
{
TheoryData<Type, object> theoryData = [];
foreach (Type format in new Type[] { typeof(int), null })
{
theoryData.Add(format, null);
theoryData.Add(format, new());
}
return theoryData;
}
[Theory]
[MemberData(nameof(SetData_TypeObjectIDataObject_TheoryData))]
public void DataObject_SetData_InvokeTypeObjectIDataObject_CallsSetData(Type format, object data)
{
Mock<IDataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.SetData(format, data))
.Verifiable();
DataObject dataObject = new(mockDataObject.Object);
dataObject.SetData(format, data);
mockDataObject.Verify(o => o.SetData(format, data), Times.Once());
}
[Fact]
public void DataObject_SetData_NullFormat_ThrowsArgumentNullException()
{
DataObject dataObject = new();
((Action)(() => dataObject.SetData((string)null, new object()))).Should()
.Throw<ArgumentNullException>().WithParameterName("format");
((Action)(() => dataObject.SetData(null, true, new object()))).Should()
.Throw<ArgumentNullException>().WithParameterName("format");
((Action)(() => dataObject.SetData(null, false, new object()))).Should()
.Throw<ArgumentNullException>().WithParameterName("format");
((Action)(() => dataObject.SetData((Type)null, new object()))).Should()
.Throw<ArgumentNullException>().WithParameterName("format");
}
[Theory]
[InlineData("")]
[InlineData(" ")]
public void DataObject_SetData_WhitespaceOrEmptyFormat_ThrowsArgumentException(string format)
{
DataObject dataObject = new();
Action action = () => dataObject.SetData(format, new object());
action.Should().Throw<ArgumentException>().WithParameterName("format");
action = () => dataObject.SetData(format, true, new object());
action.Should().Throw<ArgumentException>().WithParameterName("format");
action = () => dataObject.SetData(format, false, new object());
action.Should().Throw<ArgumentException>().WithParameterName("format");
}
[Fact]
public void DataObject_SetData_DibBitmapNoAutoConvert_ThrowsNotSupportedException()
{
DataObject dataObject = new();
((Action)(() => dataObject.SetData(DataFormats.Dib, false, new Bitmap(10, 10))))
.Should().Throw<NotSupportedException>();
}
public static TheoryData<StringCollection> SetFileDropList_TheoryData() => new()
{
{ new StringCollection() },
{ new StringCollection { "file", " ", string.Empty, null } }
};
[Theory]
[MemberData(nameof(SetFileDropList_TheoryData))]
public void DataObject_SetFileDropList_Invoke_GetReturnsExpected(StringCollection filePaths)
{
DataObject dataObject = new();
dataObject.SetFileDropList(filePaths);
dataObject.GetFileDropList().Should().BeEquivalentTo(filePaths);
dataObject.GetData(DataFormats.FileDrop, autoConvert: true).Should().BeEquivalentTo(filePaths.Cast<string>());
dataObject.GetData(DataFormats.FileDrop, autoConvert: false).Should().BeEquivalentTo(filePaths.Cast<string>());
dataObject.GetData("FileName", autoConvert: true).Should().BeEquivalentTo(filePaths.Cast<string>());
dataObject.GetData("FileName", autoConvert: false).Should().BeNull();
dataObject.GetData("FileNameW", autoConvert: true).Should().BeEquivalentTo(filePaths.Cast<string>());
dataObject.GetData("FileNameW", autoConvert: false).Should().BeNull();
dataObject.ContainsFileDropList().Should().BeTrue();
dataObject.GetDataPresent(DataFormats.FileDrop, autoConvert: true).Should().BeTrue();
dataObject.GetDataPresent(DataFormats.FileDrop, autoConvert: false).Should().BeTrue();
dataObject.GetDataPresent("FileName", autoConvert: true).Should().BeTrue();
dataObject.GetDataPresent("FileName", autoConvert: false).Should().BeFalse();
dataObject.GetDataPresent("FileNameW", autoConvert: true).Should().BeTrue();
dataObject.GetDataPresent("FileNameW", autoConvert: false).Should().BeFalse();
}
[Theory]
[MemberData(nameof(SetFileDropList_TheoryData))]
public void DataObject_SetFileDropList_InvokeMocked_CallsSetFileDropList(StringCollection filePaths)
{
Mock<DataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.SetFileDropList(filePaths))
.CallBase();
mockDataObject
.Setup(o => o.SetData(DataFormats.FileDrop, true, It.IsAny<string[]>()))
.Verifiable();
mockDataObject.Object.SetFileDropList(filePaths);
mockDataObject.Verify(o => o.SetData(DataFormats.FileDrop, true, It.IsAny<string[]>()), Times.Once());
}
[Theory]
[MemberData(nameof(SetFileDropList_TheoryData))]
public void DataObject_SetFileDropList_InvokeIDataObject_CallsSetData(StringCollection filePaths)
{
Mock<IDataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.SetData(DataFormats.FileDrop, true, It.IsAny<string[]>()))
.Verifiable();
DataObject dataObject = new(mockDataObject.Object);
dataObject.SetFileDropList(filePaths);
mockDataObject.Verify(o => o.SetData(DataFormats.FileDrop, true, It.IsAny<string[]>()), Times.Once());
}
[Fact]
public void DataObject_SetFileDropList_NullFilePaths_ThrowsArgumentNullException()
{
DataObject dataObject = new();
Action action = () => dataObject.SetFileDropList(null);
action.Should().Throw<ArgumentNullException>().WithParameterName("filePaths");
}
[Fact]
public void DataObject_SetImage_Invoke_GetReturnsExpected()
{
using Bitmap image = new(10, 10);
DataObject dataObject = new();
dataObject.SetImage(image);
dataObject.GetImage().Should().BeSameAs(image);
dataObject.GetData(DataFormats.Bitmap, autoConvert: true).Should().BeSameAs(image);
dataObject.GetData(DataFormats.Bitmap, autoConvert: false).Should().BeSameAs(image);
dataObject.GetData(typeof(Bitmap).FullName, autoConvert: true).Should().BeSameAs(image);
dataObject.GetData(typeof(Bitmap).FullName, autoConvert: false).Should().BeNull();
dataObject.GetData(DataFormats.Dib, autoConvert: true).Should().BeNull();
dataObject.GetData(DataFormats.Dib, autoConvert: false).Should().BeNull();
dataObject.ContainsImage().Should().BeTrue();
dataObject.GetDataPresent(DataFormats.Bitmap, autoConvert: true).Should().BeTrue();
dataObject.GetDataPresent(DataFormats.Bitmap, autoConvert: false).Should().BeTrue();
dataObject.GetDataPresent(typeof(Bitmap).FullName, autoConvert: true).Should().BeTrue();
dataObject.GetDataPresent(typeof(Bitmap).FullName, autoConvert: false).Should().BeFalse();
dataObject.GetDataPresent(DataFormats.Dib, autoConvert: true).Should().BeFalse();
dataObject.GetDataPresent(DataFormats.Dib, autoConvert: false).Should().BeFalse();
}
[Fact]
public void DataObject_SetImage_InvokeMocked_CallsSetImage()
{
using Bitmap image = new(10, 10);
Mock<DataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.SetImage(image))
.CallBase();
mockDataObject
.Setup(o => o.SetData(DataFormats.Bitmap, true, image))
.Verifiable();
mockDataObject.Object.SetImage(image);
mockDataObject.Verify(o => o.SetData(DataFormats.Bitmap, true, image), Times.Once());
}
[Fact]
public void DataObject_SetImage_InvokeIDataObject_CallsSetData()
{
using Bitmap image = new(10, 10);
Mock<IDataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.SetData(DataFormats.Bitmap, true, image))
.Verifiable();
DataObject dataObject = new(mockDataObject.Object);
dataObject.SetImage(image);
mockDataObject.Verify(o => o.SetData(DataFormats.Bitmap, true, image), Times.Once());
}
[Fact]
public void DataObject_SetImage_NullImage_ThrowsArgumentNullException()
{
DataObject dataObject = new();
Action action = () => dataObject.SetImage(null);
action.Should().Throw<ArgumentNullException>().WithParameterName("image");
}
public static TheoryData<string> SetText_String_TheoryData() => new()
{
{ " " },
{ "textData" }
};
[Theory]
[MemberData(nameof(SetText_String_TheoryData))]
public void DataObject_SetText_InvokeString_GetReturnsExpected(string textData)
{
DataObject dataObject = new();
dataObject.SetText(textData);
dataObject.GetText().Should().BeSameAs(textData);
dataObject.GetData(DataFormats.UnicodeText, autoConvert: true).Should().BeSameAs(textData);
dataObject.GetData(DataFormats.UnicodeText, autoConvert: false).Should().BeSameAs(textData);
dataObject.GetData(DataFormats.Text, autoConvert: true).Should().BeSameAs(textData);
dataObject.GetData(DataFormats.Text, autoConvert: false).Should().BeNull();
dataObject.GetData(DataFormats.StringFormat, autoConvert: true).Should().BeSameAs(textData);
dataObject.GetData(DataFormats.StringFormat, autoConvert: false).Should().BeNull();
dataObject.GetData(DataFormats.Rtf, autoConvert: true).Should().BeNull();
dataObject.GetData(DataFormats.Rtf, autoConvert: false).Should().BeNull();
dataObject.GetData(DataFormats.Html, autoConvert: true).Should().BeNull();
dataObject.GetData(DataFormats.Html, autoConvert: false).Should().BeNull();
dataObject.GetData(DataFormats.CommaSeparatedValue, autoConvert: true).Should().BeNull();
dataObject.GetData(DataFormats.CommaSeparatedValue, autoConvert: false).Should().BeNull();
dataObject.ContainsText().Should().BeTrue();
dataObject.GetDataPresent(DataFormats.UnicodeText, autoConvert: true).Should().BeTrue();
dataObject.GetDataPresent(DataFormats.UnicodeText, autoConvert: false).Should().BeTrue();
dataObject.GetDataPresent(DataFormats.Text, autoConvert: true).Should().BeFalse();
dataObject.GetDataPresent(DataFormats.Text, autoConvert: false).Should().BeFalse();
dataObject.GetDataPresent(DataFormats.StringFormat, autoConvert: true).Should().BeFalse();
dataObject.GetDataPresent(DataFormats.StringFormat, autoConvert: false).Should().BeFalse();
dataObject.GetDataPresent(DataFormats.Rtf, autoConvert: true).Should().BeFalse();
dataObject.GetDataPresent(DataFormats.Rtf, autoConvert: false).Should().BeFalse();
dataObject.GetDataPresent(DataFormats.Html, autoConvert: true).Should().BeFalse();
dataObject.GetDataPresent(DataFormats.Html, autoConvert: false).Should().BeFalse();
dataObject.GetDataPresent(DataFormats.CommaSeparatedValue, autoConvert: true).Should().BeFalse();
dataObject.GetDataPresent(DataFormats.CommaSeparatedValue, autoConvert: false).Should().BeFalse();
}
[Theory]
[MemberData(nameof(SetText_String_TheoryData))]
public void DataObject_SetText_InvokeStringMocked_CallsSetText(string textData)
{
Mock<DataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.SetText(textData))
.CallBase();
mockDataObject
.Setup(o => o.SetText(textData, TextDataFormat.UnicodeText))
.Verifiable();
mockDataObject.Object.SetText(textData);
mockDataObject.Verify(o => o.SetText(textData, TextDataFormat.UnicodeText), Times.Once());
}
[Theory]
[MemberData(nameof(SetText_String_TheoryData))]
public void DataObject_SetText_InvokeStringIDataObject_CallsSetData(string textData)
{
Mock<IDataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.SetData(DataFormats.UnicodeText, false, textData))
.Verifiable();
DataObject dataObject = new(mockDataObject.Object);
dataObject.SetText(textData);
mockDataObject.Verify(o => o.SetData(DataFormats.UnicodeText, false, textData), Times.Once());
}
public static TheoryData<string, TextDataFormat, string, string, string, string> SetText_StringTextDataFormat_TheoryData()
{
TheoryData<string, TextDataFormat, string, string, string, string> theoryData = [];
foreach (string textData in new string[] { "textData", " " })
{
theoryData.Add(textData, TextDataFormat.Text, textData, null, null, null);
theoryData.Add(textData, TextDataFormat.UnicodeText, textData, null, null, null);
theoryData.Add(textData, TextDataFormat.Rtf, null, textData, null, null);
theoryData.Add(textData, TextDataFormat.Html, null, null, textData, null);
theoryData.Add(textData, TextDataFormat.CommaSeparatedValue, null, null, null, textData);
}
return theoryData;
}
[Theory]
[MemberData(nameof(SetText_StringTextDataFormat_TheoryData))]
public void DataObject_SetText_InvokeStringTextDataFormat_GetReturnsExpected(string textData, TextDataFormat format, string expectedUnicodeText, string expectedRtfText, string expectedHtmlText, string expectedCsvText)
{
DataObject dataObject = new();
dataObject.SetText(textData, format);
dataObject.GetText(format).Should().Be(textData);
dataObject.GetData(DataFormats.UnicodeText, autoConvert: true).Should().Be(expectedUnicodeText);
dataObject.GetData(DataFormats.UnicodeText, autoConvert: false).Should().Be(expectedUnicodeText);
dataObject.GetData(DataFormats.Text, autoConvert: true).Should().Be(expectedUnicodeText);
dataObject.GetData(DataFormats.Text, autoConvert: false).Should().BeNull();
dataObject.GetData(DataFormats.StringFormat, autoConvert: true).Should().Be(expectedUnicodeText);
dataObject.GetData(DataFormats.StringFormat, autoConvert: false).Should().BeNull();
dataObject.GetData(DataFormats.Rtf, autoConvert: true).Should().Be(expectedRtfText);
dataObject.GetData(DataFormats.Rtf, autoConvert: false).Should().Be(expectedRtfText);
dataObject.GetData(DataFormats.Html, autoConvert: true).Should().Be(expectedHtmlText);
dataObject.GetData(DataFormats.Html, autoConvert: false).Should().Be(expectedHtmlText);
dataObject.GetData(DataFormats.CommaSeparatedValue, autoConvert: true).Should().Be(expectedCsvText);
dataObject.GetData(DataFormats.CommaSeparatedValue, autoConvert: false).Should().Be(expectedCsvText);
dataObject.ContainsText(format).Should().BeTrue();
dataObject.GetDataPresent(DataFormats.UnicodeText, autoConvert: true).Should().Be(expectedUnicodeText is not null);
dataObject.GetDataPresent(DataFormats.UnicodeText, autoConvert: false).Should().Be(expectedUnicodeText is not null);
dataObject.GetDataPresent(DataFormats.Text, autoConvert: true).Should().BeFalse();
dataObject.GetDataPresent(DataFormats.Text, autoConvert: false).Should().BeFalse();
dataObject.GetDataPresent(DataFormats.StringFormat, autoConvert: true).Should().BeFalse();
dataObject.GetDataPresent(DataFormats.StringFormat, autoConvert: false).Should().BeFalse();
dataObject.GetDataPresent(DataFormats.Rtf, autoConvert: true).Should().Be(expectedRtfText is not null);
dataObject.GetDataPresent(DataFormats.Rtf, autoConvert: false).Should().Be(expectedRtfText is not null);
dataObject.GetDataPresent(DataFormats.Html, autoConvert: true).Should().Be(expectedHtmlText is not null);
dataObject.GetDataPresent(DataFormats.Html, autoConvert: false).Should().Be(expectedHtmlText is not null);
dataObject.GetDataPresent(DataFormats.CommaSeparatedValue, autoConvert: true).Should().Be(expectedCsvText is not null);
dataObject.GetDataPresent(DataFormats.CommaSeparatedValue, autoConvert: false).Should().Be(expectedCsvText is not null);
}
public static TheoryData<string, TextDataFormat, string> SetText_StringTextDataFormatMocked_TheoryData()
{
TheoryData<string, TextDataFormat, string> theoryData = [];
foreach (string textData in new string[] { "textData", " " })
{
theoryData.Add(textData, TextDataFormat.Text, DataFormats.UnicodeText);
theoryData.Add(textData, TextDataFormat.UnicodeText, DataFormats.UnicodeText);
theoryData.Add(textData, TextDataFormat.Rtf, DataFormats.Rtf);
theoryData.Add(textData, TextDataFormat.Html, DataFormats.Html);
theoryData.Add(textData, TextDataFormat.CommaSeparatedValue, DataFormats.CommaSeparatedValue);
}
return theoryData;
}
[Theory]
[MemberData(nameof(SetText_StringTextDataFormatMocked_TheoryData))]
public void DataObject_SetText_InvokeStringTextDataFormatMocked_CallsSetText(string textData, TextDataFormat format, string expectedFormat)
{
Mock<DataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.SetText(textData, format))
.CallBase();
mockDataObject
.Setup(o => o.SetData(expectedFormat, false, textData))
.Verifiable();
mockDataObject.Object.SetText(textData, format);
mockDataObject.Verify(o => o.SetData(expectedFormat, false, textData), Times.Once());
}
[Theory]
[MemberData(nameof(SetText_StringTextDataFormatMocked_TheoryData))]
public void DataObject_SetText_InvokeStringTextDataFormatIDataObject_CallsSetData(string textData, TextDataFormat format, string expectedFormat)
{
Mock<IDataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.SetData(expectedFormat, false, textData))
.Verifiable();
DataObject dataObject = new(mockDataObject.Object);
dataObject.SetText(textData, format);
mockDataObject.Verify(o => o.SetData(expectedFormat, false, textData), Times.Once());
}
[Theory]
[NullAndEmptyStringData]
public void DataObject_SetText_NullOrEmptyTextData_ThrowsArgumentNullException(string textData)
{
DataObject dataObject = new();
((Action)(() => dataObject.SetText(textData))).Should()
.Throw<ArgumentNullException>().WithParameterName("textData");
((Action)(() => dataObject.SetText(textData, TextDataFormat.Text))).Should()
.Throw<ArgumentNullException>().WithParameterName("textData");
}
[Theory]
[InvalidEnumData<TextDataFormat>]
public void DataObject_SetText_InvalidFormat_ThrowsInvalidEnumArgumentException(TextDataFormat format)
{
DataObject dataObject = new();
((Action)(() => dataObject.SetText("text", format))).Should()
.Throw<InvalidEnumArgumentException>().WithParameterName("format");
}
[WinFormsFact]
public void DataObject_GetData_EnhancedMetafile_DoesNotTerminateProcess()
{
DataObject data = new(new DataObjectIgnoringStorageMediumForEnhancedMetafile());
// Office ignores the storage medium in GetData(EnhancedMetafile) and always returns a handle,
// even when asked for a stream. This used to crash the process when DataObject interpreted the
// handle as a pointer to a COM IStream without checking the storage medium it retrieved.
data.GetData(DataFormats.EnhancedMetafile).Should().BeNull();
}
private sealed class DataObjectIgnoringStorageMediumForEnhancedMetafile : IComDataObject
{
public void GetData(ref FORMATETC format, out STGMEDIUM medium)
{
Marshal.ThrowExceptionForHR(QueryGetData(ref format));
using var metafile = new Drawing.Imaging.Metafile("bitmaps/milkmateya01.emf");
medium = default;
medium.tymed = TYMED.TYMED_ENHMF;
medium.unionmember = metafile.GetHenhmetafile();
}
public int QueryGetData(ref FORMATETC format)
{
// do not check the requested storage medium, we always return a metafile handle, thats what Office does
if (format.cfFormat != (short)CLIPBOARD_FORMAT.CF_ENHMETAFILE || format.dwAspect != DVASPECT.DVASPECT_CONTENT || format.lindex != -1)
return (int)HRESULT.DV_E_FORMATETC;
return 0;
}
public IEnumFORMATETC EnumFormatEtc(DATADIR direction) => throw new NotImplementedException();
public void GetDataHere(ref FORMATETC format, ref STGMEDIUM medium) => throw new NotImplementedException();
public int GetCanonicalFormatEtc(ref FORMATETC formatIn, out FORMATETC formatOut) => throw new NotImplementedException();
public void SetData(ref FORMATETC formatIn, ref STGMEDIUM medium, bool release) => throw new NotImplementedException();
public int DAdvise(ref FORMATETC pFormatetc, ADVF advf, IAdviseSink adviseSink, out int connection) => throw new NotImplementedException();
public void DUnadvise(int connection) => throw new NotImplementedException();
public int EnumDAdvise(out IEnumSTATDATA enumAdvise) => throw new NotImplementedException();
}
public static TheoryData<ADVF, IAdviseSink> DAdvise_TheoryData()
{
TheoryData<ADVF, IAdviseSink> theoryData = new()
{
{ ADVF.ADVF_DATAONSTOP, null }
};
Mock<IAdviseSink> mockAdviseSink = new(MockBehavior.Strict);
theoryData.Add(ADVF.ADVF_DATAONSTOP, mockAdviseSink.Object);
return theoryData;
}
[WinFormsTheory]
[MemberData(nameof(DAdvise_TheoryData))]
public void DataObject_DAdvise_InvokeDefault_Success(ADVF advf, IAdviseSink adviseSink)
{
DataObject dataObject = new();
IComDataObject comDataObject = dataObject;
FORMATETC formatetc = default;
((HRESULT)comDataObject.DAdvise(ref formatetc, advf, adviseSink, out int connection)).Should().Be(HRESULT.E_NOTIMPL);
connection.Should().Be(0);
}
private delegate void DAdviseCallback(ref FORMATETC pFormatetc, ADVF advf, IAdviseSink adviseSink, out int connection);
[WinFormsTheory]
[MemberData(nameof(DAdvise_TheoryData))]
public void DataObject_DAdvise_InvokeCustomComDataObject_Success(ADVF advf, IAdviseSink adviseSink)
{
Mock<IComDataObject> mockComDataObject = new(MockBehavior.Strict);
mockComDataObject
.Setup(o => o.DAdvise(ref It.Ref<FORMATETC>.IsAny, advf, adviseSink, out It.Ref<int>.IsAny))
.Callback((DAdviseCallback)((ref FORMATETC pFormatetc, ADVF advf, IAdviseSink adviseSink, out int connection) =>
{
pFormatetc.cfFormat = 3;
connection = 2;
}))
.Returns(1);
DataObject dataObject = new(mockComDataObject.Object);
IComDataObject comDataObject = dataObject;
FORMATETC formatetc = default;
comDataObject.DAdvise(ref formatetc, advf, adviseSink, out int connection).Should().Be(1);
connection.Should().Be(2);
formatetc.cfFormat.Should().Be(3);
mockComDataObject.Verify(o => o.DAdvise(ref It.Ref<FORMATETC>.IsAny, advf, adviseSink, out It.Ref<int>.IsAny), Times.Once());
}
[WinFormsTheory]
[InlineData(-1)]
[InlineData(0)]
public void DataObject_DUnadvise_InvokeDefault_Success(int connection)
{
DataObject dataObject = new();
IComDataObject comDataObject = dataObject;
Action action = () => comDataObject.DUnadvise(connection);
action.Should().Throw<NotImplementedException>();
}
[WinFormsTheory]
[InlineData(-1)]
[InlineData(0)]
public void DataObject_DUnadvise_InvokeCustomComDataObject_Success(int connection)
{
Mock<IComDataObject> mockComDataObject = new(MockBehavior.Strict);
mockComDataObject
.Setup(o => o.DUnadvise(connection))
.Verifiable();
DataObject dataObject = new(mockComDataObject.Object);
IComDataObject comDataObject = dataObject;
comDataObject.DUnadvise(connection);
mockComDataObject.Verify(o => o.DUnadvise(connection), Times.Once());
}
[WinFormsFact]
public void DataObject_EnumDAdvise_InvokeDefault_Success()
{
DataObject dataObject = new();
IComDataObject comDataObject = dataObject;
((HRESULT)comDataObject.EnumDAdvise(out IEnumSTATDATA enumAdvise)).Should().Be(HRESULT.OLE_E_ADVISENOTSUPPORTED);
enumAdvise.Should().BeNull();
}
private delegate void EnumDAdviseCallback(out IEnumSTATDATA enumAdvise);
public static TheoryData<IEnumSTATDATA> EnumDAdvise_CustomComDataObject_TheoryData()
{
TheoryData<IEnumSTATDATA> theoryData = [null];
Mock<IEnumSTATDATA> mockEnumStatData = new(MockBehavior.Strict);
theoryData.Add(mockEnumStatData.Object);
return theoryData;
}
[WinFormsTheory]
[MemberData(nameof(EnumDAdvise_CustomComDataObject_TheoryData))]
public void DataObject_EnumDAdvise_InvokeCustomComDataObject_Success(IEnumSTATDATA result)
{
Mock<IComDataObject> mockComDataObject = new(MockBehavior.Strict);
mockComDataObject
.Setup(o => o.EnumDAdvise(out It.Ref<IEnumSTATDATA>.IsAny))
.Callback((EnumDAdviseCallback)((out IEnumSTATDATA enumAdvise) =>
{
enumAdvise = result;
}))
.Returns(1);
DataObject dataObject = new(mockComDataObject.Object);
IComDataObject comDataObject = dataObject;
comDataObject.EnumDAdvise(out IEnumSTATDATA enumStatData).Should().Be(1);
enumStatData.Should().BeSameAs(result);
mockComDataObject.Verify(o => o.EnumDAdvise(out It.Ref<IEnumSTATDATA>.IsAny), Times.Once());
}
public static TheoryData<int> EnumFormatEtc_Default_TheoryData() => new()
{
{ -1 },
{ 0 },
{ 1 },
{ 2 }
};
[WinFormsTheory]
[MemberData(nameof(EnumFormatEtc_Default_TheoryData))]
public void DataObject_EnumFormatEtc_InvokeDefault_Success(int celt)
{
DataObject dataObject = new();
IComDataObject comDataObject = dataObject;
IEnumFORMATETC enumerator = comDataObject.EnumFormatEtc(DATADIR.DATADIR_GET);
enumerator.Should().NotBeNull();
var result = new FORMATETC[1];
int[] fetched = new int[1];
for (int i = 0; i < 2; i++)
{
enumerator.Next(celt, result, fetched).Should().Be((int)HRESULT.S_FALSE);
result[0].cfFormat.Should().Be(0);
fetched[0].Should().Be(0);
enumerator.Next(celt, null, null).Should().Be((int)HRESULT.S_FALSE);
enumerator.Reset().Should().Be((int)HRESULT.S_OK);
}
}
public static TheoryData<string, TYMED> EnumFormatEtc_TheoryData() => new()
{
{ DataFormats.Bitmap, TYMED.TYMED_GDI },
{ DataFormats.CommaSeparatedValue, TYMED.TYMED_HGLOBAL },
{ DataFormats.Dib, TYMED.TYMED_HGLOBAL },
{ DataFormats.Dif, TYMED.TYMED_HGLOBAL },
{ DataFormats.EnhancedMetafile, TYMED.TYMED_HGLOBAL },
{ DataFormats.FileDrop, TYMED.TYMED_HGLOBAL },
{ "FileName", TYMED.TYMED_HGLOBAL },
{ "FileNameW", TYMED.TYMED_HGLOBAL },
{ DataFormats.Html, TYMED.TYMED_HGLOBAL },
{ DataFormats.Locale, TYMED.TYMED_HGLOBAL },
{ DataFormats.MetafilePict, TYMED.TYMED_HGLOBAL },
{ DataFormats.OemText, TYMED.TYMED_HGLOBAL },
{ DataFormats.Palette, TYMED.TYMED_HGLOBAL },
{ DataFormats.PenData, TYMED.TYMED_HGLOBAL },
{ DataFormats.Riff, TYMED.TYMED_HGLOBAL },
{ DataFormats.Rtf, TYMED.TYMED_HGLOBAL },
{ DataFormats.Serializable, TYMED.TYMED_HGLOBAL },
{ DataFormats.StringFormat, TYMED.TYMED_HGLOBAL },
{ DataFormats.SymbolicLink, TYMED.TYMED_HGLOBAL },
{ DataFormats.Text, TYMED.TYMED_HGLOBAL },
{ DataFormats.Tiff, TYMED.TYMED_HGLOBAL },
{ DataFormats.UnicodeText, TYMED.TYMED_HGLOBAL },
{ DataFormats.WaveAudio, TYMED.TYMED_HGLOBAL }
};
[WinFormsTheory]
[MemberData(nameof(EnumFormatEtc_TheoryData))]
public void DataObject_EnumFormatEtc_InvokeWithValues_Success(string format1, TYMED expectedTymed)
{
Mock<IDataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.GetFormats())
.Returns([format1, "Format2"]);
DataObject dataObject = new(mockDataObject.Object);
IComDataObject comDataObject = dataObject;
IEnumFORMATETC enumerator = comDataObject.EnumFormatEtc(DATADIR.DATADIR_GET);
enumerator.Should().NotBeNull();
var result = new FORMATETC[2];
int[] fetched = new int[2];
for (int i = 0; i < 1; i++)
{
// Fetch nothing.
((HRESULT)enumerator.Next(0, result, fetched)).Should().Be(HRESULT.S_FALSE);
fetched[0].Should().Be(0);
((HRESULT)enumerator.Next(0, null, null)).Should().Be(HRESULT.S_FALSE);
// Fetch negative.
((HRESULT)enumerator.Next(-1, result, fetched)).Should().Be(HRESULT.S_FALSE);
fetched[0].Should().Be(0);
((HRESULT)enumerator.Next(-1, null, null)).Should().Be(HRESULT.S_FALSE);
// Null.
((Action)(() => enumerator.Next(1, null, fetched))).Should().Throw<NullReferenceException>();
// Fetch first.
((HRESULT)enumerator.Next(i + 1, result, fetched)).Should().Be(HRESULT.S_OK);
result[0].cfFormat.Should().Be(unchecked((short)(ushort)(DataFormats.GetFormat(format1).Id)));
result[0].dwAspect.Should().Be(DVASPECT.DVASPECT_CONTENT);
result[0].lindex.Should().Be(-1);
result[0].ptd.Should().Be(IntPtr.Zero);
result[0].tymed.Should().Be(expectedTymed);
result[1].cfFormat.Should().Be(0);
fetched[0].Should().Be(1);
// Fetch second.
((HRESULT)enumerator.Next(i + 1, result, fetched)).Should().Be(HRESULT.S_OK);
result[0].cfFormat.Should().NotBe(0);
result[0].dwAspect.Should().Be(DVASPECT.DVASPECT_CONTENT);
result[0].lindex.Should().Be(-1);
result[0].ptd.Should().Be(IntPtr.Zero);
result[0].tymed.Should().Be(TYMED.TYMED_HGLOBAL);
result[1].cfFormat.Should().Be(0);
fetched[0].Should().Be(1);
// Fetch another.
((HRESULT)enumerator.Next(1, null, null)).Should().Be(HRESULT.S_FALSE);
((HRESULT)enumerator.Next(1, null, null)).Should().Be(HRESULT.S_FALSE);
// Reset.
((HRESULT)enumerator.Reset()).Should().Be(HRESULT.S_OK);
}
}
[WinFormsTheory]
[MemberData(nameof(EnumFormatEtc_Default_TheoryData))]
public void DataObject_EnumFormatEtc_InvokeNullFormats_Success(int celt)
{
Mock<IDataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.GetFormats())
.Returns((string[])null);
DataObject dataObject = new(mockDataObject.Object);
IComDataObject comDataObject = dataObject;
IEnumFORMATETC enumerator = comDataObject.EnumFormatEtc(DATADIR.DATADIR_GET);
enumerator.Should().NotBeNull();
var result = new FORMATETC[1];
int[] fetched = new int[1];
for (int i = 0; i < 2; i++)
{
((HRESULT)enumerator.Next(celt, result, fetched)).Should().Be(HRESULT.S_FALSE);
result[0].cfFormat.Should().Be(0);
fetched[0].Should().Be(0);
((HRESULT)enumerator.Next(celt, null, null)).Should().Be(HRESULT.S_FALSE);
((HRESULT)enumerator.Reset()).Should().Be(HRESULT.S_OK);
}
}
[WinFormsTheory]
[InlineData(0)]
[InlineData(1)]
public void DataObject_EnumFormatEtc_SkipDefault_Success(int celt)
{
DataObject dataObject = new();
IComDataObject comDataObject = dataObject;
IEnumFORMATETC enumerator = comDataObject.EnumFormatEtc(DATADIR.DATADIR_GET);
enumerator.Should().NotBeNull();
var result = new FORMATETC[1];
int[] fetched = new int[1];
((HRESULT)enumerator.Skip(celt)).Should().Be(HRESULT.S_FALSE);
((HRESULT)enumerator.Next(1, result, fetched)).Should().Be(HRESULT.S_FALSE);
// Negative.
((HRESULT)enumerator.Skip(-1)).Should().Be(HRESULT.S_OK);
Action action = () => enumerator.Next(1, result, fetched);
action.Should().Throw<ArgumentOutOfRangeException>().WithParameterName("index");
}
[WinFormsFact]
public void DataObject_EnumFormatEtc_SkipCustom_Success()
{
Mock<IDataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.GetFormats())
.Returns(["Format1", DataFormats.Bitmap, "Format2"]);
DataObject dataObject = new(mockDataObject.Object);
IComDataObject comDataObject = dataObject;
IEnumFORMATETC enumerator = comDataObject.EnumFormatEtc(DATADIR.DATADIR_GET);
enumerator.Should().NotBeNull();
var result = new FORMATETC[1];
int[] fetched = new int[1];
((HRESULT)enumerator.Skip(1)).Should().Be(HRESULT.S_OK);
((HRESULT)enumerator.Next(1, result, fetched)).Should().Be(HRESULT.S_OK);
result[0].cfFormat.Should().Be(2);
result[0].dwAspect.Should().Be(DVASPECT.DVASPECT_CONTENT);
result[0].lindex.Should().Be(-1);
result[0].ptd.Should().Be(IntPtr.Zero);
result[0].tymed.Should().Be(TYMED.TYMED_GDI);
fetched[0].Should().Be(1);
// Skip negative.
((HRESULT)enumerator.Skip(-2)).Should().Be(HRESULT.S_OK);
((HRESULT)enumerator.Next(1, result, fetched)).Should().Be(HRESULT.S_OK);
result[0].cfFormat.Should().Be(unchecked((short)(ushort)(DataFormats.GetFormat("Format1").Id)));
result[0].dwAspect.Should().Be(DVASPECT.DVASPECT_CONTENT);
result[0].lindex.Should().Be(-1);
result[0].ptd.Should().Be(IntPtr.Zero);
result[0].tymed.Should().Be(TYMED.TYMED_HGLOBAL);
fetched[0].Should().Be(1);
// Skip end.
((HRESULT)enumerator.Skip(1)).Should().Be(HRESULT.S_OK);
((HRESULT)enumerator.Next(1, result, fetched)).Should().Be(HRESULT.S_OK);
result[0].cfFormat.Should().Be(unchecked((short)(ushort)(DataFormats.GetFormat("Format2").Id)));
result[0].dwAspect.Should().Be(DVASPECT.DVASPECT_CONTENT);
result[0].lindex.Should().Be(-1);
result[0].ptd.Should().Be(IntPtr.Zero);
result[0].tymed.Should().Be(TYMED.TYMED_HGLOBAL);
fetched[0].Should().Be(1);
((HRESULT)enumerator.Skip(0)).Should().Be(HRESULT.S_FALSE);
((HRESULT)enumerator.Skip(1)).Should().Be(HRESULT.S_FALSE);
// Negative.
((HRESULT)enumerator.Skip(-4)).Should().Be(HRESULT.S_OK);
Action action = () => enumerator.Next(1, result, fetched);
action.Should().Throw<ArgumentOutOfRangeException>().WithParameterName("index");
}
[WinFormsTheory]
[MemberData(nameof(EnumFormatEtc_Default_TheoryData))]
public void DataObject_EnumFormatEtc_CloneDefault_Success(int celt)
{
DataObject dataObject = new();
IComDataObject comDataObject = dataObject;
IEnumFORMATETC source = comDataObject.EnumFormatEtc(DATADIR.DATADIR_GET);
source.Clone(out IEnumFORMATETC enumerator);
enumerator.Should().NotBeNull();
var result = new FORMATETC[1];
int[] fetched = new int[1];
for (int i = 0; i < 2; i++)
{
((HRESULT)enumerator.Next(celt, result, fetched)).Should().Be(HRESULT.S_FALSE);
result[0].cfFormat.Should().Be(0);
fetched[0].Should().Be(0);
((HRESULT)enumerator.Next(celt, null, null)).Should().Be(HRESULT.S_FALSE);
((HRESULT)enumerator.Reset()).Should().Be(HRESULT.S_OK);
}
}
[WinFormsTheory]
[MemberData(nameof(EnumFormatEtc_TheoryData))]
public void DataObject_EnumFormatEtc_CloneWithValues_Success(string format1, TYMED expectedTymed)
{
Mock<IDataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.GetFormats())
.Returns([format1, "Format2"]);
DataObject dataObject = new(mockDataObject.Object);
IComDataObject comDataObject = dataObject;
IEnumFORMATETC source = comDataObject.EnumFormatEtc(DATADIR.DATADIR_GET);
source.Clone(out IEnumFORMATETC enumerator);
enumerator.Should().NotBeNull();
var result = new FORMATETC[2];
int[] fetched = new int[2];
for (int i = 0; i < 1; i++)
{
// Fetch nothing.
((HRESULT)enumerator.Next(0, result, fetched)).Should().Be(HRESULT.S_FALSE);
fetched[0].Should().Be(0);
((HRESULT)enumerator.Next(0, null, null)).Should().Be(HRESULT.S_FALSE);
// Fetch negative.
((HRESULT)enumerator.Next(-1, result, fetched)).Should().Be(HRESULT.S_FALSE);
fetched[0].Should().Be(0);
((HRESULT)enumerator.Next(-1, null, null)).Should().Be(HRESULT.S_FALSE);
// Null.
((Action)(() => enumerator.Next(1, null, fetched))).Should().Throw<NullReferenceException>();
// Fetch first.
((HRESULT)enumerator.Next(i + 1, result, fetched)).Should().Be(HRESULT.S_OK);
result[0].cfFormat.Should().Be(unchecked((short)(ushort)(DataFormats.GetFormat(format1).Id)));
result[0].dwAspect.Should().Be(DVASPECT.DVASPECT_CONTENT);
result[0].lindex.Should().Be(-1);
result[0].ptd.Should().Be(IntPtr.Zero);
result[0].tymed.Should().Be(expectedTymed);
result[1].cfFormat.Should().Be(0);
fetched[0].Should().Be(1);
// Fetch second.
((HRESULT)enumerator.Next(i + 1, result, fetched)).Should().Be(HRESULT.S_OK);
result[0].cfFormat.Should().NotBe(0);
result[0].dwAspect.Should().Be(DVASPECT.DVASPECT_CONTENT);
result[0].lindex.Should().Be(-1);
result[0].ptd.Should().Be(IntPtr.Zero);
result[0].tymed.Should().Be(TYMED.TYMED_HGLOBAL);
result[1].cfFormat.Should().Be(0);
fetched[0].Should().Be(1);
// Fetch another.
((HRESULT)enumerator.Next(1, null, null)).Should().Be(HRESULT.S_FALSE);
((HRESULT)enumerator.Next(1, null, null)).Should().Be(HRESULT.S_FALSE);
// Reset.
((HRESULT)enumerator.Reset()).Should().Be(HRESULT.S_OK);
}
}
[WinFormsTheory]
[MemberData(nameof(EnumFormatEtc_Default_TheoryData))]
public void DataObject_EnumFormatEtc_CloneNullFormats_Success(int celt)
{
Mock<IDataObject> mockDataObject = new(MockBehavior.Strict);
mockDataObject
.Setup(o => o.GetFormats())
.Returns((string[])null);
DataObject dataObject = new(mockDataObject.Object);
IComDataObject comDataObject = dataObject;
IEnumFORMATETC source = comDataObject.EnumFormatEtc(DATADIR.DATADIR_GET);
source.Clone(out IEnumFORMATETC enumerator);
enumerator.Should().NotBeNull();
var result = new FORMATETC[1];
int[] fetched = new int[1];
for (int i = 0; i < 2; i++)
{
((HRESULT)enumerator.Next(celt, result, fetched)).Should().Be(HRESULT.S_FALSE);
result[0].cfFormat.Should().Be(0);
fetched[0].Should().Be(0);
((HRESULT)enumerator.Next(celt, null, null)).Should().Be(HRESULT.S_FALSE);
((HRESULT)enumerator.Reset()).Should().Be(HRESULT.S_OK);
}
}
[WinFormsTheory]
[InlineData(DATADIR.DATADIR_SET)]
[InlineData(DATADIR.DATADIR_GET - 1)]
[InlineData(DATADIR.DATADIR_SET + 1)]
public void DataObject_EnumFormatEtc_InvokeNotGet_ThrowsExternalException(DATADIR dwDirection)
{
DataObject dataObject = new();
IComDataObject comDataObject = dataObject;
((Action)(() => comDataObject.EnumFormatEtc(dwDirection))).Should().Throw<ExternalException>();
}
public static TheoryData<DATADIR, IEnumFORMATETC> EnumFormatEtc_CustomComDataObject_TheoryData()
{
TheoryData<DATADIR, IEnumFORMATETC> theoryData = [];
Mock<IEnumFORMATETC> mockEnumFormatEtc = new(MockBehavior.Strict);
theoryData.Add(DATADIR.DATADIR_GET, mockEnumFormatEtc.Object);
theoryData.Add(DATADIR.DATADIR_SET, mockEnumFormatEtc.Object);
theoryData.Add(DATADIR.DATADIR_GET - 1, mockEnumFormatEtc.Object);
theoryData.Add(DATADIR.DATADIR_SET + 1, mockEnumFormatEtc.Object);
return theoryData;
}
[WinFormsTheory]
[MemberData(nameof(EnumFormatEtc_CustomComDataObject_TheoryData))]
public void DataObject_EnumFormatEtc_InvokeCustomComDataObject_Success(DATADIR dwDirection, IEnumFORMATETC result)
{
Mock<IComDataObject> mockComDataObject = new(MockBehavior.Strict);
mockComDataObject
.Setup(o => o.EnumFormatEtc(dwDirection))
.Returns(result)
.Verifiable();
DataObject dataObject = new(mockComDataObject.Object);
IComDataObject comDataObject = dataObject;
comDataObject.EnumFormatEtc(dwDirection).Should().BeSameAs(result);
mockComDataObject.Verify(o => o.EnumFormatEtc(dwDirection), Times.Once());
}
public static TheoryData<TextDataFormat, short> GetDataHere_Text_TheoryData() => new()
{
{ TextDataFormat.Rtf, (short)DataFormats.GetFormat(DataFormats.Rtf).Id },
{ TextDataFormat.Html, (short)DataFormats.GetFormat(DataFormats.Html).Id }
};
[WinFormsTheory]
[MemberData(nameof(GetDataHere_Text_TheoryData))]
public unsafe void IComDataObjectGetDataHere_Text_Success(TextDataFormat textDataFormat, short cfFormat)
{
DataObject dataObject = new();
dataObject.SetText("text", textDataFormat);
IComDataObject iComDataObject = dataObject;
FORMATETC formatetc = new()
{
tymed = TYMED.TYMED_HGLOBAL,
cfFormat = cfFormat
};
STGMEDIUM stgMedium = new()
{
tymed = TYMED.TYMED_HGLOBAL
};
HGLOBAL handle = PInvokeCore.GlobalAlloc(
GLOBAL_ALLOC_FLAGS.GMEM_MOVEABLE | GLOBAL_ALLOC_FLAGS.GMEM_ZEROINIT,
1);
try
{
stgMedium.unionmember = handle;
iComDataObject.GetDataHere(ref formatetc, ref stgMedium);
sbyte* pChar = *(sbyte**)stgMedium.unionmember;
new string(pChar).Should().Be("text");
}
finally
{
PInvokeCore.GlobalFree(handle);
}
}
public static TheoryData<TextDataFormat, short> GetDataHere_UnicodeText_TheoryData() => new()
{
{ TextDataFormat.Text, (short)CLIPBOARD_FORMAT.CF_UNICODETEXT },
{ TextDataFormat.UnicodeText, (short)CLIPBOARD_FORMAT.CF_UNICODETEXT }
};
[WinFormsTheory]
[MemberData(nameof(GetDataHere_UnicodeText_TheoryData))]
public unsafe void IComDataObjectGetDataHere_UnicodeText_Success(TextDataFormat textDataFormat, short cfFormat)
{
DataObject dataObject = new();
dataObject.SetText("text", textDataFormat);
IComDataObject iComDataObject = dataObject;
FORMATETC formatetc = new()
{
tymed = TYMED.TYMED_HGLOBAL,
cfFormat = cfFormat
};
STGMEDIUM stgMedium = new()
{
tymed = TYMED.TYMED_HGLOBAL
};
HGLOBAL handle = PInvokeCore.GlobalAlloc(
GLOBAL_ALLOC_FLAGS.GMEM_MOVEABLE | GLOBAL_ALLOC_FLAGS.GMEM_ZEROINIT,
1);
try
{
stgMedium.unionmember = handle;
iComDataObject.GetDataHere(ref formatetc, ref stgMedium);
char* pChar = *(char**)stgMedium.unionmember;
new string(pChar).Should().Be("text");
}
finally
{
PInvokeCore.GlobalFree(handle);
}
}
[WinFormsTheory]
[MemberData(nameof(GetDataHere_Text_TheoryData))]
public unsafe void IComDataObjectGetDataHere_TextNoData_ThrowsArgumentException(TextDataFormat textDataFormat, short cfFormat)
{
DataObject dataObject = new();
dataObject.SetText("text", textDataFormat);
IComDataObject iComDataObject = dataObject;
FORMATETC formatetc = new()
{
tymed = TYMED.TYMED_HGLOBAL,
cfFormat = cfFormat
};
STGMEDIUM stgMedium = new()
{
tymed = TYMED.TYMED_HGLOBAL
};
((Action)(() => iComDataObject.GetDataHere(ref formatetc, ref stgMedium))).Should().Throw<ArgumentException>();
}
[WinFormsTheory]
[MemberData(nameof(GetDataHere_UnicodeText_TheoryData))]
public unsafe void IComDataObjectGetDataHere_UnicodeTextNoData_ThrowsArgumentException(TextDataFormat textDataFormat, short cfFormat)
{
DataObject dataObject = new();
dataObject.SetText("text", textDataFormat);
IComDataObject iComDataObject = dataObject;
FORMATETC formatetc = new()
{
tymed = TYMED.TYMED_HGLOBAL,
cfFormat = cfFormat
};
STGMEDIUM stgMedium = new()
{
tymed = TYMED.TYMED_HGLOBAL
};
((Action)(() => iComDataObject.GetDataHere(ref formatetc, ref stgMedium))).Should().Throw<ArgumentException>();
}
[WinFormsFact]
public unsafe void IComDataObjectGetDataHere_FileNames_Success()
{
DataObject dataObject = new();
dataObject.SetFileDropList(["Path1", "Path2"]);
IComDataObject iComDataObject = dataObject;
FORMATETC formatetc = new()
{
tymed = TYMED.TYMED_HGLOBAL,
cfFormat = (short)CLIPBOARD_FORMAT.CF_HDROP
};
STGMEDIUM stgMedium = new()
{
tymed = TYMED.TYMED_HGLOBAL
};
HGLOBAL handle = PInvokeCore.GlobalAlloc(
GLOBAL_ALLOC_FLAGS.GMEM_MOVEABLE | GLOBAL_ALLOC_FLAGS.GMEM_ZEROINIT,
1);
try
{
stgMedium.unionmember = handle;
iComDataObject.GetDataHere(ref formatetc, ref stgMedium);
DROPFILES* pDropFiles = *(DROPFILES**)stgMedium.unionmember;
pDropFiles->pFiles.Should().Be(20u);
pDropFiles->pt.Should().Be(Point.Empty);
pDropFiles->fNC.Should().Be(BOOL.FALSE);
pDropFiles->fWide.Should().Be(BOOL.TRUE);
char* text = (char*)IntPtr.Add((IntPtr)pDropFiles, (int)pDropFiles->pFiles);
new string(text, 0, "Path1".Length + 1 + "Path2".Length + 1 + 1).Should().Be("Path1\0Path2\0\0");
}
finally
{
PInvokeCore.GlobalFree(handle);
}
}
[WinFormsFact]
public unsafe void IComDataObjectGetDataHere_EmptyFileNames_Success()
{
DataObject dataObject = new();
dataObject.SetFileDropList([]);
IComDataObject iComDataObject = dataObject;
FORMATETC formatetc = new()
{
tymed = TYMED.TYMED_HGLOBAL,
cfFormat = (short)CLIPBOARD_FORMAT.CF_HDROP
};
STGMEDIUM stgMedium = new()
{
tymed = TYMED.TYMED_HGLOBAL
};
HGLOBAL handle = PInvokeCore.GlobalAlloc(
GLOBAL_ALLOC_FLAGS.GMEM_MOVEABLE | GLOBAL_ALLOC_FLAGS.GMEM_ZEROINIT,
(uint)sizeof(DROPFILES));
try
{
stgMedium.unionmember = handle;
iComDataObject.GetDataHere(ref formatetc, ref stgMedium);
DROPFILES* pDropFiles = *(DROPFILES**)stgMedium.unionmember;
pDropFiles->pFiles.Should().Be(0u);
pDropFiles->pt.Should().Be(Point.Empty);
pDropFiles->fNC.Should().Be(BOOL.FALSE);
pDropFiles->fWide.Should().Be(BOOL.FALSE);
}
finally
{
PInvokeCore.GlobalFree(handle);
}
}
[WinFormsFact]
public unsafe void IComDataObjectGetDataHere_FileNamesNoData_ThrowsArgumentException()
{
DataObject dataObject = new();
dataObject.SetFileDropList(["Path1", "Path2"]);
IComDataObject iComDataObject = dataObject;
FORMATETC formatetc = new()
{
tymed = TYMED.TYMED_HGLOBAL,
cfFormat = (short)CLIPBOARD_FORMAT.CF_HDROP
};
STGMEDIUM stgMedium = new()
{
tymed = TYMED.TYMED_HGLOBAL
};
((Action)(() => iComDataObject.GetDataHere(ref formatetc, ref stgMedium))).Should().Throw<ArgumentException>();
}
[WinFormsFact]
public unsafe void IComDataObjectGetDataHere_EmptyFileNamesNoData_Success()
{
DataObject dataObject = new();
dataObject.SetFileDropList([]);
IComDataObject iComDataObject = dataObject;
FORMATETC formatetc = new()
{
tymed = TYMED.TYMED_HGLOBAL,
cfFormat = (short)CLIPBOARD_FORMAT.CF_HDROP
};
STGMEDIUM stgMedium = new()
{
tymed = TYMED.TYMED_HGLOBAL
};
iComDataObject.GetDataHere(ref formatetc, ref stgMedium);
}
[WinFormsTheory]
[InlineData(TYMED.TYMED_FILE, TYMED.TYMED_FILE)]
[InlineData(TYMED.TYMED_ISTORAGE, TYMED.TYMED_ISTORAGE)]
[InlineData(TYMED.TYMED_MFPICT, TYMED.TYMED_MFPICT)]
[InlineData(TYMED.TYMED_ENHMF, TYMED.TYMED_ENHMF)]
[InlineData(TYMED.TYMED_NULL, TYMED.TYMED_NULL)]
public void IComDataObjectGetDataHere_InvalidTymed_ThrowsCOMException(TYMED formatetcTymed, TYMED stgMediumTymed)
{
DataObject dataObject = new();
IComDataObject iComDataObject = dataObject;
FORMATETC formatetc = new()
{
tymed = formatetcTymed
};
STGMEDIUM stgMedium = new()
{
tymed = stgMediumTymed
};
((Action)(() => iComDataObject.GetDataHere(ref formatetc, ref stgMedium))).Should().Throw<COMException>()
.Where(e => e.HResult == HRESULT.DV_E_TYMED);
}
[WinFormsTheory]
[InlineData(TYMED.TYMED_HGLOBAL, TYMED.TYMED_HGLOBAL, (short)CLIPBOARD_FORMAT.CF_UNICODETEXT)]
[InlineData(TYMED.TYMED_HGLOBAL, TYMED.TYMED_HGLOBAL, (short)CLIPBOARD_FORMAT.CF_HDROP)]
[InlineData(TYMED.TYMED_ISTREAM, TYMED.TYMED_ISTREAM, (short)CLIPBOARD_FORMAT.CF_UNICODETEXT)]
[InlineData(TYMED.TYMED_ISTREAM, TYMED.TYMED_ISTREAM, (short)CLIPBOARD_FORMAT.CF_HDROP)]
[InlineData(TYMED.TYMED_GDI, TYMED.TYMED_GDI, (short)CLIPBOARD_FORMAT.CF_UNICODETEXT)]
[InlineData(TYMED.TYMED_GDI, TYMED.TYMED_GDI, (short)CLIPBOARD_FORMAT.CF_HDROP)]
public void IComDataObjectGetDataHere_NoDataPresentNoData_ThrowsCOMException(TYMED formatetcTymed, TYMED stgMediumTymed, short cfFormat)
{
DataObject dataObject = new();
IComDataObject iComDataObject = dataObject;
FORMATETC formatetc = new()
{
tymed = formatetcTymed,
cfFormat = cfFormat
};
STGMEDIUM stgMedium = new()
{
tymed = stgMediumTymed
};
((Action)(() => iComDataObject.GetDataHere(ref formatetc, ref stgMedium))).Should().Throw<COMException>()
.Where(e => e.HResult == HRESULT.DV_E_FORMATETC);
}
private class DerivedDataObject : DataObject { }
private class CustomDataObject : IComDataObject, IDataObject
{
public int DAdvise(ref FORMATETC pFormatetc, ADVF advf, IAdviseSink adviseSink, out int connection) => throw new NotImplementedException();
public void DUnadvise(int connection) => throw new NotImplementedException();
public int EnumDAdvise(out IEnumSTATDATA enumAdvise) => throw new NotImplementedException();
public IEnumFORMATETC EnumFormatEtc(DATADIR direction) => throw new NotImplementedException();
public int GetCanonicalFormatEtc(ref FORMATETC formatIn, out FORMATETC formatOut) => throw new NotImplementedException();
public void GetData(ref FORMATETC format, out STGMEDIUM medium) => throw new NotImplementedException();
public object GetData(string format, bool autoConvert) => throw new NotImplementedException();
public object GetData(string format) => throw new NotImplementedException();
public object GetData(Type format) => throw new NotImplementedException();
public void GetDataHere(ref FORMATETC format, ref STGMEDIUM medium) => throw new NotImplementedException();
public bool GetDataPresent(string format, bool autoConvert) => throw new NotImplementedException();
public bool GetDataPresent(string format) => throw new NotImplementedException();
public bool GetDataPresent(Type format) => throw new NotImplementedException();
public string[] GetFormats(bool autoConvert) => throw new NotImplementedException();
public string[] GetFormats() => throw new NotImplementedException();
public int QueryGetData(ref FORMATETC format) => throw new NotImplementedException();
public void SetData(ref FORMATETC formatIn, ref STGMEDIUM medium, bool release) => throw new NotImplementedException();
public void SetData(string format, bool autoConvert, object data) => throw new NotImplementedException();
public void SetData(string format, object data) => throw new NotImplementedException();
public void SetData(Type format, object data) => throw new NotImplementedException();
public void SetData(object data) => throw new NotImplementedException();
}
public static IEnumerable<object[]> DataObjectMockRoundTripData()
{
yield return new object[] { new DataObject() };
yield return new object[] { new DerivedDataObject() };
yield return new object[] { new CustomDataObject() };
}
[WinFormsTheory]
[MemberData(nameof(DataObjectMockRoundTripData))]
public unsafe void DataObject_MockRoundTrip_OutData_IsSame(object data)
{
dynamic controlAccessor = typeof(Control).TestAccessor().Dynamic;
var dropTargetAccessor = typeof(DropTarget).TestAccessor();
IComDataObject inData = controlAccessor.CreateRuntimeDataObjectForDrag(data);
if (data is DataObject)
{
inData.Should().BeSameAs(data);
}
else
{
inData.Should().NotBeSameAs(data);
}
using var inDataPtr = ComHelpers.GetComScope<Com.IDataObject>(inData);
IDataObject outData = dropTargetAccessor.CreateDelegate<CreateWinFormsDataObjectForOutgoingDropData>()(inDataPtr);
outData.Should().BeSameAs(data);
}
[WinFormsFact]
public unsafe void DataObject_StringData_MockRoundTrip_IsWrapped()
{
string testString = "Test";
dynamic accessor = typeof(Control).TestAccessor().Dynamic;
var dropTargetAccessor = typeof(DropTarget).TestAccessor();
IComDataObject inData = accessor.CreateRuntimeDataObjectForDrag(testString);
inData.Should().BeAssignableTo<DataObject>();
using var inDataPtr = ComHelpers.GetComScope<Com.IDataObject>(inData);
IDataObject outData = dropTargetAccessor.CreateDelegate<CreateWinFormsDataObjectForOutgoingDropData>()(inDataPtr);
outData.Should().BeSameAs(inData);
outData.GetData(typeof(string)).Should().Be(testString);
}
[WinFormsFact]
public unsafe void DataObject_IDataObject_MockRoundTrip_IsWrapped()
{
CustomIDataObject data = new();
dynamic accessor = typeof(Control).TestAccessor().Dynamic;
var dropTargetAccessor = typeof(DropTarget).TestAccessor();
IComDataObject inData = accessor.CreateRuntimeDataObjectForDrag(data);
inData.Should().BeAssignableTo<DataObject>();
inData.Should().NotBeSameAs(data);
using var inDataPtr = ComHelpers.GetComScope<Com.IDataObject>(inData);
IDataObject outData = dropTargetAccessor.CreateDelegate<CreateWinFormsDataObjectForOutgoingDropData>()(inDataPtr);
outData.Should().BeSameAs(data);
}
[WinFormsFact]
public unsafe void DataObject_ComTypesIDataObject_MockRoundTrip_IsWrapped()
{
CustomComTypesDataObject data = new();
dynamic accessor = typeof(Control).TestAccessor().Dynamic;
var dropTargetAccessor = typeof(DropTarget).TestAccessor();
IComDataObject inData = accessor.CreateRuntimeDataObjectForDrag(data);
inData.Should().NotBeSameAs(data);
inData.Should().BeAssignableTo<DataObject>();
using var inDataPtr = ComHelpers.GetComScope<Com.IDataObject>(inData);
IDataObject outData = dropTargetAccessor.CreateDelegate<CreateWinFormsDataObjectForOutgoingDropData>()(inDataPtr);
outData.Should().BeSameAs(inData);
}
[WinFormsFact]
public unsafe void DataObject_Native_GetFormats_ReturnsExpected()
{
DataObject native = new();
using Bitmap bitmap = new(10, 10);
native.SetImage(bitmap);
string customFormat = "customFormat";
native.SetData(customFormat, "custom");
// Simulate receiving DataObject from native.
DataObject data = new(ComHelpers.GetComPointer<Com.IDataObject>(native));
data.GetDataPresent(typeof(Bitmap)).Should().BeTrue();
data.GetDataPresent(customFormat).Should().BeTrue();
data.GetDataPresent("notExist").Should().BeFalse();
data.GetFormats().Should().BeEquivalentTo([typeof(Bitmap).FullName, nameof(Bitmap), customFormat]);
}
}
|