Browse Source

Add initial interop testing framework (#1932)

pull/3657/head
Hugh Bellamy 5 years ago
committed by GitHub
parent
commit
3bae4e6b03
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 15
      Winforms.sln
  2. 3
      eng/configure-toolset.ps1
  3. 2
      global.json
  4. 4
      src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.IOleClientSite.cs
  5. 2
      src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.IOleControlSite.cs
  6. 15
      src/System.Windows.Forms/src/System/Windows/Forms/AxHost.OleInterfaces.cs
  7. 5
      src/System.Windows.Forms/src/System/Windows/Forms/Control.AxSourcingSite.cs
  8. 16
      src/System.Windows.Forms/src/System/Windows/Forms/WebBrowserSiteBase.cs
  9. 22
      src/System.Windows.Forms/tests/InteropTests/InteropTestBase.cs
  10. 10
      src/System.Windows.Forms/tests/InteropTests/NativeTests/CMakeLists.txt
  11. 5
      src/System.Windows.Forms/tests/InteropTests/NativeTests/NativeTests.proj
  12. 635
      src/System.Windows.Forms/tests/InteropTests/NativeTests/WebBrowserSiteBaseInteropTests.cpp
  13. 158
      src/System.Windows.Forms/tests/InteropTests/NativeTests/testhelpers.h
  14. 24
      src/System.Windows.Forms/tests/InteropTests/System.Windows.Forms.Interop.Tests.csproj
  15. 28
      src/System.Windows.Forms/tests/InteropTests/WebBrowserSiteBaseInteropTests.cs

15
Winforms.sln

@ -135,6 +135,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Windows.Forms.TestUt
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiToolStripTests", "src\System.Windows.Forms\tests\IntegrationTests\MauiTests\MauiToolStripTests\MauiToolStripTests.csproj", "{83634671-CF3A-43B0-B729-42CCBA62DF2C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Windows.Forms.Interop.Tests", "src\System.Windows.Forms\tests\InteropTests\System.Windows.Forms.Interop.Tests.csproj", "{C272DA06-B98D-4BB7-B1C4-ECF58F54B224}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -277,6 +279,18 @@ Global
{83634671-CF3A-43B0-B729-42CCBA62DF2C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{83634671-CF3A-43B0-B729-42CCBA62DF2C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{83634671-CF3A-43B0-B729-42CCBA62DF2C}.Release|Any CPU.Build.0 = Release|Any CPU
{C272DA06-B98D-4BB7-B1C4-ECF58F54B224}.Debug|Any CPU.ActiveCfg = Debug|x86
{C272DA06-B98D-4BB7-B1C4-ECF58F54B224}.Debug|Any CPU.Build.0 = Debug|x86
{C272DA06-B98D-4BB7-B1C4-ECF58F54B224}.Release|Any CPU.ActiveCfg = Release|x86
{C272DA06-B98D-4BB7-B1C4-ECF58F54B224}.Release|Any CPU.Build.0 = Release|x86
{C272DA06-B98D-4BB7-B1C4-ECF58F54B224}.Debug|x86.ActiveCfg = Debug|x86
{C272DA06-B98D-4BB7-B1C4-ECF58F54B224}.Debug|x86.Build.0 = Debug|x86
{C272DA06-B98D-4BB7-B1C4-ECF58F54B224}.Release|x86.ActiveCfg = Release|x86
{C272DA06-B98D-4BB7-B1C4-ECF58F54B224}.Release|x86.Build.0 = Release|x86
{C272DA06-B98D-4BB7-B1C4-ECF58F54B224}.Debug|x64.ActiveCfg = Debug|x64
{C272DA06-B98D-4BB7-B1C4-ECF58F54B224}.Debug|x64.Build.0 = Debug|x64
{C272DA06-B98D-4BB7-B1C4-ECF58F54B224}.Release|x64.ActiveCfg = Release|x64
{C272DA06-B98D-4BB7-B1C4-ECF58F54B224}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -321,6 +335,7 @@ Global
{73B0857A-966B-4E7D-8A83-FECFE0281AB9} = {DF68A171-D27B-4E6A-8A7E-63A651622355}
{86418F0B-39DC-4B5A-8145-6D607E6150AC} = {DF68A171-D27B-4E6A-8A7E-63A651622355}
{83634671-CF3A-43B0-B729-42CCBA62DF2C} = {8F20A905-BD37-4D80-B8DF-FA45276FC23F}
{C272DA06-B98D-4BB7-B1C4-ECF58F54B224} = {583F1292-AE8D-4511-B8D8-A81FE4642DDC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7B1B0433-F612-4E5A-BE7E-FCF5B9F6E136}

3
eng/configure-toolset.ps1

@ -1,2 +1,5 @@
$script:DoNotAbortNativeToolsInstallationOnFailure = $true
$script:DoNotDisplayNativeToolsInstallationWarnings = $true
# Add CMake to path.
$env:PATH = "$PSScriptRoot\..\.tools\bin;$env:PATH"

2
global.json

@ -21,7 +21,7 @@
"Microsoft.NET.Sdk.IL": "5.0.0-rc.1.20371.13"
},
"native-tools": {
"cmake": "3.14.2",
"cmake": "3.17.3",
"dotnet-api-docs_netcoreapp3.0": "0.0.0.1"
}
}

4
src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.IOleClientSite.cs

@ -23,9 +23,7 @@ internal partial class Interop
Ole32.OLEWHICHMK dwWhichMoniker,
IntPtr* ppmk);
[PreserveSig]
HRESULT GetContainer(
out IOleContainer container);
IOleContainer GetContainer();
[PreserveSig]
HRESULT ShowObject();

2
src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.IOleControlSite.cs

@ -24,7 +24,7 @@ internal partial class Interop
[PreserveSig]
HRESULT GetExtendedControl(
[MarshalAs(UnmanagedType.IDispatch)] out object ppDisp);
IntPtr* ppDisp);
[PreserveSig]
HRESULT TransformCoords(

15
src/System.Windows.Forms/src/System/Windows/Forms/AxHost.OleInterfaces.cs

@ -250,15 +250,21 @@ namespace System.Windows.Forms
return HRESULT.E_NOTIMPL;
}
HRESULT IOleControlSite.GetExtendedControl(out object ppDisp)
unsafe HRESULT IOleControlSite.GetExtendedControl(IntPtr* ppDisp)
{
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in GetExtendedControl " + host.ToString());
ppDisp = host.GetParentContainer().GetProxyForControl(host);
if (ppDisp == null)
{
return HRESULT.E_POINTER;
}
object proxy = host.GetParentContainer().GetProxyForControl(host);
if (proxy == null)
{
return HRESULT.E_NOTIMPL;
}
*ppDisp = Marshal.GetIDispatchForObject(proxy);
return HRESULT.S_OK;
}
@ -374,11 +380,10 @@ namespace System.Windows.Forms
return HRESULT.E_NOTIMPL;
}
HRESULT IOleClientSite.GetContainer(out IOleContainer container)
IOleContainer IOleClientSite.GetContainer()
{
Debug.WriteLineIf(AxHTraceSwitch.TraceVerbose, "in getContainer");
container = host.GetParentContainer();
return HRESULT.S_OK;
return host.GetParentContainer();
}
unsafe HRESULT IOleClientSite.ShowObject()

