lcov woes: странный дубликат конструктора, помеченный как не закрытый & amp; функция не помечена как покрытая, хотя ее строки были выполнены

В моем стремлении узнать больше об автоматизированном тестировании, запустив небольшой тестовый проект C ++ & Работая со 100% покрытием, я столкнулся со следующей проблемой — хотя все мои действительные строки кода и все ветви выполнения покрыты тестами, lcov по-прежнему сообщает о двух строках как непроверенных (они содержат только определения функций), а также как «дублирующий» метод конструктора, который предположительно не проверен, даже если он соответствует моему «реальному» конструктору (единственный когда-либо определенный) & б) отлично.

(Перейти к редактированию для минимального случая воспроизведения)

Если я генерирую ту же статистику покрытия (из того же точного источника, .gcno & .gcda файлы), используя скрипт Python gcovr и передать результаты плагину Jenkins Cobertura, он дает мне 100% по всем подсчетам — строки, условия & методы.

Вот что я имею в виду:

Страница покрытия Jenkins Cobertura: http://gints.dyndns.info/heap_std_gcovr_jenkins_cobertura.html (все на 100%).

Те же файлы .gcda, обработанные с помощью lcov: http://gints.dyndns.info/heap_std_lcov.html (две строки определения функции, помеченные как невыполненные, даже если строки в этих функциях полностью покрыты, а также функции Hit = functions Total — 1).

Статистика функций для этого исходного файла из lcov: http: // gints.dyndns.info/heap_std_lcov_func (показывает два идентичных определения конструктора, оба ссылаются на одну и ту же строку кода в файле, одно из которых помечено как 5 раз, другое — 0 раз).

Если я посмотрю на промежуточный файл lcov .info: http://gints.dyndns.info/lcov_coverage_filtered.info.txt Я вижу, что там также есть два определения конструкторов, оба должны быть в одной строке: FN: 8, _ZN4BBOS8Heap_stdC1Ev & FN: 8, _ZN4BBOS8Heap_stdC2Ev.

О, и не возражайте против беспорядка вокруг .uic include / destructor, это просто грязный способ иметь дело с О какой ветке в деструкторе сообщает gcov? Я случайно попробовал, когда сделал эти снимки файлов.

У кого-нибудь есть предложение, как решить эту проблему? Есть ли какая-то «закулисная» магия, которую здесь делает компилятор C ++? (Возможно, это дополнительная копия конструктора для специальных целей, которую я должен вызывать из своих тестов?) Как насчет обычного определения функции — как можно проверить строку определения, даже если тело полностью протестировано? Это просто проблема с lcov? Любые предложения приветствуются — я хотел бы понять Зачем это происходит, и если на самом деле есть какие-то функциональные возможности, которые мои тесты не раскрывают, а Cobertura не жалуется … или, если нет, как мне заставить lcov это понять?

РЕДАКТИРОВАТЬ: добавление минимального сценария воспроизведения ниже

lcov_repro_one_bad.cpp:

#include <stdexcept>
class Parent {
public:
Parent() throw() { }
virtual void * Do_stuff(const unsigned m) throw(std::runtime_error) =0;
};

class Child : public Parent {
public:
Child() throw();
virtual void * Do_stuff(const unsigned m)
throw(std::runtime_error);
};

Child::Child()
throw()
: Parent()
{
}

void * Child::Do_stuff(const unsigned m)
throw(std::runtime_error)
{
const int a = m;
if ( a > 10 ) {
throw std::runtime_error("oops!");
}
return NULL;
}

int main()
{
Child c;
c.Do_stuff(5);
try {
c.Do_stuff(11);
}
catch ( const std::runtime_error & ) { }
return 0;
}

Makefile:

GPP_FLAGS:=-fprofile-arcs -ftest-coverage -pedantic -pedantic-errors -W -Wall -Wextra -Werror -g -O0

all:
g++ ${GPP_FLAGS} lcov_repro_one_bad.cpp -o lcov_repro_one_bad
./lcov_repro_one_bad
lcov --capture --directory ${PWD} --output-file lcov_coverage_all.info --base-directory ${PWD}
lcov --output-file lcov_coverage_filtered.info --extract lcov_coverage_all.info ${PWD}/*.*
genhtml --output-directory lcov_coverage_html lcov_coverage_filtered.info --demangle-cpp --sort --legend --highlight

И вот освещение, которое я получаю от этого: http://gints.dyndns.info/lcov_repro_bin/lcov_coverage_html/gints/lcov_repro/lcov_repro_one_bad.cpp.gcov.html

Как вы можете видеть, предположительно строки без попаданий — это определения исключений, которые могут генерировать функции, а дополнительный конструктор без попаданий для Child все еще присутствует в списке функций (нажмите на функции вверху).

Я попытался удалить объявления throw из определений функций, и это заботится о неисполненных строках в объявлениях функций: http://gints.dyndns.info/lcov_repro_bin/lcov_coverage_html/gints/lcov_repro/lcov_repro_one_v1.cpp.gcov.html (дополнительный конструктор все еще там, как вы можете видеть).

Я попытался переместить определения функций в тело класса, а не определять их позже, и это избавляет от дополнительного конструктора: http://gints.dyndns.info/lcov_repro_bin/lcov_coverage_html/gints/lcov_repro/lcov_repro_one_v2.cpp.gcov.html (хотя, как вы можете видеть, все еще есть некоторая странность в определении функции Do_stuff).

И тогда, конечно, если я сделаю оба вышеперечисленных, все хорошо http://gints.dyndns.info/lcov_repro_bin/lcov_coverage_html/gints/lcov_repro/lcov_repro_one_ok.cpp.gcov.html

Но я все еще не знаю, что является основной причиной этого … и я все еще хочу, чтобы мои методы (включая конструктор) были определены в отдельном файле .cpp, а не в теле класса, и я хочу, чтобы мой функции должны иметь четко определенные исключения, которые они могут генерировать!

Вот источник, если вы хотите поиграть с этим: http://gints.dyndns.info/lcov_repro_src.zip

Есть идеи?

Спасибо!

5

Решение

Хорошо, после некоторой охоты вокруг & читая объявления об исключениях в C ++, я понимаю, что происходит:

  • Что касается объявлений броска без попадания, то здесь, похоже, все действительно правильно: объявления броска функции должны добавлять дополнительный код в выходной объектный файл, который проверяет наличие недопустимых (с точки зрения объявления броска) исключений. , Поскольку я не тестировал случай, когда это происходило, имеет смысл, что этот код никогда не выполнялся, и эти операторы были помечены как непопадавшие. Хотя в любом случае ситуация здесь далека от идеальной, по крайней мере, можно увидеть, откуда это происходит.

  • Что касается дублирующих конструкторов, то это похоже на известную вещь с gcc с давним обсуждением (и различными попытками исправлений для устранения получающегося дублирования объектного кода): http://gcc.gnu.org/bugzilla/show_bug.cgi?id=3187 — в основном, есть две версии созданного конструктора — одна для использования с этим классом, а другая для использования с дочерними классами, и вам нужно использовать обе, если вы хотите 100% охват.

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]