2017-02-11 43 views
7

Rozwijamy mutation testing system based on LLVM. System obsługuje projekty C++, które korzystają z GoogleTest i próbuję wspierać Rusta. Aby to zrobić, musimy wykonać następujące kroki:Jak znaleźć wskaźniki funkcji dla testów z kodu LLVM IR programu Rust?

  1. Skompiluj język na LLVM IR. Rust wspiera to.
  2. Znajdź testy w LLVM IR.
  3. Uruchom testy kodu, który jest wykonywany przez testy ("testerzy").

Wyzwanie polega na znalezieniu metod testowania jednostek za pomocą interfejsu API LLVM IR.

Rozważ the following example. Posiada 4 testy i jedną funkcję testee:

pub fn sum(a: i32, b: i32) -> i32 { 
    return a + b; 
} 

pub fn just_print() { 
    println!("I am just_print() function. I just say hello!"); 
} 

#[test] 
fn rusttest_foo_sum1() { 
    assert!(sum(3, 4) == 7); 
} 

#[test] 
fn rusttest_foo_sum2() { 
    assert!(sum(4, 5) == 9); 
} 

#[test] 
fn rusttest_foo_sum3() { 
    assert!(sum(5, 6) == 11); 
} 

#[test] 
fn rusttest_foo_sum4() { 
    assert!(sum(5, 6) == 11); 
} 

To jest the slightly prettified LLVM IR który jest produkowany przy kompilacji tego kodu rdzy.

Po zbadaniu tego LLVM IR przez pewien czas, można zauważyć, że testy uruchamiające Rust/Cargo za pomocą funkcji main wywołują funkcję test_main_static, której podano tablice opisów. Każdy opis jest parą nazwy funkcji testowej i wskaźnika funkcji testowej. See the @ref.e at line 47.

Naszym wyzwaniem jest zbieranie wskaźników funkcji do tych testów poprzez analizowanie tego wyrafinowanego układu strukturalnego, aby później można było uruchomić te funkcje za pomocą JIT LLVM, nadając mu wskaźniki funkcji, które zgromadziliśmy.

Oczywistym podejściem brute-force, które zamierzamy wykonać, jest przejście przez ten układ struktury i dokładne przeanalizowanie struktur i znalezienie prawidłowych przesunięć funkcji testowych. Takie podejście wydaje się nie być przenośne w różnych wersjach Rust lub LLVM IR, które mogą ulec zmianie w przyszłości.

Jaki jest najprostszy i jednocześnie niezawodny sposób na znalezienie wskaźników funkcji testu, innych niż domyślne parsowanie przesunięć ręcznie? To jest również cross-posted to the Rust forums.

+3

Nie jestem pewien, jak sobie z tym poradzisz, ale z pewnością życzę ci szczęścia. Testowanie mutacji w Rust byłoby niesamowite. –

Odpowiedz

1

I made it work za pomocą metody brute-force opisanej w moim pytaniu. Korzystanie z LLVM C++ API, mamy:

  • znaleźć wskaźnik do test_main_static
  • znaleźć odniesienie do @ref.e w test_main_static
  • wyliczyć poprzez @ref.e struktury i znaleźć wskaźników funkcji Test

Podejście wydaje się działać, ale naszym zmartwieniem jest to, że może nie być przenośny w różnych wersjach Rust/LLVM. Jednym z naszych kolejnych kroków będzie wdrożenie testów integralności LLVM IR wyprodukowanych przez rustc --test. Kolejnym krokiem będzie wypróbowanie tego RustTestFinder na rzeczywistych bazach kodów i zobaczymy, czy mamy jakieś problemy.

Nadal będę wdzięczny za wszelkie informacje na temat LLVM IR wyprodukowane przez rustc --test, które mogą sprawić, że sprawy będą bardziej proste.