| File: xunit\IssueAttribute.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 Xunit.Abstractions; namespace Infrastructure.Common { // The [Issue] attribute can be applied to any test method that // is marked with [WcfFact] or [WcfTheory]. It indicates the open // issue number and optionally the framework(s), or // OS(s) to which it applies. // Examples: // [Issue(999)] // means this issue applies to all OSes, all Frameworks // [Issue(999, Framework=FrameworkID.NetNative)] // means this issue only applies to NET Native // [Issue(999, OS=OSID.Ubuntu_14_04)] // means this issue only applies to Ubuntu 14.04 [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] public class IssueAttribute : WcfSkippableAttribute { private static HashSet<int> s_includeIssuesHash = DetectIssuesToInclude(); public int Issue { get; private set; } public FrameworkID Framework {get; set; } public OSID OS { get; set; } // Short name to repository where the issue exists. // It is not required to be a URL, and it won't be used to create a URL. public string Repository { get; set; } public IssueAttribute(int issue) { Issue = issue; Repository = "dotnet/wcf"; // Default framework and OS to "none" so that they must // be explicitly specified to be more specific. Framework = FrameworkID.None; OS = OSID.None; } public override string GetSkipReason(ITestMethod testMethod) { // If we are deliberately including this issue in the test run, // return "don't skip" response unconditionally. if (ShouldIncludeThisIssue(Issue)) { return null; } string repositoryAndIssue = String.Format("{0} #{1}", Repository, Issue); if (Framework.MatchesCurrent()) { // Don't skip if we are running tests with issues. // But match the Framework first so we don't run tests return String.Format("{0} on framework \"{1}\" (filter is \"{2}\")", repositoryAndIssue, FrameworkHelper.Current.Name(), Framework.Name()); } if (OS.MatchesCurrent()) { return String.Format("{0} on OS \"{1}\" (filter is \"{2}\")", repositoryAndIssue, OSHelper.Current.Name(), OS.Name()); } // If no specific OS or Framework filters, it applies to all. if (OS == OSID.None && Framework == FrameworkID.None) { return String.Format("{0}", repositoryAndIssue); } // Null means "don't skip" return null; } // Returns a HashSet<int> containing all the test issue numbers to include // during a test run (where "include" means "don't skip"). The meaning of // this HashSet is: // null: [default] don't include any tests with [Issue] (i.e. skip them all) // count == 0: Include all tests with [Issue] (i.e. don't skip any) // count > 0: Include only those tests with an issue in the HashSet private static HashSet<int> DetectIssuesToInclude() { string includeTestsWithIssues = TestProperties.GetProperty(TestProperties.IncludeTestsWithIssues_PropertyName); // Empty string means don't include any tests with issues. // In other words, all tests with [Issue] will be skipped. if (String.IsNullOrEmpty(includeTestsWithIssues)) { return null; } // The special value 'true' means include all tests with [Issue]. // The special value 'false' means skip all tests with [Issue]. bool propertyAsBool = false; if (bool.TryParse(includeTestsWithIssues, out propertyAsBool)) { return propertyAsBool ? new HashSet<int>() : null; } // Anything else is interpreted as a semicolon or comma separated list of // issue numbers to include (i.e. not skip). string[] issues = includeTestsWithIssues.Split(new char[] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries); HashSet<int> hashSet = new HashSet<int>(); foreach (string issue in issues) { int issueAsInt = 0; if (!int.TryParse(issue, out issueAsInt)) { Console.WriteLine(String.Format("Warning: The number '{0}' in IncludeTestsWithIssues is not a valid integer and will be ignored.", issue)); continue; } hashSet.Add(issueAsInt); } return hashSet; } // Returns 'true' if a test marked with the given issue should be included // (i.e. not skipped) private static bool ShouldIncludeThisIssue(int issue) { // A null HashSet (default) means no test with [Issue] is included, // meaning all of them should be skipped if (s_includeIssuesHash == null) { return false; } // An empty HashSet<> means "include all" if (s_includeIssuesHash.Count == 0) { return true; } // A non-empty HashSet contains issue numbers to include return s_includeIssuesHash.Contains(issue); } } }