From: Manuel Nickschas Date: Thu, 4 Oct 2018 19:10:13 +0000 (+0200) Subject: test: Add a spy type that waits for one or more signals X-Git-Tag: test-travis-01~109 X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=commitdiff_plain;h=12a6abcfe51ac66e8763b3caadaedcb47c2723f1;ds=sidebyside test: Add a spy type that waits for one or more signals Introducing SignalSpy that allows to wait for one or more signals to be emitted in test cases. Unlike QSignalSpy, it is not bound to a particular signal on construction; instead, one has to explicitly connect one or more signal(s) before calling wait(). --- diff --git a/src/test/util/invocationspy.cpp b/src/test/util/invocationspy.cpp index 74bb3bd2..da9c4f0a 100644 --- a/src/test/util/invocationspy.cpp +++ b/src/test/util/invocationspy.cpp @@ -43,4 +43,16 @@ bool InvocationSpy::wait(std::chrono::milliseconds timeout) return result; } +// ----------------------------------------------------------------------------------------------------------------------------------------- + +bool SignalSpy::wait(std::chrono::milliseconds timeout) +{ + bool result = InvocationSpy::wait(timeout); + for (auto&& connection : _connections) { + QObject::disconnect(connection); + } + _connections.clear(); + return result; +} + } // namespace test diff --git a/src/test/util/invocationspy.h b/src/test/util/invocationspy.h index 92dd8ec4..903fc386 100644 --- a/src/test/util/invocationspy.h +++ b/src/test/util/invocationspy.h @@ -55,7 +55,7 @@ public: * @param timeout Timeout for waiting * @returns true if the spy was notified, and false if it timed out. */ - bool wait(std::chrono::milliseconds timeout = std::chrono::seconds{60}); + virtual bool wait(std::chrono::milliseconds timeout = std::chrono::seconds{60}); signals: /// Internally used signal @@ -65,6 +65,8 @@ private: QSignalSpy _internalSpy; }; +// ----------------------------------------------------------------------------------------------------------------------------------------- + /** * Spy that allows to be notified with a value. * @@ -100,4 +102,47 @@ private: boost::optional _value; }; +// ----------------------------------------------------------------------------------------------------------------------------------------- + +/** + * Spy that is notified by one (or multiple) signal(s). + * + * Unlike QSignalSpy, this class is not bound to a particular signal. Instead, SignalSpy::connect() must be called + * to define the signal prior to calling wait(). connect() can also be called more than once, in which case any of + * the connected signals will trigger the spy. + * + * Before wait() returns, it disconnects all existing signals, so the spy can be reused without having to explicitly + * reset it. + */ +class TEST_UTIL_EXPORT SignalSpy : private InvocationSpy +{ +public: + using InvocationSpy::InvocationSpy; + + /** + * Connects a signal to wait for. + * + * @param sender The signal's sender + * @param sig The signal + */ + template + void connect(const TSender* sender, TSignal sig) { + _connections.emplace_back(QObject::connect(sender, sig, this, &SignalSpy::notify)); + } + + /** + * Waits for the spy to be notified with any of the connected signals within the given timeout. + * + * Any connections will be cleared before this function returns. When reusing the spy, one needs + * to connect signals before calling wait() again. + * + * @param timeout Timeout for waiting + * @returns true if a signal was received, and false if it timed out. + */ + bool wait(std::chrono::milliseconds timeout = std::chrono::seconds{60}) override; + +private: + std::vector _connections; +}; + } // namespace test