Skip to content

Commit

Permalink
Add auxiliary API for Proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
Vitalii Arteev committed Oct 16, 2020
1 parent 63e4de6 commit cc5fa36
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/ipc/ipc-common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ facelift_add_library(FaceliftIPCCommonLib
IPCServiceAdapterBase.h
NewIPCServiceAdapterBase.h
IPCAttachedPropertyFactory.h
observer.h
HEADERS_NO_MOC
AppendDBUSSignatureFunction.h
ipc-serialization.h
Expand Down
4 changes: 3 additions & 1 deletion src/ipc/ipc-common/IPCProxyBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#include "ipc-common.h"
#include "IPCProxyBaseBase.h"
#include "IPCProxyBinderBase.h"

#include "observer.h"

#if defined(FaceliftIPCCommonLib_LIBRARY)
# define FaceliftIPCCommonLib_EXPORT Q_DECL_EXPORT
Expand All @@ -49,10 +49,12 @@ class IPCProxyBase : public AdapterType, protected IPCProxyBaseBase

public:
using InterfaceType = AdapterType;
IsReadyObserver m_readyObserver{};

public:
IPCProxyBase(QObject *parent) : AdapterType(parent)
{
QObject::connect(this, &InterfaceBase::readyChanged, &m_readyObserver, &IsReadyObserver::onReadyChanged);
}

template<typename BinderType>
Expand Down
108 changes: 108 additions & 0 deletions src/ipc/ipc-common/observer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/**********************************************************************
**
** Copyright (C) 2020 Luxoft Sweden AB
**
** This file is part of the FaceLift project
**
** Permission is hereby granted, freIPCServiceAdapterBasee of charge, to any person
** obtaining a copy of this software and associated documentation files
** (the "Software"), to deal in the Software without restriction,
** including without limitation the rights to use, copy, modify, merge,
** publish, distribute, sublicense, and/or sell copies of the Software,
** and to permit persons to whom the Software is furnished to do so,
** subject to the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
** ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
** SOFTWARE.
**
** SPDX-License-Identifier: MIT
**
**********************************************************************/

#pragma once

#include <memory>
#include <vector>
#include <QObject>

namespace facelift {

class IObserver : public QObject
{
Q_OBJECT
public:
virtual void onReadyChanged(std::shared_ptr<QMetaObject::Connection> connection) = 0;
};

class IsReadyObserver: public QObject
{
Q_OBJECT

std::vector<IObserver *> m_observers;
std::shared_ptr<QMetaObject::Connection> connection;
public:
IsReadyObserver() : connection{std::make_shared<QMetaObject::Connection>()}
{
*connection = QObject::connect(this, &IsReadyObserver::readyChanged, this, [this] () {
for (auto observer : m_observers) {
observer->onReadyChanged( connection );
}
});
}

// Set observers
void setObservers(const std::vector<IObserver *> &observers) {
m_observers = observers;
}

// Get observers
const std::vector<IObserver *> &getObservers() const {
return m_observers;
}

Q_SIGNAL void readyChanged();

void onReadyChanged() {
emit readyChanged();
}
};

// Single-time observer which will unregister itself when done
template<typename Function>
class SingleTimeObserver : public IObserver
{
Function m_func;
public:
explicit SingleTimeObserver(Function func) : m_func{func} {}
~SingleTimeObserver() = default;

void onReadyChanged(std::shared_ptr<QMetaObject::Connection> connection) override {
m_func();
QObject::disconnect(*connection);
}
};

// Standard observer which will work for each signal
template<typename Function>
class StandartObserver : public IObserver
{
Function m_func;
public:
explicit StandartObserver(Function func) : m_func{func} {}
~StandartObserver() = default;

void onReadyChanged(std::shared_ptr<QMetaObject::Connection> ) override {
m_func();
}
};

}
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ add_test(NAME benchmarking-inprocess.cpp COMMAND test-driver.sh benchmarking/tst

if(NOT ${FACELIFT_DISABLE_GTEST})
add_subdirectory(unittest)
add_subdirectory(unittest_observer)
endif()

add_subdirectory(objectregistry)
23 changes: 23 additions & 0 deletions tests/unittest_observer/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

find_package(GTest)
if(${GTEST_FOUND})
find_library(GMOCK_LIBRARY gmock REQUIRED HINTS "${CMAKE_SYSTEM_PREFIX_PATH}")
if(NOT ${GMOCK_LIBRARY} STREQUAL "GMOCK_LIBRARY-NOTFOUND")
add_library(GTest::GMock UNKNOWN IMPORTED)
set_target_properties(GTest::GMock PROPERTIES IMPORTED_LOCATION ${GMOCK_LIBRARY})
else()
message(WARNING "Google test/mock not found.")
endif()

find_package(Threads REQUIRED)
set(FACELIFT_GTEST_LIBRARIES ${GTEST_BOTH_LIBRARIES} GTest::GMock Threads::Threads)
include_directories(${GTEST_INCLUDE_DIRS})

facelift_add_test(UnitTestsObserver
SOURCES FaceliftObserverTest.cpp
LINK_LIBRARIES ${FACELIFT_GTEST_LIBRARIES} FaceliftIPCCommonLib FaceliftModelLib)

else()
message(WARNING "Required package google test not found!")
endif()

52 changes: 52 additions & 0 deletions tests/unittest_observer/FaceliftObserverTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include <gtest/gtest.h>
#include "IPCProxyBase.h"
#include "InterfaceBase.h"

namespace {

using namespace facelift;

class Counter
{
public:
Counter() { m_value = 0; }

void incValue() {
m_value++;
}
int getValue() {
return m_value;
}
private:
int m_value;
};

class IPCProxyBaseTest : public ::testing::Test
{
public:
Counter c1;
Counter c2;
StandartObserver < std::function<void()> > * obs1 = new StandartObserver < std::function<void()> >(std::bind(&Counter::incValue, &c1) );
SingleTimeObserver< std::function<int()> > * obs2 = new SingleTimeObserver< std::function<int()> >(std::bind(&Counter::getValue, &c2) );

IPCProxyBase<InterfaceBase> proxyBase{nullptr};

~IPCProxyBaseTest(){
delete obs1;
obs1 = nullptr;
delete obs2;
obs2 = nullptr;
}
};

TEST_F(IPCProxyBaseTest, setObservers)
{
const auto expected = std::vector<IObserver*>{obs1, obs2,};
proxyBase.m_readyObserver.setObservers(expected);
const auto actual = proxyBase.m_readyObserver.getObservers();
EXPECT_EQ(expected.size(), actual.size());
EXPECT_EQ(expected[0], actual[0]);
EXPECT_EQ(expected[1], actual[1]);
}

} // end namespace

0 comments on commit cc5fa36

Please sign in to comment.