static bool CompareReports(Context context, ParsedOptions parsedOptions, List <string> rest) { if (rest.Count < 2) { Log.FatalLine("Paths to two directories containing performance reports must be passed on command line."); return(false); } string pathOne = Path.GetFullPath(rest [0]); string pathTwo = Path.GetFullPath(rest [1]); if (String.Compare(pathOne, pathTwo, StringComparison.Ordinal) == 0) { Log.FatalLine("Performance data paths must point to different directories"); return(false); } bool success; string perfDataOne; (success, perfDataOne) = EnsureDirExistsAndHasPerfData(pathOne, rest [0]); if (!success) { return(false); } string perfDataTwo; (success, perfDataTwo) = EnsureDirExistsAndHasPerfData(pathTwo, rest [1]); if (!success) { return(false); } var report = new Report(); string reportFile = report.Compare(context, Utilities.FirstOf(context.OutputDirectory, Constants.CompareResultsRelativePath), perfDataOne, perfDataTwo); return(true); (bool success, string perfDataPath) EnsureDirExistsAndHasPerfData(string path, string originalPath) { if (!Directory.Exists(path)) { Log.FatalLine($"Directory '{originalPath}' does not exist."); return(false, String.Empty); } string perfData = Path.Combine(path, Constants.RawResultsFileName); if (!File.Exists(perfData)) { Log.FatalLine($"Raw performance data file not found at '{perfData}'"); return(false, String.Empty); } return(true, perfData); } }
public ProjectLocator(ParsedOptions commandLineOptions, List <string> args) { if (commandLineOptions.Compare) { if (args.Count < 2) { throw new InvalidOperationException("At least two paths to performance data directories must be given in comparison mode"); } LocateDataForComparison(commandLineOptions, args); return; } LocateSingleProject(commandLineOptions, args); }
void LocateSingleProject(ParsedOptions commandLineOptions, List <string> args) { string projectPath = args.Count > 0 ? args [0] : String.Empty; // If a project file path is specified on command line... if (!String.IsNullOrEmpty(projectPath)) { // ...and it exists,load it and... if (File.Exists(projectPath)) { ProjectPaths.Add(projectPath); // ...if there's a sibling or specified config file, load it ProjectConfig = LoadConfigFile(commandLineOptions, Path.GetDirectoryName(projectPath) ?? String.Empty); return; } // If a project directory is specified on command line, however, and it exists... if (!Directory.Exists(projectPath)) { throw new InvalidOperationException($"'{projectPath}' does not point either to a project file or a directory containing one"); } // ...find a project in it... ProjectConfig = LoadConfigFile(commandLineOptions, projectPath); string projectFile = FindProject(projectPath, ProjectConfig); // ...and holler if it's not found if (String.IsNullOrEmpty(projectFile)) { throw new InvalidOperationException($"Could not determine how to load a supported project from '{projectPath}'"); } ProjectPaths.Add(projectFile); return; } // Otherwise, try to find compatible projects in the current directory... projectPath = Environment.CurrentDirectory; ProjectConfig = LoadConfigFile(commandLineOptions, projectPath); projectPath = FindProject(projectPath, ProjectConfig); // ...and shout if nothing's there if (String.IsNullOrEmpty(projectPath)) { throw new InvalidOperationException("No supported project found in the current directory. Please pass the project path on command line."); } ProjectPaths.Add(projectPath); }
static ProjectConfig?LoadConfigFile(ParsedOptions commandLineOptions, string dir) { string?filePath; if (!String.IsNullOrEmpty(commandLineOptions.ConfigFile)) { filePath = commandLineOptions.ConfigFile; } else { filePath = Path.Combine(dir, Constants.ConfigFileName); } if (!File.Exists(filePath)) { return(null); } return(new ProjectConfig(filePath)); }
static async Task <bool> RunPerfTests(Context context, ParsedOptions parsedOptions, List <string> rest) { var locator = new ProjectLocator(parsedOptions, rest); string xaProjectPath = locator.ProjectPaths.Count == 0 ? String.Empty : locator.ProjectPaths [0]; if (String.IsNullOrEmpty(xaProjectPath)) { Log.FatalLine("No Xamarin.Android project found or specified on command line"); return(false); } var project = new Project(context, xaProjectPath, locator.ProjectConfig); Log.LogFilePath = Path.Combine(project.FullDataDirectoryPath, Constants.LogFileName); Log.MessageLine($"Using Xamarin.Android project: {project.FullProjectFilePath}"); bool result = await project.Run(); if (!result) { Log.FatalLine("Run failed"); return(false); } var report = new Report(); string reportPath = report.Generate(project); Log.InfoLine(); Log.InfoLine($"Project: {project.FullProjectFilePath}"); Log.InfoLine($"Configuration: {project.Configuration}"); Log.InfoLine($"Output directory: {project.FullDataDirectoryPath}"); if (!String.IsNullOrEmpty(reportPath)) { Log.InfoLine($"Results report: {reportPath}"); return(true); } Log.InfoLine("No results report generated"); return(false); }
static async Task <int> Main(string [] args) { var parsedOptions = new ParsedOptions(); var opts = new OptionSet { "Usage: xaptr [OPTIONS] [(path/to/project.csproj | path/to/project/directory | path/to/project/perfdata)]...", "", "The application must be run in a directory which contains the .csproj file for the application to test, or a path to the project file must be passed as a parameter.", "Only Xamarin.Android projects are supported.", "", { "d|compare", "Compare two sets of performance data and generate a report. All data directory paths must be given on command line.", v => parsedOptions.Compare = v == null ? false : true }, { "p|perf", $"Run performance test (default: {parsedOptions.RunPerfTest})", v => parsedOptions.RunPerfTest = v == null ? false : true }, { "m|profile-managed", $"Profile managed portion of the app (default: {parsedOptions.RunManagedProfiler})", v => parsedOptions.RunManagedProfiler = v == null ? false : true }, { "n|profile-native", $"Profile native portion of the app (default: {parsedOptions.RunNativeProfiler})", v => parsedOptions.RunNativeProfiler = v == null ? false : true }, { "r|runs=", $"Number of runs for the performance test (default: {parsedOptions.RepetitionCount})", v => parsedOptions.RepetitionCount = ParseNumber(v, parsedOptions.RepetitionCount) }, "", { "a|app=", "Use the specified Android app id/package name (default is to autodetect)", v => parsedOptions.PackageName = v }, { "c|configuration=", $"Build application in the specified CONFIGURATION (default: {parsedOptions.Configuration})", v => parsedOptions.Configuration = v ?? parsedOptions.Configuration }, { "b|build-command=", $"Use COMMAND to build the package (default: {parsedOptions.BuildCommand})", v => parsedOptions.BuildCommand = v ?? parsedOptions.BuildCommand }, "", { "x|config-file=", "Pass a PATH to an xaptr configuration file", v => parsedOptions.ConfigFile = v }, { "o|output-dir=", $"Path to base directory where to store the data and report files", v => parsedOptions.OutputDirectory = v }, "", { "h|help", "Show this help message", v => parsedOptions.ShowHelp = true }, }; List <string> rest = opts.Parse(args); if (parsedOptions.ShowHelp) { opts.WriteOptionDescriptions(Console.Out); return(0); } var context = new Context { BuildCommand = parsedOptions.BuildCommand, RunNativeProfiler = parsedOptions.RunNativeProfiler, RunManagedProfiler = parsedOptions.RunManagedProfiler, RunPerformanceTest = parsedOptions.RunPerfTest, }; if (!String.IsNullOrEmpty(parsedOptions.Configuration)) { context.Configuration = parsedOptions.Configuration; } if (!String.IsNullOrEmpty(parsedOptions.PackageName)) { context.PackageName = parsedOptions.PackageName; } if (parsedOptions.RepetitionCount.HasValue) { context.RepetitionCount = parsedOptions.RepetitionCount.Value; } if (!String.IsNullOrEmpty(parsedOptions.OutputDirectory)) { context.OutputDirectory = parsedOptions.OutputDirectory; } bool result = true; if (parsedOptions.Compare) { result = CompareReports(context, parsedOptions, rest); } else { result = await RunPerfTests(context, parsedOptions, rest); } return(result ? 0 : 1); }
void LocateDataForComparison(ParsedOptions commandLineOptions, List <string> args) { }