Merge lp:~marcustomlinson/unity-scopes-api/scope_debug_mode into lp:unity-scopes-api/devel

Proposed by Marcus Tomlinson
Status: Superseded
Proposed branch: lp:~marcustomlinson/unity-scopes-api/scope_debug_mode
Merge into: lp:unity-scopes-api/devel
Diff against target: 1429 lines (+613/-99)
46 files modified
include/unity/scopes/internal/ActivationReplyObject.h (+2/-1)
include/unity/scopes/internal/DfltConfig.h.in (+3/-3)
include/unity/scopes/internal/MWRegistry.h (+1/-0)
include/unity/scopes/internal/MWScope.h (+1/-0)
include/unity/scopes/internal/PreviewReplyObject.h (+2/-1)
include/unity/scopes/internal/ReplyObject.h (+2/-1)
include/unity/scopes/internal/ResultReplyObject.h (+2/-4)
include/unity/scopes/internal/ScopeConfig.h (+2/-0)
include/unity/scopes/internal/ScopeObject.h (+4/-1)
include/unity/scopes/internal/ScopeObjectBase.h (+2/-0)
include/unity/scopes/internal/smartscopes/SSScopeObject.h (+2/-0)
include/unity/scopes/internal/zmq_middleware/ScopeI.h (+5/-2)
include/unity/scopes/internal/zmq_middleware/ZmqObjectProxy.h (+1/-1)
include/unity/scopes/internal/zmq_middleware/ZmqRegistry.h (+1/-0)
include/unity/scopes/internal/zmq_middleware/ZmqScope.h (+6/-0)
scoperegistry/scoperegistry.cpp (+9/-1)
src/scopes/internal/ActivationReplyObject.cpp (+3/-2)
src/scopes/internal/PreviewReplyObject.cpp (+3/-2)
src/scopes/internal/RegistryObject.cpp (+16/-11)
src/scopes/internal/ReplyObject.cpp (+22/-8)
src/scopes/internal/ResultReplyObject.cpp (+3/-5)
src/scopes/internal/RuntimeImpl.cpp (+5/-2)
src/scopes/internal/ScopeConfig.cpp (+49/-33)
src/scopes/internal/ScopeImpl.cpp (+4/-4)
src/scopes/internal/ScopeObject.cpp (+8/-2)
src/scopes/internal/smartscopes/SSScopeObject.cpp (+5/-0)
src/scopes/internal/zmq_middleware/ScopeI.cpp (+19/-5)
src/scopes/internal/zmq_middleware/ZmqObject.cpp (+11/-3)
src/scopes/internal/zmq_middleware/ZmqRegistry.cpp (+6/-2)
src/scopes/internal/zmq_middleware/ZmqScope.cpp (+38/-4)
src/scopes/internal/zmq_middleware/capnproto/Scope.capnp (+5/-0)
test/gtest/scopes/Invocation/CMakeLists.txt (+2/-1)
test/gtest/scopes/Invocation/DebugTestScope.cpp (+59/-0)
test/gtest/scopes/Invocation/DebugTestScope.h (+33/-0)
test/gtest/scopes/Invocation/DebugTestScope.ini.in (+5/-0)
test/gtest/scopes/Invocation/Invocation_test.cpp (+34/-0)
test/gtest/scopes/Registry/Registry_test.cpp (+58/-0)
test/gtest/scopes/Registry/other_scopes/testscopeC/CMakeLists.txt (+2/-0)
test/gtest/scopes/Registry/other_scopes/testscopeC/testscopeC.cpp (+99/-0)
test/gtest/scopes/Registry/other_scopes/testscopeC/testscopeC.ini.in (+2/-0)
test/gtest/scopes/ReplyReaper/CMakeLists.txt (+1/-0)
test/gtest/scopes/ReplyReaper/DebugScope.ini.in (+5/-0)
test/gtest/scopes/ReplyReaper/ReplyReaper_test.cpp (+63/-0)
test/gtest/scopes/internal/ScopeConfig/ScopeConfig_test.cpp (+2/-0)
test/gtest/scopes/internal/ScopeConfig/complete_config.ini.in (+1/-0)
test/gtest/scopes/internal/zmq_middleware/ZmqMiddleware/ZmqMiddleware_test.cpp (+5/-0)
To merge this branch: bzr merge lp:~marcustomlinson/unity-scopes-api/scope_debug_mode
Reviewer Review Type Date Requested Status
Unity Team Pending
Review via email: mp+230574@code.launchpad.net

Commit message

Added "DebugMode" parameter to scope config in order to enable more lenient operation timeouts when debugging that particular scope.

Description of the change

If a scope config file contains the line "DebugMode = true" the following debug timeouts are applied (only) to comms with that particular scope:

* Registry process timeout upped to 15s
* Scope idle timeout disabled
* Runtime reply reaper disabled
* Middleware two-way invocation timeout disabled
* Middleware locate() timeout upped to 15s

*** Summary of changes: ***

* Added "DebugMode" parameter to ScopeConfig (not to ScopeMetadata).

* A new debug_mode() method on ScopeObject (propagated through middleware to MWScope but not expose to the public ScopeProxy).

* An additional "dont_reap" boolean argument for ReplyObject constructor (provided via ScopeImpl from the result of fwd()->debug_mode()).

* An additional "locate_timeout" argument for ZmqObjectProxy::invoke_twoway_() allowing for both two-way and locate timeouts to be overridden from ZmqScope invocations ("locate_timeout" argument also made available on MWRegistry interface).

* Updated RuntimeImpl::run_scope() to use scope_config.debug_mode() to set idle timeout and construct ScopeObject accordingly.

* Updated scoperegistry to use scope_config.debug_mode() to set process timeout accordingly.

* Added tests.

*** Other changes: ***

* Fixed remove_local_scope() to kill scope if currently running before removing it from the list.

* Some cleaning up of API code in general.

* Invocation.shutdown_with_outstanding_async test was missing "run_test_registry();"

To post a comment you must log in.
465. By Marcus Tomlinson

Updated symbols

466. By Marcus Tomlinson

Make sure scope_processes_ map operations are under mutex protection

467. By Marcus Tomlinson

Return false from remove_local_scope() if not found (as before)

468. By Marcus Tomlinson

Added interlock in ZmqScope::debug_mode() for accessing debug_mode_ from parallel threads

469. By Marcus Tomlinson