5
src/System.Windows.Forms/src/System/Windows/Forms/Control.AxSourcingSite.cs

@ -38,11 +38,10 @@ namespace System.Windows.Forms
{
if (service == typeof(HtmlDocument))
{
HRESULT hr = _clientSite.GetContainer(out Ole32.IOleContainer iOlecontainer);
if (hr.Succeeded() && iOlecontainer is Mshtml.IHTMLDocument)
if (_clientSite.GetContainer() is Mshtml.IHTMLDocument document)
{
_shimManager ??= new HtmlShimManager();
return new HtmlDocument(_shimManager, iOlecontainer as Mshtml.IHTMLDocument);
return new HtmlDocument(_shimManager, document);
}
}
else if (_clientSite.GetType().IsAssignableFrom(service))

16
src/System.Windows.Forms/src/System/Windows/Forms/WebBrowserSiteBase.cs

@ -88,9 +88,14 @@ namespace System.Windows.Forms
return HRESULT.E_NOTIMPL;
}
HRESULT IOleControlSite.GetExtendedControl(out object ppDisp)
unsafe HRESULT IOleControlSite.GetExtendedControl(IntPtr* ppDisp)
{
ppDisp = null;
if (ppDisp == null)
{
return HRESULT.E_POINTER;
}
*ppDisp = IntPtr.Zero;
return HRESULT.E_NOTIMPL;
}
@ -98,7 +103,7 @@ namespace System.Windows.Forms
{
if (pPtlHimetric == null || pPtfContainer == null)
{
return HRESULT.E_INVALIDARG;
return HRESULT.E_POINTER;
}
if ((dwFlags & XFORMCOORDS.HIMETRICTOCONTAINER) != 0)
@ -183,10 +188,9 @@ namespace System.Windows.Forms
return HRESULT.E_NOTIMPL;
}
HRESULT IOleClientSite.GetContainer(out IOleContainer container)
IOleContainer IOleClientSite.GetContainer()
{
container = Host.GetParentContainer();
return HRESULT.S_OK;
return Host.GetParentContainer();
}
unsafe HRESULT IOleClientSite.ShowObject()

22
src/System.Windows.Forms/tests/InteropTests/InteropTestBase.cs

@ -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.
// See the LICENSE file in the project root for more information.
using Xunit.Sdk;
namespace System.Windows.Forms.InteropTests
{
public abstract class InteropTestBase
{
public const string NativeTests = "NativeTests";
public const string Success = "Success";
protected static void AssertSuccess(string result)
{
if (result != Success)
{
throw new XunitException(result);
}
}
}
}

