From 02de76014e4a44e417b9148b42c63c89f3c9cbf4 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 12 Sep 2025 12:03:41 +0300 Subject: [PATCH 01/30] Added heuristics file content detector that determines the content based on the magic number. --- Pcap++/src/PcapFileDevice.cpp | 192 ++++++++++++++++++++++++++++++---- 1 file changed, 173 insertions(+), 19 deletions(-) diff --git a/Pcap++/src/PcapFileDevice.cpp b/Pcap++/src/PcapFileDevice.cpp index 48511673bc..2ee5c7788f 100644 --- a/Pcap++/src/PcapFileDevice.cpp +++ b/Pcap++/src/PcapFileDevice.cpp @@ -1,6 +1,7 @@ #define LOG_MODULE PcapLogModuleFileDevice #include +#include #include "PcapFileDevice.h" #include "light_pcapng_ext.h" #include "Logger.h" @@ -28,6 +29,178 @@ namespace pcpp { return reinterpret_cast(pcapngHandle); } + + struct pcap_file_header + { + uint32_t magic; + uint16_t version_major; + uint16_t version_minor; + int32_t thiszone; + uint32_t sigfigs; + uint32_t snaplen; + uint32_t linktype; + }; + + struct packet_header + { + uint32_t tv_sec; + uint32_t tv_usec; + uint32_t caplen; + uint32_t len; + }; + + enum class CaptureFileFormat + { + Unknown, + Pcap, + PcapNG, + Snoop, + }; + + /// @brief Check if a stream is seekable. + /// @param stream The stream to check. + /// @return True if the stream supports seek operations, false otherwise. + bool isStreamSeekable(std::istream& stream) + { + auto pos = stream.tellg(); + if (stream.fail()) + { + stream.clear(); + return false; + } + + if (stream.seekg(pos).fail()) + { + stream.clear(); + return false; + } + + return true; + } + + /// @brief Heuristic file format detector that scans the magic number of the file format header. + class CaptureFileFormatDetector + { + public: + /// @brief Checks a content stream for the magic number and determines the type. + /// @param content A content stream that contains the file content. + /// @return A CaptureFileFormat value with the detected content type. + CaptureFileFormat detectFormat(std::istream& content) + { + // Check if the stream supports seeking. + if (!isStreamSeekable(content)) + { + throw std::runtime_error("Heuristic file format detection requires seekable stream"); + } + + if (isPcapFile(content)) + return CaptureFileFormat::Pcap; + + // PcapNG backend can support ZstdCompressed Pcap files, so we assume an archive is compressed PcapNG. + if (isPcapNgFile(content) || isZstdArchive(content)) + return CaptureFileFormat::PcapNG; + + if (isSnoopFile(content)) + return CaptureFileFormat::Snoop; + + return CaptureFileFormat::Unknown; + } + + private: + class StreamPositionCheckpoint + { + public: + StreamPositionCheckpoint(std::istream& stream) : m_Stream(stream), m_Pos(stream.tellg()) + {} + + ~StreamPositionCheckpoint() + { + m_Stream.seekg(m_Pos); + } + + private: + std::istream& m_Stream; + std::streampos m_Pos; + }; + + bool isPcapFile(std::istream& content) + { + constexpr std::array pcapMagicNumbers = { + 0xa1b2c3d4, // regular pcap, microsecond-precision + 0xd4c3b2a1, // regular pcap, microsecond-precision (byte-swapped) + 0xa1b23c4d, // regular pcap, nanosecond-precision + 0x4d3cb2a1 // regular pcap, nanosecond-precision (byte-swapped) + }; + + StreamPositionCheckpoint checkpoint(content); + + pcap_file_header header; + content.read(reinterpret_cast(&header), sizeof(header)); + if (content.gcount() != sizeof(header)) + { + return false; + } + + return std::find(pcapMagicNumbers.begin(), pcapMagicNumbers.end(), header.magic) != + pcapMagicNumbers.end(); + } + + bool isPcapNgFile(std::istream& content) + { + constexpr std::array pcapMagicNumbers = { + 0x0A0D0D0A, // pcapng magic number (palindrome) + }; + + StreamPositionCheckpoint checkpoint(content); + + uint32_t magic = 0; + content.read(reinterpret_cast(&magic), sizeof(magic)); + if (content.gcount() != sizeof(magic)) + { + return false; + } + + return std::find(pcapMagicNumbers.begin(), pcapMagicNumbers.end(), magic) != pcapMagicNumbers.end(); + } + + bool isSnoopFile(std::istream& content) + { + constexpr std::array snoopMagicNumbers = { + 0x73'6E'6F'6F'70'00'00'00, // snoop magic number, "snoop" in ASCII + 0x00'00'00'70'6F'6F'6E'73 // snoop magic number, "snoop" in ASCII (byte-swapped) + }; + + StreamPositionCheckpoint checkpoint(content); + + uint64_t magic = 0; + content.read(reinterpret_cast(&magic), sizeof(magic)); + if (content.gcount() != sizeof(magic)) + { + return false; + } + + return std::find(snoopMagicNumbers.begin(), snoopMagicNumbers.end(), magic) != snoopMagicNumbers.end(); + } + + bool isZstdArchive(std::istream& content) + { + constexpr std::array zstdMagicNumbers = { + 0x28'B5'2F'FD, // zstd archive magic number + }; + + StreamPositionCheckpoint checkpoint(content); + + uint32_t magic = 0; + content.read(reinterpret_cast(&magic), sizeof(magic)); + if (content.gcount() != sizeof(magic)) + { + return false; + } + + return std::find(zstdMagicNumbers.begin(), zstdMagicNumbers.end(), magic) != zstdMagicNumbers.end(); + } + }; + } // namespace template constexpr size_t ARRAY_SIZE(T (&)[N]) @@ -35,25 +208,6 @@ namespace pcpp return N; } - struct pcap_file_header - { - uint32_t magic; - uint16_t version_major; - uint16_t version_minor; - int32_t thiszone; - uint32_t sigfigs; - uint32_t snaplen; - uint32_t linktype; - }; - - struct packet_header - { - uint32_t tv_sec; - uint32_t tv_usec; - uint32_t caplen; - uint32_t len; - }; - static bool checkNanoSupport() { #if defined(PCAP_TSTAMP_PRECISION_NANO) From 685dd9fbe59f0832fba55697f60ea9dba054829b Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 12 Sep 2025 12:09:11 +0300 Subject: [PATCH 02/30] Moved stream checkpoint outside format detector as it is not directly tied to it. --- Pcap++/src/PcapFileDevice.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Pcap++/src/PcapFileDevice.cpp b/Pcap++/src/PcapFileDevice.cpp index 1e5598c13c..4b208b4e93 100644 --- a/Pcap++/src/PcapFileDevice.cpp +++ b/Pcap++/src/PcapFileDevice.cpp @@ -78,6 +78,22 @@ namespace pcpp return true; } + class StreamPositionCheckpoint + { + public: + StreamPositionCheckpoint(std::istream& stream) : m_Stream(stream), m_Pos(stream.tellg()) + {} + + ~StreamPositionCheckpoint() + { + m_Stream.seekg(m_Pos); + } + + private: + std::istream& m_Stream; + std::streampos m_Pos; + }; + /// @brief Heuristic file format detector that scans the magic number of the file format header. class CaptureFileFormatDetector { @@ -107,22 +123,6 @@ namespace pcpp } private: - class StreamPositionCheckpoint - { - public: - StreamPositionCheckpoint(std::istream& stream) : m_Stream(stream), m_Pos(stream.tellg()) - {} - - ~StreamPositionCheckpoint() - { - m_Stream.seekg(m_Pos); - } - - private: - std::istream& m_Stream; - std::streampos m_Pos; - }; - bool isPcapFile(std::istream& content) { constexpr std::array pcapMagicNumbers = { From 40dee69c5a0a3263db7ec3583d7716608303ae23 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 12 Sep 2025 12:31:34 +0300 Subject: [PATCH 03/30] Added a new factory function `createReader` that uses the new heuristics detection method. --- Pcap++/header/PcapFileDevice.h | 10 ++++++++++ Pcap++/src/PcapFileDevice.cpp | 23 ++++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/Pcap++/header/PcapFileDevice.h b/Pcap++/header/PcapFileDevice.h index 6c6404b69c..7b3aa4368a 100644 --- a/Pcap++/header/PcapFileDevice.h +++ b/Pcap++/header/PcapFileDevice.h @@ -119,6 +119,16 @@ namespace pcpp /// @param[in] fileName The file name to open /// @return An instance of the reader to read the file. Notice you should free this instance when done using it static IFileReaderDevice* getReader(const std::string& fileName); + + /// @brief Creates an instance of the reader best fit to read the file. + /// + /// The factory function uses heuristics based on the file content to decide the reader. + /// If the file type is known at compile time, it is better to construct a concrete reader instance directly. + /// + /// @param[in] fileName The path to the file to open. + /// @return A unique pointer to a reader instance or nullptr if the file is not supported. + /// @throws std::runtime_error If the file could not be opened. + static std::unique_ptr createReader(const std::string& fileName); }; /// @class IFileWriterDevice diff --git a/Pcap++/src/PcapFileDevice.cpp b/Pcap++/src/PcapFileDevice.cpp index 4b208b4e93..ded7dd9def 100644 --- a/Pcap++/src/PcapFileDevice.cpp +++ b/Pcap++/src/PcapFileDevice.cpp @@ -187,7 +187,7 @@ namespace pcpp constexpr std::array zstdMagicNumbers = { 0x28'B5'2F'FD, // zstd archive magic number }; - + StreamPositionCheckpoint checkpoint(content); uint32_t magic = 0; @@ -284,6 +284,27 @@ namespace pcpp return new PcapFileReaderDevice(fileName); } + std::unique_ptr IFileReaderDevice::createReader(const std::string& fileName) + { + std::ifstream fileContent(fileName, std::ios_base::binary); + if (fileContent.fail()) + { + throw std::runtime_error("Could not open: " + fileName); + } + + switch (CaptureFileFormatDetector().detectFormat(fileContent)) + { + case CaptureFileFormat::Pcap: + return std::make_unique(fileName); + case CaptureFileFormat::PcapNG: + return std::make_unique(fileName); + case CaptureFileFormat::Snoop: + return std::make_unique(fileName); + default: + return nullptr; + } + } + uint64_t IFileReaderDevice::getFileSize() const { std::ifstream fileStream(m_FileName.c_str(), std::ifstream::ate | std::ifstream::binary); From f1e3e18353481e0ac6c5517891eeec0c8f84877a Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 12 Sep 2025 12:54:37 +0300 Subject: [PATCH 04/30] Add include. --- Pcap++/src/PcapFileDevice.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Pcap++/src/PcapFileDevice.cpp b/Pcap++/src/PcapFileDevice.cpp index ded7dd9def..63add82519 100644 --- a/Pcap++/src/PcapFileDevice.cpp +++ b/Pcap++/src/PcapFileDevice.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "PcapFileDevice.h" #include "light_pcapng_ext.h" #include "Logger.h" From 8da179001137c06449b1ed5189634cce50dcf3d5 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 12 Sep 2025 13:17:27 +0300 Subject: [PATCH 05/30] Added unit tests. --- Tests/Pcap++Test/Tests/FileTests.cpp | 69 ++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 19 deletions(-) diff --git a/Tests/Pcap++Test/Tests/FileTests.cpp b/Tests/Pcap++Test/Tests/FileTests.cpp index 5b24885b2b..5c2709f96b 100644 --- a/Tests/Pcap++Test/Tests/FileTests.cpp +++ b/Tests/Pcap++Test/Tests/FileTests.cpp @@ -754,7 +754,7 @@ PTF_TEST_CASE(TestPcapNgFileReadWriteAdv) PTF_ASSERT_EQUAL(packetCount, 161); - // ------- + // ------- IFileReaderDevice::getReader() Factory // copy the .zstd file to a similar file with .zst extension std::ifstream zstdFile(EXAMPLE2_PCAPNG_ZSTD_WRITE_PATH, std::ios::binary); @@ -763,26 +763,57 @@ PTF_TEST_CASE(TestPcapNgFileReadWriteAdv) zstdFile.close(); zstFile.close(); - pcpp::IFileReaderDevice* genericReader = pcpp::IFileReaderDevice::getReader(EXAMPLE2_PCAP_PATH); - FileReaderTeardown genericReaderTeardown1(genericReader); - PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader)); - PTF_ASSERT_NULL(dynamic_cast(genericReader)); - - genericReader = pcpp::IFileReaderDevice::getReader(EXAMPLE2_PCAPNG_PATH); - FileReaderTeardown genericReaderTeardown2(genericReader); - PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader)); - - genericReader = pcpp::IFileReaderDevice::getReader(EXAMPLE_PCAPNG_ZSTD_WRITE_PATH); - FileReaderTeardown genericReaderTeardown3(genericReader); - PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader)); - PTF_ASSERT_TRUE(genericReader->open()); + { + pcpp::IFileReaderDevice* genericReader = pcpp::IFileReaderDevice::getReader(EXAMPLE2_PCAP_PATH); + FileReaderTeardown genericReaderTeardown1(genericReader); + PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader)); + PTF_ASSERT_NULL(dynamic_cast(genericReader)); + + genericReader = pcpp::IFileReaderDevice::getReader(EXAMPLE2_PCAPNG_PATH); + FileReaderTeardown genericReaderTeardown2(genericReader); + PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader)); + + genericReader = pcpp::IFileReaderDevice::getReader(EXAMPLE_PCAPNG_ZSTD_WRITE_PATH); + FileReaderTeardown genericReaderTeardown3(genericReader); + PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader)); + PTF_ASSERT_TRUE(genericReader->open()); + + genericReader = pcpp::IFileReaderDevice::getReader(EXAMPLE2_PCAPNG_ZST_WRITE_PATH); + FileReaderTeardown genericReaderTeardown4(genericReader); + PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader)); + PTF_ASSERT_TRUE(genericReader->open()); + + genericReader->close(); + } - genericReader = pcpp::IFileReaderDevice::getReader(EXAMPLE2_PCAPNG_ZST_WRITE_PATH); - FileReaderTeardown genericReaderTeardown4(genericReader); - PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader)); - PTF_ASSERT_TRUE(genericReader->open()); + // ------- IFileReaderDevice::createReader() Factory + // TODO: Move to a separate unit test. - genericReader->close(); + { + PTF_ASSERT_RAISES(pcpp::IFileReaderDevice::createReader("BogusFile"), std::runtime_error, + "Could not open: BogusFile"); + + auto genericReader = pcpp::IFileReaderDevice::createReader(EXAMPLE2_PCAP_PATH); + PTF_ASSERT_NOT_NULL(genericReader); + PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader.get())); + genericReader->close(); + + genericReader = pcpp::IFileReaderDevice::createReader(EXAMPLE2_PCAPNG_PATH); + PTF_ASSERT_NOT_NULL(genericReader); + PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader.get())); + + genericReader = pcpp::IFileReaderDevice::createReader(EXAMPLE_PCAPNG_ZSTD_WRITE_PATH); + PTF_ASSERT_NOT_NULL(genericReader); + PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader.get())); + PTF_ASSERT_TRUE(genericReader->open()); + genericReader->close(); + + genericReader = pcpp::IFileReaderDevice::createReader(EXAMPLE2_PCAPNG_ZST_WRITE_PATH); + PTF_ASSERT_NOT_NULL(genericReader); + PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader.get())); + PTF_ASSERT_TRUE(genericReader->open()); + genericReader->close(); + } // ------- From 3ad51e24358ebdd05e53e043a467889a186eaf55 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 12 Sep 2025 13:18:52 +0300 Subject: [PATCH 06/30] Deprecated old factory function. --- Pcap++/header/PcapFileDevice.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Pcap++/header/PcapFileDevice.h b/Pcap++/header/PcapFileDevice.h index 7b3aa4368a..9cccc00906 100644 --- a/Pcap++/header/PcapFileDevice.h +++ b/Pcap++/header/PcapFileDevice.h @@ -118,6 +118,8 @@ namespace pcpp /// it returns an instance of PcapFileReaderDevice /// @param[in] fileName The file name to open /// @return An instance of the reader to read the file. Notice you should free this instance when done using it + /// @deprecated Prefer `createReader` due to selection of reader based on file content instead of extension. + PCPP_DEPRECATED("Prefer `createReader` due to selection of reader based on file content instead of extension.") static IFileReaderDevice* getReader(const std::string& fileName); /// @brief Creates an instance of the reader best fit to read the file. From 15c200001f40cec4204e6bc5b9eda816a825b0ca Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 12 Sep 2025 14:08:58 +0300 Subject: [PATCH 07/30] Add byte-swapped zstd magic number. --- Pcap++/src/PcapFileDevice.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Pcap++/src/PcapFileDevice.cpp b/Pcap++/src/PcapFileDevice.cpp index 63add82519..027e4d64a6 100644 --- a/Pcap++/src/PcapFileDevice.cpp +++ b/Pcap++/src/PcapFileDevice.cpp @@ -185,8 +185,9 @@ namespace pcpp bool isZstdArchive(std::istream& content) { - constexpr std::array zstdMagicNumbers = { + constexpr std::array zstdMagicNumbers = { 0x28'B5'2F'FD, // zstd archive magic number + 0xFD'2F'B5'28, // zstd archive magic number (byte-swapped) }; StreamPositionCheckpoint checkpoint(content); From 17af8d4d9831fba040f16d1d9377caf6974d88ac Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 12 Sep 2025 14:22:27 +0300 Subject: [PATCH 08/30] Lint --- Pcap++/src/PcapFileDevice.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Pcap++/src/PcapFileDevice.cpp b/Pcap++/src/PcapFileDevice.cpp index 027e4d64a6..4c4fda5fd9 100644 --- a/Pcap++/src/PcapFileDevice.cpp +++ b/Pcap++/src/PcapFileDevice.cpp @@ -82,7 +82,7 @@ namespace pcpp class StreamPositionCheckpoint { public: - StreamPositionCheckpoint(std::istream& stream) : m_Stream(stream), m_Pos(stream.tellg()) + explicit StreamPositionCheckpoint(std::istream& stream) : m_Stream(stream), m_Pos(stream.tellg()) {} ~StreamPositionCheckpoint() @@ -127,10 +127,10 @@ namespace pcpp bool isPcapFile(std::istream& content) { constexpr std::array pcapMagicNumbers = { - 0xa1b2c3d4, // regular pcap, microsecond-precision - 0xd4c3b2a1, // regular pcap, microsecond-precision (byte-swapped) - 0xa1b23c4d, // regular pcap, nanosecond-precision - 0x4d3cb2a1 // regular pcap, nanosecond-precision (byte-swapped) + 0xa1'b2'c3'd4, // regular pcap, microsecond-precision + 0xd4'c3'b2'a1, // regular pcap, microsecond-precision (byte-swapped) + 0xa1'b2'3c'4d, // regular pcap, nanosecond-precision + 0x4d'3c'b2'a1 // regular pcap, nanosecond-precision (byte-swapped) }; StreamPositionCheckpoint checkpoint(content); @@ -149,7 +149,7 @@ namespace pcpp bool isPcapNgFile(std::istream& content) { constexpr std::array pcapMagicNumbers = { - 0x0A0D0D0A, // pcapng magic number (palindrome) + 0x0A'0D'0D'0A, // pcapng magic number (palindrome) }; StreamPositionCheckpoint checkpoint(content); From 46418ec99f6abea7bc05083c2dc69bda5c30ec76 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 12 Sep 2025 14:27:00 +0300 Subject: [PATCH 09/30] Move enum closer to first usage. --- Pcap++/src/PcapFileDevice.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Pcap++/src/PcapFileDevice.cpp b/Pcap++/src/PcapFileDevice.cpp index 4c4fda5fd9..f3cac510ad 100644 --- a/Pcap++/src/PcapFileDevice.cpp +++ b/Pcap++/src/PcapFileDevice.cpp @@ -50,14 +50,6 @@ namespace pcpp uint32_t len; }; - enum class CaptureFileFormat - { - Unknown, - Pcap, - PcapNG, - Snoop, - }; - /// @brief Check if a stream is seekable. /// @param stream The stream to check. /// @return True if the stream supports seek operations, false otherwise. @@ -95,6 +87,14 @@ namespace pcpp std::streampos m_Pos; }; + enum class CaptureFileFormat + { + Unknown, + Pcap, + PcapNG, + Snoop, + }; + /// @brief Heuristic file format detector that scans the magic number of the file format header. class CaptureFileFormatDetector { From 3d713ab3457ad3c7012e1f79b3480b469ea664d8 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Mon, 15 Sep 2025 15:42:16 +0300 Subject: [PATCH 10/30] Added unit tests for file reader device factory. --- .pre-commit-config.yaml | 2 +- .../file_heuristics/bogus-content.pcap | 1 + .../file_heuristics/bogus-content.pcapng | 1 + .../file_heuristics/bogus-content.txt | 1 + .../file_heuristics/bogus-content.zst | 1 + .../file_heuristics/microsecs.pcap | Bin 0 -> 88 bytes .../file_heuristics/nanosecs.pcap | Bin 0 -> 88 bytes .../pcap-with-dat-ext.pcap.dat | Bin 0 -> 88 bytes .../file_heuristics/pcapng-example.pcapng | Bin 0 -> 26200 bytes .../file_heuristics/pcapng-example.pcapng.zst | Bin 0 -> 25476 bytes .../pcapng-example.pcapng.zstd | Bin 0 -> 392 bytes .../pcapng-with-pcap-ext.pcapng.pcap | Bin 0 -> 26200 bytes Tests/Pcap++Test/TestDefinition.h | 1 + Tests/Pcap++Test/Tests/FileTests.cpp | 97 ++++++++++++------ Tests/Pcap++Test/main.cpp | 1 + 15 files changed, 75 insertions(+), 30 deletions(-) create mode 100644 Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.pcap create mode 100644 Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.pcapng create mode 100644 Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.txt create mode 100644 Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.zst create mode 100644 Tests/Pcap++Test/PcapExamples/file_heuristics/microsecs.pcap create mode 100644 Tests/Pcap++Test/PcapExamples/file_heuristics/nanosecs.pcap create mode 100644 Tests/Pcap++Test/PcapExamples/file_heuristics/pcap-with-dat-ext.pcap.dat create mode 100644 Tests/Pcap++Test/PcapExamples/file_heuristics/pcapng-example.pcapng create mode 100644 Tests/Pcap++Test/PcapExamples/file_heuristics/pcapng-example.pcapng.zst create mode 100644 Tests/Pcap++Test/PcapExamples/file_heuristics/pcapng-example.pcapng.zstd create mode 100644 Tests/Pcap++Test/PcapExamples/file_heuristics/pcapng-with-pcap-ext.pcapng.pcap diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 44ef689f39..1cfa3a276c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,4 +1,4 @@ -exclude: '.*\.(pcap|pcapng|dat)|(PacketExamples|PcapExamples|expected_output|pcap_examples).*\.txt' +exclude: '.*\.(pcap|pcapng|dat)|(PacketExamples|PcapExamples|expected_output|pcap_examples).*\.(txt|zst|zstd)' fail_fast: false repos: - repo: local diff --git a/Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.pcap b/Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.pcap new file mode 100644 index 0000000000..15a8eef479 --- /dev/null +++ b/Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.pcap @@ -0,0 +1 @@ +4561d5a474d6as465d8as41d1as6531863d1as65d1a36d1 \ No newline at end of file diff --git a/Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.pcapng b/Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.pcapng new file mode 100644 index 0000000000..15a8eef479 --- /dev/null +++ b/Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.pcapng @@ -0,0 +1 @@ +4561d5a474d6as465d8as41d1as6531863d1as65d1a36d1 \ No newline at end of file diff --git a/Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.txt b/Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.txt new file mode 100644 index 0000000000..15a8eef479 --- /dev/null +++ b/Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.txt @@ -0,0 +1 @@ +4561d5a474d6as465d8as41d1as6531863d1as65d1a36d1 \ No newline at end of file diff --git a/Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.zst b/Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.zst new file mode 100644 index 0000000000..15a8eef479 --- /dev/null +++ b/Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.zst @@ -0,0 +1 @@ +4561d5a474d6as465d8as41d1as6531863d1as65d1a36d1 \ No newline at end of file diff --git a/Tests/Pcap++Test/PcapExamples/file_heuristics/microsecs.pcap b/Tests/Pcap++Test/PcapExamples/file_heuristics/microsecs.pcap new file mode 100644 index 0000000000000000000000000000000000000000..20cba6b8554ff9812e28a79384e93d779218c60e GIT binary patch literal 88 wcmca|c+)~A1{MYcU}RtfazK~~hy|dSfsu)sg_Vt+gOiJ!hnJ5ZrUsWh03HhjC;$Ke literal 0 HcmV?d00001 diff --git a/Tests/Pcap++Test/PcapExamples/file_heuristics/nanosecs.pcap b/Tests/Pcap++Test/PcapExamples/file_heuristics/nanosecs.pcap new file mode 100644 index 0000000000000000000000000000000000000000..4353706a4214b7d224e51d4589b58987743b4cee GIT binary patch literal 88 zcmeaZ*|d;}frSA97#SFW91y<1&cGl5q(PX0k%^gwm5rT)lZ%^&myaJLe+j4!mplLp C?*zmE literal 0 HcmV?d00001 diff --git a/Tests/Pcap++Test/PcapExamples/file_heuristics/pcap-with-dat-ext.pcap.dat b/Tests/Pcap++Test/PcapExamples/file_heuristics/pcap-with-dat-ext.pcap.dat new file mode 100644 index 0000000000000000000000000000000000000000..20cba6b8554ff9812e28a79384e93d779218c60e GIT binary patch literal 88 wcmca|c+)~A1{MYcU}RtfazK~~hy|dSfsu)sg_Vt+gOiJ!hnJ5ZrUsWh03HhjC;$Ke literal 0 HcmV?d00001 diff --git a/Tests/Pcap++Test/PcapExamples/file_heuristics/pcapng-example.pcapng b/Tests/Pcap++Test/PcapExamples/file_heuristics/pcapng-example.pcapng new file mode 100644 index 0000000000000000000000000000000000000000..e188daa44bb29d14a6da1b06df93a942198aa426 GIT binary patch literal 26200 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 literal 0 HcmV?d00001 diff --git a/Tests/Pcap++Test/PcapExamples/file_heuristics/pcapng-example.pcapng.zstd b/Tests/Pcap++Test/PcapExamples/file_heuristics/pcapng-example.pcapng.zstd new file mode 100644 index 0000000000000000000000000000000000000000..08d9dc3dc249d4094327270b90f4d11a45920ed3 GIT binary patch literal 392 zcmd<$<>iuLU|{gI(UxKa(*L0VBnILu0C6D@g8(N`gcHI9i?adQDNsI)ase_x7zh{{ z*ciBPJ3sgSR?orU%D`aaTE^FSAm$Y>=t=Uvqtdlu$F2np0)pI+-vc!< za&R&KJbsvk$wD7wHpzC>fbC$#wBtw&$c|guD0Y~`>}UZy89{)=K^O?o{So3^3$o+S y6RdVf2y!PcgWGW$=nr#d6=PT4&9C`8fB|}3I*|!v=o1!irbP@#fg+3yAiDwJ&02>5 literal 0 HcmV?d00001 diff --git a/Tests/Pcap++Test/PcapExamples/file_heuristics/pcapng-with-pcap-ext.pcapng.pcap b/Tests/Pcap++Test/PcapExamples/file_heuristics/pcapng-with-pcap-ext.pcapng.pcap new file mode 100644 index 0000000000000000000000000000000000000000..e188daa44bb29d14a6da1b06df93a942198aa426 GIT binary patch literal 26200 zcmb_^30w{B`~IAzq=ojRFyb2=yA|L606e8y?UG}rZ9_x0TOGtbPSs-dA8$svfqURFl%LDW-? zLsSu-0e!rKLPvzS2YK}iH1ifYd)RyU*f|SCo(@h9PIlf-_Ci}94_hAxfvr&F?d!lfc>5%g)Kx%-P=E-U}`wuyt@2d3XwaJVeg6_I4gZ zM`v$mTW66#;OOJvC35t1a1c7$dI-I}?Yw;iUiRL$_MYBCFLw`bCr2j_2cezF%TwfG z>)_zzB=WWwx;xr?J3D*%IGg>yH-g|1Iz&Kx!lYC)QFozJccHb=+C9Y6kKhx|gx93; zNzo&d%q+s=C&W&S8#!UDrJ1n1vvYT$nT2nBidjhPWV3+@V-pgmB$$nwkT~9Kl61!s zbi{_bqNbs+;U@uC<-(tFi3HISjP0VliyUP~Fa zakvBRz}T7Sn;?4ms<;tu$~A{)0twtUC8@uzuX9+8XJ&Kv?)@Vm z2rj?=KA)?iYGIW;2aj`jycSXnCf1x}D+`sFP8N!>2m-NsouRSRUvElEw#?fNcuTUi zn_?jz8!HCkp<%y-HNhDk@H1}AM)u3jw5L_F#X+hJdlG0V5MJqTv#%_TBBf+X<`# zM^1E&T9m=rZBA!U-FyU?z?z^=QH=l~~m2v78n?`Puz<4uK2w64%=#O~}pI$~s` zYxtB2;XR4*X%myjjYt@o5+U|*Pe1zJy7pg=Db!p>Kf)awx4 zmqxuLnlgG}UoxfFMvVCsIn-LPUaJwq40h)p zbcGLs)1G-b*3XD9+t;Lb=N0vpAnb~|lW|)`^N_|(q6u+3EYnxyvAVIZH>CrW^q-1S z-GY6vj~laLUpbq6)e+;X7mY#bc{te;^n||FuW0D&TEx)jaX2v?f)mN(J=-|s>+)W4 zaY1vn>ue(1_ul-{Gkca=pY#(gRs@Py-bp8j%MyX4o5VuWQKBnRC3XX^d>}vEg>WX#0FwLv5r^^X~K)}Bs?TSiM7O1(n-=v!Y8tbUW5&?hHxiZ zNVFs^B(X8PQgmqs&$2DRGpzN<2P?&*k%Y93Gd)<8ruME}qTd5Ew&QzeEe`n)8c|8;AB#Rq-th?nH)g|J!Y?lpAVz$(Tnt0baPFN3 zzwAN`@C(s{OArn`&W^i72Hk$LYOj02Sp72*se0qN`w#!o@TuH&&a!2`+n22bID%*e zdPB!iDO3S|ohwlzxaSD&X@Yw~kj_0KNat+GCY5SQ6h5{(TD8k~zCc5{W!DV9jPDv8 zj+zo7&=R(WL%e}}o{ln=xY`>TZcTXfy$kL`houagWYDAN!I3R}M~w{#viM|^l2QI_gUix?XYgv5cx-*O zJ))rV4p~bC$2~?;e8T=(AN=W@>Ar}xC|a{Blm`myQM_G_P8KNgL@Z<+Y$nR5Sqc_oM6 zFX-5f7?G@c{mj#m+37RfPUV$O+OTiUl*3C+4t#ew`|FY*!l_N09%YYt?*CtggJAGI>A{$xIK#KrT=hlhXuvY4^2u8C|FtM|3Y+%U)TCw=7+3>Uc7hVKEb8& z>mOU*pWJ2aw$eM=Rfb>7+NuP6dqDJ_?wj&bggMBqOZDCK^cUuf{;Ns7>TIeR*sWlj zefz{iY0pERoZcT%{{5$A{o4HoGqv(ImTjzwJaT`{0VDgP+DWSxT%BQh`>1CThcJn| zb8yn0iW7fm2eK%eIaL24w3%8p) zyw~=bb2??j(s;r4Ia!~bJ>!D$L(|Ys!TBwM`YWwm zvh`foHGkf#AE^AuZQ)qes-(b2Nk!$W`4V&ekBR5?58S@MfBbvir^6pg=I$O+ZKb?${ zEia!HYbp(7lma_i7#ZYQ`}Va1xa zv(x`n)oniz=cVd-dB3Lfty=+t!5@4aZ~rqn_xfOGi?8}Sv9Geaw%avKk*+xR5t6lR zIo)SzExUZSzRqbs)UweGU9r!*8+8qU@_`L&+0<9&%e%ooZp?-Nfm-M{(|)`;lvv*q*t@c~)t zKR)VoTinN_^8CE)R=3C7_^O$ziFaMuS#W082aio&OGh4O#4F|6?W}#LR{5{$;_~ES zaMgj!zjNC4?V=uHX;Z)Bp*SP8YDHGE<Ia>$k{XSE0;dyQavT;ddvbaB$)|Y{rF9dr&$3=^JJn*jf*gQe6_H+DO7~sr z)hj#d>zsYStBDM+qK{5AdUZb~BX}jP>f*lto*gyezS-zQc$ek# zcR!wVZf>hf+|Jks+1O5t+Ptcn*xHl2FQ)rK#r6ZlHdiLLsQcB%*fPh?chj+J6pS5$ zC@OM5jPal3Vqk0=$Ie~EAoa>!mp6D$e5f6SZQfHeoyj)k>AJt7zm4afkDi?B;I57* zB`v)dqa6NLlJel-(Z26DopJ8*F=*3aHDTX{Gs<Z%{OMSITj6k^A*w#UbNe}wAOu3ios@k{k5a%TDuxf5d75(WBTZgC|2*RU2L^DIpM}!}u0=(fhbD8<|_q7desstEcs0VW9txH0aX?F-U!8e^#3E zXYay~Hj6ra8duvpC1&Z4=cl5gdTw2jJI(u@b1yt8vXl6rnEO3*-@%uWg*j_9F8(LF zZIU>D&HEPVV&tH2N(S``V^a&;68esHemImUkD!K5ooL`fY}oY%m=CgL=pPp8ZxMWrl zI8T4@Cxe?#;;lVhxurML%8{e29%FvCRHO&`%bE1oe448?_E&YlU!gMolF{QW)p6A0 zy!FNVH(?()W~2PogY?&LxfpDJbwSO^u4d(x-fW$m=M&TQy1V5ZgK-}R1s>e7Ig39h zp?Jf?_JO}if93n`>Z80j_0;DWVg86CHAm;TuW<`G-|3CPRGS~cqc4S}!>l77pexl?}I1b#cn_8W4acC1k!+HZ)FZ|btF8Nc-+{Z=Oz zgXOnr7ZHQh=Zfy}5h0Hx!{cXYKQuls+_i+`ud=RikNVXuMS|)P=gdjJRm~}`ICR@@ zL7I_!g5JKg;g{C6nJuYscM!MvUHQ0v$raswrvIoYC62hV-@iKFWncR4R`2&bT36=p z7nh(O>C>ZZZL!he)4_WZW<6WgZrQ+Y>klm&P-MryZ|Y|9s^Di>%O$dY!@i!aa9O56 zPt0cqq!+f)eWm<%Fxm227x3GWM!%7Lz1XPderlj1#*v<`%ND~vZp=pIGeZ(1TrP$o zU^L`2DF&(Mnl=Ug!!)~{Sf$lE{Z!`{>#7bXwfUM?vTc!{dFk#pDthEe{yX4E-oA^kOn<|_5qwJzYV zA2R;J*elS(yz0ja1$y9Iyf=yAEEfa))u=}?Vvt?EcAzA`hs%+&4c@Ko*HnD`V4$~E zeetjGc&F7z!w=Q$RVGie8}%sp^pr`{ICC%ksz{DIl386{wr88ltx0zh^iJJbS1nHu zLA$=0&G@4Y8M|znE9H+L;E!Y(e>?%M#f|=;^HDBn{`{ZF*kw1Q;{es+Q{%F)komx{sj2D;N#k~cu;>K)b{d-#Eh8W}T%f&#y zl+gN!l@Wu~=U)DSS$<*G)1T#DnsH=Q(ydk6@w4tv9=tAlf>aaCi_`M z=Df1J?xWT+xO8OYuX!`a`n=q)t&#Ng_)N_=>xNC(z0>MX`K|F8>KdP4kOIBXpYEhT#dKe!{=9As{yfL_C-!AQW}{xTHi)sa#IpZlz{ZW) zNPo^K@*pwnu%4Vw|ecI)LfTxgV8=)CT(**7LYmp^un=k zW|1cuMb&o*`PhHy!ut+yL(cvT&ngP;5TQB$OO`YX@_{bNeT zHjCy;`R5$?CzkCWlI!+HJ#JDRKL&cdU(>l0V&lealz-Zi7(%%iEdQ*$4|;4TySijL z*PwL$wB>6uQwR1lwk-1+AmD5g?5`M~Q@CLH;)*KLKMt-PG+p+U&z@JMva#iy605si zH>J6!6&4;JP@eO3T<+GO7`@v0ZM(-QKd`>hRxP{x;?2`S-3EOh_}ZX!Qx-XP}V(aUAb!Phq`?B(Wqh7Q&h|%@Wn=Xq18#iX7{NqJp zG>kVE2FpJyUmymlmsQDvdeHR{^;j`;+s9_=p&5xGv;IY4pnuZo{Ido%e?fM2MCcc1;|rt5 z?Q#w6&<3L$+MZW{CYH#v-pw`fjm7XrL^$@wMeA@O=fj;OLZ!(tCX?>_z9s<9J z*?vLpYZ!j{MHvGzdgPw|@&xvAV>Z$+MMXY{F}_kR2KwbFK?7 zuO5GXw{iHr?P+3{$JWuliNk|V)?4NFh?qL}#rKqgo2Io&V+i^T<%)q!EV;2SaifvAONc!)`{@i^$qIeK!jg7K(A%<%0%V#us_ z^^#&30!G99bp1=jAoUdv-9BvGxgq_xEgcxtPV{`M-@YLC*!GLZ+wW`l=kq+#GV-Ln zrB2HQ8_(z@r|FMW(O$wWP+QyP`sslkmX?Wo$2?xeksXi7RbX_gx%)w1(r;5~J*0js z=mUN$VEYZZu7BC62hIzyA%^*Ng&3&0IjP4Q8iUfjfYe-zsd;l4PmDhQ4ddmAJnF5-&~`APNHq}YHfLVSBeK2dosguAQ1 zKUWK0BHGMXBC22?kJ({|p>0;;lgHf1J=iyDLGa+;nY?X*w+F==`O5MRcqHZhRzB}1 zYAMLuW)Q`DX~rLeq_exP3~BLtfUQ_lnMbr`@UE*mjJ&_k{K7rSsc7K+1NQM4lQ$k? z@rHdSZxQfTUnbRC9`6AZ?+Pw-s)^p*Vzo)g+ct*H`v#BXZK%xqt;OaISCQL{jEuT_ zdU~#Kb#+~8Wo0##d6J=_VLRBs^Nl{S1Kv6^yqO*y{zQ&PLt3fO9=$n^^oa`aUW(ie zk~01v=d-&Dx1dLjLnx2dRh>bvFtP0cyX^|LN150ypUc7SpAt!9KkkIsu>pX)g2MLc zoxAQ_+8M(MfGu|1Kw+1=e+6tSCbk1$Uth<@W{wXNz!rme9p%SMS8V`di(C;G@iTl3 zk`Nd1VSH%)ifD+J9S`u)XPwp#=6oIy054~?CdWr-*vDfHK2ugA@E9F4@;n$LOx}*b z`w7LH_E{GE0-aNAUzAs3&7ta!G^d2@mQb37s{Dhz9iIZ{`BKfYTJ_$3>`vsqy1Qb- zvr)&^(D9mI4w`l6@Wj25&pe8iEAC+X`h%mgO7oK|{FPNdCq#-hg*in@6n5>^3$i&)Xh#I* z?POy!<5k+Gg3M`|@cgxD4N{vEPriYFlTXEK*5W9Gq})@-e)vD>xDaNCHA<%&;^hc6 z|19RT=)*DGeB+Va*2H=)`YQ(Z@mPbuAgAFmI#%R)GC56XPXw+iV*8A#nZI#G)4ajZ z%ySxQ_FK78v&B)!Irr3=Y_X=6+OrQ0nq30TY*_JfAOh8j6>ByGu*E<=f-g@qzF$1~ zHgjojwq_DPQZqwN%^&Cp&d~rDHM^u1?lVB0*V*6CCnzi;m}j7CVr-xv?$6V#*C2S^ zM5a84kcfdkemq@$9W6awBP~4`4x0@+5_fazZ}BYpOp;WJvZ z%R^DKM^-G&99h^-M4);JTQeqhy$u7q$y|r9%eTUKO%0UX^(j%{7$hMt;1@2|)a1r~Y|y0#5BRaLAy@aKurU^h z&D3S}UvybYzR7q**r-e4yb`N~XRV2twqnE9Lq?dfbg|-Ed`tPCb%A_5P)3*Cz>kiZ zdr(Csq%{J!rg@2oOd5*1-1$wZQweddC{@Ru2|7%{5+cCCePOgnYzgHwJLJ!lS;>r;p-`+ zuZyJIK$D)R4NDiu&k4=wa`-R0)I37$zBt#V$NPsFFZ$}bE_@32v5toqP&JK;iM2_G z{NewzE|7zho6+UiUvx?KMQ*oxHt6!fAPIQ^KRdA|Z-Ld^W^{oZoFb#kIx2p+wxAYV zQ5gyQxXBq)!O7%G(5<#|u?=|(em3S{GA6oUc3Kx47uXQT3LL|V7v$#~6ffk1=VE*Lg#$7H;4&4U>)JJ2N*;|1T&V*0oz$L#8Gyf)1Ve-7)br}FEr znaUll$9XvBIoxZ*5e)g$$3I4wvpg<>+#Rnh9e>CduQvxan)k)9ipl`k#|;|t*7jw&ncvoOTYm$#(tz`=GwvA%*F7=hO)7+=9k9iqgTi&wbBLW1OT~y`Mh zSz~aa*RyP4-GE+Wz`mE9xZqO4IXu2VMCozw_tmenMX!WVdN3G446US zwEA?LxHVVs%~*Bj#tIWLlh4Rykn!j_ju&M#>O8=jU8 zCf9+gLn!R|S*;9`aGey^OTWVW?90Bw25eVe-TZPEHstyl9_$!pK^N)#Ic>F^`Fvvz z3-u(|X@5NjY$}H_?#~Ui)S`Dvu_1@tfEYRQI*PnCj=pJ)_o-K5JqG1`&iChTBd)*^ z_8iR)a(mCdQf|meHdkEQDa{oo^2eOIS_H;K$c+aXd zH%P*DHC$g48>;Bk-D%+M3A$cD-jPNn9Mn`B{`eRwk^9fq7n3}3ZIwP&Ft(U8yY_ee za^+GU9%Fd{YD(XwY~IXVvHuanhZroG=YZEpFQnqSoXnbF;!Ru=y!lkh8#vzrFL<)B zp)QPD#`Ynzp51>;)iXXRy9_oz^V$s5Y~psg*oML!$Ez~fhIgYisVHi0601b$>$HsN z&{idG;K-H{;`J&dih{pbyrC|vUC!2QIs6`88t)_Yo>Wvuz|XifjWyx7MIU)@rRSzp ztP^jZT+we7#`-4&fSN0Lp>BP+(%9nVv|wciF_?VpA>ZGn_#hA2F=O-eFFMX7b==0* zvEL}w&xsXc(D5~NmApT%y;=-0^x_!aYtRw(OTAu~H`CNaGTRNykiL#mN-|^5y7Qj5@v!L#?rq=gF+C z+d~~HYle3U#k&~Ce-qw($rkdh`m8dFH$9HNo?H>p8RP%wD}y(9*N>~u!JK&}_ZB>R z(j<8ih7yh>`r zU+jhVKV+=M?E7M6*jIwBA=YqTjK|!hiW1~p8unS5L7f@3nXMVqqq!9C3i)-tSS<~C z+eWf^KVBr~zL?}qQEBqQm`gW#PKWOw=s;ufh8mS5!dHn;9?1y1)2r5MtXTQ~jpqVcpKixo7jC=V7ie$D;4q z@VRhT*vH)B2A}wEOuykV+HWl0P*c7iV*8A#+0S2$c+r|M?|r%=?^s{pEpzW<8-@2i zrZJRec^SG?07LXQ~fQ~OyM)>!H8`ubDwJ)MbBLs&!j;!52a3>I@Pbyx!$ZD3#kD=^Z=gT~?w^`n5|jeIeuWWk2X8|NA;R4SWY-(PBnypMDT z&6?&jcs^r7y)DVBcOuYdJa^?u&;G~fRt``j`u{7{6geR`W;{EqRW{AFjrS^cR_&3S z-bmm^%}?p~)Iw`<4ES}V;#qsO6u7bOWgQ^TSLZ2?r!`=UfsexVmVXgDg??{}T5k!h zm9yUB3-i2E%(bs%)>~e~J|1IwACI{KE;f1VEe=p4-ch{icrrE9>B`VdPR@!KAn*JA zK{N9GI_b0a%R}M0@m{>Iebqv$8R*pqc;8@o3G#gDQ^lI?Ns(%%us%&iY?}cTHdUXV zc9Bz`0--+LK+V*l)-cy?HDDi)F*U>9+S177a zEW}PF0Gk?{_&!NQ zXVuRs@TR;l=gc1pyY}iM%o{9h$n#UJ+1Si@U7GV3pA8{>mPo~ms!#UHa_UnM=34Zb z57ZpGK4D$*g?&86^cfy=qv9%WP0U7^Q^qGq;J*_!n@*ifHzrPzRrnn{5uEtns) z$FVMHYHGG){@bWgqh=2qHf$P;H`IV2inqM6>Aa@-Sm&Qd-YLcuZz>ND9z^D0O@0#G zRMYp{{pdXWP9_h(hkZQ8j5Qu}qsYt4!;VltYWpgV^$y_OaGxM24<`*r-o+g$-qd|r zYy#XXm}4FuEpFf)jJ1`e8PtGSe|D^yK0CCQfen`-^8#aRT6I8dJ)CdL)Xhi^`pkvW z4D@;e@%Ck5Lk&m_U}H1K<_W+C>cmhb_^V03l>+kf$aw8#$19T4P&eV1sr8Xy#D}Xu z2w}a;NQw9aF;OAhFiR^uW^cwPzQB2SE{iwRfXNhZ+GkA7^4I-EGjme25luCVZG*Yg z@uieErCBfw8}fKYpkmDm_e(XS{+~&V7xj!cqbw5o%738j*pVMci22xavc+}ebDZ3` zZUk50SN{jzpC^JZdxpJHb+cA;gJ<~M)(`qf`E=QHEDd7V*)KE{{wF{9UyW@A0<(Vp z8me9+Q(}9Vg~m*gN1I0d#O<$6CspFjIDu z$SL|?b!_#6 z)X|XJ`X@Dqq;-_s?P?;fjXJocL zJdWfoWzzI-W{s1*_ll2?pC1_+IfE5{s1?&>cr$a)+uw3>5A(YYNvL-UuEWdB#dCkI(d6im`Ty zniPBNBe964>aQ|6B!X7PJSkz{q=kGgN$bmrwxA#XDkm6XM?gvo25@v?*@#beaDbT?UiS^Q-Ax z%y?FOT$g-SoYagiPzU^EbXm;sOMjE9%23$Ht*OrmufgPcTD2SHb2hdi@5|4bY-|e- zpFp4Bb4_e4e?V^6x-E?nazKADW3=70dGD%_&$%3*uw!&w7h?1RzhAT*Fv;g!bqo0D z5e{coZ{*;-yEpvL)dz{O4~$iuhJ0@+{ce#AH^|@7C2a39b-D}On$?NCudAlNvqkIl zqWAXWcH*Ww@tf5N^7(3ti#(kY+Wti+G3n*UGCJ9TPBp00(%Z5+rT_0bLC)@8s#vE2 z;MS~8-H=-~{hbC{ry9@+-ob3*r{;Bn9KMj^B2TA)c7M@{T)%L9B%@Pk dev; + + // Test existent files with correct format and extension + for (const auto& filePath : { PCAP_NANOSEC_FILE_PATH, PCAP_MICROSEC_FILE_PATH }) + { + dev = pcpp::IFileReaderDevice::createReader(filePath); + PTF_ASSERT_NOT_NULL(dev); + PTF_ASSERT_NOT_NULL(dynamic_cast(dev.get())); + PTF_ASSERT_TRUE(dev->open()); + } + + for (const auto& filePath : { PCAPNG_FILE_PATH, PCAPNG_ZST_FILE_PATH, PCAPNG_ZSTD_FILE_PATH }) + { + dev = pcpp::IFileReaderDevice::createReader(filePath); + PTF_ASSERT_NOT_NULL(dev); + PTF_ASSERT_NOT_NULL(dynamic_cast(dev.get())); + PTF_ASSERT_TRUE(dev->open()); + } + + // Test existent files with correct format but wrong extension + dev = pcpp::IFileReaderDevice::createReader(PCAPNG_AS_PCAP_FILE_PATH); + PTF_ASSERT_NOT_NULL(dev); + PTF_ASSERT_NOT_NULL(dynamic_cast(dev.get())); + PTF_ASSERT_TRUE(dev->open()); + + dev = pcpp::IFileReaderDevice::createReader(PCAP_AS_DAT_FILE_PATH); + PTF_ASSERT_NOT_NULL(dev); + PTF_ASSERT_NOT_NULL(dynamic_cast(dev.get())); + PTF_ASSERT_TRUE(dev->open()); + + // Test existent files with correct extension but bogus content + for (const auto& filePath : { PCAP_BOGUS_FILE_PATH, PCAPNG_BOGUS_FILE_PATH, PCAPNG_ZST_BOGUS_FILE_PATH }) + { + dev = pcpp::IFileReaderDevice::createReader(filePath); + PTF_ASSERT_NULL(dev); + } + + // Test existent file with wrong extension and bogus content + dev = pcpp::IFileReaderDevice::createReader(BOGUS_FILE_PATH); + PTF_ASSERT_NULL(dev); +} + PTF_TEST_CASE(TestPcapFileReadWrite) { pcpp::PcapFileReaderDevice readerDev(EXAMPLE_PCAP_PATH); @@ -786,35 +854,6 @@ PTF_TEST_CASE(TestPcapNgFileReadWriteAdv) genericReader->close(); } - // ------- IFileReaderDevice::createReader() Factory - // TODO: Move to a separate unit test. - - { - PTF_ASSERT_RAISES(pcpp::IFileReaderDevice::createReader("BogusFile"), std::runtime_error, - "Could not open: BogusFile"); - - auto genericReader = pcpp::IFileReaderDevice::createReader(EXAMPLE2_PCAP_PATH); - PTF_ASSERT_NOT_NULL(genericReader); - PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader.get())); - genericReader->close(); - - genericReader = pcpp::IFileReaderDevice::createReader(EXAMPLE2_PCAPNG_PATH); - PTF_ASSERT_NOT_NULL(genericReader); - PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader.get())); - - genericReader = pcpp::IFileReaderDevice::createReader(EXAMPLE_PCAPNG_ZSTD_WRITE_PATH); - PTF_ASSERT_NOT_NULL(genericReader); - PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader.get())); - PTF_ASSERT_TRUE(genericReader->open()); - genericReader->close(); - - genericReader = pcpp::IFileReaderDevice::createReader(EXAMPLE2_PCAPNG_ZST_WRITE_PATH); - PTF_ASSERT_NOT_NULL(genericReader); - PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader.get())); - PTF_ASSERT_TRUE(genericReader->open()); - genericReader->close(); - } - // ------- pcpp::PcapNgFileReaderDevice readerDev5(EXAMPLE2_PCAPNG_PATH); diff --git a/Tests/Pcap++Test/main.cpp b/Tests/Pcap++Test/main.cpp index f37f34b761..7e8ff520db 100644 --- a/Tests/Pcap++Test/main.cpp +++ b/Tests/Pcap++Test/main.cpp @@ -215,6 +215,7 @@ int main(int argc, char* argv[]) PTF_RUN_TEST(TestLogger, "no_network;logger"); PTF_RUN_TEST(TestLoggerMultiThread, "no_network;logger;skip_mem_leak_check"); + PTF_RUN_TEST(TestIFileReaderDeviceFactory, "no_network;pcap;pcapng;snoop"); PTF_RUN_TEST(TestPcapFileReadWrite, "no_network;pcap"); PTF_RUN_TEST(TestPcapFilePrecision, "no_network;pcap"); PTF_RUN_TEST(TestPcapSllFileReadWrite, "no_network;pcap"); From a2391ecb37b1513cf4c4bbb3bc2e8c62e8cbebc7 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Mon, 15 Sep 2025 15:58:14 +0300 Subject: [PATCH 11/30] Revert indentation. --- Tests/Pcap++Test/Tests/FileTests.cpp | 42 +++++++++++++--------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/Tests/Pcap++Test/Tests/FileTests.cpp b/Tests/Pcap++Test/Tests/FileTests.cpp index 50104e1f28..21b4531bc8 100644 --- a/Tests/Pcap++Test/Tests/FileTests.cpp +++ b/Tests/Pcap++Test/Tests/FileTests.cpp @@ -831,28 +831,26 @@ PTF_TEST_CASE(TestPcapNgFileReadWriteAdv) zstdFile.close(); zstFile.close(); - { - pcpp::IFileReaderDevice* genericReader = pcpp::IFileReaderDevice::getReader(EXAMPLE2_PCAP_PATH); - FileReaderTeardown genericReaderTeardown1(genericReader); - PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader)); - PTF_ASSERT_NULL(dynamic_cast(genericReader)); - - genericReader = pcpp::IFileReaderDevice::getReader(EXAMPLE2_PCAPNG_PATH); - FileReaderTeardown genericReaderTeardown2(genericReader); - PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader)); - - genericReader = pcpp::IFileReaderDevice::getReader(EXAMPLE_PCAPNG_ZSTD_WRITE_PATH); - FileReaderTeardown genericReaderTeardown3(genericReader); - PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader)); - PTF_ASSERT_TRUE(genericReader->open()); - - genericReader = pcpp::IFileReaderDevice::getReader(EXAMPLE2_PCAPNG_ZST_WRITE_PATH); - FileReaderTeardown genericReaderTeardown4(genericReader); - PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader)); - PTF_ASSERT_TRUE(genericReader->open()); - - genericReader->close(); - } + pcpp::IFileReaderDevice* genericReader = pcpp::IFileReaderDevice::getReader(EXAMPLE2_PCAP_PATH); + FileReaderTeardown genericReaderTeardown1(genericReader); + PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader)); + PTF_ASSERT_NULL(dynamic_cast(genericReader)); + + genericReader = pcpp::IFileReaderDevice::getReader(EXAMPLE2_PCAPNG_PATH); + FileReaderTeardown genericReaderTeardown2(genericReader); + PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader)); + + genericReader = pcpp::IFileReaderDevice::getReader(EXAMPLE_PCAPNG_ZSTD_WRITE_PATH); + FileReaderTeardown genericReaderTeardown3(genericReader); + PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader)); + PTF_ASSERT_TRUE(genericReader->open()); + + genericReader = pcpp::IFileReaderDevice::getReader(EXAMPLE2_PCAPNG_ZST_WRITE_PATH); + FileReaderTeardown genericReaderTeardown4(genericReader); + PTF_ASSERT_NOT_NULL(dynamic_cast(genericReader)); + PTF_ASSERT_TRUE(genericReader->open()); + + genericReader->close(); // ------- From ea328d7555392892f479f0fd67445a5797afb8c5 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Mon, 15 Sep 2025 16:07:57 +0300 Subject: [PATCH 12/30] Fixed StreamCheckpoint to restore original stream state. --- Pcap++/src/PcapFileDevice.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Pcap++/src/PcapFileDevice.cpp b/Pcap++/src/PcapFileDevice.cpp index f3cac510ad..857a454532 100644 --- a/Pcap++/src/PcapFileDevice.cpp +++ b/Pcap++/src/PcapFileDevice.cpp @@ -74,16 +74,19 @@ namespace pcpp class StreamPositionCheckpoint { public: - explicit StreamPositionCheckpoint(std::istream& stream) : m_Stream(stream), m_Pos(stream.tellg()) + explicit StreamPositionCheckpoint(std::istream& stream) + : m_Stream(stream), m_State(stream.rdstate()), m_Pos(stream.tellg()) {} ~StreamPositionCheckpoint() { m_Stream.seekg(m_Pos); + m_Stream.clear(m_State); } private: std::istream& m_Stream; + std::ios_base::iostate m_State; std::streampos m_Pos; }; From a83ae2bd5e701650619a127876e7b1b4302f3803 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sat, 20 Sep 2025 13:02:09 +0300 Subject: [PATCH 13/30] Moved isStreamSeekable helper to inside `CaptureFileFormatDetector`. Move it out if it needs to be reused somewhere. --- Pcap++/src/PcapFileDevice.cpp | 42 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/Pcap++/src/PcapFileDevice.cpp b/Pcap++/src/PcapFileDevice.cpp index 857a454532..7e808e3eb9 100644 --- a/Pcap++/src/PcapFileDevice.cpp +++ b/Pcap++/src/PcapFileDevice.cpp @@ -50,27 +50,6 @@ namespace pcpp uint32_t len; }; - /// @brief Check if a stream is seekable. - /// @param stream The stream to check. - /// @return True if the stream supports seek operations, false otherwise. - bool isStreamSeekable(std::istream& stream) - { - auto pos = stream.tellg(); - if (stream.fail()) - { - stream.clear(); - return false; - } - - if (stream.seekg(pos).fail()) - { - stream.clear(); - return false; - } - - return true; - } - class StreamPositionCheckpoint { public: @@ -127,6 +106,27 @@ namespace pcpp } private: + /// @brief Check if a stream is seekable. + /// @param stream The stream to check. + /// @return True if the stream supports seek operations, false otherwise. + bool isStreamSeekable(std::istream& stream) + { + auto pos = stream.tellg(); + if (stream.fail()) + { + stream.clear(); + return false; + } + + if (stream.seekg(pos).fail()) + { + stream.clear(); + return false; + } + + return true; + } + bool isPcapFile(std::istream& content) { constexpr std::array pcapMagicNumbers = { From 916e8728f6b3a2a20c16e64d874f1396537744c9 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sat, 20 Sep 2025 13:23:29 +0300 Subject: [PATCH 14/30] Added pcap magic number for Alexey Kuznetzov's modified pcap format. Libpcap supports reading this format since 0.9.1. The heuristics detection will identify such magic number as pcap and leave final support decision to the pcap backend infrastructure. --- Pcap++/src/PcapFileDevice.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Pcap++/src/PcapFileDevice.cpp b/Pcap++/src/PcapFileDevice.cpp index 7e808e3eb9..e01acd60d2 100644 --- a/Pcap++/src/PcapFileDevice.cpp +++ b/Pcap++/src/PcapFileDevice.cpp @@ -129,11 +129,18 @@ namespace pcpp bool isPcapFile(std::istream& content) { - constexpr std::array pcapMagicNumbers = { + // Pcap magic numbers are taken from: https://github.com/the-tcpdump-group/libpcap/blob/master/sf-pcap.c + // There are some other reserved magic numbers but they are not supported by libpcap so we ignore them. + constexpr std::array pcapMagicNumbers = { 0xa1'b2'c3'd4, // regular pcap, microsecond-precision 0xd4'c3'b2'a1, // regular pcap, microsecond-precision (byte-swapped) + // Libpcap 1.5.0 and later support reading nanosecond-precision pcap files. 0xa1'b2'3c'4d, // regular pcap, nanosecond-precision - 0x4d'3c'b2'a1 // regular pcap, nanosecond-precision (byte-swapped) + 0x4d'3c'b2'a1, // regular pcap, nanosecond-precision (byte-swapped) + // Libpcap 0.9.1 and later support reading a modified pcap format that contains an extended header. + // Format reference: https://wiki.wireshark.org/Development/LibpcapFileFormat#modified-pcap + 0xa1'b2'cd'34, // Alexey Kuznetzov's modified libpcap format + 0x34'cd'b2'a1 // Alexey Kuznetzov's modified libpcap format (byte-swapped) }; StreamPositionCheckpoint checkpoint(content); From 169fcd2cae60a7fa2a78ee37a350eda5f97b8b1e Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 26 Sep 2025 10:52:42 +0300 Subject: [PATCH 15/30] Split the unit test into multiple smaller tests. --- Tests/Pcap++Test/TestDefinition.h | 5 +- Tests/Pcap++Test/Tests/FileTests.cpp | 74 ++++++++++++++++++---------- Tests/Pcap++Test/main.cpp | 5 +- 3 files changed, 55 insertions(+), 29 deletions(-) diff --git a/Tests/Pcap++Test/TestDefinition.h b/Tests/Pcap++Test/TestDefinition.h index 6035dc5143..9ee1947125 100644 --- a/Tests/Pcap++Test/TestDefinition.h +++ b/Tests/Pcap++Test/TestDefinition.h @@ -20,7 +20,10 @@ PTF_TEST_CASE(TestLogger); PTF_TEST_CASE(TestLoggerMultiThread); // Implemented in FileTests.cpp -PTF_TEST_CASE(TestIFileReaderDeviceFactory); +PTF_TEST_CASE(TestIFileReaderDeviceFactory_Pcap); +PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG); +PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG_ZST); +PTF_TEST_CASE(TestIFileReaderDeviceFactory_Invalid); PTF_TEST_CASE(TestPcapFileReadWrite); PTF_TEST_CASE(TestPcapFilePrecision); PTF_TEST_CASE(TestPcapSllFileReadWrite); diff --git a/Tests/Pcap++Test/Tests/FileTests.cpp b/Tests/Pcap++Test/Tests/FileTests.cpp index 21b4531bc8..55b203bdd3 100644 --- a/Tests/Pcap++Test/Tests/FileTests.cpp +++ b/Tests/Pcap++Test/Tests/FileTests.cpp @@ -26,35 +26,16 @@ class FileReaderTeardown } }; -PTF_TEST_CASE(TestIFileReaderDeviceFactory) +PTF_TEST_CASE(TestIFileReaderDeviceFactory_Pcap) { - // These files are correctly formatted and with correct extensions + // Correct format constexpr const char* PCAP_NANOSEC_FILE_PATH = "PcapExamples/file_heuristics/nanosecs.pcap"; constexpr const char* PCAP_MICROSEC_FILE_PATH = "PcapExamples/file_heuristics/microsecs.pcap"; - constexpr const char* PCAPNG_FILE_PATH = "PcapExamples/file_heuristics/pcapng-example.pcapng"; - constexpr const char* PCAPNG_ZST_FILE_PATH = "PcapExamples/file_heuristics/pcapng-example.pcapng.zst"; - constexpr const char* PCAPNG_ZSTD_FILE_PATH = "PcapExamples/file_heuristics/pcapng-example.pcapng.zstd"; - // TODO: add snoop file - - // These files are correctly formatted but with wrong extensions - constexpr const char* PCAPNG_AS_PCAP_FILE_PATH = "PcapExamples/file_heuristics/pcapng-with-pcap-ext.pcapng.pcap"; + // Correct format, wrong exteension constexpr const char* PCAP_AS_DAT_FILE_PATH = "PcapExamples/file_heuristics/pcap-with-dat-ext.pcap.dat"; - // These files have a correct extension but are actually garbage data. - constexpr const char* PCAP_BOGUS_FILE_PATH = "PcapExamples/file_heuristics/bogus-content.pcap"; - constexpr const char* PCAPNG_BOGUS_FILE_PATH = "PcapExamples/file_heuristics/bogus-content.pcapng"; - constexpr const char* PCAPNG_ZST_BOGUS_FILE_PATH = "PcapExamples/file_heuristics/bogus-content.zst"; - - // This file has a wrong extension and is actually garbage data. - constexpr const char* BOGUS_FILE_PATH = "PcapExamples/file_heuristics/bogus-content.txt"; - - // Test non-existent file - PTF_ASSERT_RAISES(pcpp::IFileReaderDevice::createReader("BogusFile"), std::runtime_error, - "Could not open: BogusFile"); - std::unique_ptr dev; - // Test existent files with correct format and extension for (const auto& filePath : { PCAP_NANOSEC_FILE_PATH, PCAP_MICROSEC_FILE_PATH }) { dev = pcpp::IFileReaderDevice::createReader(filePath); @@ -63,7 +44,22 @@ PTF_TEST_CASE(TestIFileReaderDeviceFactory) PTF_ASSERT_TRUE(dev->open()); } - for (const auto& filePath : { PCAPNG_FILE_PATH, PCAPNG_ZST_FILE_PATH, PCAPNG_ZSTD_FILE_PATH }) + dev = pcpp::IFileReaderDevice::createReader(PCAP_AS_DAT_FILE_PATH); + PTF_ASSERT_NOT_NULL(dev); + PTF_ASSERT_NOT_NULL(dynamic_cast(dev.get())); + PTF_ASSERT_TRUE(dev->open()); +} + +PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG) +{ + // Correct format + constexpr const char* PCAPNG_FILE_PATH = "PcapExamples/file_heuristics/pcapng-example.pcapng"; + // Correct format, wrong exteension + constexpr const char* PCAPNG_AS_PCAP_FILE_PATH = "PcapExamples/file_heuristics/pcapng-with-pcap-ext.pcapng.pcap"; + + std::unique_ptr dev; + + for (const auto& filePath : { PCAPNG_FILE_PATH }) { dev = pcpp::IFileReaderDevice::createReader(filePath); PTF_ASSERT_NOT_NULL(dev); @@ -76,11 +72,35 @@ PTF_TEST_CASE(TestIFileReaderDeviceFactory) PTF_ASSERT_NOT_NULL(dev); PTF_ASSERT_NOT_NULL(dynamic_cast(dev.get())); PTF_ASSERT_TRUE(dev->open()); +} - dev = pcpp::IFileReaderDevice::createReader(PCAP_AS_DAT_FILE_PATH); - PTF_ASSERT_NOT_NULL(dev); - PTF_ASSERT_NOT_NULL(dynamic_cast(dev.get())); - PTF_ASSERT_TRUE(dev->open()); +PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG_ZST) +{ + constexpr const char* PCAPNG_ZST_FILE_PATH = "PcapExamples/file_heuristics/pcapng-example.pcapng.zst"; + constexpr const char* PCAPNG_ZSTD_FILE_PATH = "PcapExamples/file_heuristics/pcapng-example.pcapng.zstd"; + + std::unique_ptr dev; + + for (const auto& filePath : { PCAPNG_ZST_FILE_PATH, PCAPNG_ZSTD_FILE_PATH }) + { + dev = pcpp::IFileReaderDevice::createReader(filePath); + PTF_ASSERT_NOT_NULL(dev); + PTF_ASSERT_NOT_NULL(dynamic_cast(dev.get())); + PTF_ASSERT_TRUE(dev->open()); + } +} + +PTF_TEST_CASE(TestIFileReaderDeviceFactory_Invalid) +{ + // Garbage data, correct extension + constexpr const char* PCAP_BOGUS_FILE_PATH = "PcapExamples/file_heuristics/bogus-content.pcap"; + constexpr const char* PCAPNG_BOGUS_FILE_PATH = "PcapExamples/file_heuristics/bogus-content.pcapng"; + constexpr const char* PCAPNG_ZST_BOGUS_FILE_PATH = "PcapExamples/file_heuristics/bogus-content.zst"; + + // Garbage data + constexpr const char* BOGUS_FILE_PATH = "PcapExamples/file_heuristics/bogus-content.txt"; + + std::unique_ptr dev; // Test existent files with correct extension but bogus content for (const auto& filePath : { PCAP_BOGUS_FILE_PATH, PCAPNG_BOGUS_FILE_PATH, PCAPNG_ZST_BOGUS_FILE_PATH }) diff --git a/Tests/Pcap++Test/main.cpp b/Tests/Pcap++Test/main.cpp index 7e8ff520db..44c74ada69 100644 --- a/Tests/Pcap++Test/main.cpp +++ b/Tests/Pcap++Test/main.cpp @@ -215,7 +215,10 @@ int main(int argc, char* argv[]) PTF_RUN_TEST(TestLogger, "no_network;logger"); PTF_RUN_TEST(TestLoggerMultiThread, "no_network;logger;skip_mem_leak_check"); - PTF_RUN_TEST(TestIFileReaderDeviceFactory, "no_network;pcap;pcapng;snoop"); + PTF_RUN_TEST(TestIFileReaderDeviceFactory_Pcap, "no_network;pcap"); + PTF_RUN_TEST(TestIFileReaderDeviceFactory_PcapNG, "no_network;pcapng"); + PTF_RUN_TEST(TestIFileReaderDeviceFactory_PcapNG_ZST, "no_network;pcapng"); + PTF_RUN_TEST(TestIFileReaderDeviceFactory_Invalid, "no_network;"); PTF_RUN_TEST(TestPcapFileReadWrite, "no_network;pcap"); PTF_RUN_TEST(TestPcapFilePrecision, "no_network;pcap"); PTF_RUN_TEST(TestPcapSllFileReadWrite, "no_network;pcap"); From f1613c4125d5e23078d30111dff120607657e7b1 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Thu, 2 Oct 2025 19:21:07 +0300 Subject: [PATCH 16/30] Added helper to indicate if ZstSupport is enabled for PcapNg devices. --- Pcap++/CMakeLists.txt | 1 + Pcap++/header/PcapFileDevice.h | 8 ++++++ Pcap++/src/PcapFileDevice.cpp | 47 ++++++++++++++++++++++++---------- 3 files changed, 42 insertions(+), 14 deletions(-) diff --git a/Pcap++/CMakeLists.txt b/Pcap++/CMakeLists.txt index feb4bae479..2f09977929 100644 --- a/Pcap++/CMakeLists.txt +++ b/Pcap++/CMakeLists.txt @@ -102,6 +102,7 @@ target_link_libraries( ) if(LIGHT_PCAPNG_ZSTD) + target_compile_definitions(Pcap++ PRIVATE -DPCPP_PCAPNG_ZSTD_SUPPORT) target_link_libraries(Pcap++ PRIVATE light_pcapng) endif() diff --git a/Pcap++/header/PcapFileDevice.h b/Pcap++/header/PcapFileDevice.h index 0b1c93933a..e4b36c1b2d 100644 --- a/Pcap++/header/PcapFileDevice.h +++ b/Pcap++/header/PcapFileDevice.h @@ -325,6 +325,10 @@ namespace pcpp PcapNgFileReaderDevice& operator=(const PcapNgFileReaderDevice& other); public: + /// @brief A static method that checks if the device was built with zstd compression support + /// @return True if zstd compression is supported, false otherwise. + static bool isZstdSupported(); + /// A constructor for this class that gets the pcap-ng full path file name to open. Notice that after calling /// this constructor the file isn't opened yet, so reading packets will fail. For opening the file call open() /// @param[in] fileName The full path of the file to read @@ -409,6 +413,10 @@ namespace pcpp PcapNgFileWriterDevice& operator=(const PcapNgFileWriterDevice& other); public: + /// @brief A static method that checks if the device was built with zstd compression support. + /// @return True if zstd compression is supported, false otherwise. + static bool isZstdSupported(); + /// A constructor for this class that gets the pcap-ng full path file name to open for writing or create. Notice /// that after calling this constructor the file isn't opened yet, so writing packets will fail. For opening the /// file call open() diff --git a/Pcap++/src/PcapFileDevice.cpp b/Pcap++/src/PcapFileDevice.cpp index e7dafef151..4bc86e243e 100644 --- a/Pcap++/src/PcapFileDevice.cpp +++ b/Pcap++/src/PcapFileDevice.cpp @@ -1,3 +1,4 @@ +#include "PcapFileDevice.h" #define LOG_MODULE PcapLogModuleFileDevice #include @@ -214,24 +215,32 @@ namespace pcpp } }; - } // namespace + template constexpr size_t ARRAY_SIZE(T (&)[N]) + { + return N; + } - template constexpr size_t ARRAY_SIZE(T (&)[N]) - { - return N; - } + bool checkNanoSupport() + { +#ifdef PCAP_TSTAMP_PRECISION_NANO + return true; +#else + PCPP_LOG_DEBUG( + "PcapPlusPlus was compiled without nano precision support which requires libpcap > 1.5.1. Please " + "recompile PcapPlusPlus with nano precision support to use this feature. Using default microsecond precision"); + return false; +#endif + } - static bool checkNanoSupport() - { -#if defined(PCAP_TSTAMP_PRECISION_NANO) - return true; + bool checkZstdSupport() + { +#ifdef PCPP_PCAPNG_ZSTD_SUPPORT + return true; #else - PCPP_LOG_DEBUG( - "PcapPlusPlus was compiled without nano precision support which requires libpcap > 1.5.1. Please " - "recompile PcapPlusPlus with nano precision support to use this feature. Using default microsecond precision"); - return false; + return false; #endif - } + } + } // namespace // ~~~~~~~~~~~~~~~~~~~ // IFileDevice members @@ -723,6 +732,11 @@ namespace pcpp // PcapNgFileReaderDevice members // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + bool PcapNgFileReaderDevice::isZstdSupported() + { + return checkZstdSupport(); + } + PcapNgFileReaderDevice::PcapNgFileReaderDevice(const std::string& fileName) : IFileReaderDevice(fileName) { m_LightPcapNg = nullptr; @@ -893,6 +907,11 @@ namespace pcpp // PcapNgFileWriterDevice members // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + bool PcapNgFileWriterDevice::isZstdSupported() + { + return checkZstdSupport(); + } + PcapNgFileWriterDevice::PcapNgFileWriterDevice(const std::string& fileName, int compressionLevel) : IFileWriterDevice(fileName) { From bc2bacd701dcc02645f8bb769a44181f31b5e768 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Thu, 2 Oct 2025 19:22:15 +0300 Subject: [PATCH 17/30] Split pcap microsecond and nanosecond file heuristics tests. Nanoseconds are skipped if they aren't supported. --- Tests/Pcap++Test/TestDefinition.h | 3 ++- Tests/Pcap++Test/Tests/FileTests.cpp | 19 ++++++++++++++----- Tests/Pcap++Test/main.cpp | 3 ++- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Tests/Pcap++Test/TestDefinition.h b/Tests/Pcap++Test/TestDefinition.h index 7bcad1fc8e..dbd3d8b95e 100644 --- a/Tests/Pcap++Test/TestDefinition.h +++ b/Tests/Pcap++Test/TestDefinition.h @@ -20,7 +20,8 @@ PTF_TEST_CASE(TestLogger); PTF_TEST_CASE(TestLoggerMultiThread); // Implemented in FileTests.cpp -PTF_TEST_CASE(TestIFileReaderDeviceFactory_Pcap); +PTF_TEST_CASE(TestIFileReaderDeviceFactory_Pcap_MicroPrecision); +PTF_TEST_CASE(TestIFileReaderDeviceFactory_Pcap_NanoPrecision); PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG); PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG_ZST); PTF_TEST_CASE(TestIFileReaderDeviceFactory_Invalid); diff --git a/Tests/Pcap++Test/Tests/FileTests.cpp b/Tests/Pcap++Test/Tests/FileTests.cpp index c45681d878..10e5ab6d60 100644 --- a/Tests/Pcap++Test/Tests/FileTests.cpp +++ b/Tests/Pcap++Test/Tests/FileTests.cpp @@ -26,25 +26,34 @@ class FileReaderTeardown } }; -PTF_TEST_CASE(TestIFileReaderDeviceFactory_Pcap) +PTF_TEST_CASE(TestIFileReaderDeviceFactory_Pcap_MicroPrecision) { // Correct format - constexpr const char* PCAP_NANOSEC_FILE_PATH = "PcapExamples/file_heuristics/nanosecs.pcap"; constexpr const char* PCAP_MICROSEC_FILE_PATH = "PcapExamples/file_heuristics/microsecs.pcap"; - // Correct format, wrong exteension + // Correct format, wrong exteension, microsecond precision constexpr const char* PCAP_AS_DAT_FILE_PATH = "PcapExamples/file_heuristics/pcap-with-dat-ext.pcap.dat"; std::unique_ptr dev; - for (const auto& filePath : { PCAP_NANOSEC_FILE_PATH, PCAP_MICROSEC_FILE_PATH }) + for (const auto& filePath : { PCAP_MICROSEC_FILE_PATH, PCAP_AS_DAT_FILE_PATH }) { dev = pcpp::IFileReaderDevice::createReader(filePath); PTF_ASSERT_NOT_NULL(dev); PTF_ASSERT_NOT_NULL(dynamic_cast(dev.get())); PTF_ASSERT_TRUE(dev->open()); } +} + +PTF_TEST_CASE(TestIFileReaderDeviceFactory_Pcap_NanoPrecision) +{ + if (!pcpp::PcapFileReaderDevice::isNanoSecondPrecisionSupported()) + { + PTF_SKIP_TEST("Nano-second precision is not supported in this platform/environment"); + } + + constexpr const char* PCAP_NANOSEC_FILE_PATH = "PcapExamples/file_heuristics/nanosecs.pcap"; - dev = pcpp::IFileReaderDevice::createReader(PCAP_AS_DAT_FILE_PATH); + auto dev = pcpp::IFileReaderDevice::createReader(PCAP_NANOSEC_FILE_PATH); PTF_ASSERT_NOT_NULL(dev); PTF_ASSERT_NOT_NULL(dynamic_cast(dev.get())); PTF_ASSERT_TRUE(dev->open()); diff --git a/Tests/Pcap++Test/main.cpp b/Tests/Pcap++Test/main.cpp index 0944667880..a82af2ffa4 100644 --- a/Tests/Pcap++Test/main.cpp +++ b/Tests/Pcap++Test/main.cpp @@ -215,7 +215,8 @@ int main(int argc, char* argv[]) PTF_RUN_TEST(TestLogger, "no_network;logger"); PTF_RUN_TEST(TestLoggerMultiThread, "no_network;logger;skip_mem_leak_check"); - PTF_RUN_TEST(TestIFileReaderDeviceFactory_Pcap, "no_network;pcap"); + PTF_RUN_TEST(TestIFileReaderDeviceFactory_Pcap_MicroPrecision, "no_network;pcap"); + PTF_RUN_TEST(TestIFileReaderDeviceFactory_Pcap_NanoPrecision, "no_network;pcap"); PTF_RUN_TEST(TestIFileReaderDeviceFactory_PcapNG, "no_network;pcapng"); PTF_RUN_TEST(TestIFileReaderDeviceFactory_PcapNG_ZST, "no_network;pcapng"); PTF_RUN_TEST(TestIFileReaderDeviceFactory_Invalid, "no_network;"); From 58ac45de32c67db462a5837943eb72bbdcdd500e Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Thu, 2 Oct 2025 19:23:15 +0300 Subject: [PATCH 18/30] Skipping Zst test case if zst is not supported. --- Tests/Pcap++Test/Tests/FileTests.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Tests/Pcap++Test/Tests/FileTests.cpp b/Tests/Pcap++Test/Tests/FileTests.cpp index 10e5ab6d60..cd31bc9c9f 100644 --- a/Tests/Pcap++Test/Tests/FileTests.cpp +++ b/Tests/Pcap++Test/Tests/FileTests.cpp @@ -85,6 +85,11 @@ PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG) PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG_ZST) { + if (!pcpp::PcapNgFileReaderDevice::isZstdSupported()) + { + PTF_SKIP_TEST("Zstandard compression is not supported in this platform/environment"); + } + constexpr const char* PCAPNG_ZST_FILE_PATH = "PcapExamples/file_heuristics/pcapng-example.pcapng.zst"; constexpr const char* PCAPNG_ZSTD_FILE_PATH = "PcapExamples/file_heuristics/pcapng-example.pcapng.zstd"; From 3b4b5ad1014905f76b900f5d46105bd705d3c453 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Thu, 2 Oct 2025 19:34:56 +0300 Subject: [PATCH 19/30] Due to file heuristics returning PcapNG format on Zstd archive, if Zstd compression is unsupported, the format detector will return Unknown. --- Pcap++/src/PcapFileDevice.cpp | 45 ++++++++++++++-------------- Tests/Pcap++Test/TestDefinition.h | 1 + Tests/Pcap++Test/Tests/FileTests.cpp | 17 +++++++++++ Tests/Pcap++Test/main.cpp | 1 + 4 files changed, 42 insertions(+), 22 deletions(-) diff --git a/Pcap++/src/PcapFileDevice.cpp b/Pcap++/src/PcapFileDevice.cpp index 4bc86e243e..97d88f2ab3 100644 --- a/Pcap++/src/PcapFileDevice.cpp +++ b/Pcap++/src/PcapFileDevice.cpp @@ -17,6 +17,27 @@ namespace pcpp { namespace { + bool checkNanoSupport() + { +#ifdef PCAP_TSTAMP_PRECISION_NANO + return true; +#else + PCPP_LOG_DEBUG( + "PcapPlusPlus was compiled without nano precision support which requires libpcap > 1.5.1. Please " + "recompile PcapPlusPlus with nano precision support to use this feature. Using default microsecond precision"); + return false; +#endif + } + + bool checkZstdSupport() + { +#ifdef PCPP_PCAPNG_ZSTD_SUPPORT + return true; +#else + return false; +#endif + } + /// @brief Converts a light_pcapng_t* to an opaque LightPcapNgHandle*. /// @param pcapngHandle The light_pcapng_t* to convert. /// @return An pointer to the opaque handle. @@ -98,7 +119,8 @@ namespace pcpp return CaptureFileFormat::Pcap; // PcapNG backend can support ZstdCompressed Pcap files, so we assume an archive is compressed PcapNG. - if (isPcapNgFile(content) || isZstdArchive(content)) + // If Zstd is not supported, we cannot read the file anyway, so we return Unknown. + if (isPcapNgFile(content) || (checkZstdSupport() && isZstdArchive(content))) return CaptureFileFormat::PcapNG; if (isSnoopFile(content)) @@ -219,27 +241,6 @@ namespace pcpp { return N; } - - bool checkNanoSupport() - { -#ifdef PCAP_TSTAMP_PRECISION_NANO - return true; -#else - PCPP_LOG_DEBUG( - "PcapPlusPlus was compiled without nano precision support which requires libpcap > 1.5.1. Please " - "recompile PcapPlusPlus with nano precision support to use this feature. Using default microsecond precision"); - return false; -#endif - } - - bool checkZstdSupport() - { -#ifdef PCPP_PCAPNG_ZSTD_SUPPORT - return true; -#else - return false; -#endif - } } // namespace // ~~~~~~~~~~~~~~~~~~~ diff --git a/Tests/Pcap++Test/TestDefinition.h b/Tests/Pcap++Test/TestDefinition.h index dbd3d8b95e..b62beec4fc 100644 --- a/Tests/Pcap++Test/TestDefinition.h +++ b/Tests/Pcap++Test/TestDefinition.h @@ -24,6 +24,7 @@ PTF_TEST_CASE(TestIFileReaderDeviceFactory_Pcap_MicroPrecision); PTF_TEST_CASE(TestIFileReaderDeviceFactory_Pcap_NanoPrecision); PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG); PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG_ZST); +PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG_ZST_Unsupported); PTF_TEST_CASE(TestIFileReaderDeviceFactory_Invalid); PTF_TEST_CASE(TestPcapFileReadWrite); PTF_TEST_CASE(TestPcapFileMicroPrecision); diff --git a/Tests/Pcap++Test/Tests/FileTests.cpp b/Tests/Pcap++Test/Tests/FileTests.cpp index cd31bc9c9f..6c386b93e4 100644 --- a/Tests/Pcap++Test/Tests/FileTests.cpp +++ b/Tests/Pcap++Test/Tests/FileTests.cpp @@ -104,6 +104,23 @@ PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG_ZST) } } +PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG_ZST_Unsupported) +{ + if (pcpp::PcapNgFileReaderDevice::isZstdSupported()) + { + PTF_SKIP_TEST("Zstandard compression is supported in this platform/environment"); + } + + constexpr const char* PCAPNG_ZST_FILE_PATH = "PcapExamples/file_heuristics/pcapng-example.pcapng.zst"; + constexpr const char* PCAPNG_ZSTD_FILE_PATH = "PcapExamples/file_heuristics/pcapng-example.pcapng.zstd"; + std::unique_ptr dev; + for (const auto& filePath : { PCAPNG_ZST_FILE_PATH, PCAPNG_ZSTD_FILE_PATH }) + { + dev = pcpp::IFileReaderDevice::createReader(filePath); + PTF_ASSERT_NULL(dev); + } +} + PTF_TEST_CASE(TestIFileReaderDeviceFactory_Invalid) { // Garbage data, correct extension diff --git a/Tests/Pcap++Test/main.cpp b/Tests/Pcap++Test/main.cpp index a82af2ffa4..52d3e63737 100644 --- a/Tests/Pcap++Test/main.cpp +++ b/Tests/Pcap++Test/main.cpp @@ -219,6 +219,7 @@ int main(int argc, char* argv[]) PTF_RUN_TEST(TestIFileReaderDeviceFactory_Pcap_NanoPrecision, "no_network;pcap"); PTF_RUN_TEST(TestIFileReaderDeviceFactory_PcapNG, "no_network;pcapng"); PTF_RUN_TEST(TestIFileReaderDeviceFactory_PcapNG_ZST, "no_network;pcapng"); + PTF_RUN_TEST(TestIFileReaderDeviceFactory_PcapNG_ZST_Unsupported, "no_network;pcapng"); PTF_RUN_TEST(TestIFileReaderDeviceFactory_Invalid, "no_network;"); PTF_RUN_TEST(TestPcapFileReadWrite, "no_network;pcap"); PTF_RUN_TEST(TestPcapFileMicroPrecision, "no_network;pcap"); From 18379b4b55ae9f1146fb1723e84e3f853d5d76af Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Thu, 2 Oct 2025 19:36:18 +0300 Subject: [PATCH 20/30] Lint --- Pcap++/header/PcapFileDevice.h | 2 +- Tests/Pcap++Test/Tests/FileTests.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Pcap++/header/PcapFileDevice.h b/Pcap++/header/PcapFileDevice.h index e4b36c1b2d..3160aa9aff 100644 --- a/Pcap++/header/PcapFileDevice.h +++ b/Pcap++/header/PcapFileDevice.h @@ -326,7 +326,7 @@ namespace pcpp public: /// @brief A static method that checks if the device was built with zstd compression support - /// @return True if zstd compression is supported, false otherwise. + /// @return True if zstd compression is supported, false otherwise. static bool isZstdSupported(); /// A constructor for this class that gets the pcap-ng full path file name to open. Notice that after calling diff --git a/Tests/Pcap++Test/Tests/FileTests.cpp b/Tests/Pcap++Test/Tests/FileTests.cpp index 6c386b93e4..eaa7d77a36 100644 --- a/Tests/Pcap++Test/Tests/FileTests.cpp +++ b/Tests/Pcap++Test/Tests/FileTests.cpp @@ -110,7 +110,7 @@ PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG_ZST_Unsupported) { PTF_SKIP_TEST("Zstandard compression is supported in this platform/environment"); } - + constexpr const char* PCAPNG_ZST_FILE_PATH = "PcapExamples/file_heuristics/pcapng-example.pcapng.zst"; constexpr const char* PCAPNG_ZSTD_FILE_PATH = "PcapExamples/file_heuristics/pcapng-example.pcapng.zstd"; std::unique_ptr dev; From 8a4f6f81ed6f6b6b9c2e8c245bac30ff9a0bbdd1 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Thu, 2 Oct 2025 19:36:37 +0300 Subject: [PATCH 21/30] Added invalid device factory to pcap tag. --- Tests/Pcap++Test/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Pcap++Test/main.cpp b/Tests/Pcap++Test/main.cpp index 52d3e63737..7b04d05cba 100644 --- a/Tests/Pcap++Test/main.cpp +++ b/Tests/Pcap++Test/main.cpp @@ -220,7 +220,7 @@ int main(int argc, char* argv[]) PTF_RUN_TEST(TestIFileReaderDeviceFactory_PcapNG, "no_network;pcapng"); PTF_RUN_TEST(TestIFileReaderDeviceFactory_PcapNG_ZST, "no_network;pcapng"); PTF_RUN_TEST(TestIFileReaderDeviceFactory_PcapNG_ZST_Unsupported, "no_network;pcapng"); - PTF_RUN_TEST(TestIFileReaderDeviceFactory_Invalid, "no_network;"); + PTF_RUN_TEST(TestIFileReaderDeviceFactory_Invalid, "no_network;pcap"); PTF_RUN_TEST(TestPcapFileReadWrite, "no_network;pcap"); PTF_RUN_TEST(TestPcapFileMicroPrecision, "no_network;pcap"); PTF_RUN_TEST(TestPcapFileNanoPrecision, "no_network;pcap"); From 7776e0ebd4fb7f498180728155ab678c096746e6 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Thu, 2 Oct 2025 19:58:21 +0300 Subject: [PATCH 22/30] Updated static zst archives to be actual archives. --- .../file_heuristics/pcapng-example.pcapng.zst | Bin 25476 -> 11345 bytes .../pcapng-example.pcapng.zstd | Bin 392 -> 11345 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Tests/Pcap++Test/PcapExamples/file_heuristics/pcapng-example.pcapng.zst b/Tests/Pcap++Test/PcapExamples/file_heuristics/pcapng-example.pcapng.zst index 6cf7e2654a6ec4d222a10fcba2ac42c4b99056d8..76b195f97f14bbbf66da4a9132f825753b1d5991 100644 GIT binary patch literal 11345 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 diff --git a/Tests/Pcap++Test/PcapExamples/file_heuristics/pcapng-example.pcapng.zstd b/Tests/Pcap++Test/PcapExamples/file_heuristics/pcapng-example.pcapng.zstd index 08d9dc3dc249d4094327270b90f4d11a45920ed3..76b195f97f14bbbf66da4a9132f825753b1d5991 100644 GIT binary patch literal 11345 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 From 4f52f59a948b6a24beacc26ef0413e351c40c4ef Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 3 Oct 2025 11:22:10 +0300 Subject: [PATCH 23/30] Centralized PTF test name width under a macro. --- Tests/PcppTestFramework/PcppTestFramework.h | 8 ++++---- Tests/PcppTestFramework/PcppTestFrameworkCommon.h | 4 ++++ Tests/PcppTestFramework/PcppTestFrameworkRun.h | 8 ++++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Tests/PcppTestFramework/PcppTestFramework.h b/Tests/PcppTestFramework/PcppTestFramework.h index 12defe2175..467ac8e5ba 100644 --- a/Tests/PcppTestFramework/PcppTestFramework.h +++ b/Tests/PcppTestFramework/PcppTestFramework.h @@ -34,8 +34,8 @@ std::cout << std::endl #define PTF_PRINT_ASSERTION(severity, op) \ - std::cout << std::left << std::setw(35) << __FUNCTION__ << ": " << severity << " (" << __FILE__ << ":" << __LINE__ \ - << "). " \ + std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << __FUNCTION__ << ": " << severity << " (" << __FILE__ \ + << ":" << __LINE__ << "). " \ << "Assert " << op << " failed:" << std::endl #define PTF_PRINT_COMPARE_ASSERTION(severity, op, actualExp, actualVal, expectedExp, expectedVal, objType) \ @@ -274,7 +274,7 @@ #define PTF_PRINT_VERBOSE(data) \ if (printVerbose) \ { \ - std::cout << std::left << std::setw(35) << __FUNCTION__ << ": " \ + std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << __FUNCTION__ << ": " \ << "[VERBOSE] " << data << std::endl; \ } @@ -282,7 +282,7 @@ { \ if (showSkipped) \ { \ - std::cout << std::left << std::setw(35) << __FUNCTION__ << ": " \ + std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << __FUNCTION__ << ": " \ << "SKIPPED (" << why << ")" << std::endl; \ } \ ptfResult = PTF_RESULT_SKIPPED; \ diff --git a/Tests/PcppTestFramework/PcppTestFrameworkCommon.h b/Tests/PcppTestFramework/PcppTestFrameworkCommon.h index e0bad8494e..99bc694b68 100644 --- a/Tests/PcppTestFramework/PcppTestFrameworkCommon.h +++ b/Tests/PcppTestFramework/PcppTestFrameworkCommon.h @@ -3,3 +3,7 @@ #define PTF_RESULT_PASSED 1 #define PTF_RESULT_FAILED 0 #define PTF_RESULT_SKIPPED -1 + +#ifndef PTF_TESTNAME_WIDTH +# define PTF_TESTNAME_WIDTH 35 +#endif // !PTF_TESTNAME_WIDTH diff --git a/Tests/PcppTestFramework/PcppTestFrameworkRun.h b/Tests/PcppTestFramework/PcppTestFrameworkRun.h index bd5cc0d20d..d6a2a64978 100644 --- a/Tests/PcppTestFramework/PcppTestFrameworkRun.h +++ b/Tests/PcppTestFramework/PcppTestFrameworkRun.h @@ -62,7 +62,7 @@ static bool __ptfCheckTags(const std::string& tagSet, const std::string& tagSetT { \ if (showSkippedTests) \ { \ - std::cout << std::left << std::setw(35) << #TestName << ": SKIPPED (tags don't match)" << std::endl; \ + std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << #TestName << ": SKIPPED (tags don't match)" << std::endl; \ } \ TestName##_result = PTF_RESULT_SKIPPED; \ } \ @@ -82,7 +82,7 @@ static bool __ptfCheckTags(const std::string& tagSet, const std::string& tagSetT catch (std::exception const& e) \ { \ TestName##_result = PTF_RESULT_FAILED; \ - std::cout << std::left << std::setw(35) << #TestName << ": FAILED. Unhandled exception occurred! " \ + std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << #TestName << ": FAILED. Unhandled exception occurred! " \ << "Exception: " << e.what() << std::endl; \ } \ if (runMemLeakCheck) \ @@ -100,14 +100,14 @@ static bool __ptfCheckTags(const std::string& tagSet, const std::string& tagSetT if (memLeakCount > 0 || memLeakSize > 0) \ { \ TestName##_result = PTF_RESULT_FAILED; \ - std::cout << std::left << std::setw(35) << #TestName << ": FAILED. Memory leak found! " \ + std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << #TestName << ": FAILED. Memory leak found! " \ << memLeakCount << " objects and " << memLeakSize << "[bytes] leaked" << std::endl; \ } \ } \ } \ if (TestName##_result == PTF_RESULT_PASSED) \ { \ - std::cout << std::left << std::setw(35) << #TestName << ": PASSED" << std::endl; \ + std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << #TestName << ": PASSED" << std::endl; \ } \ } \ if (TestName##_result == PTF_RESULT_PASSED) \ From 88ebfffe3231fc4029b5f0e13846442128d0b755 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 3 Oct 2025 11:28:12 +0300 Subject: [PATCH 24/30] Add Pcap++Test header files to test sources for IDE tooling. --- Tests/Pcap++Test/CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Tests/Pcap++Test/CMakeLists.txt b/Tests/Pcap++Test/CMakeLists.txt index 1727a4d15b..9d11744820 100644 --- a/Tests/Pcap++Test/CMakeLists.txt +++ b/Tests/Pcap++Test/CMakeLists.txt @@ -19,6 +19,14 @@ add_executable( Tests/XdpTests.cpp ) +# Added as source files for IDEs +target_sources(Pcap++Test PRIVATE + Common/GlobalTestArgs.h + Common/PcapFileNamesDef.h + Common/TestUtils.h + TestDefinition.h +) + target_link_libraries(Pcap++Test PUBLIC memplumber Pcap++ PcppTestFramework EndianPortable) if(MSVC) From 41fe18845a271c40f1f1347e23cba87d2f96e793 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 3 Oct 2025 11:31:06 +0300 Subject: [PATCH 25/30] Fixed test output formatting. --- Tests/Pcap++Test/TestDefinition.h | 12 ++++++------ Tests/Pcap++Test/Tests/FileTests.cpp | 12 ++++++------ Tests/Pcap++Test/main.cpp | 12 ++++++------ Tests/PcppTestFramework/PcppTestFrameworkCommon.h | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Tests/Pcap++Test/TestDefinition.h b/Tests/Pcap++Test/TestDefinition.h index b62beec4fc..6257f1b5eb 100644 --- a/Tests/Pcap++Test/TestDefinition.h +++ b/Tests/Pcap++Test/TestDefinition.h @@ -20,12 +20,12 @@ PTF_TEST_CASE(TestLogger); PTF_TEST_CASE(TestLoggerMultiThread); // Implemented in FileTests.cpp -PTF_TEST_CASE(TestIFileReaderDeviceFactory_Pcap_MicroPrecision); -PTF_TEST_CASE(TestIFileReaderDeviceFactory_Pcap_NanoPrecision); -PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG); -PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG_ZST); -PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG_ZST_Unsupported); -PTF_TEST_CASE(TestIFileReaderDeviceFactory_Invalid); +PTF_TEST_CASE(TestFileDeviceFactory_Pcap_MicroPrecision); +PTF_TEST_CASE(TestFileDeviceFactory_Pcap_NanoPrecision); +PTF_TEST_CASE(TestFileDeviceFactory_PcapNG); +PTF_TEST_CASE(TestFileDeviceFactory_PcapNG_ZST); +PTF_TEST_CASE(TestFileDeviceFactory_PcapNG_ZST_Unsupported); +PTF_TEST_CASE(TestFileDeviceFactory_Invalid); PTF_TEST_CASE(TestPcapFileReadWrite); PTF_TEST_CASE(TestPcapFileMicroPrecision); PTF_TEST_CASE(TestPcapFileNanoPrecision); diff --git a/Tests/Pcap++Test/Tests/FileTests.cpp b/Tests/Pcap++Test/Tests/FileTests.cpp index eaa7d77a36..5d43b49a37 100644 --- a/Tests/Pcap++Test/Tests/FileTests.cpp +++ b/Tests/Pcap++Test/Tests/FileTests.cpp @@ -26,7 +26,7 @@ class FileReaderTeardown } }; -PTF_TEST_CASE(TestIFileReaderDeviceFactory_Pcap_MicroPrecision) +PTF_TEST_CASE(TestFileDeviceFactory_Pcap_MicroPrecision) { // Correct format constexpr const char* PCAP_MICROSEC_FILE_PATH = "PcapExamples/file_heuristics/microsecs.pcap"; @@ -44,7 +44,7 @@ PTF_TEST_CASE(TestIFileReaderDeviceFactory_Pcap_MicroPrecision) } } -PTF_TEST_CASE(TestIFileReaderDeviceFactory_Pcap_NanoPrecision) +PTF_TEST_CASE(TestFileDeviceFactory_Pcap_NanoPrecision) { if (!pcpp::PcapFileReaderDevice::isNanoSecondPrecisionSupported()) { @@ -59,7 +59,7 @@ PTF_TEST_CASE(TestIFileReaderDeviceFactory_Pcap_NanoPrecision) PTF_ASSERT_TRUE(dev->open()); } -PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG) +PTF_TEST_CASE(TestFileDeviceFactory_PcapNG) { // Correct format constexpr const char* PCAPNG_FILE_PATH = "PcapExamples/file_heuristics/pcapng-example.pcapng"; @@ -83,7 +83,7 @@ PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG) PTF_ASSERT_TRUE(dev->open()); } -PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG_ZST) +PTF_TEST_CASE(TestFileDeviceFactory_PcapNG_ZST) { if (!pcpp::PcapNgFileReaderDevice::isZstdSupported()) { @@ -104,7 +104,7 @@ PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG_ZST) } } -PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG_ZST_Unsupported) +PTF_TEST_CASE(TestFileDeviceFactory_PcapNG_ZST_Unsupported) { if (pcpp::PcapNgFileReaderDevice::isZstdSupported()) { @@ -121,7 +121,7 @@ PTF_TEST_CASE(TestIFileReaderDeviceFactory_PcapNG_ZST_Unsupported) } } -PTF_TEST_CASE(TestIFileReaderDeviceFactory_Invalid) +PTF_TEST_CASE(TestFileDeviceFactory_Invalid) { // Garbage data, correct extension constexpr const char* PCAP_BOGUS_FILE_PATH = "PcapExamples/file_heuristics/bogus-content.pcap"; diff --git a/Tests/Pcap++Test/main.cpp b/Tests/Pcap++Test/main.cpp index 7b04d05cba..7bdde339a7 100644 --- a/Tests/Pcap++Test/main.cpp +++ b/Tests/Pcap++Test/main.cpp @@ -215,12 +215,12 @@ int main(int argc, char* argv[]) PTF_RUN_TEST(TestLogger, "no_network;logger"); PTF_RUN_TEST(TestLoggerMultiThread, "no_network;logger;skip_mem_leak_check"); - PTF_RUN_TEST(TestIFileReaderDeviceFactory_Pcap_MicroPrecision, "no_network;pcap"); - PTF_RUN_TEST(TestIFileReaderDeviceFactory_Pcap_NanoPrecision, "no_network;pcap"); - PTF_RUN_TEST(TestIFileReaderDeviceFactory_PcapNG, "no_network;pcapng"); - PTF_RUN_TEST(TestIFileReaderDeviceFactory_PcapNG_ZST, "no_network;pcapng"); - PTF_RUN_TEST(TestIFileReaderDeviceFactory_PcapNG_ZST_Unsupported, "no_network;pcapng"); - PTF_RUN_TEST(TestIFileReaderDeviceFactory_Invalid, "no_network;pcap"); + PTF_RUN_TEST(TestFileDeviceFactory_Pcap_MicroPrecision, "no_network;pcap"); + PTF_RUN_TEST(TestFileDeviceFactory_Pcap_NanoPrecision, "no_network;pcap"); + PTF_RUN_TEST(TestFileDeviceFactory_PcapNG, "no_network;pcapng"); + PTF_RUN_TEST(TestFileDeviceFactory_PcapNG_ZST, "no_network;pcapng"); + PTF_RUN_TEST(TestFileDeviceFactory_PcapNG_ZST_Unsupported, "no_network;pcapng"); + PTF_RUN_TEST(TestFileDeviceFactory_Invalid, "no_network;pcap"); PTF_RUN_TEST(TestPcapFileReadWrite, "no_network;pcap"); PTF_RUN_TEST(TestPcapFileMicroPrecision, "no_network;pcap"); PTF_RUN_TEST(TestPcapFileNanoPrecision, "no_network;pcap"); diff --git a/Tests/PcppTestFramework/PcppTestFrameworkCommon.h b/Tests/PcppTestFramework/PcppTestFrameworkCommon.h index 99bc694b68..8851aa6f28 100644 --- a/Tests/PcppTestFramework/PcppTestFrameworkCommon.h +++ b/Tests/PcppTestFramework/PcppTestFrameworkCommon.h @@ -5,5 +5,5 @@ #define PTF_RESULT_SKIPPED -1 #ifndef PTF_TESTNAME_WIDTH -# define PTF_TESTNAME_WIDTH 35 +# define PTF_TESTNAME_WIDTH 45 #endif // !PTF_TESTNAME_WIDTH From c8ae4f84fedf2d18bcdb10b6661e14686b5361cb Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 3 Oct 2025 11:33:08 +0300 Subject: [PATCH 26/30] Lint --- Tests/PcppTestFramework/PcppTestFramework.h | 6 +++--- Tests/PcppTestFramework/PcppTestFrameworkRun.h | 13 ++++++++----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Tests/PcppTestFramework/PcppTestFramework.h b/Tests/PcppTestFramework/PcppTestFramework.h index 467ac8e5ba..6f62cdd20f 100644 --- a/Tests/PcppTestFramework/PcppTestFramework.h +++ b/Tests/PcppTestFramework/PcppTestFramework.h @@ -34,7 +34,7 @@ std::cout << std::endl #define PTF_PRINT_ASSERTION(severity, op) \ - std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << __FUNCTION__ << ": " << severity << " (" << __FILE__ \ + std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << __FUNCTION__ << ": " << severity << " (" << __FILE__ \ << ":" << __LINE__ << "). " \ << "Assert " << op << " failed:" << std::endl @@ -274,7 +274,7 @@ #define PTF_PRINT_VERBOSE(data) \ if (printVerbose) \ { \ - std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << __FUNCTION__ << ": " \ + std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << __FUNCTION__ << ": " \ << "[VERBOSE] " << data << std::endl; \ } @@ -282,7 +282,7 @@ { \ if (showSkipped) \ { \ - std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << __FUNCTION__ << ": " \ + std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << __FUNCTION__ << ": " \ << "SKIPPED (" << why << ")" << std::endl; \ } \ ptfResult = PTF_RESULT_SKIPPED; \ diff --git a/Tests/PcppTestFramework/PcppTestFrameworkRun.h b/Tests/PcppTestFramework/PcppTestFrameworkRun.h index d6a2a64978..e3f5f8244f 100644 --- a/Tests/PcppTestFramework/PcppTestFrameworkRun.h +++ b/Tests/PcppTestFramework/PcppTestFrameworkRun.h @@ -62,7 +62,8 @@ static bool __ptfCheckTags(const std::string& tagSet, const std::string& tagSetT { \ if (showSkippedTests) \ { \ - std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << #TestName << ": SKIPPED (tags don't match)" << std::endl; \ + std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << #TestName << ": SKIPPED (tags don't match)" \ + << std::endl; \ } \ TestName##_result = PTF_RESULT_SKIPPED; \ } \ @@ -82,7 +83,8 @@ static bool __ptfCheckTags(const std::string& tagSet, const std::string& tagSetT catch (std::exception const& e) \ { \ TestName##_result = PTF_RESULT_FAILED; \ - std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << #TestName << ": FAILED. Unhandled exception occurred! " \ + std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << #TestName \ + << ": FAILED. Unhandled exception occurred! " \ << "Exception: " << e.what() << std::endl; \ } \ if (runMemLeakCheck) \ @@ -100,14 +102,15 @@ static bool __ptfCheckTags(const std::string& tagSet, const std::string& tagSetT if (memLeakCount > 0 || memLeakSize > 0) \ { \ TestName##_result = PTF_RESULT_FAILED; \ - std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << #TestName << ": FAILED. Memory leak found! " \ - << memLeakCount << " objects and " << memLeakSize << "[bytes] leaked" << std::endl; \ + std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << #TestName \ + << ": FAILED. Memory leak found! " << memLeakCount << " objects and " << memLeakSize \ + << "[bytes] leaked" << std::endl; \ } \ } \ } \ if (TestName##_result == PTF_RESULT_PASSED) \ { \ - std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << #TestName << ": PASSED" << std::endl; \ + std::cout << std::left << std::setw(PTF_TESTNAME_WIDTH) << #TestName << ": PASSED" << std::endl; \ } \ } \ if (TestName##_result == PTF_RESULT_PASSED) \ From c7cab2b4835006c48b3f0d22ae442d789a0a08e0 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 3 Oct 2025 11:34:07 +0300 Subject: [PATCH 27/30] Typo fix. --- Tests/Pcap++Test/Tests/FileTests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/Pcap++Test/Tests/FileTests.cpp b/Tests/Pcap++Test/Tests/FileTests.cpp index 5d43b49a37..12171d8893 100644 --- a/Tests/Pcap++Test/Tests/FileTests.cpp +++ b/Tests/Pcap++Test/Tests/FileTests.cpp @@ -30,7 +30,7 @@ PTF_TEST_CASE(TestFileDeviceFactory_Pcap_MicroPrecision) { // Correct format constexpr const char* PCAP_MICROSEC_FILE_PATH = "PcapExamples/file_heuristics/microsecs.pcap"; - // Correct format, wrong exteension, microsecond precision + // Correct format, wrong extension, microsecond precision constexpr const char* PCAP_AS_DAT_FILE_PATH = "PcapExamples/file_heuristics/pcap-with-dat-ext.pcap.dat"; std::unique_ptr dev; @@ -63,7 +63,7 @@ PTF_TEST_CASE(TestFileDeviceFactory_PcapNG) { // Correct format constexpr const char* PCAPNG_FILE_PATH = "PcapExamples/file_heuristics/pcapng-example.pcapng"; - // Correct format, wrong exteension + // Correct format, wrong extension constexpr const char* PCAPNG_AS_PCAP_FILE_PATH = "PcapExamples/file_heuristics/pcapng-with-pcap-ext.pcapng.pcap"; std::unique_ptr dev; From 682eeacfa3821d2f75aa0462c23ea5098f063c6c Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Mon, 6 Oct 2025 22:58:37 +0300 Subject: [PATCH 28/30] Shortened test names. --- Tests/Pcap++Test/TestDefinition.h | 12 ++++++------ Tests/Pcap++Test/Tests/FileTests.cpp | 12 ++++++------ Tests/Pcap++Test/main.cpp | 12 ++++++------ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Tests/Pcap++Test/TestDefinition.h b/Tests/Pcap++Test/TestDefinition.h index 6257f1b5eb..38dbfdd241 100644 --- a/Tests/Pcap++Test/TestDefinition.h +++ b/Tests/Pcap++Test/TestDefinition.h @@ -20,12 +20,12 @@ PTF_TEST_CASE(TestLogger); PTF_TEST_CASE(TestLoggerMultiThread); // Implemented in FileTests.cpp -PTF_TEST_CASE(TestFileDeviceFactory_Pcap_MicroPrecision); -PTF_TEST_CASE(TestFileDeviceFactory_Pcap_NanoPrecision); -PTF_TEST_CASE(TestFileDeviceFactory_PcapNG); -PTF_TEST_CASE(TestFileDeviceFactory_PcapNG_ZST); -PTF_TEST_CASE(TestFileDeviceFactory_PcapNG_ZST_Unsupported); -PTF_TEST_CASE(TestFileDeviceFactory_Invalid); +PTF_TEST_CASE(TestReaderFactory_Pcap_Micro); +PTF_TEST_CASE(TestReaderFactory_Pcap_Nano); +PTF_TEST_CASE(TestReaderFactory_PcapNG); +PTF_TEST_CASE(TestReaderFactory_PcapNG_ZST); +PTF_TEST_CASE(TestReaderFactory_PcapNG_ZST_Unsupported); +PTF_TEST_CASE(TestReaderFactory_InvalidFile); PTF_TEST_CASE(TestPcapFileReadWrite); PTF_TEST_CASE(TestPcapFileMicroPrecision); PTF_TEST_CASE(TestPcapFileNanoPrecision); diff --git a/Tests/Pcap++Test/Tests/FileTests.cpp b/Tests/Pcap++Test/Tests/FileTests.cpp index 12171d8893..ad2331f87f 100644 --- a/Tests/Pcap++Test/Tests/FileTests.cpp +++ b/Tests/Pcap++Test/Tests/FileTests.cpp @@ -26,7 +26,7 @@ class FileReaderTeardown } }; -PTF_TEST_CASE(TestFileDeviceFactory_Pcap_MicroPrecision) +PTF_TEST_CASE(TestReaderFactory_Pcap_Micro) { // Correct format constexpr const char* PCAP_MICROSEC_FILE_PATH = "PcapExamples/file_heuristics/microsecs.pcap"; @@ -44,7 +44,7 @@ PTF_TEST_CASE(TestFileDeviceFactory_Pcap_MicroPrecision) } } -PTF_TEST_CASE(TestFileDeviceFactory_Pcap_NanoPrecision) +PTF_TEST_CASE(TestReaderFactory_Pcap_Nano) { if (!pcpp::PcapFileReaderDevice::isNanoSecondPrecisionSupported()) { @@ -59,7 +59,7 @@ PTF_TEST_CASE(TestFileDeviceFactory_Pcap_NanoPrecision) PTF_ASSERT_TRUE(dev->open()); } -PTF_TEST_CASE(TestFileDeviceFactory_PcapNG) +PTF_TEST_CASE(TestReaderFactory_PcapNG) { // Correct format constexpr const char* PCAPNG_FILE_PATH = "PcapExamples/file_heuristics/pcapng-example.pcapng"; @@ -83,7 +83,7 @@ PTF_TEST_CASE(TestFileDeviceFactory_PcapNG) PTF_ASSERT_TRUE(dev->open()); } -PTF_TEST_CASE(TestFileDeviceFactory_PcapNG_ZST) +PTF_TEST_CASE(TestReaderFactory_PcapNG_ZST) { if (!pcpp::PcapNgFileReaderDevice::isZstdSupported()) { @@ -104,7 +104,7 @@ PTF_TEST_CASE(TestFileDeviceFactory_PcapNG_ZST) } } -PTF_TEST_CASE(TestFileDeviceFactory_PcapNG_ZST_Unsupported) +PTF_TEST_CASE(TestReaderFactory_PcapNG_ZST_Unsupported) { if (pcpp::PcapNgFileReaderDevice::isZstdSupported()) { @@ -121,7 +121,7 @@ PTF_TEST_CASE(TestFileDeviceFactory_PcapNG_ZST_Unsupported) } } -PTF_TEST_CASE(TestFileDeviceFactory_Invalid) +PTF_TEST_CASE(TestReaderFactory_InvalidFile) { // Garbage data, correct extension constexpr const char* PCAP_BOGUS_FILE_PATH = "PcapExamples/file_heuristics/bogus-content.pcap"; diff --git a/Tests/Pcap++Test/main.cpp b/Tests/Pcap++Test/main.cpp index 7bdde339a7..f1b09ff6f2 100644 --- a/Tests/Pcap++Test/main.cpp +++ b/Tests/Pcap++Test/main.cpp @@ -215,12 +215,12 @@ int main(int argc, char* argv[]) PTF_RUN_TEST(TestLogger, "no_network;logger"); PTF_RUN_TEST(TestLoggerMultiThread, "no_network;logger;skip_mem_leak_check"); - PTF_RUN_TEST(TestFileDeviceFactory_Pcap_MicroPrecision, "no_network;pcap"); - PTF_RUN_TEST(TestFileDeviceFactory_Pcap_NanoPrecision, "no_network;pcap"); - PTF_RUN_TEST(TestFileDeviceFactory_PcapNG, "no_network;pcapng"); - PTF_RUN_TEST(TestFileDeviceFactory_PcapNG_ZST, "no_network;pcapng"); - PTF_RUN_TEST(TestFileDeviceFactory_PcapNG_ZST_Unsupported, "no_network;pcapng"); - PTF_RUN_TEST(TestFileDeviceFactory_Invalid, "no_network;pcap"); + PTF_RUN_TEST(TestReaderFactory_Pcap_Micro, "no_network;pcap"); + PTF_RUN_TEST(TestReaderFactory_Pcap_Nano, "no_network;pcap"); + PTF_RUN_TEST(TestReaderFactory_PcapNG, "no_network;pcapng"); + PTF_RUN_TEST(TestReaderFactory_PcapNG_ZST, "no_network;pcapng"); + PTF_RUN_TEST(TestReaderFactory_PcapNG_ZST_Unsupported, "no_network;pcapng"); + PTF_RUN_TEST(TestReaderFactory_InvalidFile, "no_network;pcap"); PTF_RUN_TEST(TestPcapFileReadWrite, "no_network;pcap"); PTF_RUN_TEST(TestPcapFileMicroPrecision, "no_network;pcap"); PTF_RUN_TEST(TestPcapFileNanoPrecision, "no_network;pcap"); From 07804dac2cb388e903823693b6c16baf84be4ca9 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Mon, 6 Oct 2025 23:02:13 +0300 Subject: [PATCH 29/30] Simplified invalid file test. --- .../file_heuristics/bogus-content.pcap | 1 - .../file_heuristics/bogus-content.pcapng | 1 - .../file_heuristics/bogus-content.zst | 1 - Tests/Pcap++Test/Tests/FileTests.cpp | 16 +--------------- 4 files changed, 1 insertion(+), 18 deletions(-) delete mode 100644 Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.pcap delete mode 100644 Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.pcapng delete mode 100644 Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.zst diff --git a/Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.pcap b/Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.pcap deleted file mode 100644 index 15a8eef479..0000000000 --- a/Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.pcap +++ /dev/null @@ -1 +0,0 @@ -4561d5a474d6as465d8as41d1as6531863d1as65d1a36d1 \ No newline at end of file diff --git a/Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.pcapng b/Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.pcapng deleted file mode 100644 index 15a8eef479..0000000000 --- a/Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.pcapng +++ /dev/null @@ -1 +0,0 @@ -4561d5a474d6as465d8as41d1as6531863d1as65d1a36d1 \ No newline at end of file diff --git a/Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.zst b/Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.zst deleted file mode 100644 index 15a8eef479..0000000000 --- a/Tests/Pcap++Test/PcapExamples/file_heuristics/bogus-content.zst +++ /dev/null @@ -1 +0,0 @@ -4561d5a474d6as465d8as41d1as6531863d1as65d1a36d1 \ No newline at end of file diff --git a/Tests/Pcap++Test/Tests/FileTests.cpp b/Tests/Pcap++Test/Tests/FileTests.cpp index ad2331f87f..85cd23c067 100644 --- a/Tests/Pcap++Test/Tests/FileTests.cpp +++ b/Tests/Pcap++Test/Tests/FileTests.cpp @@ -123,25 +123,11 @@ PTF_TEST_CASE(TestReaderFactory_PcapNG_ZST_Unsupported) PTF_TEST_CASE(TestReaderFactory_InvalidFile) { - // Garbage data, correct extension - constexpr const char* PCAP_BOGUS_FILE_PATH = "PcapExamples/file_heuristics/bogus-content.pcap"; - constexpr const char* PCAPNG_BOGUS_FILE_PATH = "PcapExamples/file_heuristics/bogus-content.pcapng"; - constexpr const char* PCAPNG_ZST_BOGUS_FILE_PATH = "PcapExamples/file_heuristics/bogus-content.zst"; - // Garbage data constexpr const char* BOGUS_FILE_PATH = "PcapExamples/file_heuristics/bogus-content.txt"; - std::unique_ptr dev; - - // Test existent files with correct extension but bogus content - for (const auto& filePath : { PCAP_BOGUS_FILE_PATH, PCAPNG_BOGUS_FILE_PATH, PCAPNG_ZST_BOGUS_FILE_PATH }) - { - dev = pcpp::IFileReaderDevice::createReader(filePath); - PTF_ASSERT_NULL(dev); - } - // Test existent file with wrong extension and bogus content - dev = pcpp::IFileReaderDevice::createReader(BOGUS_FILE_PATH); + auto dev = pcpp::IFileReaderDevice::createReader(BOGUS_FILE_PATH); PTF_ASSERT_NULL(dev); } From 9c4fc083575ab1e577d92ee8fca9e6dfea1fbc71 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Mon, 6 Oct 2025 23:03:49 +0300 Subject: [PATCH 30/30] Simplified ZST tests. --- .../pcapng-example.pcapng.zstd | Bin 11345 -> 0 bytes Tests/Pcap++Test/Tests/FileTests.cpp | 23 +++++------------- 2 files changed, 6 insertions(+), 17 deletions(-) delete mode 100644 Tests/Pcap++Test/PcapExamples/file_heuristics/pcapng-example.pcapng.zstd diff --git a/Tests/Pcap++Test/PcapExamples/file_heuristics/pcapng-example.pcapng.zstd b/Tests/Pcap++Test/PcapExamples/file_heuristics/pcapng-example.pcapng.zstd deleted file mode 100644 index 76b195f97f14bbbf66da4a9132f825753b1d5991..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11345 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 dev; - - for (const auto& filePath : { PCAPNG_ZST_FILE_PATH, PCAPNG_ZSTD_FILE_PATH }) - { - dev = pcpp::IFileReaderDevice::createReader(filePath); - PTF_ASSERT_NOT_NULL(dev); - PTF_ASSERT_NOT_NULL(dynamic_cast(dev.get())); - PTF_ASSERT_TRUE(dev->open()); - } + auto dev = pcpp::IFileReaderDevice::createReader(PCAPNG_ZST_FILE_PATH); + PTF_ASSERT_NOT_NULL(dev); + PTF_ASSERT_NOT_NULL(dynamic_cast(dev.get())); + PTF_ASSERT_TRUE(dev->open()); } PTF_TEST_CASE(TestReaderFactory_PcapNG_ZST_Unsupported) @@ -112,13 +106,8 @@ PTF_TEST_CASE(TestReaderFactory_PcapNG_ZST_Unsupported) } constexpr const char* PCAPNG_ZST_FILE_PATH = "PcapExamples/file_heuristics/pcapng-example.pcapng.zst"; - constexpr const char* PCAPNG_ZSTD_FILE_PATH = "PcapExamples/file_heuristics/pcapng-example.pcapng.zstd"; - std::unique_ptr dev; - for (const auto& filePath : { PCAPNG_ZST_FILE_PATH, PCAPNG_ZSTD_FILE_PATH }) - { - dev = pcpp::IFileReaderDevice::createReader(filePath); - PTF_ASSERT_NULL(dev); - } + auto dev = pcpp::IFileReaderDevice::createReader(PCAPNG_ZST_FILE_PATH); + PTF_ASSERT_NULL(dev); } PTF_TEST_CASE(TestReaderFactory_InvalidFile)