Pergunta

Eu gostaria de escrever testes automatizados que correm em meio confiança e não conseguem se eles exigem confiança total.

Eu estou escrevendo uma biblioteca onde algumas funcionalidades só está disponível em cenários de confiança total e quero verificar se o código que deseja executar em confiança média irá funcionar bem. Se também querem saber que se eu mudar de uma classe que requer confiança total, que meus testes falhará.

Eu tentei criar um outro AppDomain e carregar o PolicyLevel meio confiança, mas eu sempre obter um erro com montagem ou sua dependência não pôde ser carregado durante a tentativa de executar o callback AppDomain cruz.

Existe uma maneira de conseguir isso?

update : respostas baseadas, aqui é o que eu tenho. Note-se que a sua classe que está sendo testado deve estender MarshalByRefObject. Isso é muito limitante, mas eu não vejo uma maneira de contornar isso.

using System;
using System.Reflection;
using System.Security;
using System.Security.Permissions;
using Xunit;

namespace PartialTrustTest
{
    [Serializable]
    public class ClassUnderTest : MarshalByRefObject
    {
        public void PartialTrustSuccess()
        {
            Console.WriteLine( "partial trust success #1" );
        }

        public void PartialTrustFailure()
        {
            FieldInfo fi = typeof (Int32).GetField( "m_value", BindingFlags.Instance | BindingFlags.NonPublic );
            object value = fi.GetValue( 1 );
            Console.WriteLine( "value: {0}", value );
        }
    }

    public class Test
    {
        [Fact]
        public void MediumTrustWithExternalClass()
        {
            // ClassUnderTest must extend MarshalByRefObject
            var classUnderTest = MediumTrustContext.Create<ClassUnderTest>();

            classUnderTest.PartialTrustSuccess();
            Assert.Throws<FieldAccessException>( classUnderTest.PartialTrustFailure );
        }
    }

    internal static class MediumTrustContext
    {
        public static T Create<T>()
        {
            AppDomain appDomain = CreatePartialTrustDomain();
            var t = (T) appDomain.CreateInstanceAndUnwrap( typeof (T).Assembly.FullName, typeof (T).FullName );
            return t;
        }

        public static AppDomain CreatePartialTrustDomain()
        {
            var setup = new AppDomainSetup {ApplicationBase = AppDomain.CurrentDomain.BaseDirectory};
            var permissions = new PermissionSet( null );
            permissions.AddPermission( new SecurityPermission( SecurityPermissionFlag.Execution ) );
            permissions.AddPermission( new ReflectionPermission( ReflectionPermissionFlag.RestrictedMemberAccess ) );
            return AppDomain.CreateDomain( "Partial Trust AppDomain: " + DateTime.Now.Ticks, null, setup, permissions );
        }
    }
}
Foi útil?

Solução

Acabei de publicar um artigo intitulado parcial Confiança testando com xUnit.net . Ele detalha a estrutura baseada em xUnit.net que usamos na equipe Entity Framework ao código de exercício sob confiança parcial.

Aqui está um exemplo de seu uso.

public class SomeTests : MarshalByRefObject
{
    [PartialTrustFact]
    public void Partial_trust_test1()
    {
        // Runs in medium trust
    }
}

// Or...

[PartialTrustFixture]
public class MoreTests : MarshalByRefObject
{
    [Fact]
    public void Another_partial_trust_test()
    {
        // Runs in medium trust
    }
}

Outras dicas

Descaradamente roubado de Como hospedar um parcial Confiança Sandbox - # 7 , mas reimplemented (junto com um caso de teste simples) em F # apenas por diversão: -)

open System
open System.Reflection
open System.Security
open System.Security.Permissions
open System.Security.Policy

type Program() =
    inherit System.MarshalByRefObject()
    member x.PartialTrustSuccess() =
        Console.WriteLine("foo")
    member x.PartialTrustFailure() =
        let field = typeof<Int32>.GetField("m_value", BindingFlags.Instance ||| BindingFlags.NonPublic)
        let value = field.GetValue(1)
        Console.WriteLine("value: {0}", value)

