| File: xunit\ConditionAttribute.cs | Web Access |
| Project: src\src\System.Private.ServiceModel\tests\Common\Infrastructure\Infrastructure.Common.csproj (Infrastructure.Common) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Xunit.Abstractions; namespace Infrastructure.Common { // The [Condition] attribute can be applied to any test method that // is marked with [WcfFact] or [WcfTheory]. It provides zero or more // member names to be evaluated at runtime to determine whether the // test should be run or skipped. // Examples: // [Condition(nameof(Root_Certificate_Installed))] // [Condition(nameof(Root_Certificate_Installed), nameof(Client_Certificate_Installed))] [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] public class ConditionAttribute : WcfSkippableAttribute { public string[] Conditions { get; private set; } public ConditionAttribute(params string[] conditions) { Conditions = conditions; } public override string GetSkipReason(ITestMethod testMethod) { // A null or empty list of conditions is treated as "no conditions", // and the test cases will not be skipped. // Example: [Condition()] or [Condition((string[]) null)] int conditionCount = Conditions == null ? 0 : Conditions.Length; if (conditionCount == 0) { return null; } MethodInfo testMethodInfo = testMethod.Method.ToRuntimeMethod(); Type testMethodDeclaringType = testMethodInfo.DeclaringType; List<string> falseConditions = new List<string>(conditionCount); foreach (string entry in Conditions) { string conditionMemberName = entry; // Null condition member names are silently tolerated if (string.IsNullOrWhiteSpace(conditionMemberName)) { continue; } string[] symbols = conditionMemberName.Split('.'); Type declaringType = testMethodDeclaringType; if (symbols.Length == 2) { conditionMemberName = symbols[1]; ITypeInfo type = testMethod.TestClass.Class.Assembly.GetTypes(false).Where(t => t.Name.Contains(symbols[0])).SingleOrDefault(); if (type != null) { declaringType = type.ToRuntimeType(); } } MethodInfo conditionMethodInfo; if ((conditionMethodInfo = LookupConditionalMethod(declaringType, conditionMemberName)) == null) { falseConditions.Add(String.Format("Condition \"{0}\" not found in type \"{1}\".", conditionMemberName, testMethodDeclaringType.FullName)); continue; } // In the case of multiple conditions, collect the results of all // of them to produce a summary skip reason. try { if (!(bool)conditionMethodInfo.Invoke(null, null)) { falseConditions.Add(conditionMemberName); } } catch (Exception exc) { falseConditions.Add(String.Format("Condition \"{0}\" threw exception {1}: \"{2}\".", conditionMemberName, exc.GetType().Name, exc.Message)); } } if (falseConditions.Count == 0) { return null; } return String.Format("{0}", String.Join(", ", falseConditions)); } internal static MethodInfo LookupConditionalMethod(Type t, string name) { if (t == null || name == null) return null; TypeInfo ti = t.GetTypeInfo(); MethodInfo mi = ti.GetDeclaredMethod(name); if (mi != null && mi.IsStatic && mi.GetParameters().Length == 0 && mi.ReturnType == typeof(bool)) return mi; PropertyInfo pi = ti.GetDeclaredProperty(name); if (pi != null && pi.PropertyType == typeof(bool) && pi.GetMethod != null && pi.GetMethod.IsStatic && pi.GetMethod.GetParameters().Length == 0) return pi.GetMethod; return LookupConditionalMethod(ti.BaseType, name); } } }