Imported Upstream version 5.20.0.180

Former-commit-id: ff953ca879339fe1e1211f7220f563e1342e66cb
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2019-02-04 20:11:37 +00:00
parent 0e2d47d1c8
commit 0510252385
3360 changed files with 83827 additions and 39243 deletions

View File

@@ -1,8 +1,6 @@
@echo off
setlocal
rem Enable Server GC for this test
set RH_UseServerGC=1
"%1\%2"
set ErrorCode=%ERRORLEVEL%
IF "%ErrorCode%"=="100" (

View File

@@ -17,10 +17,6 @@ class Program
{
SimpleReadWriteThreadStaticTest.Run(42, "SimpleReadWriteThreadStatic");
// TODO: After issue https://github.com/dotnet/corert/issues/2695 is fixed, move FinalizeTest to run at the end
if (FinalizeTest.Run() != Pass)
return Fail;
ThreadStaticsTestWithTasks.Run();
if (ThreadTest.Run() != Pass)
@@ -28,6 +24,9 @@ class Program
if (TimerTest.Run() != Pass)
return Fail;
if (FinalizeTest.Run() != Pass)
return Fail;
return Pass;
}

View File

@@ -1,4 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ServerGarbageCollection>true</ServerGarbageCollection>
</PropertyGroup>
<ItemGroup>
<Compile Include="*.cs" />
</ItemGroup>

View File

@@ -1,7 +1,5 @@
#!/usr/bin/env bash
# Enable Server GC for this test
export RH_UseServerGC=1
$1/$2
if [ $? == 100 ]; then
echo pass

View File

@@ -4,6 +4,8 @@
using System;
using Pointer = System.Reflection.Pointer;
public class BringUpTests
{
const int Pass = 100;
@@ -105,6 +107,14 @@ public class BringUpTests
return false;
}
{
// This will end up being a delegate to a sealed virtual method.
ClassWithIFoo t = new ClassWithIFoo("Class");
Func<int, string> d = t.DoFoo;
if (d(987) != "Class987")
return false;
}
Console.WriteLine("OK");
return true;
}
@@ -247,7 +257,10 @@ public class BringUpTests
unsafe
{
GetAndReturnPointerDelegate d = ClassWithPointers.GetAndReturnPointer;
if ((IntPtr)d.DynamicInvoke(new object[] { (IntPtr)8 }) != (IntPtr)50)
if (Pointer.Unbox(d.DynamicInvoke(new object[] { (IntPtr)8 })) != (void*)50)
return false;
if (Pointer.Unbox(d.DynamicInvoke(new object[] { Pointer.Box((void*)9, typeof(void*)) })) != (void*)51)
return false;
}
@@ -390,14 +403,14 @@ static class ExtensionClass
}
}
unsafe delegate IntPtr GetAndReturnPointerDelegate(void* ptr);
unsafe delegate byte* GetAndReturnPointerDelegate(void* ptr);
unsafe delegate void PassPointerByRefDelegate(ref void* ptr);
unsafe static class ClassWithPointers
{
public static IntPtr GetAndReturnPointer(void* ptr)
public static byte* GetAndReturnPointer(void* ptr)
{
return (IntPtr)((byte*)ptr + 42);
return (byte*)ptr + 42;
}
public static void PassPointerByRef(ref void* ptr)

View File

@@ -31,6 +31,8 @@ class Program
TestGvmDependencies.Run();
TestFieldAccess.Run();
TestNativeLayoutGeneration.Run();
TestInterfaceVTableTracking.Run();
TestClassVTableTracking.Run();
return 100;
}
@@ -2088,4 +2090,60 @@ class Program
throw new Exception();
}
}
class TestInterfaceVTableTracking
{
class Gen<T> { }
interface IFoo<T>
{
Array Frob();
}
class GenericBase<T> : IFoo<T>
{
public Array Frob()
{
return new Gen<T>[1,1];
}
}
class Derived<T> : GenericBase<Gen<T>>
{
}
static volatile IFoo<Gen<string>> s_foo;
public static void Run()
{
// This only really tests whether we can compile this.
s_foo = new Derived<string>();
Array arr = s_foo.Frob();
arr.SetValue(new Gen<Gen<string>>(), new int[] { 0, 0 });
}
}
class TestClassVTableTracking
{
class Unit { }
class Gen<T, U>
{
public virtual int Test()
{
return 42;
}
}
static int Call<T>()
{
return new Gen<T, Unit>().Test();
}
public static void Run()
{
// This only really tests whether we can compile this.
Call<object>();
}
}
}

View File

