1. Ned Batchelder
  2. coverage.py

Commits

Ned Batchelder  committed 50fbe53

Jumps to jumps could make loops look like they go places they really don't, so start new chunks for every absolute jump. Fixes issue #39.

  • Participants
  • Parent commits ac063eb
  • Branches default

Comments (0)

Files changed (4)

File CHANGES.txt

View file
 
 - Settings are now read from a .coveragerc file.
 
+- Fixed a problem with nested loops having their branch possibilities
+  mischaracterized: `issue 39`_.
+
 - Added an AUTHORS.txt file.
 
+.. _issue 39: http://bitbucket.org/ned/coveragepy/issue/39
+
 
 Version 3.2, 5 December 2009
 ----------------------------

File coverage/parser.py

View file
     'BREAK_LOOP', 'CONTINUE_LOOP',
     )
 
+# Opcodes that unconditionally begin a new code chunk.  By starting new chunks
+# with unconditional jump instructions, we neatly deal with jumps to jumps
+# properly.
+OPS_CHUNK_BEGIN = _opcode_set('JUMP_ABSOLUTE', 'JUMP_FORWARD')
+
 # Opcodes that push a block on the block stack.
 OPS_PUSH_BLOCK = _opcode_set('SETUP_LOOP', 'SETUP_EXCEPT', 'SETUP_FINALLY')
 
         ult = penult = None
 
         for bc in ByteCodes(self.code.co_code):
-            # Maybe have to start a new block
+            # Maybe have to start a new chunk
             if bc.offset in bytes_lines_map:
+                # Start a new chunk for each source line number.
                 if chunk:
                     chunk.exits.add(bc.offset)
                 chunk = Chunk(bc.offset, bytes_lines_map[bc.offset])
                 chunks.append(chunk)
+            elif bc.op in OPS_CHUNK_BEGIN:
+                # Jumps deserve their own unnumbered chunk.  This fixes
+                # problems with jumps to jumps getting confused.
+                if chunk:
+                    chunk.exits.add(bc.offset)
+                chunk = Chunk(bc.offset)
+                chunks.append(chunk)
 
             if not chunk:
                 chunk = Chunk(bc.offset)

File lab/cmd-opts.txt

View file
             --timid                 bool                [run].timid
 
 
-        --include=directory         [run].include
-        --include=filename
-        --include=module
-        --exclude=directory         [run].exclude
+        --include=directory *       [run].include
+        --include=filename *
+        --include=module *
+        --exclude=directory *       [run].exclude
 
 
 

File test/test_arcs.py

View file
             arcz_missing="27"   # while loop never exits naturally.
             )
 
+    def test_for_if_else_for(self):
+        self.check_coverage("""\
+            def branches_2(l):
+                if l:
+                    for e in l:
+                        a = 4
+                else:
+                    a = 6
+
+            def branches_3(l):
+                for x in l:
+                    if x:
+                        for e in l:
+                            a = 12
+                    else:
+                        a = 14
+            
+            branches_2([0,1])
+            branches_3([0,1])
+            """,
+            arcz=
+                ".1 18 8G GH H. "
+                ".2 23 34 43 26 3. 6. "
+                ".9 9A 9. AB BC CB B9 AE E9",
+            arcz_missing="26 6."
+            )
+
 
 class ExceptionArcTest(CoverageTest):
     """Arc-measuring tests involving exception handling."""