Почему kcov вычисляет неверную статистику покрытия кода для программ Rust?

Я пытался использовать kcov, чтобы получить покрытие кода для библиотеки Rust. Я следовал этому руководству, чтобы собрать и использовать kcov. Охват, кажется, работает, однако я сталкиваюсь со странно высоким освещением. Некоторые файлы в проекте получают 100% покрытие, даже если они вообще не покрыты!

Это минимальный проект, воспроизводящий проблему:

Cargo.toml

[package]
name = "mypackage"
version = "0.1.0"
authors = ["mbrt"]

SRC /lib.rs

pub mod subm;

pub fn coverage1(i : bool) -> bool {
    if i {
        true
    }
    else {
        false
    }
}

#[cfg(test)]
mod test {
    use super::coverage1;

    #[test]
    fn test_coverage1() {
        assert!(coverage1(true));
    }
}

SRC /subm.rs

pub fn coverage2(i : bool) -> bool {
    if i {
        true
    }
    else {
        false
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn test_coverage2() {
    }
}

Есть две идентичные функции, одна в корне ящика, а другая в подмодуле. Разница лишь в том, что первый тест стимулирует одну функцию, а другой вообще ничего не делает. В этом случае я ожидаю, что охват не превышает 50%.

тем не мение kcov сообщает об этом:

сводка покрытия

Покрытие для lib.rs верно:

coverage1

Но покрытие для subm.rs неправильно! Обратите внимание, что функция общедоступна, поэтому ее нельзя оптимизировать из библиотеки:

coverage2

Здесь мы можем убедиться, что kcov работает, потому что он может вычислить покрытие кода для одного файла, но не может видеть, что второй файл не покрыт вообще.

В чем здесь проблема? Может быть, тестовые двоичные файлы удаляют неиспользуемые функции и kcov не может их видеть?

2 ответа

Решение

Вы правы: на данный момент полностью неиспользуемые функции удаляются, поэтому инструменты покрытия, такие как kcov, хороши только для покрытия ветвлений внутри используемых функций (по крайней мере, суммарная функциональность таких инструментов). Существует некоторая дискуссия о том, чтобы этого не происходило по умолчанию для тестовых / отладочных сборок.

Существует обходной путь: RUSTFLAGS='-C link-dead-code' переменная окружения. Используйте его при сборке, и компилятор Rust также свяжет мертвый код:

RUSTFLAGS='-C link-dead-code' cargo test
Другие вопросы по тегам