代码之家  ›  专栏  ›  技术社区  ›  Ian Davis

如何自动化中等信任代码的测试

  •  13
  • Ian Davis  · 技术社区  · 17 年前

    我想编写自动测试,这些测试在中等信任度下运行,如果需要完全信任,则会失败。

    我正在编写一个库,其中一些功能仅在完全信任场景中可用,我想验证我希望在中等信任环境下运行的代码是否可以正常工作。如果我还想知道,如果我更改了一个需要完全信任的类,我的测试将失败。

    我已尝试创建另一个AppDomain并加载medium trust PolicyLevel,但在尝试运行跨AppDomain回调时,我始终遇到程序集错误或无法加载其依赖项。

    有办法做到这一点吗?

    使现代化

    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 );
            }
        }
    }
    5 回复  |  直到 11 年前
        1
  •  7
  •   Nathan Howell    14 年前

    无耻地从 How to Host a Partial Trust Sandbox – #7 ,但在F中重新实现(以及一个简单的测试用例),只是为了好玩:-)

    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
    

    和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
    
        2
  •  2
  •   bricelam    13 年前

    我刚刚发表了一篇题为 Partial Trust Testing with xUnit.net

    下面是它的用法示例。

    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
        }
    }
    
        3
  •  1
  •   Alex Norcliffe    14 年前

    我已经在Medium Trust上发布了一篇关于单元测试的三部分博客文章

    我以与这里的一些答案类似的方式构建了一个替代的AppDomain,但更进一步,使用MarshalByRefObject调用另一个AppDomain中的测试方法,这意味着您的测试类不需要实现MarshalByRefObject

    第三部分(包含到其他部分的链接)在这里 http://boxbinary.com/2011/10/how-to-run-a-unit-test-in-medium-trust-with-nunitpart-three-umbraco-framework-testing/

        4
  •  0
  •   Mark Seemann    17 年前

    我从未尝试过这样做,但一般来说,要处理来自自定义AppDomain的程序集加载失败,可以使用AppDomain.AssemblyResolve事件。

    虽然完全无关,但这里有 an example of using AppDomain.AssemblyResolve .

        5
  •  0
  •   Justin Standard    16 年前

    在这种情况下,编写一个在中等信任上下文中运行的单元测试,尝试访问完全信任特性,并期望抛出异常。如果您从未编写过这样的测试,那么大多数测试框架都支持的一种常见方法是:

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

    如果捕获到异常,则表示不受信任的用户无法访问该功能(并且测试通过),但如果从未捕获到异常,则测试将失败(我们预期会出现异常,但没有得到)。