Skip to content

Commit

Permalink
Add tests for OAVariantLib (dotnet#101841)
Browse files Browse the repository at this point in the history
* Add native return test for basic supported types

---------

Co-authored-by: Aaron Robinson <arobins@microsoft.com>
  • Loading branch information
2 people authored and michaelgsharp committed May 8, 2024
1 parent 1ed4ba9 commit 71d264c
Show file tree
Hide file tree
Showing 12 changed files with 550 additions and 0 deletions.
62 changes: 62 additions & 0 deletions src/tests/Interop/COM/NETClients/IDispatch/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,67 @@ System.Collections.Generic.IEnumerable<int> GetEnumerable(System.Collections.IEn
}
}

static void Validate_ValueCoerce_ReturnToManaged()
{
var dispatchCoerceTesting = (DispatchCoerceTesting)new DispatchCoerceTestingClass();

Console.WriteLine($"Calling {nameof(DispatchCoerceTesting.ReturnToManaged)} ...");

// Supported types
// See returned values in DispatchCoerceTesting.h
(VarEnum type, int expectedValue)[] supportedTypes =
{
(VarEnum.VT_EMPTY, 0),
(VarEnum.VT_I2, 123),
(VarEnum.VT_I4, 123),
(VarEnum.VT_R4, 1),
(VarEnum.VT_R8, 1),
(VarEnum.VT_CY, 123),
(VarEnum.VT_DATE, 1),
(VarEnum.VT_BSTR, 123),
(VarEnum.VT_ERROR, 123),
(VarEnum.VT_BOOL, -1),
(VarEnum.VT_DECIMAL, 123),
};

foreach (var (vt, expected) in supportedTypes)
{
Console.WriteLine($"Converting {vt} to int should be supported.");
int result = dispatchCoerceTesting.ReturnToManaged((short)vt);
Assert.Equal(expected, result);
}

// Invalid: Rejected before reaching coerce
Console.WriteLine("Invalid variant type should throw InvalidOleVariantTypeException.");
var variantException = Assert.Throws<InvalidOleVariantTypeException>(() => dispatchCoerceTesting.ReturnToManaged(0x7FFF));
Assert.Equal(unchecked((int)0x80131531), variantException.HResult);

// Not supported source or destination type: COMException { HResult: 0x80020005 }

// DISP_E_PARAMNOTFOUND: Converts to Missing
Console.WriteLine("Converting from VT_ERROR with DISP_E_PARAMNOTFOUND should be rejected.");
var comException = Assert.Throws<COMException>(() => dispatchCoerceTesting.ReturnToManaged(unchecked((short)((short)VarEnum.VT_ERROR | 0x8000))));
Assert.Equal(unchecked((int)0x80020005), comException.HResult);

Console.WriteLine("Converting int to VT_MISSING should be rejected.");
comException = Assert.Throws<COMException>(() => dispatchCoerceTesting.ReturnToManaged_Missing());
Assert.Equal(unchecked((int)0x80020005), comException.HResult);

Console.WriteLine("Converting int to VT_NULL should be rejected.");
comException = Assert.Throws<COMException>(() => dispatchCoerceTesting.ReturnToManaged_DBNull());
Assert.Equal(unchecked((int)0x80020005), comException.HResult);

// Rejected by VariantChangeTypeEx
Console.WriteLine("Converting VT_UNKNOWN to int should fail from VariantChangeTypeEx.");
Assert.Throws<InvalidCastException>(() => dispatchCoerceTesting.ReturnToManaged((short)VarEnum.VT_UNKNOWN));
Console.WriteLine("Converting VT_NULL to int should fail from VariantChangeTypeEx.");
Assert.Throws<InvalidCastException>(() => dispatchCoerceTesting.ReturnToManaged((short)VarEnum.VT_NULL));

// LOCAL_BOOL
Console.WriteLine("VARIANT_BOOL should convert to non-numeric string.");
Assert.Equal("True", dispatchCoerceTesting.BoolToString());
}

[Fact]
public static int TestEntryPoint()
{
Expand All @@ -233,6 +294,7 @@ public static int TestEntryPoint()
Validate_StructNotSupported();
Validate_LCID_Marshaled();
Validate_Enumerator();
Validate_ValueCoerce_ReturnToManaged();
}
catch (Exception e)
{
Expand Down
39 changes: 39 additions & 0 deletions src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Server.Contract;

[ComVisible(true)]
[Guid(Server.Contract.Guids.DispatchCoerceTesting)]
public class DispatchCoerceTesting : Server.Contract.IDispatchCoerceTesting
{
public int ReturnToManaged(short vt)
{
throw new NotImplementedException();
}

public int ManagedArgument(int arg)
{
return arg;
}

public System.Reflection.Missing ReturnToManaged_Missing()
{
return System.Reflection.Missing.Value;
}

public DBNull ReturnToManaged_DBNull()
{
return DBNull.Value;
}

public string BoolToString()
{
throw new NotImplementedException();
}
}
110 changes: 110 additions & 0 deletions src/tests/Interop/COM/NativeClients/Dispatch/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ void Validate_Float_In_ReturnAndUpdateByRef();
void Validate_Double_In_ReturnAndUpdateByRef();
void Validate_LCID_Marshaled();
void Validate_Enumerator();
void Validate_ParamCoerce();

template<COINIT TM>
struct ComInit
Expand Down Expand Up @@ -48,6 +49,7 @@ int __cdecl main()
Validate_Double_In_ReturnAndUpdateByRef();
Validate_LCID_Marshaled();
Validate_Enumerator();
Validate_ParamCoerce();
}
catch (HRESULT hr)
{
Expand Down Expand Up @@ -459,3 +461,111 @@ void Validate_Enumerator()
::printf(" -- Validate returned IEnumVARIANT\n");
ValidateReturnedEnumerator(&result);
}

