Skip to content

Commit

Permalink
XmlLogger now correctly closes its stream and the worker trampolines …
Browse files Browse the repository at this point in the history
…the config as approprite.
  • Loading branch information
Tobbe Gyllebring committed Aug 13, 2019
1 parent c3182ea commit b164986
Show file tree
Hide file tree
Showing 19 changed files with 195 additions and 141 deletions.
2 changes: 1 addition & 1 deletion Build.ps1
@@ -1,7 +1,7 @@
dotnet restore Cone.sln
dotnet msbuild /p:Configuration=Release

$Version = [System.Reflection.AssemblyName]::GetAssemblyName("Build\Cone\Release\net45\Cone.dll").Version.ToString(3)
$Version = [System.Reflection.AssemblyName]::GetAssemblyName("Build\Cone\Release\net452\Cone.dll").Version.ToString(3)
Write-Host Packing Version $Version

Tools\nuget pack Cone.nuspec -Properties Configuration=Release -Version $Version -OutputDirectory Build
Expand Down
4 changes: 3 additions & 1 deletion Cone.nuspec
Expand Up @@ -23,8 +23,10 @@ Say no to FluentCobol, say hello to Check.That(() => actual == expected);
</dependencies>
</metadata>
<files>
<file src="Build\Cone\$Configuration$\**" target="lib\" />
<file src="Build\Cone\$Configuration$\**" target="lib\" exclude="**\Newtonsoft.Json.dll" />
<!--
<file src="dotnet-conesole.targets" target="build\Cone.targets" />
<file src="dotnet-conesole.targets" target="buildMultiTargeting\Cone.targets" />
-->
</files>
</package>
2 changes: 1 addition & 1 deletion Run-Tests.bat
@@ -1,4 +1,4 @@
@echo off
pushd Specs\Cone.Specs
dotnet ..\..\Build\dotnet-conesole\Debug\netcoreapp2.0\dotnet-conesole.dll
dotnet ..\..\Build\dotnet-conesole\Debug\netcoreapp2.2\dotnet-conesole.dll
popd
2 changes: 1 addition & 1 deletion Source/Cone.Build/Cone.Build.csproj
Expand Up @@ -10,7 +10,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Cone.Build</RootNamespace>
<AssemblyName>Cone.Build</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<BuildPath>$(SolutionDir)</BuildPath>
<OutputPath>$(BuildPath)Bin\$(MSBuildProjectName)</OutputPath>
Expand Down
4 changes: 2 additions & 2 deletions Source/Cone.TestAdapter/Cone.TestAdapter.csproj
@@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<Import Project="$(SolutionDir)\Cone.props" />
<PropertyGroup>
<TargetFrameworks>net452</TargetFrameworks>
<TargetFrameworks>net452;net462;net472</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Version.cs" Link="Version.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.TestPlatform.ObjectModel" Version="16.0.1" PrivateAssets="All" />
<PackageReference Include="Microsoft.TestPlatform.ObjectModel" Version="16.1.1" PrivateAssets="All" />
<PackageReference Include="System.Runtime.InteropServices.RuntimeInformation" Version="4.3.0" />
<ProjectReference Include="..\Cone\Cone.csproj" PrivateAssets="All" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
Expand Down
4 changes: 3 additions & 1 deletion Source/Cone.Worker/Cone.Worker.csproj
Expand Up @@ -2,7 +2,9 @@
<Import Project="$(SolutionDir)\Cone.props" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net45;net462;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2</TargetFrameworks>
<TargetFrameworks>net452;net462;net472;netcoreapp2.0;netcoreapp2.2</TargetFrameworks>
<TargetFrameworkFamily Condition="$(TargetFramework.StartsWith('net4'))">NETFX</TargetFrameworkFamily>
<DefineConstants>$(DefineConstants);$(TargetFrameworkFamily)</DefineConstants>
<ApplicationIcon />
<StartupObject />
</PropertyGroup>
Expand Down
4 changes: 2 additions & 2 deletions Source/Cone.Worker/Program.cs
Expand Up @@ -28,7 +28,7 @@ static int Main(string[] args)
static string GetConePath(string workingDir) => Path.Combine(workingDir, "Cone.dll");

