summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRama Krishnan Raghupathy <ramarag@microsoft.com>2015-03-06 18:15:55 -0800
committerRama Krishnan Raghupathy <ramarag@microsoft.com>2015-03-06 18:15:55 -0800
commit2a1f5a35ad3678f9175a0c937eeb07a29c65ba8a (patch)
treeb0a65a0a4785e4deb39ec1eed8eba4ddff486b79
parent182d4e2ef3bea406de49147bb732767fa6190f93 (diff)
downloadcoreclr-2a1f5a35ad3678f9175a0c937eeb07a29c65ba8a.tar.gz
coreclr-2a1f5a35ad3678f9175a0c937eeb07a29c65ba8a.tar.bz2
coreclr-2a1f5a35ad3678f9175a0c937eeb07a29c65ba8a.zip
With This change the tests build all the native components first and then builds the managed components. The managed components can refer to the native projects by the following construct in the .csproj
<ProjectReference Include="CMakeLists.txt"> [tfs-changeset: 1427574]
-rw-r--r--src/pal/tools/gen-buildsys-win.bat4
-rw-r--r--tests/CMakeLists.txt31
-rw-r--r--tests/buildtest.cmd72
-rw-r--r--tests/src/AllTestProjects.sln21
-rw-r--r--tests/src/Common/Platform/platformdefines.cpp338
-rw-r--r--tests/src/Common/Platform/platformdefines.h133
-rw-r--r--tests/src/Interop/ReversePInvoke/Marshalling/CMakeLists.txt12
-rw-r--r--tests/src/Interop/ReversePInvoke/Marshalling/MarshalBoolArray.cs274
-rw-r--r--tests/src/Interop/ReversePInvoke/Marshalling/MarshalBoolArray.csproj49
-rw-r--r--tests/src/Interop/ReversePInvoke/Marshalling/MarshalBoolArrayDLL.cpp236
-rw-r--r--tests/src/Interop/ReversePInvoke/Marshalling/MarshalBoolArrayDLL.def8
-rw-r--r--tests/src/Interop/ReversePInvoke/Marshalling/app.config27
-rw-r--r--tests/src/Interop/ReversePInvoke/Marshalling/packages.config12
-rw-r--r--tests/src/dir.common.props7
-rw-r--r--tests/src/dir.targets51
15 files changed, 1260 insertions, 15 deletions
diff --git a/src/pal/tools/gen-buildsys-win.bat b/src/pal/tools/gen-buildsys-win.bat
index ac51caa0e0..6dc56585fa 100644
--- a/src/pal/tools/gen-buildsys-win.bat
+++ b/src/pal/tools/gen-buildsys-win.bat
@@ -9,7 +9,7 @@ if NOT %argC%==1 GOTO :USAGE
if %1=="/?" GOTO :USAGE
setlocal
-set basePath=%1
+set basePath=%~dp0
:: remove quotes
set "basePath=%basePath:"=%"
:: remove trailing slash
@@ -21,7 +21,7 @@ if defined CMakePath goto DoGen
for /f "delims=" %%a in ('powershell -NoProfile -ExecutionPolicy RemoteSigned "& .\probe-win.ps1"') do %%a
:DoGen
-"%CMakePath%" "-DCMAKE_USER_MAKE_RULES_OVERRIDE=%basePath%\src\pal\tools\windows-compiler-override.txt" -G "Visual Studio 12 2013 Win64" %1
+"%CMakePath%" "-DCMAKE_USER_MAKE_RULES_OVERRIDE=%basePath%\windows-compiler-override.txt" -G "Visual Studio 12 2013 Win64" %1
endlocal
GOTO :DONE
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 0000000000..f2d444c436
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,31 @@
+# Require at least version 2.8.12 of CMake
+cmake_minimum_required(VERSION 2.8.12)
+
+set(INC_PLATFORM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/Common/Platform)
+if (WIN32)
+ add_definitions(-DWINDOWS=1)
+endif()
+
+MACRO(SUBDIRLIST result curdir)
+ FILE(GLOB children RELATIVE ${curdir} ${curdir}/*)
+ SET(dirlist "")
+ FOREACH(child ${children})
+ IF(IS_DIRECTORY ${curdir}/${child})
+ LIST(APPEND dirlist ${child})
+ ENDIF()
+ ENDFOREACH()
+ SET(${result} ${dirlist})
+ENDMACRO()
+
+MACRO(ADDSUBDIR_REC curdir)
+ SUBDIRLIST(SUB_DIRS ${curdir})
+ FOREACH(subdir ${SUB_DIRS})
+ if(EXISTS "${curdir}/${subdir}/CMakeLists.txt")
+ ADD_SUBDIRECTORY(${curdir}/${subdir})
+ else()
+ ADDSUBDIR_REC(${curdir}/${subdir})
+ endif(EXISTS "${curdir}/${subdir}/CMakeLists.txt")
+ ENDFOREACH()
+ENDMACRO()
+
+ADDSUBDIR_REC(${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/tests/buildtest.cmd b/tests/buildtest.cmd
index b72856bf4a..414889232d 100644
--- a/tests/buildtest.cmd
+++ b/tests/buildtest.cmd
@@ -23,9 +23,12 @@ if not defined __BuildOS set __BuildOS=Windows_NT
if not defined __TestWorkingDir set "__TestWorkingDir=%__ProjectFilesDir%\..\binaries\tests\%__BuildOS%.%__BuildArch%.%__BuildType%"
if not defined __LogsDir set "__LogsDir=%__ProjectFilesDir%..\binaries\Logs"
+if not defined __ProductSourceDir set "__ProductSourceDir=%__ProjectFilesDir%..\src"
-set "__TestBuildLog=%__LogsDir%\Tests_%__BuildOS%__%__BuildArch%__%__BuildType%.log"
+set "__TestManagedBuildLog=%__LogsDir%\Tests_Managed_%__BuildOS%__%__BuildArch%__%__BuildType%.log"
+set "__TestNativeBuildLog=%__LogsDir%\Tests_Native_%__BuildOS%__%__BuildArch%__%__BuildType%.log"
set "__XunitWrapperBuildLog=%__LogsDir%\Tests_XunitWrapper_%__BuildOS%__%__BuildArch%__%__BuildType%.log"
+set "__CMakeTestSlnDir=%__TestWorkingDir%\CMake\"
:: Switch to clean build mode if the binaries output folder does not exist
if not exist "%__TestWorkingDir%" set __CleanBuild=1
@@ -50,8 +53,19 @@ if exist "%__TestWorkingDir%" rd /s /q "%__TestWorkingDir%"
:: Check prerequisites
:CheckPrereqs
+echo Checking pre-requisites...
+echo.
+:: Eval the output from probe-win1.ps1
+for /f "delims=" %%a in ('powershell -NoProfile -ExecutionPolicy RemoteSigned "& ""%__ProductSourceDir%\pal\tools\probe-win.ps1"""') do %%a
+
:: Check presence of VS
-if defined VS120COMNTOOLS goto CheckMSbuild
+if defined VS120COMNTOOLS goto CheckVSExistence
+echo Installation of VS 2013 is a pre-requisite to build this repository.
+goto :eof
+
+:CheckVSExistence
+:: Does VS 2013 really exist?
+if exist "%VS120COMNTOOLS%\..\IDE\devenv.exe" goto CheckMSBuild
echo Installation of VS 2013 is a pre-requisite to build this repository.
goto :eof
@@ -62,18 +76,61 @@ if not exist %_msbuildexe% set _msbuildexe="%ProgramFiles(x86)%\MSBuild\14.0\Bin
if not exist %_msbuildexe% set _msbuildexe="%ProgramFiles%\MSBuild\14.0\Bin\MSBuild.exe"
if not exist %_msbuildexe% echo Error: Could not find MSBuild.exe. Please see https://github.com/dotnet/coreclr/wiki/Developer%%20Guide for build instructions. && exit /b 1
-:: Set the environment for the build- Vs cmd prompt
+::Building Native part of Tests
+setlocal
+
+echo Commencing build of native test components for %__BuildArch%/%__BuildType%
+echo.
+
+:: Set the environment for the native build
+call "%VS120COMNTOOLS%..\..\VC\vcvarsall.bat" x86_amd64
+
+if exist "%VSINSTALLDIR%DIA SDK" goto GenVSSolution
+echo Error: DIA SDK is missing at "%VSINSTALLDIR%DIA SDK". ^
+This is due to bug in VS Intaller. It does not install DIA SDK at "%VSINSTALLDIR%" but rather ^
+at VS install location of previous version. Workaround is to copy DIA SDK folder from VS install location ^
+of previous version to "%VSINSTALLDIR%" and then resume build.
+goto :eof
+
+:GenVSSolution
+:: Regenerate the VS solution
+if not exist "%__CMakeTestSlnDir%" md "%__CMakeTestSlnDir%"
+pushd "%__CMakeTestSlnDir%"
+call "%__ProductSourceDir%\pal\tools\gen-buildsys-win.bat" "%__ProjectFilesDir%\"
+popd
+
+:BuildComponents
+if exist "%__CMakeTestSlnDir%\install.vcxproj" goto BuildTestNativeComponents
+echo Failed to generate test native component build project!
+goto :eof
+
+REM Build CoreCLR
+:BuildTestNativeComponents
+%_msbuildexe% "%__CMakeTestSlnDir%\install.vcxproj" %__MSBCleanBuildArgs% /nologo /maxcpucount /nodeReuse:false /p:Configuration=%__BuildType% /p:Platform=%__BuildArch% /fileloggerparameters:Verbosity=diag;LogFile="%__TestNativeBuildLog%"
+IF NOT ERRORLEVEL 1 goto PerformManagedTestBuild
+echo Native component build failed. Refer !__TestNativeBuildLog! for details.
+goto :eof
+
+:PerformManagedTestBuild
+REM endlocal to rid us of environment changes from vcvarsall.bat
+endlocal
+::End Building native tests
+
+::Building Managed Tests
+REM setlocal to prepare for vsdevcmd.bat
+setlocal
+:: Set the environment for the managed build- Vs cmd prompt
call "%VS120COMNTOOLS%\VsDevCmd.bat"
if not defined VSINSTALLDIR echo Error: build.cmd should be run from a Visual Studio Command Prompt. Please see https://github.com/dotnet/coreclr/wiki/Developer%%20Guide for build instructions. && exit /b 1
:BuildTests
-echo Starting the Test Build
+echo Starting the Manged Tests Build
echo.
:: Log build command line
set _buildprefix=echo
-set _buildpostfix=^> "%__TestBuildLog%"
+set _buildpostfix=^> "%__TestManagedBuildLog%"
set _buildappend=^>
call :build %1
@@ -87,9 +144,10 @@ goto :eof
:build
-%_buildprefix% %_msbuildexe% "%__ProjectFilesDir%build.proj" %__MSBCleanBuildArgs% /nologo /maxcpucount /verbosity:minimal /nodeReuse:false /fileloggerparameters:Verbosity=diag;LogFile="%__TestBuildLog%";Append %* %_buildpostfix%
-IF ERRORLEVEL 1 echo Test build failed. Refer !__TestBuildLog! for details && exit /b 1
+%_buildprefix% %_msbuildexe% "%__ProjectFilesDir%build.proj" %__MSBCleanBuildArgs% /nologo /maxcpucount /verbosity:minimal /nodeReuse:false /fileloggerparameters:Verbosity=diag;LogFile="%__TestManagedBuildLog%";Append %* %_buildpostfix%
+IF ERRORLEVEL 1 echo Test build failed. Refer !__TestManagedBuildLog! for details && exit /b 1
+endlocal
diff --git a/tests/src/AllTestProjects.sln b/tests/src/AllTestProjects.sln
index 1b54f77b67..854bea5ce2 100644
--- a/tests/src/AllTestProjects.sln
+++ b/tests/src/AllTestProjects.sln
@@ -67,6 +67,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{48E19BDB
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GC_Stress_tests_collection", "GC\Stress\Tests\GC_Stress_tests_collection.csproj", "{700E904F-A5F0-4B05-835B-EB256F4202B0}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Interop", "Interop", "{7D929CA5-2230-4EE1-990F-C518A9BEA68A}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ReversePInvoke", "ReversePInvoke", "{C0216064-946C-46BA-BAAA-406F1B4E32B5}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Marshalling", "Marshalling", "{24951158-FCC2-46D4-8982-2B34A6A8EB1B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MarshalBoolArray", "Interop\ReversePInvoke\Marshalling\MarshalBoolArray.csproj", "{F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -215,6 +223,16 @@ Global
{700E904F-A5F0-4B05-835B-EB256F4202B0}.Release|Mixed Platforms.Build.0 = Release|x64
{700E904F-A5F0-4B05-835B-EB256F4202B0}.Release|x64.ActiveCfg = Release|x64
{700E904F-A5F0-4B05-835B-EB256F4202B0}.Release|x64.Build.0 = Release|x64
+ {F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}.Debug|Mixed Platforms.ActiveCfg = Debug|x64
+ {F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}.Debug|Mixed Platforms.Build.0 = Debug|x64
+ {F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}.Debug|x64.ActiveCfg = Debug|x64
+ {F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}.Debug|x64.Build.0 = Debug|x64
+ {F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}.Release|Any CPU.ActiveCfg = Release|x64
+ {F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}.Release|Mixed Platforms.ActiveCfg = Release|x64
+ {F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}.Release|Mixed Platforms.Build.0 = Release|x64
+ {F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}.Release|x64.ActiveCfg = Release|x64
+ {F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -245,5 +263,8 @@ Global
{65972FF1-AE77-4CB3-B31D-9CA483DD9E2E} = {776B49A7-C77A-42ED-AFA7-73E255FC889E}
{48E19BDB-F7F5-4FEF-ABA9-7FEEAC96D265} = {A0C4F281-CA64-4794-A786-F3F80FCC5A06}
{700E904F-A5F0-4B05-835B-EB256F4202B0} = {48E19BDB-F7F5-4FEF-ABA9-7FEEAC96D265}
+ {C0216064-946C-46BA-BAAA-406F1B4E32B5} = {7D929CA5-2230-4EE1-990F-C518A9BEA68A}
+ {24951158-FCC2-46D4-8982-2B34A6A8EB1B} = {C0216064-946C-46BA-BAAA-406F1B4E32B5}
+ {F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0} = {24951158-FCC2-46D4-8982-2B34A6A8EB1B}
EndGlobalSection
EndGlobal
diff --git a/tests/src/Common/Platform/platformdefines.cpp b/tests/src/Common/Platform/platformdefines.cpp
new file mode 100644
index 0000000000..e5144e9328
--- /dev/null
+++ b/tests/src/Common/Platform/platformdefines.cpp
@@ -0,0 +1,338 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+
+#include "platformdefines.h"
+
+LPWSTR HackyConvertToWSTR(char* pszInput)
+{
+ size_t cchInput;
+ LPWSTR pwszOutput;
+ char* pStr;
+
+ if (NULL == pszInput) return NULL;
+
+ // poor mans strlen
+ pStr = pszInput;
+ cchInput = 0;
+ while('\0' != *pStr) {cchInput++; pStr++;}
+ pwszOutput = new WCHAR[ cchInput + 1];
+
+ for(size_t i=0; i<=cchInput; i++)
+ {
+ pwszOutput[i] = (WCHAR)pszInput[i];
+ }
+
+ return pwszOutput;
+}
+
+LPSTR HackyConvertToSTR(LPWSTR pwszInput)
+{
+ size_t cchInput;
+ LPSTR pszOutput;
+ LPWSTR pStr;
+
+ if (NULL == pwszInput) return NULL;
+
+ cchInput = wcslen(pwszInput);
+ pszOutput = new char[ cchInput + 1];
+
+ for(size_t i=0; i<=cchInput; i++)
+ {
+ // ugly down cast
+ pszOutput[i] = (char)pwszInput[i];
+ }
+
+ return pszOutput;
+}
+
+error_t TP_scpy_s(LPWSTR strDestination, size_t sizeInWords, LPCWSTR strSource)
+{
+ int cnt;
+ // copy sizeInBytes bytes of strSource into strDestination
+
+ if (NULL == strDestination || NULL == strSource) return 1;
+
+ cnt = 0;
+ while(cnt < sizeInWords && '\0' != strSource[cnt])
+ {
+ strDestination[cnt] = strSource[cnt];
+ cnt++;
+ }
+ strDestination[cnt] = '\0';
+
+ return 0;
+}
+
+error_t TP_scat_s(LPWSTR strDestination, size_t sizeInWords, LPCWSTR strSource)
+{
+ LPWSTR strEnd;
+ // locate the end (ie. '\0') and TP_scpy_s the string
+
+ if (NULL == strDestination || NULL == strSource) return 1;
+
+ strEnd = strDestination;
+ while('\0' != *strEnd) strEnd++;
+
+ return TP_scpy_s(strEnd, sizeInWords - ((strEnd - strDestination) / sizeof(WCHAR)), strSource);
+}
+
+int TP_slen(LPWSTR str)
+{
+ int len;
+
+ if (NULL == str) return 0;
+
+ len = 0;
+ while('\0' != *(str+len)) len++;
+
+ return len;
+}
+
+int TP_scmp_s(LPSTR str1, LPSTR str2)
+{
+ // < 0 str1 less than str2
+ // 0 str1 identical to str2
+ // > 0 str1 greater than str2
+
+ if (NULL == str1 && NULL != str2) return -1;
+ if (NULL != str1 && NULL == str2) return 1;
+ if (NULL == str1 && NULL == str2) return 0;
+
+ while (*str1 == *str2 && '\0' != *str1 && '\0' != *str2)
+ {
+ str1++;
+ str2++;
+ }
+
+ if ('\0' == *str1 && '\0' == *str2) return 0;
+
+ if ('\0' != *str1) return -1;
+ if ('\0' != *str2) return 1;
+
+ return (*str1 > *str2) ? 1 : -1;
+}
+
+int TP_wcmp_s(LPWSTR str1, LPWSTR str2)
+{
+ // < 0 str1 less than str2
+ // 0 str1 identical to str2
+ // > 0 str1 greater than str2
+
+ if (NULL == str1 && NULL != str2) return -1;
+ if (NULL != str1 && NULL == str2) return 1;
+ if (NULL == str1 && NULL == str2) return 0;
+
+ while (*str1 == *str2 && '\0' != *str1 && '\0' != *str2)
+ {
+ str1++;
+ str2++;
+ }
+
+ if ('\0' == *str1 && '\0' == *str2) return 0;
+
+ if ('\0' != *str1) return -1;
+ if ('\0' != *str2) return 1;
+
+ return (*str1 > *str2) ? 1 : -1;
+}
+
+error_t TP_getenv_s(size_t* pReturnValue, LPWSTR buffer, size_t sizeInWords, LPCWSTR varname)
+{
+ if (NULL == pReturnValue || NULL == varname) return 1;
+
+#ifdef WINDOWS
+
+ size_t returnValue;
+ WCHAR buf[100];
+ if( 0 != _wgetenv_s(&returnValue, buf, 100, varname) || returnValue<=0 )
+ return 2;
+
+
+ TP_scpy_s(buffer, sizeInWords, (LPWSTR)buf);
+#else
+ LPSTR pRet;
+ pRet = getenv( HackyConvertToSTR((LPWSTR)varname) );
+ if (NULL == pRet) return 2;
+ TP_scpy_s(buffer, sizeInWords, HackyConvertToWSTR(pRet));
+#endif
+ return 0;
+}
+
+error_t TP_putenv_s(LPTSTR name, LPTSTR value)
+{
+ if (NULL == name || NULL == value) return 1;
+
+#ifdef WINDOWS
+ if( 0 != _putenv_s(name, value))
+ return 2;
+ else
+ return 0;
+#else
+ int retVal = 0;
+ char *assignment = (char*) malloc(sizeof(char) * (strlen(name) + strlen(value) + 1));
+ sprintf(assignment, "%s=%s", name, value);
+
+ if (0 != putenv(assignment))
+ retVal = 2;
+ free(assignment);
+ return retVal;
+#endif
+}
+
+void TP_ZeroMemory(LPVOID buffer, size_t sizeInBytes)
+{
+ BYTE* bBuf;
+
+ // clear out the memory with 0's
+ if (NULL == buffer) return;
+
+ bBuf = (BYTE*)buffer;
+ for(int i=0; i<sizeInBytes; i++)
+ {
+ bBuf[i] = 0;
+ }
+}
+
+error_t TP_itow_s(int num, LPWSTR buffer, size_t sizeInCharacters, int radix)
+{
+ int len;
+ int tmpNum;
+
+ // only support radix == 10 and only positive numbers
+ if (10 != radix) return 1;
+ if (0 > num) return 2;
+ if (NULL == buffer) return 3;
+ if (2 > sizeInCharacters) return 4;
+
+ // take care of the trivial case
+ if (0 == num)
+ {
+ buffer[0] = '\0';
+ buffer[1] = '\0';
+ }
+
+ // get length of final string (dumb implementation)
+ len = 0;
+ tmpNum = num;
+ while (0 < tmpNum)
+ {
+ tmpNum /= 10;
+ len++;
+ }
+
+ if (len >= sizeInCharacters) return 5;
+
+ // convert num into a string (backwards)
+ buffer[len] = '\0';
+ len--;
+ while(0 < num && 0 <= len)
+ {
+ buffer[len] = (WCHAR)((num % 10) + '0');
+ len--;
+ num /= 10;
+ }
+
+ return 0;
+}
+
+LPWSTR TP_sstr(LPWSTR str, LPWSTR searchStr)
+{
+ LPWSTR start;
+ LPWSTR current;
+ LPWSTR searchCurrent;
+
+ if (NULL == str || NULL == searchStr) return NULL;
+
+ // return a pointer to where searchStr
+ // exists in str
+ current = str;
+ start = NULL;
+ searchCurrent = searchStr;
+ while('\0' != *current)
+ {
+ if (NULL != start && '\0' == *searchCurrent)
+ {
+ break;
+ }
+
+ if (*current == *searchCurrent)
+ {
+ searchCurrent++;
+ if (NULL == start) start = current;
+ }
+ else
+ {
+ searchCurrent = searchStr;
+ start = NULL;
+ }
+ current++;
+ }
+
+ return start;
+}
+
+DWORD TP_GetFullPathName(LPWSTR fileName, DWORD nBufferLength, LPWSTR lpBuffer)
+{
+#ifdef WINDOWS
+ return GetFullPathNameW(fileName, nBufferLength, lpBuffer, NULL);
+#else
+ char nativeFullPath[MAX_PATH];
+ realpath(HackyConvertToSTR(fileName), nativeFullPath);
+ LPWSTR fullPathForCLR = HackyConvertToWSTR(nativeFullPath);
+ wcscpy_s(lpBuffer, MAX_PATH, fullPathForCLR);
+ return wcslen(lpBuffer);
+#endif
+}
+DWORD TP_CreateThread(THREAD_ID* tThread, LPTHREAD_START_ROUTINE worker, LPVOID lpParameter)
+{
+#ifdef WINDOWS
+ DWORD ret;
+ *tThread = CreateThread(
+ NULL,
+ 0,
+ worker,
+ lpParameter,
+ 0,
+ &ret);
+ return ret;
+#else
+ pthread_create(
+ tThread,
+ NULL,
+ (MacWorker)worker,
+ lpParameter);
+#ifdef MAC64
+ // This is a major kludge...64 bit posix threads just can't be cast into a DWORD and there just isn't
+ // a great way to get what we're using for the ID. The fact that we're casting this at all is kind of
+ // silly since we're returing the actual thread handle and everything being done to manipulate the thread
+ // is done with that. Anyhow, the only thing done with the dword returned from this method is a printf
+ // which is good since this DWORD really shouldn't be reliably used. Just in case it is though, return
+ // a value that can be traced back to here.
+ return 42;
+#else
+ return (DWORD)*tThread;
+#endif
+#endif
+}
+
+void TP_JoinThread(THREAD_ID tThread)
+{
+#ifdef WINDOWS
+ WaitForSingleObject(tThread, INFINITE);
+#else
+ pthread_join(tThread, NULL);
+#endif
+}
+
+#ifndef WINDOWS
+void TP_DebugBreak()
+{
+#ifdef _PPC_
+ __asm__ __volatile__("trap");
+#else
+ __asm__ __volatile__("int $3");
+#endif
+}
+#endif
diff --git a/tests/src/Common/Platform/platformdefines.h b/tests/src/Common/Platform/platformdefines.h
new file mode 100644
index 0000000000..e04fa103e1
--- /dev/null
+++ b/tests/src/Common/Platform/platformdefines.h
@@ -0,0 +1,133 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef _PLATFORMDEFINES__H
+#define _PLATFORMDEFINES__H
+
+//
+// types and constants
+//
+#ifdef WINDOWS
+#include <windows.h>
+#include <string.h>
+
+#define FS_SEPERATOR L"\\"
+#define PATH_DELIMITER L";"
+#define L(t) L##t
+
+
+typedef unsigned error_t;
+typedef HANDLE THREAD_ID;
+
+#else // !WINDOWS
+#include <CoreClr.h>
+#include <pthread.h>
+#define WINAPI _cdecl
+#ifndef __stdcall
+#if __i386__
+#define __stdcall __attribute__((stdcall))
+#define _cdecl __attribute__((cdecl))
+#else
+#define __stdcall
+#define _cdecl
+#endif
+#endif
+
+LPWSTR HackyConvertToWSTR(char* pszInput);
+
+#define FS_SEPERATOR L("/")
+#define PATH_DELIMITER L(":")
+#define L(t) HackyConvertToWSTR(t)
+#define MAX_PATH 260
+
+typedef pthread_t THREAD_ID;
+typedef void* (*MacWorker)(void*);
+typedef DWORD (*LPTHREAD_START_ROUTINE)(void*);
+#ifdef UNICODE
+typedef WCHAR TCHAR;
+#else // ANSI
+typedef char TCHAR;
+#endif // UNICODE
+typedef char* LPSTR;
+typedef const char* LPCSTR;
+typedef TCHAR* LPTSTR;
+typedef const TCHAR* LPCTSTR;
+typedef void* FARPROC;
+typedef void* HMODULE;
+typedef void* ULONG_PTR;
+typedef unsigned error_t;
+typedef void* LPVOID;
+typedef char BYTE;
+typedef long long __int64;
+typedef WCHAR OLECHAR;
+#endif
+
+//
+// Method declarations
+//
+error_t TP_scpy_s(LPWSTR strDestination, size_t sizeInWords, LPCWSTR strSource);
+error_t TP_scat_s(LPWSTR strDestination, size_t sizeInWords, LPCWSTR strSource);
+int TP_slen(LPWSTR str);
+int TP_scmp_s(LPSTR str1, LPSTR str2);
+int TP_wcmp_s(LPWSTR str1, LPWSTR str2);
+error_t TP_getenv_s(size_t* pReturnValue, LPWSTR buffer, size_t sizeInWords, LPCWSTR varname);
+error_t TP_putenv_s(LPTSTR name, LPTSTR value);
+void TP_ZeroMemory(LPVOID buffer, size_t sizeInBytes);
+error_t TP_itow_s(int num, LPWSTR buffer, size_t sizeInCharacters, int radix);
+LPWSTR TP_sstr(LPWSTR str, LPWSTR searchStr);
+LPSTR HackyConvertToSTR(LPWSTR pwszInput);
+DWORD TP_CreateThread(THREAD_ID* tThread, LPTHREAD_START_ROUTINE worker, LPVOID lpParameter);
+void TP_JoinThread(THREAD_ID tThread);
+void TP_DebugBreak();
+DWORD TP_GetFullPathName(LPWSTR fileName, DWORD nBufferLength, LPWSTR lpBuffer);
+
+//
+// Method redirects
+//
+#ifdef WINDOWS
+#define TP_LoadLibrary(l) LoadLibrary(l)
+#define TP_LoadLibraryW(l) LoadLibraryW(l)
+#define TP_LoadLibraryA(l) LoadLibraryA(l)
+#define TP_GetProcAddress(m,e) GetProcAddress(m,e)
+#define TP_CoTaskMemAlloc(t) CoTaskMemAlloc(t)
+#define TP_CoTaskMemFree(t) CoTaskMemFree(t)
+#define TP_DebugBreak() DebugBreak()
+#define TP_rand rand
+#define TP_srand srand
+#else
+#define fopen_s(FILEHANDLE, FILENAME, MODE) *(FILEHANDLE) = fopen(FILENAME, MODE)
+#define _fsopen(FILENAME, MODE, ACCESS) fopen(FILENAME, MODE)
+#define GetCurrentDirectory(BUFSIZ, BUF) getcwd(BUF, BUFSIZ)
+#define DeleteFile unlink
+#define GlobalFree free
+#define sprintf_s snprintf
+#define fwscanf_s fwscanf
+#define strcat_s(DST,SIZ,SRC) strlcat(DST,SRC,SIZ)
+#define TP_LoadLibrary(l) dlopen(l, 0)
+#define TP_LoadLibraryW(l) dlopen(l, 0)
+#define TP_LoadLibraryA(l) dlopen(l, 0)
+#define TP_GetProcAddress(m,e) dlsym(m,e)
+#define TP_CoTaskMemAlloc(t) malloc(t)
+#define TP_CoTaskMemFree(t) free(t)
+#define TP_rand arc4random
+#define TP_srand srandom
+#define wcscpy_s TP_scpy_s
+#define wcscat_s TP_scat_s
+#define GetFullPathNameW(fname,buflen,buf,filepart) TP_GetFullPathName(fname,buflen,buf)
+#define wcslen TP_slen
+#define _wgetenv_s TP_getenv_s
+#define _putenv_s TP_putenv_s
+#define ZeroMemory TP_ZeroMemory
+#define _itow_s TP_itow_s
+#define wcsstr TP_sstr
+#define strcmp TP_scmp_s
+#define wcscmp TP_wcmp_s
+#endif
+
+#endif
+
diff --git a/tests/src/Interop/ReversePInvoke/Marshalling/CMakeLists.txt b/tests/src/Interop/ReversePInvoke/Marshalling/CMakeLists.txt
new file mode 100644
index 0000000000..fa312b6cd7
--- /dev/null
+++ b/tests/src/Interop/ReversePInvoke/Marshalling/CMakeLists.txt
@@ -0,0 +1,12 @@
+cmake_minimum_required (VERSION 2.6)
+project (MarshalBoolArrayDLL)
+include_directories(${INC_PLATFORM_DIR})
+set(SOURCES MarshalBoolArrayDLL.cpp MarshalBoolArrayDLL.def)
+
+# add the executable
+add_library (MarshalBoolArrayDLL SHARED ${SOURCES})
+
+# add the install targets
+install (TARGETS MarshalBoolArrayDLL DESTINATION bin)
+
+
diff --git a/tests/src/Interop/ReversePInvoke/Marshalling/MarshalBoolArray.cs b/tests/src/Interop/ReversePInvoke/Marshalling/MarshalBoolArray.cs
new file mode 100644
index 0000000000..dc56b3145b
--- /dev/null
+++ b/tests/src/Interop/ReversePInvoke/Marshalling/MarshalBoolArray.cs
@@ -0,0 +1,274 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+//
+// Adding tests for BoolArrayMarshaler code coverage
+//
+//Rule for Passing Value
+// Reverse Pinvoke
+//M--->N true,true,true,true,true
+//N----M true,false,true,false,true
+using System;
+using System.Text;
+using System.Security;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+public class MarshalBoolArray
+{
+ #region"variable"
+ const int SIZE = 5;
+ #endregion
+
+ #region "Reverse PInvoke"
+
+ #region "Bool Array"
+ [DllImport("MarshalBoolArrayDLL")]
+ private static extern bool DoCallBackIn(CallBackIn callback);
+ private delegate bool CallBackIn([In]int size, [In, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1, SizeConst = SIZE)] bool[] array);
+ private static bool TestMethod_CallBackIn(int size, bool[] array)
+ {
+ bool retVal = true;
+
+ //Check the Input
+ if (SIZE != size)
+ {
+ retVal = false;
+ TestFramework.LogError("001","Failed on the Managed Side:TestMethod_CallBackIn:Parameter Size is wrong");
+ }
+ for (int i = 0; i < SIZE; ++i) //Reverse PInvoke, true,false,true false,true
+ {
+ if ((0 == i % 2) && !array[i])
+ {
+ retVal = false;
+ TestFramework.LogError("002","Failed on the Managed Side:TestMethod_CallBackIn. The " + (i + 1) + "st Item failed");
+ }
+ else if ((1 == i % 2) && array[i])
+ {
+ retVal = false;
+ TestFramework.LogError("003","Failed on the Managed Side:TestMethod_CallBackIn. The " + (i + 1) + "st Item failed");
+ }
+ }
+ return retVal;
+ }
+
+ [DllImport("MarshalBoolArrayDLL")]
+ private static extern bool DoCallBackOut(CallBackOut callback);
+ private delegate bool CallBackOut([In]int size, [Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1, SizeConst = SIZE)] bool[] array);
+ private static bool TestMethod_CallBackOut(int size, bool[] array)
+ {
+ bool retVal = true;
+ //Check the Input
+ if (SIZE != size)
+ {
+ retVal = false;
+ TestFramework.LogError("004","Failed on the Managed Side:TestMethod_CallBackOut:Parameter Size is wrong");
+ }
+
+ for (int i = 0; i < SIZE; ++i) //Reverse PInvoke, true,true,true true,true
+ {
+ array[i] = true;
+ }
+ return retVal;
+ }
+
+ [DllImport("MarshalBoolArrayDLL")]
+ private static extern bool DoCallBackInOut(CallBackInOut callback);
+ private delegate bool CallBackInOut([In]int size, [In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1, SizeConst = SIZE)] bool[] array);
+
+ private static bool TestMethod_CallBackInOut(int size, bool[] array)
+ {
+ bool retVal = true;
+ //Check the Input
+ if (SIZE != size)
+ {
+ retVal = false;
+ TestFramework.LogError("005","Failed on the Managed Side:TestMethod_CallBackInOut:Parameter Size is wrong");
+ }
+ for (int i = 0; i < SIZE; ++i) //Reverse PInvoke, true,false,true false,true
+ {
+ if ((0 == i % 2) && !array[i])
+ {
+ retVal = false;
+ TestFramework.LogError("006","Failed on the Managed Side:TestMethod_CallBackInOut. The " + (i + 1) + "st Item failed");
+ }
+ else if ((1 == i % 2) && array[i])
+ {
+ retVal = false;
+ TestFramework.LogError("007","Failed on the Managed Side:TestMethod_CallBackInOut. The " + (i + 1) + "st Item failed");
+ }
+ }
+
+ //Check the output
+ for (int i = 0; i < size; ++i) //Reverse PInvoke, true,true,true true,true
+ {
+ array[i] = true;
+ }
+ return retVal;
+ }
+ #endregion
+
+ #region"Bool Array Reference"
+ [DllImport("MarshalBoolArrayDLL")]
+ private static extern bool DoCallBackRefIn(CallBackRefIn callback);
+ private delegate bool CallBackRefIn([In]int size, [In, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1)] ref bool[] array);
+
+ private static bool TestMethod_CallBackRefIn(int size, ref bool[] array)
+ {
+ bool retVal = true;
+ //Check the Input
+ if (SIZE != size)
+ {
+ retVal = false;
+ TestFramework.LogError("008","Failed on the Managed Side:TestMethod_CallBackRefIn:Parameter Size is wrong");
+ }
+ //TODO: UnComment these line if the SizeConst attributes is support
+ //Since now the sizeconst doesnt support on ref,so only check the first item instead.
+ //Unhandled Exception: System.Runtime.InteropServices.MarshalDirectiveException: Cannot marshal 'parameter #2': Cannot use SizeParamIndex for ByRef array parameters.
+ //for (int i = 0; i < size; ++i) //Reverse PInvoke, true,false,true false,true
+ //{
+ // if ((0 == i % 2) && !array[i])
+ // {
+ // ReportFailure("Failed on the Managed Side:TestMethod_CallBackRefIn. The " + (i + 1) + "st Item failed", true.ToString(), false.ToString());
+ // }
+ // else if ((1 == i % 2) && array[i])
+ // {
+ // ReportFailure("Failed on the Managed Side:TestMethod_CallBackRefIn. The " + (i + 1) + "st Item failed", false.ToString(), true.ToString());
+ // }
+ // }
+ if (!array[0])
+ {
+ retVal = false;
+ TestFramework.LogError("009","Failed on the Managed Side:TestMethod_CallBackRefIn. The first Item failed");
+ }
+ return retVal;
+ }
+
+
+
+ [DllImport("MarshalBoolArrayDLL")]
+ private static extern bool DoCallBackRefOut(CallBackRefOut callback);
+ private delegate bool CallBackRefOut([In]int size, [Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1)] out bool[] array);
+
+ private static bool TestMethod_CallBackRefOut(int size, out bool[] array)
+ {
+ bool retVal = true;
+
+ //Check the Input
+ if (size != SIZE)
+ {
+ retVal = false;
+ TestFramework.LogError("010","Failed on the Managed Side:TestMethod_CallBackRefOut:Parameter Size is wrong");
+ }
+
+ array = new bool[SIZE];
+ for (int i = 0; i < SIZE; ++i) //Reverse PInvoke, true,true,true true,true
+ {
+ array[i] = true;
+ }
+ return retVal;
+ }
+
+ [DllImport("MarshalBoolArrayDLL")]
+ private static extern bool DoCallBackRefInOut(CallBackRefInOut callback);
+ private delegate bool CallBackRefInOut([In]int size, [In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1)] ref bool[] array);
+
+ private static bool TestMethod_CallBackRefInOut(int size, ref bool[] array)
+ {
+ bool retVal = true;
+ //Check the Input
+ if (SIZE != size)
+ {
+ retVal = false;
+ TestFramework.LogError("011","Failed on the Managed Side:TestMethod_CallBackRefInOut:Parameter Size is wrong");
+ }
+ //TODO: UnComment these line if the SizeConst attributes is support
+ //Since now the sizeconst doesnt support on ref,so only check the first item instead.
+ //Unhandled Exception: System.Runtime.InteropServices.MarshalDirectiveException: Cannot marshal 'parameter #2': Cannot use SizeParamIndex for ByRef array parameters.
+ //for (int i = 0; i < size; ++i) //Reverse PInvoke, true,false,true false,true
+ //{
+ // if ((0 == i % 2) && !array[i])
+ // {
+ // ReportFailure("Failed on the Managed Side:TestMethod_CallBackRefInOut. The " + (i + 1) + "st Item failed", true.ToString(), false.ToString());
+ // }
+ // else if ((1 == i % 2) && array[i])
+ // {
+ // ReportFailure("Failed on the Managed Side:TestMethod_CallBackRefInOut. The " + (i + 1) + "st Item failed", false.ToString(), true.ToString());
+ // }
+ // }
+ if (!array[0])
+ {
+ retVal = false;
+ TestFramework.LogError("012","Failed on the Managed Side:TestMethod_CallBackRefInOut. The first Item failed");
+ }
+
+ //Output
+ array = new bool[SIZE];
+ for (int i = 0; i < size; ++i) //Reverse PInvoke, true,true,true true,true
+ {
+ array[i] = true;
+ }
+ return retVal;
+ }
+ #endregion
+
+ #endregion
+
+ [System.Security.SecuritySafeCritical]
+ static int Main()
+ {
+ bool retVal = true;
+
+ TestFramework.BeginScenario("Reverse PInvoke with In attribute");
+ if (!DoCallBackIn(new CallBackIn(TestMethod_CallBackIn)))
+ {
+ retVal = false;
+ TestFramework.LogError("013","Error happens in Native side:DoCallBackIn");
+ }
+
+ TestFramework.BeginScenario("Reverse PInvoke with Out attribute");
+ if (!DoCallBackOut(new CallBackOut(TestMethod_CallBackOut)))
+ {
+ retVal = false;
+ TestFramework.LogError("014","Error happens in Native side:DoCallBackOut");
+ }
+
+ TestFramework.BeginScenario("Reverse PInvoke with InOut attribute");
+ if (!DoCallBackInOut(new CallBackInOut(TestMethod_CallBackInOut)))
+ {
+ retVal = false;
+ TestFramework.LogError("015","Error happens in Native side:DoCallBackInOut");
+ }
+
+ TestFramework.BeginScenario("Reverse PInvoke Reference In");
+ if (!DoCallBackRefIn(new CallBackRefIn(TestMethod_CallBackRefIn)))
+ {
+ retVal = false;
+ TestFramework.LogError("016","Error happens in Native side:DoCallBackRefIn");
+ }
+
+ TestFramework.BeginScenario("Reverse PInvoke Reference Out");
+ if (!DoCallBackRefOut(new CallBackRefOut(TestMethod_CallBackRefOut)))
+ {
+ retVal = false;
+ TestFramework.LogError("017","Error happens in Native side:DoCallBackRefOut");
+ }
+
+ TestFramework.BeginScenario("Reverse PInvoke Reference InOut");
+ if (!DoCallBackRefInOut(new CallBackRefInOut(TestMethod_CallBackRefInOut)))
+ {
+ retVal = false;
+ TestFramework.LogError("019","Error happens in Native side:DoCallBackRefInOut");
+ }
+
+ if(retVal)
+ {
+ Console.WriteLine("Succeeded!");
+ return 100;
+ }
+
+ Console.WriteLine("Failed!");
+ return 101;
+ }
+}
diff --git a/tests/src/Interop/ReversePInvoke/Marshalling/MarshalBoolArray.csproj b/tests/src/Interop/ReversePInvoke/Marshalling/MarshalBoolArray.csproj
new file mode 100644
index 0000000000..48ce35c79c
--- /dev/null
+++ b/tests/src/Interop/ReversePInvoke/Marshalling/MarshalBoolArray.csproj
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <AssemblyName>MarshalBoolArray</AssemblyName>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+ <DefineConstants>$(DefineConstants);STATIC</DefineConstants>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ </PropertyGroup>
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="MarshalBoolArray.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="app.config" />
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\Common\CoreCLRTestLibrary\CoreCLRTestLibrary.csproj">
+ <Project>{c8c0dc74-fac4-45b1-81fe-70c4808366e0}</Project>
+ <Name>CoreCLRTestLibrary</Name>
+ </ProjectReference>
+ <ProjectReference Include="CMakeLists.txt">
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file
diff --git a/tests/src/Interop/ReversePInvoke/Marshalling/MarshalBoolArrayDLL.cpp b/tests/src/Interop/ReversePInvoke/Marshalling/MarshalBoolArrayDLL.cpp
new file mode 100644
index 0000000000..1a04224499
--- /dev/null
+++ b/tests/src/Interop/ReversePInvoke/Marshalling/MarshalBoolArrayDLL.cpp
@@ -0,0 +1,236 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include "platformdefines.cpp"
+#include <stdio.h>
+#include <stdlib.h>
+
+const int iManaged = 10;
+const int iNative = 11;
+
+const int ArraySIZE = 5;
+
+
+//Rule for Passing Value
+// Reverse Pinvoke
+//M--->N true,true,true,true,true
+//N----M true,false,true,false,true
+
+//Reverse PInvoke
+//Pass by value
+typedef BOOL (__stdcall *CallBackIn)(int size,bool arr[]);
+extern "C" BOOL DoCallBackIn(CallBackIn callback)
+{
+ //Init
+ bool * arr = (bool*)TP_CoTaskMemAlloc(ArraySIZE);
+ for(int i = 0;i < ArraySIZE; i++ )
+ {
+ if( 0 == i%2)
+ {
+ arr[i] =true;
+ }
+ else
+ {
+ arr[i] = false;
+ }
+ }
+
+ if(!callback(ArraySIZE,arr))
+ {
+ printf("Native Side: in DoCallBackIn, The Callback return wrong value");
+ return false;
+ }
+
+ //Check the data
+ for(int i = 0;i < ArraySIZE; i++ )//Expected:true,false,true,false,true
+ {
+ if((0 == (i%2)) && !arr[i]) //expect true
+ {
+ printf("Native Side:Error in DoCallBackIn.The Item is %d\n",i+1);
+ TP_CoTaskMemFree(arr);
+ return false;
+ }
+ else if((1 == (i%2))&&arr[i]) //expect false
+ {
+ printf("Native Side:Error in DoCallBackIn.The Item is %d\n",i+1);
+ TP_CoTaskMemFree(arr);
+ return false;
+ }
+ }
+ TP_CoTaskMemFree(arr);
+ return true;
+}
+
+typedef BOOL (__stdcall *CallBackOut)(int size,bool arr[]);
+extern "C" BOOL DoCallBackOut(CallBackOut callback)
+{
+ bool * arr =(bool *)TP_CoTaskMemAlloc(ArraySIZE);
+
+ if(!callback(ArraySIZE,arr))
+ {
+ printf("Native Side: in DoCallBackOut, The Callback return wrong value");
+ return FALSE;
+ }
+
+ //Check the data returnd from Managed Side
+ for(int i = 0;i < ArraySIZE; i++ )
+ {
+ if(!arr[i]) //expect true
+ {
+ printf("Native Side:Error in DoCallBackOut.The Item is %d\n",i+1);
+ TP_CoTaskMemFree(arr);
+ return false;
+ }
+ }
+ TP_CoTaskMemFree(arr);
+ return true;
+}
+
+typedef BOOL (__stdcall *CallBackInOut)(int size,bool arr[]);
+extern "C" BOOL DoCallBackInOut(CallBackInOut callback)
+{
+ //Init
+ bool * arr =(bool *)TP_CoTaskMemAlloc(ArraySIZE);
+ for(int i = 0;i < ArraySIZE; i++ )
+ {
+ if( 0 == i%2)
+ {
+ arr[i] = true;
+ }
+ else
+ {
+ arr[i] = false;
+ }
+ }
+
+ if(!callback(ArraySIZE,arr))
+ {
+ printf("Native Side: in DoCallBackInOut, The Callback return wrong value");
+
+ return FALSE;
+ }
+
+ //Check the data
+ for(int i = 0;i < ArraySIZE; i++ )
+ {
+ if(!arr[i]) //expect true
+ {
+ printf("Native Side:Error in DoCallBackInOut.The Item is %d\n",i+1);
+ TP_CoTaskMemFree(arr);
+ return false;
+ }
+ }
+ TP_CoTaskMemFree(arr);
+ return true;
+}
+
+
+//Reverse PInvoke
+//Pass by reference
+typedef BOOL (__stdcall *CallBackRefIn)(int size,bool ** arr);
+extern "C" BOOL DoCallBackRefIn(CallBackRefIn callback)
+{
+ //Init:true,false,true,false,true
+ bool *parr = (bool *)TP_CoTaskMemAlloc(ArraySIZE);
+
+ for(int i = 0;i < ArraySIZE;++i)
+ {
+ if( 0 == i%2)
+ {
+ parr[i] = true;
+ }
+ else
+ {
+ parr[i] = false;
+ }
+ }
+
+ if(!callback(ArraySIZE,&parr)) // &parr
+ {
+ printf("Native Side: in DoCallBackRefIn, The Callback return wrong value");
+ return FALSE;
+ }
+
+ //Check the data werent changed
+ for(int i = 0;i<ArraySIZE;++i)
+ {
+ if((0==(i%2)) && !parr[i]) //expect true
+ {
+ printf("Native Side:Error in DoCallBackInOut.The Item is %d\n",i+1);
+ TP_CoTaskMemFree(parr);
+ return false;
+ }
+ else if((1==(i%2))&&parr[i]) //expect false
+ {
+ printf("Native Side:Error in DoCallBackInOut.The Item is %d\n",i+1);
+ TP_CoTaskMemFree(parr);
+ return false;
+ }
+ }
+ TP_CoTaskMemFree(parr);
+ return true;
+}
+
+typedef BOOL (__stdcall *CallBackRefOut)(int size,bool ** arr);
+extern "C" BOOL DoCallBackRefOut(CallBackRefOut callback)
+{
+
+ bool* parr = NULL;
+
+ if(!callback(ArraySIZE,&parr))
+ {
+ printf("Native Side: in DoCallBackRefOut, The Callback return wrong value");
+ return FALSE;
+ }
+
+ //Check the data were changed to true,true
+ for(int i = 0;i<ArraySIZE;++i)
+ {
+ if(!(*(parr + i))) //expect true
+ {
+ printf("Native Side:Error in DoCallBackRefOut.The Item is %d\n",i+1);
+ TP_CoTaskMemFree(parr);
+ return false;
+ }
+ }
+ TP_CoTaskMemFree(parr);
+ return true;
+}
+
+typedef BOOL (__stdcall *CallBackRefInOut)(int size,bool ** arr);
+extern "C" BOOL DoCallBackRefInOut(CallBackRefInOut callback)
+{
+ //Init,true,false,true,false
+ bool* parr = (bool*)TP_CoTaskMemAlloc(ArraySIZE);
+ for(int i = 0;i<ArraySIZE;++i)
+ {
+ if( 0 == i%2)
+ {
+ parr[i] = true;
+ }
+ else
+ {
+ parr[i] = false;
+ }
+ }
+
+ if(!callback(ArraySIZE,&parr))
+ {
+ printf("Native Side: in DoCallBackRefInOut, The Callback return wrong value");
+ return FALSE;
+ }
+
+ //Check the data were changed to true,true
+ for(int i = 0;i<ArraySIZE;++i)
+ {
+ if(!(parr[i])) //expect true
+ {
+ printf("Native Side:Error in DoCallBackRefOut.The Item is %d\n",i+1);
+ TP_CoTaskMemFree(parr);
+ return false;
+ }
+ }
+ TP_CoTaskMemFree(parr);
+ return true;
+}
diff --git a/tests/src/Interop/ReversePInvoke/Marshalling/MarshalBoolArrayDLL.def b/tests/src/Interop/ReversePInvoke/Marshalling/MarshalBoolArrayDLL.def
new file mode 100644
index 0000000000..c6ec74ce33
--- /dev/null
+++ b/tests/src/Interop/ReversePInvoke/Marshalling/MarshalBoolArrayDLL.def
@@ -0,0 +1,8 @@
+EXPORTS
+ DoCallBackIn
+ DoCallBackOut
+ DoCallBackInOut
+
+ DoCallBackRefIn
+ DoCallBackRefOut
+ DoCallBackRefInOut \ No newline at end of file
diff --git a/tests/src/Interop/ReversePInvoke/Marshalling/app.config b/tests/src/Interop/ReversePInvoke/Marshalling/app.config
new file mode 100644
index 0000000000..62803f5972
--- /dev/null
+++ b/tests/src/Interop/ReversePInvoke/Marshalling/app.config
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <runtime>
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <dependentAssembly>
+ <assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.20.0" newVersion="4.0.20.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Text.Encoding" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.10.0" newVersion="4.0.10.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.10.0" newVersion="4.0.10.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.IO" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.10.0" newVersion="4.0.10.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Reflection" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.10.0" newVersion="4.0.10.0" />
+ </dependentAssembly>
+ </assemblyBinding>
+ </runtime>
+</configuration> \ No newline at end of file
diff --git a/tests/src/Interop/ReversePInvoke/Marshalling/packages.config b/tests/src/Interop/ReversePInvoke/Marshalling/packages.config
new file mode 100644
index 0000000000..9cc46980ee
--- /dev/null
+++ b/tests/src/Interop/ReversePInvoke/Marshalling/packages.config
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="System.Console" version="4.0.0-beta-22405" />
+ <package id="System.IO" version="4.0.10-beta-22412" targetFramework="portable-net45+win" />
+ <package id="System.Reflection" version="4.0.10-beta-22412" targetFramework="portable-net45+win" />
+ <package id="System.Reflection.Primitives" version="4.0.0-beta-22605" targetFramework="portable-net45+win" />
+ <package id="System.Runtime" version="4.0.20-beta-22412" targetFramework="portable-net45+win" />
+ <package id="System.Runtime.Handles" version="4.0.0-beta-22605" targetFramework="portable-net45+win" />
+ <package id="System.Runtime.InteropServices" version="4.0.20-beta-22605" targetFramework="portable-net45+win" />
+ <package id="System.Text.Encoding" version="4.0.10-beta-22412" targetFramework="portable-net45+win" />
+ <package id="System.Threading.Tasks" version="4.0.10-beta-22412" targetFramework="portable-net45+win" />
+</packages>
diff --git a/tests/src/dir.common.props b/tests/src/dir.common.props
index beb6d17555..47c72ddeea 100644
--- a/tests/src/dir.common.props
+++ b/tests/src/dir.common.props
@@ -5,10 +5,10 @@
<PropertyGroup>
<__BuildArch Condition="'$(__BuildArch)' == ''">x64</__BuildArch>
<__BuildType Condition="'$(__BuildType)' == ''">Debug</__BuildType>
- <__BuildOS Condition="'$(__BuildOS)' == ''">Windows_NT</__BuildOS>
+ <__BuildOS Condition="'$(__BuildOS)' == ''">Windows_NT</__BuildOS>
<BuildArch>$(__BuildArch)</BuildArch>
<BuildType>$(__BuildType)</BuildType>
- <BuildOS>$(__BuildOS)</BuildOS>
+ <BuildOS>$(__BuildOS)</BuildOS>
<Configuration Condition="'$(Configuration)' ==''">$(BuildType)</Configuration>
<Platform Condition="'$(Platform)'==''">$(BuildArch)</Platform>
</PropertyGroup>
@@ -31,8 +31,9 @@
<PropertyGroup>
<BaseOutputPathWithConfig>$(ProjectDir)\..\binaries\tests\$(BuildOS).$(Platform).$(Configuration)\</BaseOutputPathWithConfig>
<BaseOutputPathWithConfig Condition="'$(__TestWorkingDir)' != ''">$(__TestWorkingDir)\</BaseOutputPathWithConfig>
- <BinDir>$(BaseOutputPathWithConfig)\..\..\..\</BinDir>
+ <BinDir>$(BaseOutputPathWithConfig)\..</BinDir>
<BaseIntermediateOutputPath>$(BinDir)\intermediates\</BaseIntermediateOutputPath>
+ <__CMakeTestSlnDir Condition="'$(__CMakeTestSlnDir)' == ''">$(BaseOutputPathWithConfig)\CMake\</__CMakeTestSlnDir>
<BuildProjectRelativeDir>$(MSBuildProjectName)\</BuildProjectRelativeDir>
<BuildProjectRelativeDir Condition="'$(MSBuildProjectDirectory.Contains($(SourceDir)))'">$([System.String]::Copy('$(MSBuildProjectDirectory)').Replace($(SourceDir),''))</BuildProjectRelativeDir>
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(BuildProjectRelativeDir)\$(BuildOS).$(Platform).$(Configuration)\</IntermediateOutputPath>
diff --git a/tests/src/dir.targets b/tests/src/dir.targets
index 853685d06c..a149ad5008 100644
--- a/tests/src/dir.targets
+++ b/tests/src/dir.targets
@@ -55,8 +55,53 @@
Condition="'$(GenerateRunScript)' != 'false'"
DependsOnTargets="GenerateExecutionScriptsInternal" />
-<PropertyGroup>
- <OutDir>$(BaseOutputPathWithConfig)$(BuildProjectRelativeDir)\</OutDir>
-</PropertyGroup>
+ <PropertyGroup>
+ <OutDir>$(BaseOutputPathWithConfig)$(BuildProjectRelativeDir)\</OutDir>
+ </PropertyGroup>
+
+ <Target Name="CopyNativeProjectBinaries">
+ <ItemGroup>
+ <NativeProjectBinaries Include="$(NativeProjectOutPutFolder)\**\*.*" />
+ </ItemGroup>
+
+ <Error Text="Then Native Project files are missing in $(NativeProjectOutPutFolder) please run build from the root of the repo at least once"
+ Condition="'@(NativeProjectBinaries)' == ''" />
+
+ <Copy
+ SourceFiles="@(NativeProjectBinaries)"
+ DestinationFiles="@(NativeProjectBinaries -> '$(OutDir)%(RecursiveDir)%(Filename)%(Extension)')"
+ SkipUnchangedFiles="$(SkipCopyUnchangedFiles)"
+ OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
+ Retries="$(CopyRetryCount)"
+ RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
+ UseHardlinksIfPossible="$(CreateHardLinksForCopyFilesToOutputDirectoryIfPossible)">
+ <Output TaskParameter="DestinationFiles" ItemName="FileWrites" />
+ </Copy>
+ </Target>
+ <Target Name="ResolveCmakeNativeProjectReference"
+ Condition="'@(ProjectReference)' != ''"
+ BeforeTargets="BeforeResolveReferences;BeforeClean" >
+ <ItemGroup>
+ <NativeProjectReference Include="%(ProjectReference.Identity)" Condition="$([System.String]::Copy(%(ProjectReference.FileName)).ToUpper()) == 'CMAKELISTS'" />
+ <ProjectReference Remove="%(NativeProjectReference.Identity)" />
+ <NativeProjectReferenceNormalized Include="@(NativeProjectReference -> '%(FullPath)')" />
+ </ItemGroup>
+ </Target>
+
+ <Target Name="ConsolidateNativeProjectReference"
+ Condition="'@(ProjectReference)' != ''"
+ BeforeTargets="Build" >
+ <ItemGroup>
+ <NativeProjectOutPutFoldersToCopy Include="$([System.String]::Copy('%(NativeProjectReferenceNormalized.RelativeDir)').Replace($(SourceDir),$(__CMakeTestSlnDir)src\))$(Configuration)\"/>
+ </ItemGroup>
+
+ <Message Text= "Project filese are :$([System.String]::Copy(%(ProjectReference.FileName)).ToUpper()) " />
+ <Message Text= "Project refernce are :%(ProjectReference.Identity)" />
+ <Message Text= "Native Project refernce are :%(NativeProjectReference.Identity)" />
+ <Message Text= "Native Project refernce are :%(NativeProjectReferenceNormalized.Identity)" />
+ <Message Text= "Native Binaries will be copied from :%(NativeProjectOutPutFoldersToCopy.Identity)" />
+ <MSBuild Projects="$(MSBuildProjectFile)" Targets="CopyNativeProjectBinaries" Properties="NativeProjectOutPutFolder=%(NativeProjectOutPutFoldersToCopy.Identity)" Condition="'@(NativeProjectReference)' != ''" />
+
+ </Target>
</Project>