Example #1
0
        private static void TransformSequences_AddSources(IEnumerable <File> files, IEnumerable <Method> methods, IDictionary <uint, CodeCoverageStringTextSource> sourceRepository)
        {
            if (files == null || !files.Any())
            {
                return;
            }

            // Dictionary with stored source file names per module
            var filesDictionary = new Dictionary <string, uint>();

            foreach (var file in files.
                     Where(file => !String.IsNullOrWhiteSpace(file.FullPath) &&
                           !filesDictionary.ContainsKey(file.FullPath)))
            {
                var source = CodeCoverageStringTextSource.GetSource(file.FullPath); // never reurns null
                if (source.FileType == FileType.CSharp)
                {
                    sourceRepository.Add(file.UniqueId, source);
                }
                filesDictionary.Add(file.FullPath, file.UniqueId);
            }

            foreach (var method in methods)
            {
                if (method.SequencePoints.Length != 0)
                {
                    MapFileReferences(method.SequencePoints, filesDictionary);
                }
                if (method.BranchPoints.Length != 0)
                {
                    MapFileReferences(method.BranchPoints, filesDictionary);
                }
            }
        }
        public void WhenLoggerNotProvided_ExceptionThrown()
        {
            // arrange
            ILog logger = null;

            // act/assert
            Assert.Throws <ArgumentNullException>(() => CodeCoverageStringTextSource.GetSource("", logger));
        }
Example #3
0
        public void CreateGetKeysValuesCopyEnumerate()
        {
            var sRepo = new SourceRepository();

            Assert.True(sRepo.IsReadOnly == false);
            Assert.True(sRepo.Count == 0);

            var        mockLog = new Mock <ILog>();
            var        source1 = new CodeCoverageStringTextSource("abc", "", mockLog.Object);
            const uint fileId1 = 1;

            sRepo.Add(fileId1, source1);
            Assert.True(sRepo.Count == 1);
            Assert.True(sRepo.Keys.Count == 1);
            Assert.True(sRepo.Values.Count == 1);

            var        source2 = new CodeCoverageStringTextSource("def", "", mockLog.Object);
            const uint fileId2 = 2;

            sRepo.Add(fileId2, source2);
            Assert.True(sRepo.Count == 2);

            var array = new KeyValuePair <uint, CodeCoverageStringTextSource> [2];

            Assert.That(delegate { sRepo.CopyTo(array, 0); }, Throws.Nothing);

            // IDictionary is not ordered
            Assert.True(array[0].Key == fileId1 || array[1].Key == fileId2);
            Assert.True(array[0].Value == source1 || array[1].Value == source2);

            Assert.True(array[1].Key != default(uint));
            Assert.True(array[1].Value != default(CodeCoverageStringTextSource));

            // covers generic enumerator
            int count = 0;

            foreach (var item in sRepo)
            {
                Assert.True(item.Key != default(uint));
                Assert.True(item.Value != default(CodeCoverageStringTextSource));
                count += 1;
            }
            Assert.True(count == 2);

            // covers GetEnumerator
            count = 0;
            var e = ((IEnumerable)sRepo).GetEnumerator();

            while (e.MoveNext())
            {
                count += 1;
            }
            Assert.True(count == 2);
        }
Example #4
0
        public void CreateGetSourceAndSequencePoints()
        {
            const uint   fileId1      = 1;
            const string sourceString = "abc { def }";

            var mockLog = new Mock <ILog>();
            var source  = new CodeCoverageStringTextSource(sourceString, "", mockLog.Object);

            var sRepo = new SourceRepository();

            sRepo[fileId1] = source;

            var spLeft = new SequencePoint()
            {
                FileId      = 1,
                StartLine   = 1,
                EndLine     = 1,
                StartColumn = 5,
                EndColumn   = 6
            };

            var spRight = new SequencePoint()
            {
                FileId      = 1,
                StartLine   = 1,
                EndLine     = 1,
                StartColumn = 11,
                EndColumn   = 12
            };

            var spInvalid = new SequencePoint()
            {
                FileId      = 2,
                StartLine   = 1,
                EndLine     = 1,
                StartColumn = 11,
                EndColumn   = 12
            };

            Assert.True(sRepo.GetCodeCoverageStringTextSource(0) == null);
            Assert.True(sRepo.GetCodeCoverageStringTextSource(1) == source);
            Assert.True(sRepo.GetCodeCoverageStringTextSource(2) == null);
            Assert.True(sRepo.GetCodeCoverageStringTextSource(1).GetLine(1) == sourceString);
            Assert.True(sRepo.GetCodeCoverageStringTextSource(1).GetText(spLeft) == "{");
            Assert.True(sRepo.GetCodeCoverageStringTextSource(1).GetText(spRight) == "}");

            Assert.True(sRepo.GetSequencePointText(null) == "");
            Assert.True(sRepo.GetSequencePointText(spInvalid) == "");

            Assert.True(sRepo.GetSequencePointText(spLeft) == "{");
            Assert.True(sRepo.GetSequencePointText(spRight) == "}");
        }