@@ -1,14 +1,13 @@
@echo off
setlocal
set ErrorCode=100
for /f "usebackq delims=;" %%F in (`"%1\%2" world`) do (
if "%%F"=="Hello world" set ErrorCode=0
)
IF "%ErrorCode%"=="0" (
echo %~n0: pass
call emrun --browser=firefox --browser_args=-headless --safe_firefox_profile --silence_timeout 10 "%1\%2"
IF "%errorlevel%"=="100" (
echo %~n0: Pass
EXIT /b 0
) ELSE (
echo %~n0: fail - %ErrorCode%
echo %~n0: fail - %ErrorLevel%
EXIT /b 1
)
endlocal

View File

@@ -4,6 +4,9 @@
<ProjectReference Include="CpObj.ilproj" Condition="'$(OS)' == 'Windows_NT'" />
<IlcArg Include="-r:$(IntermediateOutputPath)\CpObj.dll" Condition="'$(OS)' == 'Windows_NT'" />
<ProjectReference Include="ILHelpers.ilproj" Condition="'$(OS)' == 'Windows_NT'" />
<IlcArg Include="-r:$(IntermediateOutputPath)\ILHelpers.dll" Condition="'$(OS)' == 'Windows_NT'" />
</ItemGroup>
<PropertyGroup Condition="'$(OS)' == 'Windows_NT'">

View File

@@ -0,0 +1,111 @@
// 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.
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 )
.ver 4:0:0:0
}
.assembly extern System.Private.CoreLib
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )
.ver 4:0:0:0
}
.assembly ILHelpers { }
.class public ILHelpers.ILHelpersTest
{
.method public static void EatArgs(string, object)
{
ret
}
.method public static void EatArg(object)
{
ret
}
//this is copied from the test case for https://github.com/dotnet/coreclr/issues/14784
//its been adapted to remove the requirement for Console.WriteLine because thats not supported in WASM
//it can be removed once we have support for Console.WriteLine and can run the CoreCLR tests
.method public static int32 InlineAssignByte()
{
.locals init (
int8 local,
object b
)
ldstr "InlineAssignByte"
ldc.i4 300
dup
stloc.0
box int32
stloc.1
ldloc.1
call void ILHelpers.ILHelpersTest::EatArgs(string, object)
ldstr "InlineAssignByte"
ldloc.0
box int32
call void ILHelpers.ILHelpersTest::EatArgs(string, object)
ldloc.1
//after the unboxing and truncation on the way in ensure that we can subtract 200 and end up with the expected 100 return value
unbox.any int32
ldc.i4 200
sub
ret
}
.method public static int32 DupTest(int32&)
{
.locals init (
int32 local,
int32 local2
)
ldarg.0
//push a bunch of entries onto the stack using dup, we will consume them through the rest of this method
dup
dup
dup
dup
dup
//first off lets ensure the passed parameter was pointing to an int of less than 10 (it should be 9)
ldind.i4
ldc.i4 10
clt
brtrue target
//this is just trying to mess with the stack accross basic block boundries
//it should actually leave the evaluation stack unchanged in the end
pop
dup
//make sure we can deref one of our duplicate int refs and box it without any trouble
target: ldind.i4
box int32
call void ILHelpers.ILHelpersTest::EatArg(object)
//deref one of our duplicates and add 1 to it, this should not write back to the parameter it should only be stored in the local
ldind.i4
ldc.i4 1
add
stloc.0
//load one of our duplicates and add 200 to it, we're eventually going to return this value and test for it in the caller
ldind.i4
ldc.i4 200
add
//this should write back into the parameter
stind.i4
ldloc.0
dup
add
dup
stloc.1
ldloc.0
ceq
//if the added value equals the source value we've got something writing to its original StackEntry instead of a dup
brtrue failure
ldind.i4
ret
failure:
pop
ldc.i4 0
ret
}
}

View File

