Skip to content

Commit

Permalink
[netcore] Add target for running coreclr tests
Browse files Browse the repository at this point in the history
Commit migrated from mono/mono@f88da6c
  • Loading branch information
marek-safar committed Sep 27, 2019
1 parent ec694b2 commit 7210337
Show file tree
Hide file tree
Showing 9 changed files with 908 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/mono/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ endif

if ENABLE_NETCORE
update_submodules =
SUBDIRS = mk llvm mono runtime netcore
SUBDIRS = mk llvm mono runtime netcore netcore/corerun
else
update_submodules = update_submodules
SUBDIRS = $(build_with_msvc) mk po $(libgc_dir) llvm mono $(ikvm_native_dir) support data runtime scripts man samples $(tools_dir) $(build_without_msvc) $(docs_dir) acceptance-tests
Expand Down
1 change: 1 addition & 0 deletions src/mono/configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -6778,6 +6778,7 @@ tools/mono-hang-watchdog/Makefile
runtime/Makefile
msvc/Makefile
po/Makefile
netcore/corerun/Makefile
])

if test x$host_win32 = xyes; then
Expand Down
35 changes: 35 additions & 0 deletions src/mono/netcore/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ NETCORETESTS_VERSION := $(shell cat ../eng/Versions.props | sed -n 's/.*Microsof
NETCOREAPP_VERSION := $(shell cat ../eng/Versions.props | sed -n 's/.*MicrosoftNETCoreAppVersion>\(.*\)<\/MicrosoftNETCoreAppVersion.*/\1/p' )
ROSLYN_VERSION:= $(shell cat ../eng/Versions.props | sed -n 's/.*MicrosoftNetCompilersVersion>\(.*\)<\/MicrosoftNetCompilersVersion.*/\1/p' )

# Should be automated but not sure how for now
# the name is misleading osx version is used for any unix like systems
# the url is manually extracted from coreclr-outerloop (https://dev.azure.com/dnceng/public/_build?definitionId=98&_a=summary) Build artifacts published page
CORECLR_TESTS:=https://dev.azure.com/dnceng/9ee6d478-d288-47f7-aacc-f6e6d082ae6d/_apis/build/builds/368250/artifacts?artifactName=Tests_OSX_x64_checked_outerloop&api-version=5.2-preview.5&%24format=zip

# runtime version used by $(DOTNET) - local .net core sdk to bootstrap stuff
# it doesn't match NETCOREAPP_VERSION
BOOTSTRAP_RUNTIME = $(shell ls ../.dotnet/shared/Microsoft.NETCore.App | tail -1)
Expand Down Expand Up @@ -234,6 +239,36 @@ build-test-corefx-%:
xunit-summary:
./xunit-summary.py "corefx/tests"


update-tests-coreclr: coreclr/.stamp-tests

coreclr/.stamp-tests:
rm -rf coreclr/tests
curl -L "$(CORECLR_TESTS)" --output coreclr/tests.zip
$(UNZIPCMD) coreclr/tests.zip -C coreclr/
mkdir coreclr/tests
$(UNZIPCMD) coreclr/Tests_Linux_x64_checked/Linux.x64.Checked.tar.gz -C coreclr/tests
touch $@

.PHONY: corerun
corerun:
cp corerun/corerun $(SHAREDRUNTIME)

run-tests-coreclr: prepare update-tests-coreclr corerun
rm -rf coreclr/output.log
@counter=0; \
failures=0; \
test_files=$$(find coreclr/tests -type f -name "*.sh"); \
for testdir in $$test_files; do \
counter=$$((counter+1)); \
echo "Running $$testdir"; \
if sh $$testdir -coreroot=$(realpath $(SHAREDRUNTIME)) >>coreclr/output.log 2>&1 ; then \
echo "FAILED"; \
failures=$$((failures+1)); \
fi; \
done; \
echo "Tests Count: $$counter"; \
echo "Failed: $$failures"
endif

distdir:
Expand Down
1 change: 1 addition & 0 deletions src/mono/netcore/corerun/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/corerun
7 changes: 7 additions & 0 deletions src/mono/netcore/corerun/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Files copied from coreclr/src/coreclr/hosts/unixcorerun repo

AM_CPPFLAGS = $(SHARED_CFLAGS)

bin_PROGRAMS = corerun

corerun_SOURCES = corerun.cpp coreruncommon.cpp coreruncommon.h coreclrhost.h
125 changes: 125 additions & 0 deletions src/mono/netcore/corerun/coreclrhost.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// 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.

//
// APIs for hosting CoreCLR
//

#ifndef __CORECLR_HOST_H__
#define __CORECLR_HOST_H__

#if defined(_WIN32) && defined(_M_IX86)
#define CORECLR_CALLING_CONVENTION __stdcall
#else
#define CORECLR_CALLING_CONVENTION
#endif

// For each hosting API, we define a function prototype and a function pointer
// The prototype is useful for implicit linking against the dynamic coreclr
// library and the pointer for explicit dynamic loading (dlopen, LoadLibrary)
#define CORECLR_HOSTING_API(function, ...) \
extern "C" int CORECLR_CALLING_CONVENTION function(__VA_ARGS__); \
typedef int (CORECLR_CALLING_CONVENTION *function##_ptr)(__VA_ARGS__)

//
// Initialize the CoreCLR. Creates and starts CoreCLR host and creates an app domain
//
// Parameters:
// exePath - Absolute path of the executable that invoked the ExecuteAssembly (the native host application)
// appDomainFriendlyName - Friendly name of the app domain that will be created to execute the assembly
// propertyCount - Number of properties (elements of the following two arguments)
// propertyKeys - Keys of properties of the app domain
// propertyValues - Values of properties of the app domain
// hostHandle - Output parameter, handle of the created host
// domainId - Output parameter, id of the created app domain
//
// Returns:
// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
//
CORECLR_HOSTING_API(coreclr_initialize,
const char* exePath,
const char* appDomainFriendlyName,
int propertyCount,
const char** propertyKeys,
const char** propertyValues,
void** hostHandle,
unsigned int* domainId);

//
// Shutdown CoreCLR. It unloads the app domain and stops the CoreCLR host.
//
// Parameters:
// hostHandle - Handle of the host
// domainId - Id of the domain
//
// Returns:
// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
//
CORECLR_HOSTING_API(coreclr_shutdown,
void* hostHandle,
unsigned int domainId);

//
// Shutdown CoreCLR. It unloads the app domain and stops the CoreCLR host.
//
// Parameters:
// hostHandle - Handle of the host
// domainId - Id of the domain
// latchedExitCode - Latched exit code after domain unloaded
//
// Returns:
// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
//
CORECLR_HOSTING_API(coreclr_shutdown_2,
void* hostHandle,
unsigned int domainId,
int* latchedExitCode);

//
// Create a native callable function pointer for a managed method.
//
// Parameters:
// hostHandle - Handle of the host
// domainId - Id of the domain
// entryPointAssemblyName - Name of the assembly which holds the custom entry point
// entryPointTypeName - Name of the type which holds the custom entry point
// entryPointMethodName - Name of the method which is the custom entry point
// delegate - Output parameter, the function stores a native callable function pointer to the delegate at the specified address
//
// Returns:
// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
//
CORECLR_HOSTING_API(coreclr_create_delegate,
void* hostHandle,
unsigned int domainId,
const char* entryPointAssemblyName,
const char* entryPointTypeName,
const char* entryPointMethodName,
void** delegate);

//
// Execute a managed assembly with given arguments
//
// Parameters:
// hostHandle - Handle of the host
// domainId - Id of the domain
// argc - Number of arguments passed to the executed assembly
// argv - Array of arguments passed to the executed assembly
// managedAssemblyPath - Path of the managed assembly to execute (or NULL if using a custom entrypoint).
// exitCode - Exit code returned by the executed assembly
//
// Returns:
// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
//
CORECLR_HOSTING_API(coreclr_execute_assembly,
void* hostHandle,
unsigned int domainId,
int argc,
const char** argv,
const char* managedAssemblyPath,
unsigned int* exitCode);

#undef CORECLR_HOSTING_API

#endif // __CORECLR_HOST_H__
162 changes: 162 additions & 0 deletions src/mono/netcore/corerun/corerun.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include <coreruncommon.h>
#include <string>
#include <string.h>
#include <sys/stat.h>

// Display the command line options
void DisplayUsage()
{
fprintf(
stderr,
"Usage: corerun [OPTIONS] assembly [ARGUMENTS]\n"
"Execute the specified managed assembly with the passed in arguments\n\n"
"Options:\n"
"-c, --clr-path path to the libcoreclr.so and the managed CLR assemblies\n");
}

// Parse the command line arguments
bool ParseArguments(
const int argc,
const char* argv[],
const char** clrFilesPath,
const char** managedAssemblyPath,
int* managedAssemblyArgc,
const char*** managedAssemblyArgv)
{
bool success = false;

*clrFilesPath = nullptr;
*managedAssemblyPath = nullptr;
*managedAssemblyArgv = nullptr;
*managedAssemblyArgc = 0;

// The command line must contain at least the current exe name and the managed assembly path
if (argc >= 2)
{
for (int i = 1; i < argc; i++)
{
// Check for an option
if (argv[i][0] == '-')
{
// Path to the libcoreclr.so and the managed CLR assemblies
if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--clr-path") == 0)
{
i++;
if (i < argc)
{
*clrFilesPath = argv[i];
}
else
{
fprintf(stderr, "Option %s: missing path\n", argv[i - 1]);
break;
}
}
else if (strcmp(argv[i], "-?") == 0 || strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0)
{
DisplayUsage();
break;
}
else
{
fprintf(stderr, "Unknown option %s\n", argv[i]);
break;
}
}
else
{
// First argument that is not an option is the managed assembly to execute
*managedAssemblyPath = argv[i];

int managedArgvOffset = (i + 1);
*managedAssemblyArgc = argc - managedArgvOffset;
if (*managedAssemblyArgc != 0)
{
*managedAssemblyArgv = &argv[managedArgvOffset];
}
success = true;
break;
}
}
}
else
{
DisplayUsage();
}

return success;
}

int corerun(const int argc, const char* argv[])
{
const char* clrFilesPath;
const char* managedAssemblyPath;
const char** managedAssemblyArgv;
int managedAssemblyArgc;

if (!ParseArguments(
argc,
argv,
&clrFilesPath,
&managedAssemblyPath,
&managedAssemblyArgc,
&managedAssemblyArgv))
{
// Invalid command line
return -1;
}

// Check if the specified managed assembly file exists
struct stat sb;
if (stat(managedAssemblyPath, &sb) == -1)
{
perror("Managed assembly not found");
return -1;
}

// Verify that the managed assembly path points to a file
if (!S_ISREG(sb.st_mode))
{
fprintf(stderr, "The specified managed assembly is not a file\n");
return -1;
}

// Make sure we have a full path for argv[0].
std::string argv0AbsolutePath;
if (!GetEntrypointExecutableAbsolutePath(argv0AbsolutePath))
{
perror("Could not get full path");
return -1;
}

std::string clrFilesAbsolutePath;
if(!GetClrFilesAbsolutePath(argv0AbsolutePath.c_str(), clrFilesPath, clrFilesAbsolutePath))
{
return -1;
}

std::string managedAssemblyAbsolutePath;
if (!GetAbsolutePath(managedAssemblyPath, managedAssemblyAbsolutePath))
{
perror("Failed to convert managed assembly path to absolute path");
return -1;
}

int exitCode = ExecuteManagedAssembly(
argv0AbsolutePath.c_str(),
clrFilesAbsolutePath.c_str(),
managedAssemblyAbsolutePath.c_str(),
managedAssemblyArgc,
managedAssemblyArgv);

return exitCode;
}

int main(const int argc, const char* argv[])
{
return corerun(argc, argv);
}
Loading

0 comments on commit 7210337

Please sign in to comment.