2015-09-11 14 views
11

Ho provato a utilizzare kcov per ottenere la copertura del codice per una libreria Rust. Ho seguito this tutorial per costruire e usare kcov. La copertura sembra funzionare, tuttavia sto affrontando una strana copertura elevata. Alcuni file nel progetto ricevono una copertura del 100%, anche se in realtà non sono coperti affatto!Perché kcov calcola statistiche di copertura del codice errate per i programmi Rust?

Questo è un progetto minimal che riproduce il problema:

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() { 
    } 
} 

Esistono due funzioni identiche, una nella radice della cassa e un'altra in un sottomodulo. L'unica differenza è che il primo test stimola una funzione e l'altra non fa assolutamente nulla. In questo caso mi aspetterei una copertura non superiore al 50%.

Tuttavia kcov rapporti questo:

coverage summary

La copertura per lib.rs è corretta:

coverage1

Ma la copertura per subm.rs e 'corretto Si noti che la funzione è pubblica, quindi non può essere ottimizzata fuori dalla libreria:

coverage2

Qui possiamo verificare che kcov sta lavorando, perché è in grado di calcolare la copertura del codice per un file, ma è non è in grado di vedere che il secondo file non è affatto coperto.

Qual è il problema qui? Forse i binari di test eliminano le funzioni inutilizzate e kcov non le vede?

+2

* la funzione è pubblica, quindi non può essere ottimizzata dalla libreria * - è assolutamente possibile. Tutto è compilato staticamente, quindi il compilatore sa quali funzioni vengono utilizzate (e come!) Quando crea il binario. Questo è un enorme vantaggio dovuto alla monomorfizzazione. – Shepmaster

+0

@Shepmaster Buon punto, non ci ho pensato. – mbrt

risposta

5

Hai ragione: le funzioni totalmente inutilizzate sono spogliate al momento, quindi gli strumenti di copertura come kcov sono utili solo per la copertura delle filiali all'interno delle funzioni utilizzate (almeno, la funzionalità di riepilogo di tali strumenti). C'è some discussion su come fare questo non accade di default per le build di test/debug.

+0

Suppongo che per lo meno le funzioni dovrebbero rimanere quando l'interruttore "copertura" è acceso. –

+0

@MatthieuM. Il problema è che questo non è il caso, per quanto posso vedere. – mbrt

+1

@brt: Infatti, che è abbastanza divertente. –

10

C'è una soluzione alternativa: la variabile di ambiente RUSTFLAGS='-C link-dead-code'. Usalo mentre costruisci e il compilatore di Rust collegherà anche il codice morto:

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