From 713e3ac5d0ff63313fa2b6b8df25e41b1045519a Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 13 Jan 2012 14:52:58 -0600 Subject: [PATCH] Add "# @no-test" tag to blacklist statements from test coverage analysis. It can apply to either single statements: print "don't cover"; # @no-test or a block of statements: if ( F ) { # @no-test ... } --- src/Brofiler.cc | 2 +- src/Brofiler.h | 14 ++- src/parse.y | 89 +++++++++++-------- src/scan.l | 2 + .../coverage.coverage-blacklist/output | 5 ++ testing/btest/coverage/coverage-blacklist.bro | 29 ++++++ 6 files changed, 99 insertions(+), 42 deletions(-) create mode 100644 testing/btest/Baseline/coverage.coverage-blacklist/output create mode 100644 testing/btest/coverage/coverage-blacklist.bro diff --git a/src/Brofiler.cc b/src/Brofiler.cc index 8db5861d20..75c054a681 100644 --- a/src/Brofiler.cc +++ b/src/Brofiler.cc @@ -5,7 +5,7 @@ #include "util.h" Brofiler::Brofiler() - : delim('\t') + : delim('\t'), ignoring(0) { } diff --git a/src/Brofiler.h b/src/Brofiler.h index 0a284c62c8..58c23f06b1 100644 --- a/src/Brofiler.h +++ b/src/Brofiler.h @@ -34,14 +34,24 @@ public: void SetDelim(char d) { delim = d; } + void IncIgnoreDepth() { ignoring++; } + void DecIgnoreDepth() { ignoring--; } + + void AddStmt(const Stmt* s) { if ( ignoring == 0 ) stmts.push_back(s); } + +private: /** * The current, global Brofiler instance creates this list at parse-time. */ list stmts; -private: /** - * + * Indicates whether new statments will not be considered as part of + * coverage statistics because it was marked with the @no-test tag. + */ + unsigned int ignoring; + + /** * This maps Stmt location-desc pairs to the total number of times that * Stmt has been executed. The map can be initialized from a file at * startup time and modified at shutdown time before writing back diff --git a/src/parse.y b/src/parse.y index fb731d9555..35eae155b5 100644 --- a/src/parse.y +++ b/src/parse.y @@ -29,6 +29,8 @@ %token TOK_DOC TOK_POST_DOC +%token TOK_NO_TEST + %left ',' '|' %right '=' TOK_ADD_TO TOK_REMOVE_FROM %right '?' ':' TOK_USING @@ -42,6 +44,7 @@ %right '!' %left '$' '[' ']' '(' ')' TOK_HAS_FIELD TOK_HAS_ATTR +%type opt_no_test opt_no_test_block %type TOK_ID TOK_PATTERN_TEXT single_pattern TOK_DOC TOK_POST_DOC %type opt_doc_list opt_post_doc_list %type local_id global_id def_global_id event_id global_or_event_id resolve_id begin_func @@ -196,6 +199,7 @@ static std::list* concat_opt_docs (std::list* pre, %} %union { + bool b; char* str; std::list* str_l; ID* id; @@ -1315,121 +1319,117 @@ attr: ; stmt: - '{' stmt_list '}' + '{' opt_no_test_block stmt_list '}' { - set_location(@1, @3); - $$ = $2; + set_location(@1, @4); + $$ = $3; + if ( $2 ) brofiler.DecIgnoreDepth(); } - | TOK_PRINT expr_list ';' + | TOK_PRINT expr_list ';' opt_no_test { set_location(@1, @3); $$ = new PrintStmt($2); - brofiler.stmts.push_back($$); + if ( ! $4 ) brofiler.AddStmt($$); } - | TOK_EVENT event ';' + | TOK_EVENT event ';' opt_no_test { set_location(@1, @3); $$ = new EventStmt($2); - brofiler.stmts.push_back($$); + if ( ! $4 ) brofiler.AddStmt($$); } | TOK_IF '(' expr ')' stmt { set_location(@1, @4); $$ = new IfStmt($3, $5, new NullStmt()); - //brofiler.stmts.push_back($$); } | TOK_IF '(' expr ')' stmt TOK_ELSE stmt { set_location(@1, @4); $$ = new IfStmt($3, $5, $7); - //brofiler.stmts.push_back($$); } | TOK_SWITCH expr '{' case_list '}' { set_location(@1, @2); $$ = new SwitchStmt($2, $4); - //brofiler.stmts.push_back($$); } | for_head stmt { $1->AsForStmt()->AddBody($2); - //brofiler.stmts.push_back($1); } - | TOK_NEXT ';' + | TOK_NEXT ';' opt_no_test { set_location(@1, @2); $$ = new NextStmt; - brofiler.stmts.push_back($$); + if ( ! $3 ) brofiler.AddStmt($$); } - | TOK_BREAK ';' + | TOK_BREAK ';' opt_no_test { set_location(@1, @2); $$ = new BreakStmt; - brofiler.stmts.push_back($$); + if ( ! $3 ) brofiler.AddStmt($$); } - | TOK_RETURN ';' + | TOK_RETURN ';' opt_no_test { set_location(@1, @2); $$ = new ReturnStmt(0); - brofiler.stmts.push_back($$); + if ( ! $3 ) brofiler.AddStmt($$); } - | TOK_RETURN expr ';' + | TOK_RETURN expr ';' opt_no_test { set_location(@1, @2); $$ = new ReturnStmt($2); - brofiler.stmts.push_back($$); + if ( ! $4 ) brofiler.AddStmt($$); } - | TOK_ADD expr ';' + | TOK_ADD expr ';' opt_no_test { set_location(@1, @3); $$ = new AddStmt($2); - brofiler.stmts.push_back($$); + if ( ! $4 ) brofiler.AddStmt($$); } - | TOK_DELETE expr ';' + | TOK_DELETE expr ';' opt_no_test { set_location(@1, @3); $$ = new DelStmt($2); - brofiler.stmts.push_back($$); + if ( ! $4 ) brofiler.AddStmt($$); } - | TOK_LOCAL local_id opt_type init_class opt_init opt_attr ';' + | TOK_LOCAL local_id opt_type init_class opt_init opt_attr ';' opt_no_test { set_location(@1, @7); $$ = add_local($2, $3, $4, $5, $6, VAR_REGULAR); - brofiler.stmts.push_back($$); + if ( ! $8 ) brofiler.AddStmt($$); } - | TOK_CONST local_id opt_type init_class opt_init opt_attr ';' + | TOK_CONST local_id opt_type init_class opt_init opt_attr ';' opt_no_test { set_location(@1, @6); $$ = add_local($2, $3, $4, $5, $6, VAR_CONST); - brofiler.stmts.push_back($$); + if ( ! $8 ) brofiler.AddStmt($$); } | TOK_WHEN '(' expr ')' stmt { set_location(@3, @5); $$ = new WhenStmt($3, $5, 0, 0, false); - brofiler.stmts.push_back($$); } - | TOK_WHEN '(' expr ')' stmt TOK_TIMEOUT expr '{' stmt_list '}' + | TOK_WHEN '(' expr ')' stmt TOK_TIMEOUT expr '{' opt_no_test_block stmt_list '}' { - set_location(@3, @8); - $$ = new WhenStmt($3, $5, $9, $7, false); - brofiler.stmts.push_back($$); + set_location(@3, @9); + $$ = new WhenStmt($3, $5, $10, $7, false); + if ( $9 ) brofiler.DecIgnoreDepth(); } @@ -1437,21 +1437,20 @@ stmt: { set_location(@4, @6); $$ = new WhenStmt($4, $6, 0, 0, true); - brofiler.stmts.push_back($$); } - | TOK_RETURN TOK_WHEN '(' expr ')' stmt TOK_TIMEOUT expr '{' stmt_list '}' + | TOK_RETURN TOK_WHEN '(' expr ')' stmt TOK_TIMEOUT expr '{' opt_no_test_block stmt_list '}' { - set_location(@4, @9); - $$ = new WhenStmt($4, $6, $10, $8, true); - brofiler.stmts.push_back($$); + set_location(@4, @10); + $$ = new WhenStmt($4, $6, $11, $8, true); + if ( $10 ) brofiler.DecIgnoreDepth(); } - | expr ';' + | expr ';' opt_no_test { set_location(@1, @2); $$ = new ExprStmt($1); - brofiler.stmts.push_back($$); + if ( ! $3 ) brofiler.AddStmt($$); } | ';' @@ -1649,6 +1648,18 @@ opt_doc_list: { $$ = 0; } ; +opt_no_test: + TOK_NO_TEST + { $$ = true; } + | + { $$ = false; } + +opt_no_test_block: + TOK_NO_TEST + { $$ = true; brofiler.IncIgnoreDepth(); } + | + { $$ = false; } + %% int yyerror(const char msg[]) diff --git a/src/scan.l b/src/scan.l index 623e0d2ed6..4914783c44 100644 --- a/src/scan.l +++ b/src/scan.l @@ -216,6 +216,8 @@ ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+)) } } +#{OWS}@no-test.* return TOK_NO_TEST; + #.* /* eat comments */ {WS} /* eat whitespace */ diff --git a/testing/btest/Baseline/coverage.coverage-blacklist/output b/testing/btest/Baseline/coverage.coverage-blacklist/output new file mode 100644 index 0000000000..6d3d243220 --- /dev/null +++ b/testing/btest/Baseline/coverage.coverage-blacklist/output @@ -0,0 +1,5 @@ +1 /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/coverage.coverage-blacklist/coverage-blacklist.bro, line 13 print cover me; +1 /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/coverage.coverage-blacklist/coverage-blacklist.bro, line 17 print always executed; +0 /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/coverage.coverage-blacklist/coverage-blacklist.bro, line 26 print also impossible, but included in code coverage analysis; +1 /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/coverage.coverage-blacklist/coverage-blacklist.bro, line 29 print success; +1 /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/coverage.coverage-blacklist/coverage-blacklist.bro, line 5 print first; diff --git a/testing/btest/coverage/coverage-blacklist.bro b/testing/btest/coverage/coverage-blacklist.bro new file mode 100644 index 0000000000..04983a921f --- /dev/null +++ b/testing/btest/coverage/coverage-blacklist.bro @@ -0,0 +1,29 @@ +# @TEST-EXEC: BROFILER_FILE=coverage bro -b %INPUT +# @TEST-EXEC: grep %INPUT coverage | sort -k2 >output +# @TEST-EXEC: btest-diff output + +print "first"; + +if ( F ) + { # @no-test + print "hello"; + print "world"; + } + +print "cover me"; + +if ( T ) + { + print "always executed"; + } + +print "don't cover me"; # @no-test + +if ( 0 + 0 == 1 ) print "impossible"; # @no-test + +if ( 1 == 0 ) + { + print "also impossible, but included in code coverage analysis"; + } + +print "success";