Skip to content

Commit

Permalink
- Added GTest
Browse files Browse the repository at this point in the history
- Added some tests
- Fixed the receive function that was prone to losing data
  • Loading branch information
FlorianReimold committed Feb 6, 2024
1 parent 4946dc2 commit 13a98c7
Show file tree
Hide file tree
Showing 15 changed files with 1,160 additions and 99 deletions.
21 changes: 21 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ option(UDPCAP_BUILD_SAMPLES
"Build project samples"
ON)

option(UDPCAP_BUILD_TESTS
"Build the udpcap GTests. Requires GTest::GTest to be available."
OFF)

option(UDPCAP_THIRDPARTY_ENABLED
"Enable building against the builtin dependencies"
ON)
Expand All @@ -57,6 +61,12 @@ cmake_dependent_option(UDPCAP_THIRDPARTY_USE_BUILTIN_ASIO
"UDPCAP_THIRDPARTY_ENABLED"
OFF)

cmake_dependent_option(UDPCAP_THIRDPARTY_USE_BUILTIN_GTEST
"Fetch and build tests against a predefined version of GTest. If disabled, the targets have to be provided externally."
ON
"UDPCAP_THIRDPARTY_ENABLED AND UDPCAP_BUILD_TESTS"
OFF)

# Module path for finding udpcap
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/udpcap/modules)

Expand All @@ -75,6 +85,12 @@ if (UDPCAP_THIRDPARTY_USE_BUILTIN_ASIO)
include(thirdparty/asio/asio_make_available.cmake)
endif()

#--- Fetch GTest -------------------------------
if (UDPCAP_THIRDPARTY_USE_BUILTIN_GTEST)
include(thirdparty/GTest/GTest_make_available.cmake)
endif()


#----------------------------------------------

# Set Debug postfix
Expand All @@ -94,6 +110,11 @@ if (UDPCAP_BUILD_SAMPLES)
add_subdirectory(samples/asio_sender_unicast)
endif()

# Tests
if (UDPCAP_BUILD_TESTS)
enable_testing()
add_subdirectory(tests/udpcap_test)
endif()

# Make this package available for packing with CPack
include("${CMAKE_CURRENT_LIST_DIR}/cpack_config.cmake")
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Udpcap has a very simple API with strong similarities to other well-known socket

int main()
{
// Create a Udpcap socket and bind it to a port. For this exampel we want to
// Create a Udpcap socket and bind it to a port. For this example we want to
// receive data from any local or remote source and therefore not bind to an
// IP address.

Expand All @@ -70,13 +70,23 @@ int main()

for (;;)
{
// Allocate a buffer for the received datagram. The size of the buffer
// should be large enough to hold the largest possible datagram.
std::vector<char> datagram(65535);

// Create an error code object to hold the error code if an error occurs.
Udpcap::Error error = Udpcap::Error::OK;

// Receive a datagram from the Socket. This is a blocking
// operation. The operation will return once a datagram has been received,
// the socket was closed by another thread or an error occured.
std::vector<char> received_datagram = socket.receiveDatagram();
size_t num_bytes = socket.receiveDatagram(datagram.data(), datagram.size(), error);

// Resize the buffer to the actual size of the received datagram.
datagram.resize(num_bytes);

std::cout << "Received " << received_datagram.size() << " bytes: "
<< std::string(received_datagram.data(), received_datagram.size())
std::cout << "Received " << datagram.size() << " bytes: "
<< std::string(datagram.data(), datagram.size())
<< std::endl;
}

Expand Down Expand Up @@ -117,10 +127,12 @@ You can set the following CMake Options to control how Udpcap is supposed to bui
**Option** | **Type** | **Default** | **Explanation** |
|----------------------------------------------|----------|-------------|-----------------------------------------------------------------------------------------------------------------|
| `UDPCAP_BUILD_SAMPLES` | `BOOL` | `ON` | Build the Udpcap (and asio) samples for sending and receiving dummy data |
| `UDPCAP_BUILD_TESTS` | `BOOL` | `OFF` | Build the udpcap GTests. Requires GTest::GTest to be available. |
| `UDPCAP_THIRDPARTY_ENABLED` | `BOOL` | `ON` | Activate / Deactivate the usage of integrated dependencies. |
| `UDPCAP_THIRDPARTY_USE_BUILTIN_NPCAP` | `BOOL` | `ON` | Fetch and build against an integrated Version of the npcap SDK. <br>Only available if `UDPCAP_THIRDPARTY_ENABLED=ON` |
| `UDPCAP_THIRDPARTY_USE_BUILTIN_PCAPPLUSPLUS` | `BOOL` | `ON` | Fetch and build against an integrated Version of Pcap++. <br>_Only available if `UDPCAP_THIRDPARTY_ENABLED=ON`_ |
| `UDPCAP_THIRDPARTY_USE_BUILTIN_ASIO` | `BOOL` | `ON` | Fetch and build against an integrated Version of asio. <br>Only available if `UDPCAP_THIRDPARTY_ENABLED=ON` |
| `UDPCAP_THIRDPARTY_USE_BUILTIN_GTEST` | `BOOL` | `ON` | Fetch and build tests against a predefined version of GTest. If disabled, the targets have to be provided externally. <br>Only available if `UDPCAP_THIRDPARTY_ENABLED=ON` and `UDPCAP_BUILD_TESTS=ON`|
| `BUILD_SHARED_LIBS` | `BOOL` | | Not a udpcap option, but use this to control whether you want to have a static or shared library |
# How to integrate Udpcap in your project
Expand Down
29 changes: 18 additions & 11 deletions samples/udpcap_receiver_multicast/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,11 @@ int main()
return 1;
}

