Domanda

Vorrei scrivere dei test automatizzati che vengono eseguiti in media fiducia e falliscono se richiedono piena fiducia.

Sto scrivendo una libreria dove alcune funzionalità è disponibile solo negli scenari di piena fiducia e voglio verificare che il codice voglio correre in mezzo di fiducia funzionerà bene. Se vogliono anche sapere che se cambio una classe che richiede la piena fiducia, che i miei test avrà esito negativo.

Ho provato a generare un altro dominio di applicazione e il caricamento del PolicyLevel fiducia media, ma ho sempre un errore sul montaggio o la sua dipendenza non può essere caricato durante il tentativo di eseguire il callback dominio di applicazione croce.

C'è un modo per tirare fuori questo?

update : risposte Based, ecco quello che ho. Si noti che la classe in fase di test deve estendersi MarshalByRefObject. Questo è molto limitante, ma non vedo un modo intorno ad esso.

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 );
        }
    }
}
È stato utile?

Soluzione

Ho appena pubblicato un articolo dal titolo attendibilità parziale Test con xUnit.net . Vi si descrive il quadro xUnit.net-based che usiamo sulla squadra Entity Framework di esercitare codice sotto attendibilità parziale.

Ecco un esempio del suo utilizzo.

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
    }
}

Altri suggerimenti

spudoratamente rubato da Come ospitare una parziale fiducia Sandbox - # 7 , ma reimplementato (insieme ad un semplice caso di test) in F # solo per calci: -)

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 una versione 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

Ho postato un post sul blog in tre parti sulla unit testing in Medium Trust

I spin up un AppDomain alternativa in modo simile ad alcuni risposte qui, ma lo prendo ulteriormente utilizzando un MarshalByRefObject per invocare il metodo di prova in un altro dominio di applicazione, significa che le vostre classi di test non è necessario implementare MarshalByRefObject

La terza parte (che contiene i collegamenti alle altre parti) è qui http://boxbinary.com/2011/10/how-to-run-a-unit-test-in-medium-trust-with -nunitpart-tre Umbraco-quadro-testing /

Non ho mai cercato di fare questo, ma in generale, per gestire errori di caricamento di montaggio da AppDomain personalizzate, è possibile utilizzare l'evento AppDomain.AssemblyResolve.

Anche se del tutto estranei, ecco un esempio di utilizzo AppDomain. AssemblyResolve .

La risposta dipende da ciò che il codice fa quando qualcuno con i privilegi di fiducia medio tenta di accedere a una funzione piena fiducia. Presumo sarà gettato una sorta di eccezione.

In questo caso, scrivere uno unit test che viene eseguito in un contesto di fiducia medio, tenta di accedere a una funzione piena fiducia, e si aspetta che la generazione di un'eccezione. Se non hai mai scritto un test come questo, un modo comune per farlo che la maggior parte framework di test sosterranno è questa:

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 l'eccezione e 'colto, significa che l'utente non attendibile non ha ottenuto per accedere alla funzione (e il test viene superato), ma se l'eccezione non viene mai catturato, il test fallisce (ci aspettavamo un'eccezione e non sono mai più ).

Si tratta di pseudo codice java-esque ma questo modello dovrebbe funzionare in qualsiasi lingua si sta utilizzando ammesso che supporta la gestione delle eccezioni.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top