@@ -0,0 +1,20 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<OutputType>Library</OutputType>
<DebugType>portable</DebugType>
<OutputPath>$(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\</OutputPath>
<IntermediateOutputPath>$(MSBuildProjectDirectory)\obj\$(Configuration)\$(Platform)\</IntermediateOutputPath>
</PropertyGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<Compile Include="ILHelpers.il" />
<PackageReference Include="Microsoft.NETCore.App">
<Version>$(MicrosoftNETCoreAppPackageVersion)</Version>
</PackageReference>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>

View File

@@ -13,16 +13,46 @@ internal static class Program
private static int staticInt;
[ThreadStatic]
private static int threadStaticInt;
private static unsafe void Main(string[] args)
private static unsafe int Main(string[] args)
{
PrintLine("Starting");
Add(1, 2);
int tempInt = 0;
int tempInt2 = 0;
(*(&tempInt)) = 9;
if(tempInt == 9)
{
PrintLine("Hello from C#!");
}
int* targetAddr = (tempInt > 0) ? (&tempInt2) : (&tempInt);
(*targetAddr) = 1;
if(tempInt2 == 1 && tempInt == 9)
{
PrintLine("basic block stack entry Test: Ok.");
}
if(ILHelpers.ILHelpersTest.InlineAssignByte() == 100)
{
PrintLine("Inline assign byte Test: Ok.");
}
else
{
PrintLine("Inline assign byte Test: Failed.");
}
int dupTestInt = 9;
if(ILHelpers.ILHelpersTest.DupTest(ref dupTestInt) == 209 && dupTestInt == 209)
{
PrintLine("dup test: Ok.");
}
else
{
PrintLine("dup test: Failed.");
}
TestClass tempObj = new TestDerivedClass(1337);
tempObj.TestMethod("Hello");
tempObj.TestVirtualMethod("Hello");
@@ -55,12 +85,19 @@ internal static class Program
PrintLine("thread static int field test: Ok.");
}
StaticCtorTest();
var boxedInt = (object)tempInt;
if(((int)boxedInt) == 9)
{
PrintLine("box test: Ok.");
}
else
{
PrintLine("box test: Failed. Value:");
PrintLine(boxedInt.ToString());
}
var boxedStruct = (object)new BoxStubTest { Value = "Boxed Stub Test: Ok." };
PrintLine(boxedStruct.ToString());
@@ -157,6 +194,10 @@ internal static class Program
arrayTest[1].Value = "Array load/store test: Ok.";
PrintLine(arrayTest[1].Value);
int ii = 0;
arrayTest[ii++].Value = "dup ref test: Ok.";
PrintLine(arrayTest[0].Value);
var largeArrayTest = new long[] { Int64.MaxValue, 0, Int64.MinValue, 0 };
if(largeArrayTest[0] == Int64.MaxValue &&
largeArrayTest[1] == 0 &&
@@ -186,6 +227,9 @@ internal static class Program
IntToStringTest();
CastingTestClass castingTest = new DerivedCastingTestClass1();
PrintLine("interface call test: Ok " + (castingTest as ICastingTest1).GetValue().ToString());
if (((DerivedCastingTestClass1)castingTest).GetValue() == 1 && !(castingTest is DerivedCastingTestClass2))
{
PrintLine("Type casting with isinst & castclass to class test: Ok.");
@@ -208,17 +252,74 @@ internal static class Program
ldindTest();
System.Diagnostics.Debugger.Break();
InterfaceDispatchTest();
var testRuntimeHelpersInitArray = new long[] {1, 2, 3};
if(testRuntimeHelpersInitArray[0] == 1 &&
var testRuntimeHelpersInitArray = new long[] { 1, 2, 3 };
if (testRuntimeHelpersInitArray[0] == 1 &&
testRuntimeHelpersInitArray[1] == 2 &&
testRuntimeHelpersInitArray[2] == 3)
{
PrintLine("Runtime.Helpers array initialization test: Ok.");
}
var testMdArrayInstantiation = new int[2, 2];
if (testMdArrayInstantiation != null && testMdArrayInstantiation.GetLength(0) == 2 && testMdArrayInstantiation.GetLength(1) == 2)
PrintLine("Multi-dimension array instantiation test: Ok.");
int intToCast = 1;
double castedDouble = (double)intToCast;
if (castedDouble == 1d)
{
PrintLine("(double) cast test: Ok.");
}
else
{
var toInt = (int)castedDouble;
// PrintLine("expected 1m, but was " + castedDouble.ToString()); // double.ToString is not compiling at the time of writing, but this would be better output
PrintLine($"(double) cast test : Failed. Back to int on next line");
PrintLine(toInt.ToString());
}
if (1f < 2d && 1d < 2f && 1f == 1d)
{
PrintLine("different width float comparisons: Ok.");
}
// floats are 7 digits precision, so check some double more precise to make sure there is no loss occurring through some inadvertent cast to float
if (10.23456789d != 10.234567891d)
{
PrintLine("double precision comparison: Ok.");
}
if (12.34567f == 12.34567f && 12.34567f != 12.34568f)
{
PrintLine("float comparison: Ok.");
}
// Create a ByReference<char> through the ReadOnlySpan ctor and call the ByReference.Value via the indexer.
var span = "123".AsSpan();
if (span[0] != '1'
|| span[1] != '2'
|| span[2] != '3')
{
PrintLine("ByReference intrinsics exercise via ReadOnlySpan failed");
PrintLine(span[0].ToString());
PrintLine(span[1].ToString());
PrintLine(span[2].ToString());
}
else
{
PrintLine("ByReference intrinsics exercise via ReadOnlySpan OK.");
}
TestConstrainedClassCalls();
// This test should remain last to get other results before stopping the debugger
PrintLine("Debugger.Break() test: Ok if debugger is open and breaks.");
System.Diagnostics.Debugger.Break();
PrintLine("Done");
return 100;
}
private static int StaticDelegateTarget()
@@ -346,6 +447,160 @@ internal static class Program
}
}
private static void InterfaceDispatchTest()
{
ItfStruct itfStruct = new ItfStruct();
if (ItfCaller(itfStruct) == 4)
{
PrintLine("Struct interface test: Ok.");
}
}
// Calls the ITestItf interface via a generic to ensure the concrete type is known and
// an interface call is generated instead of a virtual or direct call
private static int ItfCaller<T>(T obj) where T : ITestItf
{
return obj.GetValue();
}
private static void StaticCtorTest()
{
BeforeFieldInitTest.Nop();
if (StaticsInited.BeforeFieldInitInited)
{
PrintLine("BeforeFieldInitType inited too early");
}
else
{
int x = BeforeFieldInitTest.TestField;
if (StaticsInited.BeforeFieldInitInited)
{
PrintLine("BeforeFieldInit test: Ok.");
}
else
{
PrintLine("BeforeFieldInit cctor not run");
}
}
NonBeforeFieldInitTest.Nop();
if (StaticsInited.NonBeforeFieldInitInited)
{
PrintLine("NonBeforeFieldInit test: Ok.");
}
else
{
PrintLine("NonBeforeFieldInitType cctor not run");
}
}
private static void TestConstrainedClassCalls()
{
string s = "utf-8";
PrintString("Direct ToString test: ");
string stringDirectToString = s.ToString();
if (s.Equals(stringDirectToString))
{
PrintLine("Ok.");
}
else
{
PrintString("Failed. Returned string:\"");
PrintString(stringDirectToString);
PrintLine("\"");
}
// Generic calls on methods not defined on object
uint dataFromBase = GenericGetData<MyBase>(new MyBase(11));
PrintString("Generic call to base class test: ");
if (dataFromBase == 11)
{
PrintLine("Ok.");
}
else
{
PrintLine("Failed.");
}
uint dataFromUnsealed = GenericGetData<UnsealedDerived>(new UnsealedDerived(13));
PrintString("Generic call to unsealed derived class test: ");
if (dataFromUnsealed == 26)
{
PrintLine("Ok.");
}
else
{
PrintLine("Failed.");
}
uint dataFromSealed = GenericGetData<SealedDerived>(new SealedDerived(15));
PrintString("Generic call to sealed derived class test: ");
if (dataFromSealed == 45)
{
PrintLine("Ok.");
}
else
{
PrintLine("Failed.");
}
uint dataFromUnsealedAsBase = GenericGetData<MyBase>(new UnsealedDerived(17));
PrintString("Generic call to unsealed derived class as base test: ");
if (dataFromUnsealedAsBase == 34)
{
PrintLine("Ok.");
}
else
{
PrintLine("Failed.");
}
uint dataFromSealedAsBase = GenericGetData<MyBase>(new SealedDerived(19));
PrintString("Generic call to sealed derived class as base test: ");
if (dataFromSealedAsBase == 57)
{
PrintLine("Ok.");
}
else
{
PrintLine("Failed.");
}
// Generic calls to methods defined on object
uint hashCodeOfSealedViaGeneric = (uint)GenericGetHashCode<MySealedClass>(new MySealedClass(37));
PrintString("Generic GetHashCode for sealed class test: ");
if (hashCodeOfSealedViaGeneric == 74)
{
PrintLine("Ok.");
}
else
{
PrintLine("Failed.");
}
uint hashCodeOfUnsealedViaGeneric = (uint)GenericGetHashCode<MyUnsealedClass>(new MyUnsealedClass(41));
PrintString("Generic GetHashCode for unsealed class test: ");
if (hashCodeOfUnsealedViaGeneric == 82)
{
PrintLine("Ok.");
}
else
{
PrintLine("Failed.");
}
}
static uint GenericGetData<T>(T obj) where T : MyBase
{
return obj.GetData();
}
static int GenericGetHashCode<T>(T obj)
{
return obj.GetHashCode();
}
[DllImport("*")]
private static unsafe extern int printf(byte* str, byte* unused);
}
@@ -433,6 +688,38 @@ public class TestDerivedClass : TestClass
}
}
public class StaticsInited
{
public static bool BeforeFieldInitInited;
public static bool NonBeforeFieldInitInited;
}
public class BeforeFieldInitTest
{
public static int TestField = BeforeFieldInit();
public static void Nop() { }
static int BeforeFieldInit()
{
StaticsInited.BeforeFieldInitInited = true;
return 3;
}
}
public class NonBeforeFieldInitTest
{
public static int TestField;
public static void Nop() { }
static NonBeforeFieldInitTest()
{
TestField = 4;
StaticsInited.NonBeforeFieldInitInited = true;
}
}
public interface ICastingTest1
{
int GetValue();
@@ -457,3 +744,110 @@ public class DerivedCastingTestClass2 : CastingTestClass, ICastingTest2
{
public override int GetValue() => 2;
}
public interface ITestItf
{
int GetValue();
}
public struct ItfStruct : ITestItf
{
public int GetValue()
{
return 4;
}
}
public sealed class MySealedClass
{
uint _data;
public MySealedClass()
{
_data = 104;
}
public MySealedClass(uint data)
{
_data = data;
}
public uint GetData()
{
return _data;
}
public override int GetHashCode()
{
return (int)_data * 2;
}
public override string ToString()
{
Program.PrintLine("MySealedClass.ToString called. Data:");
Program.PrintLine(_data.ToString());
return _data.ToString();
}
}
public class MyUnsealedClass
{
uint _data;
public MyUnsealedClass()
{
_data = 24;
}
public MyUnsealedClass(uint data)
{
_data = data;
}
public uint GetData()
{
return _data;
}
public override int GetHashCode()
{
return (int)_data * 2;
}
public override string ToString()
{
return _data.ToString();
}
}
public class MyBase
{
protected uint _data;
public MyBase(uint data)
{
_data = data;
}
public virtual uint GetData()
{
return _data;
}
}
public class UnsealedDerived : MyBase
{
public UnsealedDerived(uint data) : base(data) { }
public override uint GetData()
{
return _data * 2;
}
}
public sealed class SealedDerived : MyBase
{
public SealedDerived(uint data) : base(data) { }
public override uint GetData()
{
return _data * 3;
}
}

View File

@@ -3,9 +3,17 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
// Make sure the interop data are present even without reflection
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.All)]
internal class __BlockAllReflectionAttribute : Attribute { }
}
// Name of namespace matches the name of the assembly on purpose to
// ensure that we can handle this (mostly an issue for C++ code generation).
namespace PInvokeTests
@@ -97,6 +105,9 @@ namespace PInvokeTests
[DllImport("*", CallingConvention = CallingConvention.StdCall)]
public static extern int SafeHandleOutTest(out SafeMemoryHandle sh1);
[DllImport("*", CallingConvention = CallingConvention.StdCall)]
public static extern int SafeHandleRefTest(ref SafeMemoryHandle sh1, bool change);
[DllImport("*", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern bool LastErrorTest();
@@ -104,6 +115,11 @@ namespace PInvokeTests
[DllImport("*", CallingConvention = CallingConvention.StdCall)]
static extern bool ReversePInvoke_Int(Delegate_Int del);
delegate int Delegate_Int_AggressiveInlining(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j);
[DllImport("*", CallingConvention = CallingConvention.StdCall, EntryPoint = "ReversePInvoke_Int")]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static extern bool ReversePInvoke_Int_AggressiveInlining(Delegate_Int_AggressiveInlining del);
[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet=CharSet.Ansi)]
delegate bool Delegate_String(string s);
[DllImport("*", CallingConvention = CallingConvention.StdCall)]
@@ -233,8 +249,9 @@ namespace PInvokeTests
TestSizeParamIndex();
#if !CODEGEN_CPP
TestDelegate();
#endif
TestStruct();
TestMarshalStructAPIs();
#endif
return 100;
}
@@ -435,6 +452,18 @@ namespace PInvokeTests
int actual = SafeHandleOutTest(out hnd2);
int expected = unchecked((int)hnd2.DangerousGetHandle().ToInt64());
ThrowIfNotEquals(actual, expected, "SafeHandle out marshalling failed");
Console.WriteLine("Testing marshalling ref SafeHandle");
SafeMemoryHandle hndOriginal = hnd2;
SafeHandleRefTest(ref hnd2, false);
ThrowIfNotEquals(hndOriginal, hnd2, "SafeHandle no-op ref marshalling failed");
int actual3 = SafeHandleRefTest(ref hnd2, true);
int expected3 = unchecked((int)hnd2.DangerousGetHandle().ToInt64());
ThrowIfNotEquals(actual3, expected3, "SafeHandle ref marshalling failed");
hndOriginal.Dispose();
hnd2.Dispose();
}
private static void TestSizeParamIndex()
@@ -473,8 +502,13 @@ namespace PInvokeTests
private static void TestDelegate()
{
Console.WriteLine("Testing Delegate");
Delegate_Int del = new Delegate_Int(Sum);
ThrowIfNotEquals(true, ReversePInvoke_Int(del), "Delegate marshalling failed.");
Delegate_Int_AggressiveInlining del_aggressive = new Delegate_Int_AggressiveInlining(Sum);
ThrowIfNotEquals(true, ReversePInvoke_Int_AggressiveInlining(del_aggressive), "Delegate marshalling with aggressive inlining failed.");
unsafe
{
//
@@ -562,20 +596,35 @@ namespace PInvokeTests
public ExplicitStruct f2;
}
[StructLayout(LayoutKind.Explicit)]
public struct TestStruct2
{
[FieldOffset(0)]
public int f1;
[FieldOffset(8)]
[StructLayout(LayoutKind.Sequential)]
public struct NonBlittableStruct
{
public int f1;
public bool f2;
public bool f3;
public bool f4;
}
[StructLayout(LayoutKind.Sequential)]
public class BlittableClass
{
public long f1;
public int f2;
public int f3;
public long f4;
}
[StructLayout(LayoutKind.Sequential)]
public class NonBlittableClass
{
public bool f1;
public bool f2;
public int f3;
}
private static void TestStruct()
{
#if !CODEGEN_CPP
Console.WriteLine("Testing Structs");
SequentialStruct ss = new SequentialStruct();
ss.f0 = 100;
@@ -639,24 +688,6 @@ namespace PInvokeTests
InlineUnicodeStruct ius = new InlineUnicodeStruct();
ius.inlineString = "Hello World";
TestStruct2 ts = new TestStruct2() { f1 = 100, f2 = true};
int size = Marshal.SizeOf<TestStruct2>(ts);
IntPtr memory = Marshal.AllocHGlobal(size);
try
{
Marshal.StructureToPtr<TestStruct2>(ts, memory, false);
TestStruct2 ts2 = Marshal.PtrToStructure<TestStruct2>(memory);
ThrowIfNotEquals(true, ts2.f1 == 100 && ts2.f2 == true, "Struct marshalling Marshal API failed");
IntPtr offset = Marshal.OffsetOf<TestStruct2>("f2");
ThrowIfNotEquals(new IntPtr(8), offset, "Struct marshalling OffsetOf failed.");
}
finally
{
Marshal.FreeHGlobal(memory);
}
ThrowIfNotEquals(true, InlineArrayTest(ref ias, ref ius), "inline array marshalling failed");
bool pass = true;
for (short i = 0; i < 128; i++)
@@ -672,7 +703,6 @@ namespace PInvokeTests
ThrowIfNotEquals("Hello World", ius.inlineString, "Inline ByValTStr Unicode marshalling failed");
// RhpThrowEx is not implemented in CPPCodeGen
pass = false;
AutoStruct autoStruct = new AutoStruct();
try
@@ -691,7 +721,59 @@ namespace PInvokeTests
callbacks.callback1 = new Callback1(callbackFunc1);
callbacks.callback2 = new Callback2(callbackFunc2);
ThrowIfNotEquals(true, RegisterCallbacks(ref callbacks), "Scenario 7: Struct with delegate marshalling failed");
#endif
}
private static void TestMarshalStructAPIs()
{
Console.WriteLine("Testing Marshal APIs for structs");
NonBlittableStruct ts = new NonBlittableStruct() { f1 = 100, f2 = true, f3 = false, f4 = true };
int size = Marshal.SizeOf<NonBlittableStruct>(ts);
ThrowIfNotEquals(16, size, "Marshal.SizeOf<NonBlittableStruct> failed");
IntPtr memory = Marshal.AllocHGlobal(size);
try
{
Marshal.StructureToPtr<NonBlittableStruct>(ts, memory, false);
NonBlittableStruct ts2 = Marshal.PtrToStructure<NonBlittableStruct>(memory);
ThrowIfNotEquals(true, ts2.f1 == 100 && ts2.f2 == true && ts2.f3 == false && ts2.f4 == true, "NonBlittableStruct marshalling Marshal API failed");
IntPtr offset = Marshal.OffsetOf<NonBlittableStruct>("f2");
ThrowIfNotEquals(new IntPtr(4), offset, "Struct marshalling OffsetOf failed.");
}
finally
{
Marshal.FreeHGlobal(memory);
}
BlittableClass bc = new BlittableClass() { f1 = 100, f2 = 12345678, f3 = 999, f4 = -4 };
int bc_size = Marshal.SizeOf<BlittableClass>(bc);
ThrowIfNotEquals(24, bc_size, "Marshal.SizeOf<BlittableClass> failed");
IntPtr bc_memory = Marshal.AllocHGlobal(bc_size);
try
{
Marshal.StructureToPtr<BlittableClass>(bc, bc_memory, false);
BlittableClass bc2 = Marshal.PtrToStructure<BlittableClass>(bc_memory);
ThrowIfNotEquals(true, bc2.f1 == 100 && bc2.f2 == 12345678 && bc2.f3 == 999 && bc2.f4 == -4, "BlittableClass marshalling Marshal API failed");
}
finally
{
Marshal.FreeHGlobal(bc_memory);
}
NonBlittableClass nbc = new NonBlittableClass() { f1 = false, f2 = true, f3 = 42 };
int nbc_size = Marshal.SizeOf<NonBlittableClass>(nbc);
ThrowIfNotEquals(12, nbc_size, "Marshal.SizeOf<NonBlittableClass> failed");
IntPtr nbc_memory = Marshal.AllocHGlobal(nbc_size);
try
{
Marshal.StructureToPtr<NonBlittableClass>(nbc, nbc_memory, false);
NonBlittableClass nbc2 = Marshal.PtrToStructure<NonBlittableClass>(nbc_memory);
ThrowIfNotEquals(true, nbc2.f1 == false && nbc2.f2 == true && nbc2.f3 == 42, "NonBlittableClass marshalling Marshal API failed");
}
finally
{
Marshal.FreeHGlobal(nbc_memory);
}
}
}

View File

@@ -313,13 +313,17 @@ DLL_EXPORT bool __stdcall SafeHandleTest(HANDLE sh, long shValue)
DLL_EXPORT long __stdcall SafeHandleOutTest(HANDLE **sh)
{
if (sh == NULL)
return -1;
*sh = (HANDLE *)malloc(100);
return (long)((size_t)(*sh));
}
DLL_EXPORT long __stdcall SafeHandleRefTest(HANDLE **sh, bool alloc)
{
if (alloc)
*sh = (HANDLE *)malloc(100);
return (long)((size_t)(*sh));
}
DLL_EXPORT bool __stdcall ReversePInvoke_Int(int(__stdcall *fnPtr) (int, int, int, int, int, int, int, int, int, int))
{
return fnPtr(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) == 55;

View File

@@ -10,6 +10,7 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Reflection;
[assembly: TestAssembly]
@@ -43,6 +44,7 @@ internal class ReflectionTest
TestCreateDelegate.Run();
TestInstanceFields.Run();
TestReflectionInvoke.Run();
TestByRefReturnInvoke.Run();
return 100;
}
@@ -89,9 +91,34 @@ internal class ReflectionTest
{
return "Hello " + _world;
}
#if OPTIMIZED_MODE_WITHOUT_SCANNER
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
#endif
public static unsafe string GetHelloPointer(char* ptr)
{
return "Hello " + unchecked((int)ptr);
}
#if OPTIMIZED_MODE_WITHOUT_SCANNER
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
#endif
public static unsafe string GetHelloPointerToo(char** ptr)
{
return "Hello " + unchecked((int)ptr);
}
#if OPTIMIZED_MODE_WITHOUT_SCANNER
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
#endif
public static unsafe bool* GetPointer(void* ptr, object dummyJustToMakeThisUseSharedThunk)
{
return (bool*)ptr;
}
}
public static void Run()
public static unsafe void Run()
{
Console.WriteLine(nameof(TestReflectionInvoke));
@@ -102,6 +129,9 @@ internal class ReflectionTest
InvokeTests.GetHello(null);
InvokeTests.GetHelloGeneric<int>(0);
InvokeTests.GetHelloGeneric<double>(0);
InvokeTests.GetHelloPointer(null);
InvokeTests.GetHelloPointerToo(null);
InvokeTests.GetPointer(null, null);
string unused;
InvokeTests.GetHelloByRef(null, out unused);
unused.ToString();
@@ -128,6 +158,31 @@ internal class ReflectionTest
if ((string)args[1] != "Hello world")
throw new Exception();
}
{
MethodInfo helloPointerMethod = typeof(InvokeTests).GetTypeInfo().GetDeclaredMethod("GetHelloPointer");
string resultNull = (string)helloPointerMethod.Invoke(null, new object[] { null });
if (resultNull != "Hello 0")
throw new Exception();
string resultVal = (string)helloPointerMethod.Invoke(null, new object[] { Pointer.Box((void*)42, typeof(char*)) });
if (resultVal != "Hello 42")
throw new Exception();
}
{
MethodInfo helloPointerTooMethod = typeof(InvokeTests).GetTypeInfo().GetDeclaredMethod("GetHelloPointerToo");
string result = (string)helloPointerTooMethod.Invoke(null, new object[] { Pointer.Box((void*)85, typeof(char**)) });
if (result != "Hello 85")
throw new Exception();
}
{
MethodInfo getPointerMethod = typeof(InvokeTests).GetTypeInfo().GetDeclaredMethod("GetPointer");
object result = getPointerMethod.Invoke(null, new object[] { Pointer.Box((void*)2018, typeof(void*)), null });
if (Pointer.Unbox(result) != (void*)2018)
throw new Exception();
}
}
}
@@ -384,7 +439,23 @@ internal class ReflectionTest
}
}
ref struct ByRefLike<T>
{
public readonly T Value;
public ByRefLike(T value)
{
Value = value;
}
public override string ToString()
{
return Value.ToString() + " " + typeof(T).ToString();
}
}
delegate string ToStringDelegate(ref ByRefLike thisObj);
delegate string ToStringDelegate<T>(ref ByRefLike<T> thisObj);
public static void Run()
{
@@ -396,15 +467,40 @@ internal class ReflectionTest
default(ByRefLike).ToString();
ToStringDelegate s = null;
s = s.Invoke;
default(ByRefLike<object>).ToString();
ToStringDelegate<object> s2 = null;
s2 = s2.Invoke;
}
Type byRefLikeType = GetTestType(nameof(TestByRefLikeTypeMethod), nameof(ByRefLike));
MethodInfo toStringMethod = byRefLikeType.GetMethod("ToString");
var toString = (ToStringDelegate)toStringMethod.CreateDelegate(typeof(ToStringDelegate));
{
Type byRefLikeType = GetTestType(nameof(TestByRefLikeTypeMethod), nameof(ByRefLike));
MethodInfo toStringMethod = byRefLikeType.GetMethod("ToString");
var toString = (ToStringDelegate)toStringMethod.CreateDelegate(typeof(ToStringDelegate));
ByRefLike foo = new ByRefLike(123);
if (toString(ref foo) != "123")
throw new Exception();
ByRefLike foo = new ByRefLike(123);
if (toString(ref foo) != "123")
throw new Exception();
}
{
Type byRefLikeGenericType = typeof(ByRefLike<string>);
MethodInfo toStringGenericMethod = byRefLikeGenericType.GetMethod("ToString");
var toStringGeneric = (ToStringDelegate<string>)toStringGenericMethod.CreateDelegate(typeof(ToStringDelegate<string>));
ByRefLike<string> fooGeneric = new ByRefLike<string>("Hello");
if (toStringGeneric(ref fooGeneric) != "Hello System.String")
throw new Exception();
}
{
Type byRefLikeGenericType = typeof(ByRefLike<object>);
MethodInfo toStringGenericMethod = byRefLikeGenericType.GetMethod("ToString");
var toStringGeneric = (ToStringDelegate<object>)toStringGenericMethod.CreateDelegate(typeof(ToStringDelegate<object>));
ByRefLike<object> fooGeneric = new ByRefLike<object>("Hello");
if (toStringGeneric(ref fooGeneric) != "Hello System.Object")
throw new Exception();
}
}
}
@@ -501,6 +597,203 @@ internal class ReflectionTest
}
}
class TestByRefReturnInvoke
{
enum Mine { One = 2018 }
[StructLayout(LayoutKind.Sequential)]
struct BigStruct { public ulong X, Y, Z, W, A, B, C, D; }
public ref struct ByRefLike { }
private sealed class TestClass<T>
{
private T _value;
public TestClass(T value) { _value = value; }
public ref T RefReturningProp
{
#if OPTIMIZED_MODE_WITHOUT_SCANNER
[MethodImpl(MethodImplOptions.NoInlining)]
#endif
get => ref _value;
}
#if OPTIMIZED_MODE_WITHOUT_SCANNER
[MethodImpl(MethodImplOptions.NoInlining)]
#endif
public static unsafe ref ByRefLike ByRefLikeRefReturningMethod(ByRefLike* a) => ref *a;
}
private sealed unsafe class TestClassIntPointer
{
private int* _value;
public TestClassIntPointer(int* value) { _value = value; }
public ref int* RefReturningProp
{
#if OPTIMIZED_MODE_WITHOUT_SCANNER
[MethodImpl(MethodImplOptions.NoInlining)]
#endif
get => ref _value;
}
public unsafe ref int* NullRefReturningProp
{
#if OPTIMIZED_MODE_WITHOUT_SCANNER
[MethodImpl(MethodImplOptions.NoInlining)]
#endif
get => ref *(int**)null;
}
}
public static void TestRefReturnPropertyGetValue()
{
TestRefReturnInvoke('a', (p, t) => p.GetValue(t));
TestRefReturnInvoke(Mine.One, (p, t) => p.GetValue(t));
TestRefReturnInvoke("Hello", (p, t) => p.GetValue(t));
TestRefReturnInvoke(new BigStruct { X = 123, D = 456 }, (p, t) => p.GetValue(t));
TestRefReturnInvoke(new object(), (p, t) => p.GetValue(t));
TestRefReturnInvoke((object)null, (p, t) => p.GetValue(t));
}
public static void TestRefReturnMethodInvoke()
{
TestRefReturnInvoke(Mine.One, (p, t) => p.GetGetMethod().Invoke(t, Array.Empty<object>()));
TestRefReturnInvoke("Hello", (p, t) => p.GetGetMethod().Invoke(t, Array.Empty<object>()));
TestRefReturnInvoke(new BigStruct { X = 123, D = 456 }, (p, t) => p.GetGetMethod().Invoke(t, Array.Empty<object>()));
TestRefReturnInvoke(new object(), (p, t) => p.GetGetMethod().Invoke(t, Array.Empty<object>()));
TestRefReturnInvoke((object)null, (p, t) => p.GetGetMethod().Invoke(t, Array.Empty<object>()));
}
public static void TestRefReturnNullable()
{
TestRefReturnInvokeNullable<int>(42);
TestRefReturnInvokeNullable<Mine>(Mine.One);
TestRefReturnInvokeNullable<BigStruct>(new BigStruct { X = 987, D = 543 });
}
public static void TestRefReturnNullableNoValue()
{
TestRefReturnInvokeNullable<int>(default(int?));
TestRefReturnInvokeNullable<Mine>(default(Mine?));
TestRefReturnInvokeNullable<BigStruct>(default(BigStruct?));
}
public static unsafe void TestRefReturnOfPointer()
{
int* expected = (int*)0x1122334455667788;
TestClassIntPointer tc = new TestClassIntPointer(expected);
if (string.Empty.Length > 0)
{
((IntPtr)tc.RefReturningProp).ToString();
}
PropertyInfo p = typeof(TestClassIntPointer).GetProperty(nameof(TestClassIntPointer.RefReturningProp));
object rv = p.GetValue(tc);
Assert.True(rv is Pointer);
int* actual = (int*)(Pointer.Unbox(rv));
Assert.Equal((IntPtr)expected, (IntPtr)actual);
}
public static unsafe void TestNullRefReturnOfPointer()
{
TestClassIntPointer tc = new TestClassIntPointer(null);
if (string.Empty.Length > 0)
{
((IntPtr)tc.NullRefReturningProp).ToString();
}
PropertyInfo p = typeof(TestClassIntPointer).GetProperty(nameof(TestClassIntPointer.NullRefReturningProp));
Assert.NotNull(p);
Assert.Throws<NullReferenceException>(() => p.GetValue(tc));
}
public static unsafe void TestByRefLikeRefReturn()
{
if (string.Empty.Length > 0)
{
TestClass<int>.ByRefLikeRefReturningMethod(null);
}
ByRefLike brl = new ByRefLike();
ByRefLike* pBrl = &brl;
MethodInfo mi = typeof(TestClass<int>).GetMethod(nameof(TestClass<int>.ByRefLikeRefReturningMethod));
try
{
// Don't use Assert.Throws because that will make a lambda and invalidate the pointer
object o = mi.Invoke(null, new object[] { Pointer.Box(pBrl, typeof(ByRefLike*)) });
Assert.Fail();
}
catch (NotSupportedException)
{
}
}
private static void TestRefReturnInvoke<T>(T value, Func<PropertyInfo, TestClass<T>, object> invoker)
{
TestClass<T> tc = new TestClass<T>(value);
if (String.Empty.Length > 0)
{
tc.RefReturningProp.ToString();
}
PropertyInfo p = typeof(TestClass<T>).GetProperty(nameof(TestClass<T>.RefReturningProp));
object rv = invoker(p, tc);
if (rv != null)
{
Assert.Equal(typeof(T), rv.GetType());
}
if (typeof(T).IsValueType)
{
Assert.Equal(value, rv);
}
else
{
Assert.Same(value, rv);
}
}
private static void TestRefReturnInvokeNullable<T>(T? nullable) where T : struct
{
TestClass<T?> tc = new TestClass<T?>(nullable);
if (string.Empty.Length > 0)
{
tc.RefReturningProp.ToString();
}
PropertyInfo p = typeof(TestClass<T?>).GetProperty(nameof(TestClass<T?>.RefReturningProp));
object rv = p.GetValue(tc);
if (rv != null)
{
Assert.Equal(typeof(T), rv.GetType());
}
if (nullable.HasValue)
{
Assert.Equal(nullable.Value, rv);
}
else
{
Assert.Null(rv);
}
}
public static void Run()
{
Console.WriteLine(nameof(TestByRefReturnInvoke));
TestRefReturnPropertyGetValue();
TestRefReturnMethodInvoke();
TestRefReturnNullable();
TestRefReturnNullableNoValue();
TestRefReturnOfPointer();
TestNullRefReturnOfPointer();
TestByRefLikeRefReturn();
}
}
#region Helpers
private static Type GetTestType(string testName, string typeName)
@@ -534,6 +827,66 @@ internal class ReflectionTest
return true;
}
class Assert
{
public static void Equal<T>(T expected, T actual)
{
if (object.ReferenceEquals(expected, actual))
return;
if ((object)expected == null || (object)actual == null)
throw new Exception();
if (!expected.Equals(actual))
throw new Exception();
}
public static void Same<T>(T expected, T actual)
{
if (!object.ReferenceEquals(expected, actual))
throw new Exception();
}
public static void Null(object x)
{
if (x != null)
throw new Exception();
}
public static void NotNull(object x)
{
if (x == null)
throw new Exception();
}
public static void True(bool x)
{
if (!x)
throw new Exception();
}
public static void Fail()
{
throw new Exception();
}
public static void Throws<T>(Action a)
{
try
{
a();
}
catch (Exception ex)
{
if (ex.GetType() != typeof(T))
throw new Exception();
return;
}
throw new Exception();
}
}
#endregion
}

