From 84a5ee3ba3659f98258f47cf9408421acaf1059f Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Thu, 13 Mar 2014 14:11:24 -0500 Subject: [PATCH] Add collected path and branch information to xdebug_get_code_coverage() output. --- php_xdebug.h | 1 + xdebug_branch_info.c | 27 ++++++++++++++++- xdebug_branch_info.h | 2 +- xdebug_code_coverage.c | 68 ++++++++++++++++++++++++++++++++++++++++-- xdebug_code_coverage.h | 6 ++-- 5 files changed, 97 insertions(+), 7 deletions(-) diff --git a/php_xdebug.h b/php_xdebug.h index f3fef9740..1d7d3b791 100644 --- a/php_xdebug.h +++ b/php_xdebug.h @@ -32,6 +32,7 @@ #include "xdebug_handlers.h" #include "xdebug_hash.h" #include "xdebug_llist.h" +#include "xdebug_branch_info.h" #include "xdebug_code_coverage.h" extern zend_module_entry xdebug_module_entry; diff --git a/xdebug_branch_info.c b/xdebug_branch_info.c index 4e4a1aaca..1c83392cd 100644 --- a/xdebug_branch_info.c +++ b/xdebug_branch_info.c @@ -11,7 +11,7 @@ */ #include #include -#include "xdebug_branch_info.h" +#include "php_xdebug.h" ZEND_EXTERN_MODULE_GLOBALS(xdebug) @@ -207,3 +207,28 @@ void xdebug_branch_info_dump(zend_op_array *opa, xdebug_branch_info *branch_info printf("\n"); } } + +void xdebug_branch_info_add_branches_and_paths(char *filename, xdebug_branch_info *branch_info TSRMLS_DC) +{ + xdebug_coverage_file *file; + + if (strcmp(XG(previous_filename), filename) == 0) { + file = XG(previous_file); + } else { + /* Check if the file already exists in the hash */ + if (!xdebug_hash_find(XG(code_coverage), filename, strlen(filename), (void *) &file)) { + /* The file does not exist, so we add it to the hash, and + * add a line element to the file */ + file = xdmalloc(sizeof(xdebug_coverage_file)); + file->name = xdstrdup(filename); + file->lines = xdebug_hash_alloc(128, xdebug_coverage_line_dtor); + file->branch_info = NULL; + + xdebug_hash_add(XG(code_coverage), filename, strlen(filename), file); + } + XG(previous_filename) = file->name; + XG(previous_file) = file; + } + + file->branch_info = branch_info; +} diff --git a/xdebug_branch_info.h b/xdebug_branch_info.h index 717b701cb..99c706439 100644 --- a/xdebug_branch_info.h +++ b/xdebug_branch_info.h @@ -20,7 +20,6 @@ #define __HAVE_XDEBUG_BRANCH_INFO_H__ #include "xdebug_set.h" -#include "php_xdebug.h" typedef struct _xdebug_branch { unsigned int start_lineno; @@ -53,6 +52,7 @@ void xdebug_branch_post_process(xdebug_branch_info *branch_info); void xdebug_branch_find_paths(xdebug_branch_info *branch_info); void xdebug_branch_info_dump(zend_op_array *opa, xdebug_branch_info *branch_info TSRMLS_DC); +void xdebug_branch_info_add_branches_and_paths(char *filename, xdebug_branch_info *branch_info TSRMLS_DC); void xdebug_branch_info_free(xdebug_branch_info *branch_info); #endif diff --git a/xdebug_code_coverage.c b/xdebug_code_coverage.c index 0e7714afb..d67ac91ba 100644 --- a/xdebug_code_coverage.c +++ b/xdebug_code_coverage.c @@ -38,6 +38,9 @@ void xdebug_coverage_file_dtor(void *data) { xdebug_coverage_file *file = (xdebug_coverage_file *) data; + if (file->branch_info) { + xdebug_branch_info_free(file->branch_info); + } xdebug_hash_destroy(file->lines); xdfree(file->name); xdfree(file); @@ -324,6 +327,7 @@ void xdebug_count_line(char *filename, int lineno, int executable, int deadcode file = xdmalloc(sizeof(xdebug_coverage_file)); file->name = xdstrdup(filename); file->lines = xdebug_hash_alloc(128, xdebug_coverage_line_dtor); + file->branch_info = NULL; xdebug_hash_add(XG(code_coverage), filename, strlen(filename), file); } @@ -583,9 +587,7 @@ static void prefill_from_oparray(char *fn, zend_op_array *op_array TSRMLS_DC) if (branch_info) { xdebug_branch_post_process(branch_info); xdebug_branch_find_paths(branch_info); - xdebug_branch_info_dump(op_array, branch_info TSRMLS_CC); - - xdebug_branch_info_free(branch_info); + xdebug_branch_info_add_branches_and_paths(fn, branch_info TSRMLS_CC); } } @@ -705,6 +707,60 @@ static void add_line(void *ret, xdebug_hash_element *e) } } +static void add_branches(zval *retval, xdebug_branch_info *branch_info TSRMLS_DC) +{ + zval *branches, *branch, *out; + unsigned int i; + + MAKE_STD_ZVAL(branches); + array_init(branches); + + for (i = 0; i < branch_info->starts->size; i++) { + if (xdebug_set_in(branch_info->starts, i)) { + MAKE_STD_ZVAL(branch); + array_init(branch); + add_assoc_long(branch, "op_start", i); + add_assoc_long(branch, "op_end", branch_info->branches[i].end_op); + add_assoc_long(branch, "line_start", branch_info->branches[i].start_lineno); + add_assoc_long(branch, "line_end", branch_info->branches[i].end_lineno); + + MAKE_STD_ZVAL(out); + array_init(out); + if (branch_info->branches[i].out[0]) { + add_index_long(out, branch_info->branches[i].out[0], 0); + } + if (branch_info->branches[i].out[1]) { + add_index_long(out, branch_info->branches[i].out[1], 0); + } + add_assoc_zval(branch, "out", out); + add_index_zval(branches, i, branch); + } + } + + add_assoc_zval_ex(retval, "branches", 9, branches); +} + +static void add_paths(zval *retval, xdebug_branch_info *branch_info TSRMLS_DC) +{ + zval *paths, *path; + unsigned int i, j; + + MAKE_STD_ZVAL(paths); + array_init(paths); + + for (i = 0; i < branch_info->paths_count; i++) { + MAKE_STD_ZVAL(path); + array_init(path); + + for (j = 0; j < branch_info->paths[i]->elements_count; j++) { + add_next_index_long(path, branch_info->paths[i]->elements[j]); + } + add_next_index_zval(paths, path); + } + + add_assoc_zval_ex(retval, "paths", 6, paths); +} + static void add_file(void *ret, xdebug_hash_element *e) { xdebug_coverage_file *file = (xdebug_coverage_file*) e->ptr; @@ -723,6 +779,12 @@ static void add_file(void *ret, xdebug_hash_element *e) target_hash = HASH_OF(lines); zend_hash_sort(target_hash, zend_qsort, xdebug_lineno_cmp, 0 TSRMLS_CC); + /* Add the branch and path info */ + if (file->branch_info) { + add_branches(lines, file->branch_info); + add_paths(lines, file->branch_info); + } + add_assoc_zval_ex(retval, file->name, strlen(file->name) + 1, lines); } diff --git a/xdebug_code_coverage.h b/xdebug_code_coverage.h index d1bf92a61..be78f27bc 100644 --- a/xdebug_code_coverage.h +++ b/xdebug_code_coverage.h @@ -22,6 +22,7 @@ #include "php.h" #include "xdebug_hash.h" #include "xdebug_mm.h" +#include "xdebug_branch_info.h" typedef struct xdebug_coverage_line { int lineno; @@ -30,8 +31,9 @@ typedef struct xdebug_coverage_line { } xdebug_coverage_line; typedef struct xdebug_coverage_file { - char *name; - xdebug_hash *lines; + char *name; + xdebug_hash *lines; + xdebug_branch_info *branch_info; } xdebug_coverage_file; /* Needed for code coverage as Zend doesn't always add EXT_STMT when expected */