10
src/System.Windows.Forms/tests/InteropTests/NativeTests/CMakeLists.txt

@ -0,0 +1,10 @@
cmake_minimum_required (VERSION 2.6)
project (NativeTests)
set(CMAKE_MACOSX_RPATH 1)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_library(NativeTests SHARED
WebBrowserSiteBaseInteropTests.cpp
)
install(TARGETS NativeTests)

5
src/System.Windows.Forms/tests/InteropTests/NativeTests/NativeTests.proj

@ -0,0 +1,5 @@
<Project Sdk="Microsoft.DotNet.CMake.Sdk">
<PropertyGroup>
<CMakeLists>CMakeLists.txt</CMakeLists>
</PropertyGroup>
</Project>

635
src/System.Windows.Forms/tests/InteropTests/NativeTests/WebBrowserSiteBaseInteropTests.cpp

@ -0,0 +1,635 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#include "ocidl.h"
#include "testhelpers.h"
#include <sstream>
#include <atlbase.h>
using namespace ATL;
static HRESULT Test_IOleControlSite_OnControlInfoChanged(IOleControlSite* pControlSite, std::wstringstream& output)
{
HRESULT hr;
hr = pControlSite->OnControlInfoChanged();
assertEqualHr(S_OK, hr);
return S_OK;
}
static HRESULT Test_IOleControlSite_LockInPlaceActive(IOleControlSite* pControlSite, std::wstringstream& output)
{
HRESULT hr;
// Negative tests.
hr = pControlSite->LockInPlaceActive(TRUE);
assertEqualHr(E_NOTIMPL, hr);
hr = pControlSite->LockInPlaceActive(TRUE);
assertEqualHr(E_NOTIMPL, hr);
return S_OK;
}
static HRESULT Test_IOleControlSite_GetExtendedControl(IOleControlSite* pControlSite, std::wstringstream& output)
{
HRESULT hr;
IDispatch* pDisp;
pDisp = (IDispatch*)(long)0xdeadbeef;
hr = pControlSite->GetExtendedControl(&pDisp);
assertEqualHr(E_NOTIMPL, hr);
assertNull(pDisp);
// Negative tests.
hr = pControlSite->GetExtendedControl(NULL);
assertEqualHr(E_POINTER, hr);
return S_OK;
}
static HRESULT Test_IOleControlSite_TransformCoords(IOleControlSite* pControlSite, std::wstringstream& output)
{
HRESULT hr;
POINTL ptlHimetric;
POINTF ptfContainer;
// HIMETRICTOCONTAINER, SIZE
ptlHimetric.x = 1000;
ptlHimetric.y = 2000;
ptfContainer.x = 0;
ptfContainer.y = 0;
hr = pControlSite->TransformCoords(&ptlHimetric, &ptfContainer, XFORMCOORDS_HIMETRICTOCONTAINER | XFORMCOORDS_SIZE);
assertEqualHr(S_OK, hr);
assertEqualInt(1000, ptlHimetric.x);
assertEqualInt(2000, ptlHimetric.y);
assertEqualFloat(38, ptfContainer.x);
assertEqualFloat(76, ptfContainer.y);
ptlHimetric.x = 0;
ptlHimetric.y = 0;
ptfContainer.x = -1;
ptfContainer.y = -2;
hr = pControlSite->TransformCoords(&ptlHimetric, &ptfContainer, XFORMCOORDS_HIMETRICTOCONTAINER | XFORMCOORDS_SIZE);
assertEqualHr(S_OK, hr);
assertEqualInt(0, ptlHimetric.x);
assertEqualInt(0, ptlHimetric.y);
assertEqualFloat(0, ptfContainer.x);
assertEqualFloat(0, ptfContainer.y);
// HIMETRICTOCONTAINER, POSITION
ptlHimetric.x = 1000;
ptlHimetric.y = 2000;
ptfContainer.x = 0;
ptfContainer.y = 0;
hr = pControlSite->TransformCoords(&ptlHimetric, &ptfContainer, XFORMCOORDS_HIMETRICTOCONTAINER | XFORMCOORDS_POSITION);
assertEqualHr(S_OK, hr);
assertEqualInt(1000, ptlHimetric.x);
assertEqualInt(2000, ptlHimetric.y);
assertEqualFloat(38, ptfContainer.x);
assertEqualFloat(76, ptfContainer.y);
ptlHimetric.x = 0;
ptlHimetric.y = 0;
ptfContainer.x = 1;
ptfContainer.y = 2;
hr = pControlSite->TransformCoords(&ptlHimetric, &ptfContainer, XFORMCOORDS_HIMETRICTOCONTAINER | XFORMCOORDS_POSITION);
assertEqualHr(S_OK, hr);
assertEqualInt(0, ptlHimetric.x);
assertEqualInt(0, ptlHimetric.y);
assertEqualFloat(0, ptfContainer.x);
assertEqualFloat(0, ptfContainer.y);
// CONTAINERTOHIMETRIC, SIZE
ptlHimetric.x = 0;
ptlHimetric.y = 0;
ptfContainer.x = 38;
ptfContainer.y = 76;
hr = pControlSite->TransformCoords(&ptlHimetric, &ptfContainer, XFORMCOORDS_CONTAINERTOHIMETRIC | XFORMCOORDS_SIZE);
assertEqualHr(S_OK, hr);
assertEqualInt(1005, ptlHimetric.x);
assertEqualInt(2011, ptlHimetric.y);
assertEqualFloat(38, ptfContainer.x);
assertEqualFloat(76, ptfContainer.y);
ptlHimetric.x = 1;
ptlHimetric.y = 2;
ptfContainer.x = 0;
ptfContainer.y = 0;
hr = pControlSite->TransformCoords(&ptlHimetric, &ptfContainer, XFORMCOORDS_CONTAINERTOHIMETRIC | XFORMCOORDS_SIZE);
assertEqualHr(S_OK, hr);
assertEqualInt(0, ptlHimetric.x);
assertEqualInt(0, ptlHimetric.y);
assertEqualFloat(0, ptfContainer.x);
assertEqualFloat(0, ptfContainer.y);
// CONTAINERTOHIMETRIC, POSITION
ptlHimetric.x = 0;
ptlHimetric.y = 0;
ptfContainer.x = 38;
ptfContainer.y = 76;
hr = pControlSite->TransformCoords(&ptlHimetric, &ptfContainer, XFORMCOORDS_CONTAINERTOHIMETRIC | XFORMCOORDS_POSITION);
assertEqualHr(S_OK, hr);
assertEqualInt(1005, ptlHimetric.x);
assertEqualInt(2011, ptlHimetric.y);
assertEqualFloat(38, ptfContainer.x);
assertEqualFloat(76, ptfContainer.y);
ptlHimetric.x = 1;
ptlHimetric.y = 2;
ptfContainer.x = 0;
ptfContainer.y = 0;
hr = pControlSite->TransformCoords(&ptlHimetric, &ptfContainer, XFORMCOORDS_CONTAINERTOHIMETRIC | XFORMCOORDS_POSITION);
assertEqualHr(S_OK, hr);
assertEqualInt(0, ptlHimetric.x);
assertEqualInt(0, ptlHimetric.y);
assertEqualFloat(0, ptfContainer.x);
assertEqualFloat(0, ptfContainer.y);
// Negative tests.
hr = pControlSite->TransformCoords(NULL, &ptfContainer, XFORMCOORDS_HIMETRICTOCONTAINER | XFORMCOORDS_SIZE);
assertEqualHr(E_POINTER, hr);
hr = pControlSite->TransformCoords(&ptlHimetric, NULL, XFORMCOORDS_HIMETRICTOCONTAINER | XFORMCOORDS_SIZE);
assertEqualHr(E_POINTER, hr);
hr = pControlSite->TransformCoords(&ptlHimetric, &ptfContainer, XFORMCOORDS_HIMETRICTOCONTAINER);
assertEqualHr(E_INVALIDARG, hr);
hr = pControlSite->TransformCoords(&ptlHimetric, &ptfContainer, XFORMCOORDS_CONTAINERTOHIMETRIC);
assertEqualHr(E_INVALIDARG, hr);
return S_OK;
}
static HRESULT Test_IOleControlSite_TranslateAccelerator(IOleControlSite* pControlSite, std::wstringstream& output)
{
HRESULT hr;
MSG msg = { 0 };
hr = pControlSite->TranslateAccelerator(&msg, 0);
assertEqualHr(S_FALSE, hr);
// Negative tests.
hr = pControlSite->TranslateAccelerator(NULL, 0);
assertEqualHr(E_POINTER, hr);
return S_OK;
}
static HRESULT Test_IOleControlSite_OnFocus(IOleControlSite* pControlSite, std::wstringstream& output)
{
HRESULT hr;
hr = pControlSite->OnFocus(TRUE);
assertEqualHr(S_OK, hr);
hr = pControlSite->OnFocus(TRUE);
assertEqualHr(S_OK, hr);
return S_OK;
}
static HRESULT Test_IOleControlSite_ShowPropertyFrame(IOleControlSite* pControlSite, std::wstringstream& output)
{
HRESULT hr;
// Negative tests.
hr = pControlSite->ShowPropertyFrame();
assertEqualHr(E_NOTIMPL, hr);
return S_OK;
}
static HRESULT Test_IOleControlSite(IOleControlSite* pControlSite, std::wstringstream& output)
{
HRESULT hr;
hr = Test_IOleControlSite_OnControlInfoChanged(pControlSite, output);
if (hr != S_OK)
{
return hr;
}
hr = Test_IOleControlSite_GetExtendedControl(pControlSite, output);
if (hr != S_OK)
{
return hr;
}
hr = Test_IOleControlSite_LockInPlaceActive(pControlSite, output);
if (hr != S_OK)
{
return hr;
}
hr = Test_IOleControlSite_TransformCoords(pControlSite, output);
if (hr != S_OK)
{
return hr;
}
hr = Test_IOleControlSite_TranslateAccelerator(pControlSite, output);
if (hr != S_OK)
{
return hr;
}
hr = Test_IOleControlSite_OnFocus(pControlSite, output);
if (hr != S_OK)
{
return hr;
}
hr = Test_IOleControlSite_ShowPropertyFrame(pControlSite, output);
if (hr != S_OK)
{
return hr;
}
return S_OK;
}
static HRESULT Test_ISimpleFrameSite_PreMessageFilter(ISimpleFrameSite* pSimpleFrameSite, std::wstringstream& output)
{
HRESULT hr;
hr = pSimpleFrameSite->PreMessageFilter(NULL, 0, NULL, NULL, NULL, NULL);
assertEqualHr(S_OK, hr);
hr = pSimpleFrameSite->PreMessageFilter((HWND)1, 1, (WPARAM)1, (LPARAM)1, (LRESULT*)1, (DWORD*)1);
assertEqualHr(S_OK, hr);
return S_OK;
}
static HRESULT Test_ISimpleFrameSite_PostMessageFilter(ISimpleFrameSite* pSimpleFrameSite, std::wstringstream& output)
{
HRESULT hr;
hr = pSimpleFrameSite->PostMessageFilter(NULL, 0, NULL, NULL, NULL, 0);
assertEqualHr(S_FALSE, hr);
hr = pSimpleFrameSite->PostMessageFilter((HWND)1, 1, (WPARAM)1, (LPARAM)1, (LRESULT*)1, 1);
assertEqualHr(S_FALSE, hr);
return S_OK;
}
static HRESULT Test_ISimpleFrameSite(ISimpleFrameSite* pSimpleFrameSite, std::wstringstream& output)
{
HRESULT hr;
hr = Test_ISimpleFrameSite_PreMessageFilter(pSimpleFrameSite, output);
if (hr != S_OK)
{
return hr;
}
hr = Test_ISimpleFrameSite_PostMessageFilter(pSimpleFrameSite, output);
if (hr != S_OK)
{
return hr;
}
return S_OK;
}
static HRESULT Test_IOleClientSite_SaveObject(IOleClientSite* pClientSite, std::wstringstream& output)
{
HRESULT hr;
// Negative tests.
hr = pClientSite->SaveObject();
assertEqualHr(E_NOTIMPL, hr);
return S_OK;
}
static HRESULT Test_IOleClientSite_GetMoniker(IOleClientSite* pClientSite, std::wstringstream& output)
{
HRESULT hr;
IMoniker* pmk;
// Negative tests.
pmk = (IMoniker*)(long)0xdeadbeef;
hr = pClientSite->GetMoniker(0, 0, &pmk);
assertEqualHr(E_NOTIMPL, hr);
assertNull(pmk);
hr = pClientSite->GetMoniker(0, 0, NULL);
assertEqualHr(E_POINTER, hr);
return S_OK;
}
static HRESULT Test_IOleClientSite_GetContainer(IOleClientSite* pClientSite, std::wstringstream& output)
{
HRESULT hr;
IOleContainer* pContainer;
pContainer = (IOleContainer*)(long)0xdeadbeef;
hr = pClientSite->GetContainer(&pContainer);
assertEqualHr(S_OK, hr);
assertNotNull(pContainer);
#if false
// Negative tests.
hr = pClientSite->GetContainer(NULL);
assertEqualHr(E_POINTER, hr);
#endif
return S_OK;
}
static HRESULT Test_IOleClientSite_ShowObject(IOleClientSite* pClientSite, std::wstringstream& output)
{
HRESULT hr;
hr = pClientSite->ShowObject();
assertEqualHr(S_OK, hr);
return S_OK;
}
static HRESULT Test_IOleClientSite_OnShowWindow(IOleClientSite* pClientSite, std::wstringstream& output)
{
HRESULT hr;
hr = pClientSite->OnShowWindow(TRUE);
assertEqualHr(S_OK, hr);
hr = pClientSite->OnShowWindow(FALSE);
assertEqualHr(S_OK, hr);
return S_OK;
}
static HRESULT Test_IOleClientSite_RequestNewObjectLayout(IOleClientSite* pClientSite, std::wstringstream& output)
{
HRESULT hr;
// Negative tests.
hr = pClientSite->RequestNewObjectLayout();
assertEqualHr(E_NOTIMPL, hr);
return S_OK;
}
static HRESULT Test_IOleClientSite(IOleClientSite* pClientSite, std::wstringstream& output)
{
HRESULT hr;
hr = Test_IOleClientSite_SaveObject(pClientSite, output);
if (hr != S_OK)
{
return hr;
}
hr = Test_IOleClientSite_GetMoniker(pClientSite, output);
if (hr != S_OK)
{
return hr;
}
hr = Test_IOleClientSite_GetContainer(pClientSite, output);
if (hr != S_OK)
{
return hr;
}
hr = Test_IOleClientSite_ShowObject(pClientSite, output);
if (hr != S_OK)
{
return hr;
}
hr = Test_IOleClientSite_OnShowWindow(pClientSite, output);
if (hr != S_OK)
{
return hr;
}
hr = Test_IOleClientSite_RequestNewObjectLayout(pClientSite, output);
if (hr != S_OK)
{
return hr;
}
return S_OK;
}
static HRESULT Test_IOleInPlaceSite_GetWindow(IOleInPlaceSite* pInPlaceSite, std::wstringstream& output)
{
HRESULT hr;
HWND hwnd;
hwnd = NULL;
hr = pInPlaceSite->GetWindow(&hwnd);
assertEqualHr(S_OK, hr);
assertNotNull(hwnd);
// Negative tests.
hr = pInPlaceSite->GetWindow(NULL);
assertEqualHr(E_POINTER, hr);
return S_OK;
}
static HRESULT Test_IOleInPlaceSite_ContextSensitiveHelp(IOleInPlaceSite* pInPlaceSite, std::wstringstream& output)
{
HRESULT hr;
// Negative tests.
hr = pInPlaceSite->ContextSensitiveHelp(TRUE);
assertEqualHr(E_NOTIMPL, hr);
hr = pInPlaceSite->ContextSensitiveHelp(FALSE);
assertEqualHr(E_NOTIMPL, hr);
return S_OK;
}
static HRESULT Test_IOleInPlaceSite_CanInPlaceActivate(IOleInPlaceSite* pInPlaceSite, std::wstringstream& output)
{
HRESULT hr;
hr = pInPlaceSite->CanInPlaceActivate();
assertEqualHr(S_OK, hr);
return S_OK;
}
static HRESULT Test_IOleInPlaceSite_OnInPlaceActivate(IOleInPlaceSite* pInPlaceSite, std::wstringstream& output)
{
HRESULT hr;
hr = pInPlaceSite->OnInPlaceActivate();
assertEqualHr(S_OK, hr);
return S_OK;
}
static HRESULT Test_IOleInPlaceSite_OnUIActivate(IOleInPlaceSite* pInPlaceSite, std::wstringstream& output)
{
HRESULT hr;
hr = pInPlaceSite->OnUIActivate();
assertEqualHr(S_OK, hr);
return S_OK;
}
static HRESULT Test_IOleInPlaceSite_GetWindowContext(IOleInPlaceSite* pInPlaceSite, std::wstringstream& output)
{
HRESULT hr;
IOleInPlaceFrame* pFrame;
IOleInPlaceUIWindow* pDoc;
RECT posRect;
RECT clipRect;
OLEINPLACEFRAMEINFO frameInfo;
pFrame = NULL;
pDoc = NULL;
posRect = { 0 };
clipRect = { 0 };
frameInfo = { 0 };
hr = pInPlaceSite->GetWindowContext(&pFrame, &pDoc, &posRect, &clipRect, NULL);
assertEqualHr(S_OK, hr);
assertNotNull(pFrame);
assertNull(pDoc);
assertEqualInt(0, posRect.left);
assertEqualInt(0, posRect.top);
assertEqualInt(250, posRect.right);
assertEqualInt(250, posRect.bottom);
assertEqualInt(0, clipRect.left);
assertEqualInt(0, clipRect.top);
assertEqualInt(32000, clipRect.right);
assertEqualInt(32000, clipRect.bottom);
pFrame = NULL;
pDoc = NULL;
posRect = { 0 };
clipRect = { 0 };
frameInfo = { 0 };
hr = pInPlaceSite->GetWindowContext(&pFrame, &pDoc, &posRect, &clipRect, &frameInfo);
assertEqualHr(S_OK, hr);
assertNotNull(pFrame);
assertNull(pDoc);
assertEqualInt(0, posRect.left);
assertEqualInt(0, posRect.top);
assertEqualInt(250, posRect.right);
assertEqualInt(250, posRect.bottom);
assertEqualInt(0, clipRect.left);
assertEqualInt(0, clipRect.top);
assertEqualInt(32000, clipRect.right);
assertEqualInt(32000, clipRect.bottom);
assertEqualInt(sizeof(OLEINPLACEFRAMEINFO), frameInfo.cb);
assertEqualBool(FALSE, frameInfo.fMDIApp);
assertEqualInt(0, frameInfo.cAccelEntries);
assertNull(frameInfo.haccel);
assertNull(frameInfo.hwndFrame);
// Negative tests.
#if false
hr = pInPlaceSite->GetWindowContext(NULL, &pDoc, &posRect, &clipRect, &frameInfo);
assertEqualHr(E_POINTER, hr);
hr = pInPlaceSite->GetWindowContext(&pFrame, NULL, &posRect, &clipRect, &frameInfo);
assertEqualHr(E_POINTER, hr);
#endif
hr = pInPlaceSite->GetWindowContext(&pFrame, &pDoc, NULL, &clipRect, &frameInfo);
assertEqualHr(E_POINTER, hr);
hr = pInPlaceSite->GetWindowContext(&pFrame, &pDoc, &posRect, NULL, &frameInfo);
assertEqualHr(E_POINTER, hr);
return S_OK;
}
static HRESULT Test_IOleInPlaceSite(IOleInPlaceSite* pInPlaceSite, std::wstringstream& output)
{
HRESULT hr;
hr = Test_IOleInPlaceSite_GetWindow(pInPlaceSite, output);
if (hr != S_OK)
{
return hr;
}
hr = Test_IOleInPlaceSite_ContextSensitiveHelp(pInPlaceSite, output);
if (hr != S_OK)
{
return hr;
}
hr = Test_IOleInPlaceSite_CanInPlaceActivate(pInPlaceSite, output);
if (hr != S_OK)
{
return hr;
}
hr = Test_IOleInPlaceSite_OnInPlaceActivate(pInPlaceSite, output);
if (hr != S_OK)
{
return hr;
}
hr = Test_IOleInPlaceSite_OnUIActivate(pInPlaceSite, output);
if (hr != S_OK)
{
return hr;
}
hr = Test_IOleInPlaceSite_GetWindowContext(pInPlaceSite, output);
if (hr != S_OK)
{
return hr;
}
return S_OK;
}
TEST const WCHAR* WINAPI Test_WebBrowserSiteBase(IUnknown* pUnknown)
{
return RunTest([&](std::wstringstream& output)
{
HRESULT hr;
CComPtr<IOleControlSite> pControlSite;
CComPtr<ISimpleFrameSite> pSimpleFrameSite;
CComPtr<IOleClientSite> pClientSite;
CComPtr<IOleInPlaceSite> pInPlaceSite;
hr = pUnknown->QueryInterface(IID_IOleControlSite, (void**)&pControlSite);
hr = Test_IOleControlSite(pControlSite, output);
if (hr != S_OK)
{
return hr;
}
hr = pUnknown->QueryInterface(IID_ISimpleFrameSite, (void**)&pSimpleFrameSite);
hr = Test_ISimpleFrameSite(pSimpleFrameSite, output);
if (hr != S_OK)
{
return hr;
}
hr = pUnknown->QueryInterface(IID_IOleClientSite, (void**)&pClientSite);
hr = Test_IOleClientSite(pClientSite, output);
if (hr != S_OK)
{
return hr;
}
hr = pUnknown->QueryInterface(IID_IOleInPlaceSite, (void**)&pInPlaceSite);
hr = Test_IOleInPlaceSite(pInPlaceSite, output);
if (hr != S_OK)
{
return hr;
}
return S_OK;
});
}

