2015-09-11 19 views
11

我試圖使用kcov來獲取Rust庫的代碼覆蓋率。我遵循this tutorial來構建和使用kcov。覆蓋似乎工作,但我面臨一個奇怪的高覆蓋率。項目中的某些文件可以獲得100%的覆蓋率,即使它們實際上沒有被覆蓋!爲什麼kcov會爲Rust程序計算不正確的代碼覆蓋率統計信息?

這是一個很小的項目重現問題:

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報告如下:

coverage summary

lib.rs覆蓋率是正確的:

coverage1

subm.rs覆蓋率是錯誤的!請注意該函數是公共的,所以它不能從庫優化掉了:

coverage2

在這裏,我們可以驗證kcov工作,因爲它能夠計算代碼覆蓋率爲一個文件,但它是無法看到第二個文件沒有被覆蓋。

這裏有什麼問題?也許測試二進制文件剝離未使用的函數,kcov看不到它們?

+2

*該函數是公共的,所以它不能從庫中優化* - 它絕對可以。所有東西都是靜態編譯的,所以編譯器知道在創建二進制文件時使用了哪些函數(以及如何!)。由於單態化,這是一個巨大的好處。 – Shepmaster

+0

@Shepmaster好點,我沒有想過。 – mbrt

回答

5

你是對的:目前完全沒有使用的函數被剝離,所以像kcov這樣的覆蓋工具只適用於被使用函數中的分支覆蓋(至少是這些工具的總結功能)。有some discussion關於在測試/調試版本中默認不會發生這種情況。

+0

我想至少應該在「覆蓋」開關打開時保留這些功能。 –

+0

@MatthieuM。據我所知,問題在於情況並非如此。 – mbrt

+1

@brt:的確,這相當有趣。 –

10

有一種解決方法:RUSTFLAGS='-C link-dead-code'環境變量。建設時使用它,Rust編譯器也會鏈接死碼:

RUSTFLAGS='-C link-dead-code' cargo test