使用Roslyn.Services.Workspace进行单元测试会导致在x86目标下工作时出现SecurityException

时间:2013-05-06 07:04:42

标签: nunit deserialization appdomain roslyn ncrunch

我正在处理我的项目的常量集,我想使用来验证源代码级别中的一些常量。为实现这一目标,我将使用以下代码段将整个解决方案加载到AppDomain with IsFullyTrusted == true and IsHomogenous == true, i.e. remoting is enabled with x86 platform target

// load workspace, i.e. solution from Visual Studio
var workspace = Roslyn.Services.Workspace.LoadSolution(solutionFile);

使用带有Roslyn

的x86平台测试NCrunch和NUnit的跑步者

同时使用 1.45或 2.6.2 nunit-console-x86.exe并将平台配置x86作为测试运行者时,我会不断关注System.Security.SecurityException < /强>:

System.Security.SecurityException : Type System.Runtime.Remoting.ObjRef and the types derived from it (such as System.Runtime.Remoting.ObjRef) are not permitted to be deserialized at this security level.

Server stack trace: 
   at System.Runtime.Serialization.FormatterServices.CheckTypeSecurity(Type t, TypeFilterLevel securityLevel)
   at System.Runtime.Serialization.Formatters.Binary.ObjectReader.CheckSecurity(ParseRecord pr)
   at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ParseObject(ParseRecord pr)
   at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Parse(ParseRecord pr)
   at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryObjectWithMapTyped record)
   at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryHeaderEnum binaryHeaderEnum)
   at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
   at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
   at System.Runtime.Remoting.Channels.CoreChannel.DeserializeBinaryRequestMessage(String objectUri, Stream inputStream, Boolean bStrictBinding, TypeFilterLevel securityLevel)
   at System.Runtime.Remoting.Channels.BinaryServerFormatterSink.ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, IMessage& responseMsg, ITransportHeaders& responseHeaders, Stream& responseStream)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at Roslyn.Utilities.RemoteServices.Initialize(Int32 clientProcessId)
   at Roslyn.Utilities.RemoteServices.StartRemoteServicesProcess()
   at Roslyn.Utilities.RemoteServices.get_Instance()
   at Roslyn.Utilities.RemoteServices.CreateInstance[T]()
   at Roslyn.Services.Host.TemporaryStorageServiceFactory.CreateService(IWorkspaceServiceProvider workspaceServices)
   at Roslyn.Services.Host.WorkspaceServiceProviderFactory.<>c__DisplayClass6.<OnImportsSatisfied>b__1(IWorkspaceServiceProvider wsp)
   at Roslyn.Services.Host.WorkspaceServiceProvider.ConstructService(Type type)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Roslyn.Services.Host.WorkspaceServiceProvider.GetService[TWorkspaceService]()
   at Roslyn.Services.SolutionServices..ctor(IWorkspaceServiceProvider workspaceServices)
   at Roslyn.Services.Solution..ctor(SolutionId id, String filePath, VersionStamp version, VersionStamp latestProjectVersion, IWorkspaceServiceProvider workspaceServices)
   at Roslyn.Services.Host.SolutionFactoryServiceFactory.SolutionFactoryService.CreateSolution(SolutionId id)
   at Roslyn.Services.Host.TrackingWorkspace.CreateNewSolution(ISolutionFactoryService solutionFactory, SolutionId id)
   at Roslyn.Services.Host.TrackingWorkspace..ctor(IWorkspaceServiceProvider workspaceServiceProvider, Boolean enableBackgroundCompilation, Boolean enableInProgressSolutions)
   at Roslyn.Services.Host.HostWorkspace..ctor(IWorkspaceServiceProvider workspaceServiceProvider, Boolean enableBackgroundCompilation, Boolean enableInProgressSolutions, Boolean enableFileTracking)
   at Roslyn.Services.Host.LoadedWorkspace..ctor(IWorkspaceServiceProvider workspaceServiceProvider, IDictionary`2 globalProperties, Boolean enableBackgroundCompilation, Boolean enableFileTracking)
   at Roslyn.Services.Host.LoadedWorkspace.LoadSolution(String solutionFileName, String configuration, String platform, Boolean enableFileTracking)
   at Roslyn.Services.Workspace.LoadSolution(String solutionFileName, String configuration, String platform, Boolean enableFileTracking)

a discussion on NCrunch forum但我已尝试以下所有选项但未成功

  • [assembly: AllowPartiallyTrustedCallers]添加到AssemblyInfo.cs
  • [assembly: SecurityRules(SecurityRuleSet.Level1)]添加到AssemblyInfo.cs
  • <NetFx40_LegacySecurityPolicy enabled="true" />添加到a​​pp.config
  • 以管理员身份运行VS2012
  • 使用[SecuritySafeCritical]
  • 装饰单元测试和实现
  • 更新:创建新AppDomain并提供
    • PermissionState.UnrestrictedSecurityPermissionFlag.AllFlagsDataProtectionPermissionFlags.AllFlags
    • 添加主机证据:SecurityZone.MyComputerSystem.Security.Policy.HashSystem.Security.Policy.StrongName
    • 创建fullTrustAssemblies
    • 时,将所有程序集(我的和Roslyn CTP)添加到AppDomain

更新#2

只有当我在x86配置下运行测试时才会发生此异常,在我切换到x64平台配置后,一切似乎都正常工作

问题

app.configAppDomain是否有任何其他属性或配置更改可能有助于在x86配置下运行时在System.Runtime.Remoting.ObjRef的.NET Framework远程处理中启用反序列化?

临时解决方案

仅针对unittest项目切换到x64构建配置

源代码

其他信息

我也注意到了......

  1. 在所有测试完成后,很多Roslyn.Services.dll实例都在后台挂起。
  2. NCrunch缺乏主机证据:System.Security.Policy.HashSystem.Security.Policy.StrongName带有测试运行器程序集名称
  3. MSIL(应该是x64内部)和 2.6.2 nunit-console.exe测试运行器工作正常,所以它看起来像Roslyn配置/远程处理/安全配置问题即可。

2 个答案:

答案 0 :(得分:4)

看起来正在部分信任中执行测试,而Resharper正在完全信任中运行它们。

Roslyn尚未在部分信任方案中进行测试。可能会访问需要完全信任的API。

我没有使用ncrunch,但也许有一种方法可以配置它以完全信任的方式运行测试?

答案 1 :(得分:1)

我想添加一些内容!

升级NUnit实例后,我设法运行到软件的2.6.2和2.6.3,我的团队遇到了Akim看到的确切System.Security异常的类似问题。

我们正在创建一个IpcChannel,其中包含一些我们自定义的NUnit逻辑,这些逻辑并非使用正确的信任设置创建,因此我们不得不更改类似的内容:

IpcChannel channel = new IpcChannel(string.Format("localhost:{0}", portNum));

到 -

BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
serverProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();

var properties = new System.Collections.Hashtable();
properties["name"] = "ipc";
properties["priority"] = "20";
properties["portName"] = string.Format("localhost:{0}", portNum);

IpcChannel channel = new IpcChannel(properties, clientProvider, serverProvider);

只是一个快速修复我注意到我想我会转发任何人看到类似的东西,不能只是切换他们的平台设置。公平地说,我花了大约四个小时来弄清楚所以我不想让这些知识浪费掉。