[<EntryPoint>]
let main _ =
    let appDomain =
        let setup = AppDomainSetup(ApplicationBase = AppDomain.CurrentDomain.BaseDirectory)
        let permissions = PermissionSet(null)
        permissions.AddPermission(SecurityPermission(SecurityPermissionFlag.Execution)) |> ignore
        permissions.AddPermission(ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess)) |> ignore
        AppDomain.CreateDomain("Partial Trust AppDomain", null, setup, permissions)

    let program = appDomain.CreateInstanceAndUnwrap(
                      typeof<Program>.Assembly.FullName,
                      typeof<Program>.FullName) :?> Program

    program.PartialTrustSuccess()

    try
        program.PartialTrustFailure()
        Console.Error.WriteLine("partial trust test failed")
    with
        | :? FieldAccessException -> ()

    0

E uma versão C #:

using System;
using System.Reflection;
using System.Security;
using System.Security.Permissions;
using System.Security.Policy;

namespace PartialTrustTest
{
    internal class Program : MarshalByRefObject
    {
        public void PartialTrustSuccess()
        {
            Console.WriteLine("partial trust success #1");
        }

        public void PartialTrustFailure()
        {
            FieldInfo fi = typeof(Int32).GetField("m_value", BindingFlags.Instance | BindingFlags.NonPublic);
            object value = fi.GetValue(1);
            Console.WriteLine("value: {0}", value);
        }

        private static AppDomain CreatePartialTrustDomain()
        {
            AppDomainSetup setup = new AppDomainSetup() { ApplicationBase = AppDomain.CurrentDomain.BaseDirectory };
            PermissionSet permissions = new PermissionSet(null);
            permissions.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
            permissions.AddPermission(new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess));
            return AppDomain.CreateDomain("Partial Trust AppDomain", null, setup, permissions);
        }

        static void Main(string[] args)
        {
            AppDomain appDomain = CreatePartialTrustDomain();

            Program program = (Program)appDomain.CreateInstanceAndUnwrap(
                typeof(Program).Assembly.FullName,
                typeof(Program).FullName);

            program.PartialTrustSuccess();

            try
            {
                program.PartialTrustFailure();
                Console.Error.WriteLine("!!! partial trust test failed");
            }
            catch (FieldAccessException)
            {
                Console.WriteLine("partial trust success #2");
            }
        }
    }
}
 C:\temp\PartialTrustTest\bin\Debug>PartialTrustTest.exe
 partial trust success #1
 partial trust success #2

Eu publiquei um post no blog de três partes sobre o teste de unidade em confiança média

Eu girar um AppDomain alternativa em uma forma similar a algumas respostas aqui, mas levá-la ainda mais usando um MarshalByRefObject para invocar o método de teste em outro AppDomain, ou seja, suas classes de teste não precisa implementar MarshalByRefObject

A terceira parte (contendo links para as outras partes) é aqui http://boxbinary.com/2011/10/how-to-run-a-unit-test-in-medium-trust-with -nunitpart-três umbraco-estrutura de testes /

Eu nunca tentou fazer isso, mas, em geral, para lidar com a montagem carregar falhas de AppDomains personalizados, você pode usar o evento AppDomain.AssemblyResolve.

Embora totalmente independentes, aqui está um exemplo do uso AppDomain. AssemblyResolve .

A resposta depende do que o seu código faz quando alguém com tentativas de privilégio de confiança média para acessar um recurso de confiança total. Presumo algum tipo de exceção será lançada.

Nesse caso, escrever um teste de unidade que corre em meio contexto confiança, as tentativas para aceder a um recurso de plena confiança, e espera que a exceção seja lançada. Se você nunca escreveu um teste como este, uma maneira comum de fazer isso que a maioria das estruturas de teste irão apoiar é o seguinte:

testMediumTrustUserWontAccessFeatureX()
{
    // set up the context of your test ...

    try
    {
        accessFullTrustFeature();
        fail("Test failed - Medium trust user can access full trust feature");
    }
    catch( SomeKindOfException e )
    {
        // Success - feature was denied to the untrusted user 
    }
}

Se a exceção é detectada, significa que o usuário não confiável não conseguiu acessar o recurso (eo teste passa), mas se a exceção nunca é pego, o teste falhar (que esperávamos uma exceção e não obtê-lo ).

Este é um código pseudo java-esque, mas este padrão deve funcionar em qualquer linguagem que você está usando assumindo que apoiar o tratamento de exceção.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top