Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests for OAVariantLib #101841

Merged
merged 11 commits into from
May 5, 2024
61 changes: 61 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,66 @@ 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
(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 +293,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