Example #5
0
        public void CreateAddClear()
        {
            var sRepo = new SourceRepository();

            Assert.True(sRepo.Count == 0);

            var        source = new CodeCoverageStringTextSource("", "");
            const uint fileId = 1;

            sRepo.Add(fileId, source);
            Assert.True(sRepo.Count == 1);

            sRepo.Clear();
            Assert.True(sRepo.Count == 0);
        }
        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");
        }
Example #7
0
        public void CreateAddRemoveKeyAndValue()
        {
            var        sRepo  = new SourceRepository();
            var        source = new CodeCoverageStringTextSource("", "");
            const uint fileId = 1;

            sRepo.Add(fileId, source);
            Assert.True(sRepo.Count == 1);

            Assert.True(sRepo.ContainsKey(fileId));
            Assert.True(sRepo.Remove(fileId));
            Assert.True(sRepo.Count == 0);
            Assert.False(sRepo.Remove(fileId));
            Assert.True(sRepo.Count == 0);
        }
        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 CountLinesWithLineFeed()
        {
            // arrange
            const string input   = "\n\n\n\n\n\n\n";
            var          mockLog = new Mock <ILog>();
            var          source  = new CodeCoverageStringTextSource(input, "", mockLog.Object);

            // assert
            Assert.True(source.LinesCount == 7);

            // act
            var result = source.GetLine(1); // existing line index

            // assert
            Assert.True(result == "\n");
        }
        public void ConstructWithTwoLinesNoCrLfAtEof()
        {
            // arrange
            const string input   = "\tfirst line\r\tsecond line";
            var          mockLog = new Mock <ILog>();
            var          source  = new CodeCoverageStringTextSource(input, "", mockLog.Object);

            // 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");
        }
Example #11
0
        public void CreateAddRemoveKeyValuePair()
        {
            var sRepo = new SourceRepository();

            Assert.True(sRepo.Count == 0);

            var        source = new CodeCoverageStringTextSource("", "");
            const uint fileId = 1;

            sRepo.Add(new KeyValuePair <uint, CodeCoverageStringTextSource>(fileId, source));
            Assert.True(sRepo.Contains(new KeyValuePair <uint, CodeCoverageStringTextSource>(fileId, source)));
            Assert.True(sRepo.Remove(new KeyValuePair <uint, CodeCoverageStringTextSource>(fileId, source)));
            Assert.False(sRepo.Remove(new KeyValuePair <uint, CodeCoverageStringTextSource>(fileId, source)));

            sRepo.Clear();
            Assert.True(sRepo.Count == 0);
        }
Example #12
0
        public void CreateAddIndexerTryGetValue()
        {
            var sRepo = new SourceRepository();

            Assert.True(sRepo.Count == 0);

            var        source = new CodeCoverageStringTextSource("", "");
            const uint fileId = 1;

            Assert.That(delegate { sRepo[fileId] = source; }, Throws.Nothing);
            Assert.True(sRepo.Count == 1);
            Assert.True(ReferenceEquals(sRepo[fileId], source));

            CodeCoverageStringTextSource getSource = null;

            sRepo.TryGetValue(fileId, out getSource);
            Assert.True(ReferenceEquals(getSource, source));
        }
        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);
        }
        public void ConstructWithEmptyString()
        {
            // arrangevar mockLog = new Mock<ILog>();
            var mockLog = new Mock <ILog>();
            var source  = new CodeCoverageStringTextSource(string.Empty, "", mockLog.Object);

            // 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);
        }
Example #15
0
        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;
            }
        }
