LCOV - code coverage report
Current view: top level - dpdklibs/unittest - Utils_test.cxx (source / functions) Coverage Total Hit
Test: code.result Lines: 100.0 % 47 47
Test Date: 2025-12-21 13:07:08 Functions: 100.0 % 2 2

            Line data    Source code
       1              : /**
       2              :  * @file Utils_test.cxx 
       3              :  *
       4              :  * Test various utility functions in this package
       5              :  *
       6              :  * This is part of the DUNE DAQ Application Framework, copyright 2020.
       7              :  * Licensing/copyright details are in the COPYING file that you should have
       8              :  * received with this code.
       9              :  */
      10              : 
      11              : #include "dpdklibs/udp/Utils.hpp"
      12              : 
      13              : #define BOOST_TEST_MODULE Utils_test // NOLINT
      14              : 
      15              : #include "TRACE/trace.h"
      16              : #include "boost/test/unit_test.hpp"
      17              : 
      18              : #include <cstdio>
      19              : #include <filesystem>
      20              : #include <fstream>
      21              : #include <limits>
      22              : #include <map>
      23              : #include <string>
      24              : #include <unordered_map>
      25              : 
      26              : using namespace dunedaq::dpdklibs;
      27              : 
      28              : BOOST_AUTO_TEST_SUITE(Utils_test)
      29              : 
      30            2 : BOOST_AUTO_TEST_CASE(GetEthernetPackets)
      31              : {
      32              : 
      33            1 :   const std::string tmp_filename = std::tmpnam(nullptr);
      34              : 
      35              :   // Construct a fake ethernet packet where the only contents which
      36              :   // matter are the ether_type (sanity-checked in
      37              :   // udp::get_ethernet_packets) and ipv4_packet_length (used by
      38              :   // udp::get_ethernet_packets to determine the next packet). For the
      39              :   // IPv4 packet length, while two bytes are allocated in the IPv4
      40              :   // header to describe the size of the IPv4 packet, for the sake of
      41              :   // simplicity we're only using the lower byte.
      42              :   
      43            1 :   const uint8_t ipv4_packet_length = 28; // For the purposes of this test, do not make the length longer than 255!
      44            1 :   const uint8_t ipv4_packet_length_position = 17; // Comes after a 14-byte ethernet header and three bytes of IPv4 header
      45            1 :   const uint8_t ether_type = 0x08;
      46              : 
      47            1 :   std::vector<uint8_t> fake_ethernet_packet = {
      48              :                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      49              :                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      50              :                                         ether_type, 0x00, 
      51              :                                         0x00, 0x00,
      52              :                                         0x00, ipv4_packet_length,
      53              :                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      54              :                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      55              :                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
      56            1 :   };
      57              : 
      58            1 :   BOOST_REQUIRE_EQUAL(fake_ethernet_packet.size(), ipv4_packet_length + sizeof(rte_ether_hdr)); // This is really a test-of-the-test
      59              :   
      60            1 :   std::ofstream tmpfile(tmp_filename);
      61            1 :   BOOST_REQUIRE(tmpfile.is_open());
      62              :   
      63           43 :   for (auto& byte : fake_ethernet_packet) {
      64           42 :     tmpfile << byte;
      65              :   }
      66            1 :   tmpfile.close();
      67              : 
      68            1 :   std::vector<char> buffervec;
      69            1 :   udp::add_file_contents_to_vector(tmp_filename, buffervec);
      70            1 :   BOOST_REQUIRE_EQUAL(fake_ethernet_packet.size(), buffervec.size());
      71              :   
      72            1 :   std::vector<std::pair<const void*, int>> packets = udp::get_ethernet_packets(buffervec);
      73              : 
      74            1 :   BOOST_REQUIRE_EQUAL(packets.size(), 1);
      75            1 :   BOOST_REQUIRE_EQUAL(packets[0].second, fake_ethernet_packet.size());
      76              : 
      77            1 :   std::vector<uint8_t> fake_ethernet_packet2 = fake_ethernet_packet;
      78            1 :   const uint8_t payload_size = 100; // Notice I'm careful not to make the IPv4 packet exceed 255 bytes here
      79            1 :   fake_ethernet_packet2.resize(fake_ethernet_packet2.size() + payload_size, 0xA);
      80            1 :   fake_ethernet_packet2.at(ipv4_packet_length_position) = fake_ethernet_packet2.at(ipv4_packet_length_position) + payload_size;
      81            1 :   BOOST_REQUIRE_EQUAL(ipv4_packet_length + payload_size, fake_ethernet_packet2.at(ipv4_packet_length_position));
      82              : 
      83            1 :   tmpfile.open(tmp_filename, std::ofstream::app);
      84            1 :   BOOST_REQUIRE(tmpfile.is_open());
      85              : 
      86          143 :   for (auto& byte : fake_ethernet_packet2) {
      87          142 :     tmpfile << byte;
      88              :   }
      89            1 :   tmpfile.close();
      90              : 
      91            1 :   buffervec.resize(0);
      92            1 :   udp::add_file_contents_to_vector(tmp_filename, buffervec);
      93            1 :   BOOST_REQUIRE_EQUAL(buffervec.size(), fake_ethernet_packet.size() + fake_ethernet_packet2.size());
      94              :   
      95            1 :   packets = udp::get_ethernet_packets(buffervec);
      96              : 
      97            1 :   BOOST_REQUIRE_EQUAL(packets.size(), 2);
      98            1 :   BOOST_REQUIRE_EQUAL(packets[0].second, fake_ethernet_packet.size());
      99            1 :   BOOST_REQUIRE_EQUAL(packets[1].second, fake_ethernet_packet2.size());
     100              : 
     101            1 :   BOOST_REQUIRE_EQUAL(buffervec.at( buffervec.size() - 1 ), 0xA);
     102              : 
     103              :   // Now some checks that get_ethernet_packets can catch when something goes wrong
     104              : 
     105            1 :   auto orig_ipv4_packet_size = buffervec.at(ipv4_packet_length_position);
     106            1 :   buffervec.at(ipv4_packet_length_position) = 0; // The first packet will now state a length of zero bytes, shorter than is allowed in the function (and in basic logic)
     107              :   
     108            2 :   BOOST_CHECK_THROW(udp::get_ethernet_packets(buffervec), dunedaq::dpdklibs::BadPacketHeaderIssue);
     109              : 
     110              :   // Restore the valid size of the packet, but now give the ethernet header an invalid ethertype
     111            1 :   buffervec.at(ipv4_packet_length_position) = orig_ipv4_packet_size;
     112            1 :   buffervec.at(6 + 6) = 0xAA; // 6 + 6 to account for the two 6-byte MAC addresses past which the ether type byte lives.
     113            2 :   BOOST_CHECK_THROW(udp::get_ethernet_packets(buffervec), dunedaq::dpdklibs::BadPacketHeaderIssue);
     114              : 
     115            1 :   buffervec.at(6 + 6) = ether_type;
     116            1 :   BOOST_CHECK_NO_THROW(udp::get_ethernet_packets(buffervec)); // Just a quick check that we got things to return to normal
     117              : 
     118            1 :   std::filesystem::remove(tmp_filename);
     119            1 : }
     120              : 
     121              : BOOST_AUTO_TEST_SUITE_END()
        

Generated by: LCOV version 2.0-1