public static void ParseGenerateCompare(string path, List <Skeleton> skeletons, DocumentFormat format, bool autoRemarks = false) { var document = Parser.Parse(Path.Combine(ROOT, INPUT, path), format, autoRemarks); var columns = document.Results.ProgramClassDocumentSnapshot.TextSourceInfo.ColumnsLayout; var writer = new StringWriter(); // write parsing errors WriteErrors(writer, document.Results.AllDiagnostics(), columns); // write generated code var codegen = new TypeCobol.Codegen.Generators.DefaultGenerator(document.Results, writer, skeletons); var program = document.Results.ProgramClassDocumentSnapshot.Program; codegen.Generate(program == null ? null : program.SyntaxTree.Root, program == null ? null : program.SymbolTable, columns); // flush writer.Close(); // compare with expected result string expected = File.ReadAllText(Path.Combine(ROOT, OUTPUT, path), format.Encoding); TypeCobol.Test.TestUtils.compareLines(path, writer.ToString(), expected); }
public static void CheckTests(string rootFolder, string resultFolder, string timedResultFile, string regex, string[] include, string[] exclude, string[] copiesFolder, string skelPath, int stopAfterAsManyErrors, bool autoRemarks, string expectedResultFile) { string[] files = Directory.GetFiles(rootFolder, regex, SearchOption.AllDirectories); bool codegen = true; var format = TypeCobol.Compiler.DocumentFormat.RDZReferenceFormat; string resultFile = "GeneratedResultFile.txt"; //Initialize both files File.WriteAllText(timedResultFile, ""); if (expectedResultFile != null) { File.WriteAllText(resultFile, ""); } int tested = 0, nbFilesInError = 0, ignores = 0; TimeSpan parsingSumDuration = new TimeSpan(0); TimeSpan codeGenSumDuration = new TimeSpan(0); int parseErrors = 0; int codegenErrors = 0; int codegenDiff = 0; foreach (var file in files) { string filename = Path.GetFileName(file); AppendTextToFiles((filename + ':'), timedResultFile, resultFile); bool ignore = include.Length > 0 && !include.Contains(filename); if (!ignore) { ignore = exclude.Contains(filename); } if (ignore) { ignores++; File.AppendAllText(timedResultFile, " ignored.\n"); continue; } string path = Path.Combine(rootFolder, filename); Stopwatch watch = new Stopwatch(); watch.Start(); var document = new TypeCobol.Parser(); var options = new TypeCobolOptions { ExecToStep = ExecutionStep.CrossCheck, #if EUROINFO_RULES AutoRemarksEnable = autoRemarks #endif }; document.Init(path, options, format, copiesFolder); document.Parse(path); watch.Stop(); //TestJSONSerializer.DumpAsJSON(unit.CodeElementsDocumentSnapshot.CodeElements, filename); TimeSpan elapsed = watch.Elapsed; parsingSumDuration += elapsed; string formatted = String.Format("{0:00}m{1:00}s{2:000}ms", elapsed.Minutes, elapsed.Seconds, elapsed.Milliseconds); AppendTextToFiles(" parsed in " + formatted + "\n", timedResultFile); AppendTextToFiles("- " + document.Results.PerfStatsForText.FirstCompilationTime + " ms : text update\n", timedResultFile); AppendTextToFiles("- " + document.Results.PerfStatsForScanner.FirstCompilationTime + " ms : scanner\n", timedResultFile); AppendTextToFiles("- " + document.Results.PerfStatsForPreprocessor.FirstCompilationTime + " ms : preprocessor\n", timedResultFile); AppendTextToFiles("- " + document.Results.PerfStatsForCodeElementsParser.FirstCompilationTime + " ms : code elements parser\n", timedResultFile); AppendTextToFiles("- " + document.Results.PerfStatsForTemporarySemantic.FirstCompilationTime + " ms : temporary semantic class parser\n", timedResultFile); AppendTextToFiles("- " + document.Results.PerfStatsForProgramCrossCheck.FirstCompilationTime + " ms : cross check class parser\n", timedResultFile); tested++; Console.WriteLine(filename); bool okay = true; var diagnostics = document.Results.AllDiagnostics(); if (diagnostics.Count > 0) { okay = false; parseErrors += diagnostics.Count; } displayAndWriteErrorsToGrammarResult(diagnostics, timedResultFile, resultFile); if (!okay) { nbFilesInError++; if (nbFilesInError >= stopAfterAsManyErrors) { break; } } if (codegen && okay) { watch.Reset(); watch.Start(); var writer = new StringWriter(); //Retrieve skeletons var skeletons = !string.IsNullOrEmpty(skelPath) ? Config.Parse(skelPath) : null; var generator = new TypeCobol.Codegen.Generators.DefaultGenerator(document.Results, writer, skeletons, null); var columns = document.Results.ProgramClassDocumentSnapshot.TextSourceInfo.ColumnsLayout; generator.Generate(document.Results, columns); writer.Close(); //Write duration to GrammarResultFile watch.Stop(); elapsed = watch.Elapsed; codeGenSumDuration += elapsed; formatted = String.Format("{0:00}m{1:00}s{2:000}ms", elapsed.Minutes, elapsed.Seconds, elapsed.Milliseconds); AppendTextToFiles(" generated in " + formatted + "\n", timedResultFile); //Error during generation, no need to check the content of generated Cobol if (generator.Diagnostics != null && generator.Diagnostics.Count > 0) { codegenErrors += generator.Diagnostics.Count; displayAndWriteErrorsToGrammarResult(generator.Diagnostics, timedResultFile, resultFile); nbFilesInError++; if (nbFilesInError >= stopAfterAsManyErrors) { break; } } else { //Compare generated Cobol with expected var expected = AsLines(File.ReadAllText(path, format.Encoding)); var actual = AsLines(writer.ToString()); Directory.CreateDirectory(resultFolder); var linesKO = new List <int>(); for (int i = 0; i < Math.Min(expected.Count, actual.Count); i++) { if (!expected[i].Equals(actual[i])) { linesKO.Add(i); } } var errors = new System.Text.StringBuilder(); string fmt = Lines2FormatString(Math.Max(expected.Count, actual.Count)); if (linesKO.Count > 0 || expected.Count != actual.Count) { errors.AppendLine("--- Lines mismatch ---"); File.WriteAllLines( resultFolder + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(file) + "-Expected" + Path.GetExtension(file), expected); File.WriteAllLines( resultFolder + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(file) + "-Actual" + Path.GetExtension(file), actual); } int start = -1; for (int i = 0; i < linesKO.Count; i++) { int currentline = linesKO[i]; bool follows = i > 0 && linesKO[i - 1] == currentline - 1; if (!follows) { start = currentline; before(errors, expected, currentline, 3, fmt); } bool preceeds = i + 1 < linesKO.Count && linesKO[i + 1] == currentline + 1; if (!preceeds) { diff(errors, expected, actual, start, currentline, fmt); after(errors, expected, currentline, 3, fmt); start = -1; } } for (int i = actual.Count; i < expected.Count; i++) { errors.AppendLine(String.Format("-{0:" + fmt + "} {1}", i, expected[i])); } for (int i = expected.Count; i < actual.Count; i++) { errors.AppendLine(String.Format("+{0:" + fmt + "} {1}", i, actual[i])); } if (errors.Length > 0) { codegenDiff += linesKO.Count + Math.Abs(actual.Count - expected.Count); AppendTextToFiles(errors.ToString(), timedResultFile, resultFile); if (okay) { nbFilesInError++; } } } } else { AppendTextToFiles("\n", timedResultFile, resultFile); } } TimeSpan totalTestDuration = parsingSumDuration + codeGenSumDuration; string parsingTotalDurationFormatted = String.Format("{0:00}m{1:00}s{2:000}ms", parsingSumDuration.Minutes, parsingSumDuration.Seconds, parsingSumDuration.Milliseconds); string message = "Files tested=" + tested + "/" + files.Length + ", files in error=" + nbFilesInError + ", ignored=" + ignores + "\n"; AppendTextToFiles(message, resultFile); if (parseErrors > 0) { message += "Parsing errors: " + parseErrors + '\n'; } if (codegenErrors > 0) { message += "Codegen errors: " + codegenErrors + '\n'; } if (codegenDiff > 0) { message += "Codegen Diff: " + codegenDiff + '\n'; } message += "Parsing time: " + parsingTotalDurationFormatted; if (codegen) { string codeGenTotalDurationFormatted = string.Format("{0:00}m{1:00}s{2:000}ms", codeGenSumDuration.Minutes, codeGenSumDuration.Seconds, codeGenSumDuration.Milliseconds); string totalDurationFormatted = String.Format("{0:00}m{1:00}s{2:000}ms", totalTestDuration.Minutes, totalTestDuration.Seconds, totalTestDuration.Milliseconds); message += " + Codegen time: " + codeGenTotalDurationFormatted + " => Total time: " + totalDurationFormatted; } AppendTextToFiles(message, timedResultFile); if (nbFilesInError > 0 && expectedResultFile == null) { Assert.Fail('\n' + message); //If no expectedFile to compare throw assert if error } else if (expectedResultFile != null) //If expectedFileResult exists compare the DefaultGeneratedFile with expectedFile { StreamReader expectedResultReader = new StreamReader(new FileStream(expectedResultFile, FileMode.Open)); StreamReader actualResultReader = new StreamReader(new FileStream(resultFile, FileMode.Open)); TestUtils.compareLines("GrammarTestCompareFiles", expectedResultReader.ReadToEnd(), actualResultReader.ReadToEnd()); //The test will fail if result files are different expectedResultReader.Close(); actualResultReader.Close(); } }
public static void CheckTests(string rootFolder, string resultFolder, string resultFile, string regex, string[] include, string[] exclude, string[] copiesFolder, int stopAfterAsManyErrors = 10000) { string[] files = Directory.GetFiles(rootFolder, regex, SearchOption.AllDirectories); bool codegen = true; var format = TypeCobol.Compiler.DocumentFormat.RDZReferenceFormat; File.WriteAllText(resultFile, ""); int tested = 0, nbFilesInError = 0, ignores = 0; TimeSpan parsingSumDuration = new TimeSpan(0); TimeSpan codeGenSumDuration = new TimeSpan(0); int parseErrors = 0; int codegenErrors = 0; foreach (var file in files) { string filename = Path.GetFileName(file); File.AppendAllText(resultFile, (filename + ':')); bool ignore = include.Length > 0 && !include.Contains(filename); if (!ignore) { ignore = exclude.Contains(filename); } if (ignore) { ignores++; File.AppendAllText(resultFile, " ignored.\n"); continue; } string path = Path.Combine(rootFolder, filename); Stopwatch watch = new Stopwatch(); watch.Start(); var document = new Parser(); document.Init(path, new TypeCobolOptions { ExecToStep = ExecutionStep.SemanticCheck }, format, copiesFolder); document.Parse(path); watch.Stop(); //TestJSONSerializer.DumpAsJSON(unit.CodeElementsDocumentSnapshot.CodeElements, filename); TimeSpan elapsed = watch.Elapsed; parsingSumDuration += elapsed; string formatted = String.Format("{0:00}m{1:00}s{2:000}ms", elapsed.Minutes, elapsed.Seconds, elapsed.Milliseconds); File.AppendAllText(resultFile, " parsed in " + formatted + "\n"); File.AppendAllText(resultFile, "- " + document.Results.PerfStatsForText.FirstCompilationTime + " ms : text update\n"); File.AppendAllText(resultFile, "- " + document.Results.PerfStatsForScanner.FirstCompilationTime + " ms : scanner\n"); File.AppendAllText(resultFile, "- " + document.Results.PerfStatsForPreprocessor.FirstCompilationTime + " ms : preprocessor\n"); File.AppendAllText(resultFile, "- " + document.Results.PerfStatsForCodeElementsParser.FirstCompilationTime + " ms : code elements parser\n"); File.AppendAllText(resultFile, "- " + document.Results.PerfStatsForProgramClassParser.FirstCompilationTime + " ms : program class parser\n"); tested++; Console.WriteLine(filename); bool okay = true; var diagnostics = document.Results.AllDiagnostics(); if (diagnostics.Count > 0) { okay = false; parseErrors += diagnostics.Count; } displayAndWriteErrorsToGrammarResult(resultFile, diagnostics); if (!okay) { nbFilesInError++; if (nbFilesInError >= stopAfterAsManyErrors) { break; } } if (codegen && okay) { var writer = new StringWriter(); watch.Reset(); watch.Start(); var generator = new TypeCobol.Codegen.Generators.DefaultGenerator(document.Results, writer, null); var columns = document.Results.ProgramClassDocumentSnapshot.TextSourceInfo.ColumnsLayout; generator.Generate(document.Results, columns); //Write duration to GrammarResultFile watch.Stop(); elapsed = watch.Elapsed; codeGenSumDuration += elapsed; formatted = String.Format("{0:00}m{1:00}s{2:000}ms", elapsed.Minutes, elapsed.Seconds, elapsed.Milliseconds); File.AppendAllText(resultFile, " generated in " + formatted + "\n"); writer.Close(); var expected = AsLines(File.ReadAllText(path, format.Encoding)); var actual = AsLines(writer.ToString()); Directory.CreateDirectory(resultFolder); var linesKO = new List <int>(); for (int i = 0; i < Math.Min(expected.Count, actual.Count); i++) { if (!expected[i].Equals(actual[i])) { linesKO.Add(i); } } var errors = new System.Text.StringBuilder(); string fmt = Lines2FormatString(Math.Max(expected.Count, actual.Count)); if (linesKO.Count > 0 || expected.Count != actual.Count) { errors.AppendLine("--- Lines mismatch ---"); File.WriteAllLines( resultFolder + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(file) + "-Expected" + Path.GetExtension(file), expected); File.WriteAllLines( resultFolder + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(file) + "-Actual" + Path.GetExtension(file), actual); } int start = -1; for (int i = 0; i < linesKO.Count; i++) { int currentline = linesKO[i]; bool follows = i > 0 && linesKO[i - 1] == currentline - 1; if (!follows) { start = currentline; before(errors, expected, currentline, 3, fmt); } bool preceeds = i + 1 < linesKO.Count && linesKO[i + 1] == currentline + 1; if (!preceeds) { diff(errors, expected, actual, start, currentline, fmt); after(errors, expected, currentline, 3, fmt); start = -1; } } for (int i = actual.Count; i < expected.Count; i++) { errors.AppendLine(String.Format("-{0:" + fmt + "} {1}", i, expected[i])); } for (int i = expected.Count; i < actual.Count; i++) { errors.AppendLine(String.Format("+{0:" + fmt + "} {1}", i, actual[i])); } if (errors.Length > 0) { codegenErrors += linesKO.Count + Math.Abs(actual.Count - expected.Count); File.AppendAllText(resultFile, errors.ToString()); if (okay) { nbFilesInError++; } } } else { File.AppendAllText(resultFile, "\n"); } } TimeSpan totalTestDuration = parsingSumDuration + codeGenSumDuration; string parsingTotalDurationFormatted = String.Format("{0:00}m{1:00}s{2:000}ms", parsingSumDuration.Minutes, parsingSumDuration.Seconds, parsingSumDuration.Milliseconds); string message = "Files tested=" + tested + "/" + files.Length + ", files in error=" + nbFilesInError + ", ignored=" + ignores + "\n"; if (parseErrors > 0) { message += "Parsing errors: " + parseErrors + '\n'; } if (codegenErrors > 0) { message += "Codegen errors: " + codegenErrors + '\n'; } message += "Parsing time: " + parsingTotalDurationFormatted; if (codegen) { string codeGenTotalDurationFormatted = string.Format("{0:00}m{1:00}s{2:000}ms", codeGenSumDuration.Minutes, codeGenSumDuration.Seconds, codeGenSumDuration.Milliseconds); string totalDurationFormatted = String.Format("{0:00}m{1:00}s{2:000}ms", totalTestDuration.Minutes, totalTestDuration.Seconds, totalTestDuration.Milliseconds); message += " + Codegen time: " + codeGenTotalDurationFormatted + " => Total time: " + totalDurationFormatted; } File.AppendAllText(resultFile, message); if (nbFilesInError > 0) { Assert.Fail('\n' + message); } }
private static ReturnCode runOnce2(TypeCobolConfiguration config, AbstractErrorWriter errorWriter) { var parser = new Parser(); bool diagDetected = false; EventHandler <Tools.APIHelpers.DiagnosticsErrorEvent> DiagnosticsErrorEvent = null; DiagnosticsErrorEvent += delegate(object sender, Tools.APIHelpers.DiagnosticsErrorEvent diagEvent) { //Delegate Event to handle diagnostics generated while loading dependencies/intrinsics diagDetected = true; var diagnostic = diagEvent.Diagnostic; Server.AddError(errorWriter, MessageCode.IntrinsicLoading, diagnostic.ColumnStart, diagnostic.ColumnEnd, diagnostic.Line, "Error while parsing : " + diagnostic, diagEvent.Path); }; parser.CustomSymbols = Tools.APIHelpers.Helpers.LoadIntrinsic(config.Copies, config.Format, DiagnosticsErrorEvent); //Load of the intrinsics parser.CustomSymbols = Tools.APIHelpers.Helpers.LoadDependencies(config.Dependencies, config.Format, parser.CustomSymbols, config.InputFiles, DiagnosticsErrorEvent); //Load of the dependency files if (diagDetected) { throw new CopyLoadingException("Diagnostics detected while parsing Intrinsic file", null, null, logged: false, needMail: false); } ReturnCode returnCode = ReturnCode.Success; for (int c = 0; c < config.InputFiles.Count; c++) { string path = config.InputFiles[c]; try { var typeCobolOptions = new TypeCobolOptions { HaltOnMissingCopy = config.HaltOnMissingCopyFilePath != null, ExecToStep = config.ExecToStep, }; #if EUROINFO_RULES typeCobolOptions.AutoRemarksEnable = config.AutoRemarks; #endif parser.Init(path, typeCobolOptions, config.Format, config.CopyFolders); //Init parser create CompilationProject & Compiler before parsing the given file } catch (Exception ex) { throw new ParsingException(MessageCode.ParserInit, ex.Message, path, ex); //Make ParsingException trace back to RunOnce() } parser.Parse(path); bool copyAreMissing = false; if (!string.IsNullOrEmpty(config.HaltOnMissingCopyFilePath)) { if (parser.MissingCopys.Count > 0) { //Write in the specified file all the absent copys detected File.WriteAllLines(config.HaltOnMissingCopyFilePath, parser.MissingCopys); copyAreMissing = true; } else { //Delete the file File.Delete(config.HaltOnMissingCopyFilePath); } } var allDiags = parser.Results.AllDiagnostics(); errorWriter.AddErrors(path, allDiags.Take(config.MaximumDiagnostics == 0 ? allDiags.Count : config.MaximumDiagnostics)); //Write diags into error file if (allDiags.Count > 0) { foreach (var diag in allDiags) { if (diag.CatchedException != null) { AnalyticsWrapper.Telemetry.TrackException(diag.CatchedException); AnalyticsWrapper.Telemetry.SendMail(diag.CatchedException, config.InputFiles, config.CopyFolders, config.CommandLine); } } AnalyticsWrapper.Telemetry.TrackEvent("[Diagnostics] Detected"); //Exception is thrown just below } //Copy missing is more important than diagnostics if (copyAreMissing) { throw new MissingCopyException("Some copy are missing", path, null, logged: false, needMail: false); } else if (parser.Results.AllDiagnostics().Any(d => d.Info.Severity == Compiler.Diagnostics.Severity.Error)) { throw new PresenceOfDiagnostics("Diagnostics Detected"); //Make ParsingException trace back to RunOnce() } if (parser.Results.CodeElementsDocumentSnapshot == null && config.ExecToStep > ExecutionStep.Preprocessor) { throw new ParsingException(MessageCode.SyntaxErrorInParser, "File \"" + path + "\" has syntactic error(s) preventing codegen (CodeElements).", path); //Make ParsingException trace back to RunOnce() } else if (parser.Results.ProgramClassDocumentSnapshot == null && config.ExecToStep > ExecutionStep.SyntaxCheck) { throw new ParsingException(MessageCode.SyntaxErrorInParser, "File \"" + path + "\" has semantic error(s) preventing codegen (ProgramClass).", path); //Make ParsingException trace back to RunOnce() } if (config.ExecToStep >= ExecutionStep.Generate) { var skeletons = TypeCobol.Codegen.Config.Config.Parse(config.skeletonPath); var codegen = new TypeCobol.Codegen.Generators.DefaultGenerator(parser.Results, new StreamWriter(config.OutputFiles[c]), skeletons); try { codegen.Generate(parser.Results, ColumnsLayout.CobolReferenceFormat); if (codegen.Diagnostics != null) { errorWriter.AddErrors(path, codegen.Diagnostics); //Write diags into error file throw new PresenceOfDiagnostics("Diagnostics Detected"); //Make ParsingException trace back to RunOnce() } } catch (PresenceOfDiagnostics) { //rethrow exception throw; } catch (Exception e) { if (e is GenerationException) { throw e; //Throw the same exception to let runOnce() knows there is a problem } throw new GenerationException(e.Message, path, e); //Otherwise create a new GenerationException } } if (parser.Results.AllDiagnostics().Any(d => d.Info.Severity == Compiler.Diagnostics.Severity.Warning)) { returnCode = ReturnCode.Warning; } } return(returnCode); }
private static void runOnce2(Config config) { TextWriter w; if (config.ErrorFile == null) { w = Console.Error; } else { w = File.CreateText(config.ErrorFile); } AbstractErrorWriter errorWriter; if (config.IsErrorXML) { errorWriter = new XMLWriter(w); } else { errorWriter = new ConsoleWriter(w); } errorWriter.Outputs = config.OutputFiles; var parser = new Parser(); parser.CustomSymbols = LoadCopies(errorWriter, config.Copies, config.Format); //Load of the intrinsics parser.CustomSymbols = LoadDependencies(errorWriter, config.Dependencies, config.Format, parser.CustomSymbols); //Load of the dependency files for (int c = 0; c < config.InputFiles.Count; c++) { string path = config.InputFiles[c]; try { var typeCobolOptions = new TypeCobolOptions { HaltOnMissingCopy = config.HaltOnMissingCopyFilePath != null, ExecToStep = config.ExecToStep, }; #if EUROINFO_RULES typeCobolOptions.AutoRemarksEnable = config.AutoRemarks; #endif parser.Init(path, typeCobolOptions, config.Format, config.CopyFolders); } catch (Exception ex) { Server.AddError(errorWriter, MessageCode.ParserInit, ex.Message, path); continue; } parser.Parse(path); if (!string.IsNullOrEmpty(config.HaltOnMissingCopyFilePath)) { if (parser.MissingCopys.Count > 0) { //Write in the specified file all the absent copys detected File.WriteAllLines(config.HaltOnMissingCopyFilePath, parser.MissingCopys); } else { //Delete the file File.Delete(config.HaltOnMissingCopyFilePath); } } if (parser.Results.CodeElementsDocumentSnapshot == null && config.ExecToStep > ExecutionStep.Preprocessor) { Server.AddError(errorWriter, MessageCode.SyntaxErrorInParser, "File \"" + path + "\" has syntactic error(s) preventing codegen (CodeElements).", path); continue; } else if (parser.Results.ProgramClassDocumentSnapshot == null && config.ExecToStep > ExecutionStep.SyntaxCheck) { Server.AddError(errorWriter, MessageCode.SyntaxErrorInParser, "File \"" + path + "\" has semantic error(s) preventing codegen (ProgramClass).", path); continue; } var allDiags = parser.Results.AllDiagnostics(); int errors = allDiags.Count; errorWriter.AddErrors(path, allDiags); if (config.ExecToStep >= ExecutionStep.Generate && errors == 0) { var skeletons = TypeCobol.Codegen.Config.Config.Parse(config.skeletonPath); var codegen = new TypeCobol.Codegen.Generators.DefaultGenerator(parser.Results, new StreamWriter(config.OutputFiles[c]), skeletons); var program = parser.Results.ProgramClassDocumentSnapshot.Program; codegen.Generate(program.SyntaxTree.Root, program.SymbolTable, ColumnsLayout.CobolReferenceFormat); } } errorWriter.Write(); errorWriter.FlushAndClose(); errorWriter = null; //as w can be a Text file created, we need to close it w.Close(); }