158
src/System.Windows.Forms/tests/InteropTests/NativeTests/testhelpers.h

@ -0,0 +1,158 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#pragma once
#include <assert.h>
#include <stdio.h>
#include <sstream>
#include <type_traits>
#include <Windows.h>
#define TEST extern "C" __declspec(dllexport)
template<typename T, typename = std::enable_if_t<std::is_floating_point<T>::value>>
static inline bool is_essentially_equal_to(const T& a, const T& b)
{
if (std::isnan(a))
{
return std::isnan(b);
}
else if (std::isnan(b))
{
return false;
}
return std::abs(a - b) <= std::numeric_limits<T>::epsilon() * std::fmin(std::abs(a), std::abs(b));
}
template< typename... Args >
std::wstring format(const wchar_t* format, Args... args)
{
int length = std::swprintf(nullptr, 0, format, args...);
// If this fails, let the program crash.
wchar_t* buf = new wchar_t[length + 1];
std::swprintf(buf, length + 1, format, args...);
std::wstring str(buf);
delete[] buf;
return str;
}
static void printAssertionFailure(std::wstringstream& output, const char* file, const char* function, int line = __LINE__)
{
output << format(L"Assertion failure: file %hs in %hs, line %d", file, function, line) << std::endl;
}
#define printLine() printAssertionFailure(output, __FILE__, __FUNCTION__, __LINE__);
#define assertEqualInt(expected, actual) \
if ((expected) != (actual)) \
{ \
printLine(); \
output << format(L"Expected: %d\n", (int)((expected))); \
output << format(L"Actual: %d\n", (int)((actual))); \
return E_FAIL; \
}
#define assertEqualBool(expected, actual) \
if ((expected) != (actual)) \
{ \
printLine(); \
if ((expected)) \
{ \
output << format(L"Expected: TRUE\n"); \
output << format(L"Actual: FALSE\n"); \
} \
else \
{ \
output << format(L"Expected: FALSE\n"); \
output << format(L"Actual: TRUE\n"); \
} \
return E_FAIL; \
}
#define assertEqualFloat(expected, actual) \
if (!is_essentially_equal_to((float)((expected)), (float)((actual)))) \
{ \
printLine(); \
output << format(L"Expected: %f\n", (float)((expected))); \
output << format(L"Actual: %f\n", (float)((actual))); \
return E_FAIL; \
}
#define assertEqualDouble(expected, actual) \
if (!is_essentially_equal_to((double)((expected)), (double)((actual)))) \
{ \
printLine(); \
output << format(L"Expected: %f\n", (double)((expected))); \
output << format(L"Actual: %f\n", (double)((actual))); \
return E_FAIL; \
}
#define assertEqualHr(expected, actual) \
if ((int)((expected)) != (int)((actual))) \
{ \
printLine(); \
output << format(L"Expected: 0x%08X\n", (int)((expected))); \
output << format(L"Actual: 0x%08X\n", (int)((actual))); \
return E_FAIL; \
}
#define assertEqualWString(expected, actual) \
if (!(expected) && (actual)) \
{ \
output << format(L"Expected: NULL\n"); \
output << format(L"Actual: %s\n", (const wchar_t*)((actual))); \
} \
else if ((expected) && !(actual)) \
{ \
output << format(L"Expected: %s\n", (const wchar_t*)((expected))); \
output << format(L"Actual: NULL\n"); \
} \
else if (wcscmp((const wchar_t*)(expected), (const wchar_t*)(actual)) != 0) \
{ \
printLine(); \
output << format(L"Expected: %s\n", (const wchar_t*)((expected))); \
output << format(L"Actual: %s\n", (const wchar_t*)((actual))); \
return E_FAIL; \
}
#define assertNull(actual) \
if ((actual)) \
{ \
printLine(); \
output << format(L"Actual: %p\n", ((actual))); \
return E_FAIL; \
}
#define assertNotNull(actual) \
if (!(actual) || (void*)((actual)) == (void*)(long)0xdeadbeef) \
{ \
printLine(); \
output << format(L"Actual: %p\n", ((actual))); \
return E_FAIL; \
}
template<typename T>
static const WCHAR* RunTest(T method)
{
std::wstringstream output;
HRESULT hr = method(output);
if (hr == S_OK)
{
output << L"Success";
}
return Duplicate(output.str().c_str());
}
// Need to allocate this as CoTaskMemAlloc to be interpreted by interop marshallers.
static const WCHAR* Duplicate(const WCHAR* source)
{
size_t length = wcslen(source) + 1;
WCHAR* clone = (WCHAR*)CoTaskMemAlloc(length * sizeof(WCHAR));
wcscpy_s(clone, length, source);
return clone;
}

