/// <summary> /// Get line-parsed source from file name /// </summary> /// <param name="filePath"></param> /// <returns></returns> public static CodeCoverageStringTextSource GetSource(string filePath) { var retSource = new CodeCoverageStringTextSource(null, filePath); // null indicates source-file not found if (System.IO.File.Exists(filePath)) { try { using (Stream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) using (var reader = new StreamReader(stream, Encoding.Default, true)) { stream.Position = 0; retSource = new CodeCoverageStringTextSource(reader.ReadToEnd(), filePath); } } catch (Exception e) { // Source is optional (for excess-branch removal), application can continue without it e.InformUser(); // Do not throw ExitApplicationWithoutReportingException } } else { String.Format("Source file {0} not found", filePath).InformUserSoft(); } return(retSource); }
public void ConstructWithEmptyString() { // arrange var source = new CodeCoverageStringTextSource(string.Empty, ""); // assert Assert.True (source.LinesCount == 0); // act var result = source.GetLine(1); // not existing line index // assert Assert.True (result == string.Empty); // act result = source.GetLine(0); // invalid line index // assert Assert.True (result == string.Empty); // act var sp = new SequencePoint { StartLine = 1, StartColumn = 1, EndLine = 1, EndColumn = 6}; result = source.GetText(sp); // assert Assert.True (result == string.Empty); // act sp = new SequencePoint { StartLine = -1, StartColumn = -1, EndLine = -2, EndColumn = 6}; result = source.GetText(sp); // assert Assert.True (result == string.Empty); }
/// <summary> /// Get line-parsed source from file name /// </summary> /// <param name="filename"></param> /// <returns></returns> public static CodeCoverageStringTextSource GetSource(string filename) { var retSource = (CodeCoverageStringTextSource)null; try { using (Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read)) { try { stream.Position = 0; using (var reader = new StreamReader(stream, Encoding.Default, true)) { retSource = new CodeCoverageStringTextSource(reader.ReadToEnd()); switch (Path.GetExtension(filename).ToLowerInvariant()) { case ".cs": retSource.FileType = FileType.CSharp; break; case ".vb": retSource.FileType = FileType.VBasic; break; default: retSource.FileType = FileType.Unsupported; break; } } } catch (Exception) {} } } catch (Exception) {} return(retSource); }
public void ConstructWithSingleLine() { // arrange const string input = "single line"; var source = new CodeCoverageStringTextSource(input, ""); // assert Assert.True (source.LinesCount == 1); // act var result = source.GetLine(1); // existing line index // assert Assert.True (result == input); // act result = source.GetLine(0); // invalid line index // assert Assert.True (result == string.Empty); // act var sp = new SequencePoint { StartLine = 1, StartColumn = 1, EndLine = 1, EndColumn = 7}; result = source.GetText(sp); // assert Assert.True (result == "single"); // act with too small StartColumn sp = new SequencePoint { StartLine = 1, StartColumn = -1, EndLine = 1, EndColumn = 7}; result = source.GetText(sp); // assert Assert.True (result == "single"); // act with too large StartColumn sp = new SequencePoint { StartLine = 1, StartColumn = 19, EndLine = 1, EndColumn = 20}; result = source.GetText(sp); // assert Assert.True (result == ""); // act with too small EndColumn sp = new SequencePoint { StartLine = 1, StartColumn = 1, EndLine = 1, EndColumn = 0}; result = source.GetText(sp); // assert Assert.True (result == ""); // act with too large EndColumn sp = new SequencePoint { StartLine = 1, StartColumn = 1, EndLine = 1, EndColumn = 20}; result = source.GetText(sp); // assert Assert.True (result == "single line"); }
public void ConstructWithNullString() { // arrange var source = new CodeCoverageStringTextSource(null, ""); // assert Assert.True (source.LinesCount == 0); // act var result = source.GetLine(1); // not existing line index // assert Assert.True (result == string.Empty); // act result = source.GetLine(0); // invalid line index // assert Assert.True (result == string.Empty); }
/// <summary> /// Get line-parsed source from file name /// </summary> /// <param name="filePath"></param> /// <param name="logger"></param> /// <returns></returns> public static CodeCoverageStringTextSource GetSource(string filePath, ILog logger) { var retSource = new CodeCoverageStringTextSource(null, filePath, logger); // null indicates source-file not found if (!System.IO.File.Exists(filePath)) { logger.InfoFormat($"Source file does not exist: {filePath}"); return(retSource); } try { using (Stream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) using (var reader = new StreamReader(stream, Encoding.Default, true)) { stream.Position = 0; retSource = new CodeCoverageStringTextSource(reader.ReadToEnd(), filePath, logger); } } catch (Exception e) { // Source is optional (for excess-branch removal), application can continue without it logger.InfoFormat($"An {e.GetType()} occured: {e.Message}"); } return(retSource); }
public void CountLinesWithMixedLineEnd() { // arrange const string input = "\r\r\r\n \r\n \r\n \r \n \n\n\n\r\n\n"; // 1 2 3 4 5 6 7 8 910 1112 var source = new CodeCoverageStringTextSource(input, ""); // assert Assert.True (source.LinesCount == 12); // act var result = source.GetLine(1); // existing line index // assert Assert.True (result == "\r"); }
public void CountLinesWithCrLf() { // arrange const string input = "\r\n\r\n\r\n\r\n"; var source = new CodeCoverageStringTextSource(input, ""); // assert Assert.True (source.LinesCount == 4); // act var result = source.GetLine(1); // existing line index // assert Assert.True (result == "\r\n"); }
public void ConstructWithFiveLines() { // arrange const string input = "\tfirst line\n \n\tthird line\r\n \r fifth line\r"; var source = new CodeCoverageStringTextSource(input, ""); // assert Assert.True (source.LinesCount == 5); // act var result = source.GetLine(1); // existing line index // assert Assert.True (result == "\tfirst line\n"); // act result = source.GetLine(2); // existing line index // assert Assert.True (result == " \n"); // act result = source.GetLine(3); // existing line index // assert Assert.True (result == "\tthird line\r\n"); // act result = source.GetLine(4); // existing line index // assert Assert.True (result == " \r"); // act result = source.GetLine(5); // existing line index // assert Assert.True (result == " fifth line\r"); // act result = source.GetLine(9); // invalid line index // assert Assert.True (result == string.Empty); // act third line request var sp = new SequencePoint { StartLine = 3, StartColumn = 8, EndLine = 3, EndColumn = 12}; result = source.GetText(sp); // assert Assert.True (result == "line"); // act invalid two lines request sp = new SequencePoint { StartLine = 1, StartColumn = 8, EndLine = 2, EndColumn = 13}; result = source.GetText(sp); // assert Assert.True (result == "line\n \n"); // act valid two lines request sp = new SequencePoint { StartLine = 1, StartColumn = 8, EndLine = 2, EndColumn = 2}; result = source.GetText(sp); // assert Assert.True (result == "line\n "); // act three lines request sp = new SequencePoint { StartLine = 1, StartColumn = 8, EndLine = 3, EndColumn = 12}; result = source.GetText(sp); // assert Assert.True (result == "line\n \n\tthird line"); }
public void ConstructWithTwoLines() { // arrange const string input = "\tfirst line\n\tsecond line\r"; var source = new CodeCoverageStringTextSource(input, ""); // assert Assert.True (source.LinesCount == 2); // act with existing line index var result = source.GetLine(1); // assert Assert.True (result == "\tfirst line\n"); // act with existing line index result = source.GetLine(2); // assert Assert.True (result == "\tsecond line\r"); // act with invalid line index result = source.GetLine(0); // assert Assert.True (result == string.Empty); // act var sp = new SequencePoint { StartLine = 2, StartColumn = 9, EndLine = 2, EndColumn = 13}; result = source.GetText(sp); // assert Assert.True (result == "line"); // act with two lines request sp = new SequencePoint { StartLine = 1, StartColumn = 8, EndLine = 2, EndColumn = 13}; result = source.GetText(sp); // assert Assert.True (result == "line\n\tsecond line"); // act with extended two lines request sp = new SequencePoint { StartLine = 1, StartColumn = -8, EndLine = 2, EndColumn = 30}; result = source.GetText(sp); // assert Assert.True (result == "\tfirst line\n\tsecond line\r"); // act with invalid first line request sp = new SequencePoint { StartLine = 1, StartColumn = 28, EndLine = 2, EndColumn = 30}; result = source.GetText(sp); // assert Assert.True (result == "\tsecond line\r"); // act with invalid first line and invalid second line request sp = new SequencePoint { StartLine = 1, StartColumn = 28, EndLine = 2, EndColumn = 0}; result = source.GetText(sp); // assert Assert.True (result == ""); }
private static void TransformSequences_RemoveFalsePositiveUnvisited (Method method, CodeCoverageStringTextSource source, ICollection<Tuple<Method, SequencePoint>> toRemoveMethodSequencePoint) { // Select false unvisited right-curly-braces at generated "MoveNext" method // (Curly braces moved to generated "MoveNext" method and left unvisited) // Source is required here to identify curly braces if (method.CallName == "MoveNext" && source.FileFound && source.FileType == FileType.CSharp) { int countDown = 2; // remove up to two last right-curly-braces foreach (var sp in method.SequencePoints.Reverse()) { if (sp.FileId == method.FileRefUniqueId && sp.IsSingleCharSequencePoint && sp.VisitCount == 0) { // unvisited only if (countDown > 0) { if (source.GetText(sp) == "}") { toRemoveMethodSequencePoint.Add (new Tuple<Method, SequencePoint>(method, sp)); countDown -= 1; } } else { break; } } } } }
private static bool TransformSequences_RemoveCompilerGeneratedBranches (Method method, CodeCoverageStringTextSource source, long startOffset, long finalOffset) { // foreach sequence point foreach (var sp in method.SequencePoints .Where (sp => sp.FileId == method.FileRefUniqueId && sp.BranchPoints.Count != 0)) { if (sp.Offset <= startOffset || sp.Offset >= finalOffset) { // doRemoveBranches where .Offset <= startOffset"{" or finalOffset"}" <= .Offset // this will exclude "{" and "}" compiler generated branches and majority of ccrewrite Code-Contract's sp.BranchPoints = new List<BranchPoint>(); } else { // branches not removed // check for other options by reading SequencePoint source var text = source.GetText(sp); // text is never null if (text.Length == 0) { ("Empty sequence-point at line: " + sp.StartLine + " column: " + sp.StartColumn).InformUser(); ("Source file: " + source.FilePath).InformUser(); return false; // signal error to caller's caller loop (break) } // Contract.Requires/Ensures is occasionally left inside method offset // Quick check for "C" before using Regex // Use Regex here! "Contract" and "." and "Requires/Ensures" // can be separated by spaces and newlines if (text[0] == 'C' && contractRegex.IsMatch(text)) { sp.BranchPoints = new List<BranchPoint>(); } // "in" keyword? if (text == "in") { // Remove generated ::MoveNext branches within "in" keyword // Not always removed in CecilSymbolManager (enumerated KeyValuePair) sp.BranchPoints = new List<BranchPoint>(); } } } return true; }
private static void TransformSequences_RemoveCompilerGeneratedBranches(Method method, CodeCoverageStringTextSource source, ref long startOffset, ref long finalOffset) { // order SequencePoints by source order (Line/Column) var sourceLineOrderedSps = method.SequencePoints.OrderBy(sp => sp.StartLine).ThenBy(sp => sp.StartColumn).Where(sp => sp.FileId == method.FileRefUniqueId).ToArray(); // get "{" if on first two positions for (int index = 0; index < Math.Min (2, sourceLineOrderedSps.Length); index++) { if (source.GetText(sourceLineOrderedSps[0]) == "{") { startOffset = sourceLineOrderedSps[0].Offset; break; } } // get "}" if on last position if (source.GetText(sourceLineOrderedSps.Last()) == "}") { finalOffset = sourceLineOrderedSps.Last().Offset; } }
private static bool TransformSequences_RemoveCompilerGeneratedBranches (Method method, CodeCoverageStringTextSource source) { // Do we have C# source? if (source.FileType == FileType.CSharp) { if (source.FileFound) { // initialize offset with unreachable values long startOffset = long.MinValue; long finalOffset = long.MaxValue; if (!method.IsGenerated) { // fill offsets with values TransformSequences_RemoveCompilerGeneratedBranches(method, source, ref startOffset, ref finalOffset); } if (!TransformSequences_RemoveCompilerGeneratedBranches (method, source, startOffset, finalOffset)) { return false; // return error/failure to caller } } else { // Do as much possible without source // This will remove generated branches within "{", "}" and "in" (single-line SequencePoints) // but cannot remove Code Contract ccrewite generated branches foreach (var sp in method.SequencePoints) { if (sp.BranchPoints.Count != 0 && sp.StartLine == sp.EndLine && sp.EndColumn - sp.StartColumn <= 2) { // Zero, one or two character sequence point should not contain branches // Never found 0 character sequencePoint // Never found 1 character sequencePoint except "{" and "}" // Never found 2 character sequencePoint except "in" keyword // Afaik, c# cannot express branch condition in one or two characters of source code // Keyword "do" does not generate SequencePoint sp.BranchPoints = new List<BranchPoint>(); } } } } return true; }
/// <summary> /// Get line-parsed source from file name /// </summary> /// <param name="filePath"></param> /// <returns></returns> public static CodeCoverageStringTextSource GetSource(string filePath) { var retSource = new CodeCoverageStringTextSource (null, filePath); // null indicates source-file not found try { using (Stream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) using (var reader = new StreamReader (stream, Encoding.Default, true)) { stream.Position = 0; retSource = new CodeCoverageStringTextSource(reader.ReadToEnd(), filePath); } } catch (Exception e) { // Source is optional (for excess-branch removal), application can continue without it e.InformUser(); // Do not throw ExitApplicationWithoutReportingException } return retSource; }
public void ConstructWithTwoLinesNoCrLfAtEof() { // arrange const string input = "\tfirst line\r\tsecond line"; var source = new CodeCoverageStringTextSource(input, ""); // assert Assert.True (source.LinesCount == 2); // act var result = source.GetLine(1); // existing line index // assert Assert.True (result == "\tfirst line\r"); // act result = source.GetLine(2); // existing line index // assert Assert.True (result == "\tsecond line"); // act result = source.GetLine(0); // invalid line index // assert Assert.True (result == string.Empty); // act on first line var sp = new SequencePoint { StartLine = 1, StartColumn = 8, EndLine = 1, EndColumn = 12}; result = source.GetText(sp); // assert Assert.True (result == "line"); // act on second line sp = new SequencePoint { StartLine = 2, StartColumn = 9, EndLine = 2, EndColumn = 13}; result = source.GetText(sp); // assert Assert.True (result == "line"); }
/// <summary> /// Get line-parsed source from file name /// </summary> /// <param name="filename"></param> /// <returns></returns> public static CodeCoverageStringTextSource GetSource(string filename) { var retSource = (CodeCoverageStringTextSource)null; try { using (Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read)) { try { stream.Position = 0; using (var reader = new StreamReader (stream, Encoding.Default, true)) { retSource = new CodeCoverageStringTextSource(reader.ReadToEnd()); switch (Path.GetExtension(filename).ToLowerInvariant()) { case ".cs": retSource.FileType = FileType.CSharp; break; case ".vb": retSource.FileType = FileType.VBasic; break; default: retSource.FileType = FileType.Unsupported; break; } } } catch (Exception) {} } } catch (Exception) {} return retSource; }