static bool RanInTestDomain(string target, string workingDir, string[] args, out int result) {
#if NET45 || NET462
#if NETFX
var targetConfig = target + ".config";
if(!File.Exists(targetConfig) || !AppDomain.CurrentDomain.IsDefaultAppDomain()) {
result = 0;
Expand All @@ -46,7 +46,7 @@ static int Main(string[] args)
new System.Security.PermissionSet(System.Security.Permissions.PermissionState.Unrestricted));
result = testDomain.ExecuteAssembly(new Uri(typeof(Program).Assembly.CodeBase).LocalPath, args);
return true;
#elif NETCOREAPP2_0 || NETCOREAPP2_1 || NETCOREAPP2_2
#else
result = 0;
return false;
#endif
Expand Down
3 changes: 1 addition & 2 deletions Source/Cone/Cone.csproj
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<Import Project="$(SolutionDir)\Cone.props" />
<PropertyGroup>
<TargetFrameworks>net45;netstandard2.0</TargetFrameworks>
<TargetFrameworks>net452;net462;net472;netstandard2.0</TargetFrameworks>
<TargetFrameworkFamily Condition="$(TargetFramework.StartsWith('netstandard'))">NETSTANDARD</TargetFrameworkFamily>
<TargetFrameworkFamily Condition="$(TargetFramework.StartsWith('net4'))">NETFX</TargetFrameworkFamily>
<DefineConstants>$(DefineConstants);$(TargetFrameworkFamily)</DefineConstants>
Expand All @@ -11,7 +11,6 @@
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<ProjectReference Include="..\Cone.Expectations\Cone.Expectations.csproj" />
</ItemGroup>

<PropertyGroup Condition="'$(TargetFramework)'=='netstandard2.0'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
Expand Down
67 changes: 53 additions & 14 deletions Source/Cone/Core/AssemblyLoader.cs
Expand Up @@ -6,6 +6,7 @@

namespace Cone.Core
{
using System.Diagnostics;
using System.IO;
#if NETFX
static class AssemblyLoader
Expand All @@ -23,28 +24,28 @@ static class AssemblyLoader

public class ConeLoadContext : AssemblyLoadContext
{
readonly TextWriter LoadingLog = TextWriter.Null;
public TextWriter LoadingLog = TextWriter.Null;
readonly Dictionary<AssemblyName, Assembly> knownAssemblies = new Dictionary<AssemblyName, Assembly>();

public Assembly ResolveKnownAssembly(AssemblyLoadContext parent, AssemblyName assemblyName) {
LoadingLog?.WriteLine($"Resolving {assemblyName}");
knownAssemblies.TryGetValue(assemblyName, out var found);
return found;
public Assembly ResolveKnownAssembly(AssemblyLoadContext _, AssemblyName assemblyName) {
if(knownAssemblies.TryGetValue(assemblyName, out var found))
return found;
return null;
}

public void Load(DependencyItem dep)
{
LoadingLog.WriteLine($"-> {dep.Path}");
if(dep.IsManaged) {
try {
var loaded = Default.LoadFromAssemblyPath(dep.Path);
knownAssemblies.Add(loaded.GetName(), loaded);
} catch {
LoadingLog?.WriteLine($"Ooops when loading {dep.Path}");
Add(Default.LoadFromAssemblyPath(dep.Path));
} catch(Exception ex) {
LoadingLog?.WriteLine($"!!! Managed Load Failure {dep.Path}: {ex}");
}
} else try {
LoadUnmanagedDllFromPath(dep.Path);
}catch {
LoadingLog?.WriteLine($"Ooops when loading {dep.Path}");
}catch(Exception ex) {
LoadingLog?.WriteLine($"!!! Native Load Failure {dep.Path}: {ex}");
}
}

Expand All @@ -69,14 +70,18 @@ public static class AssemblyLoader

public static void InitDeps(string mainAssembly) {
var deps = AssemblyJsonDeps.LoadFrom(mainAssembly);
var os = Environment.GetEnvironmentVariable("CONE_RUNTIME_OS") ?? GetOs();
var runtime = new RuntimeInfo {
OS = Environment.GetEnvironmentVariable("CONE_RUNTIME_OS") ?? (string)typeof(RuntimeEnvironment).GetMethod("GetRIDOS", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, null),
OS = os,
Arch = RuntimeEnvironment.RuntimeArchitecture,
//FrameworkVersion = "netstandard2.0",
FrameworkVersion = Environment.GetEnvironmentVariable("CONE_TARGET_FRAMEWORK"),
PackageProbePaths = AppContext.GetData("PROBING_DIRECTORIES").ToString().Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries),
ApplicationBase = Path.GetDirectoryName(mainAssembly),
PackageProbePaths = GetProbePaths(os),
};
LoadContext = new ConeLoadContext();
//foreach(var path in runtime.PackageProbePaths)
// Console.WriteLine($"Probing: {path}");
LoadContext = new ConeLoadContext { LoadingLog = TextWriter.Null };
var seen = new HashSet<string>();
foreach(var dep in deps.GetRuntimeDependencies()
.SelectMany(x => x.GetLoadOrder())
Expand All @@ -87,6 +92,40 @@ public static class AssemblyLoader

AssemblyLoadContext.Default.Resolving += LoadContext.ResolveKnownAssembly;
}

static string GetOs() {
switch(RuntimeEnvironment.OperatingSystemPlatform) {
case Platform.Windows: return "win";
case Platform.Linux: return "linux";
case Platform.Darwin: return "osx";
default: throw new NotSupportedException();
}
}

static string[] GetProbePaths(string os)
{
var probeDirs = new HashSet<string>(
AppContext.GetData("PROBING_DIRECTORIES")
.ToString()
.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries));


var packageDirectory = Environment.GetEnvironmentVariable("NUGET_PACKAGES");
if(!string.IsNullOrEmpty(packageDirectory))
probeDirs.Add(packageDirectory);

string basePath;
if (os == "win") {
basePath = Environment.GetEnvironmentVariable("USERPROFILE");
}
else {
basePath = Environment.GetEnvironmentVariable("HOME");
}
if(basePath != null)
probeDirs.Add(Path.Combine(basePath, ".nuget", "packages"));

return probeDirs.ToArray();
}
}
#endif
}
174 changes: 87 additions & 87 deletions Source/Cone/Core/Invokable.cs
@@ -1,92 +1,92 @@
using System;
using System.Collections.Concurrent;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using System.Linq;

namespace Cone.Core
{
public struct Invokable : ICustomAttributeProvider
{
static Func<object, object> TaskAwait = obj => {
var awaiter = ((Task)obj).GetAwaiter();
awaiter.GetResult();
return null;
};

static readonly ConcurrentDictionary<Type, Func<object, object>> awaiterCache = new ConcurrentDictionary<Type, Func<object, object>>();

readonly MethodInfo method;
readonly Func<object, object> awaitAction;

public Invokable(MethodInfo method) {
this.method = method;
this.awaitAction = GetAwaiterOrDefault(method.ReturnType);
using System;
using System.Collections.Concurrent;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using System.Linq;

namespace Cone.Core
{
public struct Invokable : ICustomAttributeProvider
{
static Func<object, object> TaskAwait = obj => {
var awaiter = ((Task)obj).GetAwaiter();
awaiter.GetResult();
return null;
};

static readonly ConcurrentDictionary<Type, Func<object, object>> awaiterCache = new ConcurrentDictionary<Type, Func<object, object>>();

readonly MethodInfo method;
readonly Func<object, object> awaitAction;

public Invokable(MethodInfo method) {
this.method = method;
this.awaitAction = GetAwaiterOrDefault(method.ReturnType);
}

public bool IsAsync => GetCustomAttributes(true).Any(x => x.GetType().FullName == "System.Runtime.CompilerServices.AsyncStateMachineAttribute");
public string Location => $"{method.ReturnType} {method.DeclaringType}.{method.Name}({method.GetParameters().Select(x => x.ToString()).Join(", ")})";

internal MethodInfo Target => method;
public Type ReturnType => method.ReturnType;
public Type DeclaringType => method.DeclaringType;
public string Name => method.Name;
public bool IsWaitable => awaitAction != null;
public bool IsStatic => method.IsStatic;

public object[] GetCustomAttributes(bool inherit) =>
method.GetCustomAttributes(inherit);

public object[] GetCustomAttributes(Type attributeType, bool inherit) =>
method.GetCustomAttributes(attributeType, inherit);

public bool IsDefined(Type attributeType, bool inherit) =>
method.IsDefined(attributeType, inherit);

public ParameterInfo[] GetParameters() =>
method.GetParameters();

public object Invoke(object target, object[] args) =>
method.Invoke(target, args);

public object Await(object target, object[] args) {
var r = Invoke(target, args);
return IsWaitable ? awaitAction(r) : r;
}

static Func<object, object> GetAwaiterOrDefault(Type type) {
if(type == typeof(void))
return null;

if(type == typeof(Task))
return TaskAwait;

return awaiterCache.GetOrAdd(type, CreateAwaiterOrDefault);
}

static Func<object, object> CreateAwaiterOrDefault(Type type) {
var getAwaiter = type.GetMethod("GetAwaiter", Type.EmptyTypes);
if(getAwaiter != null) {
var getResult = getAwaiter.ReturnType.GetMethod("GetResult") ??
throw new InvalidOperationException("Can't GetResult on " + getAwaiter.ReturnType);

var awaitable = Expression.Parameter(typeof(object));
var getUnboxedResult = Expression.Call(
Expression.Call(
Expression.Convert(awaitable, type),
getAwaiter),
getResult);
var body = getUnboxedResult.Type == typeof(void)
? Expression.Block(getUnboxedResult, Expression.Constant(null))
: getUnboxedResult.Box();
return Expression.Lambda<Func<object, object>>(body, awaitable)
.Compile();
}
return null;
}

public static void Await(object obj) =>
GetAwaiterOrDefault(obj.GetType())?.DynamicInvoke(obj);
}

internal MethodInfo Target => method;
public Type ReturnType => method.ReturnType;
public Type DeclaringType => method.DeclaringType;
public string Name => method.Name;
public bool IsWaitable => awaitAction != null;
public bool IsStatic => method.IsStatic;

public object[] GetCustomAttributes(bool inherit) =>
method.GetCustomAttributes(inherit);

public object[] GetCustomAttributes(Type attributeType, bool inherit) =>
method.GetCustomAttributes(attributeType, inherit);

public bool IsDefined(Type attributeType, bool inherit) =>
method.IsDefined(attributeType, inherit);

public ParameterInfo[] GetParameters() =>
method.GetParameters();

public object Invoke(object target, object[] args) =>
method.Invoke(target, args);

public object Await(object target, object[] args) {
var r = Invoke(target, args);
return IsWaitable ? awaitAction(r) : r;
}

static Func<object, object> GetAwaiterOrDefault(Type type) {
if(type == typeof(void))
return null;

if(type == typeof(Task))
return TaskAwait;

return awaiterCache.GetOrAdd(type, CreateAwaiterOrDefault);
}

static Func<object, object> CreateAwaiterOrDefault(Type type) {
var getAwaiter = type.GetMethod("GetAwaiter", Type.EmptyTypes);
if(getAwaiter != null) {
var getResult = getAwaiter.ReturnType.GetMethod("GetResult") ??
throw new InvalidOperationException("Can't GetResult on " + getAwaiter.ReturnType);

var awaitable = Expression.Parameter(typeof(object));
var getUnboxedResult = Expression.Call(
Expression.Call(
Expression.Convert(awaitable, type),
getAwaiter),
getResult);
var body = getUnboxedResult.Type == typeof(void)
? Expression.Block(getUnboxedResult, Expression.Constant(null))
: getUnboxedResult.Box();
return Expression.Lambda<Func<object, object>>(body, awaitable)
.Compile();
}
return null;
}

public static void Await(object obj) =>
GetAwaiterOrDefault(obj.GetType())?.DynamicInvoke(obj);
}
}
2 changes: 1 addition & 1 deletion Source/Cone/Runners/ConesoleRunner.cs
Expand Up @@ -3,7 +3,7 @@
using System.IO;
using System.Linq;
using System.Reflection;
#if NET45
#if NETFX
#else
using System.Runtime.Loader;
#endif
Expand Down

0 comments on commit b164986

Please sign in to comment.