Измерение покрытия библиотеки C, вызываемой в процессе Python - PullRequest
2 голосов

Позвольте мне начать с примера - вызова кода библиотеки из python.

Это код библиотеки (скомпилирован в библиотеку libfoolib):

#include <stdio.h>

void bar()
{
    printf("bar\n");
}

void foo()
{
    printf("foo\n");
}

И это код Python, вызывающий его:

#!/usr/bin/python25
import sys
import libfoolib
import processing

def callFoo():
    libfoolib.foo()

libfoolib.bar()

process = processing.Process(target=callFoo)
process.start()

Когда библиотекакомпилируется с -ftest-coverage и -fprofile-arcs, компилятор правильно генерирует файл gcno, и когда код Python выполняется, файл gcda также генерируется.Проблема в том, что он содержит только номера покрытия для функции bar, которая вызывается до разветвления питона.если foo также был вызван вне вызова обработки Python, то все хорошо.

Это то, что я получаю, когда запускаю инструмент gcov для полученных данных покрытия:

        -:    0:Source:/codeCoverageTests/pythonSIP/foo.c
        -:    0:Graph:debug/CMakeFiles/fooLib.dir/foo.c.gcno
        -:    0:Data:debug/CMakeFiles/fooLib.dir/foo.c.gcda
        -:    0:Runs:4
        -:    0:Programs:1
        -:    1:#include <stdio.h>
        -:    2:
        -:    3:void bar()
function bar called 4 returned 100% blocks executed 100%
        4:    4:{
        4:    5:    printf("bar\n");
call    0 returned 100%
        4:    6:}
        -:    7:
        -:    8:void foo()
function foo called 0 returned 0% blocks executed 0%
    #####:    9:{
    #####:   10:    printf("foo\n");
call    0 never executed
    #####:   11:}
        -:   12:

Вопрос, который у меня возникает: «Где мои foo данные покрытия?»

некоторые дополнительные сведения об окружающей среде:

  • CentOS 5.4
  • gcc: 4.1.2 20080704 (Red Hat 4.1.2-46)
  • Сборка CMake (версия 2.8.0)
  • python 2.5
  • Python для C использует SIP (версия 4.7.4)

1 Ответ

0 голосов

Проблема в том, что библиотека обработки python завершается с использованием os._exit. Это проблема, поскольку выход таким способом не вызывает обычные обработчики очистки процесса. Оказывается, что инструментарий собирает данные покрытия в буферах и записывает их только при выходе из процесса, и это происходит в обычных обработчиках очистки процесса. Из-за этих взаимодействий дочерний процесс никогда не имеет возможности записывать свои данные, а вызов foo никогда не записывается.

Чтобы это исправить, я звоню __gcov_flush вручную до конца моего процесса. А поскольку это статическая библиотека, для этой работы требуется небольшая заглушка C.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...