Hopefully fixes "terminate called without an active exception"

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/unity/scopes/internal/ActivationReplyObject.h'
2--- include/unity/scopes/internal/ActivationReplyObject.h 2014-03-07 04:19:32 +0000
3+++ include/unity/scopes/internal/ActivationReplyObject.h 2014-08-13 04:58:30 +0000
4@@ -34,7 +34,8 @@
5 class ActivationReplyObject : public ReplyObject
6 {
7 public:
8- ActivationReplyObject(ActivationListenerBase::SPtr const& receiver, RuntimeImpl const* runtime, std::string const& scope_id);
9+ ActivationReplyObject(ActivationListenerBase::SPtr const& receiver, RuntimeImpl const* runtime,
10+ std::string const& scope_id, bool dont_reap = false);
11 virtual bool process_data(VariantMap const& data) override;
12
13 private:
14
15=== modified file 'include/unity/scopes/internal/DfltConfig.h.in'
16--- include/unity/scopes/internal/DfltConfig.h.in 2014-07-25 01:23:02 +0000
17+++ include/unity/scopes/internal/DfltConfig.h.in 2014-08-13 04:58:30 +0000
18@@ -28,10 +28,10 @@
19 namespace internal
20 {
21
22-static constexpr const char* DFLT_RUNTIME_INI = "@CMAKE_INSTALL_PREFIX@/@LIB_INSTALL_PREFIX@/@UNITY_SCOPES_LIB@/Runtime.ini";
23-static constexpr const char* DFLT_REGISTRY_INI = "@CMAKE_INSTALL_PREFIX@/@LIB_INSTALL_PREFIX@/@UNITY_SCOPES_LIB@/Registry.ini";
24+static constexpr char const* DFLT_RUNTIME_INI = "@CMAKE_INSTALL_PREFIX@/@LIB_INSTALL_PREFIX@/@UNITY_SCOPES_LIB@/Runtime.ini";
25+static constexpr char const* DFLT_REGISTRY_INI = "@CMAKE_INSTALL_PREFIX@/@LIB_INSTALL_PREFIX@/@UNITY_SCOPES_LIB@/Registry.ini";
26 static constexpr char const* DFLT_REGISTRY_ID = "Registry";
27-static constexpr const char* DFLT_SS_REGISTRY_INI = "@CMAKE_INSTALL_PREFIX@/@LIB_INSTALL_PREFIX@/@UNITY_SCOPES_LIB@/Smartscopes.ini";
28+static constexpr char const* DFLT_SS_REGISTRY_INI = "@CMAKE_INSTALL_PREFIX@/@LIB_INSTALL_PREFIX@/@UNITY_SCOPES_LIB@/Smartscopes.ini";
29 static constexpr char const* DFLT_SS_REGISTRY_ID = "SSRegistry";
30 static constexpr char const* DFLT_SCOPERUNNER_PATH = "@CMAKE_INSTALL_PREFIX@/@LIB_INSTALL_PREFIX@/@UNITY_SCOPES_LIB@/scoperunner";
31 static constexpr char const* DFLT_MIDDLEWARE = "Zmq";
32
33=== modified file 'include/unity/scopes/internal/MWRegistry.h'
34--- include/unity/scopes/internal/MWRegistry.h 2014-06-04 17:49:34 +0000
35+++ include/unity/scopes/internal/MWRegistry.h 2014-08-13 04:58:30 +0000
36@@ -39,6 +39,7 @@
37 // Remote operations
38 virtual ScopeMetadata get_metadata(std::string const& scope_id) = 0;
39 virtual MetadataMap list() = 0;
40+ virtual ObjectProxy locate(std::string const& identity, int64_t timeout) = 0;
41 virtual ObjectProxy locate(std::string const& identity) = 0;
42 virtual bool is_scope_running(std::string const& scope_id) = 0;
43
44
45=== modified file 'include/unity/scopes/internal/MWScope.h'
46--- include/unity/scopes/internal/MWScope.h 2014-02-27 16:58:50 +0000
47+++ include/unity/scopes/internal/MWScope.h 2014-08-13 04:58:30 +0000
48@@ -44,6 +44,7 @@
49 virtual QueryCtrlProxy activate(VariantMap const& result, VariantMap const& hints, MWReplyProxy const& reply) = 0;
50 virtual QueryCtrlProxy perform_action(VariantMap const& result, VariantMap const& hints, std::string const& widget_id, std::string const& action_id, MWReplyProxy const& reply) = 0;
51 virtual QueryCtrlProxy preview(VariantMap const& result, VariantMap const& hints, MWReplyProxy const& reply) = 0;
52+ virtual bool debug_mode() = 0;
53
54 protected:
55 MWScope(MiddlewareBase* mw_base);
56
57=== modified file 'include/unity/scopes/internal/PreviewReplyObject.h'
58--- include/unity/scopes/internal/PreviewReplyObject.h 2014-03-07 04:19:32 +0000
59+++ include/unity/scopes/internal/PreviewReplyObject.h 2014-08-13 04:58:30 +0000
60@@ -37,7 +37,8 @@
61 class PreviewReplyObject : public ReplyObject
62 {
63 public:
64- PreviewReplyObject(PreviewListenerBase::SPtr const& receiver, RuntimeImpl const* runtime, std::string const& scope_id);
65+ PreviewReplyObject(PreviewListenerBase::SPtr const& receiver, RuntimeImpl const* runtime,
66+ std::string const& scope_id, bool dont_reap = false);
67 virtual ~PreviewReplyObject();
68
69 virtual bool process_data(VariantMap const& data) override;
70
71=== modified file 'include/unity/scopes/internal/ReplyObject.h'
72--- include/unity/scopes/internal/ReplyObject.h 2014-07-28 09:55:08 +0000
73+++ include/unity/scopes/internal/ReplyObject.h 2014-08-13 04:58:30 +0000
74@@ -47,7 +47,8 @@
75 public:
76 UNITY_DEFINES_PTRS(ReplyObject);
77
78- ReplyObject(ListenerBase::SPtr const& receiver_base, RuntimeImpl const* runtime, std::string const& scope_proxy);
79+ ReplyObject(ListenerBase::SPtr const& receiver_base, RuntimeImpl const* runtime,
80+ std::string const& scope_proxy, bool dont_reap);
81 virtual ~ReplyObject();
82
83 virtual bool process_data(VariantMap const& data) = 0;
84
85=== modified file 'include/unity/scopes/internal/ResultReplyObject.h'
86--- include/unity/scopes/internal/ResultReplyObject.h 2014-04-09 09:36:50 +0000
87+++ include/unity/scopes/internal/ResultReplyObject.h 2014-08-13 04:58:30 +0000
88@@ -37,10 +37,8 @@
89 class ResultReplyObject : public ReplyObject
90 {
91 public:
92- ResultReplyObject(SearchListenerBase::SPtr const& receiver,
93- RuntimeImpl const* runtime,
94- std::string const& scope_id,
95- int cardinality);
96+ ResultReplyObject(SearchListenerBase::SPtr const& receiver, RuntimeImpl const* runtime,
97+ std::string const& scope_id, int cardinality, bool dont_reap = false);
98 virtual ~ResultReplyObject();
99
100 virtual bool process_data(VariantMap const& data) override;
101
102=== modified file 'include/unity/scopes/internal/ScopeConfig.h'
103--- include/unity/scopes/internal/ScopeConfig.h 2014-07-22 08:02:32 +0000
104+++ include/unity/scopes/internal/ScopeConfig.h 2014-08-13 04:58:30 +0000
105@@ -52,6 +52,7 @@
106 std::string scope_runner() const; // Optional, throws NotFoundException if not present
107 int idle_timeout() const; // Optional, returns default value if not present
108 ScopeMetadata::ResultsTtlType results_ttl_type() const; // Optional, returns none if not present
109+ bool debug_mode() const; // Optional, returns false if not present
110
111 VariantMap appearance_attributes() const; // Optional, returns empty map if no attributes are present
112
113@@ -71,6 +72,7 @@
114 std::unique_ptr<std::string> scope_runner_;
115 int idle_timeout_;
116 ScopeMetadata::ResultsTtlType results_ttl_type_;
117+ bool debug_mode_;
118
119 VariantMap appearance_attributes_;
120 };
121
122=== modified file 'include/unity/scopes/internal/ScopeObject.h'
123--- include/unity/scopes/internal/ScopeObject.h 2014-02-27 16:58:50 +0000
124+++ include/unity/scopes/internal/ScopeObject.h 2014-08-13 04:58:30 +0000
125@@ -52,7 +52,7 @@
126 public:
127 UNITY_DEFINES_PTRS(ScopeObject);
128
129- ScopeObject(RuntimeImpl* runtime, ScopeBase* scope_base_);
130+ ScopeObject(RuntimeImpl* runtime, ScopeBase* scope_base, bool debug_mode = false);
131 virtual ~ScopeObject();
132
133 // Remote operation implementations
134@@ -78,12 +78,15 @@
135 MWReplyProxy const& reply,
136 InvokeInfo const& info) override;
137
138+ virtual bool debug_mode() const override;
139+
140 private:
141 MWQueryCtrlProxy query(MWReplyProxy const& reply, MiddlewareBase* mw_base,
142 std::function<QueryBase::SPtr(void)> const& query_factory_fun,
143 std::function<QueryObjectBase::SPtr(QueryBase::SPtr, MWQueryCtrlProxy)> const& query_object_factory_fun);
144 RuntimeImpl* const runtime_;
145 ScopeBase* const scope_base_;
146+ bool const debug_mode_;
147 };
148
149 } // namespace internal
150
151=== modified file 'include/unity/scopes/internal/ScopeObjectBase.h'
152--- include/unity/scopes/internal/ScopeObjectBase.h 2014-05-15 00:34:39 +0000
153+++ include/unity/scopes/internal/ScopeObjectBase.h 2014-08-13 04:58:30 +0000
154@@ -69,6 +69,8 @@
155 ActionMetadata const& hints,
156 MWReplyProxy const& reply,
157 InvokeInfo const& info) = 0;
158+
159+ virtual bool debug_mode() const = 0;
160 };
161
162 } // namespace internal
163
164=== modified file 'include/unity/scopes/internal/smartscopes/SSScopeObject.h'
165--- include/unity/scopes/internal/smartscopes/SSScopeObject.h 2014-02-27 16:58:50 +0000
166+++ include/unity/scopes/internal/smartscopes/SSScopeObject.h 2014-08-13 04:58:30 +0000
167@@ -74,6 +74,8 @@
168 MWReplyProxy const& reply,
169 InvokeInfo const& info) override;
170
171+ bool debug_mode() const override;
172+
173 private:
174 MWQueryCtrlProxy query(InvokeInfo const& info,
175 MWReplyProxy const& reply,
176
177=== modified file 'include/unity/scopes/internal/zmq_middleware/ScopeI.h'
178--- include/unity/scopes/internal/zmq_middleware/ScopeI.h 2014-02-27 15:46:44 +0000
179+++ include/unity/scopes/internal/zmq_middleware/ScopeI.h 2014-08-13 04:58:30 +0000
180@@ -43,8 +43,8 @@
181
182 private:
183 virtual void search_(Current const& current,
184- capnp::AnyPointer::Reader& in_params,
185- capnproto::Response::Builder& r);
186+ capnp::AnyPointer::Reader& in_params,
187+ capnproto::Response::Builder& r);
188 virtual void activate_(Current const& current,
189 capnp::AnyPointer::Reader& in_params,
190 capnproto::Response::Builder& r);
191@@ -54,6 +54,9 @@
192 virtual void preview_(Current const& current,
193 capnp::AnyPointer::Reader& in_params,
194 capnproto::Response::Builder& r);
195+ virtual void debug_mode_(Current const& current,
196+ capnp::AnyPointer::Reader& in_params,
197+ capnproto::Response::Builder& r);
198 };
199
200 } // namespace zmq_middleware
201
202=== modified file 'include/unity/scopes/internal/zmq_middleware/ZmqObjectProxy.h'
203--- include/unity/scopes/internal/zmq_middleware/ZmqObjectProxy.h 2014-05-29 15:41:42 +0000
204+++ include/unity/scopes/internal/zmq_middleware/ZmqObjectProxy.h 2014-08-13 04:58:30 +0000
205@@ -77,7 +77,7 @@
206 void invoke_oneway_(capnp::MessageBuilder& out_params);
207
208 ZmqReceiver invoke_twoway_(capnp::MessageBuilder& out_params);
209- ZmqReceiver invoke_twoway_(capnp::MessageBuilder& out_params, int64_t timeout);
210+ ZmqReceiver invoke_twoway_(capnp::MessageBuilder& out_params, int64_t twoway_timeout, int64_t locate_timeout = -1);
211
212 private:
213 ZmqReceiver invoke_twoway__(capnp::MessageBuilder& out_params, int64_t timeout);
214
215=== modified file 'include/unity/scopes/internal/zmq_middleware/ZmqRegistry.h'
216--- include/unity/scopes/internal/zmq_middleware/ZmqRegistry.h 2014-06-04 17:49:34 +0000
217+++ include/unity/scopes/internal/zmq_middleware/ZmqRegistry.h 2014-08-13 04:58:30 +0000
218@@ -51,6 +51,7 @@
219 // Remote operations.
220 virtual ScopeMetadata get_metadata(std::string const& scope_id) override;
221 virtual MetadataMap list() override;
222+ virtual ObjectProxy locate(std::string const& identity, int64_t timeout) override;
223 virtual ObjectProxy locate(std::string const& identity) override;
224 virtual bool is_scope_running(std::string const& scope_id) override;
225 };
226
227=== modified file 'include/unity/scopes/internal/zmq_middleware/ZmqScope.h'
228--- include/unity/scopes/internal/zmq_middleware/ZmqScope.h 2014-02-27 16:58:50 +0000
229+++ include/unity/scopes/internal/zmq_middleware/ZmqScope.h 2014-08-13 04:58:30 +0000
230@@ -62,6 +62,12 @@
231 virtual QueryCtrlProxy preview(VariantMap const& result,
232 VariantMap const& hints,
233 MWReplyProxy const& reply) override;
234+
235+ virtual bool debug_mode() override;
236+
237+private:
238+ ZmqReceiver invoke_scope_(capnp::MessageBuilder& out_params);
239+ std::unique_ptr<bool> debug_mode_;
240 };
241
242 } // namespace zmq_middleware
243
244=== modified file 'scoperegistry/scoperegistry.cpp'
245--- scoperegistry/scoperegistry.cpp 2014-07-29 10:22:45 +0000
246+++ scoperegistry/scoperegistry.cpp 2014-08-13 04:58:30 +0000
247@@ -389,7 +389,15 @@
248 scope_dir.filename().native();
249 }
250
251- exec_data.timeout_ms = timeout_ms;
252+ // Check if this scope has requested debug mode, if so, set the process timeout to 15s
253+ if (sc.debug_mode())
254+ {
255+ exec_data.timeout_ms = 15000;
256+ }
257+ else
258+ {
259+ exec_data.timeout_ms = timeout_ms;
260+ }
261
262 try
263 {
264
265=== modified file 'src/scopes/internal/ActivationReplyObject.cpp'
266--- src/scopes/internal/ActivationReplyObject.cpp 2014-03-07 04:19:32 +0000
267+++ src/scopes/internal/ActivationReplyObject.cpp 2014-08-13 04:58:30 +0000
268@@ -30,8 +30,9 @@
269 namespace internal
270 {
271
272-ActivationReplyObject::ActivationReplyObject(ActivationListenerBase::SPtr const& receiver, RuntimeImpl const* runtime, std::string const& scope_id) :
273- ReplyObject(std::static_pointer_cast<ListenerBase>(receiver), runtime, scope_id),
274+ActivationReplyObject::ActivationReplyObject(ActivationListenerBase::SPtr const& receiver, RuntimeImpl const* runtime,
275+ std::string const& scope_id, bool dont_reap) :
276+ ReplyObject(std::static_pointer_cast<ListenerBase>(receiver), runtime, scope_id, dont_reap),
277 receiver_(receiver)
278 {
279 assert(receiver_);
280
281=== modified file 'src/scopes/internal/PreviewReplyObject.cpp'
282--- src/scopes/internal/PreviewReplyObject.cpp 2014-03-07 04:19:32 +0000
283+++ src/scopes/internal/PreviewReplyObject.cpp 2014-08-13 04:58:30 +0000
284@@ -40,8 +40,9 @@
285 namespace internal
286 {
287
288-PreviewReplyObject::PreviewReplyObject(PreviewListenerBase::SPtr const& receiver, RuntimeImpl const* runtime, std::string const& scope_id) :
289- ReplyObject(std::static_pointer_cast<ListenerBase>(receiver), runtime, scope_id),
290+PreviewReplyObject::PreviewReplyObject(PreviewListenerBase::SPtr const& receiver, RuntimeImpl const* runtime,
291+ std::string const& scope_id, bool dont_reap) :
292+ ReplyObject(std::static_pointer_cast<ListenerBase>(receiver), runtime, scope_id, dont_reap),
293 receiver_(receiver)
294 {
295 assert(receiver_);
296
297=== modified file 'src/scopes/internal/RegistryObject.cpp'
298--- src/scopes/internal/RegistryObject.cpp 2014-08-06 04:54:06 +0000
299+++ src/scopes/internal/RegistryObject.cpp 2014-08-13 04:58:30 +0000
300@@ -261,18 +261,24 @@
301 "with empty id");
302 }
303
304- lock_guard<decltype(mutex_)> lock(mutex_);
305-
306- scope_processes_.erase(scope_id);
307-
308- if (scopes_.erase(scope_id) == 1)
309+ unique_lock<decltype(mutex_)> lock(mutex_);
310+ if (scopes_.find(scope_id) != scopes_.end())
311 {
312- if (publisher_)
313+ // Unlock here so that we can handle on_process_death
314+ lock.unlock();
315+ scope_processes_.at(scope_id).kill();
316+ lock.lock();
317+ scope_processes_.erase(scope_id);
318+
319+ if (scopes_.erase(scope_id) == 1)
320 {
321- // Send a blank message to subscribers to inform them that the registry has been updated
322- publisher_->send_message("");
323+ if (publisher_)
324+ {
325+ // Send a blank message to subscribers to inform them that the registry has been updated
326+ publisher_->send_message("");
327+ }
328+ return true;
329 }
330- return true;
331 }
332
333 return false;
334@@ -335,8 +341,7 @@
335 }
336
337 RegistryObject::ScopeProcess::ScopeProcess(ScopeProcess const& other)
338- : exec_data_(other.exec_data_)
339- , reg_publisher_(other.reg_publisher_)
340+ : ScopeProcess(other.exec_data_, other.reg_publisher_)
341 {
342 }
343
344
345=== modified file 'src/scopes/internal/ReplyObject.cpp'
346--- src/scopes/internal/ReplyObject.cpp 2014-07-30 21:34:13 +0000
347+++ src/scopes/internal/ReplyObject.cpp 2014-08-13 04:58:30 +0000
348@@ -41,7 +41,8 @@
349 namespace internal
350 {
351
352-ReplyObject::ReplyObject(ListenerBase::SPtr const& receiver_base, RuntimeImpl const* runtime, std::string const& scope_proxy) :
353+ReplyObject::ReplyObject(ListenerBase::SPtr const& receiver_base, RuntimeImpl const* runtime,
354+ std::string const& scope_proxy, bool dont_reap) :
355 listener_base_(receiver_base),
356 finished_(false),
357 origin_proxy_(scope_proxy),
358@@ -50,10 +51,14 @@
359 {
360 assert(receiver_base);
361 assert(runtime);
362- reap_item_ = runtime->reply_reaper()->add([this] {
363- string msg = "No activity on ReplyObject for scope " + this->origin_proxy_ + ": ReplyObject destroyed";
364- this->finished(CompletionDetails(CompletionDetails::Error, msg));
365- });
366+
367+ if (dont_reap == false)
368+ {
369+ reap_item_ = runtime->reply_reaper()->add([this] {
370+ string msg = "No activity on ReplyObject for scope " + this->origin_proxy_ + ": ReplyObject destroyed";
371+ this->finished(CompletionDetails(CompletionDetails::Error, msg));
372+ });
373+ }
374 }
375
376 ReplyObject::~ReplyObject()
377@@ -89,7 +94,10 @@
378 return; // Ignore replies that arrive after finished().
379 }
380
381- reap_item_->refresh();
382+ if (reap_item_)
383+ {
384+ reap_item_->refresh();
385+ }
386
387 {
388 unique_lock<mutex> lock(mutex_);
389@@ -148,7 +156,10 @@
390
391 // Only one thread can reach this point, any others were thrown out above.
392
393- reap_item_->destroy();
394+ if (reap_item_)
395+ {
396+ reap_item_->destroy();
397+ }
398
399 // Wait until all currently executing calls to push() have completed.
400 unique_lock<mutex> lock(mutex_);
401@@ -189,7 +200,10 @@
402 return; // Ignore info messages that arrive after finished().
403 }
404
405- reap_item_->refresh();
406+ if (reap_item_)
407+ {
408+ reap_item_->refresh();
409+ }
410 info_occurred_.exchange(true);
411
412 try
413
414=== modified file 'src/scopes/internal/ResultReplyObject.cpp'
415--- src/scopes/internal/ResultReplyObject.cpp 2014-05-29 10:03:56 +0000
416+++ src/scopes/internal/ResultReplyObject.cpp 2014-08-13 04:58:30 +0000
417@@ -43,11 +43,9 @@
418 namespace internal
419 {
420
421-ResultReplyObject::ResultReplyObject(SearchListenerBase::SPtr const& receiver,
422- RuntimeImpl const* runtime,
423- std::string const& scope_id,
424- int cardinality) :
425- ReplyObject(std::static_pointer_cast<ListenerBase>(receiver), runtime, scope_id),
426+ResultReplyObject::ResultReplyObject(SearchListenerBase::SPtr const& receiver, RuntimeImpl const* runtime,
427+ std::string const& scope_id, int cardinality, bool dont_reap) :
428+ ReplyObject(std::static_pointer_cast<ListenerBase>(receiver), runtime, scope_id, dont_reap),
429 receiver_(receiver),
430 cat_registry_(new CategoryRegistry()),
431 runtime_(runtime),
432
433=== modified file 'src/scopes/internal/RuntimeImpl.cpp'
434--- src/scopes/internal/RuntimeImpl.cpp 2014-08-08 14:06:59 +0000
435+++ src/scopes/internal/RuntimeImpl.cpp 2014-08-13 04:58:30 +0000
436@@ -357,15 +357,18 @@
437 auto run_future = std::async(launch::async, [scope_base] { scope_base->run(); });
438
439 // Create a servant for the scope and register the servant.
440- auto scope = unique_ptr<internal::ScopeObject>(new internal::ScopeObject(this, scope_base));
441 if (!scope_ini_file.empty())
442 {
443+ // Check if this scope has requested debug mode, if so, disable the idle timeout
444 ScopeConfig scope_config(scope_ini_file);
445- int idle_timeout_ms = scope_config.idle_timeout() * 1000;
446+ int idle_timeout_ms = scope_config.debug_mode() ? -1 : scope_config.idle_timeout() * 1000;
447+
448+ auto scope = unique_ptr<internal::ScopeObject>(new internal::ScopeObject(this, scope_base, scope_config.debug_mode()));
449 mw->add_scope_object(scope_id_, move(scope), idle_timeout_ms);
450 }
451 else
452 {
453+ auto scope = unique_ptr<internal::ScopeObject>(new internal::ScopeObject(this, scope_base));
454 mw->add_scope_object(scope_id_, move(scope));
455 }
456
457
458=== modified file 'src/scopes/internal/ScopeConfig.cpp'
459--- src/scopes/internal/ScopeConfig.cpp 2014-08-08 12:31:23 +0000
460+++ src/scopes/internal/ScopeConfig.cpp 2014-08-13 04:58:30 +0000
461@@ -55,6 +55,7 @@
462 const string scoperunner_key = "ScopeRunner";
463 const string idle_timeout_key = "IdleTimeout";
464 const string results_ttl_key = "ResultsTtlType";
465+ const string debug_mode_key = "DebugMode";
466
467 const string scope_appearance_group = "Appearance";
468 const string fg_color_key = "ForegroundColor";
469@@ -189,6 +190,15 @@
470 {
471 }
472
473+ try
474+ {
475+ debug_mode_ = parser()->get_boolean(scope_config_group, debug_mode_key);
476+ }
477+ catch (LogicException const&)
478+ {
479+ debug_mode_ = false;
480+ }
481+
482 // read all display attributes from scope_appearance_group
483 try
484 {
485@@ -202,39 +212,40 @@
486 }
487
488 KnownEntries const known_entries = {
489- { scope_config_group,
490- {
491- overrideable_key,
492- scope_name_key,
493- description_key,
494- author_key,
495- art_key,
496- icon_key,
497- search_hint_key,
498- hot_key_key,
499- invisible_key,
500- location_data_needed_key,
501- scoperunner_key,
502- idle_timeout_key,
503- results_ttl_key
504- }
505- },
506- { scope_appearance_group,
507- {
508- fg_color_key,
509- bg_color_key,
510- shape_images_key,
511- category_header_bg_key,
512- preview_button_color_key,
513- logo_overlay_color_key,
514- pageheader_logo_key,
515- pageheader_fg_color_key,
516- pageheader_background_key,
517- pageheader_div_color_key,
518- pageheader_nav_bg_key
519- }
520- }
521- };
522+ { scope_config_group,
523+ {
524+ overrideable_key,
525+ scope_name_key,
526+ description_key,
527+ author_key,
528+ art_key,
529+ icon_key,
530+ search_hint_key,
531+ hot_key_key,
532+ invisible_key,
533+ location_data_needed_key,
534+ scoperunner_key,
535+ idle_timeout_key,
536+ results_ttl_key,
537+ debug_mode_key
538+ }
539+ },
540+ { scope_appearance_group,
541+ {
542+ fg_color_key,
543+ bg_color_key,
544+ shape_images_key,
545+ category_header_bg_key,
546+ preview_button_color_key,
547+ logo_overlay_color_key,
548+ pageheader_logo_key,
549+ pageheader_fg_color_key,
550+ pageheader_background_key,
551+ pageheader_div_color_key,
552+ pageheader_nav_bg_key
553+ }
554+ }
555+ };
556 check_unknown_entries(known_entries);
557 }
558
559@@ -380,6 +391,11 @@
560 return results_ttl_type_;
561 }
562
563+bool ScopeConfig::debug_mode() const
564+{
565+ return debug_mode_;
566+}
567+
568 VariantMap ScopeConfig::appearance_attributes() const
569 {
570 return appearance_attributes_;
571
572=== modified file 'src/scopes/internal/ScopeImpl.cpp'
573--- src/scopes/internal/ScopeImpl.cpp 2014-07-28 08:30:35 +0000
574+++ src/scopes/internal/ScopeImpl.cpp 2014-08-13 04:58:30 +0000
575@@ -95,7 +95,7 @@
576 throw unity::InvalidArgumentException("Scope::search(): invalid SearchListenerBase (nullptr)");
577 }
578
579- ReplyObject::SPtr ro(make_shared<ResultReplyObject>(reply, runtime_, to_string(), metadata.cardinality()));
580+ ReplyObject::SPtr ro(make_shared<ResultReplyObject>(reply, runtime_, to_string(), metadata.cardinality(), fwd()->debug_mode()));
581 MWReplyProxy rp = fwd()->mw_base()->add_reply_object(ro);
582
583 // "Fake" QueryCtrlProxy that doesn't have a real MWQueryCtrlProxy yet.
584@@ -149,7 +149,7 @@
585 throw unity::InvalidArgumentException("Scope::activate(): invalid ActivationListenerBase (nullptr)");
586 }
587
588- ActivationReplyObject::SPtr ro(make_shared<ActivationReplyObject>(reply, runtime_, to_string()));
589+ ReplyObject::SPtr ro(make_shared<ActivationReplyObject>(reply, runtime_, to_string(), fwd()->debug_mode()));
590 MWReplyProxy rp = fwd()->mw_base()->add_reply_object(ro);
591
592 shared_ptr<QueryCtrlImpl> ctrl = make_shared<QueryCtrlImpl>(nullptr, rp);
593@@ -197,7 +197,7 @@
594 throw unity::InvalidArgumentException("Scope::perform_action(): invalid ActivationListenerBase (nullptr)");
595 }
596
597- ActivationReplyObject::SPtr ro(make_shared<ActivationReplyObject>(reply, runtime_, to_string()));
598+ ReplyObject::SPtr ro(make_shared<ActivationReplyObject>(reply, runtime_, to_string(), fwd()->debug_mode()));
599 MWReplyProxy rp = fwd()->mw_base()->add_reply_object(ro);
600
601 shared_ptr<QueryCtrlImpl> ctrl = make_shared<QueryCtrlImpl>(nullptr, rp);
602@@ -246,7 +246,7 @@
603 throw unity::InvalidArgumentException("Scope::preview(): invalid PreviewListenerBase (nullptr)");
604 }
605
606- PreviewReplyObject::SPtr ro(make_shared<PreviewReplyObject>(reply, runtime_, to_string()));
607+ ReplyObject::SPtr ro(make_shared<PreviewReplyObject>(reply, runtime_, to_string(), fwd()->debug_mode()));
608 MWReplyProxy rp = fwd()->mw_base()->add_reply_object(ro);
609
610 shared_ptr<QueryCtrlImpl> ctrl = make_shared<QueryCtrlImpl>(nullptr, rp);
611
612=== modified file 'src/scopes/internal/ScopeObject.cpp'
613--- src/scopes/internal/ScopeObject.cpp 2014-08-05 05:29:56 +0000
614+++ src/scopes/internal/ScopeObject.cpp 2014-08-13 04:58:30 +0000
615@@ -47,9 +47,10 @@
616 namespace internal
617 {
618
619-ScopeObject::ScopeObject(RuntimeImpl* runtime, ScopeBase* scope_base) :
620+ScopeObject::ScopeObject(RuntimeImpl* runtime, ScopeBase* scope_base, bool debug_mode) :
621 runtime_(runtime),
622- scope_base_(scope_base)
623+ scope_base_(scope_base),
624+ debug_mode_(debug_mode)
625 {
626 assert(runtime);
627 assert(scope_base);
628@@ -217,6 +218,11 @@
629 );
630 }
631
632+bool ScopeObject::debug_mode() const
633+{
634+ return debug_mode_;
635+}
636+
637 } // namespace internal
638
639 } // namespace scopes
640
641=== modified file 'src/scopes/internal/smartscopes/SSScopeObject.cpp'
642--- src/scopes/internal/smartscopes/SSScopeObject.cpp 2014-07-28 08:30:35 +0000
643+++ src/scopes/internal/smartscopes/SSScopeObject.cpp 2014-08-13 04:58:30 +0000
644@@ -192,6 +192,11 @@
645 return info.mw->create_query_ctrl_proxy(reply->identity() + ".c", info.mw->get_query_ctrl_endpoint());
646 }
647
648+bool SSScopeObject::debug_mode() const
649+{
650+ return false;
651+}
652+
653 } // namespace smartscopes
654
655 } // namespace internal
656
657=== modified file 'src/scopes/internal/zmq_middleware/ScopeI.cpp'
658--- src/scopes/internal/zmq_middleware/ScopeI.cpp 2014-05-29 15:41:42 +0000
659+++ src/scopes/internal/zmq_middleware/ScopeI.cpp 2014-08-13 04:58:30 +0000
660@@ -60,6 +60,7 @@
661 QueryCtrl* preview(ValueDict result, ValueDict hints, Reply* replyProxy);
662 QueryCtrl* perform_action(ValueDict result, ValueDict hints, string action_id, Reply* replyProxy);
663 QueryCtrl* activate(ValueDict result, ValueDict hints, Reply* replyProxy);
664+ bool debug_mode();
665 };
666
667 */
668@@ -71,7 +72,8 @@
669 { "search", bind(&ScopeI::search_, this, _1, _2, _3) },
670 { "preview", bind(&ScopeI::preview_, this, _1, _2, _3) },
671 { "activate", bind(&ScopeI::activate_, this, _1, _2, _3) },
672- { "perform_action", bind(&ScopeI::perform_action_, this, _1, _2, _3) }
673+ { "perform_action", bind(&ScopeI::perform_action_, this, _1, _2, _3) },
674+ { "debug_mode", bind(&ScopeI::debug_mode_, this, _1, _2, _3) }
675 })
676 {
677 }
678@@ -81,8 +83,8 @@
679 }
680
681 void ScopeI::search_(Current const& current,
682- capnp::AnyPointer::Reader& in_params,
683- capnproto::Response::Builder& r)
684+ capnp::AnyPointer::Reader& in_params,
685+ capnproto::Response::Builder& r)
686 {
687 auto req = in_params.getAs<capnproto::Scope::CreateQueryRequest>();
688 auto query = internal::CannedQueryImpl::create(to_variant_map(req.getQuery()));
689@@ -135,8 +137,8 @@
690 }
691
692 void ScopeI::perform_action_(Current const& current,
693- capnp::AnyPointer::Reader& in_params,
694- capnproto::Response::Builder& r)
695+ capnp::AnyPointer::Reader& in_params,
696+ capnproto::Response::Builder& r)
697 {
698 auto req = in_params.getAs<capnproto::Scope::ActionActivationRequest>();
699 auto result = ResultImpl::create_result(to_variant_map(req.getResult()));
700@@ -192,6 +194,18 @@
701 p.setCategory(ctrl_proxy->target_category().c_str());
702 }
703
704+void ScopeI::debug_mode_(Current const&,
705+ capnp::AnyPointer::Reader&,
706+ capnproto::Response::Builder& r)
707+{
708+ auto delegate = dynamic_pointer_cast<ScopeObjectBase>(del());
709+ assert(delegate);
710+ auto debug_mode = delegate->debug_mode();
711+ r.setStatus(capnproto::ResponseStatus::SUCCESS);
712+ auto debug_mode_response = r.initPayload().getAs<capnproto::Scope::DebugModeResponse>();
713+ debug_mode_response.setReturnValue(debug_mode);
714+}
715+
716 } // namespace zmq_middleware
717
718 } // namespace internal
719
720=== modified file 'src/scopes/internal/zmq_middleware/ZmqObject.cpp'
721--- src/scopes/internal/zmq_middleware/ZmqObject.cpp 2014-08-08 12:22:19 +0000
722+++ src/scopes/internal/zmq_middleware/ZmqObject.cpp 2014-08-13 04:58:30 +0000
723@@ -206,7 +206,7 @@
724 return invoke_twoway_(out_params, timeout_);
725 }
726
727-ZmqReceiver ZmqObjectProxy::invoke_twoway_(capnp::MessageBuilder& out_params, int64_t timeout)
728+ZmqReceiver ZmqObjectProxy::invoke_twoway_(capnp::MessageBuilder& out_params, int64_t twoway_timeout, int64_t locate_timeout)
729 {
730 auto registry_proxy = mw_base()->registry_proxy();
731 auto ss_registry_proxy = mw_base()->ss_registry_proxy();
732@@ -221,7 +221,15 @@
733 {
734 try
735 {
736- ObjectProxy new_proxy = registry_proxy->locate(identity());
737+ ObjectProxy new_proxy;
738+ if (locate_timeout != -1)
739+ {
740+ new_proxy = registry_proxy->locate(identity(), locate_timeout);
741+ }
742+ else
743+ {
744+ new_proxy = registry_proxy->locate(identity());
745+ }
746 // update our proxy with the newly received data
747 // (we need to first store values in local variables outside of the mutex,
748 // otherwise we will deadlock on the following ZmqObjectProxy methods)
749@@ -244,7 +252,7 @@
750 }
751
752 // Try the invocation
753- return invoke_twoway__(out_params, timeout);
754+ return invoke_twoway__(out_params, twoway_timeout);
755 }
756
757 // Get a socket to the endpoint for this proxy and write the request on the wire.
758
759=== modified file 'src/scopes/internal/zmq_middleware/ZmqRegistry.cpp'
760--- src/scopes/internal/zmq_middleware/ZmqRegistry.cpp 2014-07-14 06:54:43 +0000
761+++ src/scopes/internal/zmq_middleware/ZmqRegistry.cpp 2014-08-13 04:58:30 +0000
762@@ -144,7 +144,7 @@
763 return sm;
764 }
765
766-ObjectProxy ZmqRegistry::locate(std::string const& identity)
767+ObjectProxy ZmqRegistry::locate(std::string const& identity, int64_t timeout)
768 {
769 capnp::MallocMessageBuilder request_builder;
770 auto request = make_request_(request_builder, "locate");
771@@ -152,7 +152,6 @@
772 in_params.setIdentity(identity.c_str());
773
774 // locate uses a custom timeout because it needs to potentially fork/exec a scope.
775- int64_t timeout = mw_base()->locate_timeout();
776 auto future = mw_base()->twoway_pool()->submit([&] { return this->invoke_twoway_(request_builder, timeout); });
777 auto receiver = future.get();
778 auto segments = receiver.receive();
779@@ -192,6 +191,11 @@
780 }
781 }
782
783+ObjectProxy ZmqRegistry::locate(std::string const& identity)
784+{
785+ return locate(identity, mw_base()->locate_timeout());
786+}
787+
788 bool ZmqRegistry::is_scope_running(std::string const& scope_id)
789 {
790 capnp::MallocMessageBuilder request_builder;
791
792=== modified file 'src/scopes/internal/zmq_middleware/ZmqScope.cpp'
793--- src/scopes/internal/zmq_middleware/ZmqScope.cpp 2014-06-30 07:30:25 +0000
794+++ src/scopes/internal/zmq_middleware/ZmqScope.cpp 2014-08-13 04:58:30 +0000
795@@ -54,6 +54,7 @@
796 QueryCtrl* activate(string query, ValueDict hints, Reply* replyProxy);
797 QueryCtrl* perform_action(string query, ValueDict hints, string action_id, Reply* replyProxy);
798 QueryCtrl* preview(string query, ValueDict hints, Reply* replyProxy);
799+ bool debug_mode();
800 };
801
802 */
803@@ -90,7 +91,7 @@
804 p.setCategory(reply_proxy->target_category().c_str());
805 }
806
807- auto future = mw_base()->twoway_pool()->submit([&] { return this->invoke_twoway_(request_builder); });
808+ auto future = mw_base()->twoway_pool()->submit([&] { return this->invoke_scope_(request_builder); });
809
810 auto receiver = future.get();
811 auto segments = receiver.receive();
812@@ -122,7 +123,7 @@
813 p.setIdentity(reply_proxy->identity().c_str());
814 }
815
816- auto future = mw_base()->twoway_pool()->submit([&] { return this->invoke_twoway_(request_builder); });
817+ auto future = mw_base()->twoway_pool()->submit([&] { return this->invoke_scope_(request_builder); });
818
819 auto receiver = future.get();
820 auto segments = receiver.receive();
821@@ -157,7 +158,7 @@
822 p.setIdentity(reply_proxy->identity().c_str());
823 }
824
825- auto future = mw_base()->twoway_pool()->submit([&] { return this->invoke_twoway_(request_builder); });
826+ auto future = mw_base()->twoway_pool()->submit([&] { return this->invoke_scope_(request_builder); });
827 future.wait();
828
829 auto receiver = future.get();
830@@ -190,7 +191,7 @@
831 p.setIdentity(reply_proxy->identity().c_str());
832 }
833
834- auto future = mw_base()->twoway_pool()->submit([&] { return this->invoke_twoway_(request_builder); });
835+ auto future = mw_base()->twoway_pool()->submit([&] { return this->invoke_scope_(request_builder); });
836
837 auto receiver = future.get();
838 auto segments = receiver.receive();
839@@ -206,6 +207,39 @@
840 return make_shared<QueryCtrlImpl>(p, reply_proxy);
841 }
842
843+bool ZmqScope::debug_mode()
844+{
845+ // We only need to retrieve the debug mode state once, so we cache it in debug_mode_
846+ if (!debug_mode_)
847+ {
848+ capnp::MallocMessageBuilder request_builder;
849+ make_request_(request_builder, "debug_mode");
850+
851+ auto future = mw_base()->twoway_pool()->submit([&] { return this->invoke_twoway_(request_builder); });
852+ auto receiver = future.get();
853+ auto segments = receiver.receive();
854+ capnp::SegmentArrayMessageReader reader(segments);
855+ auto response = reader.getRoot<capnproto::Response>();
856+ throw_if_runtime_exception(response);
857+
858+ auto debug_mode_response = response.getPayload().getAs<capnproto::Scope::DebugModeResponse>();
859+ debug_mode_.reset(new bool(debug_mode_response.getReturnValue()));
860+ }
861+
862+ return *debug_mode_;
863+}
864+
865+ZmqReceiver ZmqScope::invoke_scope_(capnp::MessageBuilder& out_params)
866+{
867+ // Check if this scope has requested debug mode, if so, disable two-way timeout and set
868+ // locate timeout to 15s.
869+ if (debug_mode())
870+ {
871+ return this->invoke_twoway_(out_params, -1, 15000);
872+ }
873+ return this->invoke_twoway_(out_params);
874+}
875+
876 } // namespace zmq_middleware
877
878 } // namespace internal
879
880=== modified file 'src/scopes/internal/zmq_middleware/capnproto/Scope.capnp'
881--- src/scopes/internal/zmq_middleware/capnproto/Scope.capnp 2014-02-04 15:15:25 +0000
882+++ src/scopes/internal/zmq_middleware/capnproto/Scope.capnp 2014-08-13 04:58:30 +0000
883@@ -75,3 +75,8 @@
884 hints @1 : ValueDict.ValueDict;
885 replyProxy @2 : Proxy.Proxy;
886 }
887+
888+struct DebugModeResponse
889+{
890+ returnValue @0 : Bool;
891+}
892
893=== modified file 'test/gtest/scopes/Invocation/CMakeLists.txt'
894--- test/gtest/scopes/Invocation/CMakeLists.txt 2014-05-13 01:40:09 +0000
895+++ test/gtest/scopes/Invocation/CMakeLists.txt 2014-08-13 04:58:30 +0000
896@@ -1,8 +1,9 @@
897 configure_file(Registry.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Registry.ini)
898 configure_file(Runtime.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini)
899 configure_file(Zmq.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Zmq.ini)
900+configure_file(DebugTestScope.ini.in ${CMAKE_CURRENT_BINARY_DIR}/DebugTestScope.ini)
901
902-add_executable(Invocation_test Invocation_test.cpp TestScope.cpp EmptyScope.cpp)
903+add_executable(Invocation_test Invocation_test.cpp TestScope.cpp EmptyScope.cpp DebugTestScope.cpp)
904 target_link_libraries(Invocation_test ${TESTLIBS})
905
906 add_test(Invocation Invocation_test)
907
908=== added file 'test/gtest/scopes/Invocation/DebugTestScope.cpp'
909--- test/gtest/scopes/Invocation/DebugTestScope.cpp 1970-01-01 00:00:00 +0000
910+++ test/gtest/scopes/Invocation/DebugTestScope.cpp 2014-08-13 04:58:30 +0000
911@@ -0,0 +1,59 @@
912+/*
913+ * Copyright (C) 2014 Canonical Ltd
914+ *
915+ * This program is free software: you can redistribute it and/or modify
916+ * it under the terms of the GNU Lesser General Public License version 3 as
917+ * published by the Free Software Foundation.
918+ *
919+ * This program is distributed in the hope that it will be useful,
920+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
921+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
922+ * GNU Lesser General Public License for more details.
923+ *
924+ * You should have received a copy of the GNU Lesser General Public License
925+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
926+ *
927+ * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com>
928+ */
929+
930+#include "DebugTestScope.h"
931+
932+#include <unity/scopes/ScopeBase.h>
933+
934+#include <thread>
935+
936+using namespace std;
937+using namespace unity::scopes;
938+
939+namespace
940+{
941+
942+class TestQuery : public SearchQueryBase
943+{
944+public:
945+ TestQuery(CannedQuery const& query, SearchMetadata const& metadata)
946+ : SearchQueryBase(query, metadata)
947+ {
948+ }
949+
950+ virtual void cancelled() override
951+ {
952+ }
953+
954+ virtual void run(SearchReplyProxy const&) override
955+ {
956+ }
957+};
958+
959+} // namespace
960+
961+SearchQueryBase::UPtr DebugTestScope::search(CannedQuery const& query, SearchMetadata const& metadata)
962+{
963+ this_thread::sleep_for(chrono::milliseconds(2000)); // Attempt to timeout the two-way invocation
964+ return SearchQueryBase::UPtr(new TestQuery(query, metadata));
965+}
966+
967+PreviewQueryBase::UPtr DebugTestScope::preview(Result const&, ActionMetadata const&)
968+{
969+ return nullptr; // unused
970+}
971
972=== added file 'test/gtest/scopes/Invocation/DebugTestScope.h'
973--- test/gtest/scopes/Invocation/DebugTestScope.h 1970-01-01 00:00:00 +0000
974+++ test/gtest/scopes/Invocation/DebugTestScope.h 2014-08-13 04:58:30 +0000
975@@ -0,0 +1,33 @@
976+/*
977+ * Copyright (C) 2014 Canonical Ltd
978+ *
979+ * This program is free software: you can redistribute it and/or modify
980+ * it under the terms of the GNU Lesser General Public License version 3 as
981+ * published by the Free Software Foundation.
982+ *
983+ * This program is distributed in the hope that it will be useful,
984+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
985+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
986+ * GNU Lesser General Public License for more details.
987+ *
988+ * You should have received a copy of the GNU Lesser General Public License
989+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
990+ *
991+ * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com>
992+ */
993+
994+#ifndef TEST_DEBUGTESTSCOPE_H
995+#define TEST_DEBUGTESTSCOPE_H
996+
997+#include <unity/scopes/ScopeBase.h>
998+
999+class DebugTestScope : public unity::scopes::ScopeBase
1000+{
1001+public:
1002+ virtual unity::scopes::SearchQueryBase::UPtr search(unity::scopes::CannedQuery const&,
1003+ unity::scopes::SearchMetadata const&) override;
1004+ virtual unity::scopes::PreviewQueryBase::UPtr preview(unity::scopes::Result const&,
1005+ unity::scopes::ActionMetadata const&) override;
1006+};
1007+
1008+#endif
1009
1010=== added file 'test/gtest/scopes/Invocation/DebugTestScope.ini.in'
1011--- test/gtest/scopes/Invocation/DebugTestScope.ini.in 1970-01-01 00:00:00 +0000
1012+++ test/gtest/scopes/Invocation/DebugTestScope.ini.in 2014-08-13 04:58:30 +0000
1013@@ -0,0 +1,5 @@
1014+[ScopeConfig]
1015+DisplayName = Debug Test Scope
1016+Description = Debug Test Scope description
1017+Author = Canonical
1018+DebugMode = true
1019
1020=== modified file 'test/gtest/scopes/Invocation/Invocation_test.cpp'
1021--- test/gtest/scopes/Invocation/Invocation_test.cpp 2014-07-28 08:30:35 +0000
1022+++ test/gtest/scopes/Invocation/Invocation_test.cpp 2014-08-13 04:58:30 +0000
1023@@ -38,6 +38,7 @@
1024
1025 #include "EmptyScope.h"
1026 #include "TestScope.h"
1027+#include "DebugTestScope.h"
1028
1029 using namespace std;
1030 using namespace unity::scopes;
1031@@ -136,6 +137,26 @@
1032 EXPECT_EQ("", receiver->error_message());
1033 }
1034
1035+TEST(Invocation, no_timeout_in_debug_mode)
1036+{
1037+ auto reg_rt = run_test_registry();
1038+ auto rt = internal::RuntimeImpl::create("", "Runtime.ini");
1039+ auto mw = rt->factory()->create("DebugTestScope", "Zmq", "Zmq.ini");
1040+ mw->start();
1041+ auto proxy = mw->create_scope_proxy("DebugTestScope");
1042+ auto scope = internal::ScopeImpl::create(proxy, rt.get(), "TestScope");
1043+
1044+ auto receiver = make_shared<TestReceiver>();
1045+
1046+ // This call sleeps for 2s then returns
1047+ scope->search("test", SearchMetadata("unused", "unused"), receiver);
1048+ receiver->wait_until_finished();
1049+
1050+ // Check that the two-way invocation timeout did not kick in due to "DebugMode = true"
1051+ EXPECT_EQ(CompletionDetails::OK, receiver->status());
1052+ EXPECT_EQ("", receiver->error_message());
1053+}
1054+
1055 class NullReceiver : public SearchListenerBase
1056 {
1057 public:
1058@@ -154,6 +175,7 @@
1059
1060 TEST(Invocation, shutdown_with_outstanding_async)
1061 {
1062+ auto reg_rt = run_test_registry();
1063 auto rt = internal::RuntimeImpl::create("", "Runtime.ini");
1064 auto mw = rt->factory()->create("EmptyScope", "Zmq", "Zmq.ini");
1065 mw->start();
1066@@ -183,6 +205,12 @@
1067 rt->run_scope(&scope, runtime_ini_file, "");
1068 }
1069
1070+void debugtestscope_thread(Runtime::SPtr const& rt, string const& runtime_ini_file)
1071+{
1072+ DebugTestScope scope;
1073+ rt->run_scope(&scope, runtime_ini_file, "DebugTestScope.ini");
1074+}
1075+
1076 int main(int argc, char **argv)
1077 {
1078 ::testing::InitGoogleTest(&argc, argv);
1079@@ -193,6 +221,9 @@
1080 Runtime::SPtr esrt = move(Runtime::create_scope_runtime("EmptyScope", "Runtime.ini"));
1081 std::thread emptyscope_t(nullscope_thread, esrt, "Runtime.ini");
1082
1083+ Runtime::SPtr dsrt = move(Runtime::create_scope_runtime("DebugTestScope", "Runtime.ini"));
1084+ std::thread debugtestscope_t(debugtestscope_thread, dsrt, "Runtime.ini");
1085+
1086 // Give threads some time to bind to endpoints, to avoid getting ObjectNotExistException
1087 // from a synchronous remote call.
1088 this_thread::sleep_for(chrono::milliseconds(500));
1089@@ -205,5 +236,8 @@
1090 esrt->destroy();
1091 emptyscope_t.join();
1092
1093+ dsrt->destroy();
1094+ debugtestscope_t.join();
1095+
1096 return rc;
1097 }
1098
1099=== modified file 'test/gtest/scopes/Registry/Registry_test.cpp'
1100--- test/gtest/scopes/Registry/Registry_test.cpp 2014-08-01 03:19:32 +0000
1101+++ test/gtest/scopes/Registry/Registry_test.cpp 2014-08-13 04:58:30 +0000
1102@@ -240,6 +240,64 @@
1103 EXPECT_FALSE(r->is_scope_running("testscopeB"));
1104 }
1105
1106+TEST(Registry, no_idle_timeout_in_debug_mode)
1107+{
1108+ bool update_received = false;
1109+ std::mutex mutex;
1110+ std::condition_variable cond;
1111+
1112+ Runtime::UPtr rt = Runtime::create(TEST_RUNTIME_FILE);
1113+ RegistryProxy r = rt->registry();
1114+
1115+ // Configure testscopeC scope_state_callback
1116+ auto conn = r->set_scope_state_callback("testscopeC", [&update_received, &mutex, &cond](bool)
1117+ {
1118+ std::lock_guard<std::mutex> lock(mutex);
1119+ update_received = true;
1120+ cond.notify_one();
1121+ });
1122+
1123+ auto wait_for_state_update = [&update_received, &mutex, &cond]
1124+ {
1125+ // Wait for an update notification
1126+ std::unique_lock<std::mutex> lock(mutex);
1127+ bool success = cond.wait_for(lock, std::chrono::milliseconds(500), [&update_received] { return update_received; });
1128+ update_received = false;
1129+ return success;
1130+ };
1131+
1132+ // Move testscopeC into the scopes folder
1133+ filesystem::rename(TEST_RUNTIME_PATH "/other_scopes/testscopeC", TEST_RUNTIME_PATH "/scopes/testscopeC");
1134+ std::this_thread::sleep_for(std::chrono::milliseconds(500));
1135+
1136+ auto meta = r->get_metadata("testscopeC");
1137+ auto sp = meta.proxy();
1138+
1139+ // testscopeC should not be running at this point
1140+ EXPECT_FALSE(r->is_scope_running("testscopeC"));
1141+ EXPECT_FALSE(wait_for_state_update());
1142+
1143+ // search would fail if testscopeC can't be executed
1144+ auto receiver = std::make_shared<Receiver>();
1145+ SearchListenerBase::SPtr reply(receiver);
1146+ auto ctrl = sp->search("foo", SearchMetadata("C", "desktop"), reply);
1147+ EXPECT_TRUE(receiver->wait_until_finished());
1148+
1149+ // testscopeC should now be running
1150+ EXPECT_TRUE(wait_for_state_update());
1151+ EXPECT_TRUE(r->is_scope_running("testscopeC"));
1152+
1153+ // check that the scope is still running after 4s
1154+ // (due to "DebugMode = true" and despite "IdleTimeout = 2")
1155+ std::this_thread::sleep_for(std::chrono::seconds{4});
1156+ EXPECT_FALSE(wait_for_state_update());
1157+ EXPECT_TRUE(r->is_scope_running("testscopeC"));
1158+
1159+ // Move testscopeC back into the other_scopes folder
1160+ filesystem::rename(TEST_RUNTIME_PATH "/scopes/testscopeC", TEST_RUNTIME_PATH "/other_scopes/testscopeC");
1161+ std::this_thread::sleep_for(std::chrono::milliseconds(500));
1162+}
1163+
1164 TEST(Registry, list_update_notify_before_click_folder_exists)
1165 {
1166 bool update_received = false;
1167
1168=== modified file 'test/gtest/scopes/Registry/other_scopes/testscopeC/CMakeLists.txt'
1169--- test/gtest/scopes/Registry/other_scopes/testscopeC/CMakeLists.txt 2014-06-04 17:49:34 +0000
1170+++ test/gtest/scopes/Registry/other_scopes/testscopeC/CMakeLists.txt 2014-08-13 04:58:30 +0000
1171@@ -1,1 +1,3 @@
1172+add_library(testscopeC MODULE testscopeC.cpp)
1173+target_link_libraries(testscopeC ${LIBGTEST})
1174 configure_file(testscopeC.ini.in testscopeC.ini)
1175
1176=== added file 'test/gtest/scopes/Registry/other_scopes/testscopeC/testscopeC.cpp'
1177--- test/gtest/scopes/Registry/other_scopes/testscopeC/testscopeC.cpp 1970-01-01 00:00:00 +0000
1178+++ test/gtest/scopes/Registry/other_scopes/testscopeC/testscopeC.cpp 2014-08-13 04:58:30 +0000
1179@@ -0,0 +1,99 @@
1180+/*
1181+ * Copyright (C) 2014 Canonical Ltd
1182+ *
1183+ * This program is free software: you can redistribute it and/or modify
1184+ * it under the terms of the GNU Lesser General Public License version 3 as
1185+ * published by the Free Software Foundation.
1186+ *
1187+ * This program is distributed in the hope that it will be useful,
1188+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1189+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1190+ * GNU Lesser General Public License for more details.
1191+ *
1192+ * You should have received a copy of the GNU Lesser General Public License
1193+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1194+ *
1195+ * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com>
1196+ */
1197+
1198+#include <unity/scopes/ScopeBase.h>
1199+
1200+#define EXPORT __attribute__ ((visibility ("default")))
1201+
1202+using namespace unity::scopes;
1203+
1204+class MyQuery : public SearchQueryBase
1205+{
1206+public:
1207+ MyQuery(CannedQuery const& query, SearchMetadata const& metadata) :
1208+ SearchQueryBase(query, metadata)
1209+ {
1210+ }
1211+
1212+ virtual void cancelled() override
1213+ {
1214+ }
1215+
1216+ virtual void run(SearchReplyProxy const&) override
1217+ {
1218+ }
1219+};
1220+
1221+class MyPreview : public PreviewQueryBase
1222+{
1223+public:
1224+ MyPreview(Result const& result, ActionMetadata const& metadata)
1225+ : PreviewQueryBase(result, metadata)
1226+ {
1227+ }
1228+
1229+ virtual void cancelled() override
1230+ {
1231+ }
1232+
1233+ virtual void run(PreviewReplyProxy const&) override
1234+ {
1235+ }
1236+};
1237+
1238+class MyScope : public ScopeBase
1239+{
1240+public:
1241+ virtual void start(std::string const&) override
1242+ {
1243+ }
1244+
1245+ virtual void stop() override {}
1246+
1247+ virtual SearchQueryBase::UPtr search(CannedQuery const& q, SearchMetadata const& metadata) override
1248+ {
1249+ SearchQueryBase::UPtr query(new MyQuery(q, metadata));
1250+ return query;
1251+ }
1252+
1253+ virtual PreviewQueryBase::UPtr preview(Result const& result, ActionMetadata const& metadata) override
1254+ {
1255+ PreviewQueryBase::UPtr preview(new MyPreview(result, metadata));
1256+ return preview;
1257+ }
1258+};
1259+
1260+extern "C"
1261+{
1262+
1263+ EXPORT
1264+ unity::scopes::ScopeBase*
1265+ // cppcheck-suppress unusedFunction
1266+ UNITY_SCOPE_CREATE_FUNCTION()
1267+ {
1268+ return new MyScope;
1269+ }
1270+
1271+ EXPORT
1272+ void
1273+ // cppcheck-suppress unusedFunction
1274+ UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base)
1275+ {
1276+ delete scope_base;
1277+ }
1278+}
1279
1280=== modified file 'test/gtest/scopes/Registry/other_scopes/testscopeC/testscopeC.ini.in'
1281--- test/gtest/scopes/Registry/other_scopes/testscopeC/testscopeC.ini.in 2014-06-04 17:49:34 +0000
1282+++ test/gtest/scopes/Registry/other_scopes/testscopeC/testscopeC.ini.in 2014-08-13 04:58:30 +0000
1283@@ -6,3 +6,5 @@
1284 Icon = /foo/scope-C.Icon
1285 SearchHint = scope-C.SearchHint
1286 HotKey = scope-C.HotKey
1287+IdleTimeout = 2
1288+DebugMode = true
1289
1290=== modified file 'test/gtest/scopes/ReplyReaper/CMakeLists.txt'
1291--- test/gtest/scopes/ReplyReaper/CMakeLists.txt 2014-07-30 21:34:13 +0000
1292+++ test/gtest/scopes/ReplyReaper/CMakeLists.txt 2014-08-13 04:58:30 +0000
1293@@ -1,6 +1,7 @@
1294 configure_file(Registry.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Registry.ini)
1295 configure_file(Runtime.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini)
1296 configure_file(Zmq.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Zmq.ini)
1297+configure_file(DebugScope.ini.in ${CMAKE_CURRENT_BINARY_DIR}/DebugScope.ini)
1298
1299 add_definitions(-DTEST_DIR="${CMAKE_CURRENT_BINARY_DIR}")
1300
1301
1302=== added file 'test/gtest/scopes/ReplyReaper/DebugScope.ini.in'
1303--- test/gtest/scopes/ReplyReaper/DebugScope.ini.in 1970-01-01 00:00:00 +0000
1304+++ test/gtest/scopes/ReplyReaper/DebugScope.ini.in 2014-08-13 04:58:30 +0000
1305@@ -0,0 +1,5 @@
1306+[ScopeConfig]
1307+DisplayName = DebugScope
1308+Description = Debug Scope
1309+Author = Canonical
1310+DebugMode = true
1311
1312=== modified file 'test/gtest/scopes/ReplyReaper/ReplyReaper_test.cpp'
1313--- test/gtest/scopes/ReplyReaper/ReplyReaper_test.cpp 2014-08-06 04:54:06 +0000
1314+++ test/gtest/scopes/ReplyReaper/ReplyReaper_test.cpp 2014-08-13 04:58:30 +0000
1315@@ -106,3 +106,66 @@
1316 no_reply_rt->destroy();
1317 scope_t.join();
1318 }
1319+
1320+class NoReapReceiver : public SearchListenerBase
1321+{
1322+public:
1323+ NoReapReceiver()
1324+ : query_complete_(false)
1325+ {
1326+ }
1327+
1328+ virtual void push(CategorisedResult /* result */) override
1329+ {
1330+ }
1331+
1332+ virtual void finished(CompletionDetails const& details) override
1333+ {
1334+ // Check that finished() was called by the reaper.
1335+ EXPECT_EQ(CompletionDetails::OK, details.status());
1336+ EXPECT_EQ("", details.message());
1337+ lock_guard<mutex> lock(mutex_);
1338+ query_complete_ = true;
1339+ cond_.notify_all();
1340+ }
1341+
1342+ void wait_until_finished()
1343+ {
1344+ unique_lock<mutex> lock(mutex_);
1345+ cond_.wait(lock, [this] { return this->query_complete_; });
1346+ }
1347+
1348+private:
1349+ bool query_complete_;
1350+ mutex mutex_;
1351+ condition_variable cond_;
1352+};
1353+
1354+void scope_thread_debug_mode(Runtime::SPtr const& rt, string const& runtime_ini_file)
1355+{
1356+ NoReplyScope scope;
1357+ rt->run_scope(&scope, runtime_ini_file, TEST_DIR "/DebugScope.ini");
1358+}
1359+
1360+TEST(ReplyReaper, no_reap_in_debug_mode)
1361+{
1362+ auto reg_rt = run_test_registry();
1363+
1364+ Runtime::SPtr no_reply_rt = move(Runtime::create_scope_runtime("NoReplyScope", TEST_DIR "/Runtime.ini"));
1365+ std::thread scope_t(scope_thread_debug_mode, no_reply_rt, TEST_DIR "/Runtime.ini");
1366+
1367+ // Run a query in the scope. The query will do nothing for 3 seconds,
1368+ // but the reaper will reap after at most 2 seconds.
1369+ auto rt = internal::RuntimeImpl::create("", TEST_DIR "/Runtime.ini");
1370+ auto mw = rt->factory()->create("NoReplyScope", "Zmq", TEST_DIR "/Zmq.ini");
1371+ mw->start();
1372+ auto proxy = mw->create_scope_proxy("NoReplyScope");
1373+ auto scope = internal::ScopeImpl::create(proxy, rt.get(), "NoReplyScope");
1374+
1375+ auto receiver = make_shared<NoReapReceiver>();
1376+ scope->search("test", SearchMetadata("en", "phone"), receiver);
1377+ receiver->wait_until_finished();
1378+
1379+ no_reply_rt->destroy();
1380+ scope_t.join();
1381+}
1382
1383=== modified file 'test/gtest/scopes/internal/ScopeConfig/ScopeConfig_test.cpp'
1384--- test/gtest/scopes/internal/ScopeConfig/ScopeConfig_test.cpp 2014-08-08 14:06:59 +0000
1385+++ test/gtest/scopes/internal/ScopeConfig/ScopeConfig_test.cpp 2014-08-13 04:58:30 +0000
1386@@ -49,6 +49,7 @@
1387 EXPECT_EQ(300, cfg.idle_timeout());
1388 EXPECT_EQ(ScopeMetadata::ResultsTtlType::Large, cfg.results_ttl_type());
1389 EXPECT_TRUE(cfg.location_data_needed());
1390+ EXPECT_TRUE(cfg.debug_mode());
1391
1392 auto attrs = cfg.appearance_attributes();
1393 EXPECT_EQ(5, attrs.size());
1394@@ -78,6 +79,7 @@
1395 EXPECT_EQ(DFLT_SCOPE_IDLE_TIMEOUT, cfg.idle_timeout());
1396 EXPECT_EQ(ScopeMetadata::ResultsTtlType::None, cfg.results_ttl_type());
1397 EXPECT_FALSE(cfg.location_data_needed());
1398+ EXPECT_FALSE(cfg.debug_mode());
1399
1400 EXPECT_EQ(0, cfg.appearance_attributes().size());
1401
1402
1403=== modified file 'test/gtest/scopes/internal/ScopeConfig/complete_config.ini.in'
1404--- test/gtest/scopes/internal/ScopeConfig/complete_config.ini.in 2014-07-18 04:02:58 +0000
1405+++ test/gtest/scopes/internal/ScopeConfig/complete_config.ini.in 2014-08-13 04:58:30 +0000
1406@@ -16,6 +16,7 @@
1407 ResultsTtlType = large
1408 LocationDataNeeded = true
1409 ConfinementType = unconfined
1410+DebugMode = true
1411
1412 [Appearance]
1413 arbitrary_key = true
1414
1415=== modified file 'test/gtest/scopes/internal/zmq_middleware/ZmqMiddleware/ZmqMiddleware_test.cpp'
1416--- test/gtest/scopes/internal/zmq_middleware/ZmqMiddleware/ZmqMiddleware_test.cpp 2014-07-24 10:43:37 +0000
1417+++ test/gtest/scopes/internal/zmq_middleware/ZmqMiddleware/ZmqMiddleware_test.cpp 2014-08-13 04:58:30 +0000
1418@@ -452,6 +452,11 @@
1419 {
1420 return nullptr;
1421 }
1422+
1423+ virtual bool debug_mode() const override
1424+ {
1425+ return false;
1426+ }
1427 };
1428
1429 // Make sure that multiple threads calling wait_for_shutdown() complete

Subscribers

People subscribed via source and target branches

to all changes: