Skip to content

Commit 76654a8

Browse files
committed
Add PartialTrustExample
1 parent efbc0e6 commit 76654a8

12 files changed

+422
-0
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="..\packages\xunit.core.2.1.0-beta4-build3037\build\portable-net45+dnxcore50+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.props" Condition="Exists('..\packages\xunit.core.2.1.0-beta4-build3037\build\portable-net45+dnxcore50+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.props')" />
4+
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
5+
<PropertyGroup>
6+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
7+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
8+
<ProjectGuid>{19F535B4-8B47-4F45-A5BF-7DEAB9CBB06F}</ProjectGuid>
9+
<OutputType>Library</OutputType>
10+
<AppDesignerFolder>Properties</AppDesignerFolder>
11+
<RootNamespace>PartialTrustExample</RootNamespace>
12+
<AssemblyName>PartialTrustExample</AssemblyName>
13+
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
14+
<FileAlignment>512</FileAlignment>
15+
<NuGetPackageImportStamp>fce55182</NuGetPackageImportStamp>
16+
</PropertyGroup>
17+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
18+
<DebugSymbols>true</DebugSymbols>
19+
<DebugType>full</DebugType>
20+
<Optimize>false</Optimize>
21+
<OutputPath>bin\Debug\</OutputPath>
22+
<DefineConstants>DEBUG;TRACE</DefineConstants>
23+
<ErrorReport>prompt</ErrorReport>
24+
<WarningLevel>4</WarningLevel>
25+
</PropertyGroup>
26+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
27+
<DebugType>pdbonly</DebugType>
28+
<Optimize>true</Optimize>
29+
<OutputPath>bin\Release\</OutputPath>
30+
<DefineConstants>TRACE</DefineConstants>
31+
<ErrorReport>prompt</ErrorReport>
32+
<WarningLevel>4</WarningLevel>
33+
</PropertyGroup>
34+
<ItemGroup>
35+
<Reference Include="System" />
36+
<Reference Include="System.Core" />
37+
<Reference Include="Microsoft.CSharp" />
38+
<Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
39+
<HintPath>..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll</HintPath>
40+
<Private>True</Private>
41+
</Reference>
42+
<Reference Include="xunit.assert, Version=2.1.0.3037, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
43+
<HintPath>..\packages\xunit.assert.2.1.0-beta4-build3037\lib\portable-net45+dnxcore50+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll</HintPath>
44+
<Private>True</Private>
45+
</Reference>
46+
<Reference Include="xunit.core, Version=2.1.0.3037, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
47+
<HintPath>..\packages\xunit.extensibility.core.2.1.0-beta4-build3037\lib\portable-net45+dnxcore50+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll</HintPath>
48+
<Private>True</Private>
49+
</Reference>
50+
<Reference Include="xunit.execution.desktop, Version=2.1.0.3037, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
51+
<HintPath>..\packages\xunit.extensibility.execution.2.1.0-beta4-build3037\lib\net45\xunit.execution.desktop.dll</HintPath>
52+
<Private>True</Private>
53+
</Reference>
54+
</ItemGroup>
55+
<ItemGroup>
56+
<Compile Include="PartialTrustFactAttribute.cs" />
57+
<Compile Include="XunitExtensions\PartialTrustFactDiscoverer.cs" />
58+
<Compile Include="XunitExtensions\PartialTrustSandbox.cs" />
59+
<Compile Include="XunitExtensions\PartialTrustTestCase.cs" />
60+
<Compile Include="Properties\AssemblyInfo.cs" />
61+
<Compile Include="Samples.cs" />
62+
<Compile Include="XunitExtensions\PartialTrustTestCaseRunner.cs" />
63+
<Compile Include="XunitExtensions\PartialTrustTestInvoker.cs" />
64+
<Compile Include="XunitExtensions\PartialTrustTestRunner.cs" />
65+
</ItemGroup>
66+
<ItemGroup>
67+
<None Include="packages.config" />
68+
</ItemGroup>
69+
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
70+
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
71+
<PropertyGroup>
72+
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
73+
</PropertyGroup>
74+
<Error Condition="!Exists('..\packages\xunit.core.2.1.0-beta4-build3037\build\portable-net45+dnxcore50+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\xunit.core.2.1.0-beta4-build3037\build\portable-net45+dnxcore50+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.props'))" />
75+
</Target>
76+
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
77+
Other similar extension points exist, see Microsoft.Common.targets.
78+
<Target Name="BeforeBuild">
79+
</Target>
80+
<Target Name="AfterBuild">
81+
</Target>
82+
-->
83+
</Project>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System;
2+
using Xunit;
3+
using Xunit.Sdk;
4+
5+
namespace PartialTrustExample
6+
{
7+
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
8+
[XunitTestCaseDiscoverer("PartialTrustExample.XunitExtensions.PartialTrustFactDiscoverer", "PartialTrustExample")]
9+
public class PartialTrustFactAttribute : FactAttribute { }
10+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System.Reflection;
2+
using System.Runtime.CompilerServices;
3+
using System.Runtime.InteropServices;
4+
5+
// General Information about an assembly is controlled through the following
6+
// set of attributes. Change these attribute values to modify the information
7+
// associated with an assembly.
8+
[assembly: AssemblyTitle("PartialTrustExample")]
9+
[assembly: AssemblyDescription("")]
10+
[assembly: AssemblyConfiguration("")]
11+
[assembly: AssemblyCompany("")]
12+
[assembly: AssemblyProduct("PartialTrustExample")]
13+
[assembly: AssemblyCopyright("Copyright © 2015")]
14+
[assembly: AssemblyTrademark("")]
15+
[assembly: AssemblyCulture("")]
16+
17+
// Setting ComVisible to false makes the types in this assembly not visible
18+
// to COM components. If you need to access a type in this assembly from
19+
// COM, set the ComVisible attribute to true on that type.
20+
[assembly: ComVisible(false)]
21+
22+
// The following GUID is for the ID of the typelib if this project is exposed to COM
23+
[assembly: Guid("e31ee1e3-92c8-49f4-b882-4f98ebda294b")]
24+
25+
// Version information for an assembly consists of the following four values:
26+
//
27+
// Major Version
28+
// Minor Version
29+
// Build Number
30+
// Revision
31+
//
32+
// You can specify all the values or you can default the Build and Revision Numbers
33+
// by using the '*' as shown below:
34+
// [assembly: AssemblyVersion("1.0.*")]
35+
[assembly: AssemblyVersion("1.0.0.0")]
36+
[assembly: AssemblyFileVersion("1.0.0.0")]

PartialTrustExample/Samples.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System;
2+
using System.Security;
3+
using System.Security.Permissions;
4+
using Xunit;
5+
6+
namespace PartialTrustExample
7+
{
8+
// Test class has to be MarshalByRefObject, because it's created in the partial trust app domain sandbox.
9+
// The PartialTrustTestInvoker catches serialization issues and lets the user know they forgot to use
10+
// MarshalByRefObject (as well as cleaning up the sandbox).
11+
public class Samples : MarshalByRefObject
12+
{
13+
[Fact]
14+
public void Passing()
15+
{
16+
DemandFullTrust();
17+
}
18+
19+
[PartialTrustFact]
20+
public void Failing()
21+
{
22+
DemandFullTrust();
23+
}
24+
25+
static void DemandFullTrust()
26+
{
27+
// This demands full trust. It should pass from an full trust app domain, and
28+
// fail from a partial trust domain.
29+
new PermissionSet(PermissionState.Unrestricted).Demand();
30+
}
31+
}
32+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System.Collections.Generic;
2+
using Xunit.Abstractions;
3+
using Xunit.Sdk;
4+
5+
namespace PartialTrustExample.XunitExtensions
6+
{
7+
public class PartialTrustFactDiscoverer : IXunitTestCaseDiscoverer
8+
{
9+
readonly IMessageSink diagnosticMessageSink;
10+
11+
public PartialTrustFactDiscoverer(IMessageSink diagnosticMessageSink)
12+
{
13+
this.diagnosticMessageSink = diagnosticMessageSink;
14+
}
15+
16+
public IEnumerable<IXunitTestCase> Discover(ITestFrameworkDiscoveryOptions discoveryOptions, ITestMethod testMethod, IAttributeInfo factAttribute)
17+
{
18+
yield return new PartialTrustTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), testMethod);
19+
}
20+
}
21+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// Copied (and modified) from:
2+
// http://entityframework.codeplex.com/
3+
// At commit hash 0c1de1b441c9695ff3807dfa551dfb4b25008569
4+
//
5+
// Copyright (c) Microsoft Open Technologies, Inc.
6+
// Licensed under Apache 2 (http://entityframework.codeplex.com/SourceControl/changeset/view/0c1de1b441c9695ff3807dfa551dfb4b25008569#License.txt)
7+
8+
using System;
9+
using System.IO;
10+
using System.Runtime.InteropServices;
11+
using System.Security;
12+
using System.Security.Permissions;
13+
14+
namespace PartialTrustExample.XunitExtensions
15+
{
16+
/// <summary>
17+
/// Represents a partial trust sandbox
18+
/// </summary>
19+
public class PartialTrustSandbox : IDisposable
20+
{
21+
private static readonly PartialTrustSandbox _default = new PartialTrustSandbox("Default Partial Trust Sandbox");
22+
private AppDomain _domain;
23+
24+
/// <summary>
25+
/// Constructs a new partial trust sandbox
26+
/// </summary>
27+
/// <param name="grantReflectionPermission"> Specify true to grant unrestricted reflection permission </param>
28+
/// <param name="configurationFile"> Specify an alternate configuration file for the AppDoman. By default, the calling domain's will be used </param>
29+
/// <remarks>
30+
/// If you do not need any special configuration, use the <see cref="Default" /> instance.
31+
/// </remarks>
32+
public PartialTrustSandbox(bool grantReflectionPermission = false, string configurationFile = null)
33+
: this("Partial Trust Sandbox " + Guid.NewGuid(), grantReflectionPermission, configurationFile) { }
34+
35+
protected PartialTrustSandbox(string domainName, bool grantReflectionPermission = false, string configurationFile = null)
36+
{
37+
var securityConfig = Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), "CONFIG", "web_mediumtrust.config");
38+
var permissionXml = File.ReadAllText(securityConfig).Replace("$AppDir$", Environment.CurrentDirectory);
39+
40+
// ASP.NET's configuration files still use the full policy levels rather than just permission sets,
41+
// so we can either write a lot of code to parse them ourselves, or we can use a deprecated API to
42+
// load them.
43+
#pragma warning disable 0618
44+
var grantSet = SecurityManager.LoadPolicyLevelFromString(permissionXml, PolicyLevelType.AppDomain).GetNamedPermissionSet("ASP.Net");
45+
#pragma warning restore 0618
46+
47+
if (grantReflectionPermission)
48+
grantSet.AddPermission(new ReflectionPermission(PermissionState.Unrestricted));
49+
50+
var info = new AppDomainSetup
51+
{
52+
ApplicationBase = Environment.CurrentDirectory,
53+
PartialTrustVisibleAssemblies = new[]
54+
{
55+
// Add conditional APTCA assemblies that you need to access in partial trust here.
56+
// Do NOT add System.Web here since at least one test relies on it not being treated as conditionally APTCA.
57+
"System.ComponentModel.DataAnnotations, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9"
58+
}
59+
};
60+
61+
info.ConfigurationFile = configurationFile ?? AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
62+
63+
_domain = AppDomain.CreateDomain(domainName, null, info, grantSet, null);
64+
}
65+
66+
~PartialTrustSandbox()
67+
{
68+
Dispose(false);
69+
}
70+
71+
public static PartialTrustSandbox Default
72+
{
73+
get { return _default; }
74+
}
75+
76+
/// <summary>
77+
/// Creates a new instance of the specified type in the partial trust sandbox and returns a proxy to it.
78+
/// </summary>
79+
/// <typeparam name="T"> The type of object to create </typeparam>
80+
/// <returns> A proxy to the instance created in the partial trust sandbox </returns>
81+
public T CreateInstance<T>(params object[] args)
82+
{
83+
return (T)CreateInstance(typeof(T), args);
84+
}
85+
86+
/// <summary>
87+
/// Creates a new instance of the specified type in the partial trust sandbox and returns a proxy to it.
88+
/// </summary>
89+
/// <param name="type"> The type of object to create </param>
90+
/// <returns> A proxy to the instance created in the partial trust sandbox </returns>
91+
public object CreateInstance(Type type, params object[] args)
92+
{
93+
HandleDisposed();
94+
95+
#pragma warning disable 0618
96+
return _domain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName, false, 0, null, args, null, null, null);
97+
#pragma warning restore 0618
98+
}
99+
100+
public void Dispose()
101+
{
102+
Dispose(true);
103+
GC.SuppressFinalize(this);
104+
}
105+
106+
protected virtual void Dispose(bool disposing)
107+
{
108+
if (disposing && _domain != null)
109+
{
110+
AppDomain.Unload(_domain);
111+
_domain = null;
112+
}
113+
}
114+
115+
private void HandleDisposed()
116+
{
117+
if (_domain == null)
118+
throw new ObjectDisposedException(null);
119+
}
120+
}
121+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System.Threading;
2+
using System.Threading.Tasks;
3+
using Xunit.Abstractions;
4+
using Xunit.Sdk;
5+
6+
namespace PartialTrustExample.XunitExtensions
7+
{
8+
public class PartialTrustTestCase : XunitTestCase
9+
{
10+
public PartialTrustTestCase(IMessageSink diagnosticMessageSink, TestMethodDisplay defaultMethodDisplay, ITestMethod testMethod)
11+
: base(diagnosticMessageSink, defaultMethodDisplay, testMethod) { }
12+
13+
public override Task<RunSummary> RunAsync(IMessageSink diagnosticMessageSink,
14+
IMessageBus messageBus,
15+
object[] constructorArguments,
16+
ExceptionAggregator aggregator,
17+
CancellationTokenSource cancellationTokenSource)
18+
{
19+
return new PartialTrustTestCaseRunner(this, DisplayName, SkipReason, constructorArguments, TestMethodArguments, messageBus, aggregator, cancellationTokenSource).RunAsync();
20+
}
21+
}
22+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System.Threading;
2+
using System.Threading.Tasks;
3+
using Xunit.Sdk;
4+
5+
namespace PartialTrustExample.XunitExtensions
6+
{
7+
public class PartialTrustTestCaseRunner : XunitTestCaseRunner
8+
{
9+
public PartialTrustTestCaseRunner(IXunitTestCase testCase, string displayName, string skipReason, object[] constructorArguments, object[] testMethodArguments, IMessageBus messageBus, ExceptionAggregator aggregator, CancellationTokenSource cancellationTokenSource)
10+
: base(testCase, displayName, skipReason, constructorArguments, testMethodArguments, messageBus, aggregator, cancellationTokenSource) { }
11+
12+
protected override Task<RunSummary> RunTestAsync()
13+
{
14+
var test = new XunitTest(TestCase, DisplayName);
15+
return new PartialTrustTestRunner(test, MessageBus, TestClass, ConstructorArguments, TestMethod, TestMethodArguments, SkipReason, BeforeAfterAttributes, new ExceptionAggregator(Aggregator), CancellationTokenSource).RunAsync();
16+
}
17+
}
18+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Reflection;
4+
using System.Runtime.Serialization;
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
using Xunit.Abstractions;
8+
using Xunit.Sdk;
9+
10+
namespace PartialTrustExample.XunitExtensions
11+
{
12+
public class PartialTrustTestInvoker : XunitTestInvoker
13+
{
14+
PartialTrustSandbox sandbox;
15+
16+
public PartialTrustTestInvoker(ITest test, IMessageBus messageBus, Type testClass, object[] constructorArguments, MethodInfo testMethod, object[] testMethodArguments, IReadOnlyList<BeforeAfterTestAttribute> beforeAfterAttributes, ExceptionAggregator aggregator, CancellationTokenSource cancellationTokenSource)
17+
: base(test, messageBus, testClass, constructorArguments, testMethod, testMethodArguments, beforeAfterAttributes, aggregator, cancellationTokenSource) { }
18+
19+
protected override Task AfterTestMethodInvokedAsync()
20+
{
21+
if (sandbox != null)
22+
sandbox.Dispose();
23+
24+
return base.AfterTestMethodInvokedAsync();
25+
}
26+
27+
protected override object CreateTestClass()
28+
{
29+
sandbox = new PartialTrustSandbox();
30+
31+
try
32+
{
33+
return sandbox.CreateInstance(TestClass, ConstructorArguments);
34+
}
35+
catch (SerializationException)
36+
{
37+
sandbox.Dispose();
38+
sandbox = null;
39+
40+
throw new InvalidOperationException(string.Format("Test class {0} must derive from MarshalByRefObject to use [PartialTrustFact]", TestClass.FullName));
41+
}
42+
}
43+
}
44+
}

0 commit comments

Comments
 (0)