2014-12-03 19 views
12

Tôi muốn bao gồm mã của mình với các bài kiểm tra đơn vị. Đó là một điều tốt. Nhưng tôi có một vấn đề - tôi có một mã mạng. Mã này giải quyết các địa chỉ IPv4 và IPv6 từ các tên máy chủ, liên kết với các giao diện, nghe, kết nối, vvCách chính xác nhất để kiểm tra mã mạng trên Linux là gì?

Tôi giả sử rằng có một số khung kiểm tra C/C++ có thể được triển khai trên hầu hết mọi máy trạm hoặc một số kỹ thuật lập trình. tôi:

  • thiết lập và phá đổ các giao diện mạng tùy chỉnh với IPv4 và địa chỉ IPv6
  • bắt chước hành vi gây nhiễu khác nhau, như các gói tin bị mất, timeouting, kết nối rơi vv
  • bind hostname tới giao diện và giải quyết chúng.

Mục tiêu chính là không tương tác hoặc gây rối với giao diện mạng thực trên máy.


Bạn có thể tư vấn cho điều gì?

+3

(không phải là bản sao, nhưng điều này có thể hữu ích?) Http://stackoverflow.com/questions/2924440/advice-on-mocking-system-calls – IdeaHat

+0

Có phải tôi, hoặc là những hành vi bạn đang cố gắng kiểm tra bên ngoài phạm vi kiểm tra đơn vị và thử nghiệm tích hợp? Một điểm giả tưởng, tôi cho rằng, nhưng có thể thay đổi phạm vi câu trả lời. Đó là hai chủ đề rất khác nhau đối với hầu hết các nhà phát triển. – ChrisCM

+0

@ChrisCM Theo tôi, đây không phải là thử nghiệm tích hợp, vì tôi không muốn triển khai thực sự hoặc sử dụng nhiều máy. Ngoài ra, tôi không muốn kiểm tra toàn bộ sản phẩm, nhưng chỉ một số phần thực hiện như vòng lặp sự kiện, dịch vụ mạng, phát trực tuyến. Và nó phải là một nhị phân đơn, làm tất cả công việc. Liệu nó trông giống như thử nghiệm tích hợp theo ý kiến ​​của bạn? –

Trả lời

0

Bạn có thể kiểm tra bất kỳ mã nào nếu bạn sẵn sàng dành thời gian và năng lượng để thực hiện. Về cơ bản với thử nghiệm đơn vị bạn quan tâm đến việc đạt được tỷ lệ phần trăm mã vùng mục tiêu và trong một số ngành công nghiệp phủ sóng MC/DC. Trong một số trường hợp, bạn sẽ cần phải viết mã giả (các mô-đun xuất các chức năng giống như API OS/socket API, đến đơn vị của bạn đang được kiểm tra), sau đó sẽ giúp thực thi ổ đĩa thông qua mọi ngóc ngách trong "đơn vị đang thử nghiệm" (a .c/.cpp file) bằng cách trả về các giá trị bạn nói.

Bạn có thể cần phải chỉ định các đường dẫn bao gồm khác nhau cho phần còn lại của ứng dụng thử nghiệm để tránh xung đột tên và bạn cũng có thể phải sử dụng macro tiền xử lý trong tiêu đề thử nghiệm để làm cho API giả xuất hiện giống như thỏa thuận thực sự với "đơn vị" của bạn và giữ nó giống như trong mã sản xuất.

Bạn có thể kiểm tra trình điều khiển phần cứng và bất kỳ loại mã cấp thấp nào. Ví dụ, nếu mã của bạn đang viết và đọc bộ nhớ ánh xạ bộ nhớ mà bạn mong đợi nói logic dựa trên FPGA để thay đổi, và bạn không có phần cứng (hoặc nó là khó khăn cho bạn để tạo ra một điều kiện thử nghiệm mà không thực sự đi du lịch để mars), sau đó bạn có thể viết macro/wrapper chức năng để đọc và ghi vào sổ đăng ký mà sẽ trả lại giá trị giả lập của bạn lên. Trong quá khứ đã sử dụng CppUTest trong quá khứ mà rất dễ học. Tôi cho rằng một tìm kiếm google sẽ có nhiều kết quả.

+2

bạn nên tập trung vào giải quyết các câu hỏi thực tế ... đây chỉ là một mô tả chung của làm thế nào để làm thử nghiệm - khá nhiều bất kỳ thử nghiệm –

4

Trên hệ thống ELF, bạn có thể sử dụng elf_hook để tạm thời thay thế các phiên bản thực của các chức năng khác nhau bằng các phiên bản được chế bản của riêng bạn.

Nó cho phép bạn chuyển hướng cuộc gọi đến bất kỳ chức năng nào từ bên trong một thư viện được chia sẻ đến chức năng tùy ý của riêng bạn.

  • Tạo một thư viện chia sẻ chứa mã theo thử nghiệm
  • Trong thử nghiệm của bạn tải các thư viện chia sẻ tự động (dlopen)
  • Chuyển những biểu tượng bạn muốn thử chức năng thử nghiệm của bạn (elf_hook)
  • Bây giờ mọi cuộc gọi đến chức năng thực sự trong thư viện (mã đang được kiểm tra) sẽ được chuyển hướng đến chức năng được mô phỏng của bạn

Một điểm cộng cho phương pháp này là bạn ca n vẫn gọi hàm ban đầu khi được yêu cầu.

  • Nếu đối với một số thử nghiệm bạn muốn thực hiện cuộc gọi, ví dụ: getaddrinfo, thành công, bạn có thể gọi phiên bản hệ thống.
  • Trong các thử nghiệm khác, bạn có thể sử dụng phiên bản giả mạo của riêng bạn, ví dụ: mocked_getaddrinfo và trả lại bất kỳ thứ gì bạn muốn.
  • Bạn có thể tạo bao nhiêu mocked_getaddrinfo chức năng như bạn muốn, để thử nghiệm nhiều kịch bản

elf_hook có chữ ký sau đây:

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

Bạn sẽ sử dụng nó như thế này:

#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; 
} 

Mọi cuộc gọi đến getaddrinfo từ trong thư viện đang được kiểm tra sẽ gọi mocked_getaddrinfo.

Bài viết toàn diện của tác giả elf_hook, Anthony Shoumikhin, là here.

Các vấn đề liên quan