void Validate_ParamCoerce_Type(ComSmartPtr<IDispatchCoerceTesting>& dispatchCoerceTesting, VARENUM type, int lcid, DISPID methodId)
{
HRESULT hr;

DISPPARAMS params;
VARIANTARG arg;
params.cArgs = 1;
params.rgvarg = &arg;
params.cNamedArgs = 0;
params.rgdispidNamedArgs = nullptr;

VARIANT result;

V_VT(&arg) = type;

switch (type)
{
case VT_BSTR:
{
BSTR str = ::SysAllocString(L"123");
V_BSTR(&arg) = str;
break;
}
case VT_R4:
{
V_R4(&arg) = 1.23f;
break;
}
case VT_DATE:
case VT_R8:
{
V_R8(&arg) = 1.23;
break;
}
case VT_CY:
{
VarCyFromI4(123, &V_CY(&arg));
break;
}
case VT_DECIMAL:
{
VarDecFromI4(123, &V_DECIMAL(&arg));
break;
}
default:
{
V_I1(&arg) = 123;
break;
}
}

THROW_IF_FAILED(dispatchCoerceTesting->Invoke(
methodId,
IID_NULL,
lcid,
DISPATCH_METHOD,
&params,
&result,
nullptr,
nullptr
));

THROW_FAIL_IF_FALSE(V_I4(&result) != 0);
}

void Validate_ParamCoerce()
{
HRESULT hr;

CoreShimComActivation csact{ W("NETServer"), W("DispatchCoerceTesting") };

ComSmartPtr<IDispatchCoerceTesting> dispatchCoerceTesting;
THROW_IF_FAILED(::CoCreateInstance(CLSID_DispatchCoerceTesting, nullptr, CLSCTX_INPROC, IID_IDispatchCoerceTesting, (void**)&dispatchCoerceTesting));

LPOLESTR numericMethodName = (LPOLESTR)W("ManagedArgument");
LCID lcid = MAKELCID(LANG_USER_DEFAULT, SORT_DEFAULT);
DISPID methodId;

::wprintf(W("Invoke %s\n"), numericMethodName);
THROW_IF_FAILED(dispatchCoerceTesting->GetIDsOfNames(
IID_NULL,
&numericMethodName,
1,
lcid,
&methodId));

::wprintf(W("Validating VT_I2\n"));
Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_I2, lcid, methodId);
::wprintf(W("Validating VT_I4\n"));
Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_I4, lcid, methodId);
::wprintf(W("Validating VT_R4\n"));
Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_R4, lcid, methodId);
::wprintf(W("Validating VT_R8\n"));
Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_R8, lcid, methodId);
::wprintf(W("Validating VT_CY\n"));
Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_CY, lcid, methodId);
::wprintf(W("Validating VT_DATE\n"));
Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_DATE, lcid, methodId);
::wprintf(W("Validating VT_BSTR\n"));
Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_BSTR, lcid, methodId);
::wprintf(W("Validating VT_ERROR\n"));
Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_ERROR, lcid, methodId);
::wprintf(W("Validating VT_BOOL\n"));
Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_BOOL, lcid, methodId);
::wprintf(W("Validating VT_DECIMAL\n"));
Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_DECIMAL, lcid, methodId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
<comClass
clsid="{0F8ACD0C-ECE0-4F2A-BD1B-6BFCA93A0726}"
threadingModel="Both" />

<!-- DispatchCoerceTesting -->
<comClass
clsid="{661F9962-3477-416B-BE40-4CBA3190A562}"
threadingModel="Both" />
</file>

</assembly>
5 changes: 5 additions & 0 deletions src/tests/Interop/COM/NativeServer/COMNativeServer.X.manifest
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@
clsid="{4DBD9B61-E372-499F-84DE-EFC70AA8A009}"
threadingModel="Both" />

<!-- DispatchCoerceTesting -->
<comClass
clsid="{661F9962-3477-416B-BE40-4CBA3190A562}"
threadingModel="Both" />

<!-- AggregationTesting -->
<comClass
clsid="{4CEFE36D-F377-4B6E-8C34-819A8BB9CB04}"
Expand Down
Loading

0 comments on commit 71d264c

Please sign in to comment.