Merge lp:~marcustomlinson/unity-scopes-api/child_scopes_ordered into lp:unity-scopes-api

Proposed by Marcus Tomlinson
Status: Merged
Approved by: Paweł Stołowski
Approved revision: 613
Merged at revision: 290
Proposed branch: lp:~marcustomlinson/unity-scopes-api/child_scopes_ordered
Merge into: lp:unity-scopes-api
Prerequisite: lp:~marcustomlinson/unity-scopes-api/lp-1410125
Diff against target: 1756 lines (+1184/-27)
42 files modified
CMakeLists.txt (+1/-1)
RELEASE_NOTES.md (+7/-0)
debian/changelog (+9/-0)
debian/libunity-scopes3.symbols (+10/-1)
include/unity/scopes/AbstractScopeBase.h (+9/-0)
include/unity/scopes/ChildScope.h (+50/-0)
include/unity/scopes/Runtime.h (+0/-19)
include/unity/scopes/Scope.h (+16/-0)
include/unity/scopes/ScopeBase.h (+27/-0)
include/unity/scopes/internal/ChildScopesRepository.h (+68/-0)
include/unity/scopes/internal/MWScope.h (+4/-1)
include/unity/scopes/internal/ScopeBaseImpl.h (+11/-0)
include/unity/scopes/internal/ScopeImpl.h (+3/-0)
include/unity/scopes/internal/ScopeObject.h (+3/-0)
include/unity/scopes/internal/ScopeObjectBase.h (+4/-0)
include/unity/scopes/internal/smartscopes/SSScopeObject.h (+3/-0)
include/unity/scopes/internal/zmq_middleware/ScopeI.h (+6/-0)
include/unity/scopes/internal/zmq_middleware/ZmqScope.h (+3/-0)
include/unity/scopes/testing/MockScope.h (+4/-0)
src/scopes/AbstractScopeBase.cpp (+37/-0)
src/scopes/CMakeLists.txt (+1/-0)
src/scopes/Runtime.cpp (+0/-5)
src/scopes/ScopeBase.cpp (+10/-0)
src/scopes/internal/CMakeLists.txt (+1/-0)
src/scopes/internal/ChildScopesRepository.cpp (+243/-0)
src/scopes/internal/RuntimeImpl.cpp (+7/-0)
src/scopes/internal/ScopeBaseImpl.cpp (+50/-0)
src/scopes/internal/ScopeImpl.cpp (+10/-0)
src/scopes/internal/ScopeObject.cpp (+10/-0)
src/scopes/internal/smartscopes/SSScopeObject.cpp (+10/-0)
src/scopes/internal/zmq_middleware/ScopeI.cpp (+49/-0)
src/scopes/internal/zmq_middleware/ZmqScope.cpp (+50/-0)
src/scopes/internal/zmq_middleware/capnproto/Scope.capnp (+21/-0)
test/gtest/scopes/CMakeLists.txt (+1/-0)
test/gtest/scopes/ChildScopes/CMakeLists.txt (+10/-0)
test/gtest/scopes/ChildScopes/ChildScopes_test.cpp (+325/-0)
test/gtest/scopes/ChildScopes/Registry.ini.in (+6/-0)
test/gtest/scopes/ChildScopes/Runtime.ini.in (+6/-0)
test/gtest/scopes/ChildScopes/TestScope.h (+83/-0)
test/gtest/scopes/ChildScopes/Zmq.ini.in (+2/-0)
test/gtest/scopes/internal/RegistryObject/RegistryObject_test.cpp (+4/-0)
test/gtest/scopes/internal/zmq_middleware/ZmqMiddleware/ZmqMiddleware_test.cpp (+10/-0)
To merge this branch: bzr merge lp:~marcustomlinson/unity-scopes-api/child_scopes_ordered
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Michi Henning (community) Approve
Review via email: mp+246533@code.launchpad.net

Commit message

