/// The main entry of the application /// @para cmdArgs contains an array of commandline parameters that are parsed using CommandLine.Dll public static void Main(string[] cmdArgs) { //Global catch to prevent crash try { Run(cmdArgs); } catch (Exception ex) { if (null != _log) _log.Error("Exception during run: {0}", ex.Message); else Console.Error.WriteLine("Exception during run: {0}", ex.Message); var options = new Options(); Console.WriteLine(options.GetUsage()); #if DEBUG Console.ReadLine(); #endif Environment.Exit(2); } }
private static Report CheckFiles(Options options, string Compare = null, string Base = null) { //Check Arguments if (string.IsNullOrEmpty(Compare)) if (options.Items.Count == 2) Compare = options.Items[0]; else throw new ArgumentException("You have to set compare and base csv files!"); if (string.IsNullOrEmpty(Base)) if (options.Items.Count == 2) Base = options.Items[1]; else throw new ArgumentException("You have to set compare and base csv files!"); try { using (CsvFile csvCompare = new CsvFile(Compare, options, _log)) { csvCompare.ShowRelativeErrors = !options.AbsoluteError; try { using (CsvFile csvBase = new CsvFile(Base, options, _log)) { //#if DEBUG //Save csv files during DEBUG session // if (!string.IsNullOrEmpty(options.ReportDir)) // { // csvBase.Save(options.ReportDir, options); // csvCompare.Save(options.ReportDir, options); // } // else // { // csvBase.Save(options); // csvCompare.Save(options); // } //#endif _log.WriteLine(LogLevel.Debug, "Exiting with exit code \"{0}\".", Environment.ExitCode); return csvCompare.CompareFiles(_log, csvBase, ref options); } } catch (ArgumentException argEx) { _log.Error(argEx.Message); return null; } catch (FileNotFoundException) { throw new FileNotFoundException(string.Format(CultureInfo.CurrentCulture, "Base file \"{0}\" does not exist, exiting.", Base)); } } } catch (ArgumentException ex) { _log.Error("Nothing has been parsed; maybe wrong csv format?"); _log.Error("Exception said: {0}", ex.Message); Environment.ExitCode = 2; return null; } catch (FileNotFoundException) { throw new FileNotFoundException(string.Format(CultureInfo.CurrentCulture, "Compare file \"{0}\" does not exist, exiting.", Compare)); } }
private static void Run(string[] cmdArgs) { var options = new Options(); Parser parser = new Parser(); if (parser.ParseArguments(cmdArgs, options)) { if (options.Verbosity > 0) _log.Verbosity = (LogLevel)options.Verbosity; else #if DEBUG _log.Verbosity = LogLevel.Debug; #endif _log.WriteLine(LogLevel.Debug, "Using CSV Compare Version {0} ({1})", Info.AssemblyVersion, Assembly.GetExecutingAssembly().GetName().ProcessorArchitecture); _log.WriteLine(LogLevel.Debug, "Starting new result check @{0}", DateTime.Now); _log.WriteLine(LogLevel.Debug, "Parsing commandline options: {0} * {1}", Environment.NewLine, string.Join(" ", cmdArgs)); _log.WriteLine(LogLevel.Debug, "Successfully parsed the following options:"); _log.WriteLine(LogLevel.Debug, "Operation mode is {0}", options.Mode); _log.WriteLine(LogLevel.Debug, "Tolerance is {0}", options.Tolerance); if (options.Delimiter == 0) { _log.WriteLine(LogLevel.Debug, "Delimiter is not explicitly set, so I am using \";\""); options.Delimiter = ';'; } else _log.WriteLine(LogLevel.Debug, "Delimiter to be used to parse csv has been explicitly set and is \"{0}\"", options.Delimiter); if (null == options.Logfile) _log.WriteLine(LogLevel.Debug, "Logfile is empty"); else { if (!options.OverrideOutput && File.Exists(options.Logfile)) { options.Logfile = Path.Combine(Path.GetDirectoryName(options.Logfile), string.Format(CultureInfo.CurrentCulture, "{0:yyyy-MM-ddTHH-mm-ss}_log.txt", DateTime.Now)); _log.WriteLine(LogLevel.Warning, "Logfile already exists and --override has been set to false. Changed log file name to \"{0}\"", options.Logfile); } else _log.WriteLine(LogLevel.Debug, "Logfile is {0}", options.Logfile); _log.SetLogFile(new FileInfo(options.Logfile)); } if (options.Items.Count == 0) { _log.Error("No files or directories to be compared have been given."); Console.WriteLine(options.GetUsage()); Environment.Exit(2); } MetaReport meta = new MetaReport(); if (String.IsNullOrEmpty(options.ReportDir))//report to directory of compare file if no report directory has been set { FileAttributes attr = File.GetAttributes(options.Items[0]); if ((attr & FileAttributes.Directory) == FileAttributes.Directory) options.ReportDir = Path.GetFullPath(options.Items[0]); else options.ReportDir = Path.GetDirectoryName(options.Items[0]); _log.WriteLine(LogLevel.Warning, "No report directory has been set, using \"{0}\"", options.ReportDir); } else { meta.ReportDirSet = true; options.ReportDir = Path.GetFullPath(options.ReportDir);//normalize report dir (i.e. make absolut if relative) if (!Directory.Exists(options.ReportDir)) Directory.CreateDirectory(options.ReportDir); } meta.FileName = new FileInfo(Path.Combine(options.ReportDir, string.Format(CultureInfo.CurrentCulture, "{0:yyyy-MM-dd}-index.html", DateTime.Now))); switch (options.Mode) { case OperationMode.CsvFileCompare://compare the file given as option 1 with the file given as option 2 if (options.Items.Count != 2) { _log.Error("Not enough arguments have been given. Please specify base and compare file."); Console.WriteLine(options.GetUsage()); Environment.Exit(2); } Report rep = CheckFiles(options); if (null != rep && !options.NoMetaReport) { meta.Reports.Add(rep);//Return "1" on invalid testresults meta.WriteReport(_log, options); } break; case OperationMode.CsvTreeCompare://compare files in the dirctory option 1 with the files in directory option 2 if (options.Items.Count != 2) { _log.Error("Not enough arguments have been given. Please specify base and compare directory."); Console.WriteLine(options.GetUsage()); Environment.Exit(2); } CheckTrees(meta, options); if(!options.NoMetaReport) meta.WriteReport(_log, options); break; case OperationMode.FmuChecker://run FMU checker on all fmus in directory given via option 1 and compare the result to CSVs in the source directory if (options.Items.Count != 1) { if (options.Items.Count == 0) _log.Error("Not enough arguments have been given. Please specify a compare directory with FMUs."); else _log.Error("Too many arguments have been given. Please specify a compare directory with FMUs only."); Console.WriteLine(options.GetUsage()); Environment.Exit(2); } if (string.IsNullOrEmpty(options.CheckerPath)) { _log.Error("No path to FMU Checker binary given."); Console.WriteLine(options.GetUsage()); } else { CheckFMUTree(ref meta, options); meta.WriteReport(_log, options); } break; case OperationMode.PlotOnly: foreach (string item in options.Items) using (CsvFile file = new CsvFile(item, options, _log)) { meta.Reports.Add(file.PlotCsvFile(null, _log)); } meta.WriteReport(_log, options); break; default://Invalid mode Console.WriteLine(options.GetUsage()); break; } } else Console.WriteLine(options.GetUsage()); #if DEBUG //Keep window open in debug mode _log.WriteLine(LogLevel.Debug, "Done."); Console.ReadLine(); #endif }
private static bool RunFMUChecker(Options options, DirectoryInfo dirCompare, ref string outFile, FileInfo file) { bool bRet = true; string sArgs; using (Process p = new Process()) { outFile = string.Format(CultureInfo.CurrentCulture, "{0}/{1}.csv", dirCompare.FullName, Path.GetFileNameWithoutExtension(file.FullName)); p.StartInfo = new ProcessStartInfo(options.CheckerPath); if (!string.IsNullOrEmpty(options.CheckerArgs)) sArgs = options.CheckerArgs; else sArgs = "-l 1 -h 1e-2 -s 1.5"; p.StartInfo.Arguments = string.Format(CultureInfo.CurrentCulture, "{0} -o \"{1}\" \"{2}\"", sArgs, outFile, file.FullName); p.StartInfo.UseShellExecute = false; _log.WriteLine(LogLevel.Debug, "Run \"{0} {1}\"", p.StartInfo.FileName, p.StartInfo.Arguments); if (p.Start()) p.WaitForExit(); if (p.ExitCode != 0) { _log.Error("Error during FMU Checker run"); bRet = false; } } return bRet; }
private static void CheckTrees(MetaReport meta, Options options) { DirectoryInfo dirCompare = new DirectoryInfo(options.Items[0]); DirectoryInfo dirBase = new DirectoryInfo(options.Items[1]); FileInfo[] files = dirCompare.GetFiles("*.csv", SearchOption.AllDirectories); foreach (FileInfo file in files) { _log.WriteLine(LogLevel.Debug, "Searching for file {0} in {1}", file.Name, dirBase.FullName); //Try different locations for the base file string sBaseFile = string.Empty; if (dirBase.GetFiles(file.Name).Length == 1)//1. Base file is in the, via commandline, given base directory { sBaseFile = Path.Combine(dirBase.FullName, file.Name); _log.WriteLine(LogLevel.Debug, "Found base file in given base directory \"{0}\", comparing ...", dirBase.Name); } else { try { sBaseFile = file.FullName.Replace(options.Items[0], options.Items[1]);//2. Base file is in the same directory structure as the compare file if (!File.Exists(sBaseFile)) { _log.WriteLine(LogLevel.Warning, "{0} not found in {1} or {2}, skipping validation.", file.Name, dirBase.Name, sBaseFile); continue; } else _log.WriteLine(LogLevel.Debug, "Found base file in given base directory \"{0}\", comparing ...", dirBase); } catch (Exception ex) { _log.Error(ex.Message); continue; } } Report r = CheckFiles(options, file.FullName, sBaseFile); meta.Reports.Add(r); } }
private static void CheckFMUTree(ref MetaReport meta, Options options) { DirectoryInfo dirCompare, dirBase; string sTempDir = string.Format(CultureInfo.CurrentCulture, "{0}CSV-Compare-{1:yyyyMMdd}", Path.GetTempPath(), DateTime.Now); dirBase = new DirectoryInfo(options.Items[0]); if (!dirBase.Exists) { _log.Error("The directory \"{0}\" containing fmu files does not exist.", dirBase.FullName); Environment.Exit(2); } string outFile = string.Empty; dirCompare = new DirectoryInfo(sTempDir); if (!dirCompare.Exists) Directory.CreateDirectory(dirCompare.ToString()); if (!String.IsNullOrEmpty(options.ReportDir)) meta = new MetaReport(options.ReportDir); else meta = new MetaReport(); foreach (FileInfo file in dirBase.GetFiles("*.fmu", SearchOption.AllDirectories)) { if (!RunFMUChecker(options, dirCompare, ref outFile, file))//Skip to next FMU on error continue; string sBase = Path.Combine(file.Directory.FullName, Path.GetFileNameWithoutExtension(file.Name) + ".csv"); _log.WriteLine(LogLevel.Debug, "Searching for csv {0} ", sBase); if (!File.Exists(sBase))//if $FILENAME$.csv could not be found search for protocol.csv { sBase = Path.Combine(file.Directory.FullName, "protocol.csv"); _log.WriteLine(LogLevel.Information, "Not found trying \"{0}\"", sBase); if (!File.Exists(sBase)) { _log.Error("Found nothing to compare with, skipping {0}", file.Name); continue; } } _log.WriteLine(LogLevel.Information, "Trying to compare with \"{0}\"", sBase); try { CsvFile csvCompare = new CsvFile(outFile, options, _log); try { meta.Reports.Add(csvCompare.CompareFiles(_log, new CsvFile(sBase, options, _log), Path.Combine(options.ReportDir, file.Name + ".html"), ref options)); } catch (ArgumentNullException ex) { _log.Error(ex.Message); } } catch (ArgumentException ex) { _log.Error(ex.Message); continue; } } }
private void WriteHeader(TextWriter writer, Options options) { writer.WriteLine("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">"); writer.WriteLine("<head>"); writer.WriteLine("<title>Report {0}</title>", DateTime.Now); Assembly ass = Assembly.GetExecutingAssembly(); List<string> lScripts = new List<string>(); foreach (string s in ass.GetManifestResourceNames()) { if (!s.ToLowerInvariant().EndsWith(".js")) continue; if (options.InlineScripts) { var javascriptHeaders = new StreamReader(ass.GetManifestResourceStream(s)); lScripts.Add(string.Format("<script language=\"javascript\" type=\"text/javascript\">{0}</script>", javascriptHeaders.ReadToEnd())); } else lScripts.Add(string.Format("<script src=\"js/{0}\"></script>", s)); } lScripts = lScripts.OrderByDescending(x => x).ToList<string>();//Sort alphabetically to ensure jquery is loaded first writer.WriteLine(string.Join(Environment.NewLine, lScripts.ToArray())); if (options.InlineScripts) { writer.WriteLine("<style type=\"text/css\">"); writer.WriteLine(".jqplot-target{position:relative;color:#666;font-family:\"Trebuchet MS\",Arial,Helvetica,sans-serif;font-size:1em;}.jqplot-axis{font-size:.75em;}.jqplot-xaxis{margin-top:10px;}.jqplot-x2axis{margin-bottom:10px;}.jqplot-yaxis{margin-right:10px;}.jqplot-y2axis,.jqplot-y3axis,.jqplot-y4axis,.jqplot-y5axis,.jqplot-y6axis,.jqplot-y7axis,.jqplot-y8axis,.jqplot-y9axis{margin-left:10px;margin-right:10px;}.jqplot-axis-tick,.jqplot-xaxis-tick,.jqplot-yaxis-tick,.jqplot-x2axis-tick,.jqplot-y2axis-tick,.jqplot-y3axis-tick,.jqplot-y4axis-tick,.jqplot-y5axis-tick,.jqplot-y6axis-tick,.jqplot-y7axis-tick,.jqplot-y8axis-tick,.jqplot-y9axis-tick{position:absolute;}.jqplot-xaxis-tick{top:0;left:15px;vertical-align:top;}.jqplot-x2axis-tick{bottom:0;left:15px;vertical-align:bottom;}.jqplot-yaxis-tick{right:0;top:15px;text-align:right;}.jqplot-yaxis-tick.jqplot-breakTick{right:-20px;margin-right:0;padding:1px 5px 1px 5px;z-index:2;font-size:1.5em;}.jqplot-y2axis-tick,.jqplot-y3axis-tick,.jqplot-y4axis-tick,.jqplot-y5axis-tick,.jqplot-y6axis-tick,.jqplot-y7axis-tick,.jqplot-y8axis-tick,.jqplot-y9axis-tick{left:0;top:15px;text-align:left;}.jqplot-meterGauge-tick{font-size:.75em;color:#999;}.jqplot-meterGauge-label{font-size:1em;color:#999;}.jqplot-xaxis-label{margin-top:10px;font-size:11pt;position:absolute;}.jqplot-x2axis-label{margin-bottom:10px;font-size:11pt;position:absolute;}.jqplot-yaxis-label{margin-right:10px;font-size:11pt;position:absolute;}.jqplot-y2axis-label,.jqplot-y3axis-label,.jqplot-y4axis-label,.jqplot-y5axis-label,.jqplot-y6axis-label,.jqplot-y7axis-label,.jqplot-y8axis-label,.jqplot-y9axis-label{font-size:11pt;position:absolute;}table.jqplot-table-legend{margin-top:12px;margin-bottom:12px;margin-left:12px;margin-right:12px;}table.jqplot-table-legend,table.jqplot-cursor-legend{background-color:rgba(255,255,255,0.6);border:1px solid #ccc;position:absolute;font-size:.75em;}td.jqplot-table-legend{vertical-align:middle;}td.jqplot-seriesToggle:hover,td.jqplot-seriesToggle:active{cursor:pointer;}td.jqplot-table-legend>div{border:1px solid #ccc;padding:1px;}div.jqplot-table-legend-swatch{width:0;height:0;border-top-width:5px;border-bottom-width:5px;border-left-width:6px;border-right-width:6px;border-top-style:solid;border-bottom-style:solid;border-left-style:solid;border-right-style:solid;}.jqplot-title{top:0;left:0;padding-bottom:.5em;font-size:1.2em;}table.jqplot-cursor-tooltip{border:1px solid #ccc;font-size:.75em;}.jqplot-cursor-tooltip{border:1px solid #ccc;font-size:.75em;white-space:nowrap;background:rgba(208,208,208,0.5);padding:1px;}.jqplot-highlighter-tooltip{border:1px solid #ccc;font-size:.75em;white-space:nowrap;background:rgba(208,208,208,0.5);padding:1px;}.jqplot-point-label{font-size:.75em;z-index:2;}td.jqplot-cursor-legend-swatch{vertical-align:middle;text-align:center;}div.jqplot-cursor-legend-swatch{width:1.2em;height:.7em;}.jqplot-error{text-align:center;}.jqplot-error-message{position:relative;top:46%;display:inline-block;}div.jqplot-bubble-label{font-size:.8em;padding-left:2px;padding-right:2px;color:rgb(20%,20%,20%);}div.jqplot-bubble-label.jqplot-bubble-label-highlight{background:rgba(90%,90%,90%,0.7);}div.jqplot-noData-container{text-align:center;background-color:rgba(96%,96%,96%,0.3);}"); writer.WriteLine("body{ background: #EEEEEE; color: #000; text-align: center;}"); writer.WriteLine("body, table{ font-family: Arial, Helvetica, sans-serif; font-size: 12px; }"); writer.WriteLine("#page{ width: 700px; margin: auto; text-align: left; background-color: #FFF;}"); writer.WriteLine("table.info{ border: 0; width: 690px; margin: 5px;}"); writer.WriteLine("table.info td{ background-color: #efefef; padding: 1em;}"); writer.WriteLine("table.info td.header{ font-weight: bold; width: 150px; background-color: #EEE;}"); writer.WriteLine("tr.error td, tr.error td.header { background-color: #F5A9BC; color: red; }"); writer.WriteLine("tr.warning td, tr.warning td.header { background-color: #FFCC66; color: #FF6600; }"); writer.WriteLine("h1{ font-size: 16px; padding: 1em; }"); writer.WriteLine("</style>"); } else { writer.WriteLine("<link rel=\"stylesheet\" type=\"text/css\" href=\"css/CsvCompare.Resources.jquery.jqplot.min.css\">"); writer.WriteLine("<link rel=\"stylesheet\" type=\"text/css\" href=\"css/CsvCompare.Resources.style.css\">"); } writer.WriteLine("</head>"); writer.WriteLine("<body>"); writer.WriteLine("<div id=\"page\">"); writer.WriteLine("<a id=\"top\"/>"); writer.WriteLine("<h1>{0}</h1>", this._path); writer.WriteLine("<table class=\"info\">"); if (!String.IsNullOrEmpty(_metaPath)) if (!_bRelative) writer.WriteLine(" <tr><td class=\"header\">Meta Report:</td><td><a href=\"file:///{0}\">{1}</a></td></tr>", _metaPath.Replace("\\", "/"), _metaPath); else writer.WriteLine(" <tr><td class=\"header\">Meta Report:</td><td><a href=\"{0}\">{1}</a></td></tr>", Path.GetFileName(_metaPath), Path.GetFileName(_metaPath)); if(null != this.BaseFile) writer.WriteLine(" <tr><td class=\"header\">Base File:</td><td><a href=\"file:///{0}\">{1}</a></td></tr>", this.BaseFile.Replace("\\", "/"), this.BaseFile); if (null != this.CompareFile) writer.WriteLine(" <tr><td class=\"header\">Compare File:</td><td><a href=\"file:///{0}\">{1}</a></td></tr>", this.CompareFile.Replace("\\", "/"), this.CompareFile); writer.WriteLine(" <tr><td class=\"header\">Tolerance:</td><td>{0}</td></tr>", _tolerance); writer.WriteLine(" <tr><td class=\"header\">Tested:</td><td>{0} [UTC]</td></tr>", DateTime.UtcNow); int iTested = _chart.Count - (from c in _chart where c.Errors == -1 select c).Count(); int iErrors = (from c in _chart where c.Errors > 0 && c.Errors != -1 select c).Count(); double dSuccess; if(iTested<=0) dSuccess = 0; else dSuccess = ((1 - ((double)iErrors / (double)iTested))); writer.WriteLine(" <tr><td class=\"header\"> </td><td>The compare file contained {0} results. {1} results have been tested. {2} failed, success rate is {3:0.0%}.</td></tr>", _chart.Count, //All results iTested, //All tested results iErrors, //Errors dSuccess); writer.Write(" <tr><td class=\"header\">Average relative error:</td><td>{0:0.00}</td></tr>", this.AverageError); writer.Write(" <tr><td class=\"header\">Failed Tests:</td><td>"); foreach (Chart c in (from ch in _chart where ch.Errors > 0 select ch)) writer.WriteLine("<a href=\"#a{0}\">{1}</a><br/>", c.Id, c.Title); writer.WriteLine("</td></tr>"); writer.WriteLine("</table><hr/>"); }
public bool WriteReport(Log log, string metaPath, Options options) { if (null != metaPath) _metaPath = metaPath; else _metaPath = string.Empty; if (!string.IsNullOrEmpty(options.ReportDir)) _path = Path.Combine(options.ReportDir, Path.GetFileName(_path)); else { try { _path = Path.GetFullPath(_path); } catch (PathTooLongException) { log.Error("The report path \"{0}\" is too long for the filesystem. Cannot write this report", _path); return false; } } bool bRet = false; if (_bRelative) _path = Path.Combine(Path.GetDirectoryName(_metaPath), _path); if (!options.OverrideOutput && File.Exists(_path)) { _path = Path.Combine(Path.GetDirectoryName(_path), string.Format(CultureInfo.CurrentCulture, "{0:yyyy-MM-ddTHH-mm-ss}-{1}", DateTime.Now, Path.GetFileName(_path))); log.WriteLine(LogLevel.Warning, "Report already exists and --override has been set to false. Changed target filename to \"{0}\"", _path); } using (TextWriter writer = new StreamWriter(_path, false)) { WriteHeader(writer, options); WriteChart(writer); WriteFooter(writer); bRet = true; } log.WriteLine("Report has been written to: {0}", _path); if (!options.InlineScripts && !options.UseBitmapPlots)//Save script files from ressource to file system { Assembly ass = Assembly.GetExecutingAssembly(); foreach (string s in ass.GetManifestResourceNames()) using (Stream stream = ass.GetManifestResourceStream(s)) { string sPath = Path.GetDirectoryName(_path); if (s.ToLowerInvariant().EndsWith(".js")) sPath = Path.Combine(sPath, "js"); else if (s.ToLowerInvariant().EndsWith(".css")) sPath = Path.Combine(sPath, "css"); else continue; if (!Directory.Exists(sPath)) Directory.CreateDirectory(sPath); sPath = Path.Combine(sPath, s); if (!File.Exists(sPath)) using (FileStream fileStream = File.Create(sPath, (int)stream.Length)) { // Initialize the bytes array with the stream length and then fill it with data byte[] bytesInStream = new byte[stream.Length]; stream.Read(bytesInStream, 0, bytesInStream.Length); // Use write method to write to the file specified above fileStream.Write(bytesInStream, 0, bytesInStream.Length); } } } //Clear big data after writing this._chart.Clear(); this._data.Clear(); return bRet; }
/// Write the report to a html file /// @para log logfile object from the main program /// @para options options from commandline /// @return FALSE on error public bool WriteReport(Log log, Options options) { bool bRet = false; if (null == _reports || _reports.Count == 0 || _reports[0] == null)//Exit if empty { log.Error("No report to write!"); return false; } if (!options.NoMetaReport) { if (null == _path)// Setting output path if not already done { _path = new FileInfo(Path.Combine(Path.GetDirectoryName(_reports[0].FileName), string.Format(CultureInfo.CurrentCulture, "{0:yyyy-MM-dd}-index.html", DateTime.Now))); log.WriteLine("No report path has been given, writing to {0}", _path); } else if (!_path.Directory.Exists) _path.Directory.Create(); if (!_path.Extension.StartsWith(".htm", StringComparison.OrdinalIgnoreCase))//add file name to path if not already present _path = new FileInfo(Path.Combine(_path.FullName, string.Format(CultureInfo.CurrentCulture, "{0:yyyy-MM-dd}-index.html", DateTime.Now))); log.WriteLine("Writing meta report to {0}", _path); if (!options.OverrideOutput && _path.Exists) { _path = new FileInfo(Path.Combine(_path.DirectoryName, string.Format(CultureInfo.CurrentCulture, "{0:yyyy-MM-ddTHH-mm-ss}-index.html", DateTime.Now))); log.WriteLine(LogLevel.Warning, "Meta report already exists and --override has been set to false. Changed target filename to \"{0}\"", _path); } //if (!_path.Exists) // _path = new FileInfo(_path.DirectoryName + string.Format(CultureInfo.CurrentCulture, "{0:yyyy-MM-ddTHH-mm-ss}-index.html", DateTime.Now)); // write report to html file using (TextWriter writer = new StreamWriter(_path.FullName, false)) { writer.WriteLine("<!DOCTYPE html>"); writer.WriteLine(" <head>"); writer.WriteLine("<style type=\"text/css\">"); writer.WriteLine("body{ background: #EEEEEE; color: #000; text-align: center;}"); writer.WriteLine("body, table{ font-family: Arial, Helvetica, sans-serif; font-size: 12px; }"); writer.WriteLine("#page{ width: 700px; margin: auto; text-align: left; background-color: #FFF;}"); writer.WriteLine("table.info{ border: 0; width: 690px; margin: 5px;}"); writer.WriteLine("table.info td{ background-color: #efefef; padding: 1em;}"); writer.WriteLine("table.info td.header{ font-weight: bold; width: 150px; background-color: #EEE;}"); writer.WriteLine("table.info td.error, span.error { background-color: #F5A9BC; color: red; }"); writer.WriteLine("table.info td.ok, span.ok{ background-color: #CDFECD; color: green; }"); writer.WriteLine("table.info td.untested, span.untested{ background-color: #DDD; color: #999; }"); writer.WriteLine("table.info td.right{ text-align: right; }"); writer.WriteLine("h1{ font-size: 16px; padding: 1em; }"); writer.WriteLine("</style>"); writer.WriteLine("</head>"); writer.WriteLine("<body>"); writer.WriteLine("<div id=\"page\">"); writer.WriteLine("<table class=\"info\">"); writer.WriteLine(" <tr><td colspan=\"3\" class=\"header\"><h1>Metareport - CSV file comaprison</h1></td></tr>"); writer.WriteLine(" <tr><td colspan=\"2\" class=\"header\">Timestamp:</td><td>{0} [UTC]</td></tr>", DateTime.UtcNow); writer.WriteLine(" <tr><td colspan=\"2\" class=\"header\">Mode:</td><td>{0}</td></tr>", options.Mode.ToString()); switch (options.Mode) { case OperationMode.CsvTreeCompare: writer.WriteLine(" <tr><td colspan=\"2\" class=\"header\">Base Directory:</td><td>{0}</td></tr>", options.Items[1]); writer.WriteLine(" <tr><td colspan=\"2\" class=\"header\">Compare Directory:</td><td>{0}</td></tr>", options.Items[0]); break; case OperationMode.CsvFileCompare: writer.WriteLine(" <tr><td colspan=\"2\" class=\"header\">Base File:</td><td>{0}</td></tr>", options.Items[1]); writer.WriteLine(" <tr><td colspan=\"2\" class=\"header\">Compare File:</td><td>{0}</td></tr>", options.Items[0]); break; case OperationMode.FmuChecker: writer.WriteLine(" <tr><td colspan=\"2\" class=\"header\">FMU Checker:</td><td>{0}</td></tr>", options.CheckerPath); writer.WriteLine(" <tr><td colspan=\"2\" class=\"header\">FMU Arguments:</td><td>{0}</td></tr>", options.CheckerArgs); break; default: break; } writer.WriteLine(" <tr><td colspan=\"2\" class=\"header\">Verbosity:</td><td>{0}</td></tr>", options.Verbosity.ToString(CultureInfo.CurrentCulture)); if (null != options.Tolerance) writer.WriteLine(" <tr><td colspan=\"2\" class=\"header\">Tolerance:</td><td>{0}</td></tr>", options.Tolerance); if (!String.IsNullOrEmpty(options.Logfile)) { writer.WriteLine(" <tr><td colspan=\"2\" class=\"header\">Logfile:</td><td><a href=\"file:///{0}\">{0}</a></td></tr>", options.Logfile); writer.WriteLine(" <tr><td colspan=\"2\" class=\"header\">Loglevel:</td><td>{0}</td></tr>", ((LogLevel)options.Verbosity)); } int iTested = 0; int iErrors = 0; double dSuccess; try { iTested = _reports.Count - (from c in _reports where c.TotalErrors == -1 select c).Count(); iErrors = (from c in _reports where c.TotalErrors > 0 && c.TotalErrors != -1 select c).Count(); } catch (NullReferenceException) { //empty reports } if (iTested <= 0) dSuccess = 0; else dSuccess = ((1 - ((double)iErrors / (double)iTested))); writer.WriteLine(" <tr><td colspan=\"2\" class=\"header\">Compared Files:</td><td>The compare file contained {0} results. {1} results have been tested. {2} failed, success rate is {3:0.0%}.</td></tr>", _reports.Count, //All results iTested, //All tested results iErrors, //Errors dSuccess); writer.WriteLine("<tr><td class=\"header\" colspan=\"3\">Results</td></tr>"); writer.WriteLine("<tr><td colspan=\"2\"> </td><td>FAILED - at least one result failed its check with the base file<br/>UNTESTED - no base file has been found for all results in the file<br/>SUCCEEDED - All results have been checked and are valid</td></tr>"); //write results and paths of the sub reports foreach (Report r in _reports) { if (null != r)// Catch empty report objects { if (_bReportDirSet) { r.FileName = Path.Combine(_path.Directory.FullName, Path.GetFileName(r.FileName)); r.RelativePaths = true; } if (r.TotalErrors > 0) { if (r.RelativePaths) writer.WriteLine("<tr><td class=\"error right\">FAILED</td><td class=\"error\">Ø{0:0.00}</td><td class=\"error\"><a href=\"{1}\">{1}</a></td></tr>", r.AverageError, Path.GetFileName(r.FileName)); else writer.WriteLine("<tr><td class=\"error right\">FAILED</td><td class=\"error\">Ø{0:0.00}</td><td class=\"error\"><a href=\"file:///{0}\">{1}</a></td></tr>", r.FileName.Replace("\\", "/"), r.FileName); } else if (r.TotalErrors==-1) // if all results have not been checked, mark as "untested" { if (r.RelativePaths) writer.WriteLine("<tr><td colspan=\"2\" class=\"untested right\">UNTESTED</td><td class=\"untested\"><a href=\"{0}\">{0}</a></td></tr>", Path.GetFileName(r.FileName)); else writer.WriteLine("<tr><td colspan=\"2\" class=\"untested right\">UNTESTED</td><td class=\"untested\"><a href=\"file:///{0}\">{1}</a></td></tr>", r.FileName.Replace("\\", "/"), r.FileName); } else { if (r.RelativePaths) writer.WriteLine("<tr><td colspan=\"2\" class=\"ok right\">SUCCEEDED</td><td class=\"ok\"><a href=\"{0}\">{0}</a></td></tr>", Path.GetFileName(r.FileName)); else writer.WriteLine("<tr><td colspan=\"2\" class=\"ok right\">SUCCEEDED</td><td class=\"ok\"><td class=\"ok\"><a href=\"file:///{0}\">{1}</a></td></tr>", r.FileName.Replace("\\", "/"), r.FileName); } } } writer.WriteLine("</table>"); writer.WriteLine(@"</div> </body> </html> "); } log.WriteLine("Metareport has been written to: {0}", this.FileName); } else { log.WriteLine("Skipping generation of metareport as \"--nometareport\" has been set."); foreach (Report r in _reports) if (!r.WriteReport(log, _path.FullName, options)) log.Error("Error writing report to {0}", r.FileName); } return bRet; }