Skip to content

Commit

Permalink
Sealed the internal DataStore class, and some minor clean-up (dotnet#…
Browse files Browse the repository at this point in the history
…12503)

* Seal the internal DataStore, and some minor clean-up
* Run test that sets HighDpiMode in a separate process using RemoteExecutor
  • Loading branch information
Tanya-Solyanik authored Nov 18, 2024
1 parent ddfbcd1 commit abad7ec
Show file tree
Hide file tree
Showing 21 changed files with 167 additions and 164 deletions.
1 change: 1 addition & 0 deletions Winforms.sln
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "documentation", "documentat
docs\developer-guide.md = docs\developer-guide.md
docs\getting-started.md = docs\getting-started.md
docs\issue-guide.md = docs\issue-guide.md
docs\list-of-diagnostics.md = docs\list-of-diagnostics.md
docs\porting-guidelines.md = docs\porting-guidelines.md
README.md = README.md
docs\roadmap.md = docs\roadmap.md
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -776,7 +776,7 @@ Namespace Microsoft.VisualBasic.ApplicationServices
If dpiSetResult Then
_highDpiMode = Application.HighDpiMode
End If
Debug.Assert(dpiSetResult, "We could net set the HighDpiMode.")
Debug.Assert(dpiSetResult, "We could not set the HighDpiMode.")

' Now, let's set VisualStyles and ColorMode:
If _enableVisualStyles Then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
Imports System.ComponentModel
Imports System.Windows.Forms
Imports FluentAssertions
Imports Microsoft.DotNet.RemoteExecutor
Imports Microsoft.VisualBasic.ApplicationServices
Imports Xunit

Expand Down Expand Up @@ -89,17 +90,27 @@ Namespace Microsoft.VisualBasic.Forms.Tests
End Using
End Sub

<Fact>
Public Sub Run_DoEvents()
Public Sub DoEvents_DoesNotThrow()
Dim testCode As Action = Sub() DoEvents()
testCode.Should.NotThrow()
End Sub

<Fact>
Public Sub Run_SingleInstanceNoStartupFormException()
IsSingleInstance = True
Dim testCode As Action = Sub() Run(commandLine:={"1"})
testCode.Should.Throw(Of NoStartupFormException)()
Public Sub Run_SingleInstance_ThrowsNoStartupFormException()
' WindowsFormsApplicationBase.Run method can change process-wide settings, such as HighDpiMode,
' it should run in a dedicated process.
If (RemoteExecutor.IsSupported) Then
Dim test As Action =
Sub()
IsSingleInstance = True
Dim testCode As Action = Sub() Run(commandLine:={"1"})
testCode.Should.Throw(Of NoStartupFormException)()
End Sub

Using handle As RemoteInvokeHandle = RemoteExecutor.Invoke(test)
handle.ExitCode.Should.Be(RemoteExecutor.SuccessExitCode)
End Using
End If
End Sub

<Fact>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@

namespace Microsoft.VisualBasic.Devices.Tests;