* Introduced child_scopes() methods for aggregators to return their list of child scopes at runtime.
* Added missing virtual destructor to AbstractScopeBase. (LP: #1360266)
* Removed deprecated Runtime::run_scope() method.

To post a comment you must log in.
Revision history for this message
Michi Henning (michihenning) wrote :

Looks right to me!

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michi Henning (michihenning) wrote :

Let's give it a shot.

review: Approve
Revision history for this message
Michi Henning (michihenning) wrote :

Cool!

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
613. By Marcus Tomlinson

Merged trunk

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2015-01-21 12:46:11 +0000
3+++ CMakeLists.txt 2015-01-26 17:27:30 +0000
4@@ -227,7 +227,7 @@
5 # API version
6 set(UNITY_SCOPES_MAJOR 0)
7 set(UNITY_SCOPES_MINOR 6)
8-set(UNITY_SCOPES_MICRO 11)
9+set(UNITY_SCOPES_MICRO 12)
10 set(UNITY_SCOPES_SOVERSION 3)
11
12 # Version for testing, with all symbols visible
13
14=== modified file 'RELEASE_NOTES.md'
15--- RELEASE_NOTES.md 2015-01-07 23:03:50 +0000
16+++ RELEASE_NOTES.md 2015-01-26 17:27:30 +0000
17@@ -1,6 +1,13 @@
18 Release notes
19 =============
20
21+Changes in version 0.6.12
22+=========================
23+ - Introduced child_scopes() methods for aggregators to return their
24+ list of child scopes at runtime.
25+ - Added missing virtual destructor to AbstractScopeBase. (LP: #1360266)
26+ - Removed deprecated Runtime::run_scope() method.
27+
28 Changes in version 0.6.11
29 =========================
30 - The JSON for a CategoryRenderer now supports a "fallback" field in the
31
32=== modified file 'debian/changelog'
33--- debian/changelog 2015-01-26 09:01:10 +0000
34+++ debian/changelog 2015-01-26 17:27:30 +0000
35@@ -1,3 +1,12 @@
36+unity-scopes-api (0.6.12-0ubuntu1) UNRELEASED; urgency=medium
37+
38+ * Introduced child_scopes() methods for aggregators to return their
39+ list of child scopes at runtime.
40+ * Added missing virtual destructor to AbstractScopeBase. (LP: #1360266)
41+ * Removed deprecated Runtime::run_scope() method.
42+
43+ -- Marcus Tomlinson <marcus.tomlinson@canonical.com> Tue, 20 Jan 2015 07:52:23 +0200
44+
45 unity-scopes-api (0.6.11+15.04.20150126-0ubuntu1) vivid; urgency=low
46
47 [ Marcus Tomlinson ]
48
49=== modified file 'debian/libunity-scopes3.symbols'
50--- debian/libunity-scopes3.symbols 2015-01-21 12:46:34 +0000
51+++ debian/libunity-scopes3.symbols 2015-01-26 17:27:30 +0000
52@@ -93,6 +93,8 @@
53 (c++)"typeinfo name for unity::scopes::TimeoutException@Base" 0.4.0+14.04.20140312.1
54 (c++)"typeinfo name for unity::scopes::utility::BufferedResultForwarder@Base" 0.6.10+15.04.20141210.2
55 (c++)"typeinfo name for unity::scopes::VariantBuilder@Base" 0.4.0+14.04.20140312.1
56+ (c++)"unity::scopes::AbstractScopeBase::~AbstractScopeBase()@Base" 0replaceme
57+ (c++)"unity::scopes::AbstractScopeBase::AbstractScopeBase()@Base" 0replaceme
58 (c++)"unity::scopes::ActionMetadata::~ActionMetadata()@Base" 0.4.0+14.04.20140312.1
59 (c++)"unity::scopes::ActionMetadata::ActionMetadata(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1
60 (c++)"unity::scopes::ActionMetadata::ActionMetadata(unity::scopes::ActionMetadata&&)@Base" 0.4.0+14.04.20140312.1
61@@ -471,6 +473,7 @@
62 (c++)"unity::scopes::internal::ScopeConfig::search_hint() const@Base" 0.4.0+14.04.20140312.1
63 (c++)"unity::scopes::internal::ScopeConfig::version() const@Base" 0.6.9+15.04.20141129
64 (c++)"unity::scopes::internal::ScopeImpl::activate(unity::scopes::Result const&, unity::scopes::ActionMetadata const&, std::shared_ptr<unity::scopes::ActivationListenerBase> const&)@Base" 0.4.0+14.04.20140312.1
65+ (c++)"unity::scopes::internal::ScopeImpl::child_scopes_ordered()@Base" 0replaceme
66 (c++)"unity::scopes::internal::ScopeImpl::create(std::shared_ptr<unity::scopes::internal::MWScope> const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.6.11+15.04.20150119
67 (c++)"unity::scopes::internal::ScopeImpl::fwd()@Base" 0.4.3+14.10.20140428
68 (c++)"unity::scopes::internal::ScopeImpl::perform_action(unity::scopes::Result const&, unity::scopes::ActionMetadata const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<unity::scopes::ActivationListenerBase> const&)@Base" 0.4.0+14.04.20140312.1
69@@ -481,6 +484,7 @@
70 (c++)"unity::scopes::internal::ScopeImpl::search(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unity::scopes::FilterState const&, unity::scopes::SearchMetadata const&, std::shared_ptr<unity::scopes::SearchListenerBase> const&)@Base" 0.4.0+14.04.20140312.1
71 (c++)"unity::scopes::internal::ScopeImpl::search(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unity::scopes::SearchMetadata const&, std::shared_ptr<unity::scopes::SearchListenerBase> const&)@Base" 0.4.0+14.04.20140312.1
72 (c++)"unity::scopes::internal::ScopeImpl::search(unity::scopes::CannedQuery const&, unity::scopes::SearchMetadata const&, std::shared_ptr<unity::scopes::SearchListenerBase> const&)@Base" 0.4.0+14.04.20140312.1
73+ (c++)"unity::scopes::internal::ScopeImpl::set_child_scopes_ordered(std::list<unity::scopes::ChildScope, std::allocator<unity::scopes::ChildScope> > const&)@Base" 0replaceme
74 (c++)"unity::scopes::internal::ScopeLoader::libpath() const@Base" 0.4.0+14.04.20140312.1
75 (c++)"unity::scopes::internal::ScopeLoader::load(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.6.0+14.10.20140804.1
76 (c++)"unity::scopes::internal::ScopeLoader::scope_base() const@Base" 0.4.0+14.04.20140312.1
77@@ -536,6 +540,7 @@
78 (c++)"unity::scopes::internal::ScopeMetadataImpl::set_version(int)@Base" 0.6.9+15.04.20141129
79 (c++)"unity::scopes::internal::ScopeMetadataImpl::version() const@Base" 0.6.9+15.04.20141129
80 (c++)"unity::scopes::internal::ScopeObject::activate(unity::scopes::Result const&, unity::scopes::ActionMetadata const&, std::shared_ptr<unity::scopes::internal::MWReply> const&, unity::scopes::internal::InvokeInfo const&)@Base" 0.4.0+14.04.20140312.1
81+ (c++)"unity::scopes::internal::ScopeObject::child_scopes_ordered() const@Base" 0replaceme
82 (c++)"unity::scopes::internal::ScopeObject::debug_mode() const@Base" 0.6.2+rtm+rtm+rtm+14.09.20140818
83 (c++)"unity::scopes::internal::ScopeObject::perform_action(unity::scopes::Result const&, unity::scopes::ActionMetadata const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<unity::scopes::internal::MWReply> const&, unity::scopes::internal::InvokeInfo const&)@Base" 0.4.0+14.04.20140312.1
84 (c++)"unity::scopes::internal::ScopeObject::preview(unity::scopes::Result const&, unity::scopes::ActionMetadata const&, std::shared_ptr<unity::scopes::internal::MWReply> const&, unity::scopes::internal::InvokeInfo const&)@Base" 0.4.0+14.04.20140312.1
85@@ -543,6 +548,7 @@
86 (c++)"unity::scopes::internal::ScopeObject::~ScopeObject()@Base" 0.4.0+14.04.20140312.1
87 (c++)"unity::scopes::internal::ScopeObject::ScopeObject(unity::scopes::ScopeBase*, bool)@Base" 0.6.11+15.04.20150119
88 (c++)"unity::scopes::internal::ScopeObject::search(unity::scopes::CannedQuery const&, unity::scopes::SearchMetadata const&, std::shared_ptr<unity::scopes::internal::MWReply> const&, unity::scopes::internal::InvokeInfo const&)@Base" 0.4.0+14.04.20140312.1
89+ (c++)"unity::scopes::internal::ScopeObject::set_child_scopes_ordered(std::list<unity::scopes::ChildScope, std::allocator<unity::scopes::ChildScope> > const&)@Base" 0replaceme
90 (c++)"unity::scopes::internal::smartscopes::SSConfig::http_reply_timeout() const@Base" 0.4.4+14.10.20140508
91 (c++)"unity::scopes::internal::smartscopes::SSConfig::reg_refresh_fail_timeout() const@Base" 0.4.4+14.10.20140508
92 (c++)"unity::scopes::internal::smartscopes::SSConfig::reg_refresh_rate() const@Base" 0.4.4+14.10.20140508
93@@ -564,11 +570,13 @@
94 (c++)"unity::scopes::internal::smartscopes::SSRegistryObject::SSRegistryObject(std::shared_ptr<unity::scopes::internal::MiddlewareBase>, unity::scopes::internal::smartscopes::SSConfig const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool)@Base" 0.4.4+14.10.20140508
95 (c++)"unity::scopes::internal::smartscopes::SSRegistryObject::SSSettingsDef::~SSSettingsDef()@Base" 0.5.2+14.10.20140709.2
96 (c++)"unity::scopes::internal::smartscopes::SSScopeObject::activate(unity::scopes::Result const&, unity::scopes::ActionMetadata const&, std::shared_ptr<unity::scopes::internal::MWReply> const&, unity::scopes::internal::InvokeInfo const&)@Base" 0.4.0+14.04.20140312.1
97+ (c++)"unity::scopes::internal::smartscopes::SSScopeObject::child_scopes_ordered() const@Base" 0replaceme
98 (c++)"unity::scopes::internal::smartscopes::SSScopeObject::debug_mode() const@Base" 0.6.2+rtm+rtm+rtm+14.09.20140818
99 (c++)"unity::scopes::internal::smartscopes::SSScopeObject::perform_action(unity::scopes::Result const&, unity::scopes::ActionMetadata const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<unity::scopes::internal::MWReply> const&, unity::scopes::internal::InvokeInfo const&)@Base" 0.4.0+14.04.20140312.1
100 (c++)"unity::scopes::internal::smartscopes::SSScopeObject::preview(unity::scopes::Result const&, unity::scopes::ActionMetadata const&, std::shared_ptr<unity::scopes::internal::MWReply> const&, unity::scopes::internal::InvokeInfo const&)@Base" 0.4.0+14.04.20140312.1
101 (c++)"unity::scopes::internal::smartscopes::SSScopeObject::query(unity::scopes::internal::InvokeInfo const&, std::shared_ptr<unity::scopes::internal::MWReply> const&, std::function<std::shared_ptr<unity::scopes::QueryBase> ()> const&, std::function<void (std::shared_ptr<unity::scopes::QueryBase>)> const&)@Base" 0.4.0+14.04.20140312.1
102 (c++)"unity::scopes::internal::smartscopes::SSScopeObject::search(unity::scopes::CannedQuery const&, unity::scopes::SearchMetadata const&, std::shared_ptr<unity::scopes::internal::MWReply> const&, unity::scopes::internal::InvokeInfo const&)@Base" 0.4.0+14.04.20140312.1
103+ (c++)"unity::scopes::internal::smartscopes::SSScopeObject::set_child_scopes_ordered(std::list<unity::scopes::ChildScope, std::allocator<unity::scopes::ChildScope> > const&)@Base" 0replaceme
104 (c++)"unity::scopes::internal::smartscopes::SSScopeObject::~SSScopeObject()@Base" 0.4.0+14.04.20140312.1
105 (c++)"unity::scopes::internal::smartscopes::SSScopeObject::SSScopeObject(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<unity::scopes::internal::MiddlewareBase>, std::shared_ptr<unity::scopes::internal::smartscopes::SSRegistryObject>)@Base" 0.4.0+14.04.20140312.1
106 (c++)"unity::scopes::internal::StateReceiverObject::push_state(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unity::scopes::internal::StateReceiverObject::State const&)@Base" 0.4.2+14.04.20140404.2
107@@ -762,13 +770,14 @@
108 (c++)"unity::scopes::Runtime::proxy_to_string(std::shared_ptr<unity::scopes::Object> const&) const@Base" 0.4.0+14.04.20140312.1
109 (c++)"unity::scopes::Runtime::registry() const@Base" 0.4.0+14.04.20140312.1
110 (c++)"unity::scopes::Runtime::run_scope(unity::scopes::ScopeBase*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.4+14.10.20140508
111- (c++)"unity::scopes::Runtime::run_scope(unity::scopes::ScopeBase*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.4+14.10.20140508
112 (c++)"unity::scopes::Runtime::~Runtime()@Base" 0.4.0+14.04.20140312.1
113 (c++)"unity::scopes::Runtime::Runtime(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1
114 (c++)"unity::scopes::Runtime::string_to_proxy(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const@Base" 0.4.0+14.04.20140312.1
115 (c++)"unity::scopes::ScopeBase::activate(unity::scopes::Result const&, unity::scopes::ActionMetadata const&)@Base" 0.4.0+14.04.20140312.1
116 (c++)"unity::scopes::ScopeBase::app_directory() const@Base" 0.6.9+15.04.20141129
117 (c++)"unity::scopes::ScopeBase::cache_directory() const@Base" 0.6.0+14.10.20140804.1
118+ (c++)"unity::scopes::ScopeBase::child_scopes() const@Base" 0replaceme
119+ (c++)"unity::scopes::ScopeBase::child_scopes_ordered() const@Base" 0replaceme
120 (c++)"unity::scopes::ScopeBase::perform_action(unity::scopes::Result const&, unity::scopes::ActionMetadata const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1
121 (c++)"unity::scopes::ScopeBase::registry() const@Base" 0.6.0+14.10.20140804.1
122 (c++)"unity::scopes::ScopeBase::run()@Base" 0.4.0+14.04.20140312.1
123
124=== modified file 'include/unity/scopes/AbstractScopeBase.h'
125--- include/unity/scopes/AbstractScopeBase.h 2015-01-15 05:23:34 +0000
126+++ include/unity/scopes/AbstractScopeBase.h 2015-01-26 17:27:30 +0000
127@@ -19,6 +19,7 @@
128 #pragma once
129
130 #include <unity/scopes/ActivationQueryBase.h>
131+#include <unity/scopes/ChildScope.h>
132 #include <unity/scopes/PreviewQueryBase.h>
133 #include <unity/scopes/Registry.h>
134 #include <unity/scopes/SearchQueryBase.h>
135@@ -55,6 +56,14 @@
136 virtual std::string tmp_directory() const = 0;
137 virtual unity::scopes::RegistryProxy registry() const = 0;
138 virtual VariantMap settings() const = 0;
139+
140+ virtual ~AbstractScopeBase();
141+
142+ virtual ChildScopeList child_scopes() const = 0;
143+ virtual ChildScopeList child_scopes_ordered() const = 0;
144+
145+protected:
146+ AbstractScopeBase();
147 /// @endcond
148 };
149
150
151=== added file 'include/unity/scopes/ChildScope.h'
152--- include/unity/scopes/ChildScope.h 1970-01-01 00:00:00 +0000
153+++ include/unity/scopes/ChildScope.h 2015-01-26 17:27:30 +0000
154@@ -0,0 +1,50 @@
155+/*
156+ * Copyright (C) 2014 Canonical Ltd
157+ *
158+ * This program is free software: you can redistribute it and/or modify
159+ * it under the terms of the GNU Lesser General Public License version 3 as
160+ * published by the Free Software Foundation.
161+ *
162+ * This program is distributed in the hope that it will be useful,
163+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
164+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
165+ * GNU Lesser General Public License for more details.
166+ *
167+ * You should have received a copy of the GNU Lesser General Public License
168+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
169+ *
170+ * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com>
171+ */
172+
173+#pragma once
174+
175+#include <list>
176+#include <string>
177+
178+namespace unity
179+{
180+
181+namespace scopes
182+{
183+
184+struct ChildScope;
185+
186+/**
187+ \brief A list of child scopes.
188+*/
189+
190+typedef std::list<ChildScope> ChildScopeList;
191+
192+/**
193+ \brief A container for details about an aggregator's child scope.
194+*/
195+
196+struct ChildScope
197+{
198+ std::string id; ///< The scope id of this child scope.
199+ bool enabled; ///< Holds whether this child scope is aggregated.
200+};
201+
202+} // namespace scopes
203+
204+} // namespace unity
205
206=== modified file 'include/unity/scopes/Runtime.h'
207--- include/unity/scopes/Runtime.h 2014-12-04 04:33:50 +0000
208+++ include/unity/scopes/Runtime.h 2015-01-26 17:27:30 +0000
209@@ -114,25 +114,6 @@
210 This method is intended to run a scope that can not be loaded via the scope runner, such as
211 those written in languages that cannot be dynamically loaded.
212
213- \note This method is deprecated. Use
214- `void run_scope(ScopeBase *const scope_base, std::string const& scope_ini_file)` instead.
215-
216- \param scope_base The scope implementation
217- \param runtime_ini_file This parameter is ignored.
218- \param scope_ini_file The full path of scope configuration file
219- */
220- /// @cond
221- // TODO: next ABI incompatible release, strip out this method.
222- __attribute__ ((deprecated))
223- /// @endcond
224- void run_scope(ScopeBase *const scope_base, std::string const& runtime_ini_file, std::string const& scope_ini_file);
225-
226- /**
227- \brief Run a scope without going through the scope runner.
228-
229- This method is intended to run a scope that can not be loaded via the scope runner, such as
230- those written in languages that cannot be dynamically loaded.
231-
232 \param scope_base The scope implementation
233 \param scope_ini_file The full path of scope configuration file
234 */
235
236=== modified file 'include/unity/scopes/Scope.h'
237--- include/unity/scopes/Scope.h 2014-11-03 05:31:30 +0000
238+++ include/unity/scopes/Scope.h 2015-01-26 17:27:30 +0000
239@@ -19,6 +19,7 @@
240 #pragma once
241
242 #include <unity/scopes/ActivationListenerBase.h>
243+#include <unity/scopes/ChildScope.h>
244 #include <unity/scopes/Object.h>
245 #include <unity/scopes/PreviewListenerBase.h>
246 #include <unity/scopes/QueryCtrlProxyFwd.h>
247@@ -140,6 +141,21 @@
248 */
249 virtual ~Scope();
250
251+ /**
252+ \brief Returns a list of child scopes aggregated by this scope in user-defined order.
253+ \return The list of child scopes aggregated by this scope in user-defined order.
254+ */
255+ virtual ChildScopeList child_scopes_ordered() = 0;
256+
257+ /**
258+ \brief Sets the ordered list of child scopes aggregated by this scope.
259+ \note The only time this call will return false is if the scope cannot write to its config directory.
260+ This should not happen in real-world usage, but if it does, check the log for more detail.
261+ \param child_scopes_ordered The ordered list of child scopes aggregated by this scope.
262+ \return True if the list was successfully set.
263+ */
264+ virtual bool set_child_scopes_ordered(ChildScopeList const& child_scopes_ordered) = 0;
265+
266 protected:
267 /// @cond
268 Scope();
269
270=== modified file 'include/unity/scopes/ScopeBase.h'
271--- include/unity/scopes/ScopeBase.h 2015-01-15 05:23:34 +0000
272+++ include/unity/scopes/ScopeBase.h 2015-01-26 17:27:30 +0000
273@@ -330,6 +330,33 @@
274 */
275 virtual VariantMap settings() const final;
276
277+ /**
278+ \brief Returns a list of child scopes aggregated by this scope.
279+
280+ The scope author must ensure that the list returned by this method contains all scopes
281+ that this aggregator may collect results from. This list may contain scopes that are
282+ not currently installed and are optional for proper functioning of this scope.
283+
284+ The default behaviour of this method is to simply return all available scopes on the
285+ system. This translates to: "Any scope may potentially be aggregated by this scope".
286+
287+ \note Only aggregator scopes should implement this method.
288+
289+ \return The list of child scopes aggregated by this scope.
290+ */
291+ virtual ChildScopeList child_scopes() const;
292+
293+ /**
294+ \brief Returns a list of child scopes aggregated by this scope in user-defined order.
295+
296+ An aggregator scope must push its results in the order specified by this method's
297+ return value. The aggregator should also respect the "enabled" states of each child
298+ scope, returning results only for the child scopes that are enabled.
299+
300+ \return The list of child scopes aggregated by this scope in user-defined order.
301+ */
302+ virtual ChildScopeList child_scopes_ordered() const final;
303+
304 protected:
305 /// @cond
306 ScopeBase();
307
308=== added file 'include/unity/scopes/internal/ChildScopesRepository.h'
309--- include/unity/scopes/internal/ChildScopesRepository.h 1970-01-01 00:00:00 +0000
310+++ include/unity/scopes/internal/ChildScopesRepository.h 2015-01-26 17:27:30 +0000
311@@ -0,0 +1,68 @@
312+/*
313+ * Copyright (C) 2014 Canonical Ltd
314+ *
315+ * This program is free software: you can redistribute it and/or modify
316+ * it under the terms of the GNU Lesser General Public License version 3 as
317+ * published by the Free Software Foundation.
318+ *
319+ * This program is distributed in the hope that it will be useful,
320+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
321+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
322+ * GNU Lesser General Public License for more details.
323+ *
324+ * You should have received a copy of the GNU Lesser General Public License
325+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
326+ *
327+ * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com>
328+ */
329+
330+#pragma once
331+
332+#include <unity/scopes/ChildScope.h>
333+#include <unity/scopes/internal/Logger.h>
334+#include <unity/util/NonCopyable.h>
335+
336+#include <list>
337+#include <mutex>
338+#include <string>
339+
340+namespace unity
341+{
342+
343+namespace scopes
344+{
345+
346+namespace internal
347+{
348+
349+class ChildScopesRepository
350+{
351+public:
352+ NONCOPYABLE(ChildScopesRepository);
353+
354+ ChildScopesRepository(std::string const& repo_file_path,
355+ boost::log::sources::severity_channel_logger_mt<>& logger);
356+
357+ ChildScopeList child_scopes_ordered(ChildScopeList const& child_scopes_unordered);
358+ bool set_child_scopes_ordered(ChildScopeList const& child_scopes_ordered);
359+
360+private:
361+ bool write_repo(ChildScopeList const& child_scopes_list);
362+ ChildScopeList read_repo();
363+
364+ std::string list_to_json(ChildScopeList const& child_scopes_list);
365+ ChildScopeList json_to_list(std::string const& child_scopes_json);
366+
367+ std::string const repo_file_path_;
368+ boost::log::sources::severity_channel_logger_mt<>& logger_;
369+
370+ std::mutex mutex_;
371+ ChildScopeList cached_repo_;
372+ bool have_latest_cache_;
373+};
374+
375+} // namespace internal
376+
377+} // namespace scopes
378+
379+} // namespace unity
380
381=== modified file 'include/unity/scopes/internal/MWScope.h'
382--- include/unity/scopes/internal/MWScope.h 2014-11-03 05:31:30 +0000
383+++ include/unity/scopes/internal/MWScope.h 2015-01-26 17:27:30 +0000
384@@ -21,8 +21,9 @@
385 #include <unity/scopes/internal/MWObjectProxy.h>
386 #include <unity/scopes/internal/MWReplyProxyFwd.h>
387 #include <unity/scopes/internal/MWScopeProxyFwd.h>
388+#include <unity/scopes/CannedQuery.h>
389+#include <unity/scopes/ChildScope.h>
390 #include <unity/scopes/QueryCtrlProxyFwd.h>
391-#include <unity/scopes/CannedQuery.h>
392 #include <unity/scopes/Variant.h>
393
394 namespace unity
395@@ -43,6 +44,8 @@
396 virtual QueryCtrlProxy activate(VariantMap const& result, VariantMap const& hints, MWReplyProxy const& reply) = 0;
397 virtual QueryCtrlProxy perform_action(VariantMap const& result, VariantMap const& hints, std::string const& widget_id, std::string const& action_id, MWReplyProxy const& reply) = 0;
398 virtual QueryCtrlProxy preview(VariantMap const& result, VariantMap const& hints, MWReplyProxy const& reply) = 0;
399+ virtual ChildScopeList child_scopes_ordered() = 0;
400+ virtual bool set_child_scopes_ordered(ChildScopeList const& child_scopes_ordered) = 0;
401 virtual bool debug_mode() = 0;
402
403 protected:
404
405=== modified file 'include/unity/scopes/internal/ScopeBaseImpl.h'
406--- include/unity/scopes/internal/ScopeBaseImpl.h 2014-11-13 02:31:13 +0000
407+++ include/unity/scopes/internal/ScopeBaseImpl.h 2015-01-26 17:27:30 +0000
408@@ -18,6 +18,7 @@
409
410 #pragma once
411
412+#include <unity/scopes/ChildScope.h>
413 #include <unity/scopes/RegistryProxyFwd.h>
414 #include <unity/scopes/Variant.h>
415
416@@ -33,6 +34,7 @@
417 namespace internal
418 {
419
420+class ChildScopesRepository;
421 class SettingsDB;
422
423 class ScopeBaseImpl final
424@@ -60,6 +62,12 @@
425 void set_settings_db(std::shared_ptr<unity::scopes::internal::SettingsDB> const& db);
426 unity::scopes::VariantMap settings() const;
427
428+ void set_child_scopes_repo(std::shared_ptr<ChildScopesRepository> const& child_scopes_repo);
429+
430+ ChildScopeList child_scopes() const;
431+ ChildScopeList child_scopes_ordered(ChildScopeList const& unordered_child_scopes) const;
432+ bool set_child_scopes_ordered(ChildScopeList const& child_scopes_ordered);
433+
434 private:
435 std::string scope_directory_;
436 bool scope_dir_initialized_;
437@@ -79,6 +87,9 @@
438 std::shared_ptr<unity::scopes::internal::SettingsDB> db_;
439 bool settings_db_initialized_;
440
441+ std::shared_ptr<ChildScopesRepository> child_scopes_repo_;
442+ bool child_scopes_repo_initialized_;
443+
444 mutable std::mutex mutex_;
445 };
446
447
448=== modified file 'include/unity/scopes/internal/ScopeImpl.h'
449--- include/unity/scopes/internal/ScopeImpl.h 2015-01-09 03:16:51 +0000
450+++ include/unity/scopes/internal/ScopeImpl.h 2015-01-26 17:27:30 +0000
451@@ -81,6 +81,9 @@
452 ActionMetadata const& hints,
453 PreviewListenerBase::SPtr const& reply) override;
454
455+ virtual ChildScopeList child_scopes_ordered() override;
456+ virtual bool set_child_scopes_ordered(ChildScopeList const& child_scopes_ordered) override;
457+
458 static ScopeProxy create(MWScopeProxy const& mw_proxy, std::string const& scope_id);
459
460 private:
461
462=== modified file 'include/unity/scopes/internal/ScopeObject.h'
463--- include/unity/scopes/internal/ScopeObject.h 2015-01-09 03:47:02 +0000
464+++ include/unity/scopes/internal/ScopeObject.h 2015-01-26 17:27:30 +0000
465@@ -76,6 +76,9 @@
466 MWReplyProxy const& reply,
467 InvokeInfo const& info) override;
468
469+ virtual ChildScopeList child_scopes_ordered() const override;
470+ virtual bool set_child_scopes_ordered(ChildScopeList const& child_scopes_ordered) override;
471+
472 virtual bool debug_mode() const override;
473
474 private:
475
476=== modified file 'include/unity/scopes/internal/ScopeObjectBase.h'
477--- include/unity/scopes/internal/ScopeObjectBase.h 2015-01-09 00:14:14 +0000
478+++ include/unity/scopes/internal/ScopeObjectBase.h 2015-01-26 17:27:30 +0000
479@@ -21,6 +21,7 @@
480 #include <unity/scopes/internal/AbstractObject.h>
481 #include <unity/scopes/internal/MWQueryCtrlProxyFwd.h>
482 #include <unity/scopes/internal/MWReplyProxyFwd.h>
483+#include <unity/scopes/ChildScope.h>
484 #include <unity/scopes/Result.h>
485 #include <unity/scopes/Variant.h>
486
487@@ -67,6 +68,9 @@
488 MWReplyProxy const& reply,
489 InvokeInfo const& info) = 0;
490
491+ virtual ChildScopeList child_scopes_ordered() const = 0;
492+ virtual bool set_child_scopes_ordered(ChildScopeList const& child_scopes_ordered) = 0;
493+
494 virtual bool debug_mode() const = 0;
495 };
496
497
498=== modified file 'include/unity/scopes/internal/smartscopes/SSScopeObject.h'
499--- include/unity/scopes/internal/smartscopes/SSScopeObject.h 2015-01-20 04:14:26 +0000
500+++ include/unity/scopes/internal/smartscopes/SSScopeObject.h 2015-01-26 17:27:30 +0000
501@@ -73,6 +73,9 @@
502 MWReplyProxy const& reply,
503 InvokeInfo const& info) override;
504
505+ ChildScopeList child_scopes_ordered() const override;
506+ bool set_child_scopes_ordered(ChildScopeList const& child_scopes_ordered) override;
507+
508 bool debug_mode() const override;
509
510 private:
511
512=== modified file 'include/unity/scopes/internal/zmq_middleware/ScopeI.h'
513--- include/unity/scopes/internal/zmq_middleware/ScopeI.h 2014-11-03 05:31:30 +0000
514+++ include/unity/scopes/internal/zmq_middleware/ScopeI.h 2015-01-26 17:27:30 +0000
515@@ -53,6 +53,12 @@
516 virtual void preview_(Current const& current,
517 capnp::AnyPointer::Reader& in_params,
518 capnproto::Response::Builder& r);
519+ virtual void child_scopes_ordered_(Current const& current,
520+ capnp::AnyPointer::Reader& in_params,
521+ capnproto::Response::Builder& r);
522+ virtual void set_child_scopes_ordered_(Current const& current,
523+ capnp::AnyPointer::Reader& in_params,
524+ capnproto::Response::Builder& r);
525 virtual void debug_mode_(Current const& current,
526 capnp::AnyPointer::Reader& in_params,
527 capnproto::Response::Builder& r);
528
529=== modified file 'include/unity/scopes/internal/zmq_middleware/ZmqScope.h'
530--- include/unity/scopes/internal/zmq_middleware/ZmqScope.h 2014-11-03 05:31:30 +0000
531+++ include/unity/scopes/internal/zmq_middleware/ZmqScope.h 2015-01-26 17:27:30 +0000
532@@ -62,6 +62,9 @@
533 VariantMap const& hints,
534 MWReplyProxy const& reply) override;
535
536+ virtual ChildScopeList child_scopes_ordered() override;
537+ virtual bool set_child_scopes_ordered(ChildScopeList const& child_scopes_ordered) override;
538+
539 virtual bool debug_mode() override;
540
541 private:
542
543=== modified file 'include/unity/scopes/testing/MockScope.h'
544--- include/unity/scopes/testing/MockScope.h 2014-11-03 05:31:30 +0000
545+++ include/unity/scopes/testing/MockScope.h 2015-01-26 17:27:30 +0000
546@@ -63,6 +63,10 @@
547 MOCK_METHOD3(preview, QueryCtrlProxy(unity::scopes::Result const&,
548 ActionMetadata const&,
549 PreviewListenerBase::SPtr const&));
550+
551+ MOCK_METHOD0(child_scopes_ordered, ChildScopeList());
552+
553+ MOCK_METHOD1(set_child_scopes_ordered, bool(ChildScopeList const&));
554 };
555
556 /// @endcond
557
558=== added file 'src/scopes/AbstractScopeBase.cpp'
559--- src/scopes/AbstractScopeBase.cpp 1970-01-01 00:00:00 +0000
560+++ src/scopes/AbstractScopeBase.cpp 2015-01-26 17:27:30 +0000
561@@ -0,0 +1,37 @@
562+/*
563+ * Copyright (C) 2015 Canonical Ltd
564+ *
565+ * This program is free software: you can redistribute it and/or modify
566+ * it under the terms of the GNU Lesser General Public License version 3 as
567+ * published by the Free Software Foundation.
568+ *
569+ * This program is distributed in the hope that it will be useful,
570+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
571+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
572+ * GNU Lesser General Public License for more details.
573+ *
574+ * You should have received a copy of the GNU Lesser General Public License
575+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
576+ *
577+ * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com>
578+ */
579+
580+#include <unity/scopes/AbstractScopeBase.h>
581+
582+namespace unity
583+{
584+
585+namespace scopes
586+{
587+
588+//! @cond
589+
590+AbstractScopeBase::AbstractScopeBase() = default;
591+
592+AbstractScopeBase::~AbstractScopeBase() = default;
593+
594+//! @endcond
595+
596+} // namespace scopes
597+
598+} // namespace unity
599
600=== modified file 'src/scopes/CMakeLists.txt'
601--- src/scopes/CMakeLists.txt 2014-11-07 15:19:47 +0000
602+++ src/scopes/CMakeLists.txt 2015-01-26 17:27:30 +0000
603@@ -5,6 +5,7 @@
604 set(CAPNPROTO_FILES ${CAPNPROTO_FILES} PARENT_SCOPE)
605
606 set(SRC
607+ ${CMAKE_CURRENT_SOURCE_DIR}/AbstractScopeBase.cpp
608 ${CMAKE_CURRENT_SOURCE_DIR}/ActionMetadata.cpp
609 ${CMAKE_CURRENT_SOURCE_DIR}/ActivationListenerBase.cpp
610 ${CMAKE_CURRENT_SOURCE_DIR}/ActivationQueryBase.cpp
611
612=== modified file 'src/scopes/Runtime.cpp'
613--- src/scopes/Runtime.cpp 2014-12-04 04:33:50 +0000
614+++ src/scopes/Runtime.cpp 2015-01-26 17:27:30 +0000
615@@ -67,11 +67,6 @@
616 p->run_scope(scope_base, scope_ini_file);
617 }
618
619-void Runtime::run_scope(ScopeBase* const scope_base, std::string const&, std::string const& scope_ini_file)
620-{
621- p->run_scope(scope_base, scope_ini_file);
622-}
623-
624 ObjectProxy Runtime::string_to_proxy(string const& s) const
625 {
626 return p->string_to_proxy(s);
627
628=== modified file 'src/scopes/ScopeBase.cpp'
629--- src/scopes/ScopeBase.cpp 2014-11-13 02:47:29 +0000
630+++ src/scopes/ScopeBase.cpp 2015-01-26 17:27:30 +0000
631@@ -102,6 +102,16 @@
632 return p->settings();
633 }
634
635+ChildScopeList ScopeBase::child_scopes() const
636+{
637+ return p->child_scopes();
638+}
639+
640+ChildScopeList ScopeBase::child_scopes_ordered() const
641+{
642+ return p->child_scopes_ordered(child_scopes());
643+}
644+
645 } // namespace scopes
646
647 } // namespace unity
648
649=== modified file 'src/scopes/internal/CMakeLists.txt'
650--- src/scopes/internal/CMakeLists.txt 2014-12-01 14:12:24 +0000
651+++ src/scopes/internal/CMakeLists.txt 2015-01-26 17:27:30 +0000
652@@ -16,6 +16,7 @@
653 ${CMAKE_CURRENT_SOURCE_DIR}/CategoryImpl.cpp
654 ${CMAKE_CURRENT_SOURCE_DIR}/CategoryRegistry.cpp
655 ${CMAKE_CURRENT_SOURCE_DIR}/CategoryRendererImpl.cpp
656+ ${CMAKE_CURRENT_SOURCE_DIR}/ChildScopesRepository.cpp
657 ${CMAKE_CURRENT_SOURCE_DIR}/ColumnLayoutImpl.cpp
658 ${CMAKE_CURRENT_SOURCE_DIR}/CompletionDetailsImpl.cpp
659 ${CMAKE_CURRENT_SOURCE_DIR}/ConfigBase.cpp
660
661=== added file 'src/scopes/internal/ChildScopesRepository.cpp'
662--- src/scopes/internal/ChildScopesRepository.cpp 1970-01-01 00:00:00 +0000
663+++ src/scopes/internal/ChildScopesRepository.cpp 2015-01-26 17:27:30 +0000
664@@ -0,0 +1,243 @@
665+/*
666+ * Copyright (C) 2014 Canonical Ltd
667+ *
668+ * This program is free software: you can redistribute it and/or modify
669+ * it under the terms of the GNU Lesser General Public License version 3 as
670+ * published by the Free Software Foundation.
671+ *
672+ * This program is distributed in the hope that it will be useful,
673+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
674+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
675+ * GNU Lesser General Public License for more details.
676+ *
677+ * You should have received a copy of the GNU Lesser General Public License
678+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
679+ *
680+ * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com>
681+ */
682+
683+#include <unity/scopes/internal/ChildScopesRepository.h>
684+#include <unity/scopes/internal/JsonCppNode.h>
685+
686+#include <fstream>
687+#include <set>
688+#include <sstream>
689+
690+using namespace unity::scopes;
691+using namespace unity::scopes::internal;
692+
693+ChildScopesRepository::ChildScopesRepository(std::string const& repo_file_path,
694+ boost::log::sources::severity_channel_logger_mt<>& logger)
695+ : repo_file_path_(repo_file_path)
696+ , logger_(logger)
697+ , have_latest_cache_(false)
698+{
699+}
700+
701+ChildScopeList ChildScopesRepository::child_scopes_ordered(ChildScopeList const& child_scopes_unordered)
702+{
703+ std::lock_guard<std::mutex> lock(mutex_);
704+
705+ // unordered_set and ordered_set will act as masks for child_scopes_unordered and
706+ // child_scopes_ordered respectively when creating our resultant child scope list
707+ std::set<std::string> unordered_set;
708+ std::set<std::string> ordered_set;
709+
710+ // fill unordered_set
711+ for (auto const& child : child_scopes_unordered)
712+ {
713+ unordered_set.insert(child.id);
714+ }
715+
716+ // fill ordered_set
717+ ChildScopeList child_scopes_ordered = read_repo();
718+ for (auto const& child : child_scopes_ordered)
719+ {
720+ // scopes in child_scopes_ordered that are also in child_scopes_unordered should be removed
721+ // from unordered_set (to avoid duplicates in our resultant child scope list)
722+ if (unordered_set.erase(child.id) > 0)
723+ {
724+ // only the scopes from child_scopes_ordered that appear in child_scopes_unordered
725+ // should be added to ordered_set (a scope not found in child_scopes_unordered was
726+ // probably uninstalled since the repo was last written)
727+ ordered_set.insert(child.id);
728+ }
729+ }
730+
731+ // has anything changed since the repo was last written?
732+ if (child_scopes_ordered.size() == ordered_set.size() && // if no scopes have been removed
733+ unordered_set.size() == 0) // and no scopes have been added
734+ {
735+ return child_scopes_ordered; // return the repo list as is
736+ }
737+
738+ // now create a new list by first adding child_scopes_ordered then child_scopes_unordered,
739+ // using each set as a mask to determine whether or not a scope should be included
740+ ChildScopeList new_child_scopes_ordered;
741+ {
742+ // add child_scopes_ordered to new_child_scopes_ordered
743+ if (child_scopes_ordered.size() == ordered_set.size())
744+ {
745+ new_child_scopes_ordered = child_scopes_ordered;
746+ }
747+ else if (!ordered_set.empty())
748+ {
749+ // use ordered_set as a mask
750+ for (auto const& child : child_scopes_ordered)
751+ {
752+ if (ordered_set.find(child.id) != ordered_set.end())
753+ {
754+ new_child_scopes_ordered.push_back(child);
755+ }
756+ }
757+ }
758+
759+ // add child_scopes_unordered to new_child_scopes_ordered
760+ if (child_scopes_unordered.size() == unordered_set.size())
761+ {
762+ new_child_scopes_ordered.insert(new_child_scopes_ordered.end(),
763+ child_scopes_unordered.begin(),
764+ child_scopes_unordered.end());
765+ }
766+ else if (!unordered_set.empty())
767+ {
768+ // use unordered_set as a mask
769+ for (auto const& child : child_scopes_unordered)
770+ {
771+ if (unordered_set.find(child.id) != unordered_set.end())
772+ {
773+ new_child_scopes_ordered.push_back(child);
774+ }
775+ }
776+ }
777+ }
778+
779+ // write the new ordered list to file
780+ write_repo(new_child_scopes_ordered);
781+ return new_child_scopes_ordered;
782+}
783+
784+bool ChildScopesRepository::set_child_scopes_ordered(ChildScopeList const& child_scopes_ordered)
785+{
786+ // simply write child_scopes_ordered to file
787+ std::lock_guard<std::mutex> lock(mutex_);
788+ return write_repo(child_scopes_ordered);
789+}
790+
791+bool ChildScopesRepository::write_repo(ChildScopeList const& child_scopes_list)
792+{
793+ assert(!mutex_.try_lock());
794+
795+ // open repository for output
796+ std::ofstream repo_file(repo_file_path_);
797+ if (repo_file.fail())
798+ {
799+ BOOST_LOG_SEV(logger_, Logger::Error) << "ChildScopesRepository::write_repo(): "
800+ << "Failed to open file: \"" << repo_file_path_
801+ << "\"";
802+ return false;
803+ }
804+
805+ repo_file << list_to_json(child_scopes_list);
806+ repo_file.close();
807+
808+ cached_repo_ = child_scopes_list;
809+ have_latest_cache_ = true;
810+ return true;
811+}
812+
813+ChildScopeList ChildScopesRepository::read_repo()
814+{
815+ // if we already have the latest cache of the repo, simply return it
816+ if (have_latest_cache_)
817+ {
818+ return cached_repo_;
819+ }
820+
821+ // open repository for input
822+ std::ifstream repo_file(repo_file_path_);
823+ if (repo_file.fail())
824+ {
825+ BOOST_LOG_SEV(logger_, Logger::Info) << "ChildScopesRepository::read_repo(): "
826+ << "Failed to open file: \"" << repo_file_path_
827+ << "\"";
828+ return ChildScopeList();
829+ }
830+
831+ cached_repo_ = json_to_list(std::string((std::istreambuf_iterator<char>(repo_file)),
832+ std::istreambuf_iterator<char>()));
833+ repo_file.close();
834+
835+ have_latest_cache_ = true;
836+ return cached_repo_;
837+}
838+
839+std::string ChildScopesRepository::list_to_json(ChildScopeList const& child_scopes_list)
840+{
841+ std::ostringstream child_scopes_json;
842+ child_scopes_json << "[";
843+ for (auto const& child_scope : child_scopes_list)
844+ {
845+ child_scopes_json << (child_scopes_json.tellp() == 1 ? "{" : ",{");
846+ child_scopes_json << "\"id\":\"" << child_scope.id << "\"";
847+ child_scopes_json << ",";
848+ child_scopes_json << "\"enabled\":" << (child_scope.enabled ? "true" : "false");
849+ child_scopes_json << "}";
850+ }
851+ child_scopes_json << "]";
852+ return child_scopes_json.str();
853+}
854+
855+ChildScopeList ChildScopesRepository::json_to_list(std::string const& child_scopes_json)
856+{
857+ JsonCppNode json_node;
858+ try
859+ {
860+ json_node.read_json(child_scopes_json);
861+ }
862+ catch (std::exception const& e)
863+ {
864+ BOOST_LOG_SEV(logger_, Logger::Error) << "ChildScopesRepository::json_to_list(): "
865+ << "Exception thrown while reading json string: "
866+ << e.what();
867+ return ChildScopeList();
868+ }
869+ if (json_node.type() != JsonCppNode::Array)
870+ {
871+ BOOST_LOG_SEV(logger_, Logger::Error) << "ChildScopesRepository::json_to_list(): "
872+ << "Root node of json string is not an array:"
873+ << std::endl << child_scopes_json;
874+ return ChildScopeList();
875+ }
876+
877+ ChildScopeList return_list;
878+ for (int i = 0; i < json_node.size(); ++i)
879+ {
880+ auto child_node = json_node.get_node(i);
881+
882+ if (!child_node->has_node("id") ||
883+ !child_node->has_node("enabled"))
884+ {
885+ BOOST_LOG_SEV(logger_, Logger::Error) << "ChildScopesRepository::json_to_list(): "
886+ << "Child node is missing a required field. "
887+ << "Skipping child node:" << std::endl
888+ << child_node->to_json_string();
889+ continue;
890+ }
891+ auto id_node = child_node->get_node("id");
892+ auto enabled_node = child_node->get_node("enabled");
893+
894+ if (id_node->type() != JsonCppNode::String ||
895+ enabled_node->type() != JsonCppNode::Bool)
896+ {
897+ BOOST_LOG_SEV(logger_, Logger::Error) << "ChildScopesRepository::json_to_list(): "
898+ << "Child node contains an invalid value type. "
899+ << "Skipping child node:" << std::endl
900+ << child_node->to_json_string();
901+ continue;
902+ }
903+ return_list.push_back( ChildScope{id_node->as_string(),
904+ enabled_node->as_bool()} );
905+ }
906+ return return_list;
907+}
908
909=== modified file 'src/scopes/internal/RuntimeImpl.cpp'
910--- src/scopes/internal/RuntimeImpl.cpp 2015-01-18 23:48:55 +0000
911+++ src/scopes/internal/RuntimeImpl.cpp 2015-01-26 17:27:30 +0000
912@@ -18,6 +18,7 @@
913
914 #include <unity/scopes/internal/RuntimeImpl.h>
915
916+#include <unity/scopes/internal/ChildScopesRepository.h>
917 #include <unity/scopes/internal/DfltConfig.h>
918 #include <unity/scopes/internal/Logger.h>
919 #include <unity/scopes/internal/MWStateReceiver.h>
920@@ -388,6 +389,12 @@
921 {
922 scope_base->p->set_settings_db(nullptr);
923 }
924+
925+ // Configure the child scopes repository
926+ string child_scopes_repo = config_dir + "/child-scopes.json";
927+
928+ auto repo = make_shared<ChildScopesRepository>(child_scopes_repo, logger());
929+ scope_base->p->set_child_scopes_repo(repo);
930 }
931
932 scope_base->p->set_registry(registry_);
933
934=== modified file 'src/scopes/internal/ScopeBaseImpl.cpp'
935--- src/scopes/internal/ScopeBaseImpl.cpp 2015-01-14 02:19:17 +0000
936+++ src/scopes/internal/ScopeBaseImpl.cpp 2015-01-26 17:27:30 +0000
937@@ -19,7 +19,9 @@
938 #include <unity/scopes/internal/ScopeBaseImpl.h>
939
940 #include <unity/UnityExceptions.h>
941+#include <unity/scopes/internal/ChildScopesRepository.h>
942 #include <unity/scopes/internal/SettingsDB.h>
943+#include <unity/scopes/Registry.h>
944 #include <unity/scopes/ScopeExceptions.h>
945
946 using namespace unity;
947@@ -42,6 +44,7 @@
948 , tmp_dir_initialized_(false)
949 , registry_initialized_(false)
950 , settings_db_initialized_(false)
951+ , child_scopes_repo_initialized_(false)
952 {
953 }
954
955@@ -171,6 +174,53 @@
956 return db_ ? db_->settings() : VariantMap();
957 }
958
959+void ScopeBaseImpl::set_child_scopes_repo(std::shared_ptr<ChildScopesRepository> const& child_scopes_repo)
960+{
961+ lock_guard<mutex> lock(mutex_);
962+ child_scopes_repo_ = child_scopes_repo;
963+ child_scopes_repo_initialized_ = true;
964+}
965+
966+ChildScopeList ScopeBaseImpl::child_scopes() const
967+{
968+ // Get a copy of the registry proxy
969+ RegistryProxy reg = registry();
970+ if (!reg)
971+ {
972+ return ChildScopeList();
973+ }
974+
975+ // The default behaviour of this method is to simply return all available scopes on the system.
976+ ChildScopeList return_list;
977+ auto all_scopes = reg->list();
978+ for (auto const& scope : all_scopes)
979+ {
980+ // New scopes are added disabled by default
981+ return_list.push_back( ChildScope{scope.first, false} );
982+ }
983+ return return_list;
984+}
985+
986+ChildScopeList ScopeBaseImpl::child_scopes_ordered(ChildScopeList const& child_scopes_unordered) const
987+{
988+ lock_guard<mutex> lock(mutex_);
989+ if (!child_scopes_repo_initialized_)
990+ {
991+ throw LogicException("ScopeBase::child_scopes_ordered() cannot be called from constructor");
992+ }
993+ return child_scopes_repo_ ? child_scopes_repo_->child_scopes_ordered(child_scopes_unordered) : ChildScopeList();
994+}
995+
996+bool ScopeBaseImpl::set_child_scopes_ordered(ChildScopeList const& child_scopes_ordered)
997+{
998+ lock_guard<mutex> lock(mutex_);
999+ if (!child_scopes_repo_initialized_)
1000+ {
1001+ throw LogicException("ScopeBase::set_child_scopes_ordered() cannot be called from constructor");
1002+ }
1003+ return child_scopes_repo_ ? child_scopes_repo_->set_child_scopes_ordered(child_scopes_ordered) : false;
1004+}
1005+
1006 } // namespace internal
1007
1008 } // namespace scopes
1009
1010=== modified file 'src/scopes/internal/ScopeImpl.cpp'
1011--- src/scopes/internal/ScopeImpl.cpp 2015-01-09 03:16:51 +0000
1012+++ src/scopes/internal/ScopeImpl.cpp 2015-01-26 17:27:30 +0000
1013@@ -283,6 +283,16 @@
1014 return ctrl;
1015 }
1016
1017+ChildScopeList ScopeImpl::child_scopes_ordered()
1018+{
1019+ return fwd()->child_scopes_ordered();
1020+}
1021+
1022+bool ScopeImpl::set_child_scopes_ordered(ChildScopeList const& child_scopes_ordered)
1023+{
1024+ return fwd()->set_child_scopes_ordered(child_scopes_ordered);
1025+}
1026+
1027 ScopeProxy ScopeImpl::create(MWScopeProxy const& mw_proxy, std::string const& scope_id)
1028 {
1029 return make_shared<ScopeImpl>(mw_proxy, scope_id);
1030
1031=== modified file 'src/scopes/internal/ScopeObject.cpp'
1032--- src/scopes/internal/ScopeObject.cpp 2015-01-09 03:47:02 +0000
1033+++ src/scopes/internal/ScopeObject.cpp 2015-01-26 17:27:30 +0000
1034@@ -213,6 +213,16 @@
1035 );
1036 }
1037
1038+ChildScopeList ScopeObject::child_scopes_ordered() const
1039+{
1040+ return scope_base_->child_scopes_ordered();
1041+}
1042+
1043+bool ScopeObject::set_child_scopes_ordered(ChildScopeList const& child_scopes_ordered)
1044+{
1045+ return scope_base_->p->set_child_scopes_ordered(child_scopes_ordered);
1046+}
1047+
1048 bool ScopeObject::debug_mode() const
1049 {
1050 return debug_mode_;
1051
1052=== modified file 'src/scopes/internal/smartscopes/SSScopeObject.cpp'
1053--- src/scopes/internal/smartscopes/SSScopeObject.cpp 2015-01-09 03:16:51 +0000
1054+++ src/scopes/internal/smartscopes/SSScopeObject.cpp 2015-01-26 17:27:30 +0000
1055@@ -191,6 +191,16 @@
1056 return info.mw->create_query_ctrl_proxy(reply->identity() + ".c", info.mw->get_query_ctrl_endpoint());
1057 }
1058
1059+ChildScopeList SSScopeObject::child_scopes_ordered() const
1060+{
1061+ return ChildScopeList();
1062+}
1063+
1064+bool SSScopeObject::set_child_scopes_ordered(ChildScopeList const&)
1065+{
1066+ return false;
1067+}
1068+
1069 bool SSScopeObject::debug_mode() const
1070 {
1071 return false;
1072
1073=== modified file 'src/scopes/internal/zmq_middleware/ScopeI.cpp'
1074--- src/scopes/internal/zmq_middleware/ScopeI.cpp 2014-11-18 07:04:04 +0000
1075+++ src/scopes/internal/zmq_middleware/ScopeI.cpp 2015-01-26 17:27:30 +0000
1076@@ -60,6 +60,8 @@
1077 QueryCtrl* preview(ValueDict result, ValueDict hints, Reply* replyProxy);
1078 QueryCtrl* perform_action(ValueDict result, ValueDict hints, string action_id, Reply* replyProxy);
1079 QueryCtrl* activate(ValueDict result, ValueDict hints, Reply* replyProxy);
1080+ ChildScopeList child_scopes_ordered();
1081+ bool set_child_scopes_ordered(ChildScopeList const& child_scopes_ordered);
1082 bool debug_mode();
1083 };
1084
1085@@ -73,6 +75,8 @@
1086 { "preview", bind(&ScopeI::preview_, this, ph::_1, ph::_2, ph::_3) },
1087 { "activate", bind(&ScopeI::activate_, this, ph::_1, ph::_2, ph::_3) },
1088 { "perform_action", bind(&ScopeI::perform_action_, this, ph::_1, ph::_2, ph::_3) },
1089+ { "child_scopes_ordered", bind(&ScopeI::child_scopes_ordered_, this, ph::_1, ph::_2, ph::_3) },
1090+ { "set_child_scopes_ordered", bind(&ScopeI::set_child_scopes_ordered_, this, ph::_1, ph::_2, ph::_3) },
1091 { "debug_mode", bind(&ScopeI::debug_mode_, this, ph::_1, ph::_2, ph::_3) }
1092 })
1093 {
1094@@ -194,6 +198,51 @@
1095 p.setCategory(ctrl_proxy->target_category().c_str());
1096 }
1097
1098+void ScopeI::child_scopes_ordered_(Current const&,
1099+ capnp::AnyPointer::Reader&,
1100+ capnproto::Response::Builder& r)
1101+{
1102+ auto delegate = dynamic_pointer_cast<ScopeObjectBase>(del());
1103+ assert(delegate);
1104+
1105+ auto child_scopes_ordered = delegate->child_scopes_ordered();
1106+
1107+ r.setStatus(capnproto::ResponseStatus::SUCCESS);
1108+ auto list_response = r.initPayload().getAs<capnproto::Scope::ChildScopesOrderedResponse>();
1109+ auto list = list_response.initReturnValue(child_scopes_ordered.size());
1110+
1111+ int i = 0;
1112+ for (auto const& child_scope : child_scopes_ordered)
1113+ {
1114+ list[i].setId(child_scope.id);
1115+ list[i].setEnabled(child_scope.enabled);
1116+ ++i;
1117+ }
1118+}
1119+
1120+void ScopeI::set_child_scopes_ordered_(Current const&,
1121+ capnp::AnyPointer::Reader& in_params,
1122+ capnproto::Response::Builder& r)
1123+{
1124+ auto delegate = std::dynamic_pointer_cast<ScopeObjectBase>(del());
1125+ assert(delegate);
1126+
1127+ auto list = in_params.getAs<capnproto::Scope::SetChildScopesOrderedRequest>().getChildScopesOrdered();
1128+
1129+ ChildScopeList child_scope_list;
1130+ for (size_t i = 0; i < list.size(); ++i)
1131+ {
1132+ string id = list[i].getId();
1133+ bool enabled = list[i].getEnabled();
1134+ child_scope_list.push_back( ChildScope{id, enabled} );
1135+ }
1136+
1137+ bool result = delegate->set_child_scopes_ordered(child_scope_list);
1138+ r.setStatus(capnproto::ResponseStatus::SUCCESS);
1139+ auto response = r.initPayload().getAs<capnproto::Scope::SetChildScopesOrderedResponse>();
1140+ response.setReturnValue(result);
1141+}
1142+
1143 void ScopeI::debug_mode_(Current const&,
1144 capnp::AnyPointer::Reader&,
1145 capnproto::Response::Builder& r)
1146
1147=== modified file 'src/scopes/internal/zmq_middleware/ZmqScope.cpp'
1148--- src/scopes/internal/zmq_middleware/ZmqScope.cpp 2015-01-09 03:16:51 +0000
1149+++ src/scopes/internal/zmq_middleware/ZmqScope.cpp 2015-01-26 17:27:30 +0000
1150@@ -56,6 +56,8 @@
1151 QueryCtrl* activate(string query, ValueDict hints, Reply* replyProxy);
1152 QueryCtrl* perform_action(string query, ValueDict hints, string action_id, Reply* replyProxy);
1153 QueryCtrl* preview(string query, ValueDict hints, Reply* replyProxy);
1154+ ChildScopeList child_scopes_ordered();
1155+ bool set_child_scopes_ordered(ChildScopeList const& child_scopes_ordered);
1156 bool debug_mode();
1157 };
1158
1159@@ -200,6 +202,54 @@
1160 return make_shared<QueryCtrlImpl>(p, reply_proxy);
1161 }
1162
1163+ChildScopeList ZmqScope::child_scopes_ordered()
1164+{
1165+ capnp::MallocMessageBuilder request_builder;
1166+ make_request_(request_builder, "child_scopes_ordered");
1167+
1168+ auto future = mw_base()->twoway_pool()->submit([&] { return this->invoke_scope_(request_builder); });
1169+
1170+ auto out_params = future.get();
1171+ auto response = out_params.reader->getRoot<capnproto::Response>();
1172+ throw_if_runtime_exception(response);
1173+
1174+ auto list = response.getPayload().getAs<capnproto::Scope::ChildScopesOrderedResponse>().getReturnValue();
1175+
1176+ ChildScopeList child_scope_list;
1177+ for (size_t i = 0; i < list.size(); ++i)
1178+ {
1179+ string id = list[i].getId();
1180+ bool enabled = list[i].getEnabled();
1181+ child_scope_list.push_back( ChildScope{id, enabled} );
1182+ }
1183+ return child_scope_list;
1184+}
1185+
1186+bool ZmqScope::set_child_scopes_ordered(ChildScopeList const& child_scopes_ordered)
1187+{
1188+ capnp::MallocMessageBuilder request_builder;
1189+ auto request = make_request_(request_builder, "set_child_scopes_ordered");
1190+
1191+ auto in_params = request.initInParams().getAs<capnproto::Scope::SetChildScopesOrderedRequest>();
1192+ auto list = in_params.initChildScopesOrdered(child_scopes_ordered.size());
1193+
1194+ int i = 0;
1195+ for (auto const& child_scope : child_scopes_ordered)
1196+ {
1197+ list[i].setId(child_scope.id);
1198+ list[i].setEnabled(child_scope.enabled);
1199+ ++i;
1200+ }
1201+
1202+ auto future = mw_base()->twoway_pool()->submit([&] { return this->invoke_scope_(request_builder); });
1203+ auto out_params = future.get();
1204+ auto r = out_params.reader->getRoot<capnproto::Response>();
1205+ throw_if_runtime_exception(r);
1206+
1207+ auto response = r.getPayload().getAs<capnproto::Scope::SetChildScopesOrderedResponse>();
1208+ return response.getReturnValue();
1209+}
1210+
1211 bool ZmqScope::debug_mode()
1212 {
1213 lock_guard<std::mutex> lock(debug_mode_mutex_);
1214
1215=== modified file 'src/scopes/internal/zmq_middleware/capnproto/Scope.capnp'
1216--- src/scopes/internal/zmq_middleware/capnproto/Scope.capnp 2014-08-12 13:26:35 +0000
1217+++ src/scopes/internal/zmq_middleware/capnproto/Scope.capnp 2015-01-26 17:27:30 +0000
1218@@ -76,6 +76,27 @@
1219 replyProxy @2 : Proxy.Proxy;
1220 }
1221
1222+struct ChildScope
1223+{
1224+ id @0 : Text;
1225+ enabled @1 : Bool;
1226+}
1227+
1228+struct ChildScopesOrderedResponse
1229+{
1230+ returnValue @0 : List(ChildScope);
1231+}
1232+
1233+struct SetChildScopesOrderedRequest
1234+{
1235+ childScopesOrdered @0 : List(ChildScope);
1236+}
1237+
1238+struct SetChildScopesOrderedResponse
1239+{
1240+ returnValue @0 : Bool;
1241+}
1242+
1243 struct DebugModeResponse
1244 {
1245 returnValue @0 : Bool;
1246
1247=== modified file 'test/gtest/scopes/CMakeLists.txt'
1248--- test/gtest/scopes/CMakeLists.txt 2014-12-01 01:51:38 +0000
1249+++ test/gtest/scopes/CMakeLists.txt 2015-01-26 17:27:30 +0000
1250@@ -13,6 +13,7 @@
1251 add_subdirectory(CategorisedResult)
1252 add_subdirectory(Category)
1253 add_subdirectory(CategoryRenderer)
1254+add_subdirectory(ChildScopes)
1255 add_subdirectory(ColumnLayout)
1256 add_subdirectory(Department)
1257 add_subdirectory(Filters)
1258
1259=== added directory 'test/gtest/scopes/ChildScopes'
1260=== added file 'test/gtest/scopes/ChildScopes/CMakeLists.txt'
1261--- test/gtest/scopes/ChildScopes/CMakeLists.txt 1970-01-01 00:00:00 +0000
1262+++ test/gtest/scopes/ChildScopes/CMakeLists.txt 2015-01-26 17:27:30 +0000
1263@@ -0,0 +1,10 @@
1264+configure_file(Registry.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Registry.ini)
1265+configure_file(Runtime.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini)
1266+configure_file(Zmq.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Zmq.ini)
1267+
1268+add_definitions(-DTEST_BIN_DIR="${CMAKE_CURRENT_BINARY_DIR}")
1269+
1270+add_executable(ChildScopes_test ChildScopes_test.cpp)
1271+target_link_libraries(ChildScopes_test ${TESTLIBS})
1272+
1273+add_test(ChildScopes ChildScopes_test)
1274
1275=== added file 'test/gtest/scopes/ChildScopes/ChildScopes_test.cpp'
1276--- test/gtest/scopes/ChildScopes/ChildScopes_test.cpp 1970-01-01 00:00:00 +0000
1277+++ test/gtest/scopes/ChildScopes/ChildScopes_test.cpp 2015-01-26 17:27:30 +0000
1278@@ -0,0 +1,325 @@
1279+/*
1280+ * Copyright (C) 2014 Canonical Ltd
1281+ *
1282+ * This program is free software: you can redistribute it and/or modify
1283+ * it under the terms of the GNU Lesser General Public License version 3 as
1284+ * published by the Free Software Foundation.
1285+ *
1286+ * This program is distributed in the hope that it will be useful,
1287+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1288+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1289+ * GNU Lesser General Public License for more details.
1290+ *
1291+ * You should have received a copy of the GNU Lesser General Public License
1292+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1293+ *
1294+ * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com>
1295+ */
1296+
1297+#include <unity/scopes/ChildScope.h>
1298+
1299+#include <unity/scopes/internal/RegistryObject.h>
1300+#include <unity/scopes/internal/ScopeImpl.h>
1301+
1302+#include "TestScope.h"
1303+
1304+#include <boost/filesystem/operations.hpp>
1305+#include <fstream>
1306+#include <gtest/gtest.h>
1307+
1308+using namespace boost;
1309+using namespace testing;
1310+using namespace unity::scopes;
1311+using namespace unity::scopes::internal;
1312+
1313+std::shared_ptr<core::posix::SignalTrap> trap(core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_chld}));
1314+std::unique_ptr<core::posix::ChildProcess::DeathObserver> death_observer(core::posix::ChildProcess::DeathObserver::create_once_with_signal_trap(trap));
1315+
1316+class ChildScopesTest : public Test
1317+{
1318+public:
1319+ ChildScopesTest()
1320+ {
1321+ // Run a test registry
1322+ reg_rt_ = RuntimeImpl::create("TestRegistry", "Runtime.ini");
1323+ auto reg_mw = reg_rt_->factory()->create("TestRegistry", "Zmq", "Zmq.ini");
1324+ auto reg_obj(std::make_shared<RegistryObject>(*death_observer, std::make_shared<Executor>(), reg_mw));
1325+ reg_mw->add_registry_object("TestRegistry", reg_obj);
1326+
1327+ // Create a proxy to TestScope
1328+ proxy_rt_ = RuntimeImpl::create("", "Runtime.ini");
1329+ auto scope_mw = proxy_rt_->factory()->create("TestScope", "Zmq", "Zmq.ini");
1330+ scope_mw->start();
1331+ auto proxy = scope_mw->create_scope_proxy("TestScope");
1332+ test_scope = ScopeImpl::create(proxy, "TestScope");
1333+ }
1334+
1335+ ~ChildScopesTest()
1336+ {
1337+ stop_test_scope();
1338+ }
1339+
1340+ void create_config_dir()
1341+ {
1342+ // Create an empty config directory for TestScope
1343+ system::error_code ec;
1344+ filesystem::create_directory(TEST_BIN_DIR "/TestScope", ec);
1345+ }
1346+
1347+ void remove_config_dir()
1348+ {
1349+ // Remove the config directory for TestScope
1350+ system::error_code ec;
1351+ filesystem::remove_all(TEST_BIN_DIR "/TestScope", ec);
1352+ }
1353+
1354+ void write_empty_config()
1355+ {
1356+ // open repository for output
1357+ std::ofstream repo_file(TEST_BIN_DIR "/TestScope/child-scopes.json");
1358+ repo_file << "";
1359+ repo_file.close();
1360+ }
1361+
1362+ void write_corrupt_config()
1363+ {
1364+ // open repository for output
1365+ std::ofstream repo_file(TEST_BIN_DIR "/TestScope/child-scopes.json");
1366+ repo_file << "ag;hasd;glasd;glkasdhg;klasdf;k;";
1367+ repo_file.close();
1368+ }
1369+
1370+ void write_partially_corrupt_config()
1371+ {
1372+ // open repository for output
1373+ std::ofstream repo_file(TEST_BIN_DIR "/TestScope/child-scopes.json");
1374+ repo_file << R"([{"id":"ScopeB","enabled":true},{"id":"ScopeB"},{"id":"ScopeC","enabled":"false"}])";
1375+ repo_file.close();
1376+ }
1377+
1378+ void start_test_scope()
1379+ {
1380+ // Run TestScope in a separate thread
1381+ scope_rt_ = Runtime::create_scope_runtime("TestScope", "Runtime.ini");
1382+ scope_t_ = std::thread([this]
1383+ {
1384+ TestScope scope;
1385+ scope_rt_->run_scope(&scope, "");
1386+ });
1387+
1388+ // Give the scope some time to bind to its endpoint
1389+ std::this_thread::sleep_for(std::chrono::milliseconds(500));
1390+ }
1391+
1392+ void stop_test_scope()
1393+ {
1394+ if (scope_rt_)
1395+ {
1396+ scope_rt_->destroy();
1397+ }
1398+ if (scope_t_.joinable())
1399+ {
1400+ scope_t_.join();
1401+ }
1402+ }
1403+
1404+protected:
1405+ ScopeProxy test_scope;
1406+
1407+private:
1408+ RuntimeImpl::UPtr reg_rt_;
1409+ RuntimeImpl::UPtr proxy_rt_;
1410+ Runtime::UPtr scope_rt_;
1411+ std::thread scope_t_;
1412+};
1413+
1414+TEST_F(ChildScopesTest, get_set_ordered_list)
1415+{
1416+ // Create an empty config directory for TestScope
1417+ remove_config_dir();
1418+ create_config_dir();
1419+
1420+ // Start TestScope
1421+ start_test_scope();
1422+
1423+ // 1st TestScope::child_scopes() returns: "A,B,C"
1424+ // No order has been set yet, so we should just get: "A,B,C"
1425+ ChildScopeList return_list = test_scope->child_scopes_ordered();
1426+ EXPECT_EQ(3, return_list.size());
1427+ EXPECT_EQ("ScopeA", return_list.front().id);
1428+ EXPECT_FALSE(return_list.front().enabled);
1429+ return_list.pop_front();
1430+ EXPECT_EQ("ScopeB", return_list.front().id);
1431+ EXPECT_FALSE(return_list.front().enabled);
1432+ return_list.pop_front();
1433+ EXPECT_EQ("ScopeC", return_list.front().id);
1434+ EXPECT_TRUE(return_list.front().enabled);
1435+
1436+ // Set order to: "B,E,A"
1437+ ChildScopeList list;
1438+ list.push_back({"ScopeB", false});
1439+ list.push_back({"ScopeE", false});
1440+ list.push_back({"ScopeA", true});
1441+ EXPECT_TRUE(test_scope->set_child_scopes_ordered(list));
1442+
1443+ // 2nd TestScope::child_scopes() returns: "D,A,B,C,E"
1444+ // with order: "B,E,A", we should get: "B,E,A,D,C"
1445+ return_list = test_scope->child_scopes_ordered();
1446+ EXPECT_EQ(5, return_list.size());
1447+ EXPECT_EQ("ScopeB", return_list.front().id);
1448+ EXPECT_FALSE(return_list.front().enabled);
1449+ return_list.pop_front();
1450+ EXPECT_EQ("ScopeE", return_list.front().id);
1451+ EXPECT_FALSE(return_list.front().enabled);
1452+ return_list.pop_front();
1453+ EXPECT_EQ("ScopeA", return_list.front().id);
1454+ EXPECT_TRUE(return_list.front().enabled);
1455+ return_list.pop_front();
1456+ EXPECT_EQ("ScopeD", return_list.front().id);
1457+ EXPECT_FALSE(return_list.front().enabled);
1458+ return_list.pop_front();
1459+ EXPECT_EQ("ScopeC", return_list.front().id);
1460+ EXPECT_TRUE(return_list.front().enabled);
1461+
1462+ // 3rd+ TestScope::child_scopes() returns: "D,A,B"
1463+ // with order: "B,E,A,D,C", we should get: "B,A,D"
1464+ return_list = test_scope->child_scopes_ordered();
1465+ EXPECT_EQ(3, return_list.size());
1466+ EXPECT_EQ("ScopeB", return_list.front().id);
1467+ EXPECT_FALSE(return_list.front().enabled);
1468+ return_list.pop_front();
1469+ EXPECT_EQ("ScopeA", return_list.front().id);
1470+ EXPECT_TRUE(return_list.front().enabled);
1471+ return_list.pop_front();
1472+ EXPECT_EQ("ScopeD", return_list.front().id);
1473+ EXPECT_FALSE(return_list.front().enabled);
1474+
1475+ // Set order to: "B,D,X,A"
1476+ list.clear();
1477+ list.push_back({"ScopeB", false});
1478+ list.push_back({"ScopeD", true});
1479+ list.push_back({"ScopeX", true});
1480+ list.push_back({"ScopeA", false});
1481+ EXPECT_TRUE(test_scope->set_child_scopes_ordered(list));
1482+
1483+ // 3rd+ TestScope::child_scopes() returns: "D,A,B"
1484+ // with order: "B,D,X,A", we should get: "B,D,A"
1485+ return_list = test_scope->child_scopes_ordered();
1486+ return_list = test_scope->child_scopes_ordered();
1487+ EXPECT_EQ(3, return_list.size());
1488+ EXPECT_EQ("ScopeB", return_list.front().id);
1489+ EXPECT_FALSE(return_list.front().enabled);
1490+ return_list.pop_front();
1491+ EXPECT_EQ("ScopeD", return_list.front().id);
1492+ EXPECT_TRUE(return_list.front().enabled);
1493+ return_list.pop_front();
1494+ EXPECT_EQ("ScopeA", return_list.front().id);
1495+ EXPECT_FALSE(return_list.front().enabled);
1496+}
1497+
1498+TEST_F(ChildScopesTest, existing_config)
1499+{
1500+ // Use config from previous test
1501+ // Start TestScope
1502+ start_test_scope();
1503+
1504+ // 1st TestScope::child_scopes() returns: "A,B,C"
1505+ // with order: "B,D,A" (from previous test), we should get: "B,A,C"
1506+ ChildScopeList return_list = test_scope->child_scopes_ordered();
1507+ EXPECT_EQ(3, return_list.size());
1508+ EXPECT_EQ("ScopeB", return_list.front().id);
1509+ EXPECT_FALSE(return_list.front().enabled);
1510+ return_list.pop_front();
1511+ EXPECT_EQ("ScopeA", return_list.front().id);
1512+ EXPECT_FALSE(return_list.front().enabled);
1513+ return_list.pop_front();
1514+ EXPECT_EQ("ScopeC", return_list.front().id);
1515+ EXPECT_TRUE(return_list.front().enabled);
1516+}
1517+
1518+TEST_F(ChildScopesTest, no_config_dir)
1519+{
1520+ // Remove the config directory for TestScope
1521+ remove_config_dir();
1522+
1523+ // Start TestScope
1524+ start_test_scope();
1525+
1526+ // Set order to: "B,A,C" (should fail)
1527+ ChildScopeList list;
1528+ list.push_back({"ScopeB", false});
1529+ list.push_back({"ScopeA", false});
1530+ list.push_back({"ScopeC", true});
1531+ EXPECT_FALSE(test_scope->set_child_scopes_ordered(list));
1532+
1533+ // 1st TestScope::child_scopes() returns: "A,B,C"
1534+ // No order was set, so we should just get: "A,B,C"
1535+ ChildScopeList return_list = test_scope->child_scopes_ordered();
1536+ EXPECT_EQ(3, return_list.size());
1537+ EXPECT_EQ("ScopeA", return_list.front().id);
1538+ EXPECT_FALSE(return_list.front().enabled);
1539+ return_list.pop_front();
1540+ EXPECT_EQ("ScopeB", return_list.front().id);
1541+ EXPECT_FALSE(return_list.front().enabled);
1542+ return_list.pop_front();
1543+ EXPECT_EQ("ScopeC", return_list.front().id);
1544+ EXPECT_TRUE(return_list.front().enabled);
1545+}
1546+
1547+TEST_F(ChildScopesTest, corrupted_config)
1548+{
1549+ // Create an empty config directory for TestScope
1550+ remove_config_dir();
1551+ create_config_dir();
1552+
1553+ // Partially corrupt config (Sets order to: "B")
1554+ write_partially_corrupt_config();
1555+ start_test_scope();
1556+
1557+ // 1st TestScope::child_scopes() returns: "A,B,C"
1558+ // with partial order: "B", we should get: "B,A,C"
1559+ ChildScopeList return_list = test_scope->child_scopes_ordered();
1560+ EXPECT_EQ(3, return_list.size());
1561+ EXPECT_EQ("ScopeB", return_list.front().id);
1562+ EXPECT_TRUE(return_list.front().enabled);
1563+ return_list.pop_front();
1564+ EXPECT_EQ("ScopeA", return_list.front().id);
1565+ EXPECT_FALSE(return_list.front().enabled);
1566+ return_list.pop_front();
1567+ EXPECT_EQ("ScopeC", return_list.front().id);
1568+ EXPECT_TRUE(return_list.front().enabled);
1569+
1570+ // Empty config
1571+ write_empty_config();
1572+ stop_test_scope();
1573+ start_test_scope();
1574+
1575+ // Check that nothing crashes and we simply get the list from the scope as is
1576+ return_list = test_scope->child_scopes_ordered();
1577+ EXPECT_EQ(3, return_list.size());
1578+ EXPECT_EQ("ScopeA", return_list.front().id);
1579+ EXPECT_FALSE(return_list.front().enabled);
1580+ return_list.pop_front();
1581+ EXPECT_EQ("ScopeB", return_list.front().id);
1582+ EXPECT_FALSE(return_list.front().enabled);
1583+ return_list.pop_front();
1584+ EXPECT_EQ("ScopeC", return_list.front().id);
1585+ EXPECT_TRUE(return_list.front().enabled);
1586+
1587+ // Corrupt config
1588+ write_corrupt_config();
1589+ stop_test_scope();
1590+ start_test_scope();
1591+
1592+ // Check that nothing crashes and we simply get the list from the scope as is
1593+ return_list = test_scope->child_scopes_ordered();
1594+ EXPECT_EQ(3, return_list.size());
1595+ EXPECT_EQ("ScopeA", return_list.front().id);
1596+ EXPECT_FALSE(return_list.front().enabled);
1597+ return_list.pop_front();
1598+ EXPECT_EQ("ScopeB", return_list.front().id);
1599+ EXPECT_FALSE(return_list.front().enabled);
1600+ return_list.pop_front();
1601+ EXPECT_EQ("ScopeC", return_list.front().id);
1602+ EXPECT_TRUE(return_list.front().enabled);
1603+}
1604
1605=== added file 'test/gtest/scopes/ChildScopes/Registry.ini.in'
1606--- test/gtest/scopes/ChildScopes/Registry.ini.in 1970-01-01 00:00:00 +0000
1607+++ test/gtest/scopes/ChildScopes/Registry.ini.in 2015-01-26 17:27:30 +0000
1608@@ -0,0 +1,6 @@
1609+[Registry]
1610+Middleware = Zmq
1611+Zmq.ConfigFile = Zmq.ini
1612+Scope.InstallDir = /unused
1613+Click.InstallDir = /unused
1614+Scoperunner.Path = /unused
1615
1616=== added file 'test/gtest/scopes/ChildScopes/Runtime.ini.in'
1617--- test/gtest/scopes/ChildScopes/Runtime.ini.in 1970-01-01 00:00:00 +0000
1618+++ test/gtest/scopes/ChildScopes/Runtime.ini.in 2015-01-26 17:27:30 +0000
1619@@ -0,0 +1,6 @@
1620+[Runtime]
1621+Registry.Identity = TestRegistry
1622+Registry.ConfigFile = Registry.ini
1623+Default.Middleware = Zmq
1624+Zmq.ConfigFile = Zmq.ini
1625+ConfigDir = @CMAKE_CURRENT_BINARY_DIR@
1626
1627=== added file 'test/gtest/scopes/ChildScopes/TestScope.h'
1628--- test/gtest/scopes/ChildScopes/TestScope.h 1970-01-01 00:00:00 +0000
1629+++ test/gtest/scopes/ChildScopes/TestScope.h 2015-01-26 17:27:30 +0000
1630@@ -0,0 +1,83 @@
1631+/*
1632+ * Copyright (C) 2014 Canonical Ltd
1633+ *
1634+ * This program is free software: you can redistribute it and/or modify
1635+ * it under the terms of the GNU Lesser General Public License version 3 as
1636+ * published by the Free Software Foundation.
1637+ *
1638+ * This program is distributed in the hope that it will be useful,
1639+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1640+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1641+ * GNU Lesser General Public License for more details.
1642+ *
1643+ * You should have received a copy of the GNU Lesser General Public License
1644+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1645+ *
1646+ * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com>
1647+ */
1648+
1649+#pragma once
1650+
1651+#include <unity/scopes/ScopeBase.h>
1652+
1653+namespace unity
1654+{
1655+
1656+namespace scopes
1657+{
1658+
1659+class TestScope : public ScopeBase
1660+{
1661+public:
1662+ SearchQueryBase::UPtr search(CannedQuery const&, SearchMetadata const&) override
1663+ {
1664+ return nullptr;
1665+ }
1666+
1667+ PreviewQueryBase::UPtr preview(Result const&, ActionMetadata const&) override
1668+ {
1669+ return nullptr;
1670+ }
1671+
1672+ ChildScopeList child_scopes() const override
1673+ {
1674+ // 1st TestScope::child_scopes() returns: "A,B,C"
1675+ if (i == 0)
1676+ {
1677+ ChildScopeList list;
1678+ list.push_back({"ScopeA", false});
1679+ list.push_back({"ScopeB", false});
1680+ list.push_back({"ScopeC", true});
1681+ ++i;
1682+ return list;
1683+ }
1684+ // 2nd TestScope::child_scopes() returns: "D,A,B,C,E"
1685+ else if (i == 1)
1686+ {
1687+ ChildScopeList list;
1688+ list.push_back({"ScopeD", false});
1689+ list.push_back({"ScopeA", false});
1690+ list.push_back({"ScopeB", false});
1691+ list.push_back({"ScopeC", true});
1692+ list.push_back({"ScopeE", true});
1693+ ++i;
1694+ return list;
1695+ }
1696+ // 3rd+ TestScope::child_scopes() returns: D,A,B
1697+ else
1698+ {
1699+ ChildScopeList list;
1700+ list.push_back({"ScopeD", true});
1701+ list.push_back({"ScopeA", false});
1702+ list.push_back({"ScopeB", false});
1703+ return list;
1704+ }
1705+ }
1706+
1707+private:
1708+ mutable int i = 0;
1709+};
1710+
1711+} // namespace scopes
1712+
1713+} // namespace unity
1714
1715=== added file 'test/gtest/scopes/ChildScopes/Zmq.ini.in'
1716--- test/gtest/scopes/ChildScopes/Zmq.ini.in 1970-01-01 00:00:00 +0000
1717+++ test/gtest/scopes/ChildScopes/Zmq.ini.in 2015-01-26 17:27:30 +0000
1718@@ -0,0 +1,2 @@
1719+[Zmq]
1720+EndpointDir = /tmp
1721
1722=== modified file 'test/gtest/scopes/internal/RegistryObject/RegistryObject_test.cpp'
1723--- test/gtest/scopes/internal/RegistryObject/RegistryObject_test.cpp 2014-12-02 15:31:29 +0000
1724+++ test/gtest/scopes/internal/RegistryObject/RegistryObject_test.cpp 2015-01-26 17:27:30 +0000
1725@@ -91,6 +91,10 @@
1726 MOCK_METHOD3(preview, QueryCtrlProxy(Result const&,
1727 ActionMetadata const&,
1728 PreviewListenerBase::SPtr const&));
1729+
1730+ MOCK_METHOD0(child_scopes_ordered, ChildScopeList());
1731+
1732+ MOCK_METHOD1(set_child_scopes_ordered, bool(ChildScopeList const&));
1733 };
1734
1735
1736
1737=== modified file 'test/gtest/scopes/internal/zmq_middleware/ZmqMiddleware/ZmqMiddleware_test.cpp'
1738--- test/gtest/scopes/internal/zmq_middleware/ZmqMiddleware/ZmqMiddleware_test.cpp 2014-08-12 13:26:35 +0000
1739+++ test/gtest/scopes/internal/zmq_middleware/ZmqMiddleware/ZmqMiddleware_test.cpp 2015-01-26 17:27:30 +0000
1740@@ -453,6 +453,16 @@
1741 return nullptr;
1742 }
1743
1744+ virtual ChildScopeList child_scopes_ordered() const override
1745+ {
1746+ return ChildScopeList();
1747+ }
1748+
1749+ virtual bool set_child_scopes_ordered(ChildScopeList const&) override
1750+ {
1751+ return false;
1752+ }
1753+
1754 virtual bool debug_mode() const override
1755 {
1756 return false;

Subscribers

People subscribed via source and target branches

to all changes: