diff --git a/AppInspector.CLI/AppInspector.CLI.csproj b/AppInspector.CLI/AppInspector.CLI.csproj index 5ab49697..03f4c8b8 100644 --- a/AppInspector.CLI/AppInspector.CLI.csproj +++ b/AppInspector.CLI/AppInspector.CLI.csproj @@ -66,7 +66,7 @@ - + diff --git a/AppInspector.CLI/CLICmdOptions.cs b/AppInspector.CLI/CLICmdOptions.cs index 845bff87..0773a964 100644 --- a/AppInspector.CLI/CLICmdOptions.cs +++ b/AppInspector.CLI/CLICmdOptions.cs @@ -3,6 +3,7 @@ using CommandLine; using Microsoft.ApplicationInspector.Commands; +using System.Collections.Generic; namespace Microsoft.ApplicationInspector.CLI { @@ -19,51 +20,14 @@ public class CLICommandOptions : CommandOptions public string OutputFileFormat { get; set; } = "text"; } - /// - /// CLI command distinct arguments - /// - [Verb("get-tags", HelpText = "Inspect source directory/file/compressed file (.tgz|zip) against defined characteristics for unique tags")] - public class CLIGetTagsCommandOptions : CLICommandOptions - { - [Option('s', "source-path", Required = true, HelpText = "Source file or directory to inspect")] - public string? SourcePath { get; set; } - - [Option('r', "custom-rules-path", Required = false, HelpText = "Custom rules file or directory path")] - public string? CustomRulesPath { get; set; } - - [Option('i', "ignore-default-rules", Required = false, HelpText = "Exclude default rules bundled with application", Default = false)] - public bool IgnoreDefaultRules { get; set; } - - [Option('c', "confidence-filters", Required = false, HelpText = "Output only matches with specified confidence , [high|medium|low]", Default = "high,medium")] - public string ConfidenceFilters { get; set; } = "high,medium"; - - [Option('k', "file-path-exclusions", Required = false, HelpText = "Exclude source files (none|default: sample,example,test,docs,lib,.vs,.git)", Default = "sample,example,test,docs,lib,.vs,.git")] - public string FilePathExclusions { get; set; } = "sample,example,test,docs,.vs,.git"; - - [Option("file-timeout", Required = false, HelpText = "If set, maximum amount of time in milliseconds to allow for processing each file.", Default = 0)] - public int FileTimeOut { get; set; } = 0; - - [Option("processing-timeout", Required = false, HelpText = "If set, maximum amount of time in milliseconds to allow for processing overall.", Default = 0)] - public int ProcessingTimeOut { get; set; } = 0; - - [Option("single-threaded", Required = false, HelpText = "Disables parallel processing.")] - public bool SingleThread { get; set; } - - [Option("no-show-progress", Required = false, HelpText = "Disable progress information.")] - public bool NoShowProgressBar { get; set; } - - [Option("scan-unknown-filetypes", Required = false, HelpText = "Scan files of unknown types.")] - public bool ScanUnknownTypes { get; set; } - } - /// /// CLI command distinct arguments /// [Verb("analyze", HelpText = "Inspect source directory/file/compressed file (.tgz|zip) against defined characteristics")] public class CLIAnalyzeCmdOptions : CLICommandOptions { - [Option('s', "source-path", Required = true, HelpText = "Source file or directory to inspect")] - public string? SourcePath { get; set; } + [Option('s', "source-path", Required = true, HelpText = "Source file or directory to inspect, comma separated", Separator = ',')] + public IEnumerable SourcePath { get; set; } = new string[0]; [Option('r', "custom-rules-path", Required = false, HelpText = "Custom rules file or directory path")] public string? CustomRulesPath { get; set; } @@ -74,8 +38,9 @@ public class CLIAnalyzeCmdOptions : CLICommandOptions [Option('c', "confidence-filters", Required = false, HelpText = "Output only matches with specified confidence , [high|medium|low]", Default = "high,medium")] public string ConfidenceFilters { get; set; } = "high,medium"; - [Option('k', "file-path-exclusions", Required = false, HelpText = "Exclude source files (none|default: sample,example,test,docs,lib,.vs,.git)", Default = "sample,example,test,docs,lib,.vs,.git")] - public string FilePathExclusions { get; set; } = "sample,example,test,docs,.vs,.git"; + [Option('k', "file-path-exclusions", Required = false, HelpText = "Exclude source files that match glob patterns. Example: \".git,**Tests**\". Use \"none\" to disable.", Default = "*/bin,*/obj,*/.vs,*/.git", Separator = ',')] + + public IEnumerable FilePathExclusions { get; set; } = new string[] { }; [Option('f', "output-file-format", Required = false, HelpText = "Output format [html|json|text]", Default = "html")] public new string OutputFileFormat { get; set; } = "html"; @@ -83,8 +48,8 @@ public class CLIAnalyzeCmdOptions : CLICommandOptions [Option('e', "text-format", Required = false, HelpText = "Match text format specifiers", Default = "Tag:%T,Rule:%N,Ruleid:%R,Confidence:%X,File:%F,Sourcetype:%t,Line:%L,Sample:%m")] public string TextOutputFormat { get; set; } = "Tag:%T,Rule:%N,Ruleid:%R,Confidence:%X,File:%F,Sourcetype:%t,Line:%L,Sample:%m"; - [Option("file-timeout", Required = false, HelpText = "If set, maximum amount of time in milliseconds to allow for processing each file.", Default = 0)] - public int FileTimeOut { get; set; } = 0; + [Option("file-timeout", Required = false, HelpText = "If set, maximum amount of time in milliseconds to allow for processing each file.", Default = 60000)] + public int FileTimeOut { get; set; } = 60000; [Option("processing-timeout", Required = false, HelpText = "If set, maximum amount of time in milliseconds to allow for processing overall.", Default = 0)] public int ProcessingTimeOut { get; set; } = 0; @@ -100,44 +65,37 @@ public class CLIAnalyzeCmdOptions : CLICommandOptions [Option("scan-unknown-filetypes", Required = false, HelpText = "Scan files of unknown types.")] public bool ScanUnknownTypes { get; set; } + + [Option('t',"tags-only", Required = false, HelpText = "Only get tags (no detailed match data).")] + public bool TagsOnly { get; set; } } [Verb("tagdiff", HelpText = "Compares unique tag values between two source paths")] public class CLITagDiffCmdOptions : CLICommandOptions { - [Option("src1", Required = true, HelpText = "Source 1 to compare")] - public string? SourcePath1 { get; set; } + [Option("src1", Required = true, HelpText = "Source 1 to compare (commaa separated)")] + public IEnumerable SourcePath1 { get; set; } = System.Array.Empty(); - [Option("src2", Required = true, HelpText = "Source 2 to compare")] - public string? SourcePath2 { get; set; } + [Option("src2", Required = true, HelpText = "Source 2 to compare (commaa separated)")] + public IEnumerable SourcePath2 { get; set; } = System.Array.Empty(); [Option('t', "test-type", Required = false, HelpText = "Type of test to run [equality|inequality]", Default = "equality")] public string TestType { get; set; } = "equality"; - [Option('k', "file-path-exclusions", Required = false, HelpText = "Exclude source files (none|default: sample,example,test,docs,.vs,.git)", Default = "sample,example,test,docs,.vs,.git")] - public string FilePathExclusions { get; set; } = "sample,example,test,docs,.vs,.git"; + [Option('k', "file-path-exclusions", Required = false, HelpText = "Exclude source files that match glob patterns. Example: \".git,**Tests**\". Use \"none\" to disable.", Default = "*/bin,*/obj,*/.vs,*/.git", Separator = ',')] + public IEnumerable FilePathExclusions { get; set; } = new string[] { }; [Option('r', "custom-rules-path", Required = false, HelpText = "Custom rules file or directory path")] public string? CustomRulesPath { get; set; } [Option('i', "ignore-default-rules", Required = false, HelpText = "Exclude default rules bundled with application", Default = false)] public bool IgnoreDefaultRules { get; set; } - } - [Verb("tagtest", HelpText = "Test (T/F) for presence of custom rule set in source")] - public class CLITagTestCmdOptions : CLICommandOptions - { - [Option('s', "source-path", Required = true, HelpText = "Source file or directory to inspect")] - public string? SourcePath { get; set; } + [Option("file-timeout", Required = false, HelpText = "If set, maximum amount of time in milliseconds to allow for processing each file.", Default = 60000)] + public int FileTimeOut { get; set; } = 60000; - [Option('t', "test-type", Required = false, HelpText = "Test to perform [rulespresent|rulesnotpresent] ", Default = "rulespresent")] - public string TestType { get; set; } = "rulespresent"; - - [Option('r', "custom-rules-path", Required = false, HelpText = "Custom rules file or directory path")] - public string? CustomRulesPath { get; set; } - - [Option('k', "file-path-exclusions", Required = false, HelpText = "Exclude source files (none|default: sample,example,test,docs,.vs,.git)", Default = "sample,example,test,docs,.vs,.git")] - public string FilePathExclusions { get; set; } = "sample,example,test,docs,.vs,.git"; + [Option("processing-timeout", Required = false, HelpText = "If set, maximum amount of time in milliseconds to allow for processing overall.", Default = 0)] + public int ProcessingTimeOut { get; set; } = 0; } [Verb("exporttags", HelpText = "Export unique rule tags to view what code features may be detected")] diff --git a/AppInspector.CLI/Program.cs b/AppInspector.CLI/Program.cs index 3b882881..a5d815d2 100644 --- a/AppInspector.CLI/Program.cs +++ b/AppInspector.CLI/Program.cs @@ -6,6 +6,7 @@ using NLog; using ShellProgressBar; using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; @@ -13,7 +14,7 @@ namespace Microsoft.ApplicationInspector.CLI { - public class Program + public static class Program { /// /// CLI program entry point which defines command verbs and options to running @@ -30,19 +31,15 @@ public static int Main(string[] args) { var argsResult = Parser.Default.ParseArguments(args) + CLIPackRulesCmdOptions>(args) .MapResult( (CLIAnalyzeCmdOptions cliOptions) => VerifyOutputArgsRun(cliOptions), (CLITagDiffCmdOptions cliOptions) => VerifyOutputArgsRun(cliOptions), - (CLITagTestCmdOptions cliOptions) => VerifyOutputArgsRun(cliOptions), (CLIExportTagsCmdOptions cliOptions) => VerifyOutputArgsRun(cliOptions), (CLIVerifyRulesCmdOptions cliOptions) => VerifyOutputArgsRun(cliOptions), (CLIPackRulesCmdOptions cliOptions) => VerifyOutputArgsRun(cliOptions), - (CLIGetTagsCommandOptions cliOptions) => VerifyOutputArgsRun(cliOptions), errs => 2 ); @@ -99,17 +96,6 @@ private static int VerifyOutputArgsRun(CLITagDiffCmdOptions options) CommonOutputChecks(options); return RunTagDiffCommand(options); } - - private static int VerifyOutputArgsRun(CLITagTestCmdOptions options) - { - Logger logger = Utils.SetupLogging(options, true); - WriteOnce.Log = logger; - options.Log = logger; - - CommonOutputChecks(options); - return RunTagTestCommand(options); - } - private static int VerifyOutputArgsRun(CLIExportTagsCmdOptions options) { Logger logger = Utils.SetupLogging(options, true); @@ -155,16 +141,6 @@ private static int VerifyOutputArgsRun(CLIPackRulesCmdOptions options) return RunPackRulesCommand(options); } - private static int VerifyOutputArgsRun(CLIGetTagsCommandOptions options) - { - Logger logger = Utils.SetupLogging(options, true); - WriteOnce.Log = logger; - options.Log = logger; - - CommonOutputChecks(options); - return RunGetTagsCommand(options); - } - private static int VerifyOutputArgsRun(CLIAnalyzeCmdOptions options) { Logger logger = Utils.SetupLogging(options, true); @@ -229,12 +205,12 @@ private static void CommonOutputChecks(CLICommandOptions options) //validate output is not empty if no file output specified if (string.IsNullOrEmpty(options.OutputFilePath)) { - if (options.ConsoleVerbosityLevel.ToLower() == "none") + if (string.Equals(options.ConsoleVerbosityLevel, "none", StringComparison.OrdinalIgnoreCase)) { WriteOnce.Error(MsgHelp.GetString(MsgHelp.ID.CMD_NO_OUTPUT)); throw new Exception(MsgHelp.GetString(MsgHelp.ID.CMD_NO_OUTPUT)); } - else if (options.ConsoleVerbosityLevel.ToLower() == "low") + else if (string.Equals(options.ConsoleVerbosityLevel, "low", StringComparison.OrdinalIgnoreCase)) { WriteOnce.SafeLog("Verbosity set low. Detailed output limited.", NLog.LogLevel.Info); } @@ -266,77 +242,11 @@ private static void ValidFileWritePath(string filePath) #region RunCmdsWriteResults - private static int RunGetTagsCommand(CLIGetTagsCommandOptions cliOptions) - { - GetTagsCommand command = new GetTagsCommand(new GetTagsCommandOptions() - { - SourcePath = cliOptions.SourcePath ?? "", - CustomRulesPath = cliOptions.CustomRulesPath ?? "", - IgnoreDefaultRules = cliOptions.IgnoreDefaultRules, - ConfidenceFilters = cliOptions.ConfidenceFilters, - FilePathExclusions = cliOptions.FilePathExclusions, - ConsoleVerbosityLevel = cliOptions.ConsoleVerbosityLevel, - Log = cliOptions.Log, - SingleThread = cliOptions.SingleThread, - NoShowProgress = cliOptions.NoShowProgressBar, - FileTimeOut = cliOptions.FileTimeOut, - ProcessingTimeOut = cliOptions.ProcessingTimeOut, - ScanUnknownTypes = cliOptions.ScanUnknownTypes - }); - - - if (!cliOptions.NoShowProgressBar) - { - WriteOnce.PauseConsoleOutput = true; - } - - GetTagsResult getTagsResult = command.GetResult(); - - if (cliOptions.NoShowProgressBar) - { - ResultsWriter.Write(getTagsResult, cliOptions); - } - else - { - var done = false; - - _ = Task.Factory.StartNew(() => - { - ResultsWriter.Write(getTagsResult, cliOptions); - done = true; - }); - - var options = new ProgressBarOptions - { - ForegroundColor = ConsoleColor.Yellow, - ForegroundColorDone = ConsoleColor.DarkGreen, - BackgroundColor = ConsoleColor.DarkGray, - BackgroundCharacter = '\u2593', - DisableBottomPercentage = true - }; - - using (var pbar = new IndeterminateProgressBar("Writing Result Files.", options)) - { - while (!done) - { - Thread.Sleep(10); - } - pbar.Message = $"Results written."; - - pbar.Finished(); - } - } - - WriteOnce.PauseConsoleOutput = false; - - return (int)getTagsResult.ResultCode; - } - private static int RunAnalyzeCommand(CLIAnalyzeCmdOptions cliOptions) { AnalyzeCommand command = new AnalyzeCommand(new AnalyzeOptions() { - SourcePath = cliOptions.SourcePath ?? "", + SourcePath = cliOptions.SourcePath ?? Array.Empty(), CustomRulesPath = cliOptions.CustomRulesPath ?? "", IgnoreDefaultRules = cliOptions.IgnoreDefaultRules, ConfidenceFilters = cliOptions.ConfidenceFilters, @@ -348,7 +258,8 @@ private static int RunAnalyzeCommand(CLIAnalyzeCmdOptions cliOptions) FileTimeOut = cliOptions.FileTimeOut, ProcessingTimeOut = cliOptions.ProcessingTimeOut, ContextLines = cliOptions.ContextLines, - ScanUnknownTypes = cliOptions.ScanUnknownTypes + ScanUnknownTypes = cliOptions.ScanUnknownTypes, + TagsOnly = cliOptions.TagsOnly }); if (!cliOptions.NoShowProgressBar) @@ -385,12 +296,13 @@ private static int RunAnalyzeCommand(CLIAnalyzeCmdOptions cliOptions) { while (!done) { - Thread.Sleep(10); + Thread.Sleep(100); } - pbar.Message = $"Results written."; + pbar.Message = "Results written."; pbar.Finished(); } + Console.Write(Environment.NewLine); } WriteOnce.PauseConsoleOutput = false; @@ -402,8 +314,8 @@ private static int RunTagDiffCommand(CLITagDiffCmdOptions cliOptions) { TagDiffCommand command = new TagDiffCommand(new TagDiffOptions() { - SourcePath1 = cliOptions.SourcePath1 ?? "", - SourcePath2 = cliOptions.SourcePath2 ?? "", + SourcePath1 = cliOptions.SourcePath1, + SourcePath2 = cliOptions.SourcePath2, CustomRulesPath = cliOptions.CustomRulesPath, IgnoreDefaultRules = cliOptions.IgnoreDefaultRules, FilePathExclusions = cliOptions.FilePathExclusions, @@ -417,25 +329,7 @@ private static int RunTagDiffCommand(CLITagDiffCmdOptions cliOptions) return (int)tagDiffResult.ResultCode; } - - private static int RunTagTestCommand(CLITagTestCmdOptions cliOptions) - { - TagTestCommand command = new TagTestCommand(new TagTestOptions() - { - SourcePath = cliOptions.SourcePath, - CustomRulesPath = cliOptions.CustomRulesPath, - FilePathExclusions = cliOptions.FilePathExclusions, - TestType = cliOptions.TestType, - ConsoleVerbosityLevel = cliOptions.ConsoleVerbosityLevel, - Log = cliOptions.Log - }); - - TagTestResult tagTestCommand = command.GetResult(); - ResultsWriter.Write(tagTestCommand, cliOptions); - - return (int)tagTestCommand.ResultCode; - } - + private static int RunExportTagsCommand(CLIExportTagsCmdOptions cliOptions) { ExportTagsCommand command = new ExportTagsCommand(new ExportTagsOptions() diff --git a/AppInspector.CLI/ResultsWriter.cs b/AppInspector.CLI/ResultsWriter.cs index b6365e03..3d70e484 100644 --- a/AppInspector.CLI/ResultsWriter.cs +++ b/AppInspector.CLI/ResultsWriter.cs @@ -19,11 +19,7 @@ public static void Write(Result result, CLICommandOptions options) string commandCompletedMsg; //perform type checking and assign final msg string - if (result is TagTestResult) - { - commandCompletedMsg = "Tag Test"; - } - else if (result is TagDiffResult) + if (result is TagDiffResult) { commandCompletedMsg = "Tag Diff"; } @@ -67,10 +63,6 @@ public static void Write(Result result, CLICommandOptions options) return; } } - else if (result is GetTagsResult gtr && options is CLIGetTagsCommandOptions gtco) - { - commandCompletedMsg = "Get Tags"; - } else { throw new Exception("Unrecognized object types for write results"); diff --git a/AppInspector.CLI/Writers/GetTagsTextWriter.cs b/AppInspector.CLI/Writers/GetTagsTextWriter.cs deleted file mode 100644 index 06b20248..00000000 --- a/AppInspector.CLI/Writers/GetTagsTextWriter.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (C) Microsoft. All rights reserved. -// Licensed under the MIT License. See LICENSE.txt in the project root for license information. - -using Microsoft.ApplicationInspector.Commands; -using System.Collections.Generic; - -namespace Microsoft.ApplicationInspector.CLI -{ - public class GetTagsTextWriter : CommandResultsWriter - { - public override void WriteResults(Result result, CLICommandOptions commandOptions, bool autoClose = true) - { - GetTagsResult getTagsResult = (GetTagsResult)result; - CLIGetTagsCommandOptions cliGetTagsCommandOptions = (CLIGetTagsCommandOptions)commandOptions; - - //For console output, update write once for same results to console or file - WriteOnce.TextWriter = TextWriter; - - foreach (var tag in getTagsResult.Metadata.UniqueTags ?? new List()) - { - WriteOnce.Result(tag); - } - - if (autoClose) - { - FlushAndClose(); - } - } - } -} \ No newline at end of file diff --git a/AppInspector.CLI/Writers/JsonWriter.cs b/AppInspector.CLI/Writers/JsonWriter.cs index 7e36df4b..5c105090 100644 --- a/AppInspector.CLI/Writers/JsonWriter.cs +++ b/AppInspector.CLI/Writers/JsonWriter.cs @@ -24,10 +24,8 @@ public override void WriteResults(Result result, CLICommandOptions commandOption { switch (result) { - case TagTestResult: case TagDiffResult: case ExportTagsResult: - case GetTagsResult: case VerifyRulesResult: jsonSerializer.Serialize(TextWriter, result); break; diff --git a/AppInspector.CLI/Writers/TagTestTextWriter.cs b/AppInspector.CLI/Writers/TagTestTextWriter.cs deleted file mode 100644 index 4e326915..00000000 --- a/AppInspector.CLI/Writers/TagTestTextWriter.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (C) Microsoft. All rights reserved. -// Licensed under the MIT License. See LICENSE.txt in the project root for license information. - -using Microsoft.ApplicationInspector.Commands; -using System; - -namespace Microsoft.ApplicationInspector.CLI -{ - public class TagTestTextWriter : CommandResultsWriter - { - public override void WriteResults(Result result, CLICommandOptions commandOptions, bool autoClose = true) - { - CLITagTestCmdOptions cLITagTestCmdOptions = (CLITagTestCmdOptions)commandOptions; - TagTestResult tagTestResult = (TagTestResult)result; - - //For console output, update write once for same results to console or file - WriteOnce.TextWriter = TextWriter; - - if (string.IsNullOrEmpty(commandOptions.OutputFilePath)) - { - WriteOnce.Result("Results"); - } - - WriteOnce.General(MsgHelp.FormatString(MsgHelp.ID.TAGTEST_RESULTS_TEST_TYPE, cLITagTestCmdOptions.TestType), false, WriteOnce.ConsoleVerbosity.Low); - - if (tagTestResult.ResultCode == TagTestResult.ExitCode.TestFailed) - { - WriteOnce.Any(MsgHelp.GetString(MsgHelp.ID.TAGTEST_RESULTS_FAIL), true, ConsoleColor.Red, WriteOnce.ConsoleVerbosity.Low); - } - else - { - WriteOnce.Any(MsgHelp.GetString(MsgHelp.ID.TAGTEST_RESULTS_SUCCESS), true, ConsoleColor.Green, WriteOnce.ConsoleVerbosity.Low); - } - - if (tagTestResult.TagsStatusList.Count > 0) - { - WriteOnce.Result("Test results:"); - - foreach (TagStatus tag in tagTestResult.TagsStatusList) - { - WriteOnce.General(string.Format("Tag: {0}, Detected: {1}", tag.Tag, tag.Detected)); - } - } - - WriteOnce.NewLine(); - - if (autoClose) - { - FlushAndClose(); - } - } - } -} \ No newline at end of file diff --git a/AppInspector.CLI/Writers/WriterFactory.cs b/AppInspector.CLI/Writers/WriterFactory.cs index 3e1b9077..98a7557f 100644 --- a/AppInspector.CLI/Writers/WriterFactory.cs +++ b/AppInspector.CLI/Writers/WriterFactory.cs @@ -9,7 +9,7 @@ namespace Microsoft.ApplicationInspector.CLI { - public class WriterFactory + public static class WriterFactory { /// /// Responsible for returning the correct cmd and format writer for output of cmd results. An an output @@ -29,10 +29,6 @@ public class WriterFactory { writer = GetAnalyzeWriter(cliAnalyzeCmdOptions); } - else if (options is CLITagTestCmdOptions cliTagTestCmdOptions) - { - writer = GetTagTestWriter(cliTagTestCmdOptions); - } else if (options is CLITagDiffCmdOptions cliTagDiffCmdOptions) { writer = GetTagDiffWriter(cliTagDiffCmdOptions); @@ -49,10 +45,6 @@ public class WriterFactory { writer = GetPackRulesWriter(cliPackRulesCmdOptions); } - else if (options is CLIGetTagsCommandOptions cliGetTagsCmdOptions) - { - writer = GetGetTagsWriter(cliGetTagsCmdOptions); - } else { throw new Exception("Unrecognized object type in writer request"); @@ -122,58 +114,6 @@ public static CommandResultsWriter GetExportTagsWriter(CLIExportTagsCmdOptions o return writer; } - private static CommandResultsWriter GetGetTagsWriter(CLIGetTagsCommandOptions options) - { - CommandResultsWriter? writer; - - switch (options.OutputFileFormat.ToLower()) - { - case "json": - writer = new JsonWriter(); - break; - - case "text": - writer = new GetTagsTextWriter(); - break; - - default: - WriteOnce.Error(MsgHelp.FormatString(MsgHelp.ID.CMD_INVALID_ARG_VALUE, "-f")); - throw new OpException((MsgHelp.FormatString(MsgHelp.ID.CMD_INVALID_ARG_VALUE, "-f"))); - } - - //assign the stream as a file or console - writer.OutputFileName = options.OutputFilePath; - writer.TextWriter = GetTextWriter(writer.OutputFileName); - - return writer; - } - - private static CommandResultsWriter GetTagTestWriter(CLITagTestCmdOptions options) - { - CommandResultsWriter? writer; - - switch (options.OutputFileFormat.ToLower()) - { - case "json": - writer = new JsonWriter(); - break; - - case "text": - writer = new TagTestTextWriter(); - break; - - default: - WriteOnce.Error(MsgHelp.FormatString(MsgHelp.ID.CMD_INVALID_ARG_VALUE, "-f")); - throw new OpException((MsgHelp.FormatString(MsgHelp.ID.CMD_INVALID_ARG_VALUE, "-f"))); - } - - //assign the stream as a file or console - writer.OutputFileName = options.OutputFilePath; - writer.TextWriter = GetTextWriter(writer.OutputFileName); - - return writer; - } - private static CommandResultsWriter GetTagDiffWriter(CLITagDiffCmdOptions options) { CommandResultsWriter? writer; diff --git a/AppInspector/AppInspector.Commands.csproj b/AppInspector/AppInspector.Commands.csproj index a74ce59e..68fdc5a5 100644 --- a/AppInspector/AppInspector.Commands.csproj +++ b/AppInspector/AppInspector.Commands.csproj @@ -58,10 +58,11 @@ - - + + + - + diff --git a/AppInspector/Commands/AnalyzeCommand.cs b/AppInspector/Commands/AnalyzeCommand.cs index 5fb39478..6b4f14b7 100644 --- a/AppInspector/Commands/AnalyzeCommand.cs +++ b/AppInspector/Commands/AnalyzeCommand.cs @@ -1,16 +1,19 @@ // Copyright (C) Microsoft. All rights reserved. // Licensed under the MIT License. See LICENSE.txt in the project root for license information. +using GlobExpressions; using Microsoft.ApplicationInspector.RulesEngine; using Microsoft.CST.RecursiveExtractor; using Newtonsoft.Json; using NLog; using ShellProgressBar; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -21,14 +24,15 @@ namespace Microsoft.ApplicationInspector.Commands /// public class AnalyzeOptions : CommandOptions { - public string SourcePath { get; set; } = ""; + public IEnumerable SourcePath { get; set; } = Array.Empty(); public string? CustomRulesPath { get; set; } public bool IgnoreDefaultRules { get; set; } public string ConfidenceFilters { get; set; } = "high,medium"; - public string FilePathExclusions { get; set; } = "sample,example,test,docs,.vs,.git"; + public IEnumerable FilePathExclusions { get; set; } = Array.Empty(); public bool SingleThread { get; set; } = false; public bool TreatEverythingAsCode { get; set; } = false; public bool NoShowProgress { get; set; } = true; + public bool TagsOnly { get; set; } = false; public int FileTimeOut { get; set; } = 0; public int ProcessingTimeOut { get; set; } = 0; public int ContextLines { get; set; } = 3; @@ -69,31 +73,30 @@ public AnalyzeResult() /// public class AnalyzeCommand { - private IEnumerable? _srcfileList; + private readonly List _srcfileList = new(); private MetaDataHelper? _metaDataHelper; //wrapper containing MetaData object to be assigned to result private RuleProcessor? _rulesProcessor; + private const int _sleepDelay = 100; + private DateTime DateScanned { get; } - private DateTime DateScanned { get; set; } - - private readonly List _fileExclusionList = new List(); + private readonly List _fileExclusionList = new(); private Confidence _confidence; private readonly AnalyzeOptions _options; //copy of incoming caller options + /// + /// Constructor for AnalyzeCommand. + /// + /// public AnalyzeCommand(AnalyzeOptions opt) { _options = opt; - if (!string.IsNullOrEmpty(opt.FilePathExclusions)) - { - _fileExclusionList = opt.FilePathExclusions.ToLower().Split(",").ToList(); - if (_fileExclusionList != null && (_fileExclusionList.Contains("none") || _fileExclusionList.Contains("None"))) - { - _fileExclusionList.Clear(); - } + if (opt.FilePathExclusions.Any(x => !x.Equals("none"))){ + _fileExclusionList = opt.FilePathExclusions.Select(x => new Glob(x)).ToList(); } else { - _fileExclusionList = new List(); + _fileExclusionList = new List(); } DateScanned = DateTime.Now; @@ -132,8 +135,7 @@ private void ConfigureConsoleOutput() } else { - WriteOnce.ConsoleVerbosity verbosity = WriteOnce.ConsoleVerbosity.Medium; - if (!Enum.TryParse(_options.ConsoleVerbosityLevel, true, out verbosity)) + if (!Enum.TryParse(_options.ConsoleVerbosityLevel, true, out WriteOnce.ConsoleVerbosity verbosity)) { throw new OpException(MsgHelp.FormatString(MsgHelp.ID.CMD_INVALID_ARG_VALUE, "-x")); } @@ -180,33 +182,36 @@ private void ConfigSourcetoScan() { WriteOnce.SafeLog("AnalyzeCommand::ConfigSourcetoScan", LogLevel.Trace); - if (string.IsNullOrEmpty(_options.SourcePath)) + if (!_options.SourcePath.Any()) { throw new OpException(MsgHelp.FormatString(MsgHelp.ID.CMD_REQUIRED_ARG_MISSING, "SourcePath")); } - if (Directory.Exists(_options.SourcePath)) + foreach(var entry in _options.SourcePath) { - try + if (Directory.Exists(entry)) { - _srcfileList = Directory.EnumerateFiles(_options.SourcePath, "*.*", SearchOption.AllDirectories); - if (!_srcfileList.Any()) + try + { + _srcfileList.AddRange(Directory.EnumerateFiles(entry, "*.*", SearchOption.AllDirectories)); + } + catch (Exception) { - throw new OpException(MsgHelp.FormatString(MsgHelp.ID.CMD_INVALID_FILE_OR_DIR, _options.SourcePath)); + throw; } } - catch (Exception) + else if (File.Exists(entry)) { - throw; + _srcfileList.Add(entry); + } + else + { + throw new OpException(MsgHelp.FormatString(MsgHelp.ID.CMD_INVALID_FILE_OR_DIR, string.Join(',', _options.SourcePath))); } } - else if (File.Exists(_options.SourcePath)) //not a directory but make one for single flow - { - _srcfileList = new List() { _options.SourcePath }; - } - else + if (!_srcfileList.Any()) { - throw new OpException(MsgHelp.FormatString(MsgHelp.ID.CMD_INVALID_FILE_OR_DIR, _options.SourcePath)); + throw new OpException(MsgHelp.FormatString(MsgHelp.ID.CMD_INVALID_FILE_OR_DIR, string.Join(',', _options.SourcePath))); } } @@ -238,7 +243,7 @@ private void ConfigRules() } else if (File.Exists(_options.CustomRulesPath)) //verify custom rules before use { - RulesVerifier verifier = new RulesVerifier(_options.CustomRulesPath, _options.Log); + RulesVerifier verifier = new(_options.CustomRulesPath, _options.Log); verifier.Verify(); if (!verifier.IsVerified) { @@ -264,13 +269,14 @@ private void ConfigRules() { logger = _options.Log, treatEverythingAsCode = _options.TreatEverythingAsCode, - confidenceFilter = _confidence + confidenceFilter = _confidence, + Parallel = !_options.SingleThread }; _rulesProcessor = new RuleProcessor(rulesSet, rpo); //create metadata helper to wrap and help populate metadata from scan - _metaDataHelper = new MetaDataHelper(_options.SourcePath, false); + _metaDataHelper = new MetaDataHelper(string.Join(',',_options.SourcePath)); } #endregion configureMethods @@ -284,7 +290,11 @@ private void ConfigRules() public AnalyzeResult.ExitCode PopulateRecords(CancellationToken cancellationToken, AnalyzeOptions opts, IEnumerable populatedEntries) { WriteOnce.SafeLog("AnalyzeCommand::PopulateRecords", LogLevel.Trace); - + if (_metaDataHelper is null) + { + WriteOnce.Error("MetadataHelper is null"); + throw new ArgumentNullException("_metaDataHelper"); + } if (_rulesProcessor is null || populatedEntries is null) { return AnalyzeResult.ExitCode.CriticalError; @@ -302,7 +312,7 @@ public AnalyzeResult.ExitCode PopulateRecords(CancellationToken cancellationToke { try { - Parallel.ForEach(populatedEntries, new ParallelOptions() { CancellationToken = cancellationToken }, entry => ProcessAndAddToMetadata(entry)); + Parallel.ForEach(populatedEntries, new ParallelOptions() { CancellationToken = cancellationToken, MaxDegreeOfParallelism = Environment.ProcessorCount * 3 / 2 }, entry => ProcessAndAddToMetadata(entry)); } catch (OperationCanceledException) { @@ -319,7 +329,7 @@ void ProcessAndAddToMetadata(FileEntry file) var sw = new Stopwatch(); sw.Start(); - if (_fileExclusionList.Any(x => file.FullPath.ToLower().Contains(x))) + if (_fileExclusionList.Any(x => x.IsMatch(file.FullPath))) { WriteOnce.SafeLog(MsgHelp.FormatString(MsgHelp.ID.ANALYZE_EXCLUDED_TYPE_SKIPPED, fileRecord.FileName), LogLevel.Debug); fileRecord.Status = ScanState.Skipped; @@ -333,17 +343,17 @@ void ProcessAndAddToMetadata(FileEntry file) } else { - _ = _metaDataHelper?.FileExtensions.TryAdd(Path.GetExtension(file.FullPath).Replace('.', ' ').TrimStart(), 0); + _ = _metaDataHelper.FileExtensions.TryAdd(Path.GetExtension(file.FullPath).Replace('.', ' ').TrimStart(), 0); LanguageInfo languageInfo = new LanguageInfo(); if (Language.FromFileName(file.FullPath, ref languageInfo)) { - _metaDataHelper?.AddLanguage(languageInfo.Name); + _metaDataHelper.AddLanguage(languageInfo.Name); } else { - _metaDataHelper?.AddLanguage("Unknown"); + _metaDataHelper.AddLanguage("Unknown"); languageInfo = new LanguageInfo() { Extensions = new string[] { Path.GetExtension(file.FullPath) }, Name = "Unknown" }; if (!_options.ScanUnknownTypes) { @@ -358,7 +368,17 @@ void ProcessAndAddToMetadata(FileEntry file) if (opts.FileTimeOut > 0) { using var cts = new CancellationTokenSource(); - var t = Task.Run(() => results = _rulesProcessor.AnalyzeFile(file, languageInfo), cts.Token); + var t = Task.Run(() => + { + if (opts.TagsOnly) + { + results = _rulesProcessor.AnalyzeFile(file, languageInfo, _metaDataHelper.UniqueTags.Keys, -1); + } + else + { + results = _rulesProcessor.AnalyzeFile(file, languageInfo, null, opts.ContextLines); + } + }, cts.Token); if (!t.Wait(new TimeSpan(0, 0, 0, 0, opts.FileTimeOut))) { WriteOnce.Error($"{file.FullPath} timed out."); @@ -372,7 +392,14 @@ void ProcessAndAddToMetadata(FileEntry file) } else { - results = _rulesProcessor.AnalyzeFile(file, languageInfo); + if (opts.TagsOnly) + { + results = _rulesProcessor.AnalyzeFile(file, languageInfo, _metaDataHelper.UniqueTags.Keys, -1); + } + else + { + results = _rulesProcessor.AnalyzeFile(file, languageInfo, null, opts.ContextLines); + } fileRecord.Status = ScanState.Analyzed; } @@ -383,7 +410,14 @@ void ProcessAndAddToMetadata(FileEntry file) } foreach (var matchRecord in results) { - _metaDataHelper?.AddMatchRecord(matchRecord); + if (opts.TagsOnly) + { + _metaDataHelper.AddTagsFromMatchRecord(matchRecord); + } + else + { + _metaDataHelper.AddMatchRecord(matchRecord); + } } } } @@ -393,19 +427,28 @@ void ProcessAndAddToMetadata(FileEntry file) fileRecord.ScanTime = sw.Elapsed; - _metaDataHelper?.Files.Add(fileRecord); + _metaDataHelper.Files.Add(fileRecord); } } - public async Task PopulateRecordsAsync(CancellationToken cancellationToken, AnalyzeOptions opts) + /// + /// Populate the records in the metadata asynchronously. + /// + /// + /// Result code. + public async Task PopulateRecordsAsync(CancellationToken cancellationToken) { WriteOnce.SafeLog("AnalyzeCommand::PopulateRecordsAsync", LogLevel.Trace); - + if (_metaDataHelper is null) + { + WriteOnce.Error("MetadataHelper is null"); + throw new ArgumentNullException("_metaDataHelper"); + } if (_rulesProcessor is null) { return AnalyzeResult.ExitCode.CriticalError; } - await foreach (var entry in GetFileEntriesAsync(opts)) + await foreach (var entry in GetFileEntriesAsync()) { if (cancellationToken.IsCancellationRequested) { return AnalyzeResult.ExitCode.Canceled; } await ProcessAndAddToMetadata(entry, cancellationToken); @@ -420,7 +463,7 @@ async Task ProcessAndAddToMetadata(FileEntry file, CancellationToken cancellatio var sw = new Stopwatch(); sw.Start(); - if (_fileExclusionList.Any(x => file.FullPath.ToLower().Contains(x))) + if (_fileExclusionList.Any(x => x.IsMatch(file.FullPath))) { WriteOnce.SafeLog(MsgHelp.FormatString(MsgHelp.ID.ANALYZE_EXCLUDED_TYPE_SKIPPED, fileRecord.FileName), LogLevel.Debug); fileRecord.Status = ScanState.Skipped; @@ -434,19 +477,19 @@ async Task ProcessAndAddToMetadata(FileEntry file, CancellationToken cancellatio } else { - _ = _metaDataHelper?.FileExtensions.TryAdd(Path.GetExtension(file.FullPath).Replace('.', ' ').TrimStart(), 0); + _ = _metaDataHelper.FileExtensions.TryAdd(Path.GetExtension(file.FullPath).Replace('.', ' ').TrimStart(), 0); LanguageInfo languageInfo = new LanguageInfo(); if (Language.FromFileName(file.FullPath, ref languageInfo)) { - _metaDataHelper?.AddLanguage(languageInfo.Name); + _metaDataHelper.AddLanguage(languageInfo.Name); } else { - _metaDataHelper?.AddLanguage("Unknown"); + _metaDataHelper.AddLanguage("Unknown"); languageInfo = new LanguageInfo() { Extensions = new string[] { Path.GetExtension(file.FullPath) }, Name = "Unknown" }; - if (!opts.ScanUnknownTypes) + if (!_options.ScanUnknownTypes) { fileRecord.Status = ScanState.Skipped; } @@ -454,7 +497,9 @@ async Task ProcessAndAddToMetadata(FileEntry file, CancellationToken cancellatio if (fileRecord.Status != ScanState.Skipped) { - var results = await _rulesProcessor.AnalyzeFileAsync(file, languageInfo, cancellationToken); + var results = _options.TagsOnly ? + await _rulesProcessor.AnalyzeFileAsync(file, languageInfo, cancellationToken, _metaDataHelper.UniqueTags.Keys, -1) : + await _rulesProcessor.AnalyzeFileAsync(file, languageInfo, cancellationToken, null, _options.ContextLines); fileRecord.Status = ScanState.Analyzed; if (results.Any()) @@ -464,7 +509,14 @@ async Task ProcessAndAddToMetadata(FileEntry file, CancellationToken cancellatio } foreach (var matchRecord in results) { - _metaDataHelper?.AddMatchRecord(matchRecord); + if (_options.TagsOnly) + { + _metaDataHelper.AddTagsFromMatchRecord(matchRecord); + } + else + { + _metaDataHelper.AddMatchRecord(matchRecord); + } } } } @@ -474,17 +526,21 @@ async Task ProcessAndAddToMetadata(FileEntry file, CancellationToken cancellatio fileRecord.ScanTime = sw.Elapsed; - _metaDataHelper?.Files.Add(fileRecord); + _metaDataHelper.Files.Add(fileRecord); } } + /// + /// Gets the FileEntries synchronously. + /// + /// An Enumerable of FileEntries. public IEnumerable GetFileEntries() { WriteOnce.SafeLog("AnalyzeCommand::GetFileEntries", LogLevel.Trace); Extractor extractor = new(); - foreach (var srcFile in _srcfileList ?? Array.Empty()) + foreach (var srcFile in _srcfileList ?? new List()) { foreach(var entry in extractor.Extract(srcFile, new ExtractorOptions() { Parallel = false })) { @@ -493,13 +549,16 @@ public IEnumerable GetFileEntries() } } - - public async IAsyncEnumerable GetFileEntriesAsync(AnalyzeOptions opts) + /// + /// Gets the FileEntries asynchronously. + /// + /// An enumeration of FileEntries + public async IAsyncEnumerable GetFileEntriesAsync() { WriteOnce.SafeLog("AnalyzeCommand::GetFileEntriesAsync", LogLevel.Trace); Extractor extractor = new(); - foreach (var srcFile in _srcfileList ?? Array.Empty()) + foreach (var srcFile in _srcfileList ?? new List()) { await foreach (var entry in extractor.ExtractAsync(srcFile, new ExtractorOptions() { Parallel = false })) { @@ -542,24 +601,34 @@ private bool IsBinary(Stream fileContents) return false; } + /// + /// Perform Analysis and get the result Asynchronously + /// + /// Cancellation token to stop analysis and return results found so far. + /// public async Task GetResultAsync(CancellationToken cancellationToken) { WriteOnce.SafeLog("AnalyzeCommand::GetResultAsync", LogLevel.Trace); WriteOnce.Operation(MsgHelp.FormatString(MsgHelp.ID.CMD_RUNNING, "Analyze")); + if (_metaDataHelper is null) + { + WriteOnce.Error("MetadataHelper is null"); + throw new ArgumentNullException("_metaDataHelper"); + } AnalyzeResult analyzeResult = new AnalyzeResult() { AppVersion = Utils.GetVersionString() }; - var exitCode = await PopulateRecordsAsync(cancellationToken, _options); + var exitCode = await PopulateRecordsAsync(cancellationToken); //wrapup result status - if (_metaDataHelper?.Files.All(x => x.Status == ScanState.Skipped) ?? false) + if (_metaDataHelper.Files.All(x => x.Status == ScanState.Skipped)) { WriteOnce.Error(MsgHelp.GetString(MsgHelp.ID.ANALYZE_NOSUPPORTED_FILETYPES)); analyzeResult.ResultCode = AnalyzeResult.ExitCode.NoMatches; } - else if (_metaDataHelper?.Matches.Count == 0) + else if (_metaDataHelper.UniqueTagsCount == 0) { WriteOnce.Error(MsgHelp.GetString(MsgHelp.ID.ANALYZE_NOPATTERNS)); analyzeResult.ResultCode = AnalyzeResult.ExitCode.NoMatches; @@ -590,6 +659,11 @@ public AnalyzeResult GetResult() { WriteOnce.SafeLog("AnalyzeCommand::GetResult", LogLevel.Trace); WriteOnce.Operation(MsgHelp.FormatString(MsgHelp.ID.CMD_RUNNING, "Analyze")); + if (_metaDataHelper is null) + { + WriteOnce.Error("MetadataHelper is null"); + throw new ArgumentNullException("_metaDataHelper"); + } AnalyzeResult analyzeResult = new AnalyzeResult() { AppVersion = Utils.GetVersionString() @@ -600,13 +674,13 @@ public AnalyzeResult GetResult() if (!_options.NoShowProgress) { var done = false; - List fileQueue = new(); + ConcurrentBag fileQueue = new(); _ = Task.Factory.StartNew(() => { try { - foreach(var entry in GetFileEntries()) + foreach (var entry in GetFileEntries()) { fileQueue.Add(entry); } @@ -631,14 +705,14 @@ public AnalyzeResult GetResult() { while (!done) { - Thread.Sleep(10); + Thread.Sleep(_sleepDelay); pbar.Message = $"Enumerating Files. {fileQueue.Count} Discovered."; } pbar.Message = $"Enumerating Files. {fileQueue.Count} Discovered."; pbar.Finished(); } - + Console.Write(Environment.NewLine); done = false; var options2 = new ProgressBarOptions @@ -662,17 +736,18 @@ public AnalyzeResult GetResult() while (!done) { - Thread.Sleep(10); - var current = _metaDataHelper?.Files.Count ?? 0; + Thread.Sleep(_sleepDelay); + var current = _metaDataHelper.Files.Count; var timePerRecord = sw.Elapsed.TotalMilliseconds / current; var millisExpected = (int)(timePerRecord * (fileQueue.Count - current)); var timeExpected = new TimeSpan(0, 0, 0, 0, millisExpected); - progressBar.Tick(_metaDataHelper?.Files.Count ?? 0, timeExpected, $"Analyzing Files. {_metaDataHelper?.Matches.Count} Matches. {_metaDataHelper?.Files.Count(x => x.Status == ScanState.Skipped)} Files Skipped. {_metaDataHelper?.Files.Count(x => x.Status == ScanState.TimedOut)} Timed Out. {_metaDataHelper?.Files.Count(x => x.Status == ScanState.Affected)} Affected. {_metaDataHelper?.Files.Count(x => x.Status == ScanState.Analyzed)} Not Affected."); + progressBar.Tick(_metaDataHelper.Files.Count, timeExpected, $"Analyzing Files. {_metaDataHelper.Matches.Count} Matches. {_metaDataHelper.Files.Count(x => x.Status == ScanState.Skipped)} Files Skipped. {_metaDataHelper.Files.Count(x => x.Status == ScanState.TimedOut)} Timed Out. {_metaDataHelper.Files.Count(x => x.Status == ScanState.Affected)} Affected. {_metaDataHelper.Files.Count(x => x.Status == ScanState.Analyzed)} Not Affected."); } - progressBar.Message = $"{_metaDataHelper?.Matches.Count} Matches. {_metaDataHelper?.Files.Count(x => x.Status == ScanState.Skipped)} Files Skipped. {_metaDataHelper?.Files.Count(x => x.Status == ScanState.TimedOut)} Timed Out. {_metaDataHelper?.Files.Count(x => x.Status == ScanState.Affected)} Affected. {_metaDataHelper?.Files.Count(x => x.Status == ScanState.Analyzed)} Not Affected."; + progressBar.Message = $"{_metaDataHelper.Matches.Count} Matches. {_metaDataHelper.Files.Count(x => x.Status == ScanState.Skipped)} Files Skipped. {_metaDataHelper.Files.Count(x => x.Status == ScanState.TimedOut)} Timed Out. {_metaDataHelper.Files.Count(x => x.Status == ScanState.Affected)} Affected. {_metaDataHelper.Files.Count(x => x.Status == ScanState.Analyzed)} Not Affected."; progressBar.Tick(progressBar.MaxTicks); } + Console.Write(Environment.NewLine); } else { @@ -680,12 +755,12 @@ public AnalyzeResult GetResult() } //wrapup result status - if (_metaDataHelper?.Files.All(x => x.Status == ScanState.Skipped) ?? false) + if (_metaDataHelper.Files.All(x => x.Status == ScanState.Skipped)) { WriteOnce.Error(MsgHelp.GetString(MsgHelp.ID.ANALYZE_NOSUPPORTED_FILETYPES)); analyzeResult.ResultCode = AnalyzeResult.ExitCode.NoMatches; } - else if (_metaDataHelper?.Matches.Count == 0) + else if (_metaDataHelper.UniqueTagsCount == 0) { WriteOnce.Error(MsgHelp.GetString(MsgHelp.ID.ANALYZE_NOPATTERNS)); analyzeResult.ResultCode = AnalyzeResult.ExitCode.NoMatches; diff --git a/AppInspector/Commands/ExportTagsCommand.cs b/AppInspector/Commands/ExportTagsCommand.cs index 08acde2c..7d4563b2 100644 --- a/AppInspector/Commands/ExportTagsCommand.cs +++ b/AppInspector/Commands/ExportTagsCommand.cs @@ -12,7 +12,7 @@ namespace Microsoft.ApplicationInspector.Commands { /// - /// + /// Options for the Export Tags command. /// public class ExportTagsOptions : CommandOptions { diff --git a/AppInspector/Commands/GetTagsCommand.cs b/AppInspector/Commands/GetTagsCommand.cs deleted file mode 100644 index b921e273..00000000 --- a/AppInspector/Commands/GetTagsCommand.cs +++ /dev/null @@ -1,723 +0,0 @@ -// Copyright (C) Microsoft. All rights reserved. -// Licensed under the MIT License. See LICENSE.txt in the project root for license information. - -using Microsoft.ApplicationInspector.RulesEngine; -using Microsoft.CST.RecursiveExtractor; -using Newtonsoft.Json; -using NLog; -using ShellProgressBar; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.ApplicationInspector.Commands -{ - /// - /// Options specific to analyze operation not to be confused with CLIAnalyzeCmdOptions which include CLI only args - /// - public class GetTagsCommandOptions : CommandOptions - { - public string SourcePath { get; set; } = ""; - public string? CustomRulesPath { get; set; } - public bool IgnoreDefaultRules { get; set; } - public string ConfidenceFilters { get; set; } = "high,medium"; - public string FilePathExclusions { get; set; } = "sample,example,test,docs,.vs,.git"; - public bool SingleThread { get; set; } = false; - public bool TreatEverythingAsCode { get; set; } = false; - public bool NoShowProgress { get; set; } = true; - public int FileTimeOut { get; set; } = 0; - public int ProcessingTimeOut { get; set; } - public bool ScanUnknownTypes { get; set; } - } - - /// - /// Result of Analyze command GetResult() operation - /// - public class GetTagsResult : Result - { - public enum ExitCode - { - Success = 0, - NoMatches = 1, - CriticalError = Utils.ExitCode.CriticalError, //ensure common value for final exit log mention - Canceled = 3, - TimedOut = 4 - } - - [JsonProperty(Order = 2, PropertyName = "resultCode")] - public ExitCode ResultCode { get; set; } - - /// - /// Analyze command result object containing scan properties - /// - [JsonProperty(Order = 3, PropertyName = "metaData")] - public MetaData Metadata { get; set; } - - public GetTagsResult() - { - Metadata = new MetaData("", "");//needed for serialization for other commands; replaced later - } - } - - /// - /// Analyze operation for setup and processing of results from Rulesengine - /// - public class GetTagsCommand - { - private IEnumerable? _srcfileList; - private MetaDataHelper? _metaDataHelper; //wrapper containing MetaData object to be assigned to result - private RuleProcessor? _rulesProcessor; - - private DateTime DateScanned { get; set; } - - private readonly List _fileExclusionList = new List(); - private Confidence _confidence; - private readonly GetTagsCommandOptions _options; //copy of incoming caller options - - public GetTagsCommand(GetTagsCommandOptions opt) - { - _options = opt; - - if (!string.IsNullOrEmpty(opt.FilePathExclusions)) - { - _fileExclusionList = opt.FilePathExclusions.ToLower().Split(",").ToList(); - if (_fileExclusionList != null && (_fileExclusionList.Contains("none") || _fileExclusionList.Contains("None"))) - { - _fileExclusionList.Clear(); - } - } - else - { - _fileExclusionList = new List(); - } - - DateScanned = DateTime.Now; - - try - { - _options.Log ??= Utils.SetupLogging(_options); - WriteOnce.Log ??= _options.Log; - - ConfigureConsoleOutput(); - ConfigSourcetoScan(); - ConfigConfidenceFilters(); - ConfigRules(); - } - catch (OpException e) //group error handling - { - WriteOnce.Error(e.Message); - throw; - } - } - - #region configureMethods - - /// - /// Establish console verbosity - /// For NuGet DLL use, console is automatically muted overriding any arguments sent - /// - private void ConfigureConsoleOutput() - { - WriteOnce.SafeLog("AnalyzeCommand::ConfigureConsoleOutput", LogLevel.Trace); - - //Set console verbosity based on run context (none for DLL use) and caller arguments - if (!Utils.CLIExecutionContext) - { - WriteOnce.Verbosity = WriteOnce.ConsoleVerbosity.None; - } - else - { - WriteOnce.ConsoleVerbosity verbosity = WriteOnce.ConsoleVerbosity.Medium; - if (!Enum.TryParse(_options.ConsoleVerbosityLevel, true, out verbosity)) - { - throw new OpException(MsgHelp.FormatString(MsgHelp.ID.CMD_INVALID_ARG_VALUE, "-x")); - } - else - { - WriteOnce.Verbosity = verbosity; - } - } - } - - /// - /// Expects user to supply all that apply impacting which rule pattern matches are returned - /// - private void ConfigConfidenceFilters() - { - WriteOnce.SafeLog("AnalyzeCommand::ConfigConfidenceFilters", LogLevel.Trace); - //parse and verify confidence values - if (string.IsNullOrEmpty(_options.ConfidenceFilters)) - { - _confidence = Confidence.High | Confidence.Medium; //excludes low by default - } - else - { - string[] confidences = _options.ConfidenceFilters.Split(','); - foreach (string confidence in confidences) - { - Confidence single; - if (Enum.TryParse(confidence, true, out single)) - { - _confidence |= single; - } - else - { - throw new OpException(MsgHelp.FormatString(MsgHelp.ID.CMD_INVALID_ARG_VALUE, "x")); - } - } - } - } - - /// - /// Simple validation on source path provided for scanning and preparation - /// - private void ConfigSourcetoScan() - { - WriteOnce.SafeLog("AnalyzeCommand::ConfigSourcetoScan", LogLevel.Trace); - - if (string.IsNullOrEmpty(_options.SourcePath)) - { - throw new OpException(MsgHelp.FormatString(MsgHelp.ID.CMD_REQUIRED_ARG_MISSING, "SourcePath")); - } - - if (Directory.Exists(_options.SourcePath)) - { - try - { - _srcfileList = Directory.EnumerateFiles(_options.SourcePath, "*.*", SearchOption.AllDirectories); - if (!_srcfileList.Any()) - { - throw new OpException(MsgHelp.FormatString(MsgHelp.ID.CMD_INVALID_FILE_OR_DIR, _options.SourcePath)); - } - } - catch (Exception) - { - throw new OpException(MsgHelp.FormatString(MsgHelp.ID.CMD_INVALID_FILE_OR_DIR, _options.SourcePath)); - } - } - else if (File.Exists(_options.SourcePath)) //not a directory but make one for single flow - { - _srcfileList = new List() { _options.SourcePath }; - } - else - { - throw new OpException(MsgHelp.FormatString(MsgHelp.ID.CMD_INVALID_FILE_OR_DIR, _options.SourcePath)); - } - } - - /// - /// Add default and/or custom rules paths - /// Iterate paths and add to ruleset - /// - private void ConfigRules() - { - WriteOnce.SafeLog("AnalyzeCommand::ConfigRules", LogLevel.Trace); - - RuleSet? rulesSet = null; - - if (!_options.IgnoreDefaultRules) - { - rulesSet = Utils.GetDefaultRuleSet(_options.Log); - } - - if (!string.IsNullOrEmpty(_options.CustomRulesPath)) - { - if (rulesSet == null) - { - rulesSet = new RuleSet(_options.Log); - } - - if (Directory.Exists(_options.CustomRulesPath)) - { - rulesSet.AddDirectory(_options.CustomRulesPath); - } - else if (File.Exists(_options.CustomRulesPath)) //verify custom rules before use - { - RulesVerifier verifier = new RulesVerifier(_options.CustomRulesPath, _options.Log); - verifier.Verify(); - if (!verifier.IsVerified) - { - throw new OpException(MsgHelp.FormatString(MsgHelp.ID.VERIFY_RULE_LOADFILE_FAILED, _options.CustomRulesPath)); - } - - rulesSet.AddRange(verifier.CompiledRuleset); - } - else - { - throw new OpException(MsgHelp.FormatString(MsgHelp.ID.CMD_INVALID_RULE_PATH, _options.CustomRulesPath)); - } - } - - //error check based on ruleset not path enumeration - if (rulesSet == null || !rulesSet.Any()) - { - throw new OpException(MsgHelp.GetString(MsgHelp.ID.CMD_NORULES_SPECIFIED)); - } - - //instantiate a RuleProcessor with the added rules and exception for dependency - var rpo = new RuleProcessorOptions() - { - logger = _options.Log, - treatEverythingAsCode = _options.TreatEverythingAsCode, - confidenceFilter = _confidence - }; - - _rulesProcessor = new RuleProcessor(rulesSet, rpo); - - //create metadata helper to wrap and help populate metadata from scan - _metaDataHelper = new MetaDataHelper(_options.SourcePath, false); - } - - #endregion configureMethods - - public IEnumerable GetFileEntries() - { - WriteOnce.SafeLog("GetTagsCommand::GetFileEntries", LogLevel.Trace); - - Extractor extractor = new(); - - foreach (var srcFile in _srcfileList ?? Array.Empty()) - { - foreach (var entry in extractor.Extract(srcFile, new ExtractorOptions() { Parallel = false })) - { - yield return entry; - } - } - } - - public GetTagsResult.ExitCode PopulateRecords(CancellationToken cancellationToken, GetTagsCommandOptions opts, IEnumerable populatedEntries) - { - WriteOnce.SafeLog("GetTagsCommand::PopulateRecords", LogLevel.Trace); - - if (_rulesProcessor is null || populatedEntries is null) - { - return GetTagsResult.ExitCode.CriticalError; - } - if (opts.SingleThread) - { - foreach (var entry in populatedEntries) - { - if (cancellationToken.IsCancellationRequested) - { - return GetTagsResult.ExitCode.Canceled; - } - ProcessAndAddToMetadata(entry); - } - } - else - { - try - { - Parallel.ForEach(populatedEntries, new ParallelOptions() { CancellationToken = cancellationToken }, entry => ProcessAndAddToMetadata(entry)); - } - catch (OperationCanceledException) - { - return GetTagsResult.ExitCode.Canceled; - } - } - - return GetTagsResult.ExitCode.Success; - - void ProcessAndAddToMetadata(FileEntry file) - { - var fileRecord = new FileRecord() { FileName = file.FullPath, ModifyTime = file.ModifyTime, CreateTime = file.CreateTime, AccessTime = file.AccessTime }; - - var sw = new Stopwatch(); - sw.Start(); - - - if (_fileExclusionList.Any(v => file.FullPath.ToLower().Contains(v))) - { - WriteOnce.SafeLog(MsgHelp.FormatString(MsgHelp.ID.ANALYZE_EXCLUDED_TYPE_SKIPPED, fileRecord.FileName), LogLevel.Debug); - fileRecord.Status = ScanState.Skipped; - } - else - { - if (IsBinary(file.Content)) - { - WriteOnce.SafeLog(MsgHelp.FormatString(MsgHelp.ID.ANALYZE_EXCLUDED_BINARY, fileRecord.FileName), LogLevel.Debug); - fileRecord.Status = ScanState.Skipped; - } - else - { - _ = _metaDataHelper?.FileExtensions.TryAdd(Path.GetExtension(file.FullPath).Replace('.', ' ').TrimStart(), 0); - - LanguageInfo languageInfo = new LanguageInfo(); - - if (Language.FromFileName(file.FullPath, ref languageInfo)) - { - _metaDataHelper?.AddLanguage(languageInfo.Name); - } - else - { - _metaDataHelper?.AddLanguage("Unknown"); - languageInfo = new LanguageInfo() { Extensions = new string[] { Path.GetExtension(file.FullPath) }, Name = "Unknown" }; - if (!_options.ScanUnknownTypes) - { - fileRecord.Status = ScanState.Skipped; - } - } - - if (fileRecord.Status != ScanState.Skipped) - { - List results = new List(); - - if (opts.FileTimeOut > 0) - { - using var cts = new CancellationTokenSource(); - var t = Task.Run(() => results = _rulesProcessor.AnalyzeFile(file, languageInfo, _metaDataHelper?.UniqueTags.Keys, -1), cts.Token); - if (!t.Wait(new TimeSpan(0, 0, 0, 0, opts.FileTimeOut))) - { - WriteOnce.Error($"{file.FullPath} timed out."); - fileRecord.Status = ScanState.TimedOut; - cts.Cancel(); - } - else - { - fileRecord.Status = ScanState.Analyzed; - } - } - else - { - results = _rulesProcessor.AnalyzeFile(file, languageInfo, _metaDataHelper?.UniqueTags.Keys, -1); - fileRecord.Status = ScanState.Analyzed; - } - - if (results.Any()) - { - fileRecord.Status = ScanState.Affected; - foreach (var matchRecord in results) - { - _metaDataHelper?.AddTagsFromMatchRecord(matchRecord); - } - } - } - } - } - - sw.Stop(); - - fileRecord.ScanTime = sw.Elapsed; - - _metaDataHelper?.Files.Add(fileRecord); - } - } - - private bool IsBinary(Stream fileContents) - { - var numRead = 1; - var span = new Span(new byte[8192]); - var controlsEncountered = 0; - var maxControlsEncountered = (int)(0.3 * fileContents.Length); - while (numRead > 0) - { - numRead = fileContents.Read(span); - for (var i = 0; i < numRead; i++) { - var ch = (char)span[i]; - if (ch == '\0') - { - fileContents.Position = 0; - return true; - } - else if (char.IsControl(ch) && !char.IsWhiteSpace(ch)) - { - if (++controlsEncountered > maxControlsEncountered) - { - fileContents.Position = 0; - return true; - } - } - } - - } - fileContents.Position = 0; - return false; - } - - public async IAsyncEnumerable GetFileEntriesAsync(GetTagsCommandOptions opts) - { - WriteOnce.SafeLog("AnalyzeCommand::GetFileEntriesAsync", LogLevel.Trace); - - Extractor extractor = new(); - foreach (var srcFile in _srcfileList ?? Array.Empty()) - { - await foreach (var entry in extractor.ExtractAsync(srcFile, new ExtractorOptions() { Parallel = false })) - { - yield return entry; - } - } - } - - public async Task PopulateRecordsAsync(CancellationToken cancellationToken, GetTagsCommandOptions opts) - { - WriteOnce.SafeLog("GetTagsCommand::PopulateRecordsAsync", LogLevel.Trace); - - if (_rulesProcessor is null) - { - return GetTagsResult.ExitCode.CriticalError; - } - await foreach (var entry in GetFileEntriesAsync(opts)) - { - if (cancellationToken.IsCancellationRequested) { return GetTagsResult.ExitCode.Canceled; } - await ProcessAndAddToMetadata(entry, cancellationToken); - } - - return GetTagsResult.ExitCode.Success; - - async Task ProcessAndAddToMetadata(FileEntry file, CancellationToken cancellationToken) - { - var fileRecord = new FileRecord() { FileName = file.FullPath, ModifyTime = file.ModifyTime, CreateTime = file.CreateTime, AccessTime = file.AccessTime }; - - var sw = new Stopwatch(); - sw.Start(); - - if (_fileExclusionList.Any(x => file.FullPath.ToLower().Contains(x))) - { - WriteOnce.SafeLog(MsgHelp.FormatString(MsgHelp.ID.ANALYZE_EXCLUDED_TYPE_SKIPPED, fileRecord.FileName), LogLevel.Debug); - fileRecord.Status = ScanState.Skipped; - } - else - { - if (IsBinary(file.Content)) - { - WriteOnce.SafeLog(MsgHelp.FormatString(MsgHelp.ID.ANALYZE_EXCLUDED_BINARY, fileRecord.FileName), LogLevel.Debug); - fileRecord.Status = ScanState.Skipped; - } - else - { - _ = _metaDataHelper?.FileExtensions.TryAdd(Path.GetExtension(file.FullPath).Replace('.', ' ').TrimStart(), 0); - - LanguageInfo languageInfo = new LanguageInfo(); - - if (Language.FromFileName(file.FullPath, ref languageInfo)) - { - _metaDataHelper?.AddLanguage(languageInfo.Name); - } - else - { - _metaDataHelper?.AddLanguage("Unknown"); - languageInfo = new LanguageInfo() { Extensions = new string[] { Path.GetExtension(file.FullPath) }, Name = "Unknown" }; - } - - var results = await _rulesProcessor.AnalyzeFileAsync(file, languageInfo, cancellationToken, _metaDataHelper?.UniqueTags.Keys); - - if (results.Any()) - { - fileRecord.Status = ScanState.Affected; - fileRecord.NumFindings = results.Count; - } - else - { - fileRecord.Status = ScanState.Analyzed; - } - foreach (var matchRecord in results) - { - _metaDataHelper?.AddTagsFromMatchRecord(matchRecord); - } - } - } - - sw.Stop(); - - fileRecord.ScanTime = sw.Elapsed; - - _metaDataHelper?.Files.Add(fileRecord); - } - } - - - public async Task GetResultAsync(CancellationToken cancellationToken) - { - WriteOnce.SafeLog("AnalyzeCommand::GetResultAsync", LogLevel.Trace); - WriteOnce.Operation(MsgHelp.FormatString(MsgHelp.ID.CMD_RUNNING, "Analyze")); - GetTagsResult GetTagsResult = new GetTagsResult() - { - AppVersion = Utils.GetVersionString() - }; - - var exitCode = await PopulateRecordsAsync(cancellationToken, _options); - - //wrapup result status - if (_metaDataHelper?.Files.All(x => x.Status == ScanState.Skipped) ?? false) - { - WriteOnce.Error(MsgHelp.GetString(MsgHelp.ID.ANALYZE_NOSUPPORTED_FILETYPES)); - GetTagsResult.ResultCode = GetTagsResult.ExitCode.NoMatches; - } - else if (_metaDataHelper?.UniqueTagsCount == 0) - { - WriteOnce.Error(MsgHelp.GetString(MsgHelp.ID.ANALYZE_NOPATTERNS)); - GetTagsResult.ResultCode = GetTagsResult.ExitCode.NoMatches; - } - else if (_metaDataHelper != null && _metaDataHelper.Metadata != null) - { - _metaDataHelper.Metadata.DateScanned = DateScanned.ToString(); - _metaDataHelper.PrepareReport(); - GetTagsResult.Metadata = _metaDataHelper.Metadata; //replace instance with metadatahelper processed one - GetTagsResult.ResultCode = GetTagsResult.ExitCode.Success; - } - - if (cancellationToken.IsCancellationRequested) - { - GetTagsResult.ResultCode = GetTagsResult.ExitCode.Canceled; - } - - return GetTagsResult; - } - - /// - /// Main entry point to start analysis from CLI; handles setting up rules, directory enumeration - /// file type detection and handoff - /// Pre: All Configure Methods have been called already and we are ready to SCAN - /// - /// - public GetTagsResult GetResult() - { - WriteOnce.SafeLog("GetTagsCommand::GetResult", LogLevel.Trace); - WriteOnce.Operation(MsgHelp.FormatString(MsgHelp.ID.CMD_RUNNING, "GetTags")); - GetTagsResult getTagsResult = new GetTagsResult() - { - AppVersion = Utils.GetVersionString() - }; - - var timedOut = false; - - if (!_options.NoShowProgress) - { - var done = false; - List fileQueue = new(); - - _ = Task.Factory.StartNew(() => - { - try - { - foreach(var entry in GetFileEntries()) - { - fileQueue.Add(entry); - } - } - catch (OverflowException e) - { - WriteOnce.Error($"Overflowed while extracting file entries. Check the input for quines or zip bombs. {e.Message}"); - } - done = true; - }); - - var options = new ProgressBarOptions - { - ForegroundColor = ConsoleColor.Yellow, - ForegroundColorDone = ConsoleColor.DarkGreen, - BackgroundColor = ConsoleColor.DarkGray, - BackgroundCharacter = '\u2593', - DisableBottomPercentage = true - }; - - using (var pbar = new IndeterminateProgressBar("Enumerating Files.", options)) - { - while (!done) - { - Thread.Sleep(10); - pbar.Message = $"Enumerating Files. {fileQueue.Count} Discovered."; - } - pbar.Message = $"Enumerating Files. {fileQueue.Count} Discovered."; - pbar.Finished(); - } - - done = false; - - var options2 = new ProgressBarOptions - { - ForegroundColor = ConsoleColor.Yellow, - ForegroundColorDone = ConsoleColor.DarkGreen, - BackgroundColor = ConsoleColor.DarkGray, - BackgroundCharacter = '\u2593', - DisableBottomPercentage = false, - ShowEstimatedDuration = true - }; - - using (var progressBar = new ProgressBar(fileQueue.Count, $"Getting Tags..", options2)) - { - var sw = new Stopwatch(); - sw.Start(); - _ = Task.Factory.StartNew(() => - { - DoProcessing(fileQueue); - done = true; - }); - - while (!done) - { - Thread.Sleep(10); - var current = _metaDataHelper?.Files.Count ?? 0; - var timePerRecord = sw.Elapsed.TotalMilliseconds / current; - var millisExpected = (int)(timePerRecord * (fileQueue.Count - current)); - var timeExpected = new TimeSpan(0, 0, 0, 0, millisExpected); - progressBar.Tick(_metaDataHelper?.Files.Count ?? 0, timeExpected, $"Getting Tags. {_metaDataHelper?.UniqueTagsCount} Tags Found. {_metaDataHelper?.Files.Count(x => x.Status == ScanState.Skipped)} Files Skipped. {_metaDataHelper?.Files.Count(x => x.Status == ScanState.TimedOut)} Timed Out. {_metaDataHelper?.Files.Count(x => x.Status == ScanState.Affected || x.Status == ScanState.Analyzed)} Analyzed."); - } - progressBar.Message = $"{_metaDataHelper?.UniqueTagsCount} Tags Found. {_metaDataHelper?.Files.Count(x => x.Status == ScanState.Skipped)} Files Skipped. {_metaDataHelper?.Files.Count(x => x.Status == ScanState.TimedOut)} Timed Out. {_metaDataHelper?.Files.Count(x => x.Status == ScanState.Affected || x.Status == ScanState.Analyzed)} Analyzed."; - progressBar.Tick(progressBar.MaxTicks); - } - } - else - { - DoProcessing(GetFileEntries()); - } - - //wrapup result status - if (_metaDataHelper?.Files.All(x => x.Status == ScanState.Skipped) ?? false) - { - WriteOnce.Error(MsgHelp.GetString(MsgHelp.ID.ANALYZE_NOSUPPORTED_FILETYPES)); - getTagsResult.ResultCode = GetTagsResult.ExitCode.NoMatches; - } - else if (_metaDataHelper?.UniqueTagsCount == 0) - { - WriteOnce.Error(MsgHelp.GetString(MsgHelp.ID.ANALYZE_NOPATTERNS)); - getTagsResult.ResultCode = GetTagsResult.ExitCode.NoMatches; - } - else if (_metaDataHelper != null && _metaDataHelper.Metadata != null) - { - _metaDataHelper.Metadata.DateScanned = DateScanned.ToString(); - _metaDataHelper.PrepareReport(); - getTagsResult.Metadata = _metaDataHelper.Metadata; //replace instance with metadatahelper processed one - getTagsResult.ResultCode = GetTagsResult.ExitCode.Success; - } - - if (timedOut) - { - getTagsResult.ResultCode = GetTagsResult.ExitCode.TimedOut; - } - - return getTagsResult; - - void DoProcessing(IEnumerable fileEntries) - { - if (_options.ProcessingTimeOut > 0) - { - using var cts = new CancellationTokenSource(); - var t = Task.Run(() => PopulateRecords(cts.Token, _options, fileEntries), cts.Token); - if (!t.Wait(new TimeSpan(0, 0, 0, 0, _options.ProcessingTimeOut))) - { - timedOut = true; - WriteOnce.Error($"Processing timed out."); - cts.Cancel(); - if (_metaDataHelper is not null) - { - // Populate skips for all the entries we didn't process - foreach (var entry in fileEntries.Where(x => !_metaDataHelper.Files.Any(y => x.FullPath == y.FileName))) - { - _metaDataHelper.Files.Add(new FileRecord() { AccessTime = entry.AccessTime, CreateTime = entry.CreateTime, ModifyTime = entry.ModifyTime, FileName = entry.FullPath, Status = ScanState.TimeOutSkipped }); - } - } - } - } - else - { - PopulateRecords(new CancellationToken(), _options, fileEntries); - } - } - } - } -} \ No newline at end of file diff --git a/AppInspector/Commands/TagDiffCommand.cs b/AppInspector/Commands/TagDiffCommand.cs index 8647c260..0d1c032e 100644 --- a/AppInspector/Commands/TagDiffCommand.cs +++ b/AppInspector/Commands/TagDiffCommand.cs @@ -11,12 +11,14 @@ namespace Microsoft.ApplicationInspector.Commands { public class TagDiffOptions : CommandOptions { - public string SourcePath1 { get; set; } = ""; - public string SourcePath2 { get; set; } = ""; + public IEnumerable SourcePath1 { get; set; } = Array.Empty(); + public IEnumerable SourcePath2 { get; set; } = Array.Empty(); public string TestType { get; set; } = "equality"; - public string FilePathExclusions { get; set; } = "sample,example,test,docs,.vs,.git"; + public IEnumerable FilePathExclusions { get; set; } = new string[] { }; public string? CustomRulesPath { get; set; } public bool IgnoreDefaultRules { get; set; } + public int FileTimeOut { get; set; } + public int ProcessingTimeOut { get; set; } } /// @@ -143,11 +145,7 @@ private void ConfigSourceToScan() { WriteOnce.SafeLog("TagDiff::ConfigRules", LogLevel.Trace); - if (_options?.SourcePath1 == _options?.SourcePath2) - { - throw new OpException(MsgHelp.GetString(MsgHelp.ID.TAGDIFF_SAME_FILE_ARG)); - } - else if (string.IsNullOrEmpty(_options?.SourcePath1) || string.IsNullOrEmpty(_options?.SourcePath2)) + if ((!_options?.SourcePath1.Any() ?? true) || (!_options?.SourcePath2.Any() ?? true)) { throw new OpException(MsgHelp.GetString(MsgHelp.ID.CMD_INVALID_ARG_VALUE)); } @@ -172,90 +170,89 @@ public TagDiffResult GetResult() try { #region setup analyze calls - - GetTagsCommand cmd1 = new GetTagsCommand(new GetTagsCommandOptions + if (_options is null) { - SourcePath = _options?.SourcePath1 ?? "", - CustomRulesPath = _options?.CustomRulesPath, - IgnoreDefaultRules = _options?.IgnoreDefaultRules ?? false, - FilePathExclusions = _options?.FilePathExclusions ?? "", + throw new ArgumentNullException("_options"); + } + AnalyzeCommand cmd1 = new(new AnalyzeOptions() + { + SourcePath = _options.SourcePath1, + CustomRulesPath = _options.CustomRulesPath, + IgnoreDefaultRules = _options.IgnoreDefaultRules, + FilePathExclusions = _options.FilePathExclusions, ConsoleVerbosityLevel = "none", - Log = _options?.Log + Log = _options.Log, + TagsOnly = true, }); - GetTagsCommand cmd2 = new GetTagsCommand(new GetTagsCommandOptions + AnalyzeCommand cmd2 = new(new AnalyzeOptions() { - SourcePath = _options?.SourcePath2 ?? "", - CustomRulesPath = _options?.CustomRulesPath, - IgnoreDefaultRules = _options != null ? _options.IgnoreDefaultRules : false, - FilePathExclusions = _options?.FilePathExclusions ?? "", + SourcePath = _options.SourcePath2, + CustomRulesPath = _options.CustomRulesPath, + IgnoreDefaultRules = _options.IgnoreDefaultRules, + FilePathExclusions = _options.FilePathExclusions, ConsoleVerbosityLevel = "none", - Log = _options?.Log + Log = _options.Log, + TagsOnly = true }); - GetTagsResult analyze1 = cmd1.GetResult(); - GetTagsResult analyze2 = cmd2.GetResult(); + AnalyzeResult analyze1 = cmd1.GetResult(); + AnalyzeResult analyze2 = cmd2.GetResult(); //restore WriteOnce.Verbosity = saveVerbosity; #endregion setup analyze calls - bool equalTagsCompare1; - bool equalTagsCompare2; - //process results for each analyze call before comparing results - if (analyze1.ResultCode == GetTagsResult.ExitCode.CriticalError) + if (analyze1.ResultCode == AnalyzeResult.ExitCode.CriticalError) { - throw new OpException(MsgHelp.FormatString(MsgHelp.ID.CMD_CRITICAL_FILE_ERR, _options?.SourcePath1 ?? "")); + throw new OpException(MsgHelp.FormatString(MsgHelp.ID.CMD_CRITICAL_FILE_ERR, string.Join(',',_options.SourcePath1))); } - else if (analyze2.ResultCode == GetTagsResult.ExitCode.CriticalError) + else if (analyze2.ResultCode == AnalyzeResult.ExitCode.CriticalError) { - throw new OpException(MsgHelp.FormatString(MsgHelp.ID.CMD_CRITICAL_FILE_ERR, _options?.SourcePath2 ?? "")); + throw new OpException(MsgHelp.FormatString(MsgHelp.ID.CMD_CRITICAL_FILE_ERR, string.Join(',', _options.SourcePath2))); } - else if (analyze1.ResultCode == GetTagsResult.ExitCode.NoMatches || analyze2.ResultCode == GetTagsResult.ExitCode.NoMatches) + else if (analyze1.ResultCode == AnalyzeResult.ExitCode.NoMatches || analyze2.ResultCode == AnalyzeResult.ExitCode.NoMatches) { throw new OpException(MsgHelp.GetString(MsgHelp.ID.TAGDIFF_NO_TAGS_FOUND)); } else //compare tag results; assumed (result1&2 == AnalyzeCommand.ExitCode.Success) { - int count1 = 0; - int sizeTags1 = analyze1.Metadata.UniqueTags != null ? analyze1.Metadata.UniqueTags.Count : 0; - string[] file1Tags = new string[sizeTags1]; + + var list1 = analyze1.Metadata.UniqueTags ?? new List(); + var list2 = analyze2.Metadata.UniqueTags ?? new List(); - foreach (string tag in analyze1.Metadata.UniqueTags ?? new List()) + var removed = list1.Except(list2); + var added = list2.Except(list1); + + foreach(var add in added) { - file1Tags[count1++] = tag; + tagDiffResult.TagDiffList.Add(new TagDiff() + { + Source = TagDiff.DiffSource.Source2, + Tag = add + }); } - - int count2 = 0; - int sizeTags2 = analyze2.Metadata.UniqueTags != null ? analyze2.Metadata.UniqueTags.Count : 0; - string[] file2Tags = new string[sizeTags2]; - - foreach (string tag in analyze2.Metadata.UniqueTags ?? new List()) + foreach (var remove in removed) { - file2Tags[count2++] = tag; + tagDiffResult.TagDiffList.Add(new TagDiff() + { + Source = TagDiff.DiffSource.Source1, + Tag = remove + }); } - //can't simply compare counts as content may differ; must compare both in directions in two passes a->b; b->a - equalTagsCompare1 = CompareTags(file1Tags, file2Tags, ref tagDiffResult, TagDiff.DiffSource.Source1); - //reverse order for second pass - equalTagsCompare2 = CompareTags(file2Tags, file1Tags, ref tagDiffResult, TagDiff.DiffSource.Source2); - - //final results - bool resultsDiffer = !(equalTagsCompare1 && equalTagsCompare2); - if (_arg_tagTestType == TagTestType.Inequality && !resultsDiffer) - { - tagDiffResult.ResultCode = TagDiffResult.ExitCode.TestFailed; - } - else if (_arg_tagTestType == TagTestType.Equality && resultsDiffer) + if (tagDiffResult.TagDiffList.Count > 0) { - tagDiffResult.ResultCode = TagDiffResult.ExitCode.TestFailed; + tagDiffResult.ResultCode = _arg_tagTestType == TagTestType.Inequality ? TagDiffResult.ExitCode.TestPassed : TagDiffResult.ExitCode.TestFailed; } else { - tagDiffResult.ResultCode = TagDiffResult.ExitCode.TestPassed; + tagDiffResult.ResultCode = _arg_tagTestType == TagTestType.Inequality ? TagDiffResult.ExitCode.TestFailed : TagDiffResult.ExitCode.TestPassed; } + + return tagDiffResult; } } catch (OpException e) @@ -265,24 +262,6 @@ public TagDiffResult GetResult() //caught for CLI callers with final exit msg about checking log or throws for DLL callers throw; } - - return tagDiffResult; - } - - private bool CompareTags(string[] fileTags1, string[] fileTags2, ref TagDiffResult tagDiffResult, TagDiff.DiffSource source) - { - bool found = true; - //are all tags in file1 found in file2 - foreach (string s1 in fileTags1) - { - if (!fileTags2.Contains(s1)) - { - found = false; - tagDiffResult.TagDiffList.Add(new TagDiff() { Tag = s1, Source = source }); - } - } - - return found; } } } \ No newline at end of file diff --git a/AppInspector/Commands/TagTestCommand.cs b/AppInspector/Commands/TagTestCommand.cs deleted file mode 100644 index 055cc1b9..00000000 --- a/AppInspector/Commands/TagTestCommand.cs +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright (C) Microsoft. All rights reserved. -// Licensed under the MIT License. See LICENSE.txt in the project root for license information. - -using Microsoft.ApplicationInspector.RulesEngine; -using Newtonsoft.Json; -using NLog; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Microsoft.ApplicationInspector.Commands -{ - public class TagTestOptions : CommandOptions - { - public string? SourcePath { get; set; } - public string TestType { get; set; } = "rulespresent"; - public string? CustomRulesPath { get; set; } - public string FilePathExclusions { get; set; } = "sample,example,test,docs,.vs,.git"; - } - - public class TagStatus - { - /// - /// Tag name from the applicable rule - /// - public string? Tag { get; set; } - - /// - /// True/false indicator of test status for given tag - /// - public bool Detected { get; set; } - } - - public class TagTestResult : Result - { - public enum ExitCode - { - TestPassed = 0, - TestFailed = 1, - CriticalError = Utils.ExitCode.CriticalError //ensure common value for final exit log mention - } - - [JsonProperty(Order = 2, PropertyName = "resultCode")] - public ExitCode ResultCode { get; set; } - - /// - /// List of tags from test and detection status of each - /// - [JsonProperty(Order = 3, PropertyName = "tagsStatusList")] - public List TagsStatusList { get; set; } - - public TagTestResult() - { - TagsStatusList = new List(); - } - } - - /// - /// Used to test a specific set of rules were all found in target source; Pass/Fail as well as inverse option to test if a set of rules is not - /// found in source code - /// - public class TagTestCommand - { - private enum TagTestType { RulesPresent, RulesNotPresent } - - private readonly TagTestOptions _options; - private TagTestType _arg_tagTestType; - private RuleSet _rulesSet; - - /// Compares a set of rules against a source path... - /// Used for both RulesPresent and RulesNotePresent options - /// Focus is pass/fail not detailed comparison output -see Tagdiff for more - public TagTestCommand(TagTestOptions opt) - { - _options = opt; - _options.TestType ??= "rulespresent"; - - try - { - _options.Log ??= Utils.SetupLogging(_options); - WriteOnce.Log ??= _options.Log; - _rulesSet = new RuleSet(_options.Log); - - ConfigureConsoleOutput(); - ConfigureCompareTest(); - ConfigureRules(); - } - catch (OpException e) //group error handling - { - WriteOnce.Error(e.Message); - throw; - } - } - - #region configure - - /// - /// Establish console verbosity - /// For NuGet DLL use, console is muted overriding any arguments sent - /// - private void ConfigureConsoleOutput() - { - WriteOnce.SafeLog("TagTestCommand::ConfigureConsoleOutput", LogLevel.Trace); - - //Set console verbosity based on run context (none for DLL use) and caller arguments - if (!Utils.CLIExecutionContext) - { - WriteOnce.Verbosity = WriteOnce.ConsoleVerbosity.None; - } - else - { - WriteOnce.ConsoleVerbosity verbosity = WriteOnce.ConsoleVerbosity.Medium; - if (!Enum.TryParse(_options.ConsoleVerbosityLevel, true, out verbosity)) - { - throw new OpException(MsgHelp.FormatString(MsgHelp.ID.CMD_INVALID_ARG_VALUE, "-x")); - } - else - { - WriteOnce.Verbosity = verbosity; - } - } - } - - private void ConfigureCompareTest() - { - if (!Enum.TryParse(_options.TestType, true, out _arg_tagTestType)) - { - throw new OpException(MsgHelp.FormatString(MsgHelp.ID.CMD_INVALID_ARG_VALUE, _options.TestType)); - } - } - - public void ConfigureRules() - { - WriteOnce.SafeLog("TagTestCommand::ConfigRules", LogLevel.Trace); - - if (string.IsNullOrEmpty(_options.CustomRulesPath)) - { - throw new OpException(MsgHelp.GetString(MsgHelp.ID.CMD_NORULES_SPECIFIED)); - } - - RulesVerifier verifier = new RulesVerifier(_options.CustomRulesPath, _options.Log); - verifier.Verify(); - if (!verifier.IsVerified) - { - throw new OpException(MsgHelp.GetString(MsgHelp.ID.VERIFY_RULES_RESULTS_FAIL)); - } - - _rulesSet = verifier.CompiledRuleset ?? new RuleSet(null); - - //error check based on ruleset not path enumeration - if (!_rulesSet.Any()) - { - throw new OpException(MsgHelp.GetString(MsgHelp.ID.CMD_NORULES_SPECIFIED)); - } - } - - #endregion configure - - /// - /// Main entry from CLI - /// - /// - public TagTestResult GetResult() - { - WriteOnce.SafeLog("TagTestCommand::Run", LogLevel.Trace); - WriteOnce.Operation(MsgHelp.FormatString(MsgHelp.ID.CMD_RUNNING, "Tag Test")); - TagTestResult tagTestResult = new TagTestResult() - { - AppVersion = Utils.GetVersionString() - }; - - //init based on true or false present argument value - WriteOnce.ConsoleVerbosity saveVerbosity = WriteOnce.Verbosity; - GetTagsResult.ExitCode analyzeCmdResult = GetTagsResult.ExitCode.CriticalError; - - try - { - //setup analyze call with silent option - GetTagsCommand cmd1 = new GetTagsCommand(new GetTagsCommandOptions - { - SourcePath = _options?.SourcePath ?? "", - IgnoreDefaultRules = true, - CustomRulesPath = _options?.CustomRulesPath ?? "", - FilePathExclusions = _options?.FilePathExclusions ?? "", - ConsoleVerbosityLevel = "none", - Log = _options?.Log - }); - - //get and perform initial analyze on results - GetTagsResult analyze1 = cmd1.GetResult(); - - //restore - WriteOnce.Verbosity = saveVerbosity; - - if (analyze1.ResultCode == GetTagsResult.ExitCode.CriticalError) - { - throw new OpException(MsgHelp.GetString(MsgHelp.ID.CMD_CRITICAL_FILE_ERR)); - } - else if (analyzeCmdResult == GetTagsResult.ExitCode.NoMatches) - { - WriteOnce.General(MsgHelp.FormatString(MsgHelp.ID.TAGTEST_RESULTS_TEST_TYPE, _arg_tagTestType.ToString()), false, WriteOnce.ConsoleVerbosity.Low); - tagTestResult.ResultCode = _arg_tagTestType == TagTestType.RulesPresent ? TagTestResult.ExitCode.TestFailed : TagTestResult.ExitCode.TestPassed; - } - else //assumed (result == AnalyzeCommand.ExitCode.MatchesFound) - { - tagTestResult.ResultCode = TagTestResult.ExitCode.TestPassed; - - int count = 0; - int sizeTags = analyze1.Metadata.UniqueTags != null ? analyze1.Metadata.UniqueTags.Count : 0; - string[] tagsFound = new string[sizeTags]; - - foreach (string tag in analyze1.Metadata.UniqueTags ?? new List()) - { - tagsFound[count++] = tag; - } - - foreach (Rule? rule in _rulesSet) - { - //supports both directions by generalizing - string[]? testList1 = _arg_tagTestType == TagTestType.RulesNotPresent ? - rule?.Tags : tagsFound; - - string[]? testList2 = _arg_tagTestType == TagTestType.RulesNotPresent ? - tagsFound : rule?.Tags; - - foreach (string t in testList2 ?? new string[] { }) - { - if (TagTest(testList1, t)) - { - tagTestResult.TagsStatusList.Add(new TagStatus() { Tag = t, Detected = true }); - } - else - { - tagTestResult.ResultCode = TagTestResult.ExitCode.TestFailed; - tagTestResult.TagsStatusList.Add(new TagStatus() { Tag = t, Detected = false }); - } - } - } - } - } - catch (OpException e) - { - WriteOnce.Verbosity = saveVerbosity; - WriteOnce.Error(e.Message); - //caught for CLI callers with final exit msg about checking log or throws for DLL callers - throw; - } - - return tagTestResult; - } - - private bool TagTest(string[]? list, string? test) - { - if (_arg_tagTestType == TagTestType.RulesNotPresent) - { - return (!list?.Any(v => v.Equals(test)) ?? false); - } - else - { - return (list?.Any(v => v.Equals(test)) ?? false); - } - } - } -} \ No newline at end of file diff --git a/AppInspector/FileRecord.cs b/AppInspector/FileRecord.cs index 50f3c448..52cbc4f4 100644 --- a/AppInspector/FileRecord.cs +++ b/AppInspector/FileRecord.cs @@ -1,4 +1,6 @@ -using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using System; namespace Microsoft.ApplicationInspector.Commands { @@ -13,6 +15,7 @@ public class FileRecord public DateTime AccessTime { get; set; } = DateTime.MinValue; } + [JsonConverter(typeof(StringEnumConverter))] public enum ScanState { None, diff --git a/AppInspector/MetaDataHelper.cs b/AppInspector/MetaDataHelper.cs index a9c921ef..ccd844ac 100644 --- a/AppInspector/MetaDataHelper.cs +++ b/AppInspector/MetaDataHelper.cs @@ -23,7 +23,6 @@ public class MetaDataHelper internal ConcurrentDictionary UniqueDependencies { get; set; } = new ConcurrentDictionary(); private ConcurrentDictionary AppTypes { get; set; } = new ConcurrentDictionary(); - private ConcurrentDictionary FileNames { get; set; } = new ConcurrentDictionary(); internal ConcurrentDictionary UniqueTags { get; set; } = new ConcurrentDictionary(); private ConcurrentDictionary Outputs { get; set; } = new ConcurrentDictionary(); private ConcurrentDictionary Targets { get; set; } = new ConcurrentDictionary(); @@ -40,10 +39,13 @@ public class MetaDataHelper internal MetaData Metadata { get; set; } - public MetaDataHelper(string sourcePath, bool uniqueMatchesOnly) + public MetaDataHelper(string sourcePath) { - sourcePath = Path.GetFullPath(sourcePath);//normalize for .\ and similar - Metadata = new MetaData(GetDefaultProjectName(sourcePath), sourcePath); + if (!sourcePath.Contains(',')) + { + sourcePath = Path.GetFullPath(sourcePath);//normalize for .\ and similar + } + Metadata = new MetaData(sourcePath, sourcePath); } /// @@ -353,15 +355,15 @@ public string DetectSolutionType(MatchRecord match) private string ExtractValue(string s) { - if (s.ToLower().Contains("]", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -28,14 +27,12 @@ ], "applies_to": [ "php" ], "severity": "moderate", - "_comment": "", "patterns": [ { "pattern": "(include|require) .*;", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -48,14 +45,12 @@ ], "applies_to": [ "objective-c" ], "severity": "moderate", - "_comment": "", "patterns": [ { "pattern": "#import .*", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -68,34 +63,29 @@ ], "applies_to": [ "groovy" ], "severity": "moderate", - "_comment": "", "patterns": [ { "pattern": "import .*", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "loadScriptByName", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "evaluate ?\\(.*", "type": "regex", - "scopes": [ "code" ], - "_comment": "" + "scopes": [ "code" ] }, { "pattern": "shell\\.parse ?\\(*", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -108,21 +98,18 @@ ], "applies_to": [ "python", "java", "swift", "go" ], "severity": "moderate", - "_comment": "", "patterns": [ { "pattern": "import .*", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "package .*", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -135,21 +122,18 @@ ], "applies_to": [ "perl", "rust"], "severity": "moderate", - "_comment": "", "patterns": [ { "pattern": "use .*;", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "package .*;", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -162,21 +146,18 @@ ], "applies_to": [ "ruby" ], "severity": "moderate", - "_comment": "", "patterns": [ { "pattern": "load .*", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "require .*", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -189,13 +170,11 @@ ], "applies_to": [ "csharp" ], "severity": "moderate", - "_comment": "", "patterns": [ { "pattern": "using .*;", "type": "regex", - "scopes": [ "code" ], - "_comment": "" + "scopes": [ "code" ] } ] }, @@ -208,35 +187,30 @@ ], "applies_to": [ "javascript" ], "severity": "moderate", - "_comment": "", "patterns": [ { "pattern": "import .*;", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "fetchInject ?\\(.*", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "require ?\\(['\\\"]([^'\\\"]+);", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "\\$\\.getScript\\(.*", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] } diff --git a/AppInspector/rules/default/general/platforms.json b/AppInspector/rules/default/general/platforms.json index 104f8f69..0d81bc30 100644 --- a/AppInspector/rules/default/general/platforms.json +++ b/AppInspector/rules/default/general/platforms.json @@ -61,16 +61,14 @@ "type": "string", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "kitkat|jellybean|lollipop|marshmallow|nougat|oreo", - "type": "regex-word", + "type": "regexword", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -88,15 +86,14 @@ "type": "string", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ], "conditions": [ { "pattern": { "pattern": "chart", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -104,8 +101,7 @@ "_comment": "" }, "search_in": "finding-region(-10,10)", - "negate_finding": true, - "_comment": "" + "negate_finding": true } ] }, @@ -120,11 +116,10 @@ "patterns": [ { "pattern": "AppleWebKit|UIKit|ios", - "type": "regex-word", + "type": "regexword", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -139,11 +134,10 @@ "patterns": [ { "pattern": "(os x)|osx|macos|macosx", - "type": "regex-word", + "type": "regexword", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -161,8 +155,7 @@ "type": "regex", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -180,8 +173,7 @@ "type": "regex", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -200,8 +192,7 @@ "type": "regex", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -216,10 +207,9 @@ "patterns": [ { "pattern": "Windows universal platform|UWP", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], - "modifiers": [ "i" ], - "_comment": "" + "modifiers": [ "i" ] } ] }, @@ -234,11 +224,10 @@ "patterns": [ { "pattern": "linux|xubuntu|ubuntu|coreos|manjaro|archlinux|debian|mint|gentoo|opensuse|redhat|mandrake|mandriva|slackware", - "type": "regex-word", + "type": "regexword", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -253,11 +242,10 @@ "patterns": [ { "pattern": "xbox", - "type": "regex-word", + "type": "regexword", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ], "conditions": [ @@ -272,8 +260,7 @@ "_comment": "" }, "search_in": "finding-region(-5,5)", - "negate_finding": true, - "_comment": "" + "negate_finding": true } ] }, @@ -291,8 +278,7 @@ "type": "regex", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ], "conditions": [ @@ -307,8 +293,7 @@ "_comment": "" }, "search_in": "finding-region(-7,7)", - "negate_finding": true, - "_comment": "" + "negate_finding": true } ] }, @@ -323,7 +308,7 @@ "patterns": [ { "pattern": "IOT", - "type": "regex-word", + "type": "regexword", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], "confidence": "high", @@ -342,11 +327,10 @@ "patterns": [ { "pattern": "kinex", - "type": "regex-word", + "type": "regexword", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -364,8 +348,7 @@ "type": "regex", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] } diff --git a/AppInspector/rules/default/general/solutioninfo.json b/AppInspector/rules/default/general/solutioninfo.json index eb5c4638..7c5c11b3 100644 --- a/AppInspector/rules/default/general/solutioninfo.json +++ b/AppInspector/rules/default/general/solutioninfo.json @@ -11,7 +11,7 @@ "patterns": [ { "pattern": "Win32|Any CPU|Win64|x64|x86|Arm|Arm64", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "modifiers": [ "i" ], "confidence": "high" @@ -50,8 +50,7 @@ "pattern": ".*<\/Authors>", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -69,8 +68,7 @@ "pattern": ".*<\/Version>", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -88,8 +86,7 @@ "pattern": ".*<\/Description>", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -132,8 +129,7 @@ "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -149,7 +145,7 @@ "patterns": [ { "pattern": "ServiceStatus|ServiceController|InstallService", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "confidence": "high" } @@ -169,8 +165,7 @@ "pattern": "(/etc/rc\\.d/service|/etc/systemd/system)", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -186,7 +181,7 @@ "patterns": [ { "pattern": "RegisterServiceCtrlHandler|serviceCtrlHandler|StartServiceCtrlDispatcher|SERVICE_STATUS|SERVICE_RUNNING|SERVICE_WIN32|SERVICE_CONTROL", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "confidence": "high" } @@ -206,8 +201,7 @@ "pattern": "(.*)<\/artifactId>", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -225,8 +219,7 @@ "pattern": "\\\"description\\\"\\s*:\\s*\\\"([^\\\"])+\\\"", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -244,8 +237,7 @@ "pattern": "\\\"version\\\"\\s*:\\s*\\\"([^\\\"])+\\\"", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -263,8 +255,7 @@ "pattern": "\\\"author\\\"\\s*:\\s*\\\"([^\\\"])+\\\"", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -282,8 +273,7 @@ "type": "regex", "scopes": [ "code" ], "confidence": "high", - "modifiers": [ "i" ], - "_comment": "" + "modifiers": [ "i" ] } ] }, @@ -319,8 +309,7 @@ "pattern": ".*<\/TargetFramework(s)?>", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -335,7 +324,7 @@ "patterns": [ { "pattern": "Kubernetes", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "modifiers": [ "i" ], "confidence": "high" @@ -353,7 +342,7 @@ "patterns": [ { "pattern": "Docker|RancherOS", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "modifiers": [ "i" ], "confidence": "high" @@ -371,7 +360,7 @@ "patterns": [ { "pattern": "rktlet", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "modifiers": [ "i" ], "confidence": "high" @@ -389,7 +378,7 @@ "patterns": [ { "pattern": "CRI-O", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "modifiers": [ "i" ], "confidence": "high" @@ -407,7 +396,7 @@ "patterns": [ { "pattern": "hyper-v", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "modifiers": [ "i" ], "confidence": "high" @@ -425,7 +414,7 @@ "patterns": [ { "pattern": "Nano Server|Server Core", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "modifiers": [ "i" ], "confidence": "high" diff --git a/AppInspector/rules/default/infrastructure/microsoft_arm_tmpl.json b/AppInspector/rules/default/infrastructure/microsoft_arm_tmpl.json index 1d3e0301..2ba18f23 100644 --- a/AppInspector/rules/default/infrastructure/microsoft_arm_tmpl.json +++ b/AppInspector/rules/default/infrastructure/microsoft_arm_tmpl.json @@ -13,7 +13,7 @@ "patterns": [ { "pattern": "DeploymentOperationsExtensions|DeploymentScriptsClient|IDeploymentOperations|IDeploymentScriptsClient", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], diff --git a/AppInspector/rules/default/networkcomms/outbound_network.json b/AppInspector/rules/default/networkcomms/outbound_network.json index 7b622c7f..674a3794 100644 --- a/AppInspector/rules/default/networkcomms/outbound_network.json +++ b/AppInspector/rules/default/networkcomms/outbound_network.json @@ -12,7 +12,7 @@ "patterns": [ { "pattern": "tftp|ntp\\.org|ntpupdate|imap|snmp|ftps|sftp|ftp|nntp|smtp|telnet|ssh|pop3|gopher", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -40,8 +40,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "TcpConnection", @@ -49,8 +48,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "(Anonymous|Named)Pipe(Client|Server)Stream", @@ -59,8 +57,7 @@ "code" ], "modifiers": [], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -358,13 +355,12 @@ }, { "pattern": "curl|wpget", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "modifiers": [], - "confidence": "medium", - "_comment": "" + "confidence": "medium" } ] }, @@ -385,8 +381,7 @@ "code" ], "modifiers": [], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -407,8 +402,7 @@ "code" ], "modifiers": [], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -429,8 +423,7 @@ "code" ], "modifiers": [], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -451,8 +444,7 @@ "code" ], "modifiers": [], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -473,8 +465,7 @@ "code" ], "modifiers": [], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -495,8 +486,7 @@ "code" ], "modifiers": [], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -517,8 +507,7 @@ "code" ], "modifiers": [], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -539,8 +528,7 @@ "code" ], "modifiers": [], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -560,8 +548,7 @@ "code" ], "modifiers": [], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "send\\(", @@ -570,8 +557,7 @@ "code" ], "modifiers": [], - "confidence": "medium", - "_comment": "" + "confidence": "medium" } ] } diff --git a/AppInspector/rules/default/os/acl.json b/AppInspector/rules/default/os/acl.json index f204e4b3..1051b171 100644 --- a/AppInspector/rules/default/os/acl.json +++ b/AppInspector/rules/default/os/acl.json @@ -13,7 +13,7 @@ "patterns": [ { "pattern": "FileSecurity|DirectorySecurity", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -32,8 +32,7 @@ "_comment": "" }, "search_in": "finding-region(-5,5)", - "negate_finding": false, - "_comment": "" + "negate_finding": false } ] }, @@ -51,7 +50,7 @@ "patterns": [ { "pattern": "acl.(remove|add)", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -75,7 +74,7 @@ "patterns": [ { "pattern": "SetNamedSecurityInfo|SetEntriesInAcl|AddAccessAllowed|AceAddAccessAllowedObjectAce|AddAce|SetFileSecurity|DeleteAce", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -83,7 +82,7 @@ }, { "pattern": "AuthzModifyClaims|AuthzModifySids|BuildExplicitAccessWithName|SetUserObjectSecurity|DestroyPrivateObjectSecurity|SetKernelObjectSecurity|SetSecurityDescriptorSacl|SetSecurityDescriptorOwner|SetSecurityDescriptorGroup|SetPrivateObjectSecurity|SetNamedSecurityInfo|SetServiceObjectSecurity", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -106,7 +105,7 @@ "patterns": [ { "pattern": "AuditSetPerUserPolicy|AuditSetSecurity", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -114,7 +113,7 @@ }, { "pattern": "DestroyPrivateObjectSecurity|SetKernelObjectSecurity|SetSecurityDescriptorSacl|SetSecurityDescriptorOwner|SetSecurityDescriptorGroup|SetPrivateObjectSecurity|SetNamedSecurityInfo|SetServiceObjectSecurity", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -137,8 +136,7 @@ "scopes": [ "code" ], - "confidence": "medium", - "_comment": "" + "confidence": "medium" } ] }, @@ -157,7 +155,7 @@ "patterns": [ { "pattern": "ImpersonateAnonymousToken|ImpersonateLoggedOnUser", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -179,7 +177,7 @@ "patterns": [ { "pattern": "WindowsImpersonationContext|WindowsIdentity\\.Impersonate|WindowsIdentity\\.RunImpersonated|ImpersonateIdentity", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -201,7 +199,7 @@ "patterns": [ { "pattern": "WindowsImpersonationContext|WindowsIdentity\\.Impersonate|WindowsIdentity\\.RunImpersonated", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -224,7 +222,7 @@ "patterns": [ { "pattern": "AuthzSetAppContainerInformation", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -247,7 +245,7 @@ "patterns": [ { "pattern": "AdjustTokenPrivileges|SetTokenInformation", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -313,8 +311,7 @@ "type": "regex", "scopes": [ "code" ], "confidence": "high", - "modifiers": [ "i" ], - "_comment": "" + "modifiers": [ "i" ] } ] } diff --git a/AppInspector/rules/default/os/dynamic_execution.json b/AppInspector/rules/default/os/dynamic_execution.json index 9b2fb39f..ac2727f4 100644 --- a/AppInspector/rules/default/os/dynamic_execution.json +++ b/AppInspector/rules/default/os/dynamic_execution.json @@ -53,31 +53,27 @@ "type": "regex", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "exec(Sync)?\\(", "type": "substring", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "\\bspawn\\(", "type": "regex", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "\\bsystem\\(", "type": "regex", "scopes": [ "code" ], - "modifiers": [ "i" ], - "_comment": "" + "modifiers": [ "i" ] } ] }, @@ -99,8 +95,7 @@ "type": "substring", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -122,8 +117,7 @@ "type": "regex", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -186,7 +180,7 @@ }, { "pattern": "shellexecute|createprocess|execl|execlp|execlp|execv|execve|execvp|execvpe|execle|fork|QProcess", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -241,8 +235,7 @@ "pattern": "\\bsystem\\(", "type": "regex", "scopes": [ "code" ], - "modifiers": [ "i" ], - "_comment": "" + "modifiers": [ "i" ] } ] }, @@ -257,7 +250,7 @@ "patterns": [ { "pattern": "xp_cmdshell|xp_regread|xp_instance_regread|xp_regwrite|sp_makewebtask|xp_sendmail|sp_configure|sp_executesql|dbcc writepage", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "modifiers": [ "i" ], "confidence": "high" @@ -275,21 +268,21 @@ "patterns": [ { "pattern": "powershell|cmd|rundll32|regedit|wscript|javaw|csc|regsvr32|certutil|bitsadmin|schtasks|wmic|eqnedt32|msiexec|cmstp|mshta|curl|installutil|regsvcs|regasm|msbuild|cscript|msxsl|runonce", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "modifiers": [ "i" ], "confidence": "high" }, { "pattern": "sc (config|query|start|stop)", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "modifiers": [ "i" ], "confidence": "high" }, { "pattern": "reg (add|copy|delete|import|export|restore|save|unload|compare)", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "modifiers": [ "i" ], "confidence": "high" @@ -402,8 +395,7 @@ "_comment": "" }, "search_in": "finding-region(-200,0)", - "negate_finding": false, - "_comment": "" + "negate_finding": false } ] }, diff --git a/AppInspector/rules/default/os/file_io.json b/AppInspector/rules/default/os/file_io.json index ae2e7af0..3c23e1c3 100644 --- a/AppInspector/rules/default/os/file_io.json +++ b/AppInspector/rules/default/os/file_io.json @@ -14,12 +14,11 @@ "patterns": [ { "pattern": "ifstream|fread|fgets|fgetc", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -41,8 +40,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "new StreamReader", @@ -50,8 +48,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "File.OpenText", @@ -59,8 +56,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -82,8 +78,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": ".readlines(", @@ -91,16 +86,14 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": ".read(", "type": "string", "scopes": [ "code" - ], - "_comment": "" + ] } ] }, @@ -121,8 +114,7 @@ "type": "string", "scopes": [ "code" - ], - "_comment": "" + ] }, { "pattern": "fs.ReadStream", @@ -130,16 +122,14 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "fs.open", "type": "string", "scopes": [ "code" - ], - "_comment": "" + ] } ] }, @@ -161,8 +151,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "FileReader|new Scanner\\(Files\\.readAllLines|Files\\.readAllBytes|FileInputStream", @@ -170,8 +159,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -193,8 +181,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "FileReader|new Scanner\\(Files\\.readAllLines|Files\\.readAllBytes|FileInputStream", @@ -202,8 +189,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -226,16 +212,14 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "remove", "type": "regex", "scopes": [ "code" - ], - "_comment": "" + ] } ], "conditions": [ @@ -248,8 +232,7 @@ ] }, "search_in": "finding-region(-200,1)", - "negate_finding": false, - "_comment": "" + "negate_finding": false } ] }, @@ -271,8 +254,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -294,8 +276,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "os.ulink(", @@ -303,8 +284,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -326,8 +306,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -349,8 +328,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -372,8 +350,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "fs.remove(", @@ -381,8 +358,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -404,8 +380,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -428,8 +403,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "fopen\\(.*,.*w.*\\);", @@ -456,8 +430,7 @@ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -479,8 +452,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "open\\(.*,.*w.*\\);", @@ -520,8 +492,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "WriteStream|appendFile|copyFile|createWriteStream|ftruncate", @@ -529,8 +500,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "FileWriter|BufferedWriter|FileUtils\\.copyFile|Files\\.copy", @@ -538,8 +508,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -561,8 +530,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -584,8 +552,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": ".write", @@ -593,15 +560,14 @@ "scopes": [ "code" ], - "confidence": "medium", - "_comment": "" + "confidence": "medium" } ], "conditions": [ { "pattern": { "pattern": "use std::io::Write|use std::io::File|use std:fs:File", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -609,8 +575,7 @@ "_comment": "" }, "search_in": "finding-region(-240,240)", - "negate_finding": false, - "_comment": "" + "negate_finding": false } ] } diff --git a/AppInspector/rules/default/os/process.json b/AppInspector/rules/default/os/process.json index 78304376..deb36570 100644 --- a/AppInspector/rules/default/os/process.json +++ b/AppInspector/rules/default/os/process.json @@ -10,21 +10,19 @@ "patterns": [ { "pattern": "mutex|semaphore|thread|lock|fork", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "async|await", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], - "confidence": "medium", - "_comment": "" + "confidence": "medium" } ] }, @@ -40,16 +38,14 @@ "OS.Process.Multiprocessing" ], "severity": "moderate", - "_comment": "", "patterns": [ { "pattern": "WaitForSingleObject|WaitForMultipleObjects", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -71,8 +67,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "(new System\\.Diagnostics.Process\\(\\)| new Process\\(\\))", @@ -102,8 +97,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "(new System\\.Diagnostics.Process\\(\\)| new Process\\(\\))", @@ -183,7 +177,7 @@ }, { "pattern": "ReadProcessMemory|OpenProcess|VirtualQueryEx", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ] @@ -214,8 +208,7 @@ "type": "substring", "scopes": [ "code" - ], - "_comment": "" + ] } ] }, diff --git a/AppInspector/rules/default/os/setenv.json b/AppInspector/rules/default/os/setenv.json index d52218de..ad817032 100644 --- a/AppInspector/rules/default/os/setenv.json +++ b/AppInspector/rules/default/os/setenv.json @@ -9,11 +9,10 @@ "OS.Environment.Write" ], "severity": "moderate", - "_comment": "", "patterns": [ { "pattern": "setenv|putenv", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -40,8 +39,7 @@ "scopes": [ "code" ], - "confidence": "medium", - "_comment": "" + "confidence": "medium" } ] }, @@ -63,8 +61,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -79,7 +76,6 @@ "OS.Environment.Write" ], "severity": "moderate", - "_comment": "", "patterns": [ { "pattern": "SetEnvironmentVariable", @@ -87,8 +83,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -103,7 +98,6 @@ "OS.Environment.Write" ], "severity": "moderate", - "_comment": "", "patterns": [ { "pattern": "SetEnvironmentVariable|\\$env:.+=", @@ -111,8 +105,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -127,7 +120,6 @@ "OS.Environment.Write" ], "severity": "moderate", - "_comment": "", "patterns": [ { "pattern": "process\\.env\\[\\\".*\\\"\\] *= *", @@ -135,8 +127,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "app\\.set\\('environment'", @@ -144,8 +135,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -167,8 +157,7 @@ "scopes": [ "code" ], - "confidence": "medium", - "_comment": "" + "confidence": "medium" } ], "conditions": [ @@ -183,8 +172,7 @@ "_comment": "" }, "search_in": "finding-region(-10,10)", - "negate_finding": false, - "_comment": "" + "negate_finding": false } ] }, @@ -206,8 +194,7 @@ "scopes": [ "code" ], - "confidence": "medium", - "_comment": "" + "confidence": "medium" } ] }, @@ -229,8 +216,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -245,7 +231,6 @@ "OS.Environment.Read" ], "severity": "moderate", - "_comment": "", "patterns": [ { "pattern": "GetEnvironmentVariable", @@ -253,8 +238,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -269,7 +253,6 @@ "OS.Environment.Read" ], "severity": "moderate", - "_comment": "", "patterns": [ { "pattern": "GetEnvironmentVariable|\\$env:|Env:\\\\", @@ -277,8 +260,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -293,7 +275,6 @@ "OS.Environment.Read" ], "severity": "moderate", - "_comment": "", "patterns": [ { "pattern": "= *process\\.env\\[\\\".*\\\"\\]", @@ -301,8 +282,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "app\\.get\\('environment'", @@ -310,8 +290,7 @@ "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -333,8 +312,7 @@ "scopes": [ "code" ], - "confidence": "medium", - "_comment": "" + "confidence": "medium" } ], "conditions": [ @@ -349,8 +327,7 @@ "_comment": "" }, "search_in": "finding-region(-10,10)", - "negate_finding": false, - "_comment": "" + "negate_finding": false } ] }, @@ -364,11 +341,10 @@ "OS.Environment.Read" ], "severity": "moderate", - "_comment": "", "patterns": [ { "pattern": "getenv", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], diff --git a/AppInspector/rules/default/os/system_registry.json b/AppInspector/rules/default/os/system_registry.json index f187b791..b5b61682 100644 --- a/AppInspector/rules/default/os/system_registry.json +++ b/AppInspector/rules/default/os/system_registry.json @@ -14,10 +14,9 @@ "patterns": [ { "pattern": "RegSetValueEx|RegOpenKeyEx|RegCreateKeyEx", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -37,8 +36,7 @@ "pattern": "Registry(Key)?(.*)?.(SetValue|CreateSubKey|Delete)", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -56,25 +54,23 @@ "patterns": [ { "pattern": "CreateSubKey|SetValue", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ], "conditions": [ { "pattern": { "pattern": "HKEY_|Registry", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "_comment": "" }, "search_in": "finding-region(-40,40)", - "negate_finding": false, - "_comment": "" + "negate_finding": false } ] }, @@ -92,7 +88,7 @@ "patterns": [ { "pattern": "_?winreg\\.(Set|Delete|Create)(Key|Value)(Ex)?", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "confidence": "high", "_comment": "_winreg and winreg built-in modules" @@ -136,8 +132,7 @@ "_comment": "" }, "search_in": "finding-region(-5,5)", - "negate_finding": false, - "_comment": "" + "negate_finding": false } ] }, @@ -153,7 +148,7 @@ "patterns": [ { "pattern": "RegistryAccessRule|RegistrySecurity", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "confidence": "high" } @@ -174,7 +169,7 @@ "patterns": [ { "pattern": "RegGetValue|RegGetDWord|RegGetString|CRegKey|RegOpenKey|RegQueryKeyEx", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "confidence": "high" } @@ -216,8 +211,7 @@ "_comment": "" }, "search_in": "finding-region(-5,5)", - "negate_finding": false, - "_comment": "" + "negate_finding": false } ] }, @@ -237,23 +231,21 @@ "pattern": "Registry(Key)?(.*)?.GetValue", "type": "string", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ], "conditions": [ { "pattern": { "pattern": "HKEY_", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "_comment": "" }, "search_in": "finding-region(-40,40)", - "negate_finding": false, - "_comment": "" + "negate_finding": false } ] }, @@ -273,23 +265,21 @@ "pattern": ".open_subkey(", "type": "string", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ], "conditions": [ { "pattern": { "pattern": "HKEY_", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "_comment": "" }, "search_in": "finding-region(-40,40)", - "negate_finding": false, - "_comment": "" + "negate_finding": false } ] } diff --git a/AppInspector/rules/default/os/user_accts.json b/AppInspector/rules/default/os/user_accts.json index d1779673..d68b8040 100644 --- a/AppInspector/rules/default/os/user_accts.json +++ b/AppInspector/rules/default/os/user_accts.json @@ -13,12 +13,11 @@ "patterns": [ { "pattern": "NetUserAdd|NetGroupAddUser|NetLocalGroupAdd", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -36,12 +35,11 @@ "patterns": [ { "pattern": "NetGroupSetInfo|NetGroupSetUsers|NetLocalGroupDel|NetUserChangePassword", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] } diff --git a/AppInspector/rules/default/security_feature/authentication.json b/AppInspector/rules/default/security_feature/authentication.json index d5106aae..052f4c96 100644 --- a/AppInspector/rules/default/security_feature/authentication.json +++ b/AppInspector/rules/default/security_feature/authentication.json @@ -13,40 +13,28 @@ "type": "regex", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "System\\.IdentityModel|AzureADB2C|SingleAccountPublicClientApplication|MultipleAccountPublicClientApplication", "type": "regex", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { - "pattern": "microsoft\\.aad|adal|msal|AADClient|Microsoft\\.IdentityModel|passport\\.net|ServicePrincipalCredentials", - "type": "regex-word", + "pattern": "microsoft\\.aad|microsoft\\.adal|microsoft\\.msal|AADClient|Microsoft\\.IdentityModel|passport\\.net|ServicePrincipalCredentials", + "type": "regexword", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "AuthenticationResult|MsalServiceException", - "type": "regex-word", - "scopes": [ "code", "comment" ], - "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" - }, - { - "pattern": "aad", - "type": "regex-word", + "type": "regexword", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], - "confidence": "medium", - "_comment": "" + "confidence": "high" } ] }, @@ -61,10 +49,9 @@ "patterns": [ { "pattern": "AcquireTokenForClient|ConfidentialClientApplicationBuilder", - "type": "regex-word", + "type": "regexword", "scopes": [ "code", "comment" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ], "conditions": [ @@ -78,8 +65,7 @@ "_comment": "negate cases for certificate rule identifying client TLS auth" }, "search_in": "finding-region(-10,10)", - "negate_finding": true, - "_comment": "" + "negate_finding": true } ] }, @@ -97,16 +83,14 @@ "type": "regex", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "OIDAuthorizationRequest|accounts\\.google\\.com/o/oauth2|googleapis\\.com/oauth2|GTMAppAuth", "type": "regex", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -121,35 +105,31 @@ "patterns": [ { "pattern": "oauth", - "type": "regex", + "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "auth.?token|access.?token|client.?credentials|client.?id|client.?secret|api.?key", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "low" }, { "pattern": "Authorization: Bearer", "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "bearer", "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "medium", - "_comment": "" + "confidence": "low" } ] }, @@ -167,8 +147,7 @@ "type": "regex", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -183,32 +162,28 @@ "patterns": [ { "pattern": "active.?directory|ADFS", - "type": "regex-word", + "type": "regexword", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "ADsOpenObject|ADObject|ADComputer|ADGroup|ADUser|ADContainer|ADDomain", - "type": "regex-word", + "type": "regexword", "scopes": [ "code", "comment" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "Microsoft\\.IdentityModel\\.ActiveDirectory", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "System\\.DirectoryServices|IDirectoryObject|IDirectorySearch", "type": "regex", "scopes": [ "code", "comment" ], - "confidence": "medium", - "_comment": "" + "confidence": "medium" } ] }, @@ -223,11 +198,10 @@ "patterns": [ { "pattern": "LDAP|ldaps", - "type": "regex-word", + "type": "regexword", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -244,23 +218,20 @@ "pattern": "WWW-Authenticate: NTLM|windowsAuthentication|CredentialCache\\.DefaultCredentials|HTTPNtlmAuthHandler", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "LogonUserA|LogonUserEx|LogonUserW", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "NTLM", "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "medium", - "_comment": "" + "confidence": "medium" } ] }, @@ -301,14 +272,13 @@ "patterns": [ { "pattern": "jwt|RFC 7519|System\\.IdentityModel\\.Tokens\\.Jwt|JwtSecurityToken|JsonWebToken", - "type": "regex-word", + "type": "regexword", "scopes": [ "code", "comment" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -328,8 +298,7 @@ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -347,11 +316,10 @@ "patterns": [ { "pattern": "AuthenticationHeaderValue\\(\"SAML\"", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -366,19 +334,17 @@ "patterns": [ { "pattern": "SAML|saml2", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "federation|sso", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "medium", - "_comment": "" + "confidence": "medium" } ] }, @@ -393,11 +359,10 @@ "patterns": [ { "pattern": "\"Authorization: Basic|WWW-Authenticate|AuthenticationHeaderValue\\(\"Basic\"", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -411,14 +376,33 @@ "severity": "critical", "patterns": [ { - "pattern": "principal|identity|auth|authenticated|authentication|log(in|on)|log(off|out)|signin|sign-?in|signout|sign-?out|networkcredential", - "type": "regex-word", + "pattern": "principal|identity|auth|authenticated|authentication|signin|sign-?in|signout|sign-?out|networkcredential", + "type": "regexword", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" + } + ] + }, + { + "name": "Authentication: General", + "id": "AI040001", + "description": "Authentication: General", + "tags": [ + "Authentication.General" + ], + "severity": "critical", + "patterns": [ + { + "pattern": "log(in|on)|log(off|out)", + "type": "regexword", + "scopes": [ + "code" + ], + "modifiers": [ "i" ], + "confidence": "low" } ] }, @@ -433,19 +417,17 @@ "patterns": [ { "pattern": "(username|userid|password|passphrase|multi-factor|credential|acct)s?", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" }, { "pattern": "connection.?string|conn.?string|DefaultNetworkCredentials", "type": "regex", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "medium", - "_comment": "" + "confidence": "medium" } ] } diff --git a/AppInspector/rules/default/security_feature/authorization.json b/AppInspector/rules/default/security_feature/authorization.json index dccea913..64e021af 100644 --- a/AppInspector/rules/default/security_feature/authorization.json +++ b/AppInspector/rules/default/security_feature/authorization.json @@ -12,7 +12,7 @@ "patterns": [ { "pattern": "sharedAccessPolicy|storageAccessKey|sharedAccessAccountPolicy|storageAccountOrConnectionString", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -42,7 +42,7 @@ "patterns": [ { "pattern": "rbac|userrole*s|roles*", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -64,7 +64,7 @@ "patterns": [ { "pattern": "permissions*", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -84,8 +84,7 @@ "_comment": "eliminate notices" }, "search_in": "finding-region(-10,10)", - "negate_finding": true, - "_comment": "" + "negate_finding": true } ] }, @@ -102,7 +101,7 @@ "patterns": [ { "pattern": "claims*", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -122,8 +121,7 @@ "_comment": "eliminate notices" }, "search_in": "finding-region(-10,10)", - "negate_finding": true, - "_comment": "" + "negate_finding": true } ] }, @@ -160,8 +158,7 @@ "_comment": "since already covered by another rule if SAS related" }, "search_in": "finding-region(-10,10)", - "negate_finding": true, - "_comment": "" + "negate_finding": true } ] } diff --git a/AppInspector/rules/default/test_frameworks/cpp_testing.json b/AppInspector/rules/default/test_frameworks/cpp_testing.json index 54840868..3aa7dd3d 100644 --- a/AppInspector/rules/default/test_frameworks/cpp_testing.json +++ b/AppInspector/rules/default/test_frameworks/cpp_testing.json @@ -21,8 +21,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, diff --git a/AppInspector/rules/default/test_frameworks/java_testing.json b/AppInspector/rules/default/test_frameworks/java_testing.json index 3065b230..67fa91cb 100644 --- a/AppInspector/rules/default/test_frameworks/java_testing.json +++ b/AppInspector/rules/default/test_frameworks/java_testing.json @@ -356,8 +356,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -454,8 +453,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -480,8 +478,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -698,8 +695,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, diff --git a/AppInspector/rules/default/test_frameworks/javascript_testing.json b/AppInspector/rules/default/test_frameworks/javascript_testing.json index 69218671..31cfad28 100644 --- a/AppInspector/rules/default/test_frameworks/javascript_testing.json +++ b/AppInspector/rules/default/test_frameworks/javascript_testing.json @@ -18,8 +18,7 @@ ], "modifiers": [ ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -44,8 +43,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -70,8 +68,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -96,8 +93,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -122,8 +118,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -148,8 +143,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -174,8 +168,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -200,8 +193,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -226,8 +218,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -252,8 +243,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -278,8 +268,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -304,8 +293,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -330,8 +318,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -356,8 +343,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -382,8 +368,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -408,8 +393,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -434,8 +418,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -460,8 +443,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -486,8 +468,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -512,8 +493,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -538,8 +518,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -564,8 +543,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -590,8 +568,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -616,8 +593,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -642,8 +618,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -668,8 +643,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -694,8 +668,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -720,8 +693,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -746,8 +718,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -796,8 +767,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -822,8 +792,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -848,8 +817,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -874,8 +842,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -900,8 +867,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -926,8 +892,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -952,8 +917,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -979,8 +943,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -1005,8 +968,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -1031,8 +993,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -1057,8 +1018,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -1083,8 +1043,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -1109,8 +1068,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -1135,8 +1093,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -1161,8 +1118,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] } diff --git a/AppInspector/rules/default/test_frameworks/objectiveC_testing.json b/AppInspector/rules/default/test_frameworks/objectiveC_testing.json index 12f2ceb4..ae379f78 100644 --- a/AppInspector/rules/default/test_frameworks/objectiveC_testing.json +++ b/AppInspector/rules/default/test_frameworks/objectiveC_testing.json @@ -12,7 +12,7 @@ "patterns": [ { "pattern": "GHUnit", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -67,8 +67,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -92,8 +91,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, diff --git a/AppInspector/rules/default/test_frameworks/powershell_testing.json b/AppInspector/rules/default/test_frameworks/powershell_testing.json index abbbfb35..ec784798 100644 --- a/AppInspector/rules/default/test_frameworks/powershell_testing.json +++ b/AppInspector/rules/default/test_frameworks/powershell_testing.json @@ -14,8 +14,7 @@ "pattern": "ester", "type": "string", "scopes": [ "code", "comment" ], - "modifiers": [ "i" ], - "_comment": "" + "modifiers": [ "i" ] } ] } diff --git a/AppInspector/rules/default/test_frameworks/python_testing.json b/AppInspector/rules/default/test_frameworks/python_testing.json index b514f855..21a3d7b5 100644 --- a/AppInspector/rules/default/test_frameworks/python_testing.json +++ b/AppInspector/rules/default/test_frameworks/python_testing.json @@ -19,8 +19,7 @@ "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, diff --git a/AppInspector/rules/default/tools/pipeline.json b/AppInspector/rules/default/tools/pipeline.json index 7a89f7aa..49e7f53b 100644 --- a/AppInspector/rules/default/tools/pipeline.json +++ b/AppInspector/rules/default/tools/pipeline.json @@ -13,8 +13,7 @@ "type": "string", "scopes": [ "code"], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -32,8 +31,7 @@ "type": "string", "scopes": [ "code"], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -51,8 +49,7 @@ "type": "string", "scopes": [ "code"], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -89,8 +86,7 @@ "type": "string", "scopes": [ "code"], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -108,8 +104,7 @@ "type": "string", "scopes": [ "code"], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -127,8 +122,7 @@ "type": "string", "scopes": [ "code"], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -146,8 +140,7 @@ "type": "string", "scopes": [ "code"], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -165,8 +158,7 @@ "type": "string", "scopes": [ "code"], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -184,8 +176,7 @@ "type": "string", "scopes": [ "code"], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -203,8 +194,7 @@ "type": "string", "scopes": [ "code"], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -222,8 +212,7 @@ "type": "string", "scopes": [ "code"], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] } diff --git a/AppInspector/rules/default/webapp/comms.json b/AppInspector/rules/default/webapp/comms.json index 764bf98a..d6b6e01e 100644 --- a/AppInspector/rules/default/webapp/comms.json +++ b/AppInspector/rules/default/webapp/comms.json @@ -26,8 +26,7 @@ "type": "regex", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -58,8 +57,7 @@ "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -89,8 +87,7 @@ "pattern": "EventSource", "type": "string", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] } diff --git a/AppInspector/rules/default/webapp/headers.json b/AppInspector/rules/default/webapp/headers.json index b20ebbd5..9116d76c 100644 --- a/AppInspector/rules/default/webapp/headers.json +++ b/AppInspector/rules/default/webapp/headers.json @@ -13,8 +13,7 @@ "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -32,8 +31,7 @@ "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -51,8 +49,7 @@ "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -70,8 +67,7 @@ "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -89,8 +85,7 @@ "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -108,8 +103,7 @@ "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -127,8 +121,7 @@ "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -146,8 +139,7 @@ "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -165,8 +157,7 @@ "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -184,8 +175,7 @@ "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -203,8 +193,7 @@ "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] } diff --git a/AppInspector/rules/default/webapp/media.json b/AppInspector/rules/default/webapp/media.json index 434419ee..5300474f 100644 --- a/AppInspector/rules/default/webapp/media.json +++ b/AppInspector/rules/default/webapp/media.json @@ -24,8 +24,7 @@ "pattern": "new AudioContext", "type": "string", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -54,8 +53,7 @@ "pattern": "getUserMedia|webkitGetUserMedia|mozGetUserMedia|msGetUserMedia", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] } diff --git a/AppInspector/rules/default/webapp/sessions.json b/AppInspector/rules/default/webapp/sessions.json index 94e7ee53..8eab3dd7 100644 --- a/AppInspector/rules/default/webapp/sessions.json +++ b/AppInspector/rules/default/webapp/sessions.json @@ -13,15 +13,14 @@ "type": "string", "modifiers": [ "i" ], "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ], "conditions": [ { "pattern": { "pattern": "cookie", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -29,8 +28,7 @@ "_comment": "" }, "search_in": "finding-region(-1,1)", - "negate_finding": false, - "_comment": "" + "negate_finding": false } ] }, @@ -48,15 +46,14 @@ "type": "string", "modifiers": [ "i" ], "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ], "conditions": [ { "pattern": { "pattern": "cookie", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -64,8 +61,7 @@ "_comment": "" }, "search_in": "finding-region(-1,1)", - "negate_finding": false, - "_comment": "" + "negate_finding": false } ] }, @@ -83,15 +79,14 @@ "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ], "conditions": [ { "pattern": { "pattern": "cookie", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -99,8 +94,7 @@ "_comment": "" }, "search_in": "finding-region(-1,1)", - "negate_finding": false, - "_comment": "" + "negate_finding": false } ] }, @@ -118,15 +112,14 @@ "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ], "conditions": [ { "pattern": { "pattern": "cookie", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -134,8 +127,7 @@ "_comment": "" }, "search_in": "finding-region(-1,1)", - "negate_finding": false, - "_comment": "" + "negate_finding": false } ] }, @@ -153,15 +145,14 @@ "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ], "conditions": [ { "pattern": { "pattern": "cookie", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -169,8 +160,7 @@ "_comment": "" }, "search_in": "finding-region(-1,1)", - "negate_finding": false, - "_comment": "" + "negate_finding": false } ] }, @@ -188,15 +178,14 @@ "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ], "conditions": [ { "pattern": { "pattern": "cookie", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -204,8 +193,7 @@ "_comment": "" }, "search_in": "finding-region(-1,1)", - "negate_finding": false, - "_comment": "" + "negate_finding": false } ] }, @@ -223,15 +211,14 @@ "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ], "conditions": [ { "pattern": { "pattern": "cookie", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], @@ -239,8 +226,7 @@ "_comment": "" }, "search_in": "finding-region(-1,1)", - "negate_finding": false, - "_comment": "" + "negate_finding": false } ] }, @@ -257,8 +243,7 @@ "pattern": "history\\.(pushState|replaceState)", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -275,8 +260,7 @@ "pattern": "new Worker", "type": "string", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] } diff --git a/AppInspector/rules/default/webapp/storage.json b/AppInspector/rules/default/webapp/storage.json index 641b1a2b..07471325 100644 --- a/AppInspector/rules/default/webapp/storage.json +++ b/AppInspector/rules/default/webapp/storage.json @@ -24,8 +24,7 @@ "pattern": "localstorage.setItem", "type": "string", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -54,8 +53,7 @@ "pattern": "sessionstorage.setItem", "type": "string", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -85,8 +83,7 @@ "type": "string", "scopes": [ "code" ], "modifiers": [ "i" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -115,8 +112,7 @@ "pattern": "indexedDB|mozIndexedDB|webkitIndexedDB|msIndexedDB", "type": "regex", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -145,8 +141,7 @@ "pattern": "new FileReader", "type": "string", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ] }, @@ -175,23 +170,21 @@ "pattern": "readAsDataURL", "type": "string", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ], "conditions": [ { "pattern": { "pattern": "FileReader", - "type": "regex-word", + "type": "regexword", "scopes": [ "code" ], "_comment": "" }, "search_in": "finding-region(-5,5)", - "negate_finding": false, - "_comment": "" + "negate_finding": false } ] }, @@ -220,8 +213,7 @@ "pattern": "fetch", "type": "string", "scopes": [ "code" ], - "confidence": "high", - "_comment": "" + "confidence": "high" } ], "conditions": [ @@ -236,8 +228,7 @@ "_comment": "" }, "search_in": "finding-region(-5,5)", - "negate_finding": false, - "_comment": "" + "negate_finding": false } ] } diff --git a/Benchmarks/AnalyzeBenchmark.cs b/Benchmarks/AnalyzeBenchmark.cs index dc2cd3bc..41fd37e7 100644 --- a/Benchmarks/AnalyzeBenchmark.cs +++ b/Benchmarks/AnalyzeBenchmark.cs @@ -10,37 +10,40 @@ namespace Benchmarks public class AnalyzeBenchmark { // Manually put the file you want to benchmark. But don't put this in a path with "Test" in the name ;) - private const string path = "C:\\Users\\gstocco\\Documents\\GitHub\\ApplicationInspector\\RulesEngine"; + private const string path = "C:\\Users\\gstocco\\Documents\\GitHub\\ApplicationInspector\\RulesEngine\\"; public AnalyzeBenchmark() { } - //[Benchmark(Baseline = true)] - //public void AnalyzeSingleThreaded() - //{ - // AnalyzeCommand command = new AnalyzeCommand(new AnalyzeOptions() - // { - // SourcePath = path, - // SingleThread = true, - // IgnoreDefaultRules = false - // }); + [Benchmark(Baseline = true)] + public static void AnalyzeSingleThreaded() + { + AnalyzeCommand command = new(new AnalyzeOptions() + { + SourcePath = new string[1] { path }, + SingleThread = true, + IgnoreDefaultRules = false, + FilePathExclusions = new string[] { "**/bin/**","**/obj/**" }, + NoShowProgress = true + }); - // AnalyzeResult analyzeResult = command.GetResult(); - //} + _ = command.GetResult(); + } [Benchmark] - public void AnalyzeMultiThread() + public static void AnalyzeMultiThread() { - AnalyzeCommand command = new AnalyzeCommand(new AnalyzeOptions() + AnalyzeCommand command = new(new AnalyzeOptions() { - SourcePath = path, + SourcePath = new string[1] { path }, SingleThread = false, IgnoreDefaultRules = false, - FilePathExclusions = "bin,obj" + FilePathExclusions = new string[] { "**/bin/**", "**/obj/**" }, + NoShowProgress = true }); - AnalyzeResult analyzeResult = command.GetResult(); + _ = command.GetResult(); } public static string GetExecutingDirectoryName() diff --git a/Benchmarks/Benchmarks.csproj b/Benchmarks/Benchmarks.csproj index 478f1116..cfd3d34a 100644 --- a/Benchmarks/Benchmarks.csproj +++ b/Benchmarks/Benchmarks.csproj @@ -6,8 +6,8 @@ - - + + diff --git a/README.md b/README.md index 4e2698fe..05914f2d 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ ERROR(S): tagdiff Compares unique tag values between two source paths - tagtest Test (T/F) for presence of custom rule set in source + gettags Checks the provided source for matching tags without additional analysis context exporttags Export unique rule tags to view what code features may be detected diff --git a/RulesEngine/AppInspector.RulesEngine.csproj b/RulesEngine/AppInspector.RulesEngine.csproj index 65a0f30a..1b8cbf1e 100644 --- a/RulesEngine/AppInspector.RulesEngine.csproj +++ b/RulesEngine/AppInspector.RulesEngine.csproj @@ -25,11 +25,11 @@ - - + + - + diff --git a/RulesEngine/Comment.cs b/RulesEngine/Comment.cs index 3fbd7a6d..1b336035 100644 --- a/RulesEngine/Comment.cs +++ b/RulesEngine/Comment.cs @@ -16,7 +16,7 @@ internal class Comment [JsonProperty(PropertyName = "inline")] public string? Inline { get; set; } - [JsonProperty(PropertyName = "preffix")] + [JsonProperty(PropertyName = "prefix")] public string? Prefix { get; set; } [JsonProperty(PropertyName = "suffix")] diff --git a/RulesEngine/Confidence.cs b/RulesEngine/Confidence.cs index 3b14ff5d..9f1db6c4 100644 --- a/RulesEngine/Confidence.cs +++ b/RulesEngine/Confidence.cs @@ -1,39 +1,10 @@ using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using System; namespace Microsoft.ApplicationInspector.RulesEngine { [Flags] - [JsonConverter(typeof(ConfidenceConverter))] + [JsonConverter(typeof(StringEnumConverter))] public enum Confidence { Unspecified = 0, Low = 1, Medium = 2, High = 4 } - - /// - /// Json converter for Pattern Type - /// - internal class ConfidenceConverter : JsonConverter - { - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - if (reader.Value is string enumString) - { - return Enum.Parse(typeof(Confidence), enumString, true); - } - - return null; - } - - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - if (value is Confidence svr) - { - string svrstr = svr.ToString().ToLower(); - writer.WriteValue(svrstr); - } - } - - public override bool CanConvert(Type objectType) - { - return objectType == typeof(string); - } - } } \ No newline at end of file diff --git a/RulesEngine/Language.cs b/RulesEngine/Language.cs index a97879be..0d69ce52 100644 --- a/RulesEngine/Language.cs +++ b/RulesEngine/Language.cs @@ -13,25 +13,25 @@ namespace Microsoft.ApplicationInspector.RulesEngine /// /// Helper class for language based commenting /// - public class Language + public sealed class Language { private static Language? _instance; - private List Comments; - private List Languages; + private readonly List Comments; + private readonly List Languages; private Language() { Assembly assembly = Assembly.GetExecutingAssembly(); // Load comments Stream? resource = assembly.GetManifestResourceStream("Microsoft.ApplicationInspector.RulesEngine.Resources.comments.json"); - using (StreamReader file = new StreamReader(resource ?? new MemoryStream())) + using (StreamReader file = new(resource ?? new MemoryStream())) { Comments = JsonConvert.DeserializeObject>(file.ReadToEnd()) ?? new List(); ; } // Load languages resource = assembly.GetManifestResourceStream("Microsoft.ApplicationInspector.RulesEngine.Resources.languages.json"); - using (StreamReader file = new StreamReader(resource ?? new MemoryStream())) + using (StreamReader file = new(resource ?? new MemoryStream())) { Languages = JsonConvert.DeserializeObject>(file.ReadToEnd()) ?? new List(); } @@ -163,12 +163,7 @@ private static Language Instance { get { - if (_instance == null) - { - _instance = new Language(); - } - - return _instance; + return _instance ??= new Language(); } } } diff --git a/RulesEngine/LanguageInfo.cs b/RulesEngine/LanguageInfo.cs index 8e4c737b..481ff3f7 100644 --- a/RulesEngine/LanguageInfo.cs +++ b/RulesEngine/LanguageInfo.cs @@ -21,6 +21,4 @@ public enum LangFileType { Code, Build }; [JsonProperty(PropertyName = "type")] public LangFileType Type { get; set; } = LangFileType.Code; } - - } \ No newline at end of file diff --git a/RulesEngine/MatchRecord.cs b/RulesEngine/MatchRecord.cs index 1fe5f9cd..228769e8 100644 --- a/RulesEngine/MatchRecord.cs +++ b/RulesEngine/MatchRecord.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. See LICENSE.txt in the project root for license information. using Newtonsoft.Json; +using System; namespace Microsoft.ApplicationInspector.RulesEngine { @@ -17,40 +18,52 @@ public class MatchRecord public MatchRecord(Rule rule) { Rule = rule; + RuleId = rule.Id; + RuleName = rule.Name; + RuleDescription = rule.Description; + Tags = rule.Tags; + Severity = rule.Severity; + } + + [JsonConstructor] + public MatchRecord(string ruleId, string ruleName) + { + RuleId = ruleId; + RuleName = ruleName; } [JsonIgnore] - public Rule Rule; + public Rule? Rule { get; set; } /// /// Rule Id found in matching rule /// [JsonProperty(PropertyName = "ruleId")] - public string RuleId => Rule.Id; + public string RuleId { get; set; } /// /// Rule name found in matching rule /// [JsonProperty(PropertyName = "ruleName")] - public string RuleName => Rule.Name; + public string RuleName { get; set; } /// /// Rule description found in matching rule /// [JsonProperty(PropertyName = "ruleDescription")] - public string? RuleDescription => Rule.Description; + public string? RuleDescription { get; set; } /// /// Tags in matching rule /// [JsonProperty(PropertyName = "tags")] - public string[]? Tags => Rule.Tags; + public string[]? Tags { get; set; } /// /// Rule severity /// _rule [JsonProperty(PropertyName = "severity")] - public Severity Severity => Rule.Severity; + public Severity Severity { get; set; } [JsonIgnore] public SearchPattern? MatchingPattern { get; set; } @@ -83,7 +96,7 @@ public MatchRecord(Rule rule) public TextContainer? FullTextContainer { get; set; } /// - /// Internal to namespace only + /// Internal to namespace only /// [JsonIgnore] public LanguageInfo LanguageInfo { get; set; } = new LanguageInfo(); diff --git a/RulesEngine/OatRegexWithIndexOp.cs b/RulesEngine/OatRegexWithIndexOp.cs index b3c71ee9..9972eb8e 100644 --- a/RulesEngine/OatRegexWithIndexOp.cs +++ b/RulesEngine/OatRegexWithIndexOp.cs @@ -17,7 +17,7 @@ namespace Microsoft.ApplicationInspector.RulesEngine /// public class OATRegexWithIndexOperation : OatOperation { - private readonly ConcurrentDictionary<(string, RegexOptions), Regex?> RegexCache = new ConcurrentDictionary<(string, RegexOptions), Regex?>(); + private readonly ConcurrentDictionary<(string, RegexOptions), Regex?> RegexCache = new(); /// /// Create an OatOperation given an analyzer @@ -30,7 +30,7 @@ public OATRegexWithIndexOperation(Analyzer analyzer) : base(Operation.Custom, an ValidationDelegate = RegexWithIndexValidationDelegate; } - public IEnumerable RegexWithIndexValidationDelegate(CST.OAT.Rule rule, Clause clause) + public static IEnumerable RegexWithIndexValidationDelegate(CST.OAT.Rule rule, Clause clause) { if (clause.Data?.Count == null || clause.Data?.Count == 0) { @@ -53,7 +53,7 @@ public IEnumerable RegexWithIndexValidationDelegate(CST.OAT.Rule rule } /// - /// Returns results with pattern index and Boundary as a tuple to enable retrieval of Rule pattern level meta-data like Confidence and report the + /// Returns results with pattern index and Boundary as a tuple to enable retrieval of Rule pattern level meta-data like Confidence and report the /// pattern that was responsible for the match /// /// @@ -63,59 +63,51 @@ public IEnumerable RegexWithIndexValidationDelegate(CST.OAT.Rule rule /// public OperationResult RegexWithIndexOperationDelegate(Clause clause, object? state1, object? state2, IEnumerable? captures) { - if (state1 is TextContainer tc && clause is OATRegexWithIndexClause src) + if (state1 is TextContainer tc && clause is OATRegexWithIndexClause src && clause.Data is List RegexList && RegexList.Count > 0) { - if (clause.Data is List RegexList && RegexList.Any()) + RegexOptions regexOpts = new(); + + if (src.Arguments.Contains("i")) { - RegexOptions regexOpts = new RegexOptions(); - if (src.Arguments.Contains("i")) - { - regexOpts |= RegexOptions.IgnoreCase; - } - if (src.Arguments.Contains("m")) - { - regexOpts |= RegexOptions.Multiline; - } + regexOpts |= RegexOptions.IgnoreCase; + } + if (src.Arguments.Contains("m")) + { + regexOpts |= RegexOptions.Multiline; + } + + List<(int, Boundary)> outmatches = new();//tuple results i.e. pattern index and where - var outmatches = new List<(int, Boundary)>();//tuple results i.e. pattern index and where + if (Analyzer != null) + { + var regex = StringToRegex(string.Join('|', RegexList), regexOpts); - if (Analyzer != null) + if (regex != null) { - for (int i = 0; i < RegexList.Count; i++) + foreach (var match in regex.Matches(tc.FullContent)) { - var regex = StringToRegex(RegexList[i], regexOpts); - if (regex != null) + if (match is Match m) { - var matches = regex.Matches(tc.Target); - if (matches.Count > 0 || (matches.Count == 0 && clause.Invert)) + Boundary translatedBoundary = new() { - foreach (var match in matches) - { - if (match is Match m) - { - Boundary translatedBoundary = new Boundary() - { - Length = m.Length, - Index = m.Index + tc.GetLineBoundary(tc.LineNumber).Index - }; + Length = m.Length, + Index = m.Index + }; - //regex patterns will be indexed off data while string patterns result in N clauses - int patternIndex = clause.Label == "0" ? i : Convert.ToInt32(clause.Label); + //regex patterns will be indexed off data while string patterns result in N clauses + int patternIndex = Convert.ToInt32(clause.Label); - // Should return only scoped matches - if (tc.ScopeMatch(src.Scopes, translatedBoundary)) - { - outmatches.Add((patternIndex, translatedBoundary)); - } - } - } + // Should return only scoped matches + if (tc.ScopeMatch(src.Scopes, translatedBoundary)) + { + outmatches.Add((patternIndex, translatedBoundary)); } } } - - var result = src.Invert ? outmatches.Count == 0 : outmatches.Count > 0; - return new OperationResult(result, result && src.Capture ? new TypedClauseCapture>(clause, outmatches, state1) : null); } + + var result = src.Invert ? outmatches.Count == 0 : outmatches.Count > 0; + return new OperationResult(result, result && src.Capture ? new TypedClauseCapture>(clause, outmatches, state1) : null); } } return new OperationResult(false, null); diff --git a/RulesEngine/OatSubstringIndexOperation.cs b/RulesEngine/OatSubstringIndexOperation.cs index 04a93653..d44a6020 100644 --- a/RulesEngine/OatSubstringIndexOperation.cs +++ b/RulesEngine/OatSubstringIndexOperation.cs @@ -28,7 +28,7 @@ public OATSubstringIndexOperation(Analyzer analyzer) : base(Operation.Custom, an ValidationDelegate = SubstringIndexValidationDelegate; } - public IEnumerable SubstringIndexValidationDelegate(CST.OAT.Rule rule, Clause clause) + public static IEnumerable SubstringIndexValidationDelegate(CST.OAT.Rule rule, Clause clause) { if (clause.Data?.Count == null || clause.Data?.Count == 0) { @@ -41,7 +41,7 @@ public IEnumerable SubstringIndexValidationDelegate(CST.OAT.Rule rule } /// - /// Returns results with pattern index and Boundary as a tuple to enable retrieval of Rule pattern level meta-data like Confidence and report the + /// Returns results with pattern index and Boundary as a tuple to enable retrieval of Rule pattern level meta-data like Confidence and report the /// pattern that was responsible for the match /// /// @@ -49,12 +49,12 @@ public IEnumerable SubstringIndexValidationDelegate(CST.OAT.Rule rule /// /// /// - public OperationResult SubstringIndexOperationDelegate(Clause clause, object? state1, object? state2, IEnumerable? captures) + public static OperationResult SubstringIndexOperationDelegate(Clause clause, object? state1, object? state2, IEnumerable? captures) { var comparisonType = clause.Arguments.Contains("i") ? StringComparison.InvariantCultureIgnoreCase : StringComparison.InvariantCulture; if (state1 is TextContainer tc && clause is OATSubstringIndexClause src) { - if (clause.Data is List stringList && stringList.Any()) + if (clause.Data is List stringList && stringList.Count > 0) { var outmatches = new List<(int, Boundary)>();//tuple results i.e. pattern index and where @@ -77,7 +77,7 @@ public OperationResult SubstringIndexOperationDelegate(Clause clause, object? st } if (!skip) { - Boundary newBoundary = new Boundary() + Boundary newBoundary = new() { Length = stringList[i].Length, Index = idx diff --git a/RulesEngine/PatternScope.cs b/RulesEngine/PatternScope.cs index 50d17049..363052f7 100644 --- a/RulesEngine/PatternScope.cs +++ b/RulesEngine/PatternScope.cs @@ -1,12 +1,13 @@ // Copyright (C) Microsoft. All rights reserved. Licensed under the MIT License. using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using System; using System.Globalization; namespace Microsoft.ApplicationInspector.RulesEngine { - [JsonConverter(typeof(PatternScopeConverter))] + [JsonConverter(typeof(StringEnumConverter))] public enum PatternScope { All, @@ -14,37 +15,4 @@ public enum PatternScope Comment, Html } - - /// - /// Json converter for Pattern Type - /// - internal class PatternScopeConverter : JsonConverter - { - public override bool CanConvert(Type objectType) - { - return objectType == typeof(string); - } - - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - if (reader.Value is string enumString) - { - enumString = enumString.Replace("-", ""); - return Enum.Parse(typeof(PatternScope), enumString, true); - } - // TODO: Should there be a separate enum value for finding a null here? - return null; - } - - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - if (value is PatternScope svr) - { - string svrstr = svr.ToString().ToLower(CultureInfo.InvariantCulture); - - writer.WriteValue(svrstr); - writer.WriteValue(svr.ToString().ToLower(CultureInfo.InvariantCulture)); - } - } - } } \ No newline at end of file diff --git a/RulesEngine/PatternType.cs b/RulesEngine/PatternType.cs index c8a6809a..3e324e38 100644 --- a/RulesEngine/PatternType.cs +++ b/RulesEngine/PatternType.cs @@ -1,6 +1,7 @@ // Copyright (C) Microsoft. All rights reserved. Licensed under the MIT License. using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using System; using System.Globalization; @@ -9,6 +10,7 @@ namespace Microsoft.ApplicationInspector.RulesEngine /// /// Pattern Type for search pattern /// + [JsonConverter(typeof(StringEnumConverter))] public enum PatternType { Regex, @@ -16,41 +18,4 @@ public enum PatternType String, Substring } - - /// - /// Json converter for Pattern Type - /// - internal class PatternTypeConverter : JsonConverter - { - public override bool CanConvert(Type objectType) - { - return objectType == typeof(string); - } - - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - if (reader.Value is string enumString) - { - enumString = enumString.Replace("-", ""); - return Enum.Parse(typeof(PatternType), enumString, true); - } - return null; - } - - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - if (value is PatternType svr) - { - string svrstr = svr.ToString().ToLower(CultureInfo.InvariantCulture); - - switch (svr) - { - case PatternType.RegexWord: - svrstr = "regex-word"; - break; - } - writer.WriteValue(svrstr); - } - } - } } \ No newline at end of file diff --git a/RulesEngine/Resources/comments.json b/RulesEngine/Resources/comments.json index 689c0500..3240ef3f 100644 --- a/RulesEngine/Resources/comments.json +++ b/RulesEngine/Resources/comments.json @@ -18,7 +18,7 @@ "php" ], "inline": "//", - "preffix": "/*", + "prefix": "/*", "suffix": "*/" }, { @@ -32,33 +32,25 @@ "powershell", "python" ], - "inline": "#", - "preffix": "#", - "suffix": "\n" + "inline": "#" }, { "language": [ "lua", "sql" ], - "inline": "--", - "preffix": "--", - "suffix": "\n" + "inline": "--" }, { "language": [ "clojure" ], - "inline": ";;", - "preffix": ";;", - "suffix": "" + "inline": ";;" }, { "language": [ "vb" ], - "inline": "'", - "preffix": "'", - "suffix": "" + "inline": "'" } ] \ No newline at end of file diff --git a/RulesEngine/Rule.cs b/RulesEngine/Rule.cs index 1b81ea1b..3adf42c4 100644 --- a/RulesEngine/Rule.cs +++ b/RulesEngine/Rule.cs @@ -82,14 +82,13 @@ public IEnumerable CompiledFileRegexes public string[]? Tags { get; set; } [JsonProperty(PropertyName = "severity")] - [JsonConverter(typeof(SeverityConverter))] public Severity Severity { get; set; } = Severity.Moderate; [JsonProperty(PropertyName = "overrides")] public string[]? Overrides { get; set; } [JsonProperty(PropertyName = "patterns")] - public SearchPattern[] Patterns { get; set; } = new SearchPattern[] { }; + public SearchPattern[] Patterns { get; set; } = Array.Empty(); [JsonProperty(PropertyName = "conditions")] public SearchCondition[]? Conditions { get; set; } diff --git a/RulesEngine/RuleProcessor.cs b/RulesEngine/RuleProcessor.cs index 00c9e479..86bf398e 100644 --- a/RulesEngine/RuleProcessor.cs +++ b/RulesEngine/RuleProcessor.cs @@ -5,6 +5,7 @@ using Microsoft.CST.RecursiveExtractor; using NLog; using System; +using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; @@ -20,9 +21,8 @@ public class RuleProcessorOptions { public RuleProcessorOptions() { - } - + public bool Parallel = true; public Confidence confidenceFilter; public Logger? logger; public bool treatEverythingAsCode = false; @@ -35,24 +35,24 @@ public class RuleProcessor { private readonly int MAX_TEXT_SAMPLE_LENGTH = 200;//char bytes - private Confidence ConfidenceLevelFilter { get; set; } + private Confidence ConfidenceLevelFilter { get; } private readonly Logger? _logger; private readonly bool _treatEverythingAsCode; private readonly Analyzer analyzer; private readonly RuleSet _ruleset; - private readonly ConcurrentDictionary> _fileRulesCache = new ConcurrentDictionary>(); - private readonly ConcurrentDictionary> _languageRulesCache = new ConcurrentDictionary>(); - private IEnumerable? _universalRulesCache = null; + private readonly ConcurrentDictionary> _fileRulesCache = new(); + private readonly ConcurrentDictionary> _languageRulesCache = new(); + private IEnumerable? _universalRulesCache; /// /// Sets severity levels for analysis /// - private Severity SeverityLevel { get; set; } + private Severity SeverityLevel { get; } /// /// Enables caching of rules queries if multiple reuses per instance /// - private bool EnableCache { get; set; } + private bool EnableCache { get; } /// /// Creates instance of RuleProcessor @@ -66,14 +66,13 @@ public RuleProcessor(RuleSet rules, RuleProcessorOptions opts) ConfidenceLevelFilter = opts.confidenceFilter; SeverityLevel = Severity.Critical | Severity.Important | Severity.Moderate | Severity.BestPractice; //finds all; arg not currently supported - analyzer = new Analyzer(); + analyzer = new Analyzer(new AnalyzerOptions(false, opts.Parallel)); analyzer.SetOperation(new WithinOperation(analyzer)); analyzer.SetOperation(new OATRegexWithIndexOperation(analyzer)); analyzer.SetOperation(new OATSubstringIndexOperation(analyzer)); } - - private string ExtractDependency(TextContainer? text, int startIndex, string? pattern, string? language) + private static string ExtractDependency(TextContainer? text, int startIndex, string? pattern, string? language) { if (text is null || string.IsNullOrEmpty(text.FullContent) || string.IsNullOrEmpty(language) || string.IsNullOrEmpty(pattern)) { @@ -84,12 +83,12 @@ private string ExtractDependency(TextContainer? text, int startIndex, string? pa int endIndex = text.FullContent.IndexOfAny(new char[] { '\n', '\r' }, startIndex); if (-1 != startIndex && -1 != endIndex) { - rawResult = text.FullContent.Substring(startIndex, endIndex - startIndex).Trim(); - Regex regex = new Regex(pattern ?? string.Empty); + rawResult = text.FullContent[startIndex..endIndex].Trim(); + Regex regex = new(pattern ?? string.Empty); MatchCollection matches = regex.Matches(rawResult); //remove surrounding import or trailing comments - if (matches != null && matches.Any()) + if (matches?.Any() == true) { foreach (Match? match in matches) { @@ -128,15 +127,15 @@ public List AnalyzeFile(string contents, FileEntry fileEntry, Langu var rulesByLanguage = GetRulesByLanguage(languageInfo.Name).Where(x => !x.AppInspectorRule.Disabled && SeverityLevel.HasFlag(x.AppInspectorRule.Severity)); var rules = rulesByLanguage.Union(GetRulesByFileName(fileEntry.FullPath).Where(x => !x.AppInspectorRule.Disabled && SeverityLevel.HasFlag(x.AppInspectorRule.Severity))); rules = rules.Union(GetUniversalRules()); - if (tagsToIgnore is not null && tagsToIgnore.Any()) + if (tagsToIgnore?.Any() == true) { rules = rules.Where(x => x.Tags.Any(y => !tagsToIgnore.Contains(y))); } - List resultsList = new List(); + List resultsList = new(); - TextContainer textContainer = new TextContainer(contents, languageInfo.Name); - - foreach (var ruleCapture in analyzer.GetCaptures(rules, textContainer)) + TextContainer textContainer = new(contents, languageInfo.Name); + var caps = analyzer.GetCaptures(rules, textContainer).ToList(); + foreach (var ruleCapture in caps) { foreach (var cap in ruleCapture.Captures) { @@ -145,7 +144,7 @@ public List AnalyzeFile(string contents, FileEntry fileEntry, Langu List ProcessBoundary(ClauseCapture cap) { - List newMatches = new List();//matches for this rule clause only + List newMatches = new();//matches for this rule clause only if (cap is TypedClauseCapture> tcc) { @@ -164,12 +163,6 @@ List ProcessBoundary(ClauseCapture cap) continue; } - if (patternIndex < 0 || patternIndex > oatRule.AppInspectorRule.Patterns.Length) - { - _logger?.Error("Index out of range for patterns for rule: " + oatRule.AppInspectorRule.Name); - continue; - } - if (!ConfidenceLevelFilter.HasFlag(oatRule.AppInspectorRule.Patterns[patternIndex].Confidence)) { continue; @@ -177,7 +170,7 @@ List ProcessBoundary(ClauseCapture cap) Location StartLocation = textContainer.GetLocation(boundary.Index); Location EndLocation = textContainer.GetLocation(boundary.Index + boundary.Length); - MatchRecord newMatch = new MatchRecord(oatRule.AppInspectorRule) + MatchRecord newMatch = new(oatRule.AppInspectorRule) { FileName = fileEntry.FullPath, FullTextContainer = textContainer, @@ -206,22 +199,19 @@ List ProcessBoundary(ClauseCapture cap) } } - List removes = new List(); + List removes = new(); - foreach (MatchRecord m in resultsList.Where(x => x.Rule.Overrides != null && x.Rule.Overrides.Length > 0)) + foreach (MatchRecord m in resultsList.Where(x => x.Rule.Overrides?.Length > 0)) { - if (m.Rule.Overrides != null && m.Rule.Overrides.Length > 0) + foreach (string ovrd in m.Rule?.Overrides ?? Array.Empty()) { - foreach (string ovrd in m.Rule.Overrides) + // Find all overriden rules and mark them for removal from issues list + foreach (MatchRecord om in resultsList.FindAll(x => x.Rule.Id == ovrd)) { - // Find all overriden rules and mark them for removal from issues list - foreach (MatchRecord om in resultsList.FindAll(x => x.Rule.Id == ovrd)) + if (om.Boundary?.Index >= m.Boundary?.Index && + om.Boundary?.Index <= m.Boundary?.Index + m.Boundary?.Length) { - if (om.Boundary?.Index >= m.Boundary?.Index && - om.Boundary?.Index <= m.Boundary?.Index + m.Boundary?.Length) - { - removes.Add(om); - } + removes.Add(om); } } } @@ -245,17 +235,16 @@ public async Task> AnalyzeFileAsync(FileEntry fileEntry, Langu var rules = rulesByLanguage.Union(GetRulesByFileName(fileEntry.FullPath).Where(x => !x.AppInspectorRule.Disabled && SeverityLevel.HasFlag(x.AppInspectorRule.Severity))); rules = rules.Union(GetUniversalRules()); - if (tagsToIgnore is not null && tagsToIgnore.Any()) + if (tagsToIgnore?.Any() == true) { rules = rules.Where(x => x.Tags.Any(y => !tagsToIgnore.Contains(y))); } - List resultsList = new List(); + List resultsList = new(); using var sr = new StreamReader(fileEntry.Content); - TextContainer textContainer = new TextContainer(await sr.ReadToEndAsync(), languageInfo.Name); - + TextContainer textContainer = new(await sr.ReadToEndAsync().ConfigureAwait(false), languageInfo.Name); foreach (var ruleCapture in analyzer.GetCaptures(rules, textContainer)) { if (cancellationToken.IsCancellationRequested) @@ -269,7 +258,7 @@ public async Task> AnalyzeFileAsync(FileEntry fileEntry, Langu List ProcessBoundary(ClauseCapture cap) { - List newMatches = new List();//matches for this rule clause only + List newMatches = new();//matches for this rule clause only if (cap is TypedClauseCapture> tcc) { @@ -301,7 +290,7 @@ List ProcessBoundary(ClauseCapture cap) Location StartLocation = textContainer.GetLocation(boundary.Index); Location EndLocation = textContainer.GetLocation(boundary.Index + boundary.Length); - MatchRecord newMatch = new MatchRecord(oatRule.AppInspectorRule) + MatchRecord newMatch = new(oatRule.AppInspectorRule) { FileName = fileEntry.FullPath, FullTextContainer = textContainer, @@ -328,26 +317,23 @@ List ProcessBoundary(ClauseCapture cap) } } - List removes = new List(); + List removes = new(); - foreach (MatchRecord m in resultsList.Where(x => x.Rule.Overrides != null && x.Rule.Overrides.Length > 0)) + foreach (MatchRecord m in resultsList.Where(x => x.Rule.Overrides?.Length > 0)) { if (cancellationToken.IsCancellationRequested) { return resultsList; } - if (m.Rule.Overrides != null && m.Rule.Overrides.Length > 0) + foreach (string ovrd in m.Rule?.Overrides ?? Array.Empty()) { - foreach (string ovrd in m.Rule.Overrides) + // Find all overriden rules and mark them for removal from issues list + foreach (MatchRecord om in resultsList.FindAll(x => x.Rule.Id == ovrd)) { - // Find all overriden rules and mark them for removal from issues list - foreach (MatchRecord om in resultsList.FindAll(x => x.Rule.Id == ovrd)) + if (om.Boundary?.Index >= m.Boundary?.Index && + om.Boundary?.Index <= m.Boundary?.Index + m.Boundary?.Length) { - if (om.Boundary?.Index >= m.Boundary?.Index && - om.Boundary?.Index <= m.Boundary?.Index + m.Boundary?.Length) - { - removes.Add(om); - } + removes.Add(om); } } } @@ -359,21 +345,6 @@ List ProcessBoundary(ClauseCapture cap) return resultsList; } - /// - /// Analyzes given line of code returning matching scan results for the - /// file passed in only; Use AllResults to get results across the entire set - /// - /// Source code - /// List of languages - /// Array of matches - public List AnalyzeFile(string filePath, string text, LanguageInfo languageInfo) - { - using var ms = new MemoryStream(Encoding.UTF8.GetBytes(text)); - var entry = new FileEntry(filePath, ms); - return AnalyzeFile(entry, languageInfo); - } - - #region Private Support Methods /// @@ -465,7 +436,7 @@ private string ExtractTextSample(string fileText, int index, int length) /// from the template /// /// - private string ExtractExcerpt(TextContainer text, int startLineNumber, int context = 3) + private static string ExtractExcerpt(TextContainer text, int startLineNumber, int context = 3) { if (context == 0) { diff --git a/RulesEngine/Ruleset.cs b/RulesEngine/Ruleset.cs index 27ecedb2..205ea453 100644 --- a/RulesEngine/Ruleset.cs +++ b/RulesEngine/Ruleset.cs @@ -12,17 +12,15 @@ using System.Text; using System.Text.RegularExpressions; - namespace Microsoft.ApplicationInspector.RulesEngine { /// /// Storage for rules /// - /// public class RuleSet : IEnumerable { private readonly Logger? _logger; - private List _oatRules = new List();//used for analyze cmd primarily + private List _oatRules = new();//used for analyze cmd primarily private IEnumerable _rules { get => _oatRules.Select(x => x.AppInspectorRule); } private Regex searchInRegex = new Regex("\\((.*),(.*)\\)", RegexOptions.Compiled); @@ -34,19 +32,6 @@ public RuleSet(Logger? log) _logger = log; } - /// - /// Delegate for deserialization error handler - /// - /// Sender object - /// Error arguments - public delegate void DeserializationError(object? sender, Newtonsoft.Json.Serialization.ErrorEventArgs e); - - /// - /// Event raised if deserialization error is encoutered while loading JSON rules - /// - public event DeserializationError? OnDeserializationError; - - /// /// Parse a directory with rule files and loads the rules /// @@ -71,17 +56,15 @@ public void AddDirectory(string path, string? tag = null) public void AddFile(string? filename, string? tag = null) { if (string.IsNullOrEmpty(filename)) - throw new ArgumentException(nameof(filename)); + throw new ArgumentException(null, nameof(filename)); _logger?.Debug("Attempting to read rule file: " + filename); if (!File.Exists(filename)) throw new FileNotFoundException(); - using (StreamReader file = File.OpenText(filename)) - { - AddString(file.ReadToEnd(), filename, tag); - } + using StreamReader file = File.OpenText(filename); + AddString(file.ReadToEnd(), filename, tag); } /// @@ -161,7 +144,6 @@ public IEnumerable GetUniversalRules() return _oatRules.Where(x => (x.AppInspectorRule.FileRegexes is null || x.AppInspectorRule.FileRegexes.Length == 0) && (x.AppInspectorRule.AppliesTo is null || x.AppInspectorRule.AppliesTo.Length == 0)); } - public ConvertedOatRule? AppInspectorRuleToOatRule(Rule rule) { var clauses = new List(); @@ -175,60 +157,60 @@ public IEnumerable GetUniversalRules() var modifiers = pattern.Modifiers ?? Array.Empty(); if (pattern.PatternType == PatternType.String || pattern.PatternType == PatternType.Substring) { - if (clauses.Where(x => x is OATSubstringIndexClause src && - src.Arguments.SequenceEqual(modifiers) && src.Scopes.SequenceEqual(scopes) && src.UseWordBoundaries) is IEnumerable filteredClauses && - filteredClauses.Any() && filteredClauses.First().Data is List found) + clauses.Add(new OATSubstringIndexClause(scopes, useWordBoundaries: pattern.PatternType == PatternType.String) { - found.Add(pattern.Pattern); - } - else + Label = clauseNumber.ToString(CultureInfo.InvariantCulture),//important to pattern index identification + Data = new List() { pattern.Pattern }, + Capture = true + }); + if (clauseNumber > 0) { - clauses.Add(new OATSubstringIndexClause(scopes, useWordBoundaries: pattern.PatternType == PatternType.String) - { - Label = clauseNumber.ToString(CultureInfo.InvariantCulture),//important to pattern index identification - Data = new List() { pattern.Pattern }, - Capture = true - }); - if (clauseNumber > 0) - { - expression.Append(" OR "); - } - expression.Append(clauseNumber); - clauseNumber++; + expression.Append(" OR "); } + expression.Append(clauseNumber); + clauseNumber++; } - else + else if (pattern.PatternType == PatternType.Regex) { - if (clauses.Where(x => x is OATRegexWithIndexClause src && - src.Arguments.SequenceEqual(modifiers) && src.Scopes.SequenceEqual(scopes)) is IEnumerable filteredClauses && - filteredClauses.Any() && filteredClauses.First().Data is List found) + clauses.Add(new OATRegexWithIndexClause(scopes) + { + Label = clauseNumber.ToString(CultureInfo.InvariantCulture),//important to pattern index identification + Data = new List() { pattern.Pattern }, + Capture = true, + Arguments = pattern.Modifiers?.ToList() ?? new List(), + CustomOperation = "RegexWithIndex" + }); + if (clauseNumber > 0) { - found.Add(pattern.Pattern); + expression.Append(" OR "); } - else + expression.Append(clauseNumber); + clauseNumber++; + } + else if (pattern.PatternType == PatternType.RegexWord) + { + clauses.Add(new OATRegexWithIndexClause(scopes) { - clauses.Add(new OATRegexWithIndexClause(scopes) - { - Label = clauseNumber.ToString(CultureInfo.InvariantCulture),//important to pattern index identification - Data = new List() { pattern.Pattern }, - Capture = true, - Arguments = pattern.Modifiers?.ToList() ?? new List(), - CustomOperation = "RegexWithIndex" - }); - if (clauseNumber > 0) - { - expression.Append(" OR "); - } - expression.Append(clauseNumber); - clauseNumber++; + Label = clauseNumber.ToString(CultureInfo.InvariantCulture),//important to pattern index identification + Data = new List() { $"\\b({pattern.Pattern})\\b" }, + Capture = true, + Arguments = pattern.Modifiers?.ToList() ?? new List(), + CustomOperation = "RegexWithIndex" + }); + + if (clauseNumber > 0) + { + expression.Append(" OR "); } + expression.Append(clauseNumber); + clauseNumber++; } } } - if (clauses.Any()) + if (clauses.Count > 0) { - expression.Append(")"); + expression.Append(')'); } else { @@ -239,7 +221,7 @@ public IEnumerable GetUniversalRules() { if (condition.Pattern?.Pattern != null) { - if (condition.SearchIn is null || condition.SearchIn.Equals("finding-only", StringComparison.InvariantCultureIgnoreCase)) + if (condition.SearchIn?.Equals("finding-only", StringComparison.InvariantCultureIgnoreCase) != false) { clauses.Add(new WithinClause() { @@ -343,12 +325,7 @@ IEnumerator IEnumerable.GetEnumerator() internal IEnumerable StringToRules(string jsonstring, string sourcename, string? tag = null) { - JsonSerializerSettings settings = new JsonSerializerSettings() - { - Error = HandleDeserializationError - }; - - List? ruleList = JsonConvert.DeserializeObject>(jsonstring, settings); + List? ruleList = JsonConvert.DeserializeObject>(jsonstring); if (ruleList is List) { foreach (Rule r in ruleList) @@ -357,49 +334,9 @@ internal IEnumerable StringToRules(string jsonstring, string sourcename, s r.RuntimeTag = tag ?? ""; if (r.Patterns == null) r.Patterns = Array.Empty(); - - foreach (SearchPattern pattern in r.Patterns) - { - SanitizePatternRegex(pattern); - } - - if (r.Conditions == null) - r.Conditions = Array.Empty(); - - foreach (SearchCondition condition in r.Conditions) - { - if (condition.Pattern is { }) - { - SanitizePatternRegex(condition.Pattern); - } - } - yield return r; } } } - - /// - /// Handler for deserialization error - /// - /// Sender object - /// Error arguments - private void HandleDeserializationError(object? sender, Newtonsoft.Json.Serialization.ErrorEventArgs errorArgs) - { - OnDeserializationError?.Invoke(sender, errorArgs); - } - - /// - /// Method santizes pattern to be a valid regex - /// - /// - private static void SanitizePatternRegex(SearchPattern pattern) - { - if (pattern.PatternType == PatternType.RegexWord) - { - pattern.PatternType = PatternType.Regex; - pattern.Pattern = string.Format(CultureInfo.InvariantCulture, @"\b{0}\b", pattern.Pattern); - } - } } } diff --git a/RulesEngine/SearchPattern.cs b/RulesEngine/SearchPattern.cs index eaf083bc..b9380937 100644 --- a/RulesEngine/SearchPattern.cs +++ b/RulesEngine/SearchPattern.cs @@ -35,7 +35,6 @@ public class SearchPattern } [JsonProperty(PropertyName = "type")] - [JsonConverter(typeof(PatternTypeConverter))] public PatternType? PatternType { get; set; } [JsonProperty(PropertyName = "scopes")] diff --git a/RulesEngine/Severity.cs b/RulesEngine/Severity.cs index 36a91a2c..b002b138 100644 --- a/RulesEngine/Severity.cs +++ b/RulesEngine/Severity.cs @@ -1,6 +1,7 @@ // Copyright (C) Microsoft. All rights reserved. Licensed under the MIT License. using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using System; namespace Microsoft.ApplicationInspector.RulesEngine @@ -9,7 +10,7 @@ namespace Microsoft.ApplicationInspector.RulesEngine /// Issue severity /// [Flags] - [JsonConverter(typeof(SeverityConverter))] + [JsonConverter(typeof(StringEnumConverter))] public enum Severity { /// @@ -37,46 +38,4 @@ public enum Severity /// ManualReview = 16 } - - /// - /// Json Converter for Severity - /// - internal class SeverityConverter : JsonConverter - { - public override bool CanConvert(Type objectType) - { - return objectType == typeof(string); - } - - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - if (reader.Value is string enumString) - { - enumString = enumString.Replace("-", ""); - return Enum.Parse(typeof(Severity), enumString, true); - } - return null; - } - - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - if (value is Severity svr) - { - string svrstr = svr.ToString().ToLower(); - - switch (svr) - { - case Severity.BestPractice: - svrstr = "best-practice"; - break; - - case Severity.ManualReview: - svrstr = "manual-review"; - break; - } - - writer.WriteValue(svrstr); - } - } - } } \ No newline at end of file diff --git a/RulesEngine/TextContainer.cs b/RulesEngine/TextContainer.cs index 3af0fb6e..c2f1ea2d 100644 --- a/RulesEngine/TextContainer.cs +++ b/RulesEngine/TextContainer.cs @@ -1,6 +1,8 @@ // Copyright (C) Microsoft. All rights reserved. Licensed under the MIT License. using System; +using System.Collections; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; @@ -11,87 +13,144 @@ namespace Microsoft.ApplicationInspector.RulesEngine /// public class TextContainer { - public List LineEnds; - /// /// Creates new instance /// /// Text to work with /// The language of the test /// The line number to specify. Leave empty for full file as target. - public TextContainer(string content, string language, int lineNumber = 0) + public TextContainer(string content, string language) { Language = language; - LineNumber = lineNumber; FullContent = content; - Target = LineNumber == 0 ? FullContent : GetLineContent(lineNumber); LineEnds = new List() { 0 }; LineStarts = new List() { 0, 0 }; // Find line end in the text - int pos = 0; - while (pos > -1 && pos < FullContent.Length) + int pos = FullContent.IndexOf('\n'); + while (pos > -1) { - if (++pos < FullContent.Length) + LineEnds.Add(pos); + + if (pos > 0 && pos + 1 < FullContent.Length) { - pos = FullContent.IndexOf("\n", pos, StringComparison.InvariantCultureIgnoreCase); - LineEnds.Add(pos); - if (pos > 0 && pos + 1 < FullContent.Length) - { - LineStarts.Add(pos + 1); - } + LineStarts.Add(pos + 1); } + pos = FullContent.IndexOf('\n', pos + 1); } - // Text can end with \n or not - if (LineEnds[LineEnds.Count - 1] == -1) - LineEnds[LineEnds.Count - 1] = (FullContent.Length > 0) ? FullContent.Length - 1 : 0; + if (LineEnds.Count < LineStarts.Count) + { + LineEnds.Add(FullContent.Length - 1); + } prefix = RulesEngine.Language.GetCommentPrefix(Language); suffix = RulesEngine.Language.GetCommentSuffix(Language); inline = RulesEngine.Language.GetCommentInline(Language); } + /// + /// The full string of the TextContainer representes. + /// public string FullContent { get; } + /// + /// The code language of the file + /// public string Language { get; } - public string Line { get; } = ""; - public int LineNumber { get; } + /// + /// One-indexed array of the character indexes of the ends of the lines in FullContent. + /// + public List LineEnds { get; } + /// + /// One-indexed array of the character indexes of the starts of the lines in FullContent. + /// public List LineStarts { get; } - public string Target { get; } /// - /// Returns the Boundary of a specified line number + /// A dictionary mapping character index in FullContent to if a specific character is commented. See IsCommented to use. /// - /// The line number to return the boundary for - /// - public Boundary GetBoundaryFromLine(int lineNumber) - { - Boundary result = new Boundary(); + private ConcurrentDictionary CommentedStates { get; } = new(); - if (lineNumber >= LineEnds.Count) + /// + /// Populates the CommentedStates Dictionary based on the index and the provided comment prefix and suffix + /// + /// The character index in FullContent + /// The comment prefix + /// The comment suffix + private void PopulateCommentedStatesInternal(int index, string prefix, string suffix) + { + var prefixLoc = FullContent.LastIndexOf(prefix, index, StringComparison.Ordinal); + if (prefixLoc != -1) { - return result; + if (!CommentedStates.ContainsKey(prefixLoc)) + { + var suffixLoc = FullContent.IndexOf(suffix, prefixLoc, StringComparison.Ordinal); + if (suffixLoc == -1) + { + suffixLoc = FullContent.Length - 1; + } + for (int i = prefixLoc; i <= suffixLoc; i++) + { + CommentedStates[i] = true; + } + } } + } - // Fine when the line number is 0 - var start = 0; - if (lineNumber > 0) + /// + /// Populate the CommentedStates Dictionary based on the provided index. + /// + /// The character index in FullContent to work based on. + public void PopulateCommentedState(int index) + { + var inIndex = index; + if (index >= FullContent.Length) { - start = LineEnds[lineNumber - 1] + 1; + index = FullContent.Length - 1; + } + if (index < 0) + { + index = 0; + } + // Populate true for the indexes of the most immediately preceding instance of the multiline comment type if found + if (!string.IsNullOrEmpty(prefix) && !string.IsNullOrEmpty(suffix)) + { + PopulateCommentedStatesInternal(index, prefix, suffix); + } + // Populate true for indexes of the most immediately preceding instance of the single-line comment type if found + if (!CommentedStates.ContainsKey(index) && !string.IsNullOrEmpty(inline)) + { + PopulateCommentedStatesInternal(index, inline, "\n"); + } + var i = index; + // Everything preceding this, including this, which doesn't have a commented state is + // therefore not commented so we backfill + while (!CommentedStates.ContainsKey(i) && i >= 0) + { + CommentedStates[i--] = false; + } + if (inIndex != index) + { + CommentedStates[inIndex] = CommentedStates[index]; } - result.Index = start; - result.Length = LineEnds[lineNumber] - result.Index + 1; - - return result; } - public string GetBoundaryText(Boundary capture) + /// + /// Gets the text for a given boundary + /// + /// The boundary to get text for. + /// + public string GetBoundaryText(Boundary boundary) { - if (capture is null) + if (boundary is null) { return string.Empty; } - return FullContent[(Math.Min(FullContent.Length, capture.Index))..(Math.Min(FullContent.Length, capture.Index + capture.Length))]; + var start = Math.Max(boundary.Index, 0); + var end = start + boundary.Length; + start = Math.Min(FullContent.Length, start); + end = Math.Min(FullContent.Length, end); + return FullContent[start..end]; } /// @@ -101,14 +160,14 @@ public string GetBoundaryText(Boundary capture) /// Boundary public Boundary GetLineBoundary(int index) { - Boundary result = new Boundary(); + Boundary result = new(); for (int i = 0; i < LineEnds.Count; i++) { if (LineEnds[i] >= index) { - result.Index = (i > 0 && LineEnds[i - 1] > 0) ? LineEnds[i - 1] + 1 : 0; - result.Length = LineEnds[i] - result.Index + 1; + result.Index = LineStarts[i]; + result.Length = LineEnds[i] - LineStarts[i] + 1; break; } } @@ -119,10 +178,14 @@ public Boundary GetLineBoundary(int index) /// /// Return content of the line /// - /// Line number + /// Line number (one-indexed) /// Text public string GetLineContent(int line) { + if (line >= LineEnds.Count) + { + line = LineEnds.Count - 1; + } int index = LineEnds[line]; Boundary bound = GetLineBoundary(index); return FullContent.Substring(bound.Index, bound.Length); @@ -131,11 +194,11 @@ public string GetLineContent(int line) /// /// Returns location (Line, Column) for given index in text /// - /// Position in text + /// Position in text (line is one-indexed) /// Location public Location GetLocation(int index) { - Location result = new Location(); + Location result = new(); if (index == 0) { @@ -149,8 +212,7 @@ public Location GetLocation(int index) if (LineEnds[i] >= index) { result.Line = i; - result.Column = index - LineEnds[i - 1]; - + result.Column = index - LineStarts[i]; break; } } @@ -158,157 +220,37 @@ public Location GetLocation(int index) return result; } - /// - /// Check whether the boundary in a text matches the scope of a search pattern (code, comment etc.) - /// - /// Pattern with scope - /// Boundary in a text - /// Text - /// True if boundary is matching the pattern scope - public bool ScopeMatch(IEnumerable patterns, Boundary boundary) + public bool IsCommented(int index) { - if (patterns is null) + if (!CommentedStates.ContainsKey(index)) { - return true; + PopulateCommentedState(index); } - if (patterns.Contains(PatternScope.All) || string.IsNullOrEmpty(prefix)) - return true; - bool isInComment = IsBetween(FullContent, boundary.Index, prefix, suffix, inline); - - return !(isInComment && !patterns.Contains(PatternScope.Comment)); - } - - private string inline; - private string prefix; - private string suffix; - - /// - /// Return boundary defined by line and its offset - /// - /// Line number - /// Offset from line number - /// Boundary - private int BoundaryByLine(int line, int offset) - { - int index = line + offset; - - // We need the begining of the line when going up - if (offset < 0) - index--; - - if (index < 0) - index = 0; - if (index >= LineEnds.Count) - index = LineEnds.Count - 1; - - return LineEnds[index]; + return CommentedStates[index]; } /// - /// Checks if the index in the string lies between preffix and suffix + /// Check whether the boundary in a text matches the scope of a search pattern (code, comment etc.) /// + /// The scopes to check + /// Boundary in the text /// Text - /// Index to check - /// Prefix - /// Suffix - /// True if the index is between prefix and suffix - private static bool IsBetween(string text, int index, string prefix, string suffix, string inline = "") + /// True if boundary is in a provided scope + public bool ScopeMatch(IEnumerable scopes, Boundary boundary) { - int pinnedIndex = Math.Min(index, text.Length); - string preText = text[0..pinnedIndex]; - int lastPrefix = FastGetLastIndex(preText, prefix); - if (lastPrefix >= 0) - { - int lastInline = FastGetLastIndex(preText[0..lastPrefix], inline); - // For example in C#, If this /* is actually commented out by a // - if (!(lastInline >= 0 && lastInline < lastPrefix && !preText[lastInline..lastPrefix].Contains('\n'))) - { - var commentedText = text[lastPrefix..]; - int nextSuffix = FastGetIndex(commentedText, suffix); - - // If the index is in between the last prefix before the index and the next suffix after - // that prefix Then it is commented out - if (lastPrefix + nextSuffix > pinnedIndex) - return true; - } - } - if (!string.IsNullOrEmpty(inline)) + if (scopes is null) { - int lastInline = FastGetLastIndex(preText, inline, '\n'); // Check the same line for same-line comment marks, stopping if you find a newline - if (lastInline >= 0) - { - var commentedText = text[lastInline..]; - int endOfLine = FastGetIndex(commentedText,"\n");//Environment.Newline looks for /r/n which is not guaranteed - if (endOfLine < 0) - { - endOfLine = commentedText.Length - 1; - } - if (index > lastInline && index < lastInline + endOfLine) - { - return true; - } - } + return true; } + if (scopes.Contains(PatternScope.All) || string.IsNullOrEmpty(prefix)) + return true; + bool isInComment = IsCommented(boundary.Index); - return false; + return (!isInComment && scopes.Contains(PatternScope.Code)) || (isInComment && scopes.Contains(PatternScope.Comment)); } - private static int FastGetIndex(string target, string query, char? cancelOn = null) - { - for (int i = 0; i < target.Length - query.Length; i++) - { - int offset = 0; - bool skip = false; - while (!skip && offset < query.Length) - { - if (target[i + offset].Equals(cancelOn)) - { - skip = true; - } - else if (!target[i + offset].Equals(query[offset])) - { - skip = true; - } - else - { - offset++; - } - } - if (!skip) - { - return i; - } - } - return -1; - } - - private static int FastGetLastIndex(string target, string query, char? cancelOn = null) - { - for (int i = target.Length - query.Length; i > 0; i--) - { - int offset = 0; - bool skip = false; - while(!skip && offset < query.Length) - { - if (target[i + offset].Equals(cancelOn)) - { - skip = true; - } - else if (!target[i + offset].Equals(query[offset])) - { - skip = true; - } - else - { - offset++; - } - } - if (!skip) - { - return i; - } - } - return -1; - } + private readonly string inline; + private readonly string prefix; + private readonly string suffix; } } \ No newline at end of file diff --git a/RulesPacker/ApplicationInspector.CLI.deps.json b/RulesPacker/ApplicationInspector.CLI.deps.json index d76f9ed7..f9e56dd9 100644 --- a/RulesPacker/ApplicationInspector.CLI.deps.json +++ b/RulesPacker/ApplicationInspector.CLI.deps.json @@ -6,13 +6,14 @@ "compilationOptions": {}, "targets": { ".NETCoreApp,Version=v5.0": { - "ApplicationInspector.CLI/1.2.98-g7e37069fa1": { + "ApplicationInspector.CLI/1.3.39-beta-g55b6eb5ec8": { "dependencies": { - "DotLiquid": "2.0.361", + "DotLiquid": "2.1.436", "Microsoft.ApplicationInspector.RulesEngine": "0.0.0-placeholder", "Microsoft.CST.ApplicationInspector.Commands": "0.0.0-placeholder", - "NLog": "4.7.5", - "Nerdbank.GitVersioning": "3.3.37" + "NLog": "4.7.9", + "Nerdbank.GitVersioning": "3.4.194", + "ShellProgressBar": "5.1.0" }, "runtime": { "ApplicationInspector.CLI.dll": {} @@ -55,7 +56,7 @@ "DiscUtils.Streams": "0.15.1-ci0002", "System.IO.FileSystem.DriveInfo": "4.3.0", "System.Security.AccessControl": "4.3.0", - "System.Text.Encoding.CodePages": "4.7.1", + "System.Text.Encoding.CodePages": "4.5.1", "System.Xml.XmlDocument": "4.3.0" }, "runtime": { @@ -183,19 +184,27 @@ } } }, - "DotLiquid/2.0.361": { + "DotLiquid/2.1.436": { "runtime": { - "lib/netstandard1.3/DotLiquid.dll": { - "assemblyVersion": "2.0.361.0", - "fileVersion": "2.0.361.0" + "lib/netstandard2.0/DotLiquid.dll": { + "assemblyVersion": "2.1.436.0", + "fileVersion": "2.1.436.0" } }, "resources": { - "lib/netstandard1.3/it/DotLiquid.resources.dll": { + "lib/netstandard2.0/it/DotLiquid.resources.dll": { "locale": "it" } } }, + "Glob/1.1.8": { + "runtime": { + "lib/netstandard2.0/Glob.dll": { + "assemblyVersion": "1.1.8.0", + "fileVersion": "1.1.8.0" + } + } + }, "lzo.net/0.0.3": { "dependencies": { "NETStandard.Library": "1.6.1" @@ -207,11 +216,11 @@ } } }, - "Microsoft.Bcl.AsyncInterfaces/1.1.1": { + "Microsoft.Bcl.AsyncInterfaces/5.0.0": { "runtime": { "lib/netstandard2.1/Microsoft.Bcl.AsyncInterfaces.dll": { - "assemblyVersion": "1.0.0.0", - "fileVersion": "4.700.20.21406" + "assemblyVersion": "5.0.0.0", + "fileVersion": "5.0.20.51904" } } }, @@ -223,7 +232,7 @@ "System.Memory": "4.5.3", "System.Reflection.Metadata": "1.6.0", "System.Runtime.CompilerServices.Unsafe": "4.7.0", - "System.Text.Encoding.CodePages": "4.7.1", + "System.Text.Encoding.CodePages": "4.5.1", "System.Threading.Tasks.Extensions": "4.5.3" }, "runtime": { @@ -434,23 +443,23 @@ } }, "Microsoft.CSharp/4.5.0": {}, - "Microsoft.CST.OAT/1.0.74": { + "Microsoft.CST.OAT/1.0.84": { "dependencies": { "CompareNETObjects": "4.66.0", "Microsoft.CodeAnalysis.CSharp.Scripting": "3.6.0", - "Newtonsoft.Json": "12.0.3", + "Newtonsoft.Json": "13.0.1", "Serilog": "2.9.0", "Serilog.Sinks.Console": "3.1.1", "System.Collections": "4.3.0" }, "runtime": { - "lib/netstandard2.1/OAT.dll": { + "lib/net5.0/OAT.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.0.74.17915" + "fileVersion": "1.0.84.16119" } } }, - "Microsoft.CST.RecursiveExtractor/1.0.36": { + "Microsoft.CST.RecursiveExtractor/1.0.60": { "dependencies": { "DiscUtils.Btrfs": "0.15.1-ci0002", "DiscUtils.Core": "0.15.1-ci0002", @@ -464,31 +473,31 @@ "DiscUtils.Vmdk": "0.15.1-ci0002", "DiscUtils.Wim": "0.15.1-ci0002", "DiscUtils.Xfs": "0.15.1-ci0002", - "Microsoft.Bcl.AsyncInterfaces": "1.1.1", - "NLog": "4.7.5", - "SharpCompress": "0.25.1", - "SharpZipLib": "1.2.0" + "Microsoft.Bcl.AsyncInterfaces": "5.0.0", + "NLog": "4.7.9", + "SharpCompress": "0.28.2", + "SharpZipLib": "1.3.1" }, "runtime": { - "lib/netstandard2.1/RecursiveExtractor.dll": { + "lib/net5.0/RecursiveExtractor.dll": { "assemblyVersion": "1.0.0.0", - "fileVersion": "1.0.36.24558" + "fileVersion": "1.0.60.60898" } } }, - "Microsoft.NETCore.Platforms/3.1.1": {}, + "Microsoft.NETCore.Platforms/2.1.2": {}, "Microsoft.NETCore.Targets/1.1.0": {}, "Microsoft.Win32.Primitives/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.Runtime": "4.3.0" } }, - "Nerdbank.GitVersioning/3.3.37": {}, + "Nerdbank.GitVersioning/3.4.194": {}, "NETStandard.Library/1.6.1": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.Win32.Primitives": "4.3.0", "System.AppContext": "4.3.0", "System.Collections": "4.3.0", @@ -534,19 +543,19 @@ "System.Xml.XDocument": "4.3.0" } }, - "Newtonsoft.Json/12.0.3": { + "Newtonsoft.Json/13.0.1": { "runtime": { "lib/netstandard2.0/Newtonsoft.Json.dll": { - "assemblyVersion": "12.0.0.0", - "fileVersion": "12.0.3.23909" + "assemblyVersion": "13.0.0.0", + "fileVersion": "13.0.1.25517" } } }, - "NLog/4.7.5": { + "NLog/4.7.9": { "runtime": { "lib/netstandard2.0/NLog.dll": { "assemblyVersion": "4.0.0.0", - "fileVersion": "4.7.5.12092" + "fileVersion": "4.7.9.12899" } } }, @@ -555,19 +564,19 @@ "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": {}, "runtime.native.System/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0" } }, "runtime.native.System.IO.Compression/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0" } }, "runtime.native.System.Net.Http/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0" } }, @@ -620,22 +629,31 @@ } } }, - "SharpCompress/0.25.1": { - "dependencies": { - "System.Text.Encoding.CodePages": "4.7.1" - }, + "SharpCompress/0.28.2": { "runtime": { - "lib/netstandard2.1/SharpCompress.dll": { - "assemblyVersion": "0.25.1.0", - "fileVersion": "0.25.1.0" + "lib/net5.0/SharpCompress.dll": { + "assemblyVersion": "0.28.2.0", + "fileVersion": "0.28.2.0" } } }, - "SharpZipLib/1.2.0": { + "SharpZipLib/1.3.1": { "runtime": { "lib/netstandard2.0/ICSharpCode.SharpZipLib.dll": { - "assemblyVersion": "1.2.0.246", - "fileVersion": "1.2.0.246" + "assemblyVersion": "1.3.1.9", + "fileVersion": "1.3.1.9" + } + } + }, + "ShellProgressBar/5.1.0": { + "dependencies": { + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Text.Encoding.CodePages": "4.5.1" + }, + "runtime": { + "lib/netstandard2.0/ShellProgressBar.dll": { + "assemblyVersion": "5.1.0.0", + "fileVersion": "5.1.0.0" } } }, @@ -655,7 +673,7 @@ }, "System.Collections/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.Runtime": "4.3.0" } @@ -677,7 +695,7 @@ "System.Collections.Immutable/1.5.0": {}, "System.Console/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.IO": "4.3.0", "System.Runtime": "4.3.0", @@ -686,7 +704,7 @@ }, "System.Diagnostics.Debug/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.Runtime": "4.3.0" } @@ -702,28 +720,28 @@ }, "System.Diagnostics.Tools/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.Runtime": "4.3.0" } }, "System.Diagnostics.Tracing/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.Runtime": "4.3.0" } }, "System.Globalization/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.Runtime": "4.3.0" } }, "System.Globalization.Calendars/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.Globalization": "4.3.0", "System.Runtime": "4.3.0" @@ -731,7 +749,7 @@ }, "System.Globalization.Extensions/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "System.Globalization": "4.3.0", "System.Resources.ResourceManager": "4.3.0", "System.Runtime": "4.3.0", @@ -741,7 +759,7 @@ }, "System.IO/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.Runtime": "4.3.0", "System.Text.Encoding": "4.3.0", @@ -750,7 +768,7 @@ }, "System.IO.Compression/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "System.Buffers": "4.3.0", "System.Collections": "4.3.0", "System.Diagnostics.Debug": "4.3.0", @@ -782,7 +800,7 @@ }, "System.IO.FileSystem/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.IO": "4.3.0", "System.IO.FileSystem.Primitives": "4.3.0", @@ -794,7 +812,7 @@ }, "System.IO.FileSystem.DriveInfo/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "System.Collections": "4.3.0", "System.IO": "4.3.0", "System.IO.FileSystem": "4.3.0", @@ -846,7 +864,7 @@ "System.Memory/4.5.3": {}, "System.Net.Http/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "System.Collections": "4.3.0", "System.Diagnostics.Debug": "4.3.0", "System.Diagnostics.DiagnosticSource": "4.3.0", @@ -876,7 +894,7 @@ }, "System.Net.Primitives/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.Runtime": "4.3.0", "System.Runtime.Handles": "4.3.0" @@ -884,7 +902,7 @@ }, "System.Net.Sockets/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.IO": "4.3.0", "System.Net.Primitives": "4.3.0", @@ -903,7 +921,7 @@ }, "System.Reflection/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.IO": "4.3.0", "System.Reflection.Primitives": "4.3.0", @@ -936,7 +954,7 @@ }, "System.Reflection.Extensions/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.Reflection": "4.3.0", "System.Runtime": "4.3.0" @@ -945,7 +963,7 @@ "System.Reflection.Metadata/1.6.0": {}, "System.Reflection.Primitives/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.Runtime": "4.3.0" } @@ -958,7 +976,7 @@ }, "System.Resources.ResourceManager/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.Globalization": "4.3.0", "System.Reflection": "4.3.0", @@ -967,28 +985,28 @@ }, "System.Runtime/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0" } }, "System.Runtime.CompilerServices.Unsafe/4.7.0": {}, "System.Runtime.Extensions/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.Runtime": "4.3.0" } }, "System.Runtime.Handles/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.Runtime": "4.3.0" } }, "System.Runtime.InteropServices/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.Reflection": "4.3.0", "System.Reflection.Primitives": "4.3.0", @@ -1017,7 +1035,7 @@ }, "System.Security.AccessControl/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "System.Collections": "4.3.0", "System.Globalization": "4.3.0", "System.Reflection": "4.3.0", @@ -1043,7 +1061,7 @@ }, "System.Security.Cryptography.Algorithms/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "System.Collections": "4.3.0", "System.IO": "4.3.0", "System.Resources.ResourceManager": "4.3.0", @@ -1061,7 +1079,7 @@ }, "System.Security.Cryptography.Cng/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "System.IO": "4.3.0", "System.Resources.ResourceManager": "4.3.0", "System.Runtime": "4.3.0", @@ -1076,7 +1094,7 @@ }, "System.Security.Cryptography.Csp/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "System.IO": "4.3.0", "System.Reflection": "4.3.0", "System.Resources.ResourceManager": "4.3.0", @@ -1093,7 +1111,7 @@ }, "System.Security.Cryptography.Encoding/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "System.Collections": "4.3.0", "System.Collections.Concurrent": "4.3.0", "System.Linq": "4.3.0", @@ -1137,7 +1155,7 @@ }, "System.Security.Cryptography.X509Certificates/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "System.Collections": "4.3.0", "System.Diagnostics.Debug": "4.3.0", "System.Globalization": "4.3.0", @@ -1171,7 +1189,7 @@ }, "System.Security.Principal.Windows/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.Win32.Primitives": "4.3.0", "System.Collections": "4.3.0", "System.Diagnostics.Debug": "4.3.0", @@ -1189,19 +1207,20 @@ }, "System.Text.Encoding/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.Runtime": "4.3.0" } }, - "System.Text.Encoding.CodePages/4.7.1": { + "System.Text.Encoding.CodePages/4.5.1": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1" + "Microsoft.NETCore.Platforms": "2.1.2", + "System.Runtime.CompilerServices.Unsafe": "4.7.0" } }, "System.Text.Encoding.Extensions/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.Runtime": "4.3.0", "System.Text.Encoding": "4.3.0" @@ -1220,7 +1239,7 @@ }, "System.Threading.Tasks/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.Runtime": "4.3.0" } @@ -1233,7 +1252,7 @@ }, "System.Threading.Timer/4.3.0": { "dependencies": { - "Microsoft.NETCore.Platforms": "3.1.1", + "Microsoft.NETCore.Platforms": "2.1.2", "Microsoft.NETCore.Targets": "1.1.0", "System.Runtime": "4.3.0" } @@ -1289,9 +1308,10 @@ }, "Microsoft.ApplicationInspector.RulesEngine/0.0.0-placeholder": { "dependencies": { - "Microsoft.CST.OAT": "1.0.74", - "NLog": "4.7.5", - "Newtonsoft.Json": "12.0.3" + "Microsoft.CST.OAT": "1.0.84", + "Microsoft.CST.RecursiveExtractor": "1.0.60", + "NLog": "4.7.9", + "Newtonsoft.Json": "13.0.1" }, "runtime": { "ApplicationInspector.RulesEngine.dll": {} @@ -1300,12 +1320,14 @@ "Microsoft.CST.ApplicationInspector.Commands/0.0.0-placeholder": { "dependencies": { "CommandLineParser": "2.8.0", - "DotLiquid": "2.0.361", + "DotLiquid": "2.1.436", + "Glob": "1.1.8", "Microsoft.ApplicationInspector.RulesEngine": "0.0.0-placeholder", - "Microsoft.CST.OAT": "1.0.74", - "Microsoft.CST.RecursiveExtractor": "1.0.36", - "NLog": "4.7.5", - "Newtonsoft.Json": "12.0.3" + "Microsoft.CST.OAT": "1.0.84", + "Microsoft.CST.RecursiveExtractor": "1.0.60", + "NLog": "4.7.9", + "Newtonsoft.Json": "13.0.1", + "ShellProgressBar": "5.1.0" }, "runtime": { "ApplicationInspector.Commands.dll": {} @@ -1314,7 +1336,7 @@ } }, "libraries": { - "ApplicationInspector.CLI/1.2.98-g7e37069fa1": { + "ApplicationInspector.CLI/1.3.39-beta-g55b6eb5ec8": { "type": "project", "serviceable": false, "sha512": "" @@ -1424,12 +1446,19 @@ "path": "discutils.xfs/0.15.1-ci0002", "hashPath": "discutils.xfs.0.15.1-ci0002.nupkg.sha512" }, - "DotLiquid/2.0.361": { + "DotLiquid/2.1.436": { + "type": "package", + "serviceable": true, + "sha512": "sha512-sf37qMl5xTX3jsG1AtSK3+2i1AMORyLkpNShcKdCPAwc5yRQSD41fU9RJQH8YDreIE5dQZPI9tzwrO6r6MfshA==", + "path": "dotliquid/2.1.436", + "hashPath": "dotliquid.2.1.436.nupkg.sha512" + }, + "Glob/1.1.8": { "type": "package", "serviceable": true, - "sha512": "sha512-gqsM9DvtiznbajOIpWj+xut8y45M7Fja2rKM1WVjhveYn3gFiDFjIPHVmcJIoVB4dWUd/dVzTHFv+C13XL5JIg==", - "path": "dotliquid/2.0.361", - "hashPath": "dotliquid.2.0.361.nupkg.sha512" + "sha512": "sha512-t9OBRTf69gqpQ6yO4/VQj2B+EewRmwsmv5CG48Nb5nwRJv2BWx76TY2DILlbNYE4LooHrXhw59Sdzhs1HfD++Q==", + "path": "glob/1.1.8", + "hashPath": "glob.1.1.8.nupkg.sha512" }, "lzo.net/0.0.3": { "type": "package", @@ -1438,12 +1467,12 @@ "path": "lzo.net/0.0.3", "hashPath": "lzo.net.0.0.3.nupkg.sha512" }, - "Microsoft.Bcl.AsyncInterfaces/1.1.1": { + "Microsoft.Bcl.AsyncInterfaces/5.0.0": { "type": "package", "serviceable": true, - "sha512": "sha512-yuvf07qFWFqtK3P/MRkEKLhn5r2UbSpVueRziSqj0yJQIKFwG1pq9mOayK3zE5qZCTs0CbrwL9M6R8VwqyGy2w==", - "path": "microsoft.bcl.asyncinterfaces/1.1.1", - "hashPath": "microsoft.bcl.asyncinterfaces.1.1.1.nupkg.sha512" + "sha512": "sha512-W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==", + "path": "microsoft.bcl.asyncinterfaces/5.0.0", + "hashPath": "microsoft.bcl.asyncinterfaces.5.0.0.nupkg.sha512" }, "Microsoft.CodeAnalysis.Analyzers/3.0.0": { "type": "package", @@ -1487,26 +1516,26 @@ "path": "microsoft.csharp/4.5.0", "hashPath": "microsoft.csharp.4.5.0.nupkg.sha512" }, - "Microsoft.CST.OAT/1.0.74": { + "Microsoft.CST.OAT/1.0.84": { "type": "package", "serviceable": true, - "sha512": "sha512-vrpqNQxtESZgBNBVRmMBJSBTgEKGz1kA2vIfHa3RkdyjGNIKGixpF7mgeJvjRmZh12ttGz6mAlTAxZCZHUUVdQ==", - "path": "microsoft.cst.oat/1.0.74", - "hashPath": "microsoft.cst.oat.1.0.74.nupkg.sha512" + "sha512": "sha512-Us8zbXVmrt/J/Qx0m54rsgI8Tvd79phH0wZU6wSDuQhAI22Yjd31YcFFAQQQZM9wqYaf+4JWdlhq/R1+eaeRlA==", + "path": "microsoft.cst.oat/1.0.84", + "hashPath": "microsoft.cst.oat.1.0.84.nupkg.sha512" }, - "Microsoft.CST.RecursiveExtractor/1.0.36": { + "Microsoft.CST.RecursiveExtractor/1.0.60": { "type": "package", "serviceable": true, - "sha512": "sha512-J39einBJGx9O+vLkzrW1OnFvtBNzZDev4OTnRnOt8K9OLp9gN7jp86cqOdt45m3WLstHQ8HXXjIYQSWeown79A==", - "path": "microsoft.cst.recursiveextractor/1.0.36", - "hashPath": "microsoft.cst.recursiveextractor.1.0.36.nupkg.sha512" + "sha512": "sha512-OHigf5YVF8dcv/ef0fQKfh4/DH2psyvp1tlq/k5bqJmzr7R5HXcuLLN6pyVyqZ08FgwqyVbxK3Psc61USgo4Rw==", + "path": "microsoft.cst.recursiveextractor/1.0.60", + "hashPath": "microsoft.cst.recursiveextractor.1.0.60.nupkg.sha512" }, - "Microsoft.NETCore.Platforms/3.1.1": { + "Microsoft.NETCore.Platforms/2.1.2": { "type": "package", "serviceable": true, - "sha512": "sha512-RmINcaqiEkawM9C8oxFMN/CZmn1fGKWVsosbSY/8ARUNdHqV47hqhPVbrG3qUqLaRQI5w4HuqFOqrbhoSWcH6w==", - "path": "microsoft.netcore.platforms/3.1.1", - "hashPath": "microsoft.netcore.platforms.3.1.1.nupkg.sha512" + "sha512": "sha512-mOJy3M0UN+LUG21dLGMxaWZEP6xYpQEpLuvuEQBaownaX4YuhH6NmNUlN9si+vNkAS6dwJ//N1O4DmLf2CikVg==", + "path": "microsoft.netcore.platforms/2.1.2", + "hashPath": "microsoft.netcore.platforms.2.1.2.nupkg.sha512" }, "Microsoft.NETCore.Targets/1.1.0": { "type": "package", @@ -1522,12 +1551,12 @@ "path": "microsoft.win32.primitives/4.3.0", "hashPath": "microsoft.win32.primitives.4.3.0.nupkg.sha512" }, - "Nerdbank.GitVersioning/3.3.37": { + "Nerdbank.GitVersioning/3.4.194": { "type": "package", "serviceable": true, - "sha512": "sha512-YlDKV/gSHQGDThWSGqVyPfKeNP/kx1fj/NPFFgGc/cxzgIbXv4jtYOcbFOz3ZIeAKtpCcSAmVNDOikBs3OxI/A==", - "path": "nerdbank.gitversioning/3.3.37", - "hashPath": "nerdbank.gitversioning.3.3.37.nupkg.sha512" + "sha512": "sha512-f4V2lLy9G0BnddqGhfaVa+dKsbu8iCiLiUARHKBo0l899MgJdRjVU2C7e29gHrZWxc2HZkq3aq28OHHK7q0/iQ==", + "path": "nerdbank.gitversioning/3.4.194", + "hashPath": "nerdbank.gitversioning.3.4.194.nupkg.sha512" }, "NETStandard.Library/1.6.1": { "type": "package", @@ -1536,19 +1565,19 @@ "path": "netstandard.library/1.6.1", "hashPath": "netstandard.library.1.6.1.nupkg.sha512" }, - "Newtonsoft.Json/12.0.3": { + "Newtonsoft.Json/13.0.1": { "type": "package", "serviceable": true, - "sha512": "sha512-6mgjfnRB4jKMlzHSl+VD+oUc1IebOZabkbyWj2RiTgWwYPPuaK1H97G1sHqGwPlS5npiF5Q0OrxN1wni2n5QWg==", - "path": "newtonsoft.json/12.0.3", - "hashPath": "newtonsoft.json.12.0.3.nupkg.sha512" + "sha512": "sha512-ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==", + "path": "newtonsoft.json/13.0.1", + "hashPath": "newtonsoft.json.13.0.1.nupkg.sha512" }, - "NLog/4.7.5": { + "NLog/4.7.9": { "type": "package", "serviceable": true, - "sha512": "sha512-1Udzim+UwoAGk0vW6T2rEBXJq1COvqTuE+4NFj2zHytuX1WOu+1Yes1qABG1IJOA5V3OMilIufUU1Ha9T0rrzQ==", - "path": "nlog/4.7.5", - "hashPath": "nlog.4.7.5.nupkg.sha512" + "sha512": "sha512-Y0dKY5d506ZVcb8dTMp3BSb+jUGaFu/ArvRkgn4daDWKf7qqFXjEFYjqoyTrWkcNguqS6avkwICS0hsFsr4BzA==", + "path": "nlog/4.7.9", + "hashPath": "nlog.4.7.9.nupkg.sha512" }, "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.0": { "type": "package", @@ -1676,19 +1705,26 @@ "path": "serilog.sinks.console/3.1.1", "hashPath": "serilog.sinks.console.3.1.1.nupkg.sha512" }, - "SharpCompress/0.25.1": { + "SharpCompress/0.28.2": { + "type": "package", + "serviceable": true, + "sha512": "sha512-GKQf/FicituGIF4x0YCfzcgv1WyIz0A0ujNo65USEZq9MqkYO6KLNPWEcSXAiYKC+QQwufpsvetsy2N5hATFAw==", + "path": "sharpcompress/0.28.2", + "hashPath": "sharpcompress.0.28.2.nupkg.sha512" + }, + "SharpZipLib/1.3.1": { "type": "package", "serviceable": true, - "sha512": "sha512-E7QcQVxWbHKKQZh8JoTlwjFAcJO4I9ymTxC4kPpTBtRbB9gak/B7yd/tdKCOE/c2u+N+gLicxOwP+u5CsPLVQw==", - "path": "sharpcompress/0.25.1", - "hashPath": "sharpcompress.0.25.1.nupkg.sha512" + "sha512": "sha512-/iMph6bLdKzDhwM/vkAo4BU8z5QQnyodlkZon3XRMtRmVuWv5Rph1kaDmd9XjrQxjPJPuLquTSrkEoSPq/flVw==", + "path": "sharpziplib/1.3.1", + "hashPath": "sharpziplib.1.3.1.nupkg.sha512" }, - "SharpZipLib/1.2.0": { + "ShellProgressBar/5.1.0": { "type": "package", "serviceable": true, - "sha512": "sha512-zvWa/L02JHNatdtjya6Swpudb2YEHaOLHL1eRrqpjm71iGRNUNONO5adUF/9CHbSJbzhELW1UoH4NGy7n7+3bQ==", - "path": "sharpziplib/1.2.0", - "hashPath": "sharpziplib.1.2.0.nupkg.sha512" + "sha512": "sha512-361fhmZBA2rn/Z8Tp9wDpB97H9GSRTLI5vXBky4I8fkd7H6UVYgvVSW6uv6Wd1+lUbq8JLgYo+4bhJvWF/SJCw==", + "path": "shellprogressbar/5.1.0", + "hashPath": "shellprogressbar.5.1.0.nupkg.sha512" }, "System.AppContext/4.3.0": { "type": "package", @@ -2068,12 +2104,12 @@ "path": "system.text.encoding/4.3.0", "hashPath": "system.text.encoding.4.3.0.nupkg.sha512" }, - "System.Text.Encoding.CodePages/4.7.1": { + "System.Text.Encoding.CodePages/4.5.1": { "type": "package", "serviceable": true, - "sha512": "sha512-i2fOvznVVgOOTLUz8FgSap/MsR98I4Iaoz99VXcOW/e7Y2OdY42zhYpBYpZyivk5alYY/UsOWAVswhtjxceodA==", - "path": "system.text.encoding.codepages/4.7.1", - "hashPath": "system.text.encoding.codepages.4.7.1.nupkg.sha512" + "sha512": "sha512-4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==", + "path": "system.text.encoding.codepages/4.5.1", + "hashPath": "system.text.encoding.codepages.4.5.1.nupkg.sha512" }, "System.Text.Encoding.Extensions/4.3.0": { "type": "package", diff --git a/RulesPacker/ApplicationInspector.CLI.dll b/RulesPacker/ApplicationInspector.CLI.dll index 319dbf45..180fbb23 100644 Binary files a/RulesPacker/ApplicationInspector.CLI.dll and b/RulesPacker/ApplicationInspector.CLI.dll differ diff --git a/RulesPacker/ApplicationInspector.CLI.exe b/RulesPacker/ApplicationInspector.CLI.exe index 6e5dc638..03e47a92 100644 Binary files a/RulesPacker/ApplicationInspector.CLI.exe and b/RulesPacker/ApplicationInspector.CLI.exe differ diff --git a/RulesPacker/ApplicationInspector.Commands.dll b/RulesPacker/ApplicationInspector.Commands.dll index e50dcfbb..98052c63 100644 Binary files a/RulesPacker/ApplicationInspector.Commands.dll and b/RulesPacker/ApplicationInspector.Commands.dll differ diff --git a/RulesPacker/ApplicationInspector.RulesEngine.dll b/RulesPacker/ApplicationInspector.RulesEngine.dll index d5163a9b..55e23b84 100644 Binary files a/RulesPacker/ApplicationInspector.RulesEngine.dll and b/RulesPacker/ApplicationInspector.RulesEngine.dll differ diff --git a/RulesPacker/DotLiquid.dll b/RulesPacker/DotLiquid.dll index e3262952..fe08d242 100755 Binary files a/RulesPacker/DotLiquid.dll and b/RulesPacker/DotLiquid.dll differ diff --git a/RulesPacker/Glob.dll b/RulesPacker/Glob.dll new file mode 100644 index 00000000..0e940314 Binary files /dev/null and b/RulesPacker/Glob.dll differ diff --git a/RulesPacker/ICSharpCode.SharpZipLib.dll b/RulesPacker/ICSharpCode.SharpZipLib.dll index 58893bae..aa36b113 100644 Binary files a/RulesPacker/ICSharpCode.SharpZipLib.dll and b/RulesPacker/ICSharpCode.SharpZipLib.dll differ diff --git a/RulesPacker/Microsoft.Bcl.AsyncInterfaces.dll b/RulesPacker/Microsoft.Bcl.AsyncInterfaces.dll index a5b7ff99..be25bdb6 100644 Binary files a/RulesPacker/Microsoft.Bcl.AsyncInterfaces.dll and b/RulesPacker/Microsoft.Bcl.AsyncInterfaces.dll differ diff --git a/RulesPacker/NLog.dll b/RulesPacker/NLog.dll index 3f84f921..b1da8592 100755 Binary files a/RulesPacker/NLog.dll and b/RulesPacker/NLog.dll differ diff --git a/RulesPacker/Newtonsoft.Json.dll b/RulesPacker/Newtonsoft.Json.dll index b501fb6a..1ffeabe6 100755 Binary files a/RulesPacker/Newtonsoft.Json.dll and b/RulesPacker/Newtonsoft.Json.dll differ diff --git a/RulesPacker/OAT.dll b/RulesPacker/OAT.dll index 2c5c1cfa..6e9de0bb 100644 Binary files a/RulesPacker/OAT.dll and b/RulesPacker/OAT.dll differ diff --git a/RulesPacker/RecursiveExtractor.dll b/RulesPacker/RecursiveExtractor.dll index 37f95429..eef02e58 100644 Binary files a/RulesPacker/RecursiveExtractor.dll and b/RulesPacker/RecursiveExtractor.dll differ diff --git a/RulesPacker/SharpCompress.dll b/RulesPacker/SharpCompress.dll index 7939b7f4..94aacb81 100644 Binary files a/RulesPacker/SharpCompress.dll and b/RulesPacker/SharpCompress.dll differ diff --git a/RulesPacker/ShellProgressBar.dll b/RulesPacker/ShellProgressBar.dll new file mode 100644 index 00000000..526457e4 Binary files /dev/null and b/RulesPacker/ShellProgressBar.dll differ diff --git a/RulesPacker/it/DotLiquid.resources.dll b/RulesPacker/it/DotLiquid.resources.dll index cac9df97..56fd2f7e 100755 Binary files a/RulesPacker/it/DotLiquid.resources.dll and b/RulesPacker/it/DotLiquid.resources.dll differ diff --git a/RulesPacker/preferences/tagreportgroups.json b/RulesPacker/preferences/tagreportgroups.json index 00eb956c..24aa8c1d 100644 --- a/RulesPacker/preferences/tagreportgroups.json +++ b/RulesPacker/preferences/tagreportgroups.json @@ -528,7 +528,7 @@ }, { "searchPattern": "Sensitive.Secret", - "displayName": "Senstive secret", + "displayName": "Sensitive secret", "detectedIcon": "fab fa-keycdn" }, { diff --git a/UnitTest.Commands/Tests_CLI/TestAnalyzeCmd.cs b/UnitTest.Commands/Tests_CLI/TestAnalyzeCmd.cs index 0cad15ec..4b0fdfd7 100644 --- a/UnitTest.Commands/Tests_CLI/TestAnalyzeCmd.cs +++ b/UnitTest.Commands/Tests_CLI/TestAnalyzeCmd.cs @@ -42,435 +42,297 @@ public void CleanUp() [TestMethod] public void BasicHTMLOutput_Pass() { - AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"analyze -s {0} -f html -k none", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp")); - exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } + string args = string.Format(@"analyze -s {0} -f html -k none", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp")); + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, exitCode); } [TestMethod] public void UnknownFormat_Fail() //dupliacte tags not supported for html format { - AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"analyze -b -s {0} -f unknown -k none", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp")); - exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - //check for specific error if desired - } + string args = string.Format(@"analyze -b -s {0} -f unknown -k none", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp")); + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.CriticalError); + Assert.AreEqual(AnalyzeResult.ExitCode.CriticalError, exitCode); } [TestMethod] public void ZipReadHTMLOutput_Pass() { - AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"analyze -s {0} -f html -k none -l {1}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"zipped\mainx.zip"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); + string args = string.Format(@"analyze -s {0} -f html -k none -l {1}", + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"zipped\mainx.zip"), + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, exitCode); } [TestMethod] public void InvalidOutputfilePath_Fail() { - AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"analyze -s {0} -f json -k none -o {1}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"badir\output.txt")); + string args = string.Format(@"analyze -s {0} -f json -k none -o {1}", + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"badir\output.txt")); - exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.CriticalError); + Assert.AreEqual(AnalyzeResult.ExitCode.CriticalError, exitCode); } [TestMethod] public void InvalidSourcePath_Fail() { - AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"analyze -s {0} -f json -k none -o {1}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\badfilepath.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + string args = string.Format(@"analyze -s {0} -f json -k none -o {1}", + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\badfilepath.cpp"), + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.CriticalError); + Assert.AreEqual(AnalyzeResult.ExitCode.CriticalError, exitCode); } [TestMethod] public void InvalidRulesPath_Fail() - { - AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"analyze -s {0} -r badrulespath -f json -k none -o {1}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + { + string args = string.Format(@"analyze -s {0} -r badrulespath -f json -k none -o {1}", + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + - Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.CriticalError); + Assert.AreEqual(AnalyzeResult.ExitCode.CriticalError, exitCode); } [TestMethod] public void NoDefaultNoCustomRules_Fail() { - AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"analyze -s {0} -i -f json -k none -o {1}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + string args = string.Format(@"analyze -s {0} -i -f json -k none -o {1}", + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.CriticalError); + Assert.AreEqual(AnalyzeResult.ExitCode.CriticalError, exitCode); } [TestMethod] public void NoDefaultCustomRules_Pass() { - AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"analyze -s {0} -i -r {1} -f json -k none -o {2}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - - exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); + string args = string.Format(@"analyze -s {0} -i -r {1} -f json -k none -o {2}", + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), + Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + + Assert.AreEqual(AnalyzeResult.ExitCode.Success, exitCode); } [TestMethod] public void DefaultWithCustomRules_Pass() { - AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"analyze -s {0} -r {1} -f json -k none -o {2}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + string args = string.Format(@"analyze -s {0} -r {1} -f json -k none -o {2}", + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), + Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, exitCode); } [TestMethod] public void DefaultAndCustomRulesPosMatches_Pass() { - AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"analyze -s {0} -r {1} -f json -k none -o {2}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - - exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - - string testContent = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - exitCode = testContent.Contains("Data.Parsing.JSON") ? AnalyzeResult.ExitCode.Success : exitCode; - exitCode = testContent.Contains("Data.Custom1") ? AnalyzeResult.ExitCode.Success : exitCode; - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); + string args = string.Format(@"analyze -s {0} -r {1} -f json -k none -o {2}", + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), + Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, exitCode); + string testContent = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + Assert.IsTrue(testContent.Contains("Cryptography.HashAlgorithm.Legacy")); + Assert.IsTrue(testContent.Contains("Data.Custom1")); } [TestMethod] public void ExclusionFilter_Pass() { - AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"analyze -s {0} -r {1} -f json -o {2} -k {3}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\project\one"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt"), - ".cpp"); - - exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } + string args = string.Format(@"analyze -s {0} -r {1} -f json -o {2} -k {3}", + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\project\one"), + Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt"), + "*.cpp"); + + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + + Assert.AreEqual(AnalyzeResult.ExitCode.NoMatches, exitCode); + } - Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.NoMatches); + [TestMethod] + public void MultiFiles() + { + var mainduptags = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp"); + string args = string.Format(@"analyze -s {0} -f json -o {1} -k none", + $"{mainduptags}", + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + + var exitCodeSingleThread = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, exitCodeSingleThread); + + string content = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + var result = JsonConvert.DeserializeObject(content); + var matches = result.Metadata.TotalMatchesCount; + var uniqueMatches = result.Metadata.UniqueMatchesCount; + mainduptags = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp"); + args = string.Format(@"analyze -s {0} -f json -o {1} -k none", + $"{mainduptags},{mainduptags}", + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + + exitCodeSingleThread = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, exitCodeSingleThread); + + content = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + var result2 = JsonConvert.DeserializeObject(content); + + Assert.AreEqual(matches * 2, result2.Metadata.TotalMatchesCount); + Assert.AreEqual(uniqueMatches, result2.Metadata.UniqueMatchesCount); } [TestMethod] public void ExpectedTagCountDupsAllowed_Pass() { - AnalyzeResult.ExitCode exitCodeSingleThread = AnalyzeResult.ExitCode.CriticalError; - - try - { - string args = string.Format(@"analyze -s {0} -f json -o {1} -k none --single-threaded", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - - exitCodeSingleThread = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - - if (exitCodeSingleThread == AnalyzeResult.ExitCode.Success) - { - string content = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - var result = JsonConvert.DeserializeObject(content); - exitCodeSingleThread = result.Metadata.TotalMatchesCount == 11 && result.Metadata.UniqueMatchesCount == 7 ? AnalyzeResult.ExitCode.Success : AnalyzeResult.ExitCode.NoMatches; - } - } - catch (Exception) - { - } - - Assert.IsTrue(exitCodeSingleThread == AnalyzeResult.ExitCode.Success); - - AnalyzeResult.ExitCode exitCodeMultiThread = AnalyzeResult.ExitCode.CriticalError; - - try - { - - string args = string.Format(@"analyze -s {0} -f json -o {1} -k none", + string args = string.Format(@"analyze -s {0} -f json -o {1} -k none --single-threaded", + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp"), + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + + var exitCodeSingleThread = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, exitCodeSingleThread); + + string content = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + var result = JsonConvert.DeserializeObject(content); + + Assert.AreEqual(11, result.Metadata.TotalMatchesCount); + Assert.AreEqual(7, result.Metadata.UniqueMatchesCount); + + args = string.Format(@"analyze -s {0} -f json -o {1} -k none", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp"), Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - exitCodeMultiThread = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - - if (exitCodeMultiThread == AnalyzeResult.ExitCode.Success) - { - string content = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - var result = JsonConvert.DeserializeObject(content); - exitCodeMultiThread = result.Metadata.TotalMatchesCount == 11 && result.Metadata.UniqueMatchesCount == 7 ? AnalyzeResult.ExitCode.Success : AnalyzeResult.ExitCode.NoMatches; - } - } - catch (Exception) - { - } + var exitCodeMultiThread = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, exitCodeMultiThread); - Assert.IsTrue(exitCodeMultiThread == AnalyzeResult.ExitCode.Success); + content = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + result = JsonConvert.DeserializeObject(content); + Assert.AreEqual(11, result.Metadata.TotalMatchesCount); + Assert.AreEqual(7, result.Metadata.UniqueMatchesCount); } [TestMethod] public void NoMatchesFound_Pass() { - AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"analyze -s {0} -f json -o {1} -k none", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + string args = string.Format(@"analyze -s {0} -f json -o {1} -k none", + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.NoMatches); + Assert.AreEqual(AnalyzeResult.ExitCode.NoMatches, exitCode); } [TestMethod] public void LogTraceLevel_Pass() { - AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"analyze -s {0} -f json -l {1} -v trace -k none", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log1.txt")); + string args = string.Format(@"analyze -s {0} -f json -l {1} -v trace -k none", + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log1.txt")); - exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, exitCode); - string testContent = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log1.txt")); - exitCode = testContent.ToLower().Contains("trace") ? AnalyzeResult.ExitCode.Success : AnalyzeResult.ExitCode.CriticalError; - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); + string testContent = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log1.txt")); + Assert.IsTrue(testContent.Contains("trace", StringComparison.OrdinalIgnoreCase)); } [TestMethod] public void LogErrorLevel_Pass() { - AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"analyze -s {0} -f json -l {1} -v error -k none", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\nofile.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log2.txt")); - - exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - - string testContent = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log2.txt")); - exitCode = testContent.ToLower().Contains("error") ? AnalyzeResult.ExitCode.Success : AnalyzeResult.ExitCode.CriticalError; - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); + string args = string.Format(@"analyze -s {0} -f json -l {1} -v error -k none", + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\nofile.cpp"), + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log2.txt")); + + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + Assert.AreEqual(AnalyzeResult.ExitCode.CriticalError, exitCode); + string testContent = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log2.txt")); + Assert.IsTrue(testContent.Contains("error", StringComparison.OrdinalIgnoreCase)); } [TestMethod] public void LogDebugLevel_Pass() { - AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"analyze -s {0} -f json -l {1} -v debug -k none", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log3.txt")); - - exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - - string testContent = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log3.txt")); - exitCode = testContent.ToLower().Contains("debug") ? AnalyzeResult.ExitCode.Success : AnalyzeResult.ExitCode.CriticalError; - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); + string args = string.Format(@"analyze -s {0} -f json -l {1} -v debug -k none", + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log3.txt")); + + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + Assert.AreEqual(AnalyzeResult.ExitCode.NoMatches, exitCode); + string testContent = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log3.txt")); + Assert.IsTrue(testContent.Contains("debug", StringComparison.OrdinalIgnoreCase)); } [TestMethod] public void InvalidLogPath_Fail() { AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"analyze -s {0} -f json -l {1} -k none", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\badfile.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"badir\log.txt")); - - exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } + string args = string.Format(@"analyze -s {0} -f json -l {1} -k none", + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\badfile.cpp"), + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"badir\log.txt")); - Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.CriticalError);//test fails even when values match unless this case run individually -mstest bug? + exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + + Assert.AreEqual(AnalyzeResult.ExitCode.CriticalError, exitCode);//test fails even when values match unless this case run individually -mstest bug? } [TestMethod] public void InsecureLogPath_Fail() { - AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"analyze -s {0} -f json -l {1} -k none", + string args = string.Format(@"analyze -s {0} -f json -l {1} -k none", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp")); - exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.CriticalError); + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + Assert.AreEqual(AnalyzeResult.ExitCode.CriticalError, exitCode); } [TestMethod] public void NoConsoleOutput_Pass() { - AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; - try - { - string appInspectorPath = Helper.GetPath(Helper.AppPath.appInspectorCLI); - - string args = string.Format(@"analyze -s {0} -x none -f text -k none -o {1} --no-show-progress", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); + string appInspectorPath = Helper.GetPath(Helper.AppPath.appInspectorCLI); + string args = string.Format(@"analyze -s {0} -x none -f text -k none -o {1} --no-show-progress", + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - exitCode = (AnalyzeResult.ExitCode)Helper.RunProcess(appInspectorPath, args, out string testContent); - if (exitCode == AnalyzeResult.ExitCode.Success) - { - exitCode = String.IsNullOrEmpty(testContent) ? AnalyzeResult.ExitCode.Success : AnalyzeResult.ExitCode.CriticalError; - } - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); + var exitCode = (AnalyzeResult.ExitCode)Helper.RunProcess(appInspectorPath, args, out string testContent); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, exitCode); + Assert.IsTrue(string.IsNullOrEmpty(testContent)); } [TestMethod] public void NoConsoleNoFileOutput_Fail() { - AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"analyze -s {0} -x none -f text -k none -l {1} --no-show-progress", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - - exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } + string args = string.Format(@"analyze -s {0} -x none -f text -k none -l {1} --no-show-progress", + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.CriticalError); + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + Assert.AreEqual(AnalyzeResult.ExitCode.CriticalError, exitCode); } } } \ No newline at end of file diff --git a/UnitTest.Commands/Tests_CLI/TestGetTagsCmd.cs b/UnitTest.Commands/Tests_CLI/TestAnalyzeTagsOnlyCmd.cs similarity index 51% rename from UnitTest.Commands/Tests_CLI/TestGetTagsCmd.cs rename to UnitTest.Commands/Tests_CLI/TestAnalyzeTagsOnlyCmd.cs index ddca5158..a92e1cd9 100644 --- a/UnitTest.Commands/Tests_CLI/TestGetTagsCmd.cs +++ b/UnitTest.Commands/Tests_CLI/TestAnalyzeTagsOnlyCmd.cs @@ -14,7 +14,7 @@ namespace ApplicationInspector.Unitprocess.CLICommands /// /// [TestClass] - public class CLITestGetTagsCommand + public class CLITestAnalyzeTagsOnlyCommand { [TestInitialize] public void InitOutput() @@ -42,398 +42,375 @@ public void CleanUp() [TestMethod] public void UnknownFormat_Fail() { - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"get-tags -b -s {0} -f unknown -k none", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp")); - exitCode = (GetTagsResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.CriticalError); + string args = string.Format(@"analyze -b -s {0} -f unknown -k none -t", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp")); + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + Assert.AreEqual(AnalyzeResult.ExitCode.CriticalError, exitCode); } [TestMethod] public void InvalidOutputfilePath_Fail() { - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"get-tags -s {0} -f json -k none -o {1}", + string args = string.Format(@"analyze -s {0} -f json -k none -o {1} -t", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"badir\output.txt")); - exitCode = (GetTagsResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.CriticalError); + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + Assert.AreEqual(AnalyzeResult.ExitCode.CriticalError, exitCode); } [TestMethod] public void InvalidSourcePath_Fail() { - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"get-tags -s {0} -f json -k none -o {1}", + string args = string.Format(@"analyze -s {0} -f json -k none -o {1} -t", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\badfilepath.cpp"), Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - exitCode = (GetTagsResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.CriticalError); + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + Assert.AreEqual(AnalyzeResult.ExitCode.CriticalError, exitCode); } [TestMethod] public void InvalidRulesPath_Fail() { - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; try { - string args = string.Format(@"get-tags -s {0} -r badrulespath -f json -k none -o {1}", + string args = string.Format(@"analyze -s {0} -r badrulespath -f json -k none -o {1} -t", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - exitCode = (GetTagsResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); } catch (Exception) { } - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.CriticalError); + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.CriticalError); } [TestMethod] public void NoDefaultNoCustomRules_Fail() { - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; try { - string args = string.Format(@"get-tags -s {0} -i -f json -k none -o {1}", + string args = string.Format(@"analyze -s {0} -i -f json -k none -o {1} -t", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - exitCode = (GetTagsResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); } catch (Exception) { } - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.CriticalError); + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.CriticalError); } [TestMethod] public void NoDefaultCustomRules_Pass() { - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; try { - string args = string.Format(@"get-tags -s {0} -i -r {1} -f json -k none -o {2}", + string args = string.Format(@"analyze -s {0} -i -r {1} -f json -k none -o {2} -t", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - exitCode = (GetTagsResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); } catch (Exception) { } - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.Success); + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); } [TestMethod] public void DefaultWithCustomRules_Pass() { - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; try { - string args = string.Format(@"get-tags -s {0} -r {1} -f json -k none -o {2}", + string args = string.Format(@"analyze -s {0} -r {1} -f json -k none -o {2} -t", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - exitCode = (GetTagsResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); } catch (Exception) { } - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.Success); + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); } [TestMethod] public void DefaultAndCustomRulesPosMatches_Pass() { - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"get-tags -s {0} -r {1} -f json -k none -o {2}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - - exitCode = (GetTagsResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - - string testContent = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - exitCode = testContent.Contains("Data.Parsing.JSON") ? GetTagsResult.ExitCode.Success : exitCode; - exitCode = testContent.Contains("Data.Custom1") ? GetTagsResult.ExitCode.Success : exitCode; - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.Success); + + string args = string.Format(@"analyze -s {0} -r {1} -f json -k none -o {2} -t", + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), + Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + + string testContent = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, exitCode); + Assert.IsTrue(testContent.Contains("Cryptography.HashAlgorithm.Legacy")); + Assert.IsTrue(testContent.Contains("Data.Custom1")); } [TestMethod] public void ExclusionFilter_Pass() { - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; try { - string args = string.Format(@"get-tags -s {0} -r {1} -f json -o {2} -k {3}", + string args = string.Format(@"analyze -s {0} -r {1} -f json -o {2} -k {3} -t", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\project\one"), Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt"), - ".cpp"); + "*.cpp"); - exitCode = (GetTagsResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); } catch (Exception) { } - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.NoMatches); + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.NoMatches); } [TestMethod] - public void ExpectedTagCountDupsAllowed_Pass() + public void MultiFiles() { - GetTagsResult.ExitCode exitCodeSingleThread = GetTagsResult.ExitCode.CriticalError; - - try - { - string args = string.Format(@"get-tags -s {0} -f json -o {1} -k none --single-threaded", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - - exitCodeSingleThread = (GetTagsResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - - if (exitCodeSingleThread == GetTagsResult.ExitCode.Success) - { - string content = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - var result = JsonConvert.DeserializeObject(content); - exitCodeSingleThread = result.Metadata.TotalMatchesCount == 0 && result.Metadata.UniqueMatchesCount == 0 && result.Metadata.UniqueTags.Count == 7 ? GetTagsResult.ExitCode.Success : GetTagsResult.ExitCode.NoMatches; - } - } - catch (Exception) - { - } - - Assert.IsTrue(exitCodeSingleThread == GetTagsResult.ExitCode.Success); - - GetTagsResult.ExitCode exitCodeMultiThread = GetTagsResult.ExitCode.CriticalError; - - try - { - - string args = string.Format(@"get-tags -s {0} -f json -o {1} -k none", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - - exitCodeMultiThread = (GetTagsResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - - if (exitCodeMultiThread == GetTagsResult.ExitCode.Success) - { - string content = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - var result = JsonConvert.DeserializeObject(content); - exitCodeMultiThread = result.Metadata.TotalMatchesCount == 0 && result.Metadata.UniqueMatchesCount == 0 && result.Metadata.UniqueTags.Count == 7 ? GetTagsResult.ExitCode.Success : GetTagsResult.ExitCode.NoMatches; - } - } - catch (Exception) - { - } + var mainduptags = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp"); + string args = string.Format(@"analyze -s {0} -f json -o {1} -k none -t", + $"{mainduptags}", + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + + var exitCodeSingleThread = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, exitCodeSingleThread); + + string content = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + var result = JsonConvert.DeserializeObject(content); + var matches = result.Metadata.TotalMatchesCount; + var uniqueMatches = result.Metadata.UniqueMatchesCount; + mainduptags = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp"); + args = string.Format(@"analyze -s {0} -f json -o {1} -k none -t", + $"{mainduptags},{mainduptags}", + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + + exitCodeSingleThread = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, exitCodeSingleThread); + + content = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + var result2 = JsonConvert.DeserializeObject(content); + + Assert.AreEqual(matches * 2, result2.Metadata.TotalMatchesCount); + Assert.AreEqual(uniqueMatches, result2.Metadata.UniqueMatchesCount); + } - Assert.IsTrue(exitCodeMultiThread == GetTagsResult.ExitCode.Success); + [TestMethod] + public void ExpectedTagCountDupsAllowed_Pass() + { + string args = string.Format(@"analyze -s {0} -f json -o {1} -k none --single-threaded -t", + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp"), + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + + var exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, exitCode); + string content = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + var result = JsonConvert.DeserializeObject(content); + Assert.AreEqual(0, result.Metadata.TotalMatchesCount); + Assert.AreEqual(0, result.Metadata.UniqueMatchesCount); + Assert.AreEqual(7, result.Metadata.UniqueTags.Count); + + args = string.Format(@"analyze -s {0} -f json -o {1} -k none -t", + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp"), + Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + + exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + + Assert.AreEqual(AnalyzeResult.ExitCode.Success, exitCode); + content = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); + result = JsonConvert.DeserializeObject(content); + Assert.AreEqual(0, result.Metadata.TotalMatchesCount); + Assert.AreEqual(0, result.Metadata.UniqueMatchesCount); + Assert.AreEqual(7, result.Metadata.UniqueTags.Count); + } [TestMethod] public void NoMatchesFound_Pass() { - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; try { - string args = string.Format(@"get-tags -s {0} -f json -o {1} -k none", + string args = string.Format(@"analyze -s {0} -f json -o {1} -k none -t", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - exitCode = (GetTagsResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); } catch (Exception) { } - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.NoMatches); + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.NoMatches); } [TestMethod] public void LogTraceLevel_Pass() { - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; try { - string args = string.Format(@"get-tags -s {0} -f json -l {1} -v trace -k none", + string args = string.Format(@"analyze -s {0} -f json -l {1} -v trace -k none -t", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log1.txt")); - exitCode = (GetTagsResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); string testContent = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log1.txt")); - exitCode = testContent.ToLower().Contains("trace") ? GetTagsResult.ExitCode.Success : GetTagsResult.ExitCode.CriticalError; + exitCode = testContent.ToLower().Contains("trace") ? AnalyzeResult.ExitCode.Success : AnalyzeResult.ExitCode.CriticalError; } catch (Exception) { } - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.Success); + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); } [TestMethod] public void LogErrorLevel_Pass() { - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; try { - string args = string.Format(@"get-tags -s {0} -f json -l {1} -v error -k none", + string args = string.Format(@"analyze -s {0} -f json -l {1} -v error -k none -t", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\nofile.cpp"), Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log2.txt")); - exitCode = (GetTagsResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); string testContent = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log2.txt")); - exitCode = testContent.ToLower().Contains("error") ? GetTagsResult.ExitCode.Success : GetTagsResult.ExitCode.CriticalError; + exitCode = testContent.ToLower().Contains("error") ? AnalyzeResult.ExitCode.Success : AnalyzeResult.ExitCode.CriticalError; } catch (Exception) { } - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.Success); + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); } [TestMethod] public void LogDebugLevel_Pass() { - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; try { - string args = string.Format(@"get-tags -s {0} -f json -l {1} -v debug -k none", + string args = string.Format(@"analyze -s {0} -f json -l {1} -v debug -k none -t", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log3.txt")); - exitCode = (GetTagsResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); string testContent = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log3.txt")); - exitCode = testContent.ToLower().Contains("debug") ? GetTagsResult.ExitCode.Success : GetTagsResult.ExitCode.CriticalError; + exitCode = testContent.ToLower().Contains("debug") ? AnalyzeResult.ExitCode.Success : AnalyzeResult.ExitCode.CriticalError; } catch (Exception) { } - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.Success); + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); } [TestMethod] public void InvalidLogPath_Fail() { - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; try { - string args = string.Format(@"get-tags -s {0} -f json -l {1} -k none", + string args = string.Format(@"analyze -s {0} -f json -l {1} -k none -t", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\badfile.cpp"), Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"badir\log.txt")); - exitCode = (GetTagsResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); } catch (Exception) { } - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.CriticalError);//test fails even when values match unless this case run individually -mstest bug? + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.CriticalError);//test fails even when values match unless this case run individually -mstest bug? } [TestMethod] public void InsecureLogPath_Fail() { - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; try { - string args = string.Format(@"get-tags -s {0} -f json -l {1} -k none", + string args = string.Format(@"analyze -s {0} -f json -l {1} -k none -t", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp")); - exitCode = (GetTagsResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); } catch (Exception) { } - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.CriticalError); + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.CriticalError); } [TestMethod] public void NoConsoleOutput_Pass() { - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; try { string appInspectorPath = Helper.GetPath(Helper.AppPath.appInspectorCLI); - string args = string.Format(@"get-tags -s {0} -x none -f text -k none -o {1} --no-show-progress", + string args = string.Format(@"analyze -s {0} -x none -f text -k none -o {1} --no-show-progress -t", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - exitCode = (GetTagsResult.ExitCode)Helper.RunProcess(appInspectorPath, args, out string testContent); + exitCode = (AnalyzeResult.ExitCode)Helper.RunProcess(appInspectorPath, args, out string testContent); - if (exitCode == GetTagsResult.ExitCode.Success) + if (exitCode == AnalyzeResult.ExitCode.Success) { - exitCode = string.IsNullOrEmpty(testContent) ? GetTagsResult.ExitCode.Success : GetTagsResult.ExitCode.CriticalError; + exitCode = string.IsNullOrEmpty(testContent) ? AnalyzeResult.ExitCode.Success : AnalyzeResult.ExitCode.CriticalError; } } catch (Exception) { } - Assert.AreEqual(GetTagsResult.ExitCode.Success, exitCode); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, exitCode); } [TestMethod] public void NoConsoleNoFileOutput_Fail() { - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; try { - string args = string.Format(@"get-tags -s {0} -x none -f text -k none -l {1} --no-show-progress", + string args = string.Format(@"analyze -s {0} -x none -f text -k none -l {1} --no-show-progress -t", Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - exitCode = (GetTagsResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); + exitCode = (AnalyzeResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); } catch (Exception) { } - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.CriticalError); + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.CriticalError); } } } \ No newline at end of file diff --git a/UnitTest.Commands/Tests_CLI/TestTagDiffCmd.cs b/UnitTest.Commands/Tests_CLI/TestTagDiffCmd.cs index 6c69c41f..20d5d328 100644 --- a/UnitTest.Commands/Tests_CLI/TestTagDiffCmd.cs +++ b/UnitTest.Commands/Tests_CLI/TestTagDiffCmd.cs @@ -139,27 +139,6 @@ public void InEquality_Fail() Assert.IsTrue(exitCode == TagDiffResult.ExitCode.TestFailed); } - [TestMethod] - public void SameSrcFile_Fail() - { - TagDiffResult.ExitCode exitCode = TagDiffResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"tagdiff --src1 {0} --src2 {1} -k none -l {2}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - - exitCode = (TagDiffResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == TagDiffResult.ExitCode.CriticalError); - } - [TestMethod] public void OneSrcResult_Fail() { diff --git a/UnitTest.Commands/Tests_CLI/TestTagTestCmd.cs b/UnitTest.Commands/Tests_CLI/TestTagTestCmd.cs deleted file mode 100644 index c8742bb2..00000000 --- a/UnitTest.Commands/Tests_CLI/TestTagTestCmd.cs +++ /dev/null @@ -1,493 +0,0 @@ -using ApplicationInspector.Unitprocess.Misc; -using Microsoft.ApplicationInspector.Commands; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.IO; - -namespace ApplicationInspector.Unitprocess.CLICommands -{ - /// - /// Test class for Analyze Commands - /// Each method really needs to be complete i.e. options and command objects created and checked for exceptions etc. based on inputs so - /// doesn't create a set of shared objects - /// - /// - [TestClass] - public class CLITestTagTestCmd - { - [TestInitialize] - public void InitOutput() - { - Directory.CreateDirectory(Helper.GetPath(Helper.AppPath.testOutput)); - } - - [TestCleanup] - public void CleanUp() - { - try - { - Directory.Delete(Helper.GetPath(Helper.AppPath.testOutput), true); - } - catch - { - } - - //because these are static and each test is meant to be indpendent null assign the references to create the log - WriteOnce.Log = null; - Utils.Logger = null; - } - - [TestMethod] - public void RulesPresent_Pass() - { - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - - try - { - string args = string.Format(@"tagtest -s {0} -r {1} -k none -l {2}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - - exitCode = (TagTestResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - exitCode = TagTestResult.ExitCode.CriticalError; - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestPassed); - } - - [TestMethod] - public void RulesPresent_Fail() - { - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - - try - { - string args = string.Format(@"tagtest -s {0} -r {1} -k none -l {2}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainx.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - - exitCode = (TagTestResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestFailed); - } - - [TestMethod] - public void ZipReadDiff_Pass() - { - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - - try - { - string args = string.Format(@"tagtest -s {0} -r {1} -k none -l {2}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"zipped\main.zip"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - - exitCode = (TagTestResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestPassed); - } - - [TestMethod] - public void RulesNotPresent_Pass() - { - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - - try - { - string args = string.Format(@"tagtest -s {0} -r {1} -t rulesnotpresent -k none -l {2}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainx.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - - exitCode = (TagTestResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestPassed); - } - - [TestMethod] - public void RulesNotPresent_Fail() - { - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - - try - { - string args = string.Format(@"tagtest -s {0} -r {1} -t rulesnotpresent -k none -l {2}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - - exitCode = (TagTestResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestFailed); - } - - [TestMethod] - public void InvalidSourcePath_Fail() - { - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - - try - { - string args = string.Format(@"tagtest -s {0} -r {1} -k none -l {2}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\badir\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - - exitCode = (TagTestResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.CriticalError); - } - - [TestMethod] - public void RulesPresentNoResults_Fail() - { - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - - try - { - string args = string.Format(@"tagtest -s {0} -r {1} -k none -l {2}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - - exitCode = (TagTestResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestFailed); - } - - [TestMethod] - public void RulesNotPresentNoResults_Success() - { - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - - try - { - string args = string.Format(@"tagtest -s {0} -r {1} -t rulesnotpresent -k none -l {2}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - - exitCode = (TagTestResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestPassed); - } - - [TestMethod] - public void RulesNotPresentNoResults_Fail() - { - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - - try - { - string args = string.Format(@"tagtest -s {0} -r rulesnotpresent -r {1} -k none -l {2}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myfakerule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - - exitCode = (TagTestResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.CriticalError); - } - - [TestMethod] - public void NoRules_Fail() - { - TagTestOptions options = new TagTestOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path - }; - - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - - try - { - string args = string.Format(@"tagtest -s {0} -k none -l {1}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - - exitCode = (TagTestResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.CriticalError); - } - - [TestMethod] - public void RulesPresentToTxtOutFile_Pass() - { - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - - try - { - string args = string.Format(@"tagtest -s {0} -r {1} -f text -k none -o {2} -l {3}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - - exitCode = (TagTestResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestPassed); - } - - [TestMethod] - public void RulesPresentToJsonOutFile_Pass() - { - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - - try - { - string args = string.Format(@"tagtest -s {0} -r {1} -f json -k none -o {2} -l {3}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - - exitCode = (TagTestResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestPassed); - } - - [TestMethod] - public void RulesPresentToUnknownFormat_Fail() - { - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - - try - { - string args = string.Format(@"tagtest -s {0} -r {1} -f unknown -k none -o {2} -l {3}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - - exitCode = (TagTestResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.CriticalError); - } - - [TestMethod] - public void LogTraceLevel_Pass() - { - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - - try - { - string args = string.Format(@"tagtest -s {0} -r {1} -k none -v trace -l {2}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"mybadrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - - exitCode = (TagTestResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - - if (exitCode == TagTestResult.ExitCode.CriticalError) - { - string testContent = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - exitCode = testContent.ToLower().Contains("trace") ? TagTestResult.ExitCode.TestPassed : TagTestResult.ExitCode.CriticalError; - } - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestPassed); - } - - [TestMethod] - public void LogErrorLevel_Pass() - { - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"tagtest -s {0} -r {1} -k none -v error -l {2}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\badfilepath.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - - exitCode = (TagTestResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - - if (exitCode == TagTestResult.ExitCode.CriticalError) - { - string testContent = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - exitCode = testContent.ToLower().Contains("error") ? TagTestResult.ExitCode.TestPassed : TagTestResult.ExitCode.CriticalError; - } - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestPassed); - } - - [TestMethod] - public void LogDebugLevel_Pass() - { - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"tagtest -s {0} -r {1} -k none -v debug -l {2}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - - exitCode = (TagTestResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - - if (exitCode == TagTestResult.ExitCode.CriticalError) - { - string testContent = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - exitCode = testContent.ToLower().Contains("debug") ? TagTestResult.ExitCode.TestPassed : TagTestResult.ExitCode.CriticalError; - } - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestPassed); - } - - [TestMethod] - public void InvalidLogPath_Fail() - { - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"tagtest -s {0} -r {1} -k none -l {2}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"\baddir\log.txt")); - - exitCode = (TagTestResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.CriticalError);//test fails even when values match unless this case run individually -mstest bug? - } - - [TestMethod] - public void InsecureLogPath_Fail() - { - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"tagtest -s {0} -r {1} -k none -l {2}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\blank.cpp")); - - exitCode = (TagTestResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.CriticalError); - } - - [TestMethod] - public void NoConsoleOutput_Pass() - { - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - try - { - string appInspectorPath = Helper.GetPath(Helper.AppPath.appInspectorCLI); - string args = string.Format(@"tagtest -s {0} -r {1} -k none -x none -f text -o {2}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"output.txt")); - - exitCode = (TagTestResult.ExitCode)Helper.RunProcess(appInspectorPath, args, out string testContent); - - if (exitCode == TagTestResult.ExitCode.TestPassed) - { - exitCode = String.IsNullOrEmpty(testContent) ? TagTestResult.ExitCode.TestPassed : TagTestResult.ExitCode.CriticalError; - } - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestPassed); - } - - [TestMethod] - public void NoConsoleNoFileOutput_Fail() - { - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - try - { - string args = string.Format(@"tagtest -s {0} -r {1} -k none -x none -l {2}", - Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"log.txt")); - - exitCode = (TagTestResult.ExitCode)Microsoft.ApplicationInspector.CLI.Program.Main(args.Split(' ')); - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.CriticalError); - } - } -} \ No newline at end of file diff --git a/UnitTest.Commands/Tests_NuGet/TestAnalyzeCmd.cs b/UnitTest.Commands/Tests_NuGet/TestAnalyzeCmd.cs index d1440642..c2b5992c 100644 --- a/UnitTest.Commands/Tests_NuGet/TestAnalyzeCmd.cs +++ b/UnitTest.Commands/Tests_NuGet/TestAnalyzeCmd.cs @@ -1,6 +1,7 @@ using ApplicationInspector.Unitprocess.Misc; using Microsoft.ApplicationInspector.Commands; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Newtonsoft.Json; using System; using System.IO; using System.Linq; @@ -45,8 +46,8 @@ public void InvalidLogPath_Fail() { AnalyzeOptions options = new AnalyzeOptions() { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"baddir\log.txt") }; @@ -69,8 +70,8 @@ public void BasicAnalyze_Pass() { AnalyzeOptions options = new AnalyzeOptions() { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none" //allow source under unittest path + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + FilePathExclusions = Array.Empty() //allow source under unittest path }; AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; @@ -93,8 +94,8 @@ public void BasicZipRead_Pass() { AnalyzeOptions options = new AnalyzeOptions() { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"zipped\main.zip"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"zipped\main.zip") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path }; AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; @@ -117,8 +118,8 @@ public void InvalidSourcePath_Fail() { AnalyzeOptions options = new AnalyzeOptions() { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"baddir\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"baddir\main.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path }; AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; @@ -141,8 +142,8 @@ public void InvalidRulesPath_Fail() { AnalyzeOptions options = new AnalyzeOptions() { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"notfound.json") }; @@ -166,8 +167,8 @@ public void NoDefaultNoCustomRules_Fail() { AnalyzeOptions options = new AnalyzeOptions() { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path IgnoreDefaultRules = true, }; @@ -191,8 +192,8 @@ public void NoDefaultCustomRules_Pass() { AnalyzeOptions options = new AnalyzeOptions() { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path IgnoreDefaultRules = true, CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), }; @@ -217,8 +218,8 @@ public void DefaultWithCustomRules_Pass() { AnalyzeOptions options = new AnalyzeOptions() { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), }; @@ -242,28 +243,23 @@ public void DefaultAndCustomRulesMatched_Pass() { AnalyzeOptions options = new AnalyzeOptions() { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json") }; - AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; try { AnalyzeCommand command = new AnalyzeCommand(options); AnalyzeResult result = command.GetResult(); - if (result.Metadata.UniqueTags.Any(v => v.Contains("Authentication.General")) && - result.Metadata.UniqueTags.Any(v => v.Contains("Data.Custom1"))) - { - exitCode = AnalyzeResult.ExitCode.Success; - } + Assert.AreEqual(AnalyzeResult.ExitCode.Success, result.ResultCode); + Assert.IsTrue(result.Metadata.UniqueTags.Any(v => v.Contains("Cryptography.Encryption.General"))); + Assert.IsTrue(result.Metadata.UniqueTags.Any(v => v.Contains("Data.Custom1"))); } catch (Exception) { - exitCode = AnalyzeResult.ExitCode.CriticalError; + throw; } - - Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); } [TestMethod] @@ -271,8 +267,8 @@ public void ExclusionFilter_Pass() { AnalyzeOptions options = new AnalyzeOptions() { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\project\one"), - FilePathExclusions = "main.cpp" + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\project\one") }, + FilePathExclusions = new string[] { "**/main.cpp" } }; AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; @@ -295,8 +291,8 @@ public async Task ExpectedTagCountAsync_Pass() { AnalyzeOptions options = new AnalyzeOptions() { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path SingleThread = true }; AnalyzeCommand command = new AnalyzeCommand(options); @@ -307,89 +303,101 @@ public async Task ExpectedTagCountAsync_Pass() } [TestMethod] - public async Task ScanUnknownFileTypesTest_Include() + public void ScanUnknownFileTypesTest_Include() { AnalyzeOptions options = new AnalyzeOptions() { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unknowntest"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unknowntest") }, + FilePathExclusions = Array.Empty(), ScanUnknownTypes = true }; AnalyzeCommand command = new AnalyzeCommand(options); - AnalyzeResult result = await command.GetResultAsync(new CancellationToken()); + AnalyzeResult result = command.GetResult(); Assert.AreEqual(AnalyzeResult.ExitCode.Success, result.ResultCode); Assert.AreEqual(2, result.Metadata.TotalFiles); Assert.AreEqual(0, result.Metadata.FilesSkipped); Assert.AreEqual(2, result.Metadata.FilesAffected); - Assert.AreEqual(74, result.Metadata.TotalMatchesCount); - Assert.AreEqual(24, result.Metadata.UniqueMatchesCount); + Assert.AreEqual(65, result.Metadata.TotalMatchesCount); + Assert.AreEqual(22, result.Metadata.UniqueMatchesCount); } [TestMethod] - public async Task ScanUnknownFileTypesTest_Exclude() + public void ScanUnknownFileTypesTest_Exclude() { AnalyzeOptions options = new AnalyzeOptions() { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unknowntest"), - FilePathExclusions = "none", //allow source under unittest path - ScanUnknownTypes = false + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unknowntest") }, + FilePathExclusions = Array.Empty(), + ScanUnknownTypes = false, + SingleThread = true }; AnalyzeCommand command = new AnalyzeCommand(options); - AnalyzeResult result = await command.GetResultAsync(new CancellationToken()); + AnalyzeResult result = command.GetResult(); Assert.AreEqual(AnalyzeResult.ExitCode.Success, result.ResultCode); Assert.AreEqual(2, result.Metadata.TotalFiles); Assert.AreEqual(1, result.Metadata.FilesSkipped); Assert.AreEqual(1, result.Metadata.FilesAffected); - Assert.AreEqual(39, result.Metadata.TotalMatchesCount); - Assert.AreEqual(23, result.Metadata.UniqueMatchesCount); + Assert.AreEqual(35, result.Metadata.TotalMatchesCount); + Assert.AreEqual(21, result.Metadata.UniqueMatchesCount); } [TestMethod] - public void ExpectedTagCountDupsAllowed_Pass() + public void MultiPath_Pass() { AnalyzeOptions options = new AnalyzeOptions() { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp"), - FilePathExclusions = "none", //allow source under unittest path - SingleThread = true + SourcePath = new string[] + { + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp") + }, + FilePathExclusions = Array.Empty(), }; - AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; - try + AnalyzeCommand command = new AnalyzeCommand(options); + AnalyzeResult result = command.GetResult(); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, result.ResultCode); + + AnalyzeOptions options2 = new AnalyzeOptions() { - AnalyzeCommand command = new AnalyzeCommand(options); - AnalyzeResult result = command.GetResult(); - exitCode = result.ResultCode; - if (exitCode == AnalyzeResult.ExitCode.Success) + SourcePath = new string[2] { - exitCode = result.Metadata.TotalMatchesCount == 11 && result.Metadata.UniqueMatchesCount == 7 ? AnalyzeResult.ExitCode.Success : AnalyzeResult.ExitCode.NoMatches; - } - } - catch (Exception) - { - exitCode = AnalyzeResult.ExitCode.CriticalError; - } + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp"), + Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp") + }, + FilePathExclusions = Array.Empty(), + }; - Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); + AnalyzeCommand command2 = new AnalyzeCommand(options2); + AnalyzeResult result2 = command2.GetResult(); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, result2.ResultCode); + Assert.AreEqual(result.Metadata.TotalMatchesCount * 2, result2.Metadata.TotalMatchesCount); + Assert.AreEqual(result.Metadata.UniqueMatchesCount, result2.Metadata.UniqueMatchesCount); + } - AnalyzeResult.ExitCode exitCodeMultiThread = AnalyzeResult.ExitCode.CriticalError; - options.SingleThread = false; - try - { - AnalyzeCommand command = new AnalyzeCommand(options); - AnalyzeResult result = command.GetResult(); - exitCodeMultiThread = result.ResultCode; - if (exitCodeMultiThread == AnalyzeResult.ExitCode.Success) - { - exitCodeMultiThread = result.Metadata.TotalMatchesCount == 11 && result.Metadata.UniqueMatchesCount == 7 ? AnalyzeResult.ExitCode.Success : AnalyzeResult.ExitCode.NoMatches; - } - } - catch (Exception) + + [TestMethod] + public void ExpectedTagCountDupsAllowed_Pass() + { + AnalyzeOptions options = new AnalyzeOptions() { - exitCodeMultiThread = AnalyzeResult.ExitCode.CriticalError; - } + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp") }, + FilePathExclusions = Array.Empty(), + SingleThread = true + }; + + AnalyzeCommand command = new AnalyzeCommand(options); + AnalyzeResult result = command.GetResult(); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, result.ResultCode); + Assert.AreEqual(11, result.Metadata.TotalMatchesCount); + Assert.AreEqual(7, result.Metadata.UniqueMatchesCount); - Assert.IsTrue(exitCodeMultiThread == AnalyzeResult.ExitCode.Success); + + options.SingleThread = false; + command = new AnalyzeCommand(options); + result = command.GetResult(); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, result.ResultCode); + Assert.AreEqual(11, result.Metadata.TotalMatchesCount); + Assert.AreEqual(7, result.Metadata.UniqueMatchesCount); } [TestMethod] @@ -397,8 +405,8 @@ public void NoMatchesFound_Pass() { AnalyzeOptions options = new AnalyzeOptions() { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path }; AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; @@ -421,8 +429,8 @@ public void LogTraceLevel_Pass() { AnalyzeOptions options = new AnalyzeOptions() { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path LogFileLevel = "trace", LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"logtrace.txt"), @@ -457,8 +465,8 @@ public void LogErrorLevel_Pass() { AnalyzeOptions options = new AnalyzeOptions() { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\badfile.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\badfile.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path LogFileLevel = "error", LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"logerror.txt"), @@ -490,8 +498,8 @@ public void LogDebugLevel_Pass() { AnalyzeOptions options = new AnalyzeOptions() { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path LogFileLevel = "debug", LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"logdebug.txt"), CloseLogOnCommandExit = true @@ -526,8 +534,8 @@ public void InsecureLogPath_Fail() { AnalyzeOptions options = new AnalyzeOptions() { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), }; @@ -551,8 +559,8 @@ public void NoConsoleOutput_Pass() { AnalyzeOptions options = new AnalyzeOptions() { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path ConsoleVerbosityLevel = "none" }; diff --git a/UnitTest.Commands/Tests_NuGet/TestAnalyzeTagsOnlyCmd.cs b/UnitTest.Commands/Tests_NuGet/TestAnalyzeTagsOnlyCmd.cs new file mode 100644 index 00000000..dc4d30bb --- /dev/null +++ b/UnitTest.Commands/Tests_NuGet/TestAnalyzeTagsOnlyCmd.cs @@ -0,0 +1,567 @@ +using ApplicationInspector.Unitprocess.Misc; +using Microsoft.ApplicationInspector.Commands; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace ApplicationInspector.Unitprocess.Commands +{ + /// + /// Test class for Analyze Commands + /// Each method really needs to be complete i.e. options and command objects created and checked for exceptions etc. based on inputs so + /// doesn't create a set of shared objects + /// Note: in order to avoid log reuse, include the optional parameter CloseLogOnCommandExit = true + /// + [TestClass] + public class TestAnalyzeTagsOnlyCmd + { + [TestInitialize] + public void InitOutput() + { + Directory.CreateDirectory(Helper.GetPath(Helper.AppPath.testOutput)); + } + + [TestCleanup] + public void CleanUp() + { + try + { + Directory.Delete(Helper.GetPath(Helper.AppPath.testOutput), true); + } + catch + { + } + + //because these are static and each test is meant to be indpendent null assign the references to create the log + WriteOnce.Log = null; + Utils.Logger = null; + } + + [TestMethod] + public void InvalidLogPath_Fail() + { + AnalyzeOptions options = new AnalyzeOptions() + { + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path + LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"baddir\log.txt"), + TagsOnly = true + }; + + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; + try + { + AnalyzeCommand command = new AnalyzeCommand(options); + AnalyzeResult result = command.GetResult(); + exitCode = result.ResultCode; + } + catch (Exception) + { + } + + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.CriticalError);//test fails even when values match unless this case run individually -mstest bug? + } + + [TestMethod] + public void BasicAnalyze_Pass() + { + AnalyzeOptions options = new AnalyzeOptions() + { + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + FilePathExclusions = Array.Empty(), + TagsOnly = true + }; + + AnalyzeCommand command = new AnalyzeCommand(options); + AnalyzeResult result = command.GetResult(); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, result.ResultCode); + } + + [TestMethod] + public void BasicZipRead_Pass() + { + AnalyzeOptions options = new AnalyzeOptions() + { + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"zipped\main.zip") }, + FilePathExclusions = Array.Empty(), + TagsOnly = true + }; + + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; + try + { + AnalyzeCommand command = new AnalyzeCommand(options); + AnalyzeResult result = command.GetResult(); + exitCode = result.ResultCode; + } + catch (Exception) + { + + } + + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); + } + + [TestMethod] + public void InvalidSourcePath_Fail() + { + AnalyzeOptions options = new AnalyzeOptions() + { + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"baddir\main.cpp") }, + FilePathExclusions = Array.Empty(), + TagsOnly = true + }; + + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; + try + { + AnalyzeCommand command = new AnalyzeCommand(options); + AnalyzeResult result = command.GetResult(); + exitCode = result.ResultCode; + } + catch (Exception) + { + //check for specific error if desired + } + + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.CriticalError); + } + + [TestMethod] + public void InvalidRulesPath_Fail() + { + AnalyzeOptions options = new AnalyzeOptions() + { + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + FilePathExclusions = Array.Empty(), + TagsOnly = true, + CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"notfound.json") + }; + + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; + try + { + AnalyzeCommand command = new AnalyzeCommand(options); + AnalyzeResult result = command.GetResult(); + exitCode = result.ResultCode; + } + catch (Exception) + { + //check for specific error if desired + } + + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.CriticalError); + } + + [TestMethod] + public void NoDefaultNoCustomRules_Fail() + { + AnalyzeOptions options = new AnalyzeOptions() + { + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + FilePathExclusions = Array.Empty(), + TagsOnly = true, + IgnoreDefaultRules = true, + }; + + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; + try + { + AnalyzeCommand command = new AnalyzeCommand(options); + AnalyzeResult result = command.GetResult(); + exitCode = result.ResultCode; + } + catch (Exception) + { + //check for specific error if desired + } + + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.CriticalError); + } + + [TestMethod] + public void NoDefaultCustomRules_Pass() + { + AnalyzeOptions options = new AnalyzeOptions() + { + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + FilePathExclusions = Array.Empty(), + TagsOnly = true, + IgnoreDefaultRules = true, + CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), + }; + + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; + try + { + AnalyzeCommand command = new AnalyzeCommand(options); + AnalyzeResult result = command.GetResult(); + exitCode = result.ResultCode; + } + catch (Exception) + { + exitCode = AnalyzeResult.ExitCode.CriticalError; + } + + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); + } + + [TestMethod] + public void DefaultWithCustomRules_Pass() + { + AnalyzeOptions options = new AnalyzeOptions() + { + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + FilePathExclusions = Array.Empty(), + TagsOnly = true, + CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), + }; + + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; + try + { + AnalyzeCommand command = new AnalyzeCommand(options); + AnalyzeResult result = command.GetResult(); + exitCode = result.ResultCode; + } + catch (Exception) + { + exitCode = AnalyzeResult.ExitCode.CriticalError; + } + + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); + } + + [TestMethod] + public void DefaultAndCustomRulesMatched_Pass() + { + AnalyzeOptions options = new AnalyzeOptions() + { + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + FilePathExclusions = Array.Empty(), + TagsOnly = true, + CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json") + }; + + try + { + AnalyzeCommand command = new AnalyzeCommand(options); + AnalyzeResult result = command.GetResult(); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, result.ResultCode); + Assert.IsTrue(result.Metadata.UniqueTags.Any(v => v.Contains("Cryptography.HashAlgorithm.Legacy"))); + Assert.IsTrue(result.Metadata.UniqueTags.Any(v => v.Contains("Data.Custom1"))); + } + catch (Exception) + { + throw; + } + } + + [TestMethod] + public void ExclusionFilter_Pass() + { + AnalyzeOptions options = new AnalyzeOptions() + { + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\project\one") }, + FilePathExclusions = new string[] { "main.cpp" }, + TagsOnly = true + }; + + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; + try + { + AnalyzeCommand command = new AnalyzeCommand(options); + AnalyzeResult result = command.GetResult(); + exitCode = result.ResultCode; + } + catch (Exception) + { + //check for specific error if desired + } + + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.NoMatches); + } + + [TestMethod] + public async Task ExpectedTagCountAsync() + { + AnalyzeOptions options = new AnalyzeOptions() + { + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path + SingleThread = true, + TagsOnly = true + }; + + AnalyzeCommand command = new AnalyzeCommand(options); + var result = await command.GetResultAsync(new CancellationToken()); + Assert.AreEqual(AnalyzeResult.ExitCode.Success, result.ResultCode); + Assert.AreEqual(0, result.Metadata.TotalMatchesCount); + Assert.AreEqual(0, result.Metadata.UniqueMatchesCount); + Assert.AreEqual(7, result.Metadata.UniqueTags.Count); + } + + [TestMethod] + public void ExpectedTagCount() + { + AnalyzeOptions options = new AnalyzeOptions() + { + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path + SingleThread = true, + TagsOnly = true + }; + + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; + try + { + AnalyzeCommand command = new AnalyzeCommand(options); + AnalyzeResult result = command.GetResult(); + exitCode = result.ResultCode; + if (exitCode == AnalyzeResult.ExitCode.Success) + { + exitCode = result.Metadata.TotalMatchesCount == 0 && result.Metadata.UniqueMatchesCount == 0 && result.Metadata.UniqueTags.Count == 7 ? AnalyzeResult.ExitCode.Success : AnalyzeResult.ExitCode.NoMatches; + } + } + catch (Exception) + { + exitCode = AnalyzeResult.ExitCode.CriticalError; + } + + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); + + AnalyzeResult.ExitCode exitCodeMultiThread = AnalyzeResult.ExitCode.CriticalError; + options.SingleThread = false; + try + { + AnalyzeCommand command = new AnalyzeCommand(options); + AnalyzeResult result = command.GetResult(); + exitCodeMultiThread = result.ResultCode; + if (exitCodeMultiThread == AnalyzeResult.ExitCode.Success) + { + exitCodeMultiThread = result.Metadata.TotalMatchesCount == 0 && result.Metadata.UniqueMatchesCount == 0 && result.Metadata.UniqueTags.Count == 7 ? AnalyzeResult.ExitCode.Success : AnalyzeResult.ExitCode.NoMatches; + } + } + catch (Exception) + { + exitCodeMultiThread = AnalyzeResult.ExitCode.CriticalError; + } + + Assert.IsTrue(exitCodeMultiThread == AnalyzeResult.ExitCode.Success); + } + + [TestMethod] + public void NoMatchesFound_Pass() + { + AnalyzeOptions options = new AnalyzeOptions() + { + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp") }, + FilePathExclusions = Array.Empty(), + TagsOnly = true + }; + + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; + try + { + AnalyzeCommand command = new AnalyzeCommand(options); + AnalyzeResult result = command.GetResult(); + exitCode = result.ResultCode; + } + catch (Exception) + { + exitCode = AnalyzeResult.ExitCode.CriticalError; + } + + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.NoMatches); + } + + [TestMethod] + public void LogTraceLevel_Pass() + { + AnalyzeOptions options = new AnalyzeOptions() + { + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp") }, + FilePathExclusions = Array.Empty(), + TagsOnly = true, + LogFileLevel = "trace", + LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"logtrace.txt"), + }; + + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; + try + { + AnalyzeCommand command = new AnalyzeCommand(options); + AnalyzeResult result = command.GetResult(); + exitCode = result.ResultCode; + string testLogContent = File.ReadAllText(options.LogFilePath); + if (String.IsNullOrEmpty(testLogContent)) + { + exitCode = AnalyzeResult.ExitCode.CriticalError; + } + else if (testLogContent.ToLower().Contains("trace")) + { + exitCode = AnalyzeResult.ExitCode.Success; + } + } + catch (Exception) + { + exitCode = AnalyzeResult.ExitCode.CriticalError; + } + + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); + } + + [TestMethod] + public void LogErrorLevel_Pass() + { + AnalyzeOptions options = new AnalyzeOptions() + { + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\badfile.cpp") }, + FilePathExclusions = Array.Empty(), + TagsOnly = true, + LogFileLevel = "error", + LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"logerror.txt"), + }; + + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; + try + { + AnalyzeCommand command = new AnalyzeCommand(options); + } + catch (Exception) + { + string testLogContent = File.ReadAllText(options.LogFilePath); + if (!String.IsNullOrEmpty(testLogContent) && testLogContent.ToLower().Contains("error")) + { + exitCode = AnalyzeResult.ExitCode.Success; + } + else + { + exitCode = AnalyzeResult.ExitCode.CriticalError; + } + } + + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); + } + + [TestMethod] + public void LogDebugLevel_Pass() + { + AnalyzeOptions options = new AnalyzeOptions() + { + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + FilePathExclusions = Array.Empty(), + TagsOnly = true, + LogFileLevel = "debug", + LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"logdebug.txt"), + CloseLogOnCommandExit = true + }; + + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; + try + { + AnalyzeCommand command = new AnalyzeCommand(options); + AnalyzeResult result = command.GetResult(); + exitCode = result.ResultCode; + string testLogContent = File.ReadAllText(options.LogFilePath); + if (String.IsNullOrEmpty(testLogContent)) + { + exitCode = AnalyzeResult.ExitCode.CriticalError; + } + else if (testLogContent.ToLower().Contains("debug")) + { + exitCode = AnalyzeResult.ExitCode.Success; + } + } + catch (Exception) + { + //check for specific error if desired + } + + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); + } + + [TestMethod] + public void InsecureLogPath_Fail() + { + AnalyzeOptions options = new AnalyzeOptions() + { + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + FilePathExclusions = Array.Empty(), + TagsOnly = true, + LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), + }; + + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; + try + { + AnalyzeCommand command = new AnalyzeCommand(options); + AnalyzeResult result = command.GetResult(); + exitCode = result.ResultCode; + } + catch (Exception) + { + //check for specific error if desired + } + + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.CriticalError); + } + + [TestMethod] + public void NoConsoleOutput_Pass() + { + AnalyzeOptions options = new AnalyzeOptions() + { + SourcePath = new string[1] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp") }, + FilePathExclusions = Array.Empty(), + TagsOnly = true, + ConsoleVerbosityLevel = "none" + }; + + AnalyzeResult.ExitCode exitCode = AnalyzeResult.ExitCode.CriticalError; + try + { + // Attempt to open output file. + using (var writer = new StreamWriter(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"consoleout.txt"))) + { + // Redirect standard output from the console to the output file. + Console.SetOut(writer); + + AnalyzeCommand command = new AnalyzeCommand(options); + AnalyzeResult result = command.GetResult(); + exitCode = result.ResultCode; + try + { + string testContent = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"consoleout.txt")); + if (String.IsNullOrEmpty(testContent)) + { + exitCode = AnalyzeResult.ExitCode.Success; + } + else + { + exitCode = AnalyzeResult.ExitCode.NoMatches; + } + } + catch (Exception) + { + exitCode = AnalyzeResult.ExitCode.Success;//no console output file found + } + } + } + catch (Exception) + { + exitCode = AnalyzeResult.ExitCode.CriticalError; + } + + //reset to normal + var standardOutput = new StreamWriter(Console.OpenStandardOutput()); + standardOutput.AutoFlush = true; + Console.SetOut(standardOutput); + + Assert.IsTrue(exitCode == AnalyzeResult.ExitCode.Success); + } + } +} \ No newline at end of file diff --git a/UnitTest.Commands/Tests_NuGet/TestGetTagsCmd.cs b/UnitTest.Commands/Tests_NuGet/TestGetTagsCmd.cs deleted file mode 100644 index 5461b885..00000000 --- a/UnitTest.Commands/Tests_NuGet/TestGetTagsCmd.cs +++ /dev/null @@ -1,566 +0,0 @@ -using ApplicationInspector.Unitprocess.Misc; -using Microsoft.ApplicationInspector.Commands; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace ApplicationInspector.Unitprocess.Commands -{ - /// - /// Test class for Analyze Commands - /// Each method really needs to be complete i.e. options and command objects created and checked for exceptions etc. based on inputs so - /// doesn't create a set of shared objects - /// Note: in order to avoid log reuse, include the optional parameter CloseLogOnCommandExit = true - /// - [TestClass] - public class TestGetTagsCmd - { - [TestInitialize] - public void InitOutput() - { - Directory.CreateDirectory(Helper.GetPath(Helper.AppPath.testOutput)); - } - - [TestCleanup] - public void CleanUp() - { - try - { - Directory.Delete(Helper.GetPath(Helper.AppPath.testOutput), true); - } - catch - { - } - - //because these are static and each test is meant to be indpendent null assign the references to create the log - WriteOnce.Log = null; - Utils.Logger = null; - } - - [TestMethod] - public void InvalidLogPath_Fail() - { - GetTagsCommandOptions options = new GetTagsCommandOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path - LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"baddir\log.txt") - }; - - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; - try - { - GetTagsCommand command = new GetTagsCommand(options); - GetTagsResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.CriticalError);//test fails even when values match unless this case run individually -mstest bug? - } - - [TestMethod] - public void BasicAnalyze_Pass() - { - GetTagsCommandOptions options = new GetTagsCommandOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none" //allow source under unittest path - }; - - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; - try - { - GetTagsCommand command = new GetTagsCommand(options); - GetTagsResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - - } - - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.Success); - } - - [TestMethod] - public void BasicZipRead_Pass() - { - GetTagsCommandOptions options = new GetTagsCommandOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"zipped\main.zip"), - FilePathExclusions = "none", //allow source under unittest path - }; - - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; - try - { - GetTagsCommand command = new GetTagsCommand(options); - GetTagsResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - - } - - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.Success); - } - - [TestMethod] - public void InvalidSourcePath_Fail() - { - GetTagsCommandOptions options = new GetTagsCommandOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"baddir\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path - }; - - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; - try - { - GetTagsCommand command = new GetTagsCommand(options); - GetTagsResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.CriticalError); - } - - [TestMethod] - public void InvalidRulesPath_Fail() - { - GetTagsCommandOptions options = new GetTagsCommandOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path - CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"notfound.json") - }; - - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; - try - { - GetTagsCommand command = new GetTagsCommand(options); - GetTagsResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.CriticalError); - } - - [TestMethod] - public void NoDefaultNoCustomRules_Fail() - { - GetTagsCommandOptions options = new GetTagsCommandOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path - IgnoreDefaultRules = true, - }; - - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; - try - { - GetTagsCommand command = new GetTagsCommand(options); - GetTagsResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.CriticalError); - } - - [TestMethod] - public void NoDefaultCustomRules_Pass() - { - GetTagsCommandOptions options = new GetTagsCommandOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path - IgnoreDefaultRules = true, - CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - }; - - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; - try - { - GetTagsCommand command = new GetTagsCommand(options); - GetTagsResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - exitCode = GetTagsResult.ExitCode.CriticalError; - } - - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.Success); - } - - [TestMethod] - public void DefaultWithCustomRules_Pass() - { - GetTagsCommandOptions options = new GetTagsCommandOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path - CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - }; - - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; - try - { - GetTagsCommand command = new GetTagsCommand(options); - GetTagsResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - exitCode = GetTagsResult.ExitCode.CriticalError; - } - - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.Success); - } - - [TestMethod] - public void DefaultAndCustomRulesMatched_Pass() - { - GetTagsCommandOptions options = new GetTagsCommandOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path - CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json") - }; - - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; - try - { - GetTagsCommand command = new GetTagsCommand(options); - GetTagsResult result = command.GetResult(); - if (result.Metadata.UniqueTags.Any(v => v.Contains("Authentication.General")) && - result.Metadata.UniqueTags.Any(v => v.Contains("Data.Custom1"))) - { - exitCode = GetTagsResult.ExitCode.Success; - } - } - catch (Exception) - { - exitCode = GetTagsResult.ExitCode.CriticalError; - } - - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.Success); - } - - [TestMethod] - public void ExclusionFilter_Pass() - { - GetTagsCommandOptions options = new GetTagsCommandOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\project\one"), - FilePathExclusions = "main.cpp" - }; - - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; - try - { - GetTagsCommand command = new GetTagsCommand(options); - GetTagsResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.NoMatches); - } - - [TestMethod] - public async Task ExpectedTagCountAsync() - { - GetTagsCommandOptions options = new GetTagsCommandOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp"), - FilePathExclusions = "none", //allow source under unittest path - SingleThread = true - }; - - GetTagsCommand command = new GetTagsCommand(options); - var result = await command.GetResultAsync(new CancellationToken()); - Assert.AreEqual(GetTagsResult.ExitCode.Success, result.ResultCode); - Assert.AreEqual(0, result.Metadata.TotalMatchesCount); - Assert.AreEqual(0, result.Metadata.UniqueMatchesCount); - Assert.AreEqual(7, result.Metadata.UniqueTags.Count); - } - - [TestMethod] - public void ExpectedTagCount() - { - GetTagsCommandOptions options = new GetTagsCommandOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainduptags.cpp"), - FilePathExclusions = "none", //allow source under unittest path - SingleThread = true - }; - - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; - try - { - GetTagsCommand command = new GetTagsCommand(options); - GetTagsResult result = command.GetResult(); - exitCode = result.ResultCode; - if (exitCode == GetTagsResult.ExitCode.Success) - { - exitCode = result.Metadata.TotalMatchesCount == 0 && result.Metadata.UniqueMatchesCount == 0 && result.Metadata.UniqueTags.Count == 7 ? GetTagsResult.ExitCode.Success : GetTagsResult.ExitCode.NoMatches; - } - } - catch (Exception) - { - exitCode = GetTagsResult.ExitCode.CriticalError; - } - - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.Success); - - GetTagsResult.ExitCode exitCodeMultiThread = GetTagsResult.ExitCode.CriticalError; - options.SingleThread = false; - try - { - GetTagsCommand command = new GetTagsCommand(options); - GetTagsResult result = command.GetResult(); - exitCodeMultiThread = result.ResultCode; - if (exitCodeMultiThread == GetTagsResult.ExitCode.Success) - { - exitCodeMultiThread = result.Metadata.TotalMatchesCount == 0 && result.Metadata.UniqueMatchesCount == 0 && result.Metadata.UniqueTags.Count == 7 ? GetTagsResult.ExitCode.Success : GetTagsResult.ExitCode.NoMatches; - } - } - catch (Exception) - { - exitCodeMultiThread = GetTagsResult.ExitCode.CriticalError; - } - - Assert.IsTrue(exitCodeMultiThread == GetTagsResult.ExitCode.Success); - } - - [TestMethod] - public void NoMatchesFound_Pass() - { - GetTagsCommandOptions options = new GetTagsCommandOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), - FilePathExclusions = "none", //allow source under unittest path - }; - - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; - try - { - GetTagsCommand command = new GetTagsCommand(options); - GetTagsResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - exitCode = GetTagsResult.ExitCode.CriticalError; - } - - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.NoMatches); - } - - [TestMethod] - public void LogTraceLevel_Pass() - { - GetTagsCommandOptions options = new GetTagsCommandOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), - FilePathExclusions = "none", //allow source under unittest path - - LogFileLevel = "trace", - LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"logtrace.txt"), - }; - - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; - try - { - GetTagsCommand command = new GetTagsCommand(options); - GetTagsResult result = command.GetResult(); - exitCode = result.ResultCode; - string testLogContent = File.ReadAllText(options.LogFilePath); - if (String.IsNullOrEmpty(testLogContent)) - { - exitCode = GetTagsResult.ExitCode.CriticalError; - } - else if (testLogContent.ToLower().Contains("trace")) - { - exitCode = GetTagsResult.ExitCode.Success; - } - } - catch (Exception) - { - exitCode = GetTagsResult.ExitCode.CriticalError; - } - - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.Success); - } - - [TestMethod] - public void LogErrorLevel_Pass() - { - GetTagsCommandOptions options = new GetTagsCommandOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\badfile.cpp"), - FilePathExclusions = "none", //allow source under unittest path - - LogFileLevel = "error", - LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"logerror.txt"), - }; - - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; - try - { - GetTagsCommand command = new GetTagsCommand(options); - } - catch (Exception) - { - string testLogContent = File.ReadAllText(options.LogFilePath); - if (!String.IsNullOrEmpty(testLogContent) && testLogContent.ToLower().Contains("error")) - { - exitCode = GetTagsResult.ExitCode.Success; - } - else - { - exitCode = GetTagsResult.ExitCode.CriticalError; - } - } - - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.Success); - } - - [TestMethod] - public void LogDebugLevel_Pass() - { - GetTagsCommandOptions options = new GetTagsCommandOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path - LogFileLevel = "debug", - LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"logdebug.txt"), - CloseLogOnCommandExit = true - }; - - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; - try - { - GetTagsCommand command = new GetTagsCommand(options); - GetTagsResult result = command.GetResult(); - exitCode = result.ResultCode; - string testLogContent = File.ReadAllText(options.LogFilePath); - if (String.IsNullOrEmpty(testLogContent)) - { - exitCode = GetTagsResult.ExitCode.CriticalError; - } - else if (testLogContent.ToLower().Contains("debug")) - { - exitCode = GetTagsResult.ExitCode.Success; - } - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.Success); - } - - [TestMethod] - public void InsecureLogPath_Fail() - { - GetTagsCommandOptions options = new GetTagsCommandOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path - LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), - }; - - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; - try - { - GetTagsCommand command = new GetTagsCommand(options); - GetTagsResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.CriticalError); - } - - [TestMethod] - public void NoConsoleOutput_Pass() - { - GetTagsCommandOptions options = new GetTagsCommandOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), - FilePathExclusions = "none", //allow source under unittest path - ConsoleVerbosityLevel = "none" - }; - - GetTagsResult.ExitCode exitCode = GetTagsResult.ExitCode.CriticalError; - try - { - // Attempt to open output file. - using (var writer = new StreamWriter(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"consoleout.txt"))) - { - // Redirect standard output from the console to the output file. - Console.SetOut(writer); - - GetTagsCommand command = new GetTagsCommand(options); - GetTagsResult result = command.GetResult(); - exitCode = result.ResultCode; - try - { - string testContent = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"consoleout.txt")); - if (String.IsNullOrEmpty(testContent)) - { - exitCode = GetTagsResult.ExitCode.Success; - } - else - { - exitCode = GetTagsResult.ExitCode.NoMatches; - } - } - catch (Exception) - { - exitCode = GetTagsResult.ExitCode.Success;//no console output file found - } - } - } - catch (Exception) - { - exitCode = GetTagsResult.ExitCode.CriticalError; - } - - //reset to normal - var standardOutput = new StreamWriter(Console.OpenStandardOutput()); - standardOutput.AutoFlush = true; - Console.SetOut(standardOutput); - - Assert.IsTrue(exitCode == GetTagsResult.ExitCode.Success); - } - } -} \ No newline at end of file diff --git a/UnitTest.Commands/Tests_NuGet/TestTagDiffCmd.cs b/UnitTest.Commands/Tests_NuGet/TestTagDiffCmd.cs index fdfae991..b572f05f 100644 --- a/UnitTest.Commands/Tests_NuGet/TestTagDiffCmd.cs +++ b/UnitTest.Commands/Tests_NuGet/TestTagDiffCmd.cs @@ -43,9 +43,9 @@ public void Equality_Pass() { TagDiffOptions options = new TagDiffOptions() { - SourcePath1 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - SourcePath2 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\maincopy.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath1 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + SourcePath2 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\maincopy.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path }; TagDiffResult.ExitCode exitCode = TagDiffResult.ExitCode.CriticalError; @@ -68,9 +68,9 @@ public void Equality_Fail() { TagDiffOptions options = new TagDiffOptions() { - SourcePath1 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - SourcePath2 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainx.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath1 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + SourcePath2 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainx.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path }; TagDiffResult.ExitCode exitCode = TagDiffResult.ExitCode.CriticalError; @@ -93,9 +93,9 @@ public void BasicZipReadDiff_Pass() { TagDiffOptions options = new TagDiffOptions() { - SourcePath1 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"zipped\mainx.zip"), - SourcePath2 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainx.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath1 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"zipped\mainx.zip") }, + SourcePath2 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainx.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path }; TagDiffResult.ExitCode exitCode = TagDiffResult.ExitCode.CriticalError; @@ -118,9 +118,9 @@ public void InEquality_Pass() { TagDiffOptions options = new TagDiffOptions() { - SourcePath1 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - SourcePath2 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainx.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath1 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + SourcePath2 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainx.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path TestType = "Inequality" }; @@ -145,9 +145,9 @@ public void InEquality_Fail() { TagDiffOptions options = new TagDiffOptions() { - SourcePath1 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - SourcePath2 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\maincopy.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath1 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + SourcePath2 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\maincopy.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path TestType = "Inequality" }; @@ -166,38 +166,14 @@ public void InEquality_Fail() Assert.IsTrue(exitCode == TagDiffResult.ExitCode.TestFailed); } - [TestMethod] - public void SameSrcFile_Fail() - { - TagDiffOptions options = new TagDiffOptions() - { - SourcePath1 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - SourcePath2 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path - }; - TagDiffResult.ExitCode exitCode = TagDiffResult.ExitCode.CriticalError; - try - { - TagDiffCommand command = new TagDiffCommand(options); - TagDiffResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == TagDiffResult.ExitCode.CriticalError); - } - [TestMethod] public void OneSrcResult_Fail() { TagDiffOptions options = new TagDiffOptions() { - SourcePath1 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), - SourcePath2 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath1 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp") }, + SourcePath2 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path }; TagDiffResult.ExitCode exitCode = TagDiffResult.ExitCode.CriticalError; try @@ -219,9 +195,9 @@ public void InvalidSourcePath_Fail() { TagDiffOptions options = new TagDiffOptions() { - SourcePath1 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\nofilehere.cpp"), - SourcePath2 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainx.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath1 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\nofilehere.cpp") }, + SourcePath2 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainx.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path }; TagDiffResult.ExitCode exitCode = TagDiffResult.ExitCode.CriticalError; @@ -244,9 +220,9 @@ public void NoResults_Fail() { TagDiffOptions options = new TagDiffOptions() { - SourcePath1 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), - SourcePath2 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\blank.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath1 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp") }, + SourcePath2 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\blank.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path }; TagDiffResult.ExitCode exitCode = TagDiffResult.ExitCode.CriticalError; @@ -269,9 +245,9 @@ public void NoDefaultNoCustomRules_Fail() { TagDiffOptions options = new TagDiffOptions() { - SourcePath1 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - SourcePath2 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainx.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath1 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + SourcePath2 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainx.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path IgnoreDefaultRules = true }; @@ -295,9 +271,9 @@ public void NoDefaultCustomRules_Pass() { TagDiffOptions options = new TagDiffOptions() { - SourcePath1 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - SourcePath2 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\maincopy.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath1 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + SourcePath2 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\maincopy.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path IgnoreDefaultRules = false, CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), }; @@ -322,9 +298,9 @@ public void DefaultWithCustomRules_Pass() { TagDiffOptions options = new TagDiffOptions() { - SourcePath1 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - SourcePath2 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\maincopy.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath1 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + SourcePath2 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\maincopy.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path IgnoreDefaultRules = true, CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), }; @@ -349,9 +325,9 @@ public void DefaultWithCustomRules_Fail() { TagDiffOptions options = new TagDiffOptions() { - SourcePath1 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - SourcePath2 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainx.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath1 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + SourcePath2 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainx.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), }; @@ -375,9 +351,9 @@ public void LogTraceLevel_Pass() { TagDiffOptions options = new TagDiffOptions() { - SourcePath1 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - SourcePath2 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\maincopy.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath1 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + SourcePath2 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\maincopy.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path LogFileLevel = "trace", LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"logtrace.txt"), }; @@ -412,9 +388,9 @@ public void LogErrorLevel_Pass() { TagDiffOptions options = new TagDiffOptions() { - SourcePath1 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - SourcePath2 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\nofilehere.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath1 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + SourcePath2 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\nofilehere.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path LogFileLevel = "error", LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"logerror.txt"), }; @@ -447,9 +423,9 @@ public void LogDebugLevel_Pass() { TagDiffOptions options = new TagDiffOptions() { - SourcePath1 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - SourcePath2 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\maincopy.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath1 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + SourcePath2 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\maincopy.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path LogFileLevel = "debug", LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"logdebug.txt"), }; @@ -484,9 +460,9 @@ public void InvalidLogPath_Fail() { TagDiffOptions options = new TagDiffOptions() { - SourcePath1 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - SourcePath2 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainx.cpp"), - FilePathExclusions = "none", //allow source under unittest path + SourcePath1 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + SourcePath2 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\mainx.cpp") }, + FilePathExclusions = Array.Empty(), //allow source under unittest path LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"baddir\log.txt"), }; @@ -509,9 +485,9 @@ public void InsecureLogPath_Fail() { TagDiffOptions options = new TagDiffOptions() { - SourcePath1 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - SourcePath2 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\maincopy.cpp"), - FilePathExclusions = "none", + SourcePath1 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + SourcePath2 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\maincopy.cpp") }, + FilePathExclusions = Array.Empty(), LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), }; @@ -534,9 +510,9 @@ public void NoConsoleOutput_Pass() { TagDiffOptions options = new TagDiffOptions() { - SourcePath1 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - SourcePath2 = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\maincopy.cpp"), - FilePathExclusions = "none", + SourcePath1 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp") }, + SourcePath2 = new string[] { Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\maincopy.cpp") }, + FilePathExclusions = Array.Empty(), ConsoleVerbosityLevel = "none" }; diff --git a/UnitTest.Commands/Tests_NuGet/TestTagTestCmd.cs b/UnitTest.Commands/Tests_NuGet/TestTagTestCmd.cs deleted file mode 100644 index 1d036f8e..00000000 --- a/UnitTest.Commands/Tests_NuGet/TestTagTestCmd.cs +++ /dev/null @@ -1,508 +0,0 @@ -using ApplicationInspector.Unitprocess.Misc; -using Microsoft.ApplicationInspector.Commands; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.IO; - -namespace ApplicationInspector.Unitprocess.Commands -{ - /// - /// Test class for Analyze Commands - /// Each method really needs to be complete i.e. options and command objects created and checked for exceptions etc. based on inputs so - /// doesn't create a set of shared objects - /// - /// - [TestClass] - public class TestTagTestCmd - { - [TestInitialize] - public void InitOutput() - { - Directory.CreateDirectory(Helper.GetPath(Helper.AppPath.testOutput)); - } - - [TestCleanup] - public void CleanUp() - { - try - { - Directory.Delete(Helper.GetPath(Helper.AppPath.testOutput), true); - } - catch - { - } - - //because these are static and each test is meant to be indpendent null assign the references to create the log - WriteOnce.Log = null; - Utils.Logger = null; - } - - [TestMethod] - public void RulesPresent_Pass() - { - TagTestOptions options = new TagTestOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - FilePathExclusions = "none", //allow source under unittest path - }; - - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - try - { - TagTestCommand command = new TagTestCommand(options); - TagTestResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - exitCode = TagTestResult.ExitCode.CriticalError; - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestPassed); - } - - [TestMethod] - public void RulesPresent_Fail() - { - TagTestOptions options = new TagTestOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myfakerule.json"), - FilePathExclusions = "none", //allow source under unittest path - }; - - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - try - { - TagTestCommand command = new TagTestCommand(options); - TagTestResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestFailed); - } - - [TestMethod] - public void BasicZipReadDiff_Pass() - { - TagTestOptions options = new TagTestOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"zipped\main.zip"), - CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - FilePathExclusions = "none", //allow source under unittest path - }; - - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - try - { - TagTestCommand command = new TagTestCommand(options); - TagTestResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - exitCode = TagTestResult.ExitCode.CriticalError; - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestPassed); - } - - [TestMethod] - public void RulesNotPresent_Pass() - { - TagTestOptions options = new TagTestOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myfakerule.json"), - FilePathExclusions = "none", //allow source under unittest path - TestType = "RulesNotPresent" - }; - - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - - try - { - TagTestCommand command = new TagTestCommand(options); - TagTestResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - exitCode = TagTestResult.ExitCode.CriticalError; - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestPassed); - } - - [TestMethod] - public void RulesNotPresent_Fail() - { - TagTestOptions options = new TagTestOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - FilePathExclusions = "none", //allow source under unittest path - TestType = "RulesNotPresent" - }; - - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - try - { - TagTestCommand command = new TagTestCommand(options); - TagTestResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - exitCode = TagTestResult.ExitCode.CriticalError; - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestFailed); - } - - [TestMethod] - public void InvalidSourcePath_Fail() - { - TagTestOptions options = new TagTestOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\nofilehere.cpp"), - CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - FilePathExclusions = "none", //allow source under unittest path - }; - - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - try - { - TagTestCommand command = new TagTestCommand(options); - TagTestResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.CriticalError); - } - - [TestMethod] - public void RulesPresentNoResults_Fail() - { - TagTestOptions options = new TagTestOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), - CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - FilePathExclusions = "none", //allow source under unittest path - }; - - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - try - { - TagTestCommand command = new TagTestCommand(options); - TagTestResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestFailed); - } - - [TestMethod] - public void RulesNotPresentNoResults_Success() - { - TagTestOptions options = new TagTestOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\empty.cpp"), - CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - TestType = "RulesNotPresent", - FilePathExclusions = "none", //allow source under unittest path - }; - - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - try - { - TagTestCommand command = new TagTestCommand(options); - TagTestResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestPassed); - } - - [TestMethod] - public void RulesNotPresentNoResults_Fail() - { - TagTestOptions options = new TagTestOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - TestType = "RulesNotPresent", - FilePathExclusions = "none", //allow source under unittest path - }; - - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - try - { - TagTestCommand command = new TagTestCommand(options); - TagTestResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestFailed); - } - - [TestMethod] - public void NoRules_Fail() - { - TagTestOptions options = new TagTestOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - FilePathExclusions = "none", //allow source under unittest path - }; - - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - try - { - TagTestCommand command = new TagTestCommand(options); - TagTestResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.CriticalError); - } - - [TestMethod] - public void LogTraceLevel_Pass() - { - TagTestOptions options = new TagTestOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - FilePathExclusions = "none", //allow source under unittest path - LogFileLevel = "trace", - LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"logtrace.txt"), - }; - - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - try - { - TagTestCommand command = new TagTestCommand(options); - TagTestResult result = command.GetResult(); - exitCode = result.ResultCode; - - string testLogContent = File.ReadAllText(options.LogFilePath); - if (String.IsNullOrEmpty(testLogContent)) - { - exitCode = TagTestResult.ExitCode.CriticalError; - } - else if (testLogContent.ToLower().Contains("trace")) - { - exitCode = TagTestResult.ExitCode.TestPassed; - } - } - catch (Exception) - { - exitCode = TagTestResult.ExitCode.CriticalError; - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestPassed); - } - - [TestMethod] - public void LogErrorLevel_Pass() - { - TagTestOptions options = new TagTestOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\nofilehere.cpp"), - CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - FilePathExclusions = "none", //allow source under unittest path - LogFileLevel = "error", - LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"logerror.txt"), - }; - - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - try - { - TagTestCommand command = new TagTestCommand(options); - TagTestResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - string testLogContent = File.ReadAllText(options.LogFilePath); - if (!String.IsNullOrEmpty(testLogContent) && testLogContent.ToLower().Contains("error")) - { - exitCode = TagTestResult.ExitCode.TestPassed; - } - else - { - exitCode = TagTestResult.ExitCode.CriticalError; - } - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestPassed); - } - - [TestMethod] - public void LogDebugLevel_Pass() - { - TagTestOptions options = new TagTestOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - FilePathExclusions = "none", //allow source under unittest path - LogFileLevel = "debug", - LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"logdebug.txt"), - }; - - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - try - { - TagTestCommand command = new TagTestCommand(options); - TagTestResult result = command.GetResult(); - exitCode = result.ResultCode; - - string testLogContent = File.ReadAllText(options.LogFilePath); - if (String.IsNullOrEmpty(testLogContent)) - { - exitCode = TagTestResult.ExitCode.CriticalError; - } - else if (testLogContent.ToLower().Contains("debug")) - { - exitCode = TagTestResult.ExitCode.TestPassed; - } - } - catch (Exception) - { - //check for specific error if desired - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestPassed); - } - - [TestMethod] - public void InvalidLogPath_Fail() - { - TagTestOptions options = new TagTestOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - FilePathExclusions = "none", //allow source under unittest path - LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"baddir\logdebug.txt"), - }; - - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - try - { - TagTestCommand command = new TagTestCommand(options); - TagTestResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - exitCode = TagTestResult.ExitCode.CriticalError; - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.CriticalError);//test fails even when values match unless this case run individually -mstest bug? - } - - [TestMethod] - public void InsecureLogPath_Fail() - { - TagTestOptions options = new TagTestOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - FilePathExclusions = "none", - LogFilePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - }; - - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - try - { - TagTestCommand command = new TagTestCommand(options); - TagTestResult result = command.GetResult(); - exitCode = result.ResultCode; - } - catch (Exception) - { - } - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.CriticalError); - } - - [TestMethod] - public void NoConsoleOutput_Pass() - { - TagTestOptions options = new TagTestOptions() - { - SourcePath = Path.Combine(Helper.GetPath(Helper.AppPath.testSource), @"unzipped\simple\main.cpp"), - CustomRulesPath = Path.Combine(Helper.GetPath(Helper.AppPath.testRules), @"myrule.json"), - FilePathExclusions = "none", - ConsoleVerbosityLevel = "none" - }; - - TagTestResult.ExitCode exitCode = TagTestResult.ExitCode.CriticalError; - try - { - // Attempt to open output file. - using (var writer = new StreamWriter(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"consoleout.txt"))) - { - // Redirect standard output from the console to the output file. - Console.SetOut(writer); - - TagTestCommand command = new TagTestCommand(options); - TagTestResult result = command.GetResult(); - exitCode = result.ResultCode; - try - { - string testContent = File.ReadAllText(Path.Combine(Helper.GetPath(Helper.AppPath.testOutput), @"consoleout.txt")); - if (String.IsNullOrEmpty(testContent)) - { - exitCode = TagTestResult.ExitCode.TestPassed; - } - else - { - exitCode = TagTestResult.ExitCode.TestFailed; - } - } - catch (Exception) - { - exitCode = TagTestResult.ExitCode.TestPassed;//no console output file found - } - } - } - catch (Exception) - { - exitCode = TagTestResult.ExitCode.CriticalError; - } - - //reset to normal - var standardOutput = new StreamWriter(Console.OpenStandardOutput()); - standardOutput.AutoFlush = true; - Console.SetOut(standardOutput); - - Assert.IsTrue(exitCode == TagTestResult.ExitCode.TestPassed); - } - } -} \ No newline at end of file diff --git a/version.json b/version.json index 8ce22e09..2530a411 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "1.3-beta", + "version": "1.3-rc", "publicReleaseRefSpec": [ "^refs/heads/main$", "^refs/heads/v\\d+(?:\\.\\d+)?$"