Example #16
0
        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);
        }
        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 GetSource()
        {
            var    timeReference  = DateTime.UtcNow; System.Threading.Thread.Sleep(100);
            string fileName       = System.IO.Path.GetTempPath() + Guid.NewGuid();
            string cSharpFileName = fileName + ".cs";
            string vBasicFileName = fileName + ".vb";

            string[] lines = { "First line", "Second line", "Third line" };

            // act on not existing file
            var source = CodeCoverageStringTextSource.GetSource(cSharpFileName);

            // assert
            Assert.True(!ReferenceEquals(source, null));
            Assert.True(source.FileType == FileType.CSharp);
            Assert.True(source.FilePath == cSharpFileName);
            Assert.False(source.FileFound);
            Assert.True(source.FileTime == DateTime.MinValue);
            Assert.False(source.IsChanged(source.FileTime));
            Assert.False(source.IsChanged(DateTime.MinValue));
            Assert.False(source.IsChanged(DateTime.Now));
            Assert.False(source.IsChanged(timeReference));

            // arrange
            System.IO.File.WriteAllLines(cSharpFileName, lines);

            // act on existing file
            source = CodeCoverageStringTextSource.GetSource(cSharpFileName);

            // assert
            Assert.True(!ReferenceEquals(source, null));
            Assert.True(source.FileType == FileType.CSharp);
            Assert.True(source.FilePath == cSharpFileName);
            Assert.True(source.FileFound);
            Assert.True(source.FileTime == System.IO.File.GetLastWriteTimeUtc(cSharpFileName));
            Assert.False(source.IsChanged(source.FileTime));
            Assert.False(source.IsChanged(DateTime.MinValue));
            Assert.False(source.IsChanged(DateTime.Now));
            Assert.True(source.IsChanged(timeReference));

            // destroy temp file
            System.IO.File.Delete(cSharpFileName);

            // arrange
            System.IO.File.WriteAllLines(vBasicFileName, lines);
            // act on existing file
            source = CodeCoverageStringTextSource.GetSource(vBasicFileName);

            // assert
            Assert.True(!ReferenceEquals(source, null));
            Assert.True(source.FileType == FileType.Unsupported);
            Assert.True(source.FilePath == vBasicFileName);
            Assert.True(source.FileFound);
            Assert.True(source.FileTime == System.IO.File.GetLastWriteTimeUtc(vBasicFileName));
            Assert.False(source.IsChanged(source.FileTime));
            Assert.False(source.IsChanged(DateTime.MinValue));
            Assert.False(source.IsChanged(DateTime.Now));
            Assert.True(source.IsChanged(timeReference));

            // destroy temp file
            System.IO.File.Delete(vBasicFileName);
        }
        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");
        }
Example #20
0
 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);
 }
        public void GetSource()
        {
            var    timeReference  = DateTime.UtcNow; System.Threading.Thread.Sleep(100);
            string fileName       = System.IO.Path.GetTempPath() + Guid.NewGuid();
            string cSharpFileName = fileName + ".cs";
            string vBasicFileName = fileName + ".vb";

            string[] lines = { "First line", "Second line", "Third line" };

            var mockLog = new Mock <ILog>();

            mockLog.Setup(x => x.InfoFormat(It.IsAny <string>()));

            // act on not existing file
            var source = CodeCoverageStringTextSource.GetSource(cSharpFileName, mockLog.Object);

            mockLog.Verify(x => x.InfoFormat($"Source file does not exist: {cSharpFileName}"), Times.Once());

            // assert
            Assert.True(!ReferenceEquals(source, null));
            Assert.True(source.FileType == FileType.CSharp);
            Assert.True(source.FilePath == cSharpFileName);
            Assert.False(source.FileFound);
            Assert.True(source.FileTime == DateTime.MinValue);
            Assert.False(source.IsChanged(source.FileTime));
            Assert.False(source.IsChanged(DateTime.MinValue));
            Assert.False(source.IsChanged(DateTime.UtcNow));
            Assert.False(source.IsChanged(timeReference));

            // arrange
            System.IO.File.WriteAllLines(cSharpFileName, lines);

            // act on existing file
            source = CodeCoverageStringTextSource.GetSource(cSharpFileName, mockLog.Object);

            // assert
            Assert.True(!ReferenceEquals(source, null));
            Assert.True(source.FileType == FileType.CSharp);
            Assert.True(source.FilePath == cSharpFileName);
            Assert.True(source.FileFound);
            Assert.True(source.FileTime == System.IO.File.GetLastWriteTimeUtc(cSharpFileName));
            Assert.False(source.IsChanged(source.FileTime));
            Assert.False(source.IsChanged(DateTime.MinValue));
            Assert.False(source.IsChanged(DateTime.UtcNow));
            Assert.True(source.IsChanged(timeReference));

            // destroy temp file
            System.IO.File.Delete(cSharpFileName);

            // arrange
            System.IO.File.WriteAllLines(vBasicFileName, lines);
            // act on existing file
            source = CodeCoverageStringTextSource.GetSource(vBasicFileName, mockLog.Object);

            // assert
            Assert.True(!ReferenceEquals(source, null));
            Assert.True(source.FileType == FileType.Unsupported);
            Assert.True(source.FilePath == vBasicFileName);
            Assert.True(source.FileFound);
            Assert.True(source.FileTime == System.IO.File.GetLastWriteTimeUtc(vBasicFileName));
            Assert.False(source.IsChanged(source.FileTime));
            Assert.False(source.IsChanged(DateTime.MinValue));
            Assert.False(source.IsChanged(DateTime.UtcNow));
            Assert.True(source.IsChanged(timeReference));

            // destroy temp file
            System.IO.File.Delete(vBasicFileName);
        }
Example #22
0
        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;
                        }
                    }
                }
            }
        }
        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 == "");
        }