summaryrefslogtreecommitdiff
path: root/test/network_tests/someip_tp_tests/someip_tp_test_msg_sender.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/network_tests/someip_tp_tests/someip_tp_test_msg_sender.cpp')
-rw-r--r--test/network_tests/someip_tp_tests/someip_tp_test_msg_sender.cpp1387
1 files changed, 1387 insertions, 0 deletions
diff --git a/test/network_tests/someip_tp_tests/someip_tp_test_msg_sender.cpp b/test/network_tests/someip_tp_tests/someip_tp_test_msg_sender.cpp
new file mode 100644
index 0000000..f2e4f9e
--- /dev/null
+++ b/test/network_tests/someip_tp_tests/someip_tp_test_msg_sender.cpp
@@ -0,0 +1,1387 @@
+// Copyright (C) 2015-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <iostream>
+#include <memory>
+#include <thread>
+#include <chrono>
+#include <cstring>
+#include <future>
+#include <numeric>
+#include <random>
+#include <algorithm>
+#include <list>
+
+#if defined(__linux__) || defined(ANDROID)
+#include <arpa/inet.h>
+#endif
+
+#include <gtest/gtest.h>
+
+#include <boost/asio.hpp>
+
+#include <vsomeip/vsomeip.hpp>
+
+#include "../../implementation/utility/include/byteorder.hpp"
+#include "../../implementation/message/include/deserializer.hpp"
+#include "../../implementation/message/include/serializer.hpp"
+#include "../../implementation/service_discovery/include/service_discovery.hpp"
+#include "../../implementation/service_discovery/include/message_impl.hpp"
+#include "../../implementation/service_discovery/include/constants.hpp"
+#include "../../implementation/service_discovery/include/enumeration_types.hpp"
+#include "../../implementation/service_discovery/include/eventgroupentry_impl.hpp"
+#include "../../implementation/service_discovery/include/serviceentry_impl.hpp"
+#include "../../implementation/message/include/message_impl.hpp"
+#include "../../implementation/service_discovery/include/option_impl.hpp"
+#include "../../implementation/service_discovery/include/ipv4_option_impl.hpp"
+#include "../../implementation/endpoints/include/tp.hpp"
+#include "../../implementation/endpoints/include/tp_reassembler.hpp"
+#include "../../implementation/message/include/payload_impl.hpp"
+
+#include "someip_tp_test_globals.hpp"
+
+static char* remote_address;
+static char* local_address;
+
+std::vector<someip_tp_test::test_mode_e> its_modes({
+ someip_tp_test::test_mode_e::IN_SEQUENCE,
+ someip_tp_test::test_mode_e::MIXED,
+ someip_tp_test::test_mode_e::INCOMPLETE,
+ someip_tp_test::test_mode_e::DUPLICATE,
+ someip_tp_test::test_mode_e::OVERLAP,
+ someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK,
+});
+
+class someip_tp : public ::testing::TestWithParam<someip_tp_test::test_mode_e> {
+public:
+ someip_tp() :
+ work_(std::make_shared<boost::asio::io_context::work>(io_)),
+ io_thread_(std::bind(&someip_tp::io_run, this)),
+ session_(0x0),
+ sd_session_(0x0),
+ address_remote_(boost::asio::ip::address::from_string(std::string(remote_address))),
+ address_local_(boost::asio::ip::address::from_string(std::string(local_address))),
+ runtime_(vsomeip::runtime::get()) {}
+protected:
+ void TearDown() {
+ work_.reset();
+ io_thread_.join();
+ io_.stop();
+ }
+
+ void call_shutdown_method() {
+ boost::system::error_code ec;
+ std::uint8_t shutdown_call[] = {
+ 0x45, 0x45, 0x45, 0x01,
+ 0x00, 0x00, 0x00, 0x08,
+ 0xDD, 0xDD, 0x00, 0x01,
+ 0x01, 0x00, 0x00, 0x00 };
+ boost::asio::ip::udp::socket::endpoint_type target_service(address_remote_,
+ 30001);
+ boost::asio::ip::udp::socket udp_socket2(io_, boost::asio::ip::udp::v4());
+ udp_socket2.send_to(boost::asio::buffer(shutdown_call), target_service);
+ udp_socket2.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_socket2.close(ec);
+ }
+
+ void io_run() {
+ io_.run();
+ }
+
+ void offer_service(boost::asio::ip::udp::socket* const _udp_socket) {
+ // offer the service
+ std::uint8_t its_offer_service_message[] = {
+ 0xff, 0xff, 0x81, 0x00,
+ 0x00, 0x00, 0x00, 0x30, // length
+ 0x00, 0x00, 0x00, 0x01,
+ 0x01, 0x01, 0x02, 0x00,
+ 0xc0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, // length entries array
+ 0x01, 0x00, 0x00, 0x20,
+ 0x67, 0x67, 0x00, 0x01, // service / instance
+ 0x00, 0xff, 0xff, 0xff, // major / ttl
+ 0x00, 0x00, 0x00, 0x00, // minor
+ 0x00, 0x00, 0x00, 0x0c, // length options array
+ 0x00, 0x09, 0x04, 0x00,
+ 0xff, 0xff, 0xff, 0xff, // slave address
+ 0x00, 0x11, 0x9c, 0x41,
+ };
+ std::memcpy(&its_offer_service_message[48], &address_local_.to_v4().to_bytes()[0], 4);
+ std::uint16_t its_session = htons(++sd_session_);
+ std::memcpy(&its_offer_service_message[10], &its_session, sizeof(its_session));
+
+ boost::asio::ip::udp::socket::endpoint_type target_sd(address_remote_,30490);
+ _udp_socket->send_to(boost::asio::buffer(its_offer_service_message), target_sd);
+ }
+
+ void subscribe_at_master(boost::asio::ip::udp::socket* const _udp_socket) {
+ std::uint8_t its_subscription[] = {
+ 0xff, 0xff, 0x81, 0x00,
+ 0x00, 0x00, 0x00, 0x30, // length
+ 0x00, 0x00, 0x00, 0x01,
+ 0x01, 0x01, 0x02, 0x00,
+ 0xc0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, // length entries array
+ 0x06, 0x00, 0x00, 0x10,
+ 0x45, 0x45, 0x00, 0x01, // service / instance
+ 0x00, 0xff, 0xff, 0xff, // major / ttl
+ 0x00, 0x00, 0x00, 0x01, // counter
+ 0x00, 0x00, 0x00, 0x0c, // length options array
+ 0x00, 0x09, 0x04, 0x00,
+ 0xff, 0xff, 0xff, 0xff, // slave address
+ 0x00, 0x11, 0x75, 0x31, // port 30001
+ };
+ std::memcpy(&its_subscription[48], &address_local_.to_v4().to_bytes()[0], 4);
+ std::uint16_t its_session = htons(++sd_session_);
+ std::memcpy(&its_subscription[10], &its_session, sizeof(its_session));
+
+ boost::asio::ip::udp::socket::endpoint_type target_sd(address_remote_,30490);
+ _udp_socket->send_to(boost::asio::buffer(its_subscription), target_sd);
+ }
+
+ /*
+ * @brief custom version of tp::tp_split_message with adjustable segment size
+ * needed to send overlapping segments within the 1392 byte segment size limit
+ */
+ vsomeip::tp::tp_split_messages_t split_message(const std::uint8_t * const _data,
+ std::uint32_t _size , std::uint32_t _segment_size) {
+ using namespace vsomeip::tp;
+ using namespace vsomeip;
+ tp_split_messages_t split_messages;
+
+ if (_size < VSOMEIP_MAX_UDP_MESSAGE_SIZE) {
+ std::cerr << __func__ << " called with size: " << std::dec << _size;
+ return split_messages;
+ }
+
+ const auto data_end = _data + _size;
+
+ for (auto current_offset = _data + 16; current_offset < data_end;) {
+ auto msg = std::make_shared<message_buffer_t>();
+ msg->reserve(VSOMEIP_FULL_HEADER_SIZE + sizeof(tp_header_t) + _segment_size);
+ // copy the header
+ msg->insert(msg->end(), _data, _data + VSOMEIP_FULL_HEADER_SIZE);
+ // change the message type
+ (*msg)[VSOMEIP_MESSAGE_TYPE_POS] = (*msg)[VSOMEIP_MESSAGE_TYPE_POS] | 0x20;
+ // check if last segment
+ const auto segment_end = current_offset + _segment_size;
+ const bool is_last_segment = (segment_end >= data_end);
+ // insert tp_header
+ const tp_header_t header = htonl(
+ static_cast<tp_header_t>((current_offset - VSOMEIP_FULL_HEADER_SIZE - _data)) |
+ static_cast<tp_header_t>((is_last_segment) ? 0x0u : 0x1u));
+
+ const byte_t * const headerp = reinterpret_cast<const byte_t*>(&header);
+ msg->insert(msg->end(), headerp, headerp + sizeof(tp_header_t));
+
+ // insert payload
+ if (is_last_segment) {
+ msg->insert(msg->end(), current_offset, data_end);
+ current_offset = data_end;
+ } else {
+ msg->insert(msg->end(), current_offset, segment_end);
+ current_offset += _segment_size;
+ }
+ // update length
+ const length_t its_length = static_cast<length_t>(msg->size()
+ - VSOMEIP_SOMEIP_HEADER_SIZE);
+ *(reinterpret_cast<length_t*>(&(*msg)[VSOMEIP_LENGTH_POS_MIN])) = htonl(its_length);
+ split_messages.emplace_back(std::move(msg));
+ }
+
+ return split_messages;
+ }
+
+ void create_fragments(std::uint32_t _count, vsomeip::service_t _service,
+ vsomeip::instance_t _instance,
+ vsomeip::method_t _method,
+ vsomeip::message_type_e _message_type,
+ vsomeip::client_t _client,
+ vsomeip::session_t _session,
+ std::vector<vsomeip::message_buffer_ptr_t>* _target,
+ std::uint32_t _segment_size) {
+ vsomeip::message_impl msg;
+ msg.set_reliable(false);
+ msg.set_service(_service);
+ msg.set_instance(_instance);
+ msg.set_method(_method);
+ msg.set_message_type(_message_type);
+ msg.set_return_code(vsomeip::return_code_e::E_OK);
+ if (_client == vsomeip::ANY_CLIENT) {
+ msg.set_client(0xDDDD);
+ } else {
+ msg.set_client(_client);
+ }
+ if (_session == 0xFFFF) {
+ msg.set_session(++session_);
+ } else {
+ msg.set_session(_session);
+ }
+ std::vector<vsomeip::byte_t> its_payload_data;
+ for (uint32_t i = 0; i < _count; i++) {
+ its_payload_data.resize((i * _segment_size) + _segment_size, static_cast<std::uint8_t>(i));
+ }
+ std::shared_ptr<vsomeip::payload> payload = std::make_shared<vsomeip::payload_impl>(its_payload_data);
+ msg.set_payload(payload);
+ vsomeip::serializer its_serializer(0);
+ msg.serialize(&its_serializer);
+
+ *_target = split_message(its_serializer.get_data(), its_serializer.get_size(), _segment_size);
+ its_serializer.reset();
+
+ }
+
+ vsomeip::message_buffer_t create_full_message(
+ const std::vector<vsomeip::message_buffer_ptr_t>& _fragments) {
+ auto its_reassembler = std::make_shared<vsomeip::tp::tp_reassembler>(
+ std::numeric_limits<std::uint32_t>::max(), io_);
+ vsomeip::message_buffer_t its_reassemlbed_msg;
+ for (const auto& frag : _fragments) {
+ const auto res = its_reassembler->process_tp_message(&(*frag)[0],
+ std::uint32_t(frag->size()), address_local_, 12345);
+ if (res.first) {
+ its_reassemlbed_msg = res.second;
+ }
+ }
+ its_reassembler->stop();
+ return its_reassemlbed_msg;
+ }
+
+ std::vector<int> create_shuffled_seqeuence(std::uint32_t _count) {
+ std::vector<int> its_indexes(_count);
+ std::iota(its_indexes.begin(), its_indexes.end(), 0);
+ std::random_device rd;
+ std::mt19937 its_twister(rd());
+ std::shuffle(its_indexes.begin(), its_indexes.end(), its_twister);
+ return its_indexes;
+ }
+ void increase_segment_back(const vsomeip::message_buffer_ptr_t& _seg,
+ std::uint32_t _amount) {
+ _seg->resize(_seg->size() + _amount, 0xff);
+ // update length
+ *(reinterpret_cast<vsomeip::length_t*>(&((*_seg)[VSOMEIP_LENGTH_POS_MIN]))) =
+ htonl(static_cast<vsomeip::length_t>(_seg->size() - VSOMEIP_SOMEIP_HEADER_SIZE));
+ }
+
+ void increase_segment_front(const vsomeip::message_buffer_ptr_t& _seg,
+ std::uint32_t _amount) {
+ // increase segment by amount
+ _seg->insert(_seg->begin() + VSOMEIP_TP_PAYLOAD_POS, _amount, 0xff);
+
+ // decrease offset by amount
+ const vsomeip::tp::tp_header_t its_tp_header = VSOMEIP_BYTES_TO_LONG(
+ (*_seg)[VSOMEIP_TP_HEADER_POS_MIN],
+ (*_seg)[VSOMEIP_TP_HEADER_POS_MIN + 1],
+ (*_seg)[VSOMEIP_TP_HEADER_POS_MIN + 2],
+ (*_seg)[VSOMEIP_TP_HEADER_POS_MAX]);
+ std::uint32_t its_offset = vsomeip::tp::tp::get_offset(its_tp_header);
+ its_offset -= _amount;
+ const vsomeip::tp::tp_header_t its_new_tp_header =
+ htonl(static_cast<vsomeip::tp::tp_header_t>(its_offset |
+ static_cast<vsomeip::tp::tp_header_t>(its_tp_header & 0x1)));
+ *(reinterpret_cast<vsomeip::tp::tp_header_t*>(
+ &((*_seg)[VSOMEIP_TP_HEADER_POS_MIN]))) = its_new_tp_header;
+
+ // update length
+ *(reinterpret_cast<vsomeip::length_t*>(&((*_seg)[VSOMEIP_LENGTH_POS_MIN]))) =
+ htonl(static_cast<vsomeip::length_t>(_seg->size() - VSOMEIP_SOMEIP_HEADER_SIZE));
+ }
+
+ void increase_segment_front_back(const vsomeip::message_buffer_ptr_t& _seg,
+ std::uint32_t _amount) {
+ increase_segment_front(_seg, _amount);
+ increase_segment_back(_seg, _amount);
+ }
+
+ void decrease_segment_back(const vsomeip::message_buffer_ptr_t& _seg,
+ std::uint32_t _amount) {
+ _seg->resize(_seg->size() - _amount, 0xff);
+ // update length
+ *(reinterpret_cast<vsomeip::length_t*>(&((*_seg)[VSOMEIP_LENGTH_POS_MIN]))) =
+ htonl(static_cast<vsomeip::length_t>(_seg->size() - VSOMEIP_SOMEIP_HEADER_SIZE));
+ }
+
+ void decrease_segment_front(const vsomeip::message_buffer_ptr_t& _seg,
+ std::uint32_t _amount) {
+ if (_amount % 16 != 0) {
+ std::cerr << __func__ << ":" << __LINE__ << std::endl;
+ return;
+ }
+ _seg->erase(_seg->begin() + VSOMEIP_TP_PAYLOAD_POS, _seg->begin() + VSOMEIP_TP_PAYLOAD_POS + _amount);
+ // increase offset by amount
+ const vsomeip::tp::tp_header_t its_tp_header = VSOMEIP_BYTES_TO_LONG(
+ (*_seg)[VSOMEIP_TP_HEADER_POS_MIN],
+ (*_seg)[VSOMEIP_TP_HEADER_POS_MIN + 1],
+ (*_seg)[VSOMEIP_TP_HEADER_POS_MIN + 2],
+ (*_seg)[VSOMEIP_TP_HEADER_POS_MAX]);
+ std::uint32_t its_offset = vsomeip::tp::tp::get_offset(its_tp_header);
+ its_offset += _amount;
+ const vsomeip::tp::tp_header_t its_new_tp_header =
+ htonl(static_cast<vsomeip::tp::tp_header_t>(its_offset |
+ static_cast<vsomeip::tp::tp_header_t>(its_tp_header & 0x1)));
+ *(reinterpret_cast<vsomeip::tp::tp_header_t*>(
+ &((*_seg)[VSOMEIP_TP_HEADER_POS_MIN]))) = its_new_tp_header;
+ // update length
+ *(reinterpret_cast<vsomeip::length_t*>(&((*_seg)[VSOMEIP_LENGTH_POS_MIN]))) =
+ htonl(static_cast<vsomeip::length_t>(_seg->size() - VSOMEIP_SOMEIP_HEADER_SIZE));
+ }
+
+ void decrease_segment_front_back(const vsomeip::message_buffer_ptr_t& _seg,
+ std::uint32_t _amount) {
+ if (_amount % 16 != 0) {
+ std::cerr << __func__ << ":" << __LINE__ << std::endl;
+ return;
+ }
+ decrease_segment_back(_seg, _amount);
+ decrease_segment_front(_seg, _amount);
+ }
+
+
+ enum order_e {
+ ASCENDING,
+ DESCENDING,
+ MIXED_PREDEFINED,
+ MIXED_RANDOM,
+ };
+
+ boost::asio::io_context io_;
+ std::shared_ptr<boost::asio::io_context::work> work_;
+ std::thread io_thread_;
+ std::vector<vsomeip::message_buffer_ptr_t> fragments_request_to_master_;
+ std::vector<vsomeip::message_buffer_ptr_t> fragments_response_of_master_;
+
+ std::vector<vsomeip::message_buffer_ptr_t> fragments_received_as_server_;
+ std::vector<vsomeip::message_buffer_ptr_t> fragments_response_to_master_;
+
+ std::vector<vsomeip::message_buffer_ptr_t> fragments_event_from_master_;
+ std::vector<vsomeip::message_buffer_ptr_t> fragments_event_to_master_;
+
+ std::atomic<std::uint16_t> session_;
+ std::atomic<std::uint16_t> sd_session_;
+ boost::asio::ip::address address_remote_;
+ boost::asio::ip::address address_local_;
+ std::shared_ptr<vsomeip::runtime> runtime_;
+ someip_tp_test::test_mode_e test_mode_ = GetParam();
+};
+
+INSTANTIATE_TEST_CASE_P(send_in_mode,
+ someip_tp,
+ ::testing::ValuesIn(its_modes));
+
+
+/*
+ * @test Send a big fragmented UDP request to the master and wait for the
+ * response. Check that the received response is the same as the request (server
+ * just echos the requests).
+ * Wait for a big fragmented UDP message request from the master and send back
+ * the response in the same size. Check that the request and response are
+ * identical.
+ * Do this two times one with fragments ordered ascending and one time descending.
+ * Wait for the master to subscribe and send back two big, fragmented
+ * notifications one with fragments ordered ascending and one descending
+ * Subscribe at master and wait for one fragmented event.
+ * With testmode INCOMPLETE incomplete fragments are send as well
+ * With testmode MIXED instead of ascending/descedning order the fragments are
+ * send in a predefined or in a random order
+ */
+TEST_P(someip_tp, send_in_mode)
+{
+ std::promise<void> remote_client_subscribed;
+ std::atomic<std::uint16_t> remote_client_subscription_port(0);
+ std::promise<void> offer_received;
+
+ std::mutex udp_sd_socket_mutex;
+ boost::asio::ip::udp::socket udp_sd_socket(io_,
+ boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 30490));
+
+ boost::asio::ip::udp::socket udp_client_socket(io_,
+ boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 30001));
+
+ boost::asio::ip::udp::socket udp_server_socket(io_,
+ boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 40001));
+
+ std::thread sd_receive_thread([&](){
+ std::atomic<bool> keep_receiving(true);
+ std::vector<std::uint8_t> receive_buffer(4096);
+ std::vector<vsomeip::event_t> its_received_events;
+ std::atomic<bool> service_offered(false);
+ std::atomic<bool> client_subscribed(false);
+
+ // join the sd multicast group 224.0.77.1
+ udp_sd_socket.set_option(boost::asio::ip::multicast::join_group(
+ boost::asio::ip::address::from_string("224.0.77.1").to_v4()));
+ while (keep_receiving) {
+ boost::system::error_code error;
+ std::size_t bytes_transferred = udp_sd_socket.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
+ if (error) {
+ keep_receiving = false;
+ ADD_FAILURE() << __func__ << " error: " << error.message();
+ return;
+ } else {
+ vsomeip::deserializer its_deserializer(&receive_buffer[0], bytes_transferred, 0);
+ vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_SERVICE_POS_MIN],
+ receive_buffer[VSOMEIP_SERVICE_POS_MAX]);
+ vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_METHOD_POS_MIN],
+ receive_buffer[VSOMEIP_METHOD_POS_MAX]);
+ if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
+ vsomeip::sd::message_impl sd_msg;
+ EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
+ EXPECT_EQ(1u, sd_msg.get_entries().size());
+ for (const auto& e : sd_msg.get_entries()) {
+ if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP && !client_subscribed) {
+ EXPECT_TRUE(e->is_eventgroup_entry());
+ EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP, e->get_type());
+ EXPECT_EQ(1,e->get_num_options(1));
+ EXPECT_EQ(std::uint32_t(0xFFFFFF), e->get_ttl());
+ EXPECT_EQ(someip_tp_test::service_slave.service_id, e->get_service());
+ EXPECT_EQ(someip_tp_test::service_slave.instance_id, e->get_instance());
+ EXPECT_EQ(1u, sd_msg.get_options().size());
+ if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP) {
+ std::shared_ptr<vsomeip::sd::eventgroupentry_impl> its_casted_entry =
+ std::static_pointer_cast<vsomeip::sd::eventgroupentry_impl>(e);
+ EXPECT_EQ(someip_tp_test::service_slave.eventgroup_id,
+ its_casted_entry->get_eventgroup());
+ std::shared_ptr<vsomeip::sd::option_impl> its_option =
+ sd_msg.get_options().at(its_casted_entry->get_options(1)[0]);
+ EXPECT_TRUE(its_option > 0);
+ if(its_option->get_type() == vsomeip::sd::option_type_e::IP4_ENDPOINT) {
+ std::shared_ptr<vsomeip::sd::ipv4_option_impl> its_ipv4_option =
+ std::dynamic_pointer_cast<vsomeip::sd::ipv4_option_impl> (its_option);
+ EXPECT_TRUE(its_ipv4_option > 0);
+ EXPECT_EQ(vsomeip::sd::layer_four_protocol_e::UDP, its_ipv4_option->get_layer_four_protocol());
+ EXPECT_EQ(address_remote_,
+ boost::asio::ip::address(
+ boost::asio::ip::address_v4(its_ipv4_option->get_address())));
+ remote_client_subscription_port = its_ipv4_option->get_port();
+ }
+ std::vector<vsomeip::byte_t> its_sub_ack(&receive_buffer[0], &receive_buffer[0] + VSOMEIP_FULL_HEADER_SIZE + 8 + (sd_msg.get_entries().size() * 16));
+ its_sub_ack[24] = static_cast<vsomeip::byte_t>(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK);
+ // fix length
+ const std::uint32_t its_length = htonl(static_cast<std::uint32_t>(its_sub_ack.size()) - VSOMEIP_SOMEIP_HEADER_SIZE);
+ std::memcpy(&its_sub_ack[4], &its_length, sizeof(its_length));
+ // set number of options to zero
+ its_sub_ack[27] = 0x0;
+ // update session
+ std::uint16_t its_session = htons(++sd_session_);
+ std::memcpy(&its_sub_ack[10], &its_session, sizeof(its_session));
+ boost::asio::ip::udp::socket::endpoint_type target_sd(address_remote_,30490);
+ {
+ std::lock_guard<std::mutex> its_lock(udp_sd_socket_mutex);
+ udp_sd_socket.send_to(boost::asio::buffer(its_sub_ack), target_sd);
+ }
+ std::cout << __LINE__ << ": master subscribed" << std::endl;
+ remote_client_subscribed.set_value();
+ client_subscribed = true;
+ }
+ } else if (e->get_type() == vsomeip::sd::entry_type_e::OFFER_SERVICE && !service_offered) {
+ EXPECT_TRUE(e->is_service_entry());
+ EXPECT_EQ(vsomeip::sd::entry_type_e::OFFER_SERVICE, e->get_type());
+ EXPECT_EQ(1u,e->get_num_options(1));
+ EXPECT_EQ(std::uint32_t(0xFFFFFF), e->get_ttl());
+ EXPECT_EQ(someip_tp_test::service.service_id, e->get_service());
+ EXPECT_EQ(someip_tp_test::service.instance_id, e->get_instance());
+ EXPECT_EQ(1u, sd_msg.get_options().size());
+ if (e->get_type() == vsomeip::sd::entry_type_e::OFFER_SERVICE) {
+ std::shared_ptr<vsomeip::sd::serviceentry_impl> its_casted_entry =
+ std::static_pointer_cast<vsomeip::sd::serviceentry_impl>(e);
+ EXPECT_EQ(0u, its_casted_entry->get_minor_version());
+ }
+ offer_received.set_value();
+ service_offered = true;
+ }
+ }
+ if (service_offered && client_subscribed) {
+ keep_receiving = false;
+ }
+ } else {
+ ADD_FAILURE() << " received non-sd message";
+ return;
+ }
+ }
+ }
+ });
+
+ std::thread send_thread([&]() {
+ boost::system::error_code ec;
+ try {
+
+ // wait until a offer was received
+ if (std::future_status::timeout == offer_received.get_future().wait_for(std::chrono::seconds(10))) {
+ ADD_FAILURE() << "Didn't receive offer within time";
+ return;
+ }
+
+ {
+ std::lock_guard<std::mutex> its_lock(udp_sd_socket_mutex);
+ subscribe_at_master(&udp_sd_socket);
+ }
+
+ std::mutex all_fragments_received_mutex_;
+ std::condition_variable all_fragments_received_cond_;
+ bool wait_for_all_response_fragments_received_(true);
+ std::uint32_t received_responses(0);
+ bool wait_for_all_event_fragments_received_(true);
+
+ std::thread udp_client_receive_thread([&]() {
+ bool keep_receiving(true);
+ std::vector<std::uint8_t> receive_buffer(4096);
+ while (keep_receiving) {
+ boost::system::error_code error;
+ std::size_t bytes_transferred = udp_client_socket.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
+ if (error) {
+ keep_receiving = false;
+ ADD_FAILURE() << __func__ << " error: " << error.message();
+ return;
+ } else {
+ std::uint32_t its_pos = 0;
+
+ while (bytes_transferred > 0) {
+ const std::uint32_t its_message_size = VSOMEIP_BYTES_TO_LONG(
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 1],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 2],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 3]) + VSOMEIP_SOMEIP_HEADER_SIZE;
+ std::cout << __LINE__ << ": received response " << its_message_size << std::endl;
+ vsomeip::deserializer its_deserializer(&receive_buffer[its_pos], its_message_size, 0);
+
+ vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MAX]);
+ vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_METHOD_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_METHOD_POS_MAX]);
+
+ vsomeip::message_impl msg;
+ EXPECT_TRUE(msg.deserialize(&its_deserializer));
+ if (msg.get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
+ EXPECT_EQ(vsomeip::message_type_e::MT_RESPONSE, msg.get_message_type());
+ EXPECT_EQ(someip_tp_test::service.service_id, msg.get_service());
+ } else if (msg.get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
+ std::cout << __LINE__ << ": received event" << std::endl;
+ } else if (vsomeip::tp::tp::tp_flag_is_set(receive_buffer[its_pos + VSOMEIP_MESSAGE_TYPE_POS]) &&
+ vsomeip::tp::tp::tp_flag_unset(receive_buffer[its_pos + VSOMEIP_MESSAGE_TYPE_POS]) == vsomeip::message_type_e::MT_RESPONSE) {
+ EXPECT_EQ(someip_tp_test::service.service_id, its_service);
+ EXPECT_EQ(someip_tp_test::service.method_id, its_method);
+ auto its_buffer = std::make_shared<vsomeip::message_buffer_t>(&receive_buffer[its_pos], &receive_buffer[its_pos] + its_message_size);
+
+ fragments_response_of_master_.push_back(its_buffer);
+ if (fragments_response_of_master_.size() == someip_tp_test::number_of_fragments) {
+ std::lock_guard<std::mutex> its_lock(all_fragments_received_mutex_);
+ wait_for_all_response_fragments_received_ = false;
+ std::cout << __LINE__ << ": received all response fragments as client" << std::endl;
+ all_fragments_received_cond_.notify_one();
+ if (++received_responses == 2 && !wait_for_all_event_fragments_received_) {
+ std::cout << __LINE__ << ": received all responses as client --> Finished" << std::endl;
+ keep_receiving = false;
+ }
+ }
+ } else if (vsomeip::tp::tp::tp_flag_is_set(receive_buffer[its_pos + VSOMEIP_MESSAGE_TYPE_POS]) &&
+ vsomeip::tp::tp::tp_flag_unset(receive_buffer[its_pos + VSOMEIP_MESSAGE_TYPE_POS]) == vsomeip::message_type_e::MT_NOTIFICATION) {
+ std::cout << __LINE__ << ": received event fragment" << std::endl;
+ EXPECT_EQ(someip_tp_test::service.service_id, its_service);
+ EXPECT_EQ(someip_tp_test::service.event_id, its_method);
+ auto its_buffer = std::make_shared<vsomeip::message_buffer_t>(&receive_buffer[its_pos], &receive_buffer[its_pos] + its_message_size);
+ fragments_event_from_master_.push_back(its_buffer);
+ if (fragments_event_from_master_.size() == someip_tp_test::number_of_fragments) {
+ std::lock_guard<std::mutex> its_lock(all_fragments_received_mutex_);
+ wait_for_all_event_fragments_received_ = false;
+ std::cout << __LINE__ << ": received all event fragments as client --> Finished" << std::endl;
+ all_fragments_received_cond_.notify_one();
+ if (received_responses == 2) {
+ keep_receiving = false;
+ }
+ }
+
+ }
+ its_pos += its_message_size;
+ bytes_transferred -= its_message_size;
+ }
+ }
+ }
+ });
+
+ // send SOMEI-TP message fragmented into 6 parts to service:
+ boost::asio::ip::udp::socket::endpoint_type target_service(address_remote_, 30001);
+
+ std::unique_lock<std::mutex> its_lock(all_fragments_received_mutex_);
+ for (const order_e mode : {order_e::ASCENDING, order_e::DESCENDING}) {
+ create_fragments(someip_tp_test::number_of_fragments, someip_tp_test::service.service_id,
+ someip_tp_test::service.instance_id,
+ someip_tp_test::service.method_id,
+ vsomeip::message_type_e::MT_REQUEST,
+ vsomeip::ANY_CLIENT, 0xffff,
+ &fragments_request_to_master_,
+ (test_mode_ == someip_tp_test::test_mode_e::OVERLAP ||
+ test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) ?
+ vsomeip::tp::tp::tp_max_segment_length_ - 160 :
+ vsomeip::tp::tp::tp_max_segment_length_);
+ if (mode == order_e::ASCENDING) {
+ if (test_mode_ == someip_tp_test::test_mode_e::MIXED) {
+ if (someip_tp_test::number_of_fragments != 6) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ } else {
+ auto its_indexes = {4, 1, 3, 5, 2, 0};
+ std::cout << __LINE__ << ": using following predefined sequence to send request to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ for (int i : its_indexes) {
+ udp_client_socket.send_to(boost::asio::buffer(*fragments_request_to_master_[i]), target_service);
+ }
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) {
+ if (someip_tp_test::number_of_fragments != 6) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ } else {
+ auto its_indexes = {0,1,3,5,2,4};
+ std::cout << __LINE__ << ": using following predefined sequence to send request to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ // increase third segment by 16 byte at front and back
+ increase_segment_front_back(fragments_request_to_master_[2], 16);
+ increase_segment_front(fragments_request_to_master_[4], 16);
+ for (int i : its_indexes) {
+ udp_client_socket.send_to(boost::asio::buffer(*fragments_request_to_master_[i]), target_service);
+ }
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::DUPLICATE) {
+ if (someip_tp_test::number_of_fragments < 2) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ for (auto iter = fragments_request_to_master_.begin();
+ iter != fragments_request_to_master_.end(); iter++) {
+ udp_client_socket.send_to(boost::asio::buffer(*(*iter)), target_service);
+ // send insert 2nd fragment twice
+ if (iter == fragments_request_to_master_.begin() + 1) {
+ udp_client_socket.send_to(boost::asio::buffer(*(*iter)), target_service);
+ }
+ }
+ } else {
+ if (test_mode_ == someip_tp_test::test_mode_e::INCOMPLETE) {
+ if (someip_tp_test::number_of_fragments < 3) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // send a request fragment with a different session ID first
+ vsomeip::message_buffer_t msg_incomplete(*fragments_request_to_master_[2]);
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0x33;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0x33;
+ udp_client_socket.send_to(boost::asio::buffer(msg_incomplete), target_service);
+ // send a request from a different src port as well to test cleanup
+ boost::asio::ip::udp::socket udp_client_socket2(io_,
+ boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 30004));
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0xcc;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0xcc;
+ udp_client_socket2.send_to(boost::asio::buffer(msg_incomplete), target_service);
+ boost::system::error_code ec;
+ udp_client_socket2.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_client_socket2.close(ec);
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP) {
+ if (someip_tp_test::number_of_fragments < 2) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ increase_segment_back(fragments_request_to_master_[1], 16);
+ }
+ for (const auto& fragment : fragments_request_to_master_) {
+ udp_client_socket.send_to(boost::asio::buffer(*fragment), target_service);
+ }
+ }
+ } else if (mode == order_e::DESCENDING) {
+ if (test_mode_ == someip_tp_test::test_mode_e::MIXED) {
+ std::vector<int> its_indexes = create_shuffled_seqeuence(someip_tp_test::number_of_fragments);
+ std::cout << __LINE__ << ": using following random sequence to send request to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ for (int i : its_indexes) {
+ udp_client_socket.send_to(boost::asio::buffer(*fragments_request_to_master_[i]), target_service);
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) {
+ if (someip_tp_test::number_of_fragments != 6) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ } else {
+ auto its_indexes = {5,3,2,4,1,0};
+ std::cout << __LINE__ << ": using following predefined sequence to send request to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ // increase third segment by 16 byte at front and back
+ increase_segment_front_back(fragments_request_to_master_[4], 16);
+ for (int i : its_indexes) {
+ udp_client_socket.send_to(boost::asio::buffer(*fragments_request_to_master_[i]), target_service);
+ }
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::DUPLICATE) {
+ if (someip_tp_test::number_of_fragments < 2) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ for (auto iter = fragments_request_to_master_.rbegin();
+ iter != fragments_request_to_master_.rend(); iter++) {
+ udp_client_socket.send_to(boost::asio::buffer(*(*iter)), target_service);
+ // send insert 2nd last fragment twice
+ if (iter == fragments_request_to_master_.rbegin() + 1) {
+ udp_client_socket.send_to(boost::asio::buffer(*(*iter)), target_service);
+ }
+ }
+ } else {
+ if (test_mode_ == someip_tp_test::test_mode_e::INCOMPLETE) {
+ if (someip_tp_test::number_of_fragments < 4) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // send a request fragment with a different session ID first
+ vsomeip::message_buffer_t msg_incomplete(*fragments_request_to_master_[3]);
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0x77;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0x77;
+ udp_client_socket.send_to(boost::asio::buffer(msg_incomplete), target_service);
+
+ // send a request from a different src port as well to test cleanup
+ boost::asio::ip::udp::socket udp_client_socket2(io_,
+ boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 30005));
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0xdd;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0xdd;
+ udp_client_socket2.send_to(boost::asio::buffer(msg_incomplete), target_service);
+ boost::system::error_code ec;
+ udp_client_socket2.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_client_socket2.close(ec);
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP) {
+ if (someip_tp_test::number_of_fragments < 5) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // increase second last segment by 16 byte
+ increase_segment_back(fragments_request_to_master_[4], 16);
+ }
+ for (auto iter = fragments_request_to_master_.rbegin(); iter != fragments_request_to_master_.rend(); iter++) {
+ udp_client_socket.send_to(boost::asio::buffer(*(*iter)), target_service);
+ }
+ }
+ }
+ {
+ while (wait_for_all_response_fragments_received_) {
+ if (std::cv_status::timeout ==
+ all_fragments_received_cond_.wait_for(its_lock,
+ std::chrono::seconds(20))) {
+ ADD_FAILURE() << "Didn't receive response to"
+ " fragmented message within time: " << std::uint32_t(mode);
+ return;
+ } else {
+ EXPECT_EQ(someip_tp_test::number_of_fragments, fragments_request_to_master_.size());
+ // create complete message from request
+ if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP) {
+ if (mode == ASCENDING) {
+ if (someip_tp_test::number_of_fragments < 2) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // decrease second segment by 16 byte
+ decrease_segment_back(fragments_request_to_master_[1], 16);
+ } else if (mode == DESCENDING) {
+ if (someip_tp_test::number_of_fragments < 5) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // decrease fourth segment by 16 byte
+ decrease_segment_back(fragments_request_to_master_[4], 16);
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) {
+ // remove the additional inserted bytes which weren't accepted on
+ // test masterside as they were overlapping
+ if (mode == ASCENDING) {
+ decrease_segment_front_back(fragments_request_to_master_[2], 16);
+ decrease_segment_front(fragments_request_to_master_[4], 16);
+ } else {
+ decrease_segment_front_back(fragments_request_to_master_[4], 16);
+ }
+ }
+ vsomeip::message_buffer_t its_request = create_full_message(fragments_request_to_master_);
+ if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP ||
+ test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) {
+ EXPECT_EQ(VSOMEIP_FULL_HEADER_SIZE +
+ someip_tp_test::number_of_fragments * (someip_tp_test::max_segment_size - 160),
+ its_request.size());
+ } else {
+ EXPECT_EQ(VSOMEIP_FULL_HEADER_SIZE +
+ someip_tp_test::number_of_fragments * someip_tp_test::max_segment_size,
+ its_request.size());
+ }
+ if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP && mode == ASCENDING) {
+ // response contains the additional 16 bytes of 2nd fragment instead
+ // of beginning of the 3rd fragment
+ for (std::uint32_t i = 0; i < 16; i++) {
+ its_request[VSOMEIP_PAYLOAD_POS + 2 * (someip_tp_test::max_segment_size - 160) + i] = 0xff;
+ }
+ }
+
+ // create complete message from response
+ vsomeip::message_buffer_t its_response = create_full_message(fragments_response_of_master_);
+ if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP ||
+ test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) {
+ EXPECT_EQ(VSOMEIP_FULL_HEADER_SIZE +
+ someip_tp_test::number_of_fragments * (someip_tp_test::max_segment_size - 160),
+ its_response.size());
+ } else {
+ EXPECT_EQ(VSOMEIP_FULL_HEADER_SIZE +
+ someip_tp_test::number_of_fragments * someip_tp_test::max_segment_size,
+ its_response.size());
+ }
+ // change message type of response to request again
+ its_response[VSOMEIP_MESSAGE_TYPE_POS] = static_cast<vsomeip::byte_t>(vsomeip::message_type_e::MT_REQUEST);
+ // request and response should now be equal
+ EXPECT_EQ(its_response.size(), its_request.size());
+ EXPECT_EQ(its_response, its_request);
+ EXPECT_EQ(0, std::memcmp(static_cast<void*>(&its_response[0]),
+ static_cast<void*>(&its_request[0]),
+ its_response.size()));
+ fragments_response_of_master_.clear();
+ }
+ }
+ wait_for_all_response_fragments_received_ = true;
+ }
+ fragments_request_to_master_.clear();
+ }
+
+ while (wait_for_all_event_fragments_received_) {
+ if (std::cv_status::timeout ==
+ all_fragments_received_cond_.wait_for(its_lock,
+ std::chrono::seconds(20))) {
+ ADD_FAILURE() << "Didn't receive fragmented event from "
+ " master within time";
+ }
+ }
+ // check if received event is correct
+ {
+ EXPECT_EQ(someip_tp_test::number_of_fragments, fragments_event_from_master_.size());
+ // create complete message from event
+ vsomeip::message_buffer_t its_event = create_full_message(fragments_event_from_master_);
+ vsomeip::session_t its_event_session =
+ VSOMEIP_BYTES_TO_WORD(its_event[VSOMEIP_SESSION_POS_MIN],
+ its_event[VSOMEIP_SESSION_POS_MAX]);
+
+ std::vector<vsomeip::message_buffer_ptr_t> its_cmp_event_fragments;
+ create_fragments(someip_tp_test::number_of_fragments,
+ someip_tp_test::service.service_id,
+ someip_tp_test::service.instance_id,
+ someip_tp_test::service.event_id,
+ vsomeip::message_type_e::MT_NOTIFICATION,
+ 0x0, its_event_session, &its_cmp_event_fragments,
+ (test_mode_ == someip_tp_test::test_mode_e::OVERLAP) ?
+ vsomeip::tp::tp::tp_max_segment_length_ - 160 :
+ vsomeip::tp::tp::tp_max_segment_length_);
+ vsomeip::message_buffer_t its_cmp_event = create_full_message(its_cmp_event_fragments);
+ EXPECT_EQ(its_cmp_event.size(), its_event.size());
+ EXPECT_EQ(its_cmp_event, its_event);
+ EXPECT_EQ(0, std::memcmp(static_cast<void*>(&its_cmp_event[0]),
+ static_cast<void*>(&its_event[0]),
+ its_cmp_event.size()));
+ }
+ its_lock.unlock();
+ udp_client_receive_thread.join();
+ } catch (const std::exception& _e) {
+ ADD_FAILURE() << "catched exception: " << _e.what();
+ }
+ });
+
+ std::mutex all_fragments_received_as_server_mutex_;
+ std::unique_lock<std::mutex> all_fragments_received_as_server_lock(all_fragments_received_as_server_mutex_);
+ std::condition_variable all_fragments_received_as_server_cond_;
+ bool wait_for_all_fragments_received_as_server_(true);
+ std::atomic<std::uint16_t> remote_client_request_port(0);
+
+ std::thread udp_server_send_thread([&]() {
+ // wait until client subscribed
+ if (std::future_status::timeout == remote_client_subscribed.get_future().wait_for(std::chrono::seconds(10))) {
+ ADD_FAILURE() << "Client didn't subscribe within time";
+ return;
+ }
+
+ // send fragmented event to the master
+ boost::asio::ip::udp::socket::endpoint_type master_client(address_remote_, remote_client_subscription_port);
+ for (const order_e mode : {order_e::ASCENDING, order_e::DESCENDING}) {
+ create_fragments(someip_tp_test::number_of_fragments,
+ someip_tp_test::service_slave.service_id,
+ someip_tp_test::service_slave.instance_id,
+ someip_tp_test::service_slave.event_id,
+ vsomeip::message_type_e::MT_NOTIFICATION,
+ vsomeip::ANY_CLIENT, 0xffff,
+ &fragments_event_to_master_,
+ (test_mode_ == someip_tp_test::test_mode_e::OVERLAP ||
+ test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) ?
+ vsomeip::tp::tp::tp_max_segment_length_ - 160 :
+ vsomeip::tp::tp::tp_max_segment_length_);
+ if (mode == order_e::ASCENDING) {
+ if (test_mode_ == someip_tp_test::test_mode_e::MIXED) {
+ if (someip_tp_test::number_of_fragments != 6) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ } else {
+ auto its_indexes = {2, 3, 5, 1, 4, 0};
+ std::cout << __LINE__ << ": using following predefined sequence to send event to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ for (int i : its_indexes) {
+ udp_server_socket.send_to(boost::asio::buffer(*fragments_event_to_master_[i]), master_client);
+ }
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) {
+ if (someip_tp_test::number_of_fragments != 6) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ } else {
+ auto its_indexes = {0,2,4,5,1,3};
+ std::cout << __LINE__ << ": using following predefined sequence to send event to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ // increase second segment by 16 byte at front and back
+ increase_segment_front_back(fragments_event_to_master_[1], 16);
+ increase_segment_front(fragments_event_to_master_[3], 16);
+
+ for (int i : its_indexes) {
+ udp_server_socket.send_to(boost::asio::buffer(*fragments_event_to_master_[i]), master_client);
+ }
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::DUPLICATE) {
+ if (someip_tp_test::number_of_fragments < 2) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ for (auto iter = fragments_event_to_master_.begin();
+ iter != fragments_event_to_master_.end(); iter++) {
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ // send insert 2nd fragment twice
+ if (iter == fragments_event_to_master_.begin() + 1) {
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ // send oversized fragment as well
+ increase_segment_back(*iter, 4);
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ decrease_segment_back(*iter, 4);
+ }
+ }
+ } else {
+ if (test_mode_ == someip_tp_test::test_mode_e::INCOMPLETE) {
+ if (someip_tp_test::number_of_fragments < 3) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // send an event fragment with a different session ID first
+ vsomeip::message_buffer_t msg_incomplete(*fragments_event_to_master_[2]);
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0x44;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0x44;
+ udp_server_socket.send_to(boost::asio::buffer(msg_incomplete), master_client);
+ // send a request with a different service ID as well to test cleanup
+ msg_incomplete[VSOMEIP_SERVICE_POS_MIN] = 0xdd;
+ msg_incomplete[VSOMEIP_SERVICE_POS_MAX] = 0xdd;
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0xdd;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0xdd;
+ udp_server_socket.send_to(boost::asio::buffer(msg_incomplete), master_client);
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP) {
+ if (someip_tp_test::number_of_fragments < 2) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // increase second segment by 16 byte
+ increase_segment_back(fragments_event_to_master_[1], 16);
+
+ // send one oversize message as well
+ std::vector<vsomeip::message_buffer_ptr_t> oversized_event;
+ create_fragments(someip_tp_test::number_of_fragments + 1,
+ someip_tp_test::service_slave.service_id,
+ someip_tp_test::service_slave.instance_id,
+ someip_tp_test::service_slave.event_id,
+ vsomeip::message_type_e::MT_NOTIFICATION,
+ vsomeip::ANY_CLIENT, 0xffff,
+ &oversized_event,
+ vsomeip::tp::tp::tp_max_segment_length_);
+ for (const auto& fragment : oversized_event) {
+ udp_server_socket.send_to(boost::asio::buffer(*fragment), master_client);
+ }
+ }
+ for (const auto& fragment : fragments_event_to_master_) {
+ udp_server_socket.send_to(boost::asio::buffer(*fragment), master_client);
+ }
+ }
+ } else if (mode == order_e::DESCENDING) {
+ if (test_mode_ == someip_tp_test::test_mode_e::MIXED) {
+ std::vector<int> its_indexes = create_shuffled_seqeuence(someip_tp_test::number_of_fragments);
+ std::cout << __LINE__ << ": using following random sequence to send event to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ for ( int i : its_indexes) {
+ udp_server_socket.send_to(boost::asio::buffer(*fragments_event_to_master_[i]), master_client);
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) {
+ if (someip_tp_test::number_of_fragments != 6) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ } else {
+ auto its_indexes = {5,3,2,1,0,4};
+ std::cout << __LINE__ << ": using following predefined sequence to send event to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ // increase second last segment by 16 byte at front and back
+ increase_segment_front_back(fragments_event_to_master_[4], 16);
+ // update length
+ *(reinterpret_cast<vsomeip::length_t*>(&((*fragments_event_to_master_[4])[VSOMEIP_LENGTH_POS_MIN]))) =
+ htonl(static_cast<vsomeip::length_t>(fragments_event_to_master_[4]->size() - VSOMEIP_SOMEIP_HEADER_SIZE));
+ for (int i : its_indexes) {
+ udp_server_socket.send_to(boost::asio::buffer(*fragments_event_to_master_[i]), master_client);
+ }
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::DUPLICATE) {
+ if (someip_tp_test::number_of_fragments < 2) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ for (auto iter = fragments_event_to_master_.rbegin();
+ iter != fragments_event_to_master_.rend(); iter++) {
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ // send insert 2nd last fragment twice
+ if (iter == fragments_event_to_master_.rbegin() + 1) {
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ }
+ }
+ } else {
+ if (test_mode_ == someip_tp_test::test_mode_e::INCOMPLETE) {
+ if (someip_tp_test::number_of_fragments < 4) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // send an event fragment with a different session ID first
+ vsomeip::message_buffer_t msg_incomplete(*fragments_event_to_master_[3]);
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0x55;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0x55;
+ udp_server_socket.send_to(boost::asio::buffer(msg_incomplete), master_client);
+ // send a request with a different service ID as well to test cleanup
+ msg_incomplete[VSOMEIP_SERVICE_POS_MIN] = 0xbb;
+ msg_incomplete[VSOMEIP_SERVICE_POS_MAX] = 0xbb;
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0xbb;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0xbb;
+ udp_server_socket.send_to(boost::asio::buffer(msg_incomplete), master_client);
+
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP) {
+ if (someip_tp_test::number_of_fragments < 5) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // increase second last segment by 16 byte
+ increase_segment_back(fragments_event_to_master_[4], 16);
+ }
+ for (auto iter = fragments_event_to_master_.rbegin(); iter != fragments_event_to_master_.rend(); iter++) {
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ }
+ }
+ }
+ std::cout << __LINE__ << ": send event to master " << std::uint32_t(mode) << std::endl;
+ }
+
+ for (const order_e mode : {order_e::ASCENDING, order_e::DESCENDING}) {
+ while (wait_for_all_fragments_received_as_server_) {
+ if (std::cv_status::timeout ==
+ all_fragments_received_as_server_cond_.wait_for(all_fragments_received_as_server_lock,
+ std::chrono::seconds(20))) {
+ ADD_FAILURE() << "Didn't receive request from client within time: " << std::uint32_t(mode);
+ return;
+ } else {
+ EXPECT_EQ(someip_tp_test::number_of_fragments, fragments_received_as_server_.size());
+ // create complete message from request of client
+ vsomeip::message_buffer_t its_request = create_full_message(fragments_received_as_server_);
+ if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP ||
+ test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) {
+ EXPECT_EQ(VSOMEIP_FULL_HEADER_SIZE +
+ someip_tp_test::number_of_fragments * (someip_tp_test::max_segment_size - 160),
+ its_request.size());
+ } else {
+ EXPECT_EQ(VSOMEIP_FULL_HEADER_SIZE +
+ someip_tp_test::number_of_fragments * someip_tp_test::max_segment_size,
+ its_request.size());
+ }
+ const vsomeip::client_t its_request_client =
+ VSOMEIP_BYTES_TO_WORD(its_request[VSOMEIP_CLIENT_POS_MIN],
+ its_request[VSOMEIP_CLIENT_POS_MAX]);
+ const vsomeip::session_t its_request_session =
+ VSOMEIP_BYTES_TO_WORD(its_request[VSOMEIP_SESSION_POS_MIN],
+ its_request[VSOMEIP_SESSION_POS_MAX]);
+ create_fragments(someip_tp_test::number_of_fragments,
+ someip_tp_test::service_slave.service_id,
+ someip_tp_test::service_slave.instance_id,
+ someip_tp_test::service_slave.method_id,
+ vsomeip::message_type_e::MT_RESPONSE,
+ its_request_client,
+ its_request_session,
+ &fragments_response_to_master_,
+ (test_mode_ == someip_tp_test::test_mode_e::OVERLAP ||
+ test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) ?
+ vsomeip::tp::tp::tp_max_segment_length_ - 160:
+ vsomeip::tp::tp::tp_max_segment_length_);
+ // create complete message from response
+ vsomeip::message_buffer_t its_response = create_full_message(fragments_response_to_master_);
+ // change the message type of the response to request for comparison
+ its_response[VSOMEIP_MESSAGE_TYPE_POS] = static_cast<vsomeip::byte_t>(vsomeip::message_type_e::MT_REQUEST);
+
+ EXPECT_EQ(its_response.size(), its_request.size());
+ EXPECT_EQ(its_response, its_request);
+ EXPECT_EQ(0, std::memcmp(static_cast<void*>(&its_response[0]),
+ static_cast<void*>(&its_request[0]),
+ its_response.size()));
+ // send back response
+ fragments_received_as_server_.clear();
+ EXPECT_GT(remote_client_request_port, 0);
+ boost::asio::ip::udp::socket::endpoint_type master_client(address_remote_, remote_client_request_port);
+ if (mode == order_e::ASCENDING) {
+ if (test_mode_ == someip_tp_test::test_mode_e::MIXED) {
+ if (someip_tp_test::number_of_fragments != 6) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ } else {
+ auto its_indexes = {4,2,0,1,3,5};
+ std::cout << __LINE__ << ": using following predefined sequence to send back response to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ for (int i : its_indexes) {
+ udp_server_socket.send_to(boost::asio::buffer(*fragments_response_to_master_[i]), master_client);
+ }
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) {
+ if (someip_tp_test::number_of_fragments != 6) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ } else {
+ auto its_indexes = {0,2,4,3,5,1};
+ std::cout << __LINE__ << ": using following predefined sequence to send response to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ // increase fourth segment by 16 byte at front and back
+ increase_segment_front_back(fragments_response_to_master_[3], 16);
+ increase_segment_front(fragments_response_to_master_[1], 16);
+ for (int i : its_indexes) {
+ udp_server_socket.send_to(boost::asio::buffer(*fragments_response_to_master_[i]), master_client);
+ }
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::DUPLICATE) {
+ if (someip_tp_test::number_of_fragments < 2) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ for (auto iter = fragments_response_to_master_.begin();
+ iter != fragments_response_to_master_.end(); iter++) {
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ // send 2nd fragment twice
+ if (iter == fragments_response_to_master_.begin() + 1) {
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ // send a fragment with invalid segment size as well
+ decrease_segment_back(*iter, 16);
+ increase_segment_back(*iter, 7);
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ increase_segment_back(*iter, 9);
+ }
+ }
+ } else {
+ if (test_mode_ == someip_tp_test::test_mode_e::INCOMPLETE) {
+ if (someip_tp_test::number_of_fragments < 5) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // send an event fragment with a different session ID first
+ vsomeip::message_buffer_t msg_incomplete(*fragments_response_to_master_[4]);
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0x99;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0x99;
+ udp_server_socket.send_to(boost::asio::buffer(msg_incomplete), master_client);
+ // send a request with a different service ID as well to test cleanup
+ msg_incomplete[VSOMEIP_SERVICE_POS_MIN] = 0xaa;
+ msg_incomplete[VSOMEIP_SERVICE_POS_MAX] = 0xaa;
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0xaa;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0xaa;
+ udp_server_socket.send_to(boost::asio::buffer(msg_incomplete), master_client);
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP) {
+ if (someip_tp_test::number_of_fragments < 2) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // increase second segment by 16 byte
+ increase_segment_back(fragments_response_to_master_[1], 16);
+ }
+ for (const auto& frag : fragments_response_to_master_) {
+ udp_server_socket.send_to(boost::asio::buffer(*frag), master_client);
+ }
+ }
+ } else if (mode == order_e::DESCENDING) {
+ if (test_mode_ == someip_tp_test::test_mode_e::MIXED) {
+ std::vector<int> its_indexes = create_shuffled_seqeuence(someip_tp_test::number_of_fragments);
+ std::cout << __LINE__ << ": using following random sequence to send back response to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ for ( int i : its_indexes) {
+ udp_server_socket.send_to(boost::asio::buffer(*fragments_response_to_master_[i]), master_client);
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) {
+ if (someip_tp_test::number_of_fragments != 6) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ } else {
+ auto its_indexes = {5,3,2,1,4,0};
+ std::cout << __LINE__ << ": using following predefined sequence to send response to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ // increase fith segment by 16 byte at front and back
+ increase_segment_front_back(fragments_response_to_master_[4], 16);
+ for (int i : its_indexes) {
+ udp_server_socket.send_to(boost::asio::buffer(*fragments_response_to_master_[i]), master_client);
+ }
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::DUPLICATE) {
+ if (someip_tp_test::number_of_fragments < 2) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ for (auto iter = fragments_response_to_master_.rbegin();
+ iter != fragments_response_to_master_.rend(); iter++) {
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ // send insert 2nd last fragment twice
+ if (iter == fragments_response_to_master_.rbegin() + 1) {
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ }
+ }
+ } else {
+ if (test_mode_ == someip_tp_test::test_mode_e::INCOMPLETE) {
+ if (someip_tp_test::number_of_fragments < 4) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // send an event fragment with a different session ID first
+ vsomeip::message_buffer_t msg_incomplete(*fragments_response_to_master_[3]);
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0x66;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0x66;
+ udp_server_socket.send_to(boost::asio::buffer(msg_incomplete), master_client);
+ // send a request with a different service ID as well to test cleanup
+ msg_incomplete[VSOMEIP_SERVICE_POS_MIN] = 0xef;
+ msg_incomplete[VSOMEIP_SERVICE_POS_MAX] = 0xef;
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0xef;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0xef;
+ udp_server_socket.send_to(boost::asio::buffer(msg_incomplete), master_client);
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP) {
+ if (someip_tp_test::number_of_fragments < 5) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // increase second last segment by 16 byte
+ increase_segment_back(fragments_response_to_master_[4], 16);
+ }
+ for (auto iter = fragments_response_to_master_.rbegin();
+ iter != fragments_response_to_master_.rend(); iter++) {
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ }
+ }
+ }
+ }
+ }
+ wait_for_all_fragments_received_as_server_ = true;
+ }
+ });
+
+ std::thread udp_server_receive_thread([&]() {
+ {
+ std::lock_guard<std::mutex> its_lock(udp_sd_socket_mutex);
+ offer_service(&udp_sd_socket);
+ }
+
+ bool keep_receiving(true);
+ std::vector<std::uint8_t> receive_buffer(4096);
+ while (keep_receiving) {
+ boost::system::error_code error;
+ boost::asio::ip::udp::socket::endpoint_type its_remote_endpoint;
+ std::size_t bytes_transferred = udp_server_socket.receive_from(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), its_remote_endpoint, 0, error);
+ if (error) {
+ keep_receiving = false;
+ ADD_FAILURE() << __func__ << " error: " << error.message();
+ return;
+ } else {
+ remote_client_request_port = its_remote_endpoint.port();
+ std::uint32_t its_pos = 0;
+ while (bytes_transferred > 0) {
+ const std::uint32_t its_message_size = VSOMEIP_BYTES_TO_LONG(
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 1],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 2],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 3]) + VSOMEIP_SOMEIP_HEADER_SIZE;
+ std::cout << __LINE__ << ": received request from master " << its_message_size << std::endl;
+ vsomeip::deserializer its_deserializer(&receive_buffer[its_pos], its_message_size, 0);
+
+ vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MAX]);
+ vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_METHOD_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_METHOD_POS_MAX]);
+ EXPECT_EQ(someip_tp_test::service_slave.service_id, its_service);
+ EXPECT_EQ(someip_tp_test::service_slave.method_id, its_method);
+ vsomeip::message_impl msg;
+ EXPECT_TRUE(msg.deserialize(&its_deserializer));
+ if (vsomeip::tp::tp::tp_flag_is_set(receive_buffer[its_pos + VSOMEIP_MESSAGE_TYPE_POS])) {
+ auto its_buffer = std::make_shared<vsomeip::message_buffer_t>(&receive_buffer[its_pos], &receive_buffer[its_pos] + its_message_size);
+
+ fragments_received_as_server_.push_back(its_buffer);
+ if (fragments_received_as_server_.size() == someip_tp_test::number_of_fragments) {
+ std::lock_guard<std::mutex> its_lock(all_fragments_received_as_server_mutex_);
+ wait_for_all_fragments_received_as_server_ = false;
+ std::cout << __LINE__ << ": received all fragments as server" << std::endl;
+ all_fragments_received_as_server_cond_.notify_one();
+ static int received_requests = 0;
+ if (++received_requests == 2) {
+ std::cout << __LINE__ << ": received all requests as server --> Finished" << std::endl;
+ keep_receiving = false;
+ }
+ }
+ }
+ its_pos += its_message_size;
+ bytes_transferred -= its_message_size;
+ }
+ }
+ }
+ });
+
+ send_thread.join();
+ sd_receive_thread.join();
+ udp_server_receive_thread.join();
+ udp_server_send_thread.join();
+
+ if (test_mode_ == someip_tp_test::test_mode_e::INCOMPLETE) {
+ std::cout << "Sleeping to let cleanup for unfinished TP message "
+ "trigger on master side..." << std::endl;
+ std::this_thread::sleep_for(std::chrono::seconds(11));
+ }
+ // shutdown the server
+ call_shutdown_method();
+
+ boost::system::error_code ec;
+ udp_sd_socket.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_sd_socket.close(ec);
+ udp_client_socket.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_client_socket.close(ec);
+ udp_server_socket.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_server_socket.close(ec);
+}
+
+#if defined(__linux__) || defined(ANDROID)
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ if(argc < 3) {
+ std::cerr << "Please pass an target, local IP address and test mode to this binary like: "
+ << argv[0] << " 10.0.3.1 10.0.3.202 TP_IN_SEQUENCE" << std::endl;
+ std::cerr << "Testmodes are [ IN_SEQUENCE, MIXED, INCOMPLETE, OVERLAP, OVERLAP_FRONT_BACK ]" << std::endl;
+ } else {
+ remote_address = argv[1];
+ local_address = argv[2];
+ std::string its_testmode = argv[3];
+ if (its_testmode == std::string("IN_SEQUENCE")) {
+ ::testing::GTEST_FLAG(filter) = "*send_in_mode/0";
+ } else if (its_testmode == std::string("MIXED")) {
+ ::testing::GTEST_FLAG(filter) = "*send_in_mode/1";
+ } else if (its_testmode == std::string("INCOMPLETE")) {
+ ::testing::GTEST_FLAG(filter) = "*send_in_mode/2";
+ } else if (its_testmode == std::string("DUPLICATE")) {
+ ::testing::GTEST_FLAG(filter) = "*send_in_mode/3";
+ } else if (its_testmode == std::string("OVERLAP")) {
+ ::testing::GTEST_FLAG(filter) = "*send_in_mode/4";
+ } else if (its_testmode == std::string("OVERLAP_FRONT_BACK")) {
+ ::testing::GTEST_FLAG(filter) = "*send_in_mode/5";
+ }
+ }
+ return RUN_ALL_TESTS();
+}
+#endif