summaryrefslogtreecommitdiff
path: root/test/network_tests/application_tests/application_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/network_tests/application_tests/application_test.cpp')
-rw-r--r--test/network_tests/application_tests/application_test.cpp479
1 files changed, 479 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
+
+
+
+