summaryrefslogtreecommitdiff
path: root/test/network_tests/application_tests
diff options
context:
space:
mode:
Diffstat (limited to 'test/network_tests/application_tests')
-rw-r--r--test/network_tests/application_tests/application_test.cpp479
-rw-r--r--test/network_tests/application_tests/application_test_availability.cpp39
-rwxr-xr-xtest/network_tests/application_tests/application_test_availability_starter.sh10
-rw-r--r--test/network_tests/application_tests/application_test_client.cpp199
-rw-r--r--test/network_tests/application_tests/application_test_client_availability.cpp203
-rw-r--r--test/network_tests/application_tests/application_test_daemon.cpp42
-rw-r--r--test/network_tests/application_tests/application_test_globals.hpp28
-rw-r--r--test/network_tests/application_tests/application_test_service.cpp128
-rw-r--r--test/network_tests/application_tests/application_test_single_process.cpp47
-rw-r--r--test/network_tests/application_tests/application_test_single_process.json14
-rwxr-xr-xtest/network_tests/application_tests/application_test_single_process_starter.sh23
-rwxr-xr-xtest/network_tests/application_tests/application_test_starter.sh61
-rw-r--r--test/network_tests/application_tests/conf/application_test.json.in38
-rw-r--r--test/network_tests/application_tests/conf/application_test_daemon.json.in38
-rw-r--r--test/network_tests/application_tests/conf/application_test_no_dispatch_threads.json.in37
-rw-r--r--test/network_tests/application_tests/conf/application_test_no_dispatch_threads_daemon.json.in37
16 files changed, 1423 insertions, 0 deletions
diff --git a/test/network_tests/application_tests/application_test.cpp b/test/network_tests/application_tests/application_test.cpp
new file mode 100644
index 0000000..c7ad4f8
--- /dev/null
+++ b/test/network_tests/application_tests/application_test.cpp
@@ -0,0 +1,479 @@
+// 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 <thread>
+#include <mutex>
+#include <condition_variable>
+#include <future>
+
+#include <gtest/gtest.h>
+
+#include <vsomeip/vsomeip.hpp>
+
+#include "someip_test_globals.hpp"
+
+using namespace vsomeip;
+
+class someip_application_test: public ::testing::Test {
+public:
+ someip_application_test() :
+ registered_(false) {
+
+ }
+protected:
+ void SetUp() {
+ app_ = runtime::get()->create_application("application_test");
+ if (!app_->init()) {
+ ADD_FAILURE() << "Couldn't initialize application";
+ return;
+ }
+
+ app_->register_state_handler(
+ std::bind(&someip_application_test::on_state, this,
+ std::placeholders::_1));
+ }
+
+ void on_state(vsomeip::state_type_e _state) {
+ registered_ = (_state == vsomeip::state_type_e::ST_REGISTERED);
+ }
+
+ bool registered_;
+ std::shared_ptr<application> app_;
+};
+
+/**
+ * @test Start and stop application
+ */
+TEST_F(someip_application_test, start_stop_application)
+{
+ std::promise<bool> its_promise;
+ std::thread t([&](){
+ its_promise.set_value(true);
+ app_->start();
+ });
+ EXPECT_TRUE(its_promise.get_future().get());
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ app_->stop();
+ t.join();
+}
+
+/**
+ * @test Start and stop application multiple times
+ */
+TEST_F(someip_application_test, start_stop_application_multiple)
+{
+ for (int i = 0; i < 10; ++i) {
+ std::promise<bool> its_promise;
+ std::thread t([&]() {
+ its_promise.set_value(true);
+ app_->start();
+ });
+ EXPECT_TRUE(its_promise.get_future().get());
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ app_->stop();
+ t.join();
+ }
+}
+
+/**
+ * @test Start and stop application multiple times and offer a service
+ */
+TEST_F(someip_application_test, start_stop_application_multiple_offer_service)
+{
+ for (int i = 0; i < 10; ++i) {
+ std::promise<bool> its_promise;
+ std::thread t([&]() {
+ its_promise.set_value(true);
+ app_->start();
+ });
+ EXPECT_TRUE(its_promise.get_future().get());
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ app_->offer_service(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID);
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ app_->stop_offer_service(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID);
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ app_->stop();
+ t.join();
+ }
+}
+
+/**
+ * @test Try to start an already running application again
+ */
+TEST_F(someip_application_test, restart_without_stopping)
+{
+ std::promise<bool> its_promise;
+ std::thread t([&]() {
+ its_promise.set_value(true);
+ app_->start();
+
+ });
+ EXPECT_TRUE(its_promise.get_future().get());
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ VSOMEIP_WARNING << "An error message should appear now";
+ // should print error
+ app_->start();
+ app_->stop();
+ t.join();
+}
+
+/**
+ * @test Try to stop a running application twice
+ */
+TEST_F(someip_application_test, stop_application_twice)
+{
+ std::promise<bool> its_promise;
+ std::thread t([&]() {
+ its_promise.set_value(true);
+ app_->start();
+
+ });
+ EXPECT_TRUE(its_promise.get_future().get());
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ app_->stop();
+ t.join();
+ app_->stop();
+}
+
+/**
+ * @test Checks whether watchdog handler is invoked (regularly) also after restarting.
+ */
+TEST_F(someip_application_test, watchdog_handler)
+{
+ std::atomic<int> cb_count(0);
+ auto wd_handler = [&] () {
+ ++cb_count;
+ };
+
+ app_->set_watchdog_handler(std::cref(wd_handler), std::chrono::seconds(1));
+
+ std::promise<bool> its_promise;
+ std::thread t([&]() {
+ its_promise.set_value(true);
+ app_->start();
+ });
+ EXPECT_TRUE(its_promise.get_future().get());
+
+ // wait till watchdog handler has been invoked once
+ while (0 == cb_count.load()) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ }
+ ASSERT_EQ(1, cb_count.load());
+
+ // clear handler (must not be called again)
+ app_->set_watchdog_handler(nullptr, std::chrono::seconds::zero());
+
+ // wait doubled interval (used previously)..
+ std::this_thread::sleep_for(std::chrono::seconds(2));
+ // .. to ensure it was not called again
+ ASSERT_EQ(1, cb_count.load());
+
+ // enable handler again
+ app_->set_watchdog_handler(std::cref(wd_handler), std::chrono::seconds(1));
+
+ // wait till watchdog handler has been invoked again (2nd time)
+ while (1 == cb_count.load()) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ }
+
+ app_->stop();
+ t.join();
+
+ // wait doubled interval (used previously)..
+ std::this_thread::sleep_for(std::chrono::seconds(2));
+ // .. to ensure it was not called after stop()
+ ASSERT_EQ(2, cb_count.load());
+
+ // restart application (w/ watchdog handler still set)
+ std::promise<bool> its_promise2;
+ std::thread t2([&]() {
+ its_promise2.set_value(true);
+ app_->start();
+ });
+ EXPECT_TRUE(its_promise2.get_future().get());
+
+ // wait till watchdog handler has been invoked again (3rd time)
+ while (2 == cb_count.load()) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ }
+ ASSERT_EQ(3, cb_count.load());
+
+ // clear handler again (must not be called again), this time via zero interval
+ app_->set_watchdog_handler(std::cref(wd_handler), std::chrono::seconds::zero());
+
+ // wait doubled interval (used previously)..
+ std::this_thread::sleep_for(std::chrono::seconds(2));
+ // .. to ensure it was not called again
+ ASSERT_EQ(3, cb_count.load());
+
+ app_->stop();
+ t2.join();
+}
+
+class someip_application_shutdown_test: public ::testing::Test {
+
+protected:
+ void SetUp() {
+ is_registered_ = false;
+ is_available_ = false;
+
+ app_ = runtime::get()->create_application("application_test");
+ if (!app_->init()) {
+ ADD_FAILURE() << "Couldn't initialize application";
+ return;
+ }
+
+ app_->register_message_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
+ vsomeip_test::TEST_SERVICE_INSTANCE_ID,
+ vsomeip_test::TEST_SERVICE_METHOD_ID_SHUTDOWN,
+ std::bind(&someip_application_shutdown_test::on_message_shutdown, this,
+ std::placeholders::_1));
+
+ app_->register_state_handler(
+ std::bind(&someip_application_shutdown_test::on_state, this,
+ std::placeholders::_1));
+ app_->register_availability_handler(
+ vsomeip_test::TEST_SERVICE_SERVICE_ID,
+ vsomeip_test::TEST_SERVICE_INSTANCE_ID,
+ std::bind(&someip_application_shutdown_test::on_availability,
+ this, std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3));
+
+ shutdown_thread_ = std::thread(&someip_application_shutdown_test::send_shutdown_message, this);
+
+ app_->start();
+ }
+
+ void TearDown() {
+ shutdown_thread_.join();
+ app_->stop();
+ app_.reset();
+ std::this_thread::sleep_for(std::chrono::milliseconds(5));
+ }
+
+ void on_state(vsomeip::state_type_e _state) {
+ if(_state == vsomeip::state_type_e::ST_REGISTERED)
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ is_registered_ = true;
+ cv_.notify_one();
+ }
+ }
+
+ void on_availability(vsomeip::service_t _service,
+ vsomeip::instance_t _instance, bool _is_available) {
+ (void)_service;
+ (void)_instance;
+ if(_is_available) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ is_available_ = _is_available;
+ cv_.notify_one();
+ }
+ }
+
+ void on_message_shutdown(const std::shared_ptr<message>& _request)
+ {
+ (void)_request;
+ VSOMEIP_INFO << "Shutdown method was called, going down now.";
+ app_->clear_all_handler();
+ app_->stop();
+ }
+
+ void send_shutdown_message() {
+ {
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ while (!is_registered_) {
+ if (std::cv_status::timeout
+ == cv_.wait_for(its_lock, std::chrono::seconds(10))) {
+ ADD_FAILURE()<< "Application wasn't registered in time!";
+ is_registered_ = true;
+ }
+ }
+ app_->request_service(vsomeip_test::TEST_SERVICE_SERVICE_ID,
+ vsomeip_test::TEST_SERVICE_INSTANCE_ID);
+ app_->offer_service(vsomeip_test::TEST_SERVICE_SERVICE_ID,
+ vsomeip_test::TEST_SERVICE_INSTANCE_ID);
+ while (!is_available_) {
+ if (std::cv_status::timeout
+ == cv_.wait_for(its_lock, std::chrono::seconds(10))) {
+ ADD_FAILURE()<< "Service didn't become available in time!";
+ is_available_ = true;
+ }
+ }
+ }
+
+ std::shared_ptr<message> r = runtime::get()->create_request();
+ r->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID);
+ r->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID);
+ r->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID_SHUTDOWN);
+ app_->send(r);
+ }
+
+ bool is_registered_;
+ bool is_available_;
+ std::shared_ptr<application> app_;
+ std::condition_variable cv_;
+ std::mutex mutex_;
+ std::thread shutdown_thread_;
+};
+
+class someip_application_exception_test: public ::testing::Test {
+
+protected:
+ void SetUp() {
+ is_registered_ = false;
+ is_available_ = false;
+ exception_method_called_ = false;
+
+ app_ = runtime::get()->create_application("application_test");
+ if (!app_->init()) {
+ ADD_FAILURE() << "Couldn't initialize application";
+ return;
+ }
+
+ app_->register_message_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
+ vsomeip_test::TEST_SERVICE_INSTANCE_ID,
+ vsomeip_test::TEST_SERVICE_METHOD_ID_SHUTDOWN,
+ std::bind(&someip_application_exception_test::on_message_shutdown, this,
+ std::placeholders::_1));
+ app_->register_message_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID,
+ vsomeip_test::TEST_SERVICE_INSTANCE_ID,
+ vsomeip_test::TEST_SERVICE_METHOD_ID_SHUTDOWN+1,
+ std::bind(&someip_application_exception_test::on_message_exception, this,
+ std::placeholders::_1));
+
+ app_->register_state_handler(
+ std::bind(&someip_application_exception_test::on_state, this,
+ std::placeholders::_1));
+ app_->register_availability_handler(
+ vsomeip_test::TEST_SERVICE_SERVICE_ID,
+ vsomeip_test::TEST_SERVICE_INSTANCE_ID,
+ std::bind(&someip_application_exception_test::on_availability,
+ this, std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3));
+
+ shutdown_thread_ = std::thread(&someip_application_exception_test::send_shutdown_message, this);
+
+ app_->start();
+ }
+
+ void TearDown() {
+ shutdown_thread_.join();
+ app_->stop();
+ app_.reset();
+ std::this_thread::sleep_for(std::chrono::milliseconds(5));
+ }
+
+ void on_state(vsomeip::state_type_e _state) {
+ if(_state == vsomeip::state_type_e::ST_REGISTERED)
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ is_registered_ = true;
+ cv_.notify_one();
+ }
+ }
+
+ void on_availability(vsomeip::service_t _service,
+ vsomeip::instance_t _instance, bool _is_available) {
+ (void)_service;
+ (void)_instance;
+ if(_is_available) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ is_available_ = _is_available;
+ cv_.notify_one();
+ }
+ }
+
+ void on_message_shutdown(const std::shared_ptr<message>& _request)
+ {
+ (void)_request;
+ VSOMEIP_INFO << "Shutdown method was called, going down now.";
+ app_->clear_all_handler();
+ app_->stop();
+ }
+
+ void on_message_exception(const std::shared_ptr<message>& _request)
+ {
+ (void)_request;
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ exception_method_called_ = true;
+ cv_.notify_one();
+ }
+ throw std::invalid_argument("something went terribly wrong");
+ }
+
+ void send_shutdown_message() {
+ {
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ while(!is_registered_) {
+ cv_.wait(its_lock);
+ }
+ app_->request_service(vsomeip_test::TEST_SERVICE_SERVICE_ID,
+ vsomeip_test::TEST_SERVICE_INSTANCE_ID);
+ app_->offer_service(vsomeip_test::TEST_SERVICE_SERVICE_ID,
+ vsomeip_test::TEST_SERVICE_INSTANCE_ID);
+ while(!is_available_) {
+ cv_.wait(its_lock);
+ }
+ }
+
+ std::shared_ptr<message> r = runtime::get()->create_request();
+ // call method which throws exception
+ r->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID);
+ r->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID);
+ r->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID_SHUTDOWN+1);
+ app_->send(r);
+
+ {
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ while (!exception_method_called_) {
+ cv_.wait(its_lock);
+ }
+ }
+
+
+ //shutdown test
+ r->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID);
+ r->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID);
+ r->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID_SHUTDOWN);
+ app_->send(r);
+ }
+
+ bool is_registered_;
+ bool is_available_;
+ bool exception_method_called_;
+ std::shared_ptr<application> app_;
+ std::condition_variable cv_;
+ std::mutex mutex_;
+ std::thread shutdown_thread_;
+};
+
+/**
+ * @test Stop the application through a method invoked from a dispatcher thread
+ */
+TEST_F(someip_application_shutdown_test, stop_application_from_dispatcher_thread) {
+
+}
+
+/**
+ * @test Catch unhandled exceptions from invoked handlers
+ */
+TEST_F(someip_application_exception_test, catch_exception_in_invoked_handler) {
+
+}
+
+#if defined(__linux__) || defined(ANDROID)
+int main(int argc, char** argv)
+{
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+#endif
+
+
+
+
diff --git a/test/network_tests/application_tests/application_test_availability.cpp b/test/network_tests/application_tests/application_test_availability.cpp
new file mode 100644
index 0000000..89d94c1
--- /dev/null
+++ b/test/network_tests/application_tests/application_test_availability.cpp
@@ -0,0 +1,39 @@
+// Copyright (C) 2014-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 <gtest/gtest.h>
+
+#include "application_test_client_availability.cpp"
+#include "application_test_service.cpp"
+#include "application_test_daemon.cpp"
+
+TEST(someip_application_test_availability, register_availability_handlers)
+{
+ // start application acting as daemon
+ application_test_daemon its_daemon;
+
+ // start receiver service
+ application_test_service its_receiver(application_test::service);
+
+ // start client
+ application_test_client_availability its_client(application_test::service);
+ int counter(0);
+ while (!its_client.all_availability_handlers_called() && counter < 500) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ counter++;
+ }
+
+ //shutdown
+ its_receiver.stop();
+ its_client.stop();
+ its_daemon.stop();
+}
+
+#if defined(__linux__) || defined(ANDROID)
+int main(int argc, char** argv)
+{
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+#endif
diff --git a/test/network_tests/application_tests/application_test_availability_starter.sh b/test/network_tests/application_tests/application_test_availability_starter.sh
new file mode 100755
index 0000000..645e347
--- /dev/null
+++ b/test/network_tests/application_tests/application_test_availability_starter.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+# 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/.
+
+export VSOMEIP_CONFIGURATION=application_test_single_process.json
+./application_test_availability
+
+ exit $? \ No newline at end of file
diff --git a/test/network_tests/application_tests/application_test_client.cpp b/test/network_tests/application_tests/application_test_client.cpp
new file mode 100644
index 0000000..30d0084
--- /dev/null
+++ b/test/network_tests/application_tests/application_test_client.cpp
@@ -0,0 +1,199 @@
+// Copyright (C) 2014-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 <chrono>
+#include <condition_variable>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <thread>
+#include <map>
+#include <algorithm>
+#include <future>
+#include <atomic>
+
+#include <gtest/gtest.h>
+
+#include <vsomeip/vsomeip.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+#include "application_test_globals.hpp"
+
+class application_test_client {
+public:
+ application_test_client(struct application_test::service_info _service_info) :
+ service_info_(_service_info),
+ app_(vsomeip::runtime::get()->create_application("client")),
+ wait_until_registered_(true),
+ wait_until_service_available_(true),
+ wait_for_stop_(true),
+ received_responses_(0),
+ sent_requests_(0),
+ stop_called_(false),
+ stop_thread_(std::bind(&application_test_client::wait_for_stop, this)),
+ send_thread_(std::bind(&application_test_client::send, this)) {
+ if (!app_->init()) {
+ ADD_FAILURE() << "Couldn't initialize application";
+ return;
+ }
+ app_->register_state_handler(
+ std::bind(&application_test_client::on_state, this,
+ std::placeholders::_1));
+
+ app_->register_message_handler(vsomeip::ANY_SERVICE,
+ vsomeip::ANY_INSTANCE, vsomeip::ANY_METHOD,
+ std::bind(&application_test_client::on_message, this,
+ std::placeholders::_1));
+
+ // register availability for all other services and request their event.
+ app_->register_availability_handler(service_info_.service_id,
+ service_info_.instance_id,
+ std::bind(&application_test_client::on_availability, this,
+ std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3));
+ app_->request_service(service_info_.service_id,
+ service_info_.instance_id);
+ std::promise<bool> its_promise;
+ application_thread_ = std::thread([&](){
+ its_promise.set_value(true);
+ app_->start();
+ });
+ EXPECT_TRUE(its_promise.get_future().get());
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ }
+
+ ~application_test_client() {
+ send_thread_.join();
+ stop_thread_.join();
+ application_thread_.join();
+ }
+
+ void on_state(vsomeip::state_type_e _state) {
+ VSOMEIP_INFO << "Application " << app_->get_name() << " is "
+ << (_state == vsomeip::state_type_e::ST_REGISTERED ?
+ "registered." : "deregistered.");
+
+ if (_state == vsomeip::state_type_e::ST_REGISTERED) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_until_registered_ = false;
+ condition_.notify_one();
+ }
+ }
+
+ void on_availability(vsomeip::service_t _service,
+ vsomeip::instance_t _instance, bool _is_available) {
+ VSOMEIP_INFO << "Service [" << std::setw(4)
+ << std::setfill('0') << std::hex << _service << "." << _instance
+ << "] is " << (_is_available ? "available":"not available") << ".";
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ if(_is_available) {
+ wait_until_service_available_ = false;
+ condition_.notify_one();
+ } else {
+ wait_until_service_available_ = true;
+ condition_.notify_one();
+ }
+ }
+
+ void on_message(const std::shared_ptr<vsomeip::message> &_message) {
+ ++received_responses_;
+ EXPECT_EQ(service_info_.service_id, _message->get_service());
+ EXPECT_EQ(service_info_.method_id, _message->get_method());
+ EXPECT_EQ(service_info_.instance_id, _message->get_instance());
+ VSOMEIP_INFO << "Received a response with Client/Session [" << std::setw(4)
+ << std::setfill('0') << std::hex << _message->get_client() << "/"
+ << std::setw(4) << std::setfill('0') << std::hex
+ << _message->get_session() << "]";
+ }
+
+ void send() {
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ while (wait_until_registered_ && !stop_called_) {
+ condition_.wait_for(its_lock, std::chrono::milliseconds(100));
+ }
+
+ while (wait_until_service_available_ && !stop_called_) {
+ condition_.wait_for(its_lock, std::chrono::milliseconds(100));
+ }
+ its_lock.unlock();
+ its_lock.release();
+
+ for (;;) {
+ bool send(false);
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ send = !wait_until_service_available_;
+ }
+ if (send && !stop_called_) {
+ std::shared_ptr<vsomeip::message> its_req = vsomeip::runtime::get()->create_request();
+ its_req->set_service(service_info_.service_id);
+ its_req->set_instance(service_info_.instance_id);
+ its_req->set_method(service_info_.method_id);
+ app_->send(its_req);
+ ++sent_requests_;
+ VSOMEIP_INFO << "Sent a request to the service!";
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ } else {
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
+ }
+ if(stop_called_) {
+ break;
+ }
+ }
+ }
+
+ void wait_for_stop() {
+ std::unique_lock<std::mutex> its_lock(stop_mutex_);
+ while (wait_for_stop_) {
+ stop_condition_.wait(its_lock);
+ }
+ VSOMEIP_INFO << "going down";
+ app_->clear_all_handler();
+ app_->stop();
+ }
+
+ void stop(bool check) {
+ stop_called_ = true;
+ std::lock_guard<std::mutex> its_lock(stop_mutex_);
+ wait_for_stop_ = false;
+ VSOMEIP_INFO << "going down. Sent " << sent_requests_
+ << " requests and received " << received_responses_
+ << " responses. Delta: " << sent_requests_ - received_responses_;
+ std::uint32_t counter(0);
+ if (check) {
+ while(sent_requests_ == 0 || sent_requests_ < received_responses_) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ if(++counter > 50) {
+ break;
+ }
+ }
+ EXPECT_GT(sent_requests_, 0u);
+ EXPECT_GT(received_responses_, 0u);
+ EXPECT_EQ(sent_requests_, received_responses_);
+ }
+ stop_condition_.notify_one();
+ }
+
+private:
+ struct application_test::service_info service_info_;
+ std::shared_ptr<vsomeip::application> app_;
+
+ bool wait_until_registered_;
+ bool wait_until_service_available_;
+ std::mutex mutex_;
+ std::condition_variable condition_;
+
+ bool wait_for_stop_;
+ std::mutex stop_mutex_;
+ std::condition_variable stop_condition_;
+
+ std::atomic<std::uint32_t> received_responses_;
+ std::atomic<std::uint32_t> sent_requests_;
+ std::atomic<bool> stop_called_;
+
+ std::thread stop_thread_;
+ std::thread send_thread_;
+ std::thread application_thread_;
+};
diff --git a/test/network_tests/application_tests/application_test_client_availability.cpp b/test/network_tests/application_tests/application_test_client_availability.cpp
new file mode 100644
index 0000000..16fe87b
--- /dev/null
+++ b/test/network_tests/application_tests/application_test_client_availability.cpp
@@ -0,0 +1,203 @@
+// Copyright (C) 2014-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 <chrono>
+#include <condition_variable>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <thread>
+#include <map>
+#include <algorithm>
+#include <future>
+#include <atomic>
+
+#include <gtest/gtest.h>
+
+#include <vsomeip/vsomeip.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+#include "application_test_globals.hpp"
+
+class application_test_client_availability {
+public:
+ application_test_client_availability(struct application_test::service_info _service_info) :
+ service_info_(_service_info),
+ app_(vsomeip::runtime::get()->create_application("client")),
+ wait_until_registered_(true),
+ all_availability_handlers_called_(false),
+ run_thread_(std::bind(&application_test_client_availability::run, this)) {
+ if (!app_->init()) {
+ ADD_FAILURE() << "Couldn't initialize application";
+ return;
+ }
+ app_->register_state_handler(
+ std::bind(&application_test_client_availability::on_state, this,
+ std::placeholders::_1));
+
+ // register availability handler for every possiblity of
+ // ANY_SERVICE, ANY_INSTANCE, ANY_MAJOR, ANY_MINOR
+ for (std::uint32_t i = 0; i < 16; i++) {
+ vsomeip::service_t its_service = (i & 0x8) ? service_info_.service_id : vsomeip::ANY_SERVICE;
+ vsomeip::instance_t its_instance = (i & 0x4) ? service_info_.instance_id : vsomeip::ANY_INSTANCE;
+ vsomeip::major_version_t its_major = (i & 0x2) ? service_info_.major_version : vsomeip::ANY_MAJOR;
+ vsomeip::minor_version_t its_minor = (i & 0x1) ? service_info_.minor_version : vsomeip::ANY_MINOR;
+ app_->register_availability_handler(its_service,
+ its_instance,
+ std::bind(&application_test_client_availability::on_availability, this,
+ std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3, i),
+ its_major, its_minor);
+ VSOMEIP_DEBUG << "Registering: "
+ << std::setw(4) << std::setfill('0') << std::hex << its_service << "."
+ << std::setw(4) << std::setfill('0') << std::hex << its_instance << "."
+ << std::setw(2) << std::setfill('0') << std::hex << (std::uint32_t)its_major << "."
+ << std::setw(4) << std::setfill('0') << std::hex << its_minor << "."
+ << i;
+
+ }
+ app_->register_availability_handler(service_info_.service_id,
+ service_info_.instance_id,
+ std::bind(&application_test_client_availability::on_availability, this,
+ std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3, 16),
+ service_info_.major_version, vsomeip::DEFAULT_MINOR);
+ VSOMEIP_DEBUG << "Registering: "
+ << std::setw(4) << std::setfill('0') << std::hex << service_info_.service_id << "."
+ << std::setw(4) << std::setfill('0') << std::hex << service_info_.instance_id << "."
+ << std::setw(2) << std::setfill('0') << std::hex << (std::uint32_t)service_info_.service_id << "."
+ << std::setw(4) << std::setfill('0') << std::hex << vsomeip::DEFAULT_MINOR << "."
+ << 16;
+ app_->request_service(service_info_.service_id,
+ service_info_.instance_id);
+ std::promise<bool> its_promise;
+ application_thread_ = std::thread([&](){
+ its_promise.set_value(true);
+ app_->start();
+ });
+ EXPECT_TRUE(its_promise.get_future().get());
+ }
+
+ ~application_test_client_availability() {
+ run_thread_.join();
+ application_thread_.join();
+ }
+
+ void on_state(vsomeip::state_type_e _state) {
+ VSOMEIP_INFO << "Application " << app_->get_name() << " is "
+ << (_state == vsomeip::state_type_e::ST_REGISTERED ?
+ "registered." : "deregistered.");
+
+ if (_state == vsomeip::state_type_e::ST_REGISTERED) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_until_registered_ = false;
+ condition_.notify_one();
+ }
+ }
+
+ void on_availability(vsomeip::service_t _service,
+ vsomeip::instance_t _instance, bool _is_available,
+ std::uint32_t _handler_index)
+ {
+ VSOMEIP_DEBUG<< "Service [" << std::setw(4) << std::setfill('0') << std::hex
+ << _service << "." << std::setw(4) << std::setfill('0') << _instance << "] is "
+ << (_is_available ? "available." : "NOT available.") << ". "
+ << _handler_index;
+ if(service_info_.service_id == _service
+ && service_info_.instance_id == _instance) {
+ std::lock_guard<std::mutex> its_lock(availability_handler_called_mutex_);
+ availability_handler_called_[_handler_index] = _is_available;
+ availability_condition_.notify_one();
+ }
+ }
+
+ void run() {
+ {
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ while (wait_until_registered_) {
+ condition_.wait(its_lock);
+ }
+ }
+ while(!app_->is_available(service_info_.service_id,
+ service_info_.instance_id, service_info_.major_version,
+ service_info_.minor_version)) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ }
+ for (std::uint32_t i = 0; i < 16; i++) {
+ vsomeip::service_t its_service = (i & 0x8) ? service_info_.service_id : vsomeip::ANY_SERVICE;
+ vsomeip::instance_t its_instance = (i & 0x4) ? service_info_.instance_id : vsomeip::ANY_INSTANCE;
+ vsomeip::major_version_t its_major = (i & 0x2) ? service_info_.major_version : vsomeip::ANY_MAJOR;
+ vsomeip::minor_version_t its_minor = (i & 0x1) ? service_info_.minor_version : vsomeip::ANY_MINOR;
+
+ VSOMEIP_DEBUG << "Calling is_available: "
+ << std::setw(4) << std::setfill('0') << std::hex << its_service << "."
+ << std::setw(4) << std::setfill('0') << std::hex << its_instance << "."
+ << std::setw(2) << std::setfill('0') << std::hex << (std::uint32_t)its_major << "."
+ << std::setw(4) << std::setfill('0') << std::hex << its_minor;
+ EXPECT_TRUE(app_->is_available(its_service, its_instance, its_major, its_minor));
+
+ VSOMEIP_DEBUG << "Calling are_available: "
+ << std::setw(4) << std::setfill('0') << std::hex << its_service << "."
+ << std::setw(4) << std::setfill('0') << std::hex << its_instance << "."
+ << std::setw(2) << std::setfill('0') << std::hex << (std::uint32_t)its_major << "."
+ << std::setw(4) << std::setfill('0') << std::hex << its_minor;
+ vsomeip::application::available_t are_available;
+ EXPECT_TRUE(app_->are_available(are_available, its_service, its_instance, its_major, its_minor));
+ bool found(false);
+ auto found_service = are_available.find(service_info_.service_id);
+ if(found_service != are_available.end()) {
+ auto found_instance = found_service->second.find(service_info_.instance_id);
+ if(found_instance != found_service->second.end()) {
+ auto found_major = found_instance->second.find(service_info_.major_version);
+ if (found_major != found_instance->second.end()) {
+ if (found_major->second == service_info_.minor_version) {
+ found = true;
+ }
+ }
+ }
+ }
+ EXPECT_TRUE(found);
+
+ }
+ {
+ std::unique_lock<std::mutex> its_lock(availability_handler_called_mutex_);
+ while(!std::all_of(availability_handler_called_.cbegin(),
+ availability_handler_called_.cend(),
+ [&](const availability_handler_called_t::value_type &v) {
+ return v;
+ })) {
+ availability_condition_.wait(its_lock);
+ }
+ }
+ VSOMEIP_INFO <<" Everything is available";
+ all_availability_handlers_called_ = true;
+ }
+
+ void stop() {
+ VSOMEIP_INFO << "going down";
+ app_->clear_all_handler();
+ app_->stop();
+ }
+
+ bool all_availability_handlers_called() const {
+ return all_availability_handlers_called_;
+ }
+
+private:
+ struct application_test::service_info service_info_;
+ std::shared_ptr<vsomeip::application> app_;
+ std::mutex availability_handler_called_mutex_;
+ std::condition_variable availability_condition_;
+ typedef std::array<bool, 17> availability_handler_called_t;
+ availability_handler_called_t availability_handler_called_;
+
+
+ bool wait_until_registered_;
+ std::mutex mutex_;
+ std::condition_variable condition_;
+ std::atomic<bool> all_availability_handlers_called_;
+ std::thread run_thread_;
+ std::thread application_thread_;
+};
diff --git a/test/network_tests/application_tests/application_test_daemon.cpp b/test/network_tests/application_tests/application_test_daemon.cpp
new file mode 100644
index 0000000..2f0b244
--- /dev/null
+++ b/test/network_tests/application_tests/application_test_daemon.cpp
@@ -0,0 +1,42 @@
+// Copyright (C) 2014-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 <gtest/gtest.h>
+#include <future>
+
+#include <vsomeip/vsomeip.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+class application_test_daemon {
+public:
+ application_test_daemon() :
+ app_(vsomeip::runtime::get()->create_application("daemon")) {
+ if (!app_->init()) {
+ ADD_FAILURE() << "Couldn't initialize application";
+ return;
+ }
+ std::promise<bool> its_promise;
+ application_thread_ = std::thread([&](){
+ its_promise.set_value(true);
+ app_->start();
+ });
+ EXPECT_TRUE(its_promise.get_future().get());
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ VSOMEIP_INFO << "Daemon starting";
+ }
+
+ ~application_test_daemon() {
+ application_thread_.join();
+ }
+
+ void stop() {
+ VSOMEIP_INFO << "Daemon stopping";
+ app_->stop();
+ }
+
+private:
+ std::shared_ptr<vsomeip::application> app_;
+ std::thread application_thread_;
+};
diff --git a/test/network_tests/application_tests/application_test_globals.hpp b/test/network_tests/application_tests/application_test_globals.hpp
new file mode 100644
index 0000000..7caa9db
--- /dev/null
+++ b/test/network_tests/application_tests/application_test_globals.hpp
@@ -0,0 +1,28 @@
+// Copyright (C) 2014-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/.
+
+#ifndef APPLICATION_TEST_GLOBALS_HPP_
+#define APPLICATION_TEST_GLOBALS_HPP_
+
+namespace application_test {
+
+struct service_info {
+ vsomeip::service_t service_id;
+ vsomeip::instance_t instance_id;
+ vsomeip::method_t method_id;
+ vsomeip::event_t event_id;
+ vsomeip::eventgroup_t eventgroup_id;
+ vsomeip::method_t shutdown_method_id;
+ vsomeip::major_version_t major_version;
+ vsomeip::minor_version_t minor_version;
+};
+
+
+struct service_info service = { 0x1111, 0x1, 0x1111, 0x1111, 0x1000, 0x1404, 0x2, 0x4711 };
+
+static constexpr int number_of_messages_to_send = 150;
+}
+
+#endif /* APPLICATION_TEST_GLOBALS_HPP_ */
diff --git a/test/network_tests/application_tests/application_test_service.cpp b/test/network_tests/application_tests/application_test_service.cpp
new file mode 100644
index 0000000..77d40cd
--- /dev/null
+++ b/test/network_tests/application_tests/application_test_service.cpp
@@ -0,0 +1,128 @@
+// Copyright (C) 2014-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 <chrono>
+#include <condition_variable>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <thread>
+#include <map>
+#include <algorithm>
+#include <future>
+#include <atomic>
+
+#include <gtest/gtest.h>
+
+#include <vsomeip/vsomeip.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+#include "application_test_globals.hpp"
+
+class application_test_service {
+public:
+ application_test_service(struct application_test::service_info _service_info) :
+ service_info_(_service_info),
+ // service with number 1 uses "routingmanagerd" as application name
+ // this way the same json file can be reused for all local tests
+ // including the ones with routingmanagerd
+ app_(vsomeip::runtime::get()->create_application("service")),
+ wait_until_registered_(true),
+ stop_called_(false),
+ offer_thread_(std::bind(&application_test_service::run, this)) {
+ if (!app_->init()) {
+ ADD_FAILURE() << "Couldn't initialize application";
+ return;
+ }
+ app_->register_state_handler(
+ std::bind(&application_test_service::on_state, this,
+ std::placeholders::_1));
+
+ app_->register_message_handler(service_info_.service_id,
+ service_info_.instance_id, service_info_.method_id,
+ std::bind(&application_test_service::on_request, this,
+ std::placeholders::_1));
+
+ app_->register_message_handler(service_info_.service_id,
+ service_info_.instance_id, service_info_.shutdown_method_id,
+ std::bind(&application_test_service::on_shutdown_method_called, this,
+ std::placeholders::_1));
+ std::promise<bool> its_promise;
+ application_thread_ = std::thread([&](){
+ its_promise.set_value(true);
+ app_->start();
+ });
+ EXPECT_TRUE(its_promise.get_future().get());
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ }
+
+ ~application_test_service() {
+ offer_thread_.join();
+ application_thread_.join();
+ }
+
+
+ void offer() {
+ app_->offer_service(service_info_.service_id, service_info_.instance_id,
+ service_info_.major_version, service_info_.minor_version);
+ }
+
+ void on_state(vsomeip::state_type_e _state) {
+ VSOMEIP_INFO << "Application " << app_->get_name() << " is "
+ << (_state == vsomeip::state_type_e::ST_REGISTERED ?
+ "registered." : "deregistered.");
+
+ if (_state == vsomeip::state_type_e::ST_REGISTERED) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_until_registered_ = false;
+ condition_.notify_one();
+ }
+ }
+
+ void on_request(const std::shared_ptr<vsomeip::message> &_message) {
+ app_->send(vsomeip::runtime::get()->create_response(_message));
+ VSOMEIP_INFO << "Received a request with Client/Session [" << std::setw(4)
+ << std::setfill('0') << std::hex << _message->get_client() << "/"
+ << std::setw(4) << std::setfill('0') << std::hex
+ << _message->get_session() << "]";
+ }
+
+ void on_shutdown_method_called(const std::shared_ptr<vsomeip::message> &_message) {
+ (void)_message;
+ stop();
+ }
+
+ void stop() {
+ stop_called_ = true;
+ app_->stop_offer_service(service_info_.service_id, service_info_.instance_id,
+ service_info_.major_version, service_info_.minor_version);
+ app_->clear_all_handler();
+ app_->stop();
+ }
+
+ void run() {
+ VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << service_info_.service_id << "] Running";
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ while (wait_until_registered_ && !stop_called_) {
+ condition_.wait_for(its_lock, std::chrono::milliseconds(100));
+ }
+
+ VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << service_info_.service_id << "] Offering";
+ offer();
+ }
+
+private:
+ struct application_test::service_info service_info_;
+ std::shared_ptr<vsomeip::application> app_;
+
+ bool wait_until_registered_;
+ std::mutex mutex_;
+ std::condition_variable condition_;
+ std::atomic<bool> stop_called_;
+ std::thread offer_thread_;
+ std::thread application_thread_;
+};
diff --git a/test/network_tests/application_tests/application_test_single_process.cpp b/test/network_tests/application_tests/application_test_single_process.cpp
new file mode 100644
index 0000000..c738899
--- /dev/null
+++ b/test/network_tests/application_tests/application_test_single_process.cpp
@@ -0,0 +1,47 @@
+// Copyright (C) 2014-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 <gtest/gtest.h>
+#include "application_test_service.cpp"
+#include "application_test_client.cpp"
+#include "application_test_daemon.cpp"
+
+TEST(someip_application_test_single_process, notify_increasing_counter)
+{
+ // start application acting as daemon (rm_stub)
+ auto its_daemon = std::make_shared<application_test_daemon>();
+
+ // start receiver service (rm_proxy)
+ application_test_service its_receiver(application_test::service);
+
+ // stop the daemon (rm_stub goes away)
+ its_daemon->stop();
+ its_daemon.reset();
+ // restart client which tries to communicate with service multiple times
+ // thus it will always be the new routing manager
+ for (int var = 0; var < 10; ++var) {
+ // every time the client is restarted it becomes the rm_stub again
+ application_test_client its_client(application_test::service);
+ if(var != 9) {
+ its_client.stop(false);
+ } else {
+ // for the last iteration we sleep to make sure the communication
+ // between the client and the service can be established
+ std::this_thread::sleep_for(std::chrono::milliseconds(2000));
+ its_client.stop(true);
+ }
+ }
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ its_receiver.on_shutdown_method_called(vsomeip::runtime::get()->create_message());
+}
+
+
+#if defined(__linux__) || defined(ANDROID)
+int main(int argc, char** argv)
+{
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+#endif
diff --git a/test/network_tests/application_tests/application_test_single_process.json b/test/network_tests/application_tests/application_test_single_process.json
new file mode 100644
index 0000000..b604d9a
--- /dev/null
+++ b/test/network_tests/application_tests/application_test_single_process.json
@@ -0,0 +1,14 @@
+{
+ "unicast":"127.0.0.1",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/someip.log"
+ },
+ "dlt":"false"
+ }
+}
diff --git a/test/network_tests/application_tests/application_test_single_process_starter.sh b/test/network_tests/application_tests/application_test_single_process_starter.sh
new file mode 100755
index 0000000..3919358
--- /dev/null
+++ b/test/network_tests/application_tests/application_test_single_process_starter.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# 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/.
+
+FAIL=0
+
+export VSOMEIP_CONFIGURATION=application_test_single_process.json
+./application_test_single_process
+
+if [ $? -ne 0 ]
+then
+ ((FAIL+=1))
+fi
+
+# Check if both exited successfully
+if [ $FAIL -eq 0 ]
+then
+ exit 0
+else
+ exit 1
+fi
diff --git a/test/network_tests/application_tests/application_test_starter.sh b/test/network_tests/application_tests/application_test_starter.sh
new file mode 100755
index 0000000..7e8c022
--- /dev/null
+++ b/test/network_tests/application_tests/application_test_starter.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+# 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/.
+
+FAIL=0
+
+export VSOMEIP_CONFIGURATION=application_test_no_dispatch_threads.json
+./application_test
+
+if [ $? -ne 0 ]
+then
+ ((FAIL+=1))
+fi
+
+export VSOMEIP_CONFIGURATION=application_test.json
+./application_test
+
+if [ $? -ne 0 ]
+then
+ ((FAIL+=1))
+fi
+
+cat <<End-of-message
+*******************************************************************************
+*******************************************************************************
+** Now running same tests with routingmanagerd
+*******************************************************************************
+*******************************************************************************
+End-of-message
+export VSOMEIP_CONFIGURATION=application_test_no_dispatch_threads_daemon.json
+../../examples/routingmanagerd/./routingmanagerd &
+DAEMON_PID=$!
+./application_test
+if [ $? -ne 0 ]
+then
+ ((FAIL+=1))
+fi
+
+kill $DAEMON_PID
+wait $DAEMON_PID
+
+export VSOMEIP_CONFIGURATION=application_test_daemon.json
+../../examples/routingmanagerd/./routingmanagerd &
+DAEMON_PID=$!
+./application_test
+if [ $? -ne 0 ]
+then
+ ((FAIL+=1))
+fi
+
+kill $DAEMON_PID
+
+# Check if both exited successfully
+if [ $FAIL -eq 0 ]
+then
+ exit 0
+else
+ exit 1
+fi
diff --git a/test/network_tests/application_tests/conf/application_test.json.in b/test/network_tests/application_tests/conf/application_test.json.in
new file mode 100644
index 0000000..ed5a7fc
--- /dev/null
+++ b/test/network_tests/application_tests/conf/application_test.json.in
@@ -0,0 +1,38 @@
+{
+ "unicast":"@TEST_IP_MASTER@",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/someip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"application_test",
+ "id":"0x7788",
+ "num_dispatchers":"5"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x1234",
+ "instance":"0x5678",
+ "reliable":"30503"
+ }
+ ],
+ "routing":"application_test",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp"
+ }
+}
diff --git a/test/network_tests/application_tests/conf/application_test_daemon.json.in b/test/network_tests/application_tests/conf/application_test_daemon.json.in
new file mode 100644
index 0000000..f7fd3dc
--- /dev/null
+++ b/test/network_tests/application_tests/conf/application_test_daemon.json.in
@@ -0,0 +1,38 @@
+{
+ "unicast":"@TEST_IP_MASTER@",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/someip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"application_test",
+ "id":"0x7788",
+ "num_dispatchers":"5"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x1234",
+ "instance":"0x5678",
+ "reliable":"30503"
+ }
+ ],
+ "routing":"routingmanagerd",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp"
+ }
+}
diff --git a/test/network_tests/application_tests/conf/application_test_no_dispatch_threads.json.in b/test/network_tests/application_tests/conf/application_test_no_dispatch_threads.json.in
new file mode 100644
index 0000000..20d0ebd
--- /dev/null
+++ b/test/network_tests/application_tests/conf/application_test_no_dispatch_threads.json.in
@@ -0,0 +1,37 @@
+{
+ "unicast":"@TEST_IP_MASTER@",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/someip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"application_test",
+ "id":"0x7788"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x1234",
+ "instance":"0x5678",
+ "reliable":"30503"
+ }
+ ],
+ "routing":"application_test",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp"
+ }
+}
diff --git a/test/network_tests/application_tests/conf/application_test_no_dispatch_threads_daemon.json.in b/test/network_tests/application_tests/conf/application_test_no_dispatch_threads_daemon.json.in
new file mode 100644
index 0000000..8c7622a
--- /dev/null
+++ b/test/network_tests/application_tests/conf/application_test_no_dispatch_threads_daemon.json.in
@@ -0,0 +1,37 @@
+{
+ "unicast":"@TEST_IP_MASTER@",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/someip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"application_test",
+ "id":"0x7788"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x1234",
+ "instance":"0x5678",
+ "reliable":"30503"
+ }
+ ],
+ "routing":"routingmanagerd",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp"
+ }
+}