UITestRunnerFilter.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text.RegularExpressions;
  6. namespace UnityEditor.TestTools.TestRunner.GUI
  7. {
  8. [Serializable]
  9. internal class UITestRunnerFilter
  10. {
  11. #pragma warning disable 649
  12. public string[] assemblyNames;
  13. public string[] groupNames;
  14. public string[] categoryNames;
  15. public string[] testNames;
  16. public int testRepetitions = 1;
  17. public bool synchronousOnly = false;
  18. public static string AssemblyNameFromPath(string path)
  19. {
  20. string output = Path.GetFileName(path);
  21. if (output != null && output.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
  22. return output.Substring(0, output.Length - 4);
  23. return output;
  24. }
  25. private bool CategoryMatches(IEnumerable<string> categories)
  26. {
  27. if (categoryNames == null || categoryNames.Length == 0)
  28. return true;
  29. foreach (string category in categories)
  30. {
  31. if (categoryNames.Contains(category))
  32. return true;
  33. }
  34. return false;
  35. }
  36. private bool IDMatchesAssembly(string id)
  37. {
  38. if (AreOptionalFiltersEmpty())
  39. return true;
  40. if (assemblyNames == null || assemblyNames.Length == 0)
  41. return true;
  42. int openingBracket = id.IndexOf('[');
  43. int closingBracket = id.IndexOf(']');
  44. if (openingBracket >= 0 && openingBracket < id.Length && closingBracket > openingBracket &&
  45. openingBracket < id.Length)
  46. {
  47. //Some assemblies are absolute and explicitly part of the test ID e.g.
  48. //"[/path/to/assembly-name.dll][rest of ID ...]"
  49. //While some are minimal assembly names e.g.
  50. //"[assembly-name][rest of ID ...]"
  51. //Strip them down to just the assembly name
  52. string assemblyNameFromID =
  53. AssemblyNameFromPath(id.Substring(openingBracket + 1, closingBracket - openingBracket - 1));
  54. foreach (string assemblyName in assemblyNames)
  55. {
  56. if (assemblyName.Equals(assemblyNameFromID, StringComparison.OrdinalIgnoreCase))
  57. return true;
  58. }
  59. }
  60. return false;
  61. }
  62. private bool NameMatches(string name)
  63. {
  64. if (AreOptionalFiltersEmpty())
  65. return true;
  66. if (groupNames == null || groupNames.Length == 0)
  67. return true;
  68. foreach (var nameFromFilter in groupNames)
  69. {
  70. //Strict regex match for test group name on its own
  71. if (Regex.IsMatch(name, nameFromFilter))
  72. return true;
  73. //Match test names that end with parametrized test values and full nunit generated test names that have . separators
  74. var regex = nameFromFilter.TrimEnd('$') + @"[\.|\(.*\)]";
  75. if (Regex.IsMatch(name, regex))
  76. return true;
  77. }
  78. return false;
  79. }
  80. private bool AreOptionalFiltersEmpty()
  81. {
  82. if (assemblyNames != null && assemblyNames.Length != 0)
  83. return false;
  84. if (groupNames != null && groupNames.Length != 0)
  85. return false;
  86. if (testNames != null && testNames.Length != 0)
  87. return false;
  88. return true;
  89. }
  90. private bool NameMatchesExactly(string name)
  91. {
  92. if (AreOptionalFiltersEmpty())
  93. return true;
  94. if (testNames == null || testNames.Length == 0)
  95. return true;
  96. foreach (var exactName in testNames)
  97. {
  98. if (name == exactName)
  99. return true;
  100. }
  101. return false;
  102. }
  103. private static void ClearAncestors(IEnumerable<IClearableResult> newResultList, string parentID)
  104. {
  105. if (string.IsNullOrEmpty(parentID))
  106. return;
  107. foreach (var result in newResultList)
  108. {
  109. if (result.Id == parentID)
  110. {
  111. result.Clear();
  112. ClearAncestors(newResultList, result.ParentId);
  113. break;
  114. }
  115. }
  116. }
  117. public void ClearResults(List<IClearableResult> newResultList)
  118. {
  119. foreach (var result in newResultList)
  120. {
  121. if (!result.IsSuite && CategoryMatches(result.Categories))
  122. {
  123. if (IDMatchesAssembly(result.Id) && NameMatches(result.FullName) &&
  124. NameMatchesExactly(result.FullName))
  125. {
  126. result.Clear();
  127. ClearAncestors(newResultList, result.ParentId);
  128. }
  129. }
  130. }
  131. }
  132. internal interface IClearableResult
  133. {
  134. string Id { get; }
  135. string FullName { get; }
  136. string ParentId { get; }
  137. bool IsSuite { get; }
  138. List<string> Categories { get; }
  139. void Clear();
  140. }
  141. }
  142. }