24
src/System.Windows.Forms/tests/InteropTests/System.Windows.Forms.Interop.Tests.csproj

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>System.Windows.Forms.Interop.Tests</AssemblyName>
<Platforms>x86;x64</Platforms>
</PropertyGroup>
<Import Project="ProjectReference.targets" Sdk="Microsoft.DotNet.CMake.Sdk" />
<ItemGroup>
<PackageReference Include="Moq" Version="$(MoqPackageVersion)" />
<PackageReference Include="xunit.stafact" Version="$(XUnitStaFactPackageVersion)" />
<PackageReference Include="coverlet.msbuild" Version="$(CoverletMSBuildPackageVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\System.Windows.Forms.csproj" />
</ItemGroup>
<ItemGroup>
<NativeProjectReference Include="NativeTests\CMakeLists.txt" CMakeProject="NativeTests\NativeTests.proj" BuildNative="true" />
</ItemGroup>
</Project>

28
src/System.Windows.Forms/tests/InteropTests/WebBrowserSiteBaseInteropTests.cs

@ -0,0 +1,28 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Runtime.InteropServices;
using Xunit;
namespace System.Windows.Forms.InteropTests
{
public class WebBrowserSiteBaseInteropTests : InteropTestBase
{
[WinFormsFact]
public void WebBrowserSiteBase_RunInteropTests()
{
var browser = new SubWebBrowser();
WebBrowserSiteBase site = browser.CreateWebBrowserSiteBase();
AssertSuccess(Test_WebBrowserSiteBase(site));
}
[DllImport(NativeTests, CharSet = CharSet.Unicode, ExactSpelling = true)]
private static extern string Test_WebBrowserSiteBase([MarshalAs(UnmanagedType.IUnknown)] object pUnk);
private class SubWebBrowser : WebBrowser
{
public new WebBrowserSiteBase CreateWebBrowserSiteBase() => base.CreateWebBrowserSiteBase();
}
}
}
Loading…
Cancel
Save