Skip to content

Commit

Permalink
Extend grammar coverage, adding branch coverage.
Browse files Browse the repository at this point in the history
whitequark committed May 8, 2015
1 parent 18a5e59 commit ccbcb3b
Showing 2 changed files with 48 additions and 10 deletions.
40 changes: 36 additions & 4 deletions pyparser/coverage/__init__.py
Original file line number Diff line number Diff line change
@@ -15,7 +15,10 @@ def instrument():
rewriter = source.Rewriter(_buf)
lex = lexer.Lexer(_buf, (3, 4))
in_grammar = False
stack = []
paren_stack = []
stmt_stack = [None]
all_stmt_list = []
in_square = 0
for token in lex:
if token.kind == 'from':
token = lex.next()
@@ -45,19 +48,37 @@ def instrument():
rewriter.insert_before(rparen.loc,
"loc=(%d,%d)" % (token.loc.begin_pos, token.loc.end_pos))
else:
stack.append(", loc=(%d,%d)" % (token.loc.begin_pos, token.loc.end_pos))
paren_stack.append(", loc=(%d,%d)" % (token.loc.begin_pos, token.loc.end_pos))

if token.kind == '(':
stack.append(None)
paren_stack.append(None)

if token.kind == ')':
data = stack.pop()
data = paren_stack.pop()
if data is not None:
rewriter.insert_before(token.loc, data)

if token.kind == '[':
in_square += 1
elif token.kind == ']':
in_square -= 1

if token.kind in ('def', 'if', 'elif', 'else', 'for') and in_square == 0:
all_stmt_list.append((token.loc.begin_pos, token.loc.end_pos))
stmt_stack.append("_all_stmts[(%d,%d)] = True\n" %
(token.loc.begin_pos, token.loc.end_pos))
elif token.kind == 'lambda':
stmt_stack.append(None)

if token.kind == 'indent':
data = stmt_stack.pop()
if data is not None:
rewriter.insert_after(token.loc, data + " " * token.loc.column())

with codecs.open(os.path.join(os.path.dirname(__file__), 'parser.py'), 'w',
encoding='utf-8') as f:
f.write(rewriter.rewrite().source)
f.write("\n_all_stmts = {%s}\n" % ', '.join(["(%d,%d): False" % x for x in all_stmt_list]))

# Produce an HTML report for test coverage of parser rules.
def report(parser, name='parser'):
@@ -84,6 +105,17 @@ def report(parser, name='parser'):
total_pts += pts
total_covered += covered

for stmt in parser._all_stmts:
loc = source.Range(_buf, *stmt)
if parser._all_stmts[stmt]:
rewriter.insert_before(loc, r"<span class='covered'>")
else:
rewriter.insert_before(loc, r"<span class='uncovered'>")
rewriter.insert_after(loc, r"</span>")

total_pts += 1
total_covered += (1 if parser._all_stmts[stmt] else 0)

print("GRAMMAR COVERAGE: %.2f%%" % (total_covered / total_pts * 100))

content = rewriter.rewrite().source
18 changes: 12 additions & 6 deletions pyparser/parser.py
Original file line number Diff line number Diff line change
@@ -436,14 +436,18 @@ def add_flags(self, flags):
SeqN(0, Rule('compound_stmt'), Newline()))))
def single_input(self, body):
"""single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE"""
loc = None if body == [] else body[0].loc
loc = None
if body != []:
loc = body[0].loc
return ast.Interactive(body=body, loc=loc)

@action(Expect(SeqN(0, Star(Alt(Newline(), Rule('stmt'))), Tok('eof'))))
def file_input(parser, body):
"""file_input: (NEWLINE | stmt)* ENDMARKER"""
body = reduce(list.__add__, body, [])
loc = None if body == [] else body[0].loc
loc = None
if body != []:
loc = body[0].loc
return ast.Module(body=body, loc=loc)

@action(Expect(SeqN(0, Rule('testlist'), Star(Tok('newline')), Tok('eof'))))
@@ -623,15 +627,17 @@ def expr_stmt(self, lhs, rhs):

@action(List(Rule('test'), ',', trailing=True))
def print_stmt_1(self, values):
loc = values.trailing_comma.loc if values.trailing_comma else values[-1].loc
nl = False if values.trailing_comma else True
nl, loc = True, values[-1].loc
if values.trailing_comma:
nl, loc = False, values.trailing_comma.loc
return ast.Print(dest=None, values=values, nl=nl,
dest_loc=None, loc=loc)

@action(Seq(Loc('>>'), Rule('test'), Tok(','), List(Rule('test'), ',', trailing=True)))
def print_stmt_2(self, dest_loc, dest, comma_tok, values):
loc = values.trailing_comma.loc if values.trailing_comma else values[-1].loc
nl = False if values.trailing_comma else True
nl, loc = True, values[-1].loc
if values.trailing_comma:
nl, loc = False, values.trailing_comma.loc
return ast.Print(dest=dest, values=values, nl=nl,
dest_loc=dest_loc, loc=loc)

0 comments on commit ccbcb3b

Please sign in to comment.