2014-12-03 17 views
12

Chcę zakryć mój kod testami jednostkowymi. To dobra rzecz. Ale mam problem - mam kod sieciowy. Kod ten rozwiązuje adresy IPv4 i IPv6 z nazw hostów, łączy się z interfejsami, nasłuchuje, łączy itd.Jaki jest najdokładniejszy sposób przetestowania kodu sieciowego w systemie Linux?

Zakładam, że istnieje pewna struktura testowa C/C++, którą można wdrożyć na prawie każdej stacji roboczej lub jakiejś technice programistycznej, która pozwala abym:

  • skonfigurować i zburzyć niestandardowych interfejsów sieciowych z IPv4 i IPv6 adresy
  • naśladować różne zachowanie zagłuszania, jak utrata pakietów, timeouting żywej, zasilania, itp
  • wiążą hostów do interfejsów i rozwiązywania im.

Głównym celem nie jest interakcja lub bałagan z rzeczywistymi interfejsami sieciowymi na komputerze.


Co możesz doradzić?

+3

(nie duplikat, ale może to być pomocne?) Http://stackoverflow.com/questions/2924440/advice-on-mocking-system-calls – IdeaHat

+0

Czy to ja, czy też zachowania, które próbujesz test poza zakresem testowania jednostkowego i testami integracyjnymi? Pewnie pedantyczny punkt, ale mogę zmienić zakres odpowiedzi. To są dwa bardzo różne tematy dla większości programistów. – ChrisCM

+0

@ChrisCM Moim zdaniem nie jest to test integracyjny, ponieważ nie chcę wykonywać rzeczywistych wdrożeń lub używać więcej niż jednego komputera. Ponadto nie chcę testować całego produktu, ale tylko niektóre elementy implementacyjne, takie jak pętla zdarzeń, usługa sieciowa, transmisja strumieniowa. I powinien to być pojedynczy plik binarny, który wykonuje całą pracę. Czy według ciebie wygląda testowanie integracyjne? –

Odpowiedz

0

Możesz testować dowolny kod, jeśli chcesz poświęcić czas i energię, aby to zrobić. Zasadniczo z testowaniem jednostkowym jesteś zainteresowany osiągnięciem docelowego procentu pokrycia kodu, aw niektórych branżach zasięgu MC/DC. W niektórych przypadkach będziesz musiał napisać sztuczny kod (moduły, które eksportują funkcje, które wyglądają jak OS API/gniazdo API, do twojej testowanej jednostki), co pomoże w wykonaniu każdego zakamarka w "badanej jednostce" (Plik .c/.cpp), zwracając wartości, które przekazujesz.

Być może trzeba będzie określić różne ścieżki uwzględniania testowanej jednostki od reszty aplikacji testowej, aby uniknąć konfliktów nazw, a także może być konieczne użycie makr preprocesora w nagłówkach testowych, aby pojawił się fałszywy interfejs API jak prawdziwa transakcja dla twojej "jednostki" i zachowaj ją tak, jak w kodzie produkcyjnym.

Można testować sterowniki sprzętu i dowolny rodzaj kodu niskiego poziomu.

Na przykład, jeśli twój kod zapisuje i odczytuje rejestry odwzorowane w pamięci, które według ciebie wymagają zmiany logiki opartej na FPGA, i nie masz sprzętu (lub trudno jest wygenerować warunek testowy bez rzeczywistego podróżowania na marsa), możesz pisać funkcje makr/wrapperów do odczytu i zapisu do rejestrów, które zwrócą twoje fałszywe wartości. W przeszłości używano CppUTest w przeszłości, co było łatwe do nauczenia. Przypuszczam, że wyszukiwanie google przyniesie wiele wyników.

+2

powinieneś skupić się na rozwiązywaniu faktycznego pytania ... to tylko ogólny opis tego, jak wykonać test - praktycznie każde testowanie –

4

W systemach ELF można użyć elf_hook do tymczasowej zamiany rzeczywistych wersji różnych funkcji na własne, wyśmiewane wersje.

Umożliwia przekierowywanie połączeń do dowolnej funkcji z poziomu biblioteki współużytkowanej do własnej, arbitralnej funkcji.

  • Tworzenie wspólnej biblioteki zawierającej kod badanego
  • W swojej próbie załadowania biblioteki współdzielonej dynamicznie (dlopen)
  • przekierować symbole chcesz szydzić do funkcji testowych (elf_hook)
  • teraz wszelkie wywołania do rzeczywistej funkcji w bibliotece (testowany kod) zostaną przekierowane do twojej wyśmiewanej funkcji:

Dodatkową zaletą tej metody jest to, że masz ca n nadal wywołuje oryginalną funkcję, gdy jest to wymagane.

  • Jeśli dla niektórych testów chcesz mieć połączenie, np. getaddrinfo, powodzenie, możesz zadzwonić do wersji systemu.
  • W innych testach możesz użyć własnej, wyśmiewanej wersji, np. mocked_getaddrinfo, i zwrócić, co chcesz.
  • Można utworzyć wiele mocked_getaddrinfo funkcje, jak chcesz, aby przetestować wiele scenariuszy

elf_hook ma następujący podpis:

void* elf_hook(char const* library_filename, 
       void const* library_address, 
       char const* function_name, 
       void const* substitution_address); 

będzie go używać tak:

#include <dlfcn.h> 
#include "elf_hook.h" 

void do_stuff(); // from the library under test (do_stuff calls getaddrinfo) 

// our mocked function which will alter the behaviour inside do_stuff() 
int mocked_getaddrinfo(const char* node, 
         const char* service, 
         const struct addrinfo* hints, 
         struct addrinfo** res) 
{ 
    // return a broken value to test a getaddrinfo failure 
    return 42; 
} 

// another version which actually calls the real function 
int real_getaddrinfo(const char* node, 
        const char* service, 
        const struct addrinfo* hints, 
        struct addrinfo** res) 
{ 
    // the real getaddrinfo is available to us here, we only replace it in the shared lib 
    return getaddrinfo(node, service, hints, res); 
} 

int main() 
{ 
    const char* lib_path = "path/to/library/under/test.so"; 

    // load the library under test 
    void* lib_handle = dlopen(lib_path, RTLD_LAZY); 

    // test 1: getraddrinfo is broken 
    //-------------------------------- 
    // replace getaddrinfo with our 'mocked_getaddrinfo' version 
    elf_hook(lib_path, LIBRARY_ADDRESS_BY_HANDLE(lib_handle), 
      "getaddrinfo", mocked_getaddrinfo); 

    // call a function in the library under test where getaddrinfo fails 
    do_stuff(); 

    // test 2: getraddrinfo is the system version 
    //-------------------------------- 
    // replace getaddrinfo with our 'real_getaddrinfo' version 
    elf_hook(lib_path, LIBRARY_ADDRESS_BY_HANDLE(lib_handle), 
      "getaddrinfo", real_getaddrinfo); 

    // call the same function in the library, now getaddrinfo works 
    do_stuff(); 

    dlclose(lib_handle); 
    return 0; 
} 

Wszelkie połączenia z getaddrinfo z testowanej biblioteki będą teraz wywoływać numer mocked_getaddrinfo.

Obszerny artykuł autorstwa autora elf_hook, Anthony'ego Shoumikhina, to here.

Powiązane problemy