static void Main(string[] args) { var options = new CommandLineOptions(); try { if (!Parser.Default.ParseArguments(args, options)) { return; } Console.WriteLine("Start"); Validate.FileExist(options.TestResultXmlPath, "Test Result Xml Path"); TestLoadResult testLoadResult = TestLoadResult.ConvertFrom(options.TestResultXmlPath); HtmlReportWriter writer = new HtmlReportWriter(options.OutputFolderPath, options.OutputName); writer.Write(testLoadResult); } catch (Exception ex) { Console.Error.WriteLine(ex.Message); Console.WriteLine(options.GetUsage()); } Console.WriteLine("End"); }
public void GenerateReport() { try { lock (report_lock) { var report = Path.Combine(LogDirectory, "index.html"); var vsdropsReport = Path.Combine(LogDirectory, "vsdrops_index.html"); var tmpreport = Path.Combine(LogDirectory, $"index-{Helpers.Timestamp}.tmp.html"); var tmpVsdropsReport = Path.Combine(LogDirectory, $"vsdrops_index-{Helpers.Timestamp}.tmp.html"); var tmpmarkdown = string.IsNullOrEmpty(Harness.MarkdownSummaryPath) ? string.Empty : (Harness.MarkdownSummaryPath + $".{Helpers.Timestamp}.tmp"); var allSimulatorTasks = new List <RunSimulatorTask> (); var allExecuteTasks = new List <MacExecuteTask> (); var allNUnitTasks = new List <NUnitExecuteTask> (); var allMakeTasks = new List <MakeTask> (); var allDeviceTasks = new List <RunDeviceTask> (); var allDotNetTestTasks = new List <DotNetTestTask> (); foreach (var task in Tasks) { var aggregated = task as AggregatedRunSimulatorTask; if (aggregated != null) { allSimulatorTasks.AddRange(aggregated.Tasks); continue; } var execute = task as MacExecuteTask; if (execute != null) { allExecuteTasks.Add(execute); continue; } var nunit = task as NUnitExecuteTask; if (nunit != null) { allNUnitTasks.Add(nunit); continue; } var make = task as MakeTask; if (make != null) { allMakeTasks.Add(make); continue; } var run_device = task as RunDeviceTask; if (run_device != null) { allDeviceTasks.Add(run_device); continue; } if (task is DotNetTestTask dotnet) { allDotNetTestTasks.Add(dotnet); continue; } throw new NotImplementedException(); } var allTasks = new List <ITestTask> (); if (!Populating) { allTasks.AddRange(allExecuteTasks); allTasks.AddRange(allSimulatorTasks); allTasks.AddRange(allNUnitTasks); allTasks.AddRange(allMakeTasks); allTasks.AddRange(allDeviceTasks); allTasks.AddRange(allDotNetTestTasks); } // write the html using (var stream = new FileStream(tmpreport, FileMode.Create, FileAccess.ReadWrite)) using (var writer = new StreamWriter(stream)) { xamarinStorageHtmlReportWriter.Write(allTasks, writer); } // write the vsdrops report only if needed if (vsdropsHtmlReportWriter != null) { using (var stream = new FileStream(tmpVsdropsReport, FileMode.Create, FileAccess.ReadWrite)) using (var writer = new StreamWriter(stream)) { vsdropsHtmlReportWriter.Write(allTasks, writer); } } // optionally, write the markdown if (!string.IsNullOrEmpty(tmpmarkdown)) { using (var writer = new StreamWriter(tmpmarkdown)) { markdownReportWriter.Write(allTasks, writer); } } if (File.Exists(report)) { File.Delete(report); } File.Move(tmpreport, report); if (vsdropsHtmlReportWriter != null) { if (File.Exists(vsdropsReport)) { File.Delete(vsdropsReport); } File.Move(tmpVsdropsReport, vsdropsReport); } if (!string.IsNullOrEmpty(tmpmarkdown)) { if (File.Exists(Harness.MarkdownSummaryPath)) { File.Delete(Harness.MarkdownSummaryPath); } File.Move(tmpmarkdown, Harness.MarkdownSummaryPath); } var dependentFileLocation = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); foreach (var file in new string [] { "xharness.js", "xharness.css" }) { File.Copy(Path.Combine(dependentFileLocation, file), Path.Combine(LogDirectory, file), true); } File.Copy(Path.Combine(HarnessConfiguration.RootDirectory, "xharness", "favicon.ico"), Path.Combine(LogDirectory, "favicon.ico"), true); } } catch (Exception e) { this.MainLog.WriteLine("Failed to write log: {0}", e); } }
public Task RunAsync(Jenkins jenkins, HtmlReportWriter htmlReportWriter) { var server = new HttpListener(); // Try and find an unused port int attemptsLeft = 50; int port = 51234; // Try this port first, to try to not vary between runs just because. Random r = new Random((int)DateTime.Now.Ticks); while (attemptsLeft-- > 0) { var newPort = port != 0 ? port : r.Next(49152, 65535); // The suggested range for dynamic ports is 49152-65535 (IANA) server.Prefixes.Clear(); server.Prefixes.Add("http://*:" + newPort + "/"); try { server.Start(); port = newPort; break; } catch (Exception ex) { jenkins.MainLog.WriteLine("Failed to listen on port {0}: {1}", newPort, ex.Message); port = 0; } } jenkins.MainLog.WriteLine($"Created server on localhost:{port}"); var tcs = new TaskCompletionSource <bool> (); var thread = new System.Threading.Thread(() => { while (server.IsListening) { var context = server.GetContext(); var request = context.Request; var response = context.Response; var arguments = System.Web.HttpUtility.ParseQueryString(request.Url.Query); try { var allTasks = jenkins.Tasks.SelectMany((v) => { var rv = new List <ITestTask> (); var runsim = v as AggregatedRunSimulatorTask; if (runsim != null) { rv.AddRange(runsim.Tasks); } rv.Add(v); return(rv); }); IEnumerable <ITestTask> find_tasks(StreamWriter writer, string ids) { IEnumerable <ITestTask> tasks; switch (request.Url.Query) { case "?all": tasks = jenkins.Tasks; break; case "?selected": tasks = allTasks.Where((v) => !v.Ignored); break; case "?failed": tasks = allTasks.Where((v) => v.Failed); break; case "?": writer.WriteLine("No tasks specified"); return(Array.Empty <AppleTestTask> ()); default: var id_inputs = ids.Substring(1).Split(','); var rv = new List <ITestTask> (id_inputs.Length); foreach (var id_input in id_inputs) { if (int.TryParse(id_input, out var id)) { var task = jenkins.Tasks.FirstOrDefault((t) => t.ID == id); if (task == null) { task = jenkins.Tasks.Where((v) => v is AggregatedRunSimulatorTask).Cast <AggregatedRunSimulatorTask> ().SelectMany((v) => v.Tasks).FirstOrDefault((t) => t.ID == id); } if (task == null) { writer.WriteLine($"Could not find test {id}"); } else { rv.Add(task); } } else { writer.WriteLine($"Could not parse {arguments ["id"]}"); } } tasks = rv; break; } return(tasks); } string serveFile = null; switch (request.Url.LocalPath) { case "/": response.ContentType = System.Net.Mime.MediaTypeNames.Text.Html; using (var writer = new StreamWriter(response.OutputStream)) { htmlReportWriter.Write(jenkins.Tasks, writer); } break; case "/set-option": response.ContentType = System.Net.Mime.MediaTypeNames.Text.Plain; switch (request.Url.Query) { case "?clean": jenkins.CleanSuccessfulTestRuns = true; break; case "?do-not-clean": jenkins.CleanSuccessfulTestRuns = false; break; case "?uninstall-test-app": jenkins.UninstallTestApp = true; break; case "?do-not-uninstall-test-app": jenkins.UninstallTestApp = false; break; case "?skip-permission-tests": jenkins.Harness.IncludeSystemPermissionTests = false; break; case "?include-permission-tests": jenkins.Harness.IncludeSystemPermissionTests = true; break; case "?clear-permission-tests": jenkins.Harness.IncludeSystemPermissionTests = null; break; default: throw new NotImplementedException(request.Url.Query); } using (var writer = new StreamWriter(response.OutputStream)) { writer.WriteLine("OK"); } break; case "/select": case "/deselect": response.ContentType = System.Net.Mime.MediaTypeNames.Text.Plain; using (var writer = new StreamWriter(response.OutputStream)) { foreach (var task in allTasks) { bool?is_match = null; if (!(task.Ignored || task.NotStarted)) { continue; } switch (request.Url.Query) { case "?all": is_match = true; break; case "?all-device": is_match = task is RunDeviceTask; break; case "?all-simulator": is_match = task is RunSimulatorTask; break; case "?all-ios": switch (task.Platform) { case TestPlatform.iOS: case TestPlatform.iOS_TodayExtension64: case TestPlatform.iOS_Unified: case TestPlatform.iOS_Unified32: case TestPlatform.iOS_Unified64: is_match = true; break; default: if (task.Platform.ToString().StartsWith("iOS", StringComparison.Ordinal)) { throw new NotImplementedException(); } break; } break; case "?all-tvos": switch (task.Platform) { case TestPlatform.tvOS: is_match = true; break; default: if (task.Platform.ToString().StartsWith("tvOS", StringComparison.Ordinal)) { throw new NotImplementedException(); } break; } break; case "?all-watchos": switch (task.Platform) { case TestPlatform.watchOS: case TestPlatform.watchOS_32: case TestPlatform.watchOS_64_32: is_match = true; break; default: if (task.Platform.ToString().StartsWith("watchOS", StringComparison.Ordinal)) { throw new NotImplementedException(); } break; } break; case "?all-mac": switch (task.Platform) { case TestPlatform.Mac: case TestPlatform.Mac_Modern: case TestPlatform.Mac_Full: case TestPlatform.Mac_System: is_match = true; break; default: if (task.Platform.ToString().StartsWith("Mac", StringComparison.Ordinal)) { throw new NotImplementedException(); } break; } break; default: writer.WriteLine("unknown query: {0}", request.Url.Query); break; } if (request.Url.LocalPath == "/select") { if (is_match.HasValue && is_match.Value) { task.Ignored = false; } } else if (request.Url.LocalPath == "/deselect") { if (is_match.HasValue && is_match.Value) { task.Ignored = true; } } } writer.WriteLine("OK"); } break; case "/stop": response.ContentType = System.Net.Mime.MediaTypeNames.Text.Plain; using (var writer = new StreamWriter(response.OutputStream)) { foreach (var task in find_tasks(writer, request.Url.Query)) { if (!task.Waiting) { writer.WriteLine($"Test '{task.TestName}' is not in a waiting state."); } else { task.Reset(); } } writer.WriteLine("OK"); } break; case "/run": response.ContentType = System.Net.Mime.MediaTypeNames.Text.Plain; using (var writer = new StreamWriter(response.OutputStream)) { // We want to randomize the order the tests are added, so that we don't build first the test for one device, // then for another, since that would not take advantage of running tests on several devices in parallel. foreach (var task in find_tasks(writer, request.Url.Query).Shuffle()) { if (task.InProgress || task.Waiting) { writer.WriteLine($"Test '{task.TestName}' is already executing."); } else { task.Reset(); task.BuildOnly = false; task.RunAsync(); } } writer.WriteLine("OK"); } break; case "/build": response.ContentType = System.Net.Mime.MediaTypeNames.Text.Plain; using (var writer = new StreamWriter(response.OutputStream)) { foreach (var task in find_tasks(writer, request.Url.Query)) { if (task.InProgress || task.Waiting) { writer.WriteLine($"Test '{task.TestName}' is already executing."); } else if (task is RunTestTask rtt) { rtt.Reset(); rtt.BuildAsync().ContinueWith((z) => { if (rtt.ExecutionResult == TestExecutingResult.Built) { rtt.ExecutionResult = TestExecutingResult.BuildSucceeded; } }); } else { writer.WriteLine($"Test '{task.TestName}' is not a test that can be only built."); } } writer.WriteLine("OK"); } break; case "/reload-devices": jenkins.DeviceLoader.LoadDevicesAsync().DoNotAwait(); break; case "/reload-simulators": jenkins.DeviceLoader.LoadSimulatorsAsync().DoNotAwait(); break; case "/quit": using (var writer = new StreamWriter(response.OutputStream)) { writer.WriteLine("<!DOCTYPE html>"); writer.WriteLine("<html>"); writer.WriteLine("<body onload='close ();'>Closing web page...</body>"); writer.WriteLine("</html>"); } server.Stop(); break; case "/favicon.ico": serveFile = Path.Combine(HarnessConfiguration.RootDirectory, "xharness", "favicon.ico"); goto default; case "/index.html": var redirect_to = request.Url.AbsoluteUri.Replace("/index.html", "/" + Path.GetFileName(jenkins.LogDirectory) + "/index.html"); response.Redirect(redirect_to); break; default: var filename = Path.GetFileName(request.Url.LocalPath); if (filename == "index.html" && Path.GetFileName(jenkins.LogDirectory) == Path.GetFileName(Path.GetDirectoryName(request.Url.LocalPath))) { // We're asked for the report for the current test run, so re-generate it. jenkins.GenerateReport(); } if (serveFile == null) { serveFile = Path.Combine(Path.GetDirectoryName(jenkins.LogDirectory), request.Url.LocalPath.Substring(1)); } var path = serveFile; if (File.Exists(path)) { var buffer = new byte [4096]; using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { int read; response.ContentLength64 = fs.Length; switch (Path.GetExtension(path).ToLowerInvariant()) { case ".html": response.ContentType = System.Net.Mime.MediaTypeNames.Text.Html; break; case ".css": response.ContentType = "text/css"; break; case ".js": response.ContentType = "text/javascript"; break; case ".ico": response.ContentType = "image/png"; break; default: response.ContentType = System.Net.Mime.MediaTypeNames.Text.Plain + ";charset=UTF-8"; break; } while ((read = fs.Read(buffer, 0, buffer.Length)) > 0) { response.OutputStream.Write(buffer, 0, read); } } } else { Console.WriteLine($"404: {request.Url.LocalPath}"); response.StatusCode = 404; response.OutputStream.WriteByte((byte)'?'); } break; } } catch (IOException ioe) { Console.WriteLine(ioe.Message); } catch (Exception e) { Console.WriteLine(e); } response.Close(); } tcs.SetResult(true); }) { IsBackground = true, }; thread.Start(); var url = $"http://localhost:{port}/" + Path.GetFileName(jenkins.LogDirectory) + "/index.html"; Console.WriteLine($"Launching {url} in the system's default browser."); Process.Start("open", url); return(tcs.Task); }
void RenderReport(HttpContext context) { var type = context.Request.QueryString["type"]; Report report; switch (type) { case "GdpByYear": report = Reports.GdpByYearReport.Generate(); break; case "GdpByCountry": report = Reports.GdpByCountryReport.Generate(); break; case "BiggestCountries": report = Reports.GdpYearColumnReport.BiggestCountries(); break; case "FastestGrowingCountries": report = Reports.GdpYearColumnReport.FastestGrowingCountries(); break; case "BestCountries": report = Reports.GdpYearColumnReport.BestCountries(); break; default: throw new InvalidOperationException("Invalid report type."); } try { switch (context.Request.QueryString["format"]) { case "pdf": var url = context.Request.Url.ToString().Replace("format=pdf", "print=1"); PdfConvert.ConvertHtmlToPdf(new PdfDocument { Url = url }, new PdfOutput { OutputStream = context.Response.OutputStream }); context.Response.SetFileDownloadHeaders(String.Format("Report{0}.pdf", DateTime.Now.Ticks)); break; case "text": context.Response.SetFileDownloadHeaders(String.Format("Report{0}.txt", DateTime.Now.Ticks)); TextReportWriter.WriteTo(report, context.Response.Output); break; case "xlsx": context.Response.SetFileDownloadHeaders(String.Format("Report{0}.xlsx", DateTime.Now.Ticks)); XlsxReportWriter.WriteToStream(report, Themes.Default, context.Response.OutputStream); break; default: var output = new HtmlTextWriter(context.Response.Output); var htmlWriter = new HtmlReportWriter(output); htmlWriter.RegisterCss(DextopUtil.AbsolutePath("client/css/report.css")); if (context.Request.QueryString["print"] == null) { htmlWriter.RegisterCss(DextopUtil.AbsolutePath("client/css/report-preview.css")); } htmlWriter.Write(report, new DefaultHtmlReportTheme()); break; } } catch (Exception ex) { context.Response.Write(ex.ToString()); } }