[Collection("Sequential")]
[CollectionDefinition("Sequential", DisableParallelization = true)]
[UISettings(MaxAttempts = 3)] // Try up to 3 times before failing.
public class ComputerTests
{
[Fact]
// This test does not modify the system clipboard state, do not move it into the
// sequential collection, it is safe to run in parallel with other tests in this assembly.
public void Properties()
{
Computer computer = new();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,8 @@ public void BinaryFormatWriter_TryWriteDrawingPrimitivesObject_UnsupportedObject
stream.Position.Should().Be(0);
}

public static IEnumerable<object[]?> TryWriteFrameworkObject_SupportedObjects_TestData =>
((IEnumerable<object[]?>)HashtableTests.Hashtables_TestData).Concat(
public static IEnumerable<object[]> TryWriteFrameworkObject_SupportedObjects_TestData =>
((IEnumerable<object[]>)HashtableTests.Hashtables_TestData).Concat(
ListTests.PrimitiveLists_TestData).Concat(
ListTests.ArrayLists_TestData).Concat(
PrimitiveTypeTests.Primitive_Data).Concat(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace System.Windows.Forms.Nrbf.Tests;

public class SerializationRecordExtensionsTests
{
public static IEnumerable<object[]?> TryGetFrameworkObject_SupportedObjects_TestData =>
public static IEnumerable<object[]> TryGetFrameworkObject_SupportedObjects_TestData =>
BinaryFormatWriterTests.TryWriteFrameworkObject_SupportedObjects_TestData;

[Theory]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ public string Name
}
set
{
ArgumentException.ThrowIfNullOrEmpty(value, nameof(Name));
ArgumentException.ThrowIfNullOrEmpty(value);
_name = value;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,10 @@ DataFormats.TextConstant or DataFormats.RtfConstant or DataFormats.OemTextConsta

static object ReadObjectFromHGLOBAL(HGLOBAL hglobal, bool restrictDeserialization)
{
MemoryStream stream = ReadByteStreamFromHGLOBAL(hglobal, out bool isSerializedObject);
return !isSerializedObject ? stream : BinaryFormatUtilities.ReadObjectFromStream(stream, restrictDeserialization);
MemoryStream stream = ReadByteStreamFromHGLOBAL(hglobal, out bool isSerializedObject);
return !isSerializedObject
? stream
: BinaryFormatUtilities.ReadObjectFromStream(stream, restrictDeserialization);
}
}

Expand All @@ -132,7 +134,7 @@ private static unsafe MemoryStream ReadByteStreamFromHGLOBAL(HGLOBAL hglobal, ou
int index = 0;

// The object here can either be a stream or a serialized object. We identify a serialized object
// by writing the bytes for the guid serializedObjectID at the front of the stream.
// by writing the bytes for the GUID serializedObjectID at the front of the stream.

if (isSerializedObject = bytes.AsSpan().StartsWith(s_serializedObjectID))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ public WinFormsToNativeAdapter(IDataObject dataObject)
}

/// <summary>
/// Returns true if the tymed is useable.
/// Returns true if the tymed is usable.
/// </summary>
private static bool GetTymedUseable(TYMED tymed) => (tymed & AllowedTymeds) != 0;
private static bool GetTymedUsable(TYMED tymed) => (tymed & AllowedTymeds) != 0;

HRESULT Com.IDataObject.Interface.GetData(FORMATETC* pformatetcIn, STGMEDIUM* pmedium)
{
Expand Down Expand Up @@ -63,7 +63,7 @@ HRESULT Com.IDataObject.Interface.GetData(FORMATETC* pformatetcIn, STGMEDIUM* pm

*pmedium = default;

if (!GetTymedUseable((TYMED)pformatetcIn->tymed))
if (!GetTymedUsable((TYMED)pformatetcIn->tymed))
{
return HRESULT.DV_E_TYMED;
}
Expand Down Expand Up @@ -104,7 +104,7 @@ HRESULT Com.IDataObject.Interface.GetDataHere(FORMATETC* pformatetc, STGMEDIUM*
return HRESULT.E_POINTER;
}

if (!GetTymedUseable((TYMED)pformatetc->tymed) || !GetTymedUseable(pmedium->tymed))
if (!GetTymedUsable((TYMED)pformatetc->tymed) || !GetTymedUsable(pmedium->tymed))
{
return HRESULT.DV_E_TYMED;
}
Expand Down Expand Up @@ -191,7 +191,7 @@ HRESULT Com.IDataObject.Interface.QueryGetData(FORMATETC* pformatetc)
return HRESULT.DV_E_DVASPECT;
}

if (!GetTymedUseable((TYMED)pformatetc->tymed))
if (!GetTymedUsable((TYMED)pformatetc->tymed))
{
return HRESULT.DV_E_TYMED;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,18 +104,18 @@ or DataFormats.PaletteConstant
or DataFormats.WmfConstant;

#region IDataObject
object? IDataObject.GetData(string format, bool autoConvert) => _winFormsDataObject.GetData(format, autoConvert);
object? IDataObject.GetData(string format) => _winFormsDataObject.GetData(format);
object? IDataObject.GetData(Type format) => _winFormsDataObject.GetData(format);
bool IDataObject.GetDataPresent(string format, bool autoConvert) => _winFormsDataObject.GetDataPresent(format, autoConvert);
bool IDataObject.GetDataPresent(string format) => _winFormsDataObject.GetDataPresent(format);
bool IDataObject.GetDataPresent(Type format) => _winFormsDataObject.GetDataPresent(format);
string[] IDataObject.GetFormats(bool autoConvert) => _winFormsDataObject.GetFormats(autoConvert);
string[] IDataObject.GetFormats() => _winFormsDataObject.GetFormats();
void IDataObject.SetData(string format, bool autoConvert, object? data) => _winFormsDataObject.SetData(format, autoConvert, data);
void IDataObject.SetData(string format, object? data) => _winFormsDataObject.SetData(format, data);
void IDataObject.SetData(Type format, object? data) => _winFormsDataObject.SetData(format, data);
void IDataObject.SetData(object? data) => _winFormsDataObject.SetData(data);
public object? GetData(string format, bool autoConvert) => _winFormsDataObject.GetData(format, autoConvert);
public object? GetData(string format) => _winFormsDataObject.GetData(format);
public object? GetData(Type format) => _winFormsDataObject.GetData(format);
public bool GetDataPresent(string format, bool autoConvert) => _winFormsDataObject.GetDataPresent(format, autoConvert);
public bool GetDataPresent(string format) => _winFormsDataObject.GetDataPresent(format);
public bool GetDataPresent(Type format) => _winFormsDataObject.GetDataPresent(format);
public string[] GetFormats(bool autoConvert) => _winFormsDataObject.GetFormats(autoConvert);
public string[] GetFormats() => _winFormsDataObject.GetFormats();
public void SetData(string format, bool autoConvert, object? data) => _winFormsDataObject.SetData(format, autoConvert, data);
public void SetData(string format, object? data) => _winFormsDataObject.SetData(format, data);
public void SetData(Type format, object? data) => _winFormsDataObject.SetData(format, data);
public void SetData(object? data) => _winFormsDataObject.SetData(data);
#endregion

#region Com.IDataObject.Interface
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Windows.Forms;

public partial class DataObject
{
private sealed partial class DataStore
{
private class DataStoreEntry
{
public object? Data { get; }
public bool AutoConvert { get; }

public DataStoreEntry(object? data, bool autoConvert)
{
Data = data;
AutoConvert = autoConvert;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,19 @@ namespace System.Windows.Forms;

public partial class DataObject
{
private class DataStore : IDataObject
private sealed partial class DataStore : IDataObject
{
private class DataStoreEntry
{
public object? Data { get; }
public bool AutoConvert { get; }

public DataStoreEntry(object? data, bool autoConvert)
{
Data = data;
AutoConvert = autoConvert;
}
}

private readonly Dictionary<string, DataStoreEntry> _data = new(BackCompatibleStringComparer.Default);
private readonly Dictionary<string, DataStoreEntry> _mappedData = new(BackCompatibleStringComparer.Default);

public DataStore()
{
}

public virtual object? GetData(string format, bool autoConvert)
public object? GetData(string format, bool autoConvert)
{
if (string.IsNullOrWhiteSpace(format))
{
return null;
}

object? baseVar = null;
if (_data.TryGetValue(format, out DataStoreEntry? dse))
if (_mappedData.TryGetValue(format, out DataStoreEntry? dse))
{
baseVar = dse.Data;
}
Expand All @@ -55,7 +39,7 @@ public DataStore()
{
if (!format.Equals(mappedFormats[i]))
{
if (_data.TryGetValue(mappedFormats[i], out DataStoreEntry? found))
if (_mappedData.TryGetValue(mappedFormats[i], out DataStoreEntry? found))
{
baseVar = found.Data;
}
Expand All @@ -73,11 +57,11 @@ public DataStore()
return original ?? baseVar;
}

public virtual object? GetData(string format) => GetData(format, autoConvert: true);
public object? GetData(string format) => GetData(format, autoConvert: true);

public virtual object? GetData(Type format) => GetData(format.FullName!);
public object? GetData(Type format) => GetData(format.FullName!);

public virtual void SetData(string format, bool autoConvert, object? data)
public void SetData(string format, bool autoConvert, object? data)
{
if (string.IsNullOrWhiteSpace(format))
{
Expand All @@ -100,36 +84,33 @@ public virtual void SetData(string format, bool autoConvert, object? data)
}
}

_data[format] = new DataStoreEntry(data, autoConvert);
_mappedData[format] = new DataStoreEntry(data, autoConvert);
}

public virtual void SetData(string format, object? data) => SetData(format, autoConvert: true, data);
public void SetData(string format, object? data) => SetData(format, autoConvert: true, data);

public virtual void SetData(Type format, object? data)
public void SetData(Type format, object? data)
{
ArgumentNullException.ThrowIfNull(format);
SetData(format.FullName!, data);
}

public virtual void SetData(object? data)
public void SetData(object? data)
{
ArgumentNullException.ThrowIfNull(data);

if (data is ISerializable
&& !_data.ContainsKey(DataFormats.Serializable))
&& !_mappedData.ContainsKey(DataFormats.Serializable))
{
SetData(DataFormats.Serializable, data);
}

SetData(data.GetType(), data);
}

public virtual bool GetDataPresent(Type format)
{
return GetDataPresent(format.FullName!);
}
public bool GetDataPresent(Type format) => GetDataPresent(format.FullName!);

public virtual bool GetDataPresent(string format, bool autoConvert)
public bool GetDataPresent(string format, bool autoConvert)
{
if (string.IsNullOrWhiteSpace(format))
{
Expand All @@ -138,8 +119,8 @@ public virtual bool GetDataPresent(string format, bool autoConvert)

if (!autoConvert)
{
Debug.Assert(_data is not null, "data must be non-null");
return _data.ContainsKey(format);
Debug.Assert(_mappedData is not null, "data must be non-null");
return _mappedData.ContainsKey(format);
}
else
{
Expand All @@ -159,15 +140,15 @@ public virtual bool GetDataPresent(string format, bool autoConvert)
}
}

public virtual bool GetDataPresent(string format) => GetDataPresent(format, autoConvert: true);
public bool GetDataPresent(string format) => GetDataPresent(format, autoConvert: true);

public virtual string[] GetFormats(bool autoConvert)
public string[] GetFormats(bool autoConvert)
{
Debug.Assert(_data is not null, "data collection can't be null");
Debug.Assert(_data.Keys is not null, "data Keys collection can't be null");
Debug.Assert(_mappedData is not null, "data collection can't be null");
Debug.Assert(_mappedData.Keys is not null, "data Keys collection can't be null");

string[] baseVar = new string[_data.Keys.Count];
_data.Keys.CopyTo(baseVar, 0);
string[] baseVar = new string[_mappedData.Keys.Count];
_mappedData.Keys.CopyTo(baseVar, 0);
Debug.Assert(baseVar is not null, "Collections should never return NULL arrays!!!");

if (autoConvert)
Expand All @@ -177,8 +158,8 @@ public virtual string[] GetFormats(bool autoConvert)
HashSet<string> distinctFormats = new(baseVarLength);
for (int i = 0; i < baseVarLength; i++)
{
Debug.Assert(_data[baseVar[i]] is not null, $"Null item in data collection with key '{baseVar[i]}'");
if (_data[baseVar[i]]!.AutoConvert)
Debug.Assert(_mappedData[baseVar[i]] is not null, $"Null item in data collection with key '{baseVar[i]}'");
if (_mappedData[baseVar[i]]!.AutoConvert)
{
string[] cur = GetMappedFormats(baseVar[i])!;
Debug.Assert(cur is not null, $"GetMappedFormats returned null for '{baseVar[i]}'");
Expand All @@ -199,6 +180,6 @@ public virtual string[] GetFormats(bool autoConvert)
return baseVar;
}

public virtual string[] GetFormats() => GetFormats(autoConvert: true);
public string[] GetFormats() => GetFormats(autoConvert: true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public DragDropFormat(ushort format, STGMEDIUM medium, bool copyData)
}

/// <summary>
/// Returns a copy of the storage mediumn in this instance.
/// Returns a copy of the storage medium in this instance.
/// </summary>
public STGMEDIUM GetData() => CopyData(_format, _medium);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@

namespace System.Windows.Forms.Tests;

[Collection("Sequential")] // Each registered Clipboard format is an OS singleton,
// and we should not run this test at the same time as other tests using the same format.
// Each registered Clipboard format is an OS singleton,
// and we should not run this test at the same time as other tests using the same format.
[Collection("Sequential")]
[UISettings(MaxAttempts = 3)] // Try up to 3 times before failing.
public class ClipboardComTests
{
Expand Down
Loading

0 comments on commit abad7ec

Please sign in to comment.