Skip to content

Commit 06a10a4

Browse files
authored
Replace packet creation macros in tests with cpp functions. (#1928)
* Added RawPacketFactory to replace macros `READ_FILE_AND_CREATE_PACKET` and `READ_FILE_AND_CREATE_PACKET_LINKTYPE`. * Added example usage. * Reverted test utils changes. * Added project pcpp test utils for common utils. * Added PcppTestUtilities to replace packet load macros. * Moved default resource provider into PcppTestUtilities. * Lint * Fix std::uint8_t to uint8_t. * Fix explicit ctors. * Fix includes. * Fix constness. * Fix cmake define. * Fix typo. * Fix style. * Simplified readHexResource. * Removed reserve. * Removed extra overloads on ResourceProvider. * Remove BinaryData for now. * Fixed OS separator. * Fixed header extensions. * Lint * Added documentation. * Removed unused PacketFactory API. * Lint
1 parent 2e89193 commit 06a10a4

File tree

10 files changed

+369
-17
lines changed

10 files changed

+369
-17
lines changed

Tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
if(PCAPPP_BUILD_TESTS)
22
add_subdirectory(PcppTestFramework)
3+
add_subdirectory(PcppTestUtilities)
34
add_subdirectory(Packet++Test)
45

56
if(PCAPPP_BUILD_PCAPPP)

Tests/Packet++Test/CMakeLists.txt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,15 @@ add_executable(
5151
Utils/TestUtils.cpp
5252
)
5353

54-
target_link_libraries(Packet++Test PUBLIC memplumber Packet++ PcppTestFramework EndianPortable)
54+
target_link_libraries(
55+
Packet++Test
56+
PUBLIC memplumber Packet++ PcppTestUtilities PcppTestFramework EndianPortable
57+
)
58+
59+
if(WIN32)
60+
# Otherwise winsock2.h will get conflict definitions with windows.h
61+
target_compile_definitions(Packet++Test PUBLIC WIN32_LEAN_AND_MEAN)
62+
endif()
5563

5664
if(MSVC)
5765
# This executable requires getopt.h not available on VStudio

Tests/Packet++Test/Tests/BgpTests.cpp

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,19 @@
1010

1111
PTF_TEST_CASE(BgpLayerParsingTest)
1212
{
13-
timeval time;
14-
gettimeofday(&time, nullptr);
13+
using pcpp_tests::utils::createPacketFromHexResource;
1514

16-
READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/Bgp_keepalive.dat");
17-
READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/Bgp_open.dat");
18-
READ_FILE_AND_CREATE_PACKET(3, "PacketExamples/Bgp_notification.dat");
19-
READ_FILE_AND_CREATE_PACKET(4, "PacketExamples/Bgp_notification2.dat");
20-
READ_FILE_AND_CREATE_PACKET(5, "PacketExamples/Bgp_route-refresh.dat");
21-
READ_FILE_AND_CREATE_PACKET(6, "PacketExamples/Bgp_update1.dat");
22-
READ_FILE_AND_CREATE_PACKET(7, "PacketExamples/Bgp_update2.dat");
15+
auto rawPacket1 = createPacketFromHexResource("PacketExamples/Bgp_keepalive.dat");
16+
auto rawPacket2 = createPacketFromHexResource("PacketExamples/Bgp_open.dat");
17+
auto rawPacket3 = createPacketFromHexResource("PacketExamples/Bgp_notification.dat");
18+
auto rawPacket4 = createPacketFromHexResource("PacketExamples/Bgp_notification2.dat");
19+
auto rawPacket5 = createPacketFromHexResource("PacketExamples/Bgp_route-refresh.dat");
20+
auto rawPacket6 = createPacketFromHexResource("PacketExamples/Bgp_update1.dat");
21+
auto rawPacket7 = createPacketFromHexResource("PacketExamples/Bgp_update2.dat");
2322

2423
// parse BGP KEEPALIVE message
2524

26-
pcpp::Packet bgpKAPacket(&rawPacket1);
25+
pcpp::Packet bgpKAPacket(rawPacket1.get());
2726

2827
PTF_ASSERT_TRUE(bgpKAPacket.isPacketOfType(pcpp::BGP));
2928
pcpp::BgpLayer* bgpLayer = bgpKAPacket.getLayerOfType<pcpp::BgpLayer>();
@@ -42,7 +41,7 @@ PTF_TEST_CASE(BgpLayerParsingTest)
4241

4342
// parse BGP OPEN message
4443

45-
pcpp::Packet bgpOpenPacket(&rawPacket2);
44+
pcpp::Packet bgpOpenPacket(rawPacket2.get());
4645

4746
PTF_ASSERT_TRUE(bgpOpenPacket.isPacketOfType(pcpp::BGP));
4847
bgpLayer = bgpOpenPacket.getLayerOfType<pcpp::BgpLayer>();
@@ -78,7 +77,7 @@ PTF_TEST_CASE(BgpLayerParsingTest)
7877

7978
// parse BGP NOTIFICATION message
8079

81-
pcpp::Packet bgpNotificationPacket(&rawPacket3);
80+
pcpp::Packet bgpNotificationPacket(rawPacket3.get());
8281

8382
PTF_ASSERT_TRUE(bgpNotificationPacket.isPacketOfType(pcpp::BGP));
8483
pcpp::BgpNotificationMessageLayer* bgpNotificationLayer =
@@ -100,7 +99,7 @@ PTF_TEST_CASE(BgpLayerParsingTest)
10099
"726520696e666f726d6174696f6e2e";
101100
PTF_ASSERT_EQUAL(bgpNotificationLayer->getNotificationDataAsHexString(), notificationDataAsHexString);
102101

103-
pcpp::Packet bgpNotificationNoDataPacket(&rawPacket4);
102+
pcpp::Packet bgpNotificationNoDataPacket(rawPacket4.get());
104103

105104
PTF_ASSERT_TRUE(bgpNotificationNoDataPacket.isPacketOfType(pcpp::BGP));
106105
bgpNotificationLayer = bgpNotificationNoDataPacket.getLayerOfType<pcpp::BgpNotificationMessageLayer>();
@@ -111,7 +110,7 @@ PTF_TEST_CASE(BgpLayerParsingTest)
111110

112111
// parse BGP ROUTE-REFRESH message
113112

114-
pcpp::Packet bgpRRPacket(&rawPacket5);
113+
pcpp::Packet bgpRRPacket(rawPacket5.get());
115114

116115
PTF_ASSERT_TRUE(bgpRRPacket.isPacketOfType(pcpp::BGP));
117116
pcpp::BgpRouteRefreshMessageLayer* bgpRRLayer = bgpRRPacket.getLayerOfType<pcpp::BgpRouteRefreshMessageLayer>();
@@ -124,7 +123,7 @@ PTF_TEST_CASE(BgpLayerParsingTest)
124123

125124
// parse BGP UPDATE message with Withdrawn Routes
126125

127-
pcpp::Packet bgpUpdatePacket1(&rawPacket6);
126+
pcpp::Packet bgpUpdatePacket1(rawPacket6.get());
128127

129128
PTF_ASSERT_TRUE(bgpUpdatePacket1.isPacketOfType(pcpp::BGP));
130129
pcpp::BgpUpdateMessageLayer* bgpUpdateLayer = bgpUpdatePacket1.getLayerOfType<pcpp::BgpUpdateMessageLayer>();
@@ -156,7 +155,7 @@ PTF_TEST_CASE(BgpLayerParsingTest)
156155

157156
// parse BGP UPDATE message with Path Attributes
158157

159-
pcpp::Packet bgpUpdatePacket2(&rawPacket7);
158+
pcpp::Packet bgpUpdatePacket2(rawPacket7.get());
160159

161160
PTF_ASSERT_TRUE(bgpUpdatePacket2.isPacketOfType(pcpp::BGP));
162161
bgpUpdateLayer = bgpUpdatePacket2.getLayerOfType<pcpp::BgpUpdateMessageLayer>();

Tests/Packet++Test/Utils/TestUtils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include <cstdlib>
1010
#include <vector>
1111

12+
#include "PacketFactory.h"
13+
1214
namespace pcpp_tests
1315
{
1416

Tests/Packet++Test/main.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "TestDefinition.h"
55
#include "Logger.h"
66
#include "../../Tests/Packet++Test/Utils/TestUtils.h"
7+
#include "Resources.h"
78

89
static struct option PacketTestOptions[] = {
910
{ "include-tags", required_argument, nullptr, 't' },
@@ -76,6 +77,12 @@ int main(int argc, char* argv[])
7677
<< "Built: " << pcpp::getBuildDateTime() << std::endl
7778
<< "Built from: " << pcpp::getGitInfo() << std::endl;
7879

80+
std::cout << "Using data root: current directory" << std::endl;
81+
82+
// Set the resource provider for the tests
83+
auto resourceProvider = std::make_unique<pcpp_tests::utils::ResourceProvider>("");
84+
pcpp_tests::setDefaultResourceProvider(resourceProvider.get());
85+
7986
#ifdef NDEBUG
8087
skipMemLeakCheck = true;
8188
std::cout
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
cmake_minimum_required(VERSION 3.12)
2+
3+
add_library(PcppTestUtilities STATIC EXCLUDE_FROM_ALL "PacketFactory.cpp" "Resources.cpp")
4+
5+
target_include_directories(PcppTestUtilities PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/")
6+
target_link_libraries(PcppTestUtilities PUBLIC Packet++)
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#include "PacketFactory.h"
2+
3+
#include <stdexcept>
4+
5+
#include "SystemUtils.h"
6+
#include "TimespecTimeval.h"
7+
8+
namespace pcpp_tests
9+
{
10+
using namespace pcpp;
11+
12+
namespace utils
13+
{
14+
PacketFactory::PacketFactory()
15+
{
16+
timeval factoryTimeTV;
17+
// Initialize factoryTime to the current time
18+
gettimeofday(&factoryTimeTV, nullptr);
19+
factoryTime = internal::toTimespec(factoryTimeTV);
20+
}
21+
22+
PacketFactory::PacketFactory(timespec time) : factoryTime(time)
23+
{}
24+
25+
PacketFactory::PacketFactory(timeval time) : PacketFactory(internal::toTimespec(time))
26+
{}
27+
28+
PacketFactory::PacketFactory(LinkLayerType linkType) : PacketFactory()
29+
{
30+
// Call to the default constructor to initialize factoryTime to the current time
31+
defaultLinkType = linkType;
32+
}
33+
34+
std::unique_ptr<RawPacket> PacketFactory::createFromBuffer(std::unique_ptr<uint8_t[]> buffer,
35+
size_t bufferLen) const
36+
{
37+
if (buffer == nullptr || bufferLen == 0)
38+
{
39+
throw std::invalid_argument("Buffer cannot be null and length must be greater than zero");
40+
}
41+
42+
return std::make_unique<RawPacket>(buffer.release(), static_cast<int>(bufferLen), factoryTime, true,
43+
defaultLinkType);
44+
}
45+
46+
std::unique_ptr<RawPacket> PacketFactory::createFromBufferNonOwning(std::vector<uint8_t> const& buffer) const
47+
{
48+
return createFromBufferNonOwning(buffer.data(), buffer.size());
49+
}
50+
51+
std::unique_ptr<RawPacket> PacketFactory::createFromBufferNonOwning(const uint8_t* buffer,
52+
size_t bufferLen) const
53+
{
54+
if (buffer == nullptr || bufferLen == 0)
55+
{
56+
throw std::invalid_argument("Buffer cannot be null and length must be greater than zero");
57+
}
58+
59+
return std::make_unique<RawPacket>(buffer, static_cast<int>(bufferLen), factoryTime, false,
60+
defaultLinkType);
61+
}
62+
63+
std::unique_ptr<pcpp::RawPacket> createPacketFromHexResource(const std::string& resourceName,
64+
const utils::PacketFactory& factory,
65+
utils::ResourceProvider const* resourceProvider)
66+
{
67+
using pcpp_tests::utils::ResourceType;
68+
69+
if (resourceProvider == nullptr)
70+
{
71+
// If no data loader is provided, use the current test environment's data loader
72+
resourceProvider = getDefaultResourceProvider();
73+
}
74+
75+
auto resource = resourceProvider->loadResource(resourceName.c_str(), ResourceType::HexData);
76+
return factory.createFromBuffer(std::move(resource.data), resource.length);
77+
}
78+
} // namespace utils
79+
} // namespace pcpp_tests
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#pragma once
2+
3+
#include <memory>
4+
#include <string>
5+
#include <vector>
6+
7+
#include "RawPacket.h"
8+
#include "Resources.h"
9+
10+
namespace pcpp_tests
11+
{
12+
namespace utils
13+
{
14+
class PacketFactory
15+
{
16+
public:
17+
/// @brief The time used for creating packets in the factory.
18+
timespec factoryTime;
19+
/// @brief The default link layer type for packets created by this factory.
20+
pcpp::LinkLayerType defaultLinkType = pcpp::LinkLayerType::LINKTYPE_ETHERNET;
21+
22+
/// @brief Creates a new PacketFactory instance with the current time as factoryTime.
23+
PacketFactory();
24+
/// @brief Creates a new PacketFactory instance with a specified time.
25+
/// @param time The time to use for creating packets in the factory.
26+
explicit PacketFactory(timespec time);
27+
/// @brief Creates a new PacketFactory instance with a specified time.
28+
/// @param time The time to use for creating packets in the factory.
29+
explicit PacketFactory(timeval time);
30+
/// @brief Creates a new PacketFactory instance with a specified link layer type.
31+
/// @param linkType The link layer type to use for packets created by this factory.
32+
explicit PacketFactory(pcpp::LinkLayerType linkType);
33+
34+
// TODO: RawPacket requires a move constructor to return by value efficiently.
35+
/// @brief Creates a RawPacket from a vector of bytes.
36+
/// @param buffer A unique pointer to a buffer containing the raw packet data.
37+
/// @param bufferLen The length of the buffer in bytes.
38+
/// @return A RawPacket object created from the buffer.
39+
std::unique_ptr<pcpp::RawPacket> createFromBuffer(std::unique_ptr<uint8_t[]> buffer,
40+
size_t bufferLen) const;
41+
42+
/// @brief Creates a RawPacket from a vector of bytes without taking ownership of the data.
43+
/// @param buffer A vector containing the raw packet data.
44+
/// @return A RawPacket object created from the buffer.
45+
std::unique_ptr<pcpp::RawPacket> createFromBufferNonOwning(std::vector<uint8_t> const& buffer) const;
46+
47+
/// @brief Creates a RawPacket from a buffer without taking ownership of the data.
48+
/// @param buffer A pointer to the raw packet data.
49+
/// @param bufferLen The length of the buffer in bytes.
50+
/// @return A RawPacket object created from the buffer.
51+
std::unique_ptr<pcpp::RawPacket> createFromBufferNonOwning(const uint8_t* buffer, size_t bufferLen) const;
52+
};
53+
54+
/// @brief Creates a RawPacket from a resource file.
55+
/// @param resourceName The name of the resource file to read the packet data from.
56+
/// @param factory The PacketFactory to use for creating the RawPacket.
57+
/// @param resourceProvider An optional ResourceProvider to use for loading the resource file.
58+
/// Uses the default resource provider if not provided.
59+
/// @return A RawPacket object created from the resource file.
60+
std::unique_ptr<pcpp::RawPacket> createPacketFromHexResource(
61+
const std::string& resourceName, const PacketFactory& factory = PacketFactory(),
62+
ResourceProvider const* resourceProvider = nullptr);
63+
} // namespace utils
64+
} // namespace pcpp_tests

0 commit comments

Comments
 (0)