CommandLineManager.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. using System;
  2. using UnityEditor.TestTools.CodeCoverage.CommandLineParser;
  3. using UnityEditor.TestTools.CodeCoverage.Utils;
  4. namespace UnityEditor.TestTools.CodeCoverage
  5. {
  6. internal class CommandLineManager : CommandLineManagerImplementation
  7. {
  8. private static CommandLineManager s_Instance = null;
  9. public static CommandLineManager instance
  10. {
  11. get
  12. {
  13. if (s_Instance == null)
  14. s_Instance = new CommandLineManager();
  15. return s_Instance;
  16. }
  17. }
  18. protected CommandLineManager() : base(Environment.GetCommandLineArgs())
  19. {
  20. }
  21. }
  22. internal class CommandLineManagerImplementation
  23. {
  24. public bool runFromCommandLine
  25. {
  26. get;
  27. private set;
  28. }
  29. public string coverageResultsPath
  30. {
  31. get;
  32. private set;
  33. }
  34. public string coverageHistoryPath
  35. {
  36. get;
  37. private set;
  38. }
  39. public bool generateAdditionalMetrics
  40. {
  41. get;
  42. private set;
  43. }
  44. public bool generateHTMLReportHistory
  45. {
  46. get;
  47. private set;
  48. }
  49. public bool generateHTMLReport
  50. {
  51. get;
  52. private set;
  53. }
  54. public bool generateBadgeReport
  55. {
  56. get;
  57. private set;
  58. }
  59. public bool assemblyFiltersSpecified
  60. {
  61. get;
  62. private set;
  63. }
  64. public bool pathFiltersSpecified
  65. {
  66. get;
  67. private set;
  68. }
  69. public AssemblyFiltering assemblyFiltering
  70. {
  71. get;
  72. private set;
  73. }
  74. public PathFiltering pathFiltering
  75. {
  76. get;
  77. private set;
  78. }
  79. public bool runTests
  80. {
  81. get;
  82. private set;
  83. }
  84. public bool batchmode
  85. {
  86. get;
  87. private set;
  88. }
  89. public bool burstDisabled
  90. {
  91. get;
  92. private set;
  93. }
  94. private string m_CoverageOptionsArg;
  95. private string[] m_CoverageOptions;
  96. private string m_IncludeAssemblies;
  97. private string m_ExcludeAssemblies;
  98. private string m_IncludePaths;
  99. private string m_ExcludePaths;
  100. public CommandLineManagerImplementation(string[] commandLineArgs)
  101. {
  102. runFromCommandLine = false;
  103. coverageResultsPath = string.Empty;
  104. coverageHistoryPath = string.Empty;
  105. generateAdditionalMetrics = false;
  106. generateHTMLReportHistory = false;
  107. generateHTMLReport = false;
  108. generateBadgeReport = false;
  109. assemblyFiltersSpecified = false;
  110. pathFiltersSpecified = false;
  111. assemblyFiltering = new AssemblyFiltering();
  112. pathFiltering = new PathFiltering();
  113. runTests = false;
  114. batchmode = false;
  115. burstDisabled = false;
  116. m_CoverageOptionsArg = string.Empty;
  117. m_CoverageOptions = new string[] { };
  118. m_IncludeAssemblies = string.Empty;
  119. m_ExcludeAssemblies = string.Empty;
  120. m_IncludePaths = string.Empty;
  121. m_ExcludePaths = string.Empty;
  122. CommandLineOptionSet optionSet = new CommandLineOptionSet(
  123. new CommandLineOption("enableCodeCoverage", () => { runFromCommandLine = true; }),
  124. new CommandLineOption("coverageResultsPath", filePathArg => { SetCoverageResultsPath(filePathArg); }),
  125. new CommandLineOption("coverageHistoryPath", filePathArg => { SetCoverageHistoryPath(filePathArg); }),
  126. new CommandLineOption("coverageOptions", optionsArg => { AddCoverageOptions(optionsArg); }),
  127. new CommandLineOption("runTests", () => { runTests = true; }),
  128. new CommandLineOption("batchmode", () => { batchmode = true; }),
  129. new CommandLineOption("burst-disable-compilation", () => { burstDisabled = true; })
  130. );
  131. optionSet.Parse(commandLineArgs);
  132. ValidateCoverageResultsPath();
  133. ValidateCoverageHistoryPath();
  134. if (runFromCommandLine)
  135. ParseCoverageOptions();
  136. }
  137. private void SetCoverageResultsPath(string filePathArg)
  138. {
  139. if (coverageResultsPath != string.Empty)
  140. {
  141. ResultsLogger.Log(ResultID.Warning_MultipleResultsPaths, coverageResultsPath);
  142. }
  143. else
  144. {
  145. if (filePathArg != null)
  146. {
  147. coverageResultsPath = CoverageUtils.NormaliseFolderSeparators(filePathArg);
  148. }
  149. }
  150. }
  151. private void ValidateCoverageResultsPath()
  152. {
  153. if (!CoverageUtils.EnsureFolderExists(coverageResultsPath))
  154. coverageResultsPath = string.Empty;
  155. }
  156. private void SetCoverageHistoryPath(string filePathArg)
  157. {
  158. if (coverageHistoryPath != string.Empty)
  159. {
  160. ResultsLogger.Log(ResultID.Warning_MultipleHistoryPaths, coverageHistoryPath);
  161. }
  162. else
  163. {
  164. if (filePathArg != null)
  165. {
  166. coverageHistoryPath = CoverageUtils.NormaliseFolderSeparators(filePathArg);
  167. }
  168. }
  169. }
  170. private void ValidateCoverageHistoryPath()
  171. {
  172. if (!CoverageUtils.EnsureFolderExists(coverageHistoryPath))
  173. coverageHistoryPath = string.Empty;
  174. }
  175. private void AddCoverageOptions(string coverageOptionsArg)
  176. {
  177. if (coverageOptionsArg != null)
  178. {
  179. coverageOptionsArg = coverageOptionsArg.Trim('\'');
  180. if (coverageOptionsArg != string.Empty)
  181. {
  182. if (m_CoverageOptionsArg == string.Empty)
  183. {
  184. m_CoverageOptionsArg = coverageOptionsArg;
  185. }
  186. else
  187. {
  188. m_CoverageOptionsArg += ";";
  189. m_CoverageOptionsArg += coverageOptionsArg;
  190. }
  191. }
  192. }
  193. }
  194. private void ParseCoverageOptions()
  195. {
  196. m_CoverageOptions = m_CoverageOptionsArg.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
  197. foreach (string optionArgsStr in m_CoverageOptions)
  198. {
  199. if (optionArgsStr.Length == 0)
  200. continue;
  201. string optionName = optionArgsStr;
  202. string optionArgs = string.Empty;
  203. int indexOfColon = optionArgsStr.IndexOf(':');
  204. if (indexOfColon > 0)
  205. {
  206. optionName = optionArgsStr.Substring(0, indexOfColon);
  207. optionArgs = optionArgsStr.Substring(indexOfColon+1);
  208. }
  209. switch (optionName.ToUpperInvariant())
  210. {
  211. case "GENERATEADDITIONALMETRICS":
  212. generateAdditionalMetrics = true;
  213. break;
  214. case "GENERATEHTMLREPORTHISTORY":
  215. generateHTMLReportHistory = true;
  216. break;
  217. case "GENERATEHTMLREPORT":
  218. generateHTMLReport = true;
  219. break;
  220. case "GENERATEBADGEREPORT":
  221. generateBadgeReport = true;
  222. break;
  223. case "VERBOSITY":
  224. if (optionArgs.Length > 0)
  225. {
  226. switch (optionArgs.ToUpperInvariant())
  227. {
  228. case "VERBOSE":
  229. ResultsLogger.VerbosityLevel = LogVerbosityLevel.Verbose;
  230. break;
  231. case "INFO":
  232. ResultsLogger.VerbosityLevel = LogVerbosityLevel.Info;
  233. break;
  234. case "WARNING":
  235. ResultsLogger.VerbosityLevel = LogVerbosityLevel.Warning;
  236. break;
  237. case "ERROR":
  238. ResultsLogger.VerbosityLevel = LogVerbosityLevel.Error;
  239. break;
  240. case "OFF":
  241. ResultsLogger.VerbosityLevel = LogVerbosityLevel.Off;
  242. break;
  243. }
  244. }
  245. break;
  246. case "ASSEMBLYFILTERS":
  247. if (optionArgs.Length > 0)
  248. {
  249. assemblyFiltersSpecified = true;
  250. string[] assemblyFilters = optionArgs.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
  251. for (int i = 0; i < assemblyFilters.Length; ++i)
  252. {
  253. string filter = assemblyFilters[i];
  254. string filterBody = filter.Length > 1 ? filter.Substring(1) : string.Empty;
  255. if (filter.StartsWith("+", StringComparison.OrdinalIgnoreCase))
  256. {
  257. if (m_IncludeAssemblies.Length > 0)
  258. m_IncludeAssemblies += ",";
  259. if (filterBody.StartsWith("<", StringComparison.OrdinalIgnoreCase))
  260. {
  261. if (string.Equals(filterBody, AssemblyFiltering.kUserAlias, StringComparison.OrdinalIgnoreCase))
  262. m_IncludeAssemblies += AssemblyFiltering.GetUserOnlyAssembliesString();
  263. else if (string.Equals(filterBody, AssemblyFiltering.kProjectAlias, StringComparison.OrdinalIgnoreCase))
  264. m_IncludeAssemblies += AssemblyFiltering.GetAllProjectAssembliesString();
  265. else if (string.Equals(filterBody, AssemblyFiltering.kPackagesAlias, StringComparison.OrdinalIgnoreCase))
  266. m_IncludeAssemblies += AssemblyFiltering.GetPackagesOnlyAssembliesString();
  267. else if (string.Equals(filterBody, AssemblyFiltering.kAllAlias, StringComparison.OrdinalIgnoreCase))
  268. m_IncludeAssemblies += "*";
  269. }
  270. else
  271. {
  272. m_IncludeAssemblies += filterBody;
  273. }
  274. }
  275. else if (filter.StartsWith("-", StringComparison.OrdinalIgnoreCase))
  276. {
  277. if (m_ExcludeAssemblies.Length > 0)
  278. m_ExcludeAssemblies += ",";
  279. if (filterBody.StartsWith("<", StringComparison.OrdinalIgnoreCase))
  280. {
  281. if (string.Equals(filterBody, AssemblyFiltering.kUserAlias, StringComparison.OrdinalIgnoreCase))
  282. m_ExcludeAssemblies += AssemblyFiltering.GetUserOnlyAssembliesString();
  283. else if (string.Equals(filterBody, AssemblyFiltering.kProjectAlias, StringComparison.OrdinalIgnoreCase))
  284. m_ExcludeAssemblies += AssemblyFiltering.GetAllProjectAssembliesString();
  285. else if (string.Equals(filterBody, AssemblyFiltering.kPackagesAlias, StringComparison.OrdinalIgnoreCase))
  286. m_ExcludeAssemblies += AssemblyFiltering.GetPackagesOnlyAssembliesString();
  287. else if (string.Equals(filterBody, AssemblyFiltering.kAllAlias, StringComparison.OrdinalIgnoreCase))
  288. m_ExcludeAssemblies += "*";
  289. }
  290. else
  291. {
  292. m_ExcludeAssemblies += filterBody;
  293. }
  294. }
  295. else
  296. {
  297. ResultsLogger.Log(ResultID.Warning_AssemblyFiltersNotPrefixed, filter);
  298. }
  299. }
  300. }
  301. break;
  302. case "PATHFILTERS":
  303. if (optionArgs.Length > 0)
  304. {
  305. pathFiltersSpecified = true;
  306. string[] pathFilters = optionArgs.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
  307. for (int i = 0; i < pathFilters.Length; ++i)
  308. {
  309. string filter = pathFilters[i];
  310. string filterBody = filter.Length > 1 ? filter.Substring(1) : string.Empty;
  311. if (filter.StartsWith("+", StringComparison.OrdinalIgnoreCase))
  312. {
  313. if (m_IncludePaths.Length > 0)
  314. m_IncludePaths += ",";
  315. m_IncludePaths += filterBody;
  316. }
  317. else if (filter.StartsWith("-", StringComparison.OrdinalIgnoreCase))
  318. {
  319. if (m_ExcludePaths.Length > 0)
  320. m_ExcludePaths += ",";
  321. m_ExcludePaths += filterBody;
  322. }
  323. else
  324. {
  325. ResultsLogger.Log(ResultID.Warning_PathFiltersNotPrefixed, filter);
  326. }
  327. }
  328. }
  329. break;
  330. }
  331. }
  332. if (m_IncludeAssemblies.Length == 0)
  333. {
  334. // If there are no inlcudedAssemblies specified but there are includedPaths specified
  335. // then include all project assemblies so path filtering can take precedence over assembly filtering,
  336. // othewise if there are no includedPaths specified neither then inlcude just the user assemblies (found under the Assets folder)
  337. if (m_IncludePaths.Length > 0)
  338. m_IncludeAssemblies = AssemblyFiltering.GetAllProjectAssembliesString();
  339. else
  340. m_IncludeAssemblies = AssemblyFiltering.GetUserOnlyAssembliesString();
  341. }
  342. if (m_ExcludeAssemblies.Length > 0)
  343. m_ExcludeAssemblies += ",";
  344. m_ExcludeAssemblies += AssemblyFiltering.kDefaultExcludedAssemblies;
  345. assemblyFiltering.Parse(m_IncludeAssemblies, m_ExcludeAssemblies);
  346. pathFiltering.Parse(m_IncludePaths, m_ExcludePaths);
  347. }
  348. }
  349. }