From df25dd582665758806dc8c402c03c1c6d38b4bed Mon Sep 17 00:00:00 2001 From: liuwentan Date: Thu, 25 Aug 2022 15:32:33 +0800 Subject: [PATCH] [PACKET_IO]add gtest case --- .../pcap_file_mode/pio_pcap_file.cpp | 10 +- .../pcap_live_mode/pio_pcap_live.cpp | 14 +- src/packet_io/test/CMakeLists.txt | 2 +- src/packet_io/test/gtest_packet_io.cpp | 370 +++++++++++++++--- src/packet_io/test/pcap_sample/test01-14.pcap | Bin 0 -> 2043 bytes src/packet_io/test/pcap_sample/test02-34.pcap | Bin 0 -> 7296 bytes .../test03-64.pcapng} | Bin src/packet_io/test/pcap_sample/test04-73.pcap | Bin 0 -> 24314 bytes .../test/pcap_sample/test05-110.pcap | Bin 0 -> 25319 bytes 9 files changed, 326 insertions(+), 70 deletions(-) create mode 100644 src/packet_io/test/pcap_sample/test01-14.pcap create mode 100644 src/packet_io/test/pcap_sample/test02-34.pcap rename src/packet_io/test/{test-64.pcapng => pcap_sample/test03-64.pcapng} (100%) create mode 100644 src/packet_io/test/pcap_sample/test04-73.pcap create mode 100644 src/packet_io/test/pcap_sample/test05-110.pcap diff --git a/src/packet_io/pcap_file_mode/pio_pcap_file.cpp b/src/packet_io/pcap_file_mode/pio_pcap_file.cpp index 347b357..e57d3bf 100644 --- a/src/packet_io/pcap_file_mode/pio_pcap_file.cpp +++ b/src/packet_io/pcap_file_mode/pio_pcap_file.cpp @@ -302,11 +302,13 @@ ssize_t pio_pcap_file_device_close(struct packet_io_device *pdev) } if (pdev->entity.pcap_file_dev_ctx != nullptr) { - if (pdev->entity.pcap_file_dev_ctx->entity.file != nullptr) { + if (!pdev->entity.pcap_file_dev_ctx->is_dir && + pdev->entity.pcap_file_dev_ctx->entity.file != nullptr) { cleanup_pcap_plain_file_info(pdev->entity.pcap_file_dev_ctx->entity.file); } - if (pdev->entity.pcap_file_dev_ctx->entity.dir != nullptr) { + if (pdev->entity.pcap_file_dev_ctx->is_dir && + pdev->entity.pcap_file_dev_ctx->entity.dir != nullptr) { cleanup_pcap_directory_info(pdev->entity.pcap_file_dev_ctx->entity.dir); } @@ -315,9 +317,9 @@ ssize_t pio_pcap_file_device_close(struct packet_io_device *pdev) release_pio_packet_queue(&pdev->entity.pcap_file_dev_ctx->pkt_queues[i]); } } - } - FREE(pdev->entity.pcap_file_dev_ctx); + FREE(pdev->entity.pcap_file_dev_ctx); + } return 0; } diff --git a/src/packet_io/pcap_live_mode/pio_pcap_live.cpp b/src/packet_io/pcap_live_mode/pio_pcap_live.cpp index 7aa983a..3b7f2a8 100644 --- a/src/packet_io/pcap_live_mode/pio_pcap_live.cpp +++ b/src/packet_io/pcap_live_mode/pio_pcap_live.cpp @@ -144,13 +144,15 @@ ssize_t pio_pcap_live_device_close(struct packet_io_device *pdev) return -1; } - for (uint32_t i = 0; i < VIRTUAL_QUEUE_MAX_NUM; i++) { - if (pdev->entity.pcap_live_dev_ctx->pkt_queues[i].len != 0) { - release_pio_packet_queue(&pdev->entity.pcap_live_dev_ctx->pkt_queues[i]); + if (pdev->entity.pcap_live_dev_ctx != nullptr) { + for (uint32_t i = 0; i < VIRTUAL_QUEUE_MAX_NUM; i++) { + if (pdev->entity.pcap_live_dev_ctx->pkt_queues[i].len != 0) { + release_pio_packet_queue(&pdev->entity.pcap_live_dev_ctx->pkt_queues[i]); + } } - } - FREE(pdev->entity.pcap_live_dev_ctx); + FREE(pdev->entity.pcap_live_dev_ctx); + } return 0; } @@ -252,9 +254,9 @@ ssize_t pio_pcap_live_device_send(struct packet_io_device *pdev, uint32_t txq_id for (size_t i = 0; i < nr_pkts; i++) { struct pio_packet *p = (struct pio_packet *)pkts[i]; res = pcap_sendpacket(plive_dev_ctx->pcap_handle, (u_char *)p->pkt_payload, p->pkt_len); + FREE(pkts[i]); } pthread_mutex_unlock(&plive_dev_ctx->handle_mutex); - /*TODO: when to free pio_packet? */ return 0; } diff --git a/src/packet_io/test/CMakeLists.txt b/src/packet_io/test/CMakeLists.txt index 18c8fb6..381b132 100644 --- a/src/packet_io/test/CMakeLists.txt +++ b/src/packet_io/test/CMakeLists.txt @@ -13,4 +13,4 @@ target_link_libraries( include(GoogleTest) gtest_discover_tests(gtest_packet_io) -file(COPY test-64.pcapng DESTINATION ./) \ No newline at end of file +file(COPY pcap_sample DESTINATION ./) \ No newline at end of file diff --git a/src/packet_io/test/gtest_packet_io.cpp b/src/packet_io/test/gtest_packet_io.cpp index c9db370..0d0eb47 100644 --- a/src/packet_io/test/gtest_packet_io.cpp +++ b/src/packet_io/test/gtest_packet_io.cpp @@ -4,60 +4,130 @@ #include "packet.h" #include "packet_io.h" #include "packet_io_util.h" +#include "packet_io_internal.h" +#include "../pcap_file_mode/pio_pcap_file.h" +#include "../pcap_live_mode/pio_pcap_live.h" TEST(PACKET_IO_Test, packet_io_instance_create_and_destroy) { struct packet_io_instance *ppio_inst = packet_io_instance_create(nullptr, PACKET_IO_RUN_MODE_PCAP_FILE); EXPECT_EQ(ppio_inst, nullptr); + ppio_inst = packet_io_instance_create("stellar", PACKET_IO_RUN_MODE_MAX); EXPECT_EQ(ppio_inst, nullptr); + ppio_inst = packet_io_instance_create("stellar", PACKET_IO_RUN_MODE_PCAP_FILE); EXPECT_NE(ppio_inst, nullptr); + packet_io_fini(ppio_inst); } TEST(PACKET_IO_Test, packet_io_device_open_and_close) { struct packet_io_device *pdev = packet_io_device_open(nullptr, nullptr, 1, 1); EXPECT_EQ(pdev, nullptr); + struct packet_io_instance *ppio_inst = packet_io_instance_create("stellar", PACKET_IO_RUN_MODE_PCAP_LIVE); EXPECT_NE(ppio_inst, nullptr); + pdev = packet_io_device_open(ppio_inst, nullptr, 1, 1); EXPECT_EQ(pdev, nullptr); + pdev = packet_io_device_open(ppio_inst, "tun0", 1, 1); EXPECT_NE(pdev, nullptr); + packet_io_device_close(pdev); packet_io_fini(ppio_inst); } -TEST(PACKET_IO_Test, packet_io_device_rx) { +/* case1: read 1 pkt and read 63 pkts */ +TEST(PACKET_IO_Test, packet_io_device_rx1) { struct packet_io_instance *ppio_inst = packet_io_instance_create("stellar", PACKET_IO_RUN_MODE_PCAP_FILE); - struct packet_io_device *pdev = packet_io_device_open(ppio_inst, "./test-64.pcapng", 1, 1); + EXPECT_NE(ppio_inst, nullptr); + struct packet_io_device *pdev = packet_io_device_open(ppio_inst, "./pcap_sample/test03-64.pcapng", 1, 1); EXPECT_NE(pdev, nullptr); + struct stellar_packet *rx_pkts[64]; ssize_t fetch_num = packet_io_device_rx(pdev, 0, rx_pkts, 1); EXPECT_EQ(fetch_num, 1); + + fetch_num = packet_io_device_rx(pdev, 0, rx_pkts, 63); + EXPECT_EQ(fetch_num, 63); + + packet_io_device_close(pdev); + packet_io_fini(ppio_inst); +} + +/* case2: read 64 pkts */ +TEST(PACKET_IO_Test, packet_io_device_rx2) { + struct packet_io_instance *ppio_inst = packet_io_instance_create("stellar", PACKET_IO_RUN_MODE_PCAP_FILE); + EXPECT_NE(ppio_inst, nullptr); + struct packet_io_device *pdev = packet_io_device_open(ppio_inst, "./pcap_sample/test03-64.pcapng", 1, 1); + EXPECT_NE(pdev, nullptr); + + struct stellar_packet *rx_pkts[64]; + ssize_t fetch_num = packet_io_device_rx(pdev, 0, rx_pkts, 64); + EXPECT_EQ(fetch_num, 64); + + fetch_num = packet_io_device_rx(pdev, 0, rx_pkts, 1); + EXPECT_EQ(fetch_num, 0); + + packet_io_device_close(pdev); + packet_io_fini(ppio_inst); +} + +/* case3: read 64 pkts with multi queue */ +TEST(PACKET_IO_Test, packet_io_device_rx3) { + struct packet_io_instance *ppio_inst = packet_io_instance_create("stellar", PACKET_IO_RUN_MODE_PCAP_FILE); + EXPECT_NE(ppio_inst, nullptr); + struct packet_io_device *pdev = packet_io_device_open(ppio_inst, "./pcap_sample/test03-64.pcapng", 3, 3); + EXPECT_NE(pdev, nullptr); + + struct stellar_packet *rx_pkts[64]; + ssize_t fetch_num1 = packet_io_device_rx(pdev, 0, rx_pkts, 64); + ssize_t fetch_num2 = packet_io_device_rx(pdev, 1, rx_pkts, 64); + ssize_t fetch_num3 = packet_io_device_rx(pdev, 2, rx_pkts, 64); + ssize_t fetch_num = fetch_num1 + fetch_num2 + fetch_num3; + EXPECT_EQ(fetch_num, 64); + packet_io_device_close(pdev); packet_io_fini(ppio_inst); } TEST(PACKET_IO_Test, packet_io_device_tx) { - struct packet_io_instance *ppio_inst = packet_io_instance_create("stellar", PACKET_IO_RUN_MODE_PCAP_LIVE); - struct packet_io_device *pdev = packet_io_device_open(ppio_inst, "tun0", 1, 1); - EXPECT_NE(pdev, nullptr); + struct packet_io_instance *ppio_inst_file = packet_io_instance_create("stellar_file", PACKET_IO_RUN_MODE_PCAP_FILE); + EXPECT_NE(ppio_inst_file, nullptr); + struct packet_io_instance *ppio_inst_live = packet_io_instance_create("stellar_live", PACKET_IO_RUN_MODE_PCAP_LIVE); + EXPECT_NE(ppio_inst_live, nullptr); + struct packet_io_device *pdev_file = packet_io_device_open(ppio_inst_file, "./pcap_sample/test03-64.pcapng", 1, 1); + EXPECT_NE(pdev_file, nullptr); + struct packet_io_device *pdev_live = packet_io_device_open(ppio_inst_live, "tun0", 1, 1); + EXPECT_NE(pdev_live, nullptr); + struct stellar_packet *rx_pkts[64]; - /* - ssize_t send_num = packet_io_device_tx(pdev, 0, rx_pkts, 1); - EXPECT_EQ(send_num, 0);*/ - packet_io_device_close(pdev); - packet_io_fini(ppio_inst); + ssize_t pkt_num = packet_io_device_rx(pdev_file, 0, rx_pkts, 64); + EXPECT_EQ(pkt_num, 64); + + ssize_t res = packet_io_device_tx(pdev_live, 0, rx_pkts, 1); + EXPECT_EQ(res, 0); + + res = packet_io_device_tx(pdev_live, 0, rx_pkts + 1, 63); + EXPECT_EQ(res, 0); + + packet_io_device_close(pdev_file); + packet_io_device_close(pdev_live); + packet_io_fini(ppio_inst_file); + packet_io_fini(ppio_inst_live); } TEST(PACKET_IO_Test, packet_io_pkts_free) { struct packet_io_instance *ppio_inst = packet_io_instance_create("stellar", PACKET_IO_RUN_MODE_PCAP_FILE); - struct packet_io_device *pdev = packet_io_device_open(ppio_inst, "./test-64.pcapng", 1, 1); + EXPECT_NE(ppio_inst, nullptr); + struct packet_io_device *pdev = packet_io_device_open(ppio_inst, "./pcap_sample/test03-64.pcapng", 1, 1); EXPECT_NE(pdev, nullptr); + struct stellar_packet *rx_pkts[64]; ssize_t fetch_num = packet_io_device_rx(pdev, 0, rx_pkts, 1); EXPECT_EQ(fetch_num, 1); + packet_io_pkts_free(pdev, 0, rx_pkts, 1); packet_io_device_close(pdev); packet_io_fini(ppio_inst); @@ -65,14 +135,18 @@ TEST(PACKET_IO_Test, packet_io_pkts_free) { TEST(PACKET_IO_Test, get_stellar_packet_ctrlzone) { struct packet_io_instance *ppio_inst = packet_io_instance_create("stellar", PACKET_IO_RUN_MODE_PCAP_FILE); - struct packet_io_device *pdev = packet_io_device_open(ppio_inst, "./test-64.pcapng", 1, 1); + EXPECT_NE(ppio_inst, nullptr); + struct packet_io_device *pdev = packet_io_device_open(ppio_inst, "./pcap_sample/test03-64.pcapng", 1, 1); EXPECT_NE(pdev, nullptr); + struct stellar_packet *rx_pkts[64]; ssize_t fetch_num = packet_io_device_rx(pdev, 0, rx_pkts, 1); EXPECT_EQ(fetch_num, 1); + size_t ctrlzone_len = 0; void *buff_ctrlzone = get_stellar_packet_ctrlzone(rx_pkts[0], &ctrlzone_len); EXPECT_EQ(buff_ctrlzone, rx_pkts[0]); + EXPECT_EQ(ctrlzone_len, CUSTOM_ZONE_LEN); packet_io_pkts_free(pdev, 0, rx_pkts, 1); packet_io_device_close(pdev); @@ -81,14 +155,18 @@ TEST(PACKET_IO_Test, get_stellar_packet_ctrlzone) { TEST(PACKET_IO_Test, get_stellar_packet_data) { struct packet_io_instance *ppio_inst = packet_io_instance_create("stellar", PACKET_IO_RUN_MODE_PCAP_FILE); - struct packet_io_device *pdev = packet_io_device_open(ppio_inst, "./test-64.pcapng", 1, 1); + EXPECT_NE(ppio_inst, nullptr); + struct packet_io_device *pdev = packet_io_device_open(ppio_inst, "./pcap_sample/test03-64.pcapng", 1, 1); EXPECT_NE(pdev, nullptr); + struct stellar_packet *rx_pkts[64]; ssize_t fetch_num = packet_io_device_rx(pdev, 0, rx_pkts, 1); EXPECT_EQ(fetch_num, 1); + size_t data_len = 0; void *buff_ctrlzone = get_stellar_packet_data(rx_pkts[0], &data_len); - EXPECT_EQ(buff_ctrlzone, (uint8_t *)rx_pkts[0]+64); + EXPECT_EQ(buff_ctrlzone, (uint8_t *)rx_pkts[0] + CUSTOM_ZONE_LEN); + EXPECT_NE(data_len, 0); packet_io_pkts_free(pdev, 0, rx_pkts, 1); packet_io_device_close(pdev); @@ -130,103 +208,277 @@ TEST(PACKET_IO_UTIL_Test, pio_packet_hash) { } TEST(PACKET_IO_UTIL_Test, pio_packet_queue_init) { - + struct pio_packet_queue pkt_queue; + pio_packet_queue_init(&pkt_queue); } -TEST(PACKET_IO_UTIL_Test, pio_packet_enqueue) { +TEST(PACKET_IO_UTIL_Test, pio_packet_enqueue_and_dequeue) { + struct pio_packet_queue pkt_queue; + pio_packet_queue_init(&pkt_queue); -} + struct pio_packet *p = (struct pio_packet *)malloc(COMMON_SIZE_OF_PIO_PACKET); + EXPECT_NE(p, nullptr); -TEST(PACKET_IO_UTIL_Test, pio_packet_dequeue) { + memset(p, 0, COMMON_SIZE_OF_PIO_PACKET); + p->pkt_hdr = p; + p->pkt_payload = p + CUSTOM_ZONE_LEN; + p->pkt_len = DEFAULT_MTU; + + pio_packet_enqueue(&pkt_queue, p); + EXPECT_EQ(pkt_queue.len, 1); + + struct pio_packet *dp = pio_packet_dequeue(&pkt_queue); + EXPECT_EQ(pkt_queue.len, 0); + FREE(dp); } TEST(PACKET_IO_UTIL_Test, release_pio_packet_queue) { + struct pio_packet_queue pkt_queue; + pio_packet_queue_init(&pkt_queue); + struct pio_packet *p = (struct pio_packet *)malloc(COMMON_SIZE_OF_PIO_PACKET); + EXPECT_NE(p, nullptr); + + memset(p, 0, COMMON_SIZE_OF_PIO_PACKET); + + p->pkt_hdr = p; + p->pkt_payload = p + CUSTOM_ZONE_LEN; + p->pkt_len = DEFAULT_MTU; + + pio_packet_enqueue(&pkt_queue, p); + EXPECT_EQ(pkt_queue.len, 1); + + release_pio_packet_queue(&pkt_queue); + EXPECT_EQ(pkt_queue.len, 0); } -TEST(PACKET_IO_PIO_PCAP_FILE_Test, pio_pcap_file_instance_create) { +TEST(PACKET_IO_PIO_PCAP_FILE_Test, pio_pcap_file_instance_create_and_destroy) { + struct packet_io_instance *pio_instance = CALLOC(struct packet_io_instance, 1); + EXPECT_NE(pio_instance, nullptr); + ssize_t res = strncpy_safe(pio_instance->inst_name, "stellar", sizeof(pio_instance->inst_name)); + EXPECT_EQ(res, 0); + + res = pio_pcap_file_instance_create(nullptr); + EXPECT_EQ(res, -1); + + res = pio_pcap_file_instance_create(pio_instance); + EXPECT_EQ(res, 0); + + pio_pcap_file_instance_destroy(nullptr); + + pio_pcap_file_instance_destroy(pio_instance); + FREE(pio_instance); } -TEST(PACKET_IO_PIO_PCAP_FILE_Test, pio_pcap_file_instance_destroy) { +TEST(PACKET_IO_PIO_PCAP_FILE_Test, pio_pcap_file_device_open_and_close) { + struct packet_io_instance *pio_instance = CALLOC(struct packet_io_instance, 1); + EXPECT_NE(pio_instance, nullptr); + struct packet_io_device *pdev = CALLOC(struct packet_io_device, 1); + EXPECT_NE(pdev, nullptr); -} + /* plain file */ + ssize_t res = strncpy_safe(pdev->dev_name, "./pcap_sample/test03-64.pcapng", sizeof(pdev->dev_name)); + EXPECT_EQ(res, 0); -TEST(PACKET_IO_PIO_PCAP_FILE_Test, pio_pcap_file_device_open) { + pdev->rxq_num = 1; + pdev->txq_num = 1; + pdev->ppio_inst = pio_instance; -} + res = pio_pcap_file_device_open(nullptr); + EXPECT_EQ(res, -1); -TEST(PACKET_IO_PIO_PCAP_FILE_Test, pio_pcap_file_device_close) { + res = pio_pcap_file_device_open(pdev); + EXPECT_EQ(res, 0); + res = pio_pcap_file_device_close(nullptr); + EXPECT_EQ(res, -1); + + res = pio_pcap_file_device_close(pdev); + EXPECT_EQ(res, 0); + + /* directory */ + memset(pdev, 0, sizeof(struct packet_io_device)); + res = strncpy_safe(pdev->dev_name, "./pcap_sample", sizeof(pdev->dev_name)); + EXPECT_EQ(res, 0); + + pdev->rxq_num = 1; + pdev->txq_num = 1; + pdev->ppio_inst = pio_instance; + + res = pio_pcap_file_device_open(pdev); + EXPECT_EQ(res, 0); + + res = pio_pcap_file_device_close(pdev); + EXPECT_EQ(res, 0); + + FREE(pdev); + FREE(pio_instance); } TEST(PACKET_IO_PIO_PCAP_FILE_Test, pio_pcap_file_device_receive) { + struct packet_io_instance *ppio_inst = packet_io_instance_create("stellar", PACKET_IO_RUN_MODE_PCAP_FILE); + EXPECT_NE(ppio_inst, nullptr); + /* plain file */ + struct packet_io_device *pdev = packet_io_device_open(ppio_inst, "./pcap_sample/test03-64.pcapng", 1, 1); + EXPECT_NE(pdev, nullptr); + + struct stellar_packet *rx_pkts[64]; + ssize_t res = pio_pcap_file_device_receive(pdev, 0, rx_pkts, 64); + EXPECT_EQ(res, 64); + + packet_io_pkts_free(pdev, 0, rx_pkts, 64); + packet_io_device_close(pdev); + + /* directory */ + pdev = packet_io_device_open(ppio_inst, "./pcap_sample", 1, 1); + EXPECT_NE(pdev, nullptr); + + res = pio_pcap_file_device_receive(pdev, 0, rx_pkts, 5); + EXPECT_EQ(res, 5); + + packet_io_pkts_free(pdev, 0, rx_pkts, 5); + packet_io_device_close(pdev); + + packet_io_instance_destroy(ppio_inst); } TEST(PACKET_IO_PIO_PCAP_FILE_Test, pio_pcap_file_device_pkt_free) { + struct packet_io_instance *ppio_inst = packet_io_instance_create("stellar", PACKET_IO_RUN_MODE_PCAP_FILE); + EXPECT_NE(ppio_inst, nullptr); + /* plain file */ + struct packet_io_device *pdev = packet_io_device_open(ppio_inst, "./pcap_sample/test03-64.pcapng", 1, 1); + EXPECT_NE(pdev, nullptr); + + struct stellar_packet *rx_pkts[64]; + ssize_t res = pio_pcap_file_device_receive(pdev, 0, rx_pkts, 64); + EXPECT_EQ(res, 64); + + pio_pcap_file_device_pkt_free(pdev, 0, rx_pkts, 64); + + packet_io_device_close(pdev); + packet_io_instance_destroy(ppio_inst); } TEST(PACKET_IO_PIO_PCAP_FILE_Test, pio_pcap_file_device_buff_ctrlzone) { + struct packet_io_instance *ppio_inst = packet_io_instance_create("stellar", PACKET_IO_RUN_MODE_PCAP_FILE); + EXPECT_NE(ppio_inst, nullptr); + /* plain file */ + struct packet_io_device *pdev = packet_io_device_open(ppio_inst, "./pcap_sample/test03-64.pcapng", 1, 1); + EXPECT_NE(pdev, nullptr); + + struct stellar_packet *rx_pkts[64]; + ssize_t res = pio_pcap_file_device_receive(pdev, 0, rx_pkts, 1); + EXPECT_EQ(res, 1); + + size_t ctrlzone_len = 0; + char *ctrlzone = pio_pcap_file_device_buff_ctrlzone(rx_pkts[0], &ctrlzone_len); + EXPECT_EQ(ctrlzone, (char *)rx_pkts[0]); + EXPECT_EQ(ctrlzone_len, CUSTOM_ZONE_LEN); + + pio_pcap_file_device_pkt_free(pdev, 0, rx_pkts, 1); + + packet_io_device_close(pdev); + packet_io_instance_destroy(ppio_inst); } TEST(PACKET_IO_PIO_PCAP_FILE_Test, pio_pcap_file_device_buff_mtod) { + struct packet_io_instance *ppio_inst = packet_io_instance_create("stellar", PACKET_IO_RUN_MODE_PCAP_FILE); + EXPECT_NE(ppio_inst, nullptr); + /* plain file */ + struct packet_io_device *pdev = packet_io_device_open(ppio_inst, "./pcap_sample/test03-64.pcapng", 1, 1); + EXPECT_NE(pdev, nullptr); + + struct stellar_packet *rx_pkts[64]; + ssize_t res = pio_pcap_file_device_receive(pdev, 0, rx_pkts, 1); + EXPECT_EQ(res, 1); + + size_t data_len = 0; + char *data = pio_pcap_file_device_buff_mtod(rx_pkts[0], &data_len); + EXPECT_EQ(data, (char *)rx_pkts[0] + CUSTOM_ZONE_LEN); + EXPECT_NE(data_len, 0); + + pio_pcap_file_device_pkt_free(pdev, 0, rx_pkts, 1); + + packet_io_device_close(pdev); + packet_io_instance_destroy(ppio_inst); } -TEST(PACKET_IO_PIO_PCAP_FILE_Test, pio_pcap_file_device_buff_buflen) { +TEST(PACKET_IO_PIO_PCAP_LIVE_Test, pio_pcap_live_instance_create_and_destroy) { + struct packet_io_instance *pio_instance = CALLOC(struct packet_io_instance, 1); + EXPECT_NE(pio_instance, nullptr); + ssize_t res = strncpy_safe(pio_instance->inst_name, "stellar", sizeof(pio_instance->inst_name)); + EXPECT_EQ(res, 0); + + res = pio_pcap_live_instance_create(nullptr); + EXPECT_EQ(res, -1); + + res = pio_pcap_live_instance_create(pio_instance); + EXPECT_EQ(res, 0); + + pio_pcap_live_instance_destroy(nullptr); + + pio_pcap_live_instance_destroy(pio_instance); + FREE(pio_instance); } -TEST(PACKET_IO_PIO_PCAP_FILE_Test, pio_pcap_file_device_buff_datalen) { +TEST(PACKET_IO_PIO_PCAP_LIVE_Test, pio_pcap_live_device_open_and_close) { + struct packet_io_instance *pio_instance = CALLOC(struct packet_io_instance, 1); + EXPECT_NE(pio_instance, nullptr); + struct packet_io_device *pdev = CALLOC(struct packet_io_device, 1); + EXPECT_NE(pdev, nullptr); -} + /* plain file */ + ssize_t res = strncpy_safe(pdev->dev_name, "tun0", sizeof(pdev->dev_name)); + EXPECT_EQ(res, 0); -TEST(PACKET_IO_PIO_PCAP_LIVE_Test, pio_pcap_live_instance_create) { + pdev->rxq_num = 1; + pdev->txq_num = 1; + pdev->ppio_inst = pio_instance; -} + res = pio_pcap_live_device_open(nullptr); + EXPECT_EQ(res, -1); -TEST(PACKET_IO_PIO_PCAP_LIVE_Test, pio_pcap_live_instance_destroy) { + res = pio_pcap_live_device_open(pdev); + EXPECT_EQ(res, 0); -} + res = pio_pcap_live_device_close(nullptr); + EXPECT_EQ(res, -1); -TEST(PACKET_IO_PIO_PCAP_LIVE_Test, pio_pcap_live_device_open) { - -} - -TEST(PACKET_IO_PIO_PCAP_LIVE_Test, pio_pcap_live_device_close) { - -} - -TEST(PACKET_IO_PIO_PCAP_LIVE_Test, pio_pcap_live_device_receive) { + res = pio_pcap_live_device_close(pdev); + EXPECT_EQ(res, 0); + FREE(pdev); + FREE(pio_instance); } TEST(PACKET_IO_PIO_PCAP_LIVE_Test, pio_pcap_live_device_send) { + struct packet_io_instance *ppio_inst_file = packet_io_instance_create("stellar_file", PACKET_IO_RUN_MODE_PCAP_FILE); + EXPECT_NE(ppio_inst_file, nullptr); + struct packet_io_instance *ppio_inst_live = packet_io_instance_create("stellar_live", PACKET_IO_RUN_MODE_PCAP_LIVE); + EXPECT_NE(ppio_inst_live, nullptr); + struct packet_io_device *pdev_file = packet_io_device_open(ppio_inst_file, "./pcap_sample/test03-64.pcapng", 1, 1); + EXPECT_NE(pdev_file, nullptr); + struct packet_io_device *pdev_live = packet_io_device_open(ppio_inst_live, "tun0", 1, 1); + EXPECT_NE(pdev_live, nullptr); -} - -TEST(PACKET_IO_PIO_PCAP_LIVE_Test, pio_pcap_live_device_pkt_free) { - -} - -TEST(PACKET_IO_PIO_PCAP_LIVE_Test, pio_pcap_live_device_buff_ctrlzone) { - -} - -TEST(PACKET_IO_PIO_PCAP_LIVE_Test, pio_pcap_live_device_buff_mtod) { - -} - -TEST(PACKET_IO_PIO_PCAP_LIVE_Test, pio_pcap_live_device_buff_buflen) { - -} - -TEST(PACKET_IO_PIO_PCAP_LIVE_Test, pio_pcap_live_device_buff_datalen) { + struct stellar_packet *tx_pkts[64]; + ssize_t pkt_num = packet_io_device_rx(pdev_file, 0, tx_pkts, 64); + EXPECT_EQ(pkt_num, 64); + ssize_t res = packet_io_device_tx(pdev_live, 0, tx_pkts, 64); + EXPECT_EQ(res, 0); + + packet_io_device_close(pdev_file); + packet_io_device_close(pdev_live); + packet_io_fini(ppio_inst_file); + packet_io_fini(ppio_inst_live); } int main(int argc, char ** argv) diff --git a/src/packet_io/test/pcap_sample/test01-14.pcap b/src/packet_io/test/pcap_sample/test01-14.pcap new file mode 100644 index 0000000000000000000000000000000000000000..8a0e65a6509b723827fc37f2437af563abca57cd GIT binary patch literal 2043 zcmd5+e^Aq97=ONVd>Q&B7>w|`Wl`dRK!ga0NzMt46FDdkgS%jjZNOw~V}m=ujw6n; z8I*)uYN8Mpi1-6E(vDVID$5?5s(BhndG_U(&K6n)Ze}FCdVE?&$T@)K)Yx-tG4#6mWr<0Sd2eCPt!3b(*A!<$HT;#sj7`0 zc`iZvAkj=!3C2gY;4=hpRURWmJN@WtHCXkcJ#d0P!3Rom}4R7TG6RP($MDNUr}%k^?A7&*Mxb7p|rr? z82U;W30(*l8}kG!KH@~%CTV%Lj<;iZTAoADB{(`1^VAYJ6`cnVhpvwvu4vwmSM5|8 z_mm*3Cj5cD!No^bYURBV;u$ZJM~Qsdw$$7&E+sGZ7);FW3rlQ$E6r|mLZG3#|7eG+ zYssOw;`rf|iiF05J^U3v8A>X5^cs6YS_SoX#Tmst5$g5%UUxgoe8}n(!{SzBmixoe zgZB%sKIrULXsD5id*4O8<~`Up;aar&;wtMN%LXUu2i@nL(^9J_T+%Eoja9>fhL@HFP z)1Qsis?F4#BTu>x6_yR0Z0tW%FnenL+kLG6V;(FW38*BrEztjsbKdSh^?zfR@BfS2 EUt8C&3jhEB literal 0 HcmV?d00001 diff --git a/src/packet_io/test/pcap_sample/test02-34.pcap b/src/packet_io/test/pcap_sample/test02-34.pcap new file mode 100644 index 0000000000000000000000000000000000000000..10f1af4a88055c383dabc704c63cb5d5335409be GIT binary patch literal 7296 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 literal 0 HcmV?d00001 diff --git a/src/packet_io/test/pcap_sample/test05-110.pcap b/src/packet_io/test/pcap_sample/test05-110.pcap new file mode 100644 index 0000000000000000000000000000000000000000..7059a2b1f10e04f0b472c3b3bf60e1a2dfb13a29 GIT binary patch literal 25319 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