View File

@@ -0,0 +1,14 @@
// 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.
namespace System.Runtime.InteropServices
{
[AttributeUsage(AttributeTargets.Method)]
public sealed class NativeCallableAttribute : Attribute
{
public string EntryPoint;
public CallingConvention CallingConvention;
public NativeCallableAttribute() { }
}
}

View File

@@ -0,0 +1,12 @@
@echo off
setlocal
"%1\%2"
set ErrorCode=%ERRORLEVEL%
IF "%ErrorCode%"=="100" (
echo %~n0: pass
EXIT /b 0
) ELSE (
echo %~n0: fail - %ErrorCode%
EXIT /b 1
)
endlocal

View File

@@ -0,0 +1,66 @@
// 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.
#ifdef _WIN32
#include "windows.h"
#else
#include "dlfcn.h"
#endif
#include "stdio.h"
#include "string.h"
#ifndef _WIN32
#define __stdcall
#endif
// typedef for shared lib exported methods
typedef int(__stdcall *f_ReturnsPrimitiveInt)();
typedef bool(__stdcall *f_ReturnsPrimitiveBool)();
typedef char(__stdcall *f_ReturnsPrimitiveChar)();
typedef void(__stdcall *f_EnsureManagedClassLoaders)();
#ifdef _WIN32
int main()
#else
int main(int argc, char* argv[])
#endif
{
#ifdef _WIN32
HINSTANCE handle = LoadLibrary("SharedLibrary.dll");
#elif __APPLE__
void *handle = dlopen(strcat(argv[0], ".dylib"), RTLD_LAZY);
#else
void *handle = dlopen(strcat(argv[0], ".so"), RTLD_LAZY);
#endif
if (!handle)
return 1;
#ifdef _WIN32
f_ReturnsPrimitiveInt returnsPrimitiveInt = (f_ReturnsPrimitiveInt)GetProcAddress(handle, "ReturnsPrimitiveInt");
f_ReturnsPrimitiveBool returnsPrimitiveBool = (f_ReturnsPrimitiveBool)GetProcAddress(handle, "ReturnsPrimitiveBool");
f_ReturnsPrimitiveChar returnsPrimitiveChar = (f_ReturnsPrimitiveChar)GetProcAddress(handle, "ReturnsPrimitiveChar");
f_EnsureManagedClassLoaders ensureManagedClassLoaders = (f_EnsureManagedClassLoaders)GetProcAddress(handle, "EnsureManagedClassLoaders");
#else
f_ReturnsPrimitiveInt returnsPrimitiveInt = (f_ReturnsPrimitiveInt)dlsym(handle, "ReturnsPrimitiveInt");
f_ReturnsPrimitiveBool returnsPrimitiveBool = (f_ReturnsPrimitiveBool)dlsym(handle, "ReturnsPrimitiveBool");
f_ReturnsPrimitiveChar returnsPrimitiveChar = (f_ReturnsPrimitiveChar)dlsym(handle, "ReturnsPrimitiveChar");
f_EnsureManagedClassLoaders ensureManagedClassLoaders = (f_EnsureManagedClassLoaders)dlsym(handle, "EnsureManagedClassLoaders");
#endif
if (returnsPrimitiveInt() != 10)
return 1;
if (!returnsPrimitiveBool())
return 1;
if (returnsPrimitiveChar() != 'a')
return 1;
// As long as no unmanaged exception is thrown
// managed class loaders were initialized successfully
ensureManagedClassLoaders();
return 100;
}

View File

@@ -0,0 +1,37 @@
// 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;
using System.Runtime.InteropServices;
namespace SharedLibrary
{
public class ClassLibrary
{
[NativeCallable(EntryPoint = "ReturnsPrimitiveInt", CallingConvention = CallingConvention.StdCall)]
public static int ReturnsPrimitiveInt()
{
return 10;
}
[NativeCallable(EntryPoint = "ReturnsPrimitiveBool", CallingConvention = CallingConvention.StdCall)]
public static bool ReturnsPrimitiveBool()
{
return true;
}
[NativeCallable(EntryPoint = "ReturnsPrimitiveChar", CallingConvention = CallingConvention.StdCall)]
public static char ReturnsPrimitiveChar()
{
return 'a';
}
[NativeCallable(EntryPoint = "EnsureManagedClassLoaders", CallingConvention = CallingConvention.StdCall)]
public static void EnsureManagedClassLoaders()
{
Random random = new Random();
random.Next();
}
}
}

View File

@@ -0,0 +1,35 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<OutputType>Library</OutputType>
<NativeLib>Shared</NativeLib>
</PropertyGroup>
<ItemGroup>
<Compile Include="*.cs" />
</ItemGroup>
<Target Name="NativeRunnerCompile" AfterTargets="LinkNative">
<PropertyGroup>
<NativeRunnerBinary>$(NativeOutputPath)SharedLibrary</NativeRunnerBinary>
</PropertyGroup>
<ItemGroup>
<CppCompile Include="SharedLibrary.cpp" />
</ItemGroup>
<ItemGroup>
<NativeRunnerCompilerArg Include="@(CppCompile)" />
<NativeRunnerCompilerArg Include="-o $(NativeRunnerBinary)" Condition="'$(OS)' != 'Windows_NT'" />
<NativeRunnerCompilerArg Include="/Fo$(NativeRunnerBinary)" Condition="'$(OS)' == 'Windows_NT'" />
<NativeRunnerCompilerArg Include="/Fe$(NativeRunnerBinary)" Condition="'$(OS)' == 'Windows_NT'" />
</ItemGroup>
<Exec Command="$(CppCompiler) @(NativeRunnerCompilerArg, ' ')" Condition="'$(OS)' != 'Windows_NT'" />
<WriteLinesToFile File="$(NativeIntermediateOutputPath)SharedLibrary.cl.rsp" Lines="@(NativeRunnerCompilerArg)" Overwrite="true" Condition="'$(OS)' == 'Windows_NT'"/>
<Exec Command="$(CppCompiler) @&quot;$(NativeIntermediateOutputPath)SharedLibrary.cl.rsp&quot;" Condition="'$(OS)' == 'Windows_NT'" />
</Target>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), SimpleTest.targets))\SimpleTest.targets" />
</Project>

View File

@@ -0,0 +1,9 @@
#!/usr/bin/env bash
$1/$2
if [ $? == 100 ]; then
echo pass
exit 0
else
echo fail
exit 1
fi

Some files were not shown because too many files have changed in this diff Show More