// 5) Receive data from the socket
// 3) Receive data from the socket
//
// There are 2 receiveDatagram() functions available. One of them returns
// the data as std::vector, the other expects a pointer to pre-allocated
// memory along with the maximum size.
// The receiveDatagram() function is used to receive data from the socket.
// It requires the application to allocate memory for the received data.
// If an error occurs, the error object is set accordingly.
//
// The socket.receiveDatagram() function is blocking. In this example we
// can use the applications' main thread to wait for incoming data.
Expand All @@ -91,17 +91,24 @@ int main()
Udpcap::HostAddress sender_address;
uint16_t sender_port(0);

// Allocate memory for the received datagram (with the maximum possible udp datagram size)
std::vector<char> received_datagram(65536);

// Initialize error object
Udpcap::Error error = Udpcap::Error::OK;

// Blocking receive a datagram
std::vector<char> received_datagram = socket.receiveDatagram(&sender_address, &sender_port);
size_t received_bytes = socket.receiveDatagram(received_datagram.data(), received_datagram.size(), &sender_address, &sender_port, error);

if (sender_address.isValid())
if (error)
{
std::cout << "Received " << received_datagram.size() << " bytes from " << sender_address.toString() << ":" << sender_port << ": " << std::string(received_datagram.data(), received_datagram.size()) << std::endl;
}
else
{
std::cerr << "ERROR: Failed to receive data from Udpcap Socket" << std::endl;
std::cerr << "ERROR while receiving data:" << error.ToString() << std::endl;
return 1;
}

// Shrink the received_datagram to the actual size
received_datagram.resize(received_bytes);
std::cout << "Received " << received_datagram.size() << " bytes from " << sender_address.toString() << ":" << sender_port << ": " << std::string(received_datagram.data(), received_datagram.size()) << std::endl;
}

return 0;
Expand Down
27 changes: 17 additions & 10 deletions samples/udpcap_receiver_unicast/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ int main()

// 3) Receive data from the socket
//
// There are 2 receiveDatagram() functions available. One of them returns
// the data as std::vector, the other expects a pointer to pre-allocated
// memory along with the maximum size.
// The receiveDatagram() function is used to receive data from the socket.
// It requires the application to allocate memory for the received data.
// If an error occurs, the error object is set accordingly.
//
// The socket.receiveDatagram() function is blocking. In this example we
// can use the applications' main thread to wait for incoming data.
Expand All @@ -74,17 +74,24 @@ int main()
Udpcap::HostAddress sender_address;
uint16_t sender_port(0);

// Allocate memory for the received datagram (with the maximum possible udp datagram size)
std::vector<char> received_datagram(65536);

// Initialize error object
Udpcap::Error error = Udpcap::Error::OK;

// Blocking receive a datagram
std::vector<char> received_datagram = socket.receiveDatagram(&sender_address, &sender_port);
size_t received_bytes = socket.receiveDatagram(received_datagram.data(), received_datagram.size(), &sender_address, &sender_port, error);

if (sender_address.isValid())
if (error)
{
std::cout << "Received " << received_datagram.size() << " bytes from " << sender_address.toString() << ":" << sender_port << ": " << std::string(received_datagram.data(), received_datagram.size()) << std::endl;
}
else
{
std::cerr << "ERROR: Failed to receive data from Udpcap Socket" << std::endl;
std::cerr << "ERROR while receiving data:" << error.ToString() << std::endl;
return 1;
}

// Shrink the received_datagram to the actual size
received_datagram.resize(received_bytes);
std::cout << "Received " << received_datagram.size() << " bytes from " << sender_address.toString() << ":" << sender_port << ": " << std::string(received_datagram.data(), received_datagram.size()) << std::endl;
}

return 0;
Expand Down
44 changes: 44 additions & 0 deletions tests/udpcap_test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# =========================== LICENSE =================================
#
# Copyright (C) 2016 - 2022 Continental Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# =========================== LICENSE =================================

cmake_minimum_required(VERSION 3.13)

project(udpcap_test)

set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE)

find_package(udpcap REQUIRED)
find_package(GTest REQUIRED)
find_package(asio REQUIRED)

set(sources
src/atomic_signalable.h
src/udpcap_test.cpp
)

add_executable (${PROJECT_NAME}
${sources}
)

target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_14)

target_link_libraries (${PROJECT_NAME}
udpcap::udpcap
GTest::gtest_main
$<BUILD_INTERFACE:asio::asio>
)
Loading

0 comments on commit 13a98c7

Please sign in to comment.