Merge lp:~marcustomlinson/unity-scopes-api/metadata_isaggregator_attr into lp:unity-scopes-api/devel
- metadata_isaggregator_attr
- Merge into devel
Status: | Merged |
---|---|
Approved by: | Michi Henning |
Approved revision: | 568 |
Merged at revision: | 555 |
Proposed branch: | lp:~marcustomlinson/unity-scopes-api/metadata_isaggregator_attr |
Merge into: | lp:unity-scopes-api/devel |
Prerequisite: | lp:~marcustomlinson/unity-scopes-api/rename_tags_to_keywords |
Diff against target: |
565 lines (+114/-6) 20 files modified
CONFIGFILES (+4/-0) RELEASE_NOTES.md (+2/-1) STRUCTS (+1/-0) debian/changelog (+3/-2) debian/libunity-scopes3.symbols (+5/-0) include/unity/scopes/ScopeMetadata.h (+6/-0) include/unity/scopes/internal/ScopeConfig.h (+2/-0) include/unity/scopes/internal/ScopeMetadataImpl.h (+3/-0) include/unity/scopes/testing/ScopeMetadataBuilder.h (+1/-0) scoperegistry/scoperegistry.cpp (+1/-0) src/scopes/ScopeMetadata.cpp (+5/-0) src/scopes/internal/ScopeConfig.cpp (+17/-1) src/scopes/internal/ScopeMetadataImpl.cpp (+29/-0) src/scopes/testing/ScopeMetadataBuilder.cpp (+9/-0) test/gtest/scopes/Registry/Registry_test.cpp (+2/-0) test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.ini.in (+1/-0) test/gtest/scopes/internal/ScopeConfig/ScopeConfig_test.cpp (+3/-0) test/gtest/scopes/internal/ScopeConfig/complete_config.ini.in (+1/-0) test/gtest/scopes/internal/ScopeMetadataImpl/ScopeMetadataImpl_test.cpp (+16/-1) test/gtest/scopes/testing/IsolatedScope/IsolatedScope_test.cpp (+3/-1) |
To merge this branch: | bzr merge lp:~marcustomlinson/unity-scopes-api/metadata_isaggregator_attr |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Michi Henning (community) | Approve | ||
Review via email: mp+243518@code.launchpad.net |
Commit message
Added support for IsAggregator scope .ini option.
Description of the change
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:567
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Michi Henning (michihenning) wrote : | # |
Looks fine, but don't we need to distinguish SAs from GAs in the shell? In particular, how do we prevent the creation of loops with GAs? My suggestion was to never allow a GA to aggregate another GA. That way, loops are not possible, assuming that SAs won't ever aggregate from a GA. I suspect we may need to put some special magic in place to guarantee this can't happen.
But, to me, it looks like we really need and enum for this attribute, not a boolean?
Marcus Tomlinson (marcustomlinson) wrote : | # |
> Looks fine, but don't we need to distinguish SAs from GAs in the shell? In
> particular, how do we prevent the creation of loops with GAs? My suggestion
> was to never allow a GA to aggregate another GA. That way, loops are not
> possible, assuming that SAs won't ever aggregate from a GA. I suspect we may
> need to put some special magic in place to guarantee this can't happen.
>
> But, to me, it looks like we really need and enum for this attribute, not a
> boolean?
Had a chat with the others in the standup this morning and there is a majority vote not to differentiate between GAs and SAs (at least not via this attribute). The general consensus is that we should keep the interface as generic as possible without introducing a concept of different kinds of aggregators. I think if there is any way to avoid this, we should. Our current design allows for the aggregator type to be transparent.
About the infinite loop thing. I don't see a way we can entirely avoid this as an SA may aggregate another SA that aggregates its parent again. Now that we're intruding aggregation via tags, this becomes quite possible unfortunately. I think this problem really doesn't have anything to do with what type of aggregator is involved. Its really a separate issue we need to address. The consensus of the team is to implement a simple hop count with a limit. I do believe we still have the problem whereby too many layers of aggregation will cause a deadlock from thread starvation, so we should probably implement this anyway (https:/
Michi Henning (michihenning) wrote : | # |
For SA's, we are probably a lot safer, because these aren't constructed willy-nilly on the fly.
For GA's, I think that's a real problem. What is this going to look like to the user? They make an aggregator that introduces a loop, and the queries will time out, without producing results, most likely. The user gets to see something that simply doesn't work, with no real idea of how to diagnose or remedy the problem.
Too many layers cannot cause deadlock. Rather, they'll cause queries to time out.
Even if we have loop detection of some kind, how should it behave? Detecting the loop doesn't solve the problem because, when we detect a loop, the user is still presented with a query that doesn't work. What we would need isn't loop detection, but "loop repair". The only way to fix this that I can see would be to track all scopes that are currently involved in a query and, if a subquery() goes to a scope that is already in the loop, not forward that subquery.
Doing this will be somewhat intrusive. At the very least, we would need a change at the protocol level that adds the IDs of all scopes involved so far to the search request on the wire.
Marcus Tomlinson (marcustomlinson) wrote : | # |
> For SA's, we are probably a lot safer, because these aren't constructed willy-
> nilly on the fly.
>
> For GA's, I think that's a real problem. What is this going to look like to
> the user? They make an aggregator that introduces a loop, and the queries will
> time out, without producing results, most likely. The user gets to see
> something that simply doesn't work, with no real idea of how to diagnose or
> remedy the problem.
>
> Too many layers cannot cause deadlock. Rather, they'll cause queries to time
> out.
>
> Even if we have loop detection of some kind, how should it behave? Detecting
> the loop doesn't solve the problem because, when we detect a loop, the user is
> still presented with a query that doesn't work. What we would need isn't loop
> detection, but "loop repair". The only way to fix this that I can see would be
> to track all scopes that are currently involved in a query and, if a
> subquery() goes to a scope that is already in the loop, not forward that
> subquery.
>
> Doing this will be somewhat intrusive. At the very least, we would need a
> change at the protocol level that adds the IDs of all scopes involved so far
> to the search request on the wire.
So the issue here is that aggregators can cause loops. I don't see that its really a problem specific to GAs or SAs. Now that we're introducing the concept of aggregation by keywords, SAs too become vulnerable to loops created on the fly.
Consider a News SA that aggregates all scopes with the keyword "news". Then we create a Ubuntu News SA (tagged "news") that also aggregates all scope with the keyword "news" but forwards the query "Ubuntu" to each. Perhaps the Ubuntu News scope also pushes some of its own unique results.
With the "loop repair" approach we will end up with the News scope showing only the unique results from Ubuntu News, and we won't see the Ubuntu News scope appearing under the Ubuntu News itself. That sounds like a pretty cool result.
So yeah, I'm leaning towards us implementing loop repair.
Marcus Tomlinson (marcustomlinson) wrote : | # |
Actually, its only the aggregators (identified by this config key) that we need to keep in the list of visited scopes. Looking back at my previous example, I think its totally valid that the Ubuntu News scope shows its "Ubuntu" specific results of the same leaf scopes its parent (News) has.
So the second-to-last paragraph of my last comment will change to:
With the "loop repair" approach we will end up with the News scope showing all of its regular child scopes' results, along with an "Ubuntu News" category under which all the "Ubuntu" specific results for the same children are shown. We also won't see the Ubuntu News scope appearing under Ubuntu News itself, nor the News scope showing under News either.
Michi Henning (michihenning) wrote : | # |
OK, sounds like a boolean will do in conjunction with detecting and axing off cycles.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
- 568. By Marcus Tomlinson
-
Merged devel and resolved conflicts
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:568
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Michi Henning (michihenning) wrote : | # |
OK, tests pass, so I assume the conflict resolution didn't break anything :-)
PS Jenkins bot (ps-jenkins) : | # |
Preview Diff
1 | === modified file 'CONFIGFILES' |
2 | --- CONFIGFILES 2014-12-03 07:31:22 +0000 |
3 | +++ CONFIGFILES 2014-12-08 08:09:05 +0000 |
4 | @@ -411,6 +411,10 @@ |
5 | |
6 | Note: make sure there are no trailing spaces following the keywords, as they will be preserved. |
7 | |
8 | +- IsAggregator |
9 | + |
10 | + Whether the scope is an aggregator. The default value is false. |
11 | + |
12 | |
13 | The following keys are recognized in the Appearance group: |
14 | |
15 | |
16 | === modified file 'RELEASE_NOTES.md' |
17 | --- RELEASE_NOTES.md 2014-12-03 06:53:40 +0000 |
18 | +++ RELEASE_NOTES.md 2014-12-08 08:09:05 +0000 |
19 | @@ -3,7 +3,8 @@ |
20 | |
21 | Changes in version 0.6.10 |
22 | ========================= |
23 | - - Renamed "Tags" scope .ini option to "Keywords" |
24 | + - Renamed "Tags" scope .ini option to "Keywords". |
25 | + - Added support for IsAggregator scope .ini option. |
26 | |
27 | Changes in version 0.6.9 |
28 | ======================== |
29 | |
30 | === modified file 'STRUCTS' |
31 | --- STRUCTS 2014-12-03 07:31:22 +0000 |
32 | +++ STRUCTS 2014-12-08 08:09:05 +0000 |
33 | @@ -80,6 +80,7 @@ |
34 | 'child_scopes' : array of strings, optional |
35 | 'version' : int, optional |
36 | 'keywords' : array of strings, optional |
37 | + 'is_aggregator' : bool, optional |
38 | |
39 | Query (returned by serialize()) |
40 | =============================== |
41 | |
42 | === modified file 'debian/changelog' |
43 | --- debian/changelog 2014-12-03 06:53:40 +0000 |
44 | +++ debian/changelog 2014-12-08 08:09:05 +0000 |
45 | @@ -1,8 +1,9 @@ |
46 | unity-scopes-api (0.6.10-0ubuntu1) UNRELEASED; urgency=medium |
47 | |
48 | - * Renamed "Tags" scope .ini option to "Keywords" |
49 | + * Renamed "Tags" scope .ini option to "Keywords". |
50 | + * Added support for IsAggregator scope .ini option. |
51 | |
52 | - -- Marcus Tomlinson <marcus.tomlinson@canonical.com> Wed, 03 Dec 2014 08:32:29 +0200 |
53 | + -- Marcus Tomlinson <marcus.tomlinson@canonical.com> Wed, 03 Dec 2014 09:47:07 +0200 |
54 | |
55 | unity-scopes-api (0.6.9+15.04.20141129-0ubuntu1) vivid; urgency=medium |
56 | |
57 | |
58 | === modified file 'debian/libunity-scopes3.symbols' |
59 | --- debian/libunity-scopes3.symbols 2014-12-05 08:11:13 +0000 |
60 | +++ debian/libunity-scopes3.symbols 2014-12-08 08:09:05 +0000 |
61 | @@ -450,6 +450,7 @@ |
62 | (c++)"unity::scopes::internal::ScopeConfig::icon() const@Base" 0.4.0+14.04.20140312.1 |
63 | (c++)"unity::scopes::internal::ScopeConfig::idle_timeout() const@Base" 0.4.5+14.10.20140513 |
64 | (c++)"unity::scopes::internal::ScopeConfig::invisible() const@Base" 0.4.0+14.04.20140312.1 |
65 | + (c++)"unity::scopes::internal::ScopeConfig::is_aggregator() const@Base" 0replaceme |
66 | (c++)"unity::scopes::internal::ScopeConfig::keywords() const@Base" 0.6.9+15.04.20141129 |
67 | (c++)"unity::scopes::internal::ScopeConfig::location_data_needed() const@Base" 0.5.2+14.10.20140709.2 |
68 | (c++)"unity::scopes::internal::ScopeConfig::overrideable() const@Base" 0.4.0+14.04.20140312.1 |
69 | @@ -491,6 +492,7 @@ |
70 | (c++)"unity::scopes::internal::ScopeMetadataImpl::hot_key() const@Base" 0.4.0+14.04.20140312.1 |
71 | (c++)"unity::scopes::internal::ScopeMetadataImpl::icon() const@Base" 0.4.0+14.04.20140312.1 |
72 | (c++)"unity::scopes::internal::ScopeMetadataImpl::invisible() const@Base" 0.4.0+14.04.20140312.1 |
73 | + (c++)"unity::scopes::internal::ScopeMetadataImpl::is_aggregator() const@Base" 0replaceme |
74 | (c++)"unity::scopes::internal::ScopeMetadataImpl::keywords() const@Base" 0.6.9+15.04.20141129 |
75 | (c++)"unity::scopes::internal::ScopeMetadataImpl::location_data_needed() const@Base" 0.5.2+14.10.20140709.2 |
76 | (c++)"unity::scopes::internal::ScopeMetadataImpl::operator=(unity::scopes::internal::ScopeMetadataImpl const&)@Base" 0.4.0+14.04.20140312.1 |
77 | @@ -512,6 +514,7 @@ |
78 | (c++)"unity::scopes::internal::ScopeMetadataImpl::set_hot_key(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1 |
79 | (c++)"unity::scopes::internal::ScopeMetadataImpl::set_icon(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1 |
80 | (c++)"unity::scopes::internal::ScopeMetadataImpl::set_invisible(bool)@Base" 0.4.0+14.04.20140312.1 |
81 | + (c++)"unity::scopes::internal::ScopeMetadataImpl::set_is_aggregator(bool)@Base" 0replaceme |
82 | (c++)"unity::scopes::internal::ScopeMetadataImpl::set_keywords(std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&)@Base" 0.6.9+15.04.20141129 |
83 | (c++)"unity::scopes::internal::ScopeMetadataImpl::set_location_data_needed(bool)@Base" 0.5.2+14.10.20140709.2 |
84 | (c++)"unity::scopes::internal::ScopeMetadataImpl::set_proxy(std::shared_ptr<unity::scopes::Scope> const&)@Base" 0.4.0+14.04.20140312.1 |
85 | @@ -777,6 +780,7 @@ |
86 | (c++)"unity::scopes::ScopeMetadata::hot_key() const@Base" 0.4.0+14.04.20140312.1 |
87 | (c++)"unity::scopes::ScopeMetadata::icon() const@Base" 0.4.0+14.04.20140312.1 |
88 | (c++)"unity::scopes::ScopeMetadata::invisible() const@Base" 0.4.0+14.04.20140312.1 |
89 | + (c++)"unity::scopes::ScopeMetadata::is_aggregator() const@Base" 0replaceme |
90 | (c++)"unity::scopes::ScopeMetadata::keywords() const@Base" 0.6.9+15.04.20141129 |
91 | (c++)"unity::scopes::ScopeMetadata::location_data_needed() const@Base" 0.5.2+14.10.20140709.2 |
92 | (c++)"unity::scopes::ScopeMetadata::operator=(unity::scopes::ScopeMetadata&&)@Base" 0.4.0+14.04.20140312.1 |
93 | @@ -870,6 +874,7 @@ |
94 | (c++)"unity::scopes::testing::ScopeMetadataBuilder::hot_key(unity::scopes::testing::ScopeMetadataBuilder::Optional<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&)@Base" 0.4.0+14.04.20140312.1 |
95 | (c++)"unity::scopes::testing::ScopeMetadataBuilder::icon(unity::scopes::testing::ScopeMetadataBuilder::Optional<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&)@Base" 0.4.0+14.04.20140312.1 |
96 | (c++)"unity::scopes::testing::ScopeMetadataBuilder::invisible(unity::scopes::testing::ScopeMetadataBuilder::Optional<bool> const&)@Base" 0.5.0+14.10.20140619 |
97 | + (c++)"unity::scopes::testing::ScopeMetadataBuilder::is_aggregator(unity::scopes::testing::ScopeMetadataBuilder::Optional<bool> const&)@Base" 0replaceme |
98 | (c++)"unity::scopes::testing::ScopeMetadataBuilder::keywords(unity::scopes::testing::ScopeMetadataBuilder::Optional<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > const&)@Base" 0.6.9+15.04.20141129 |
99 | (c++)"unity::scopes::testing::ScopeMetadataBuilder::location_data_needed(unity::scopes::testing::ScopeMetadataBuilder::Optional<bool> const&)@Base" 0.6.9+15.04.20141129 |
100 | (c++)"unity::scopes::testing::ScopeMetadataBuilder::operator()() const@Base" 0.4.0+14.04.20140312.1 |
101 | |
102 | === modified file 'include/unity/scopes/ScopeMetadata.h' |
103 | --- include/unity/scopes/ScopeMetadata.h 2014-12-03 06:53:40 +0000 |
104 | +++ include/unity/scopes/ScopeMetadata.h 2014-12-08 08:09:05 +0000 |
105 | @@ -213,6 +213,12 @@ |
106 | */ |
107 | std::vector<std::string> keywords() const; |
108 | |
109 | + /** |
110 | + \brief Check if this scope is an aggregator. |
111 | + \return True if this scope is an aggregator. |
112 | + */ |
113 | + bool is_aggregator() const; // optional (default = false) |
114 | + |
115 | private: |
116 | ScopeMetadata(std::unique_ptr<internal::ScopeMetadataImpl>); // Instantiable only by ScopeMetadataImpl |
117 | std::unique_ptr<internal::ScopeMetadataImpl> p; |
118 | |
119 | === modified file 'include/unity/scopes/internal/ScopeConfig.h' |
120 | --- include/unity/scopes/internal/ScopeConfig.h 2014-12-03 06:53:40 +0000 |
121 | +++ include/unity/scopes/internal/ScopeConfig.h 2014-12-08 08:09:05 +0000 |
122 | @@ -55,6 +55,7 @@ |
123 | std::vector<std::string> child_scope_ids() const; // Optional, returns an empty vector if no ids are present |
124 | int version() const; // Optional, returns 0 if not present |
125 | std::vector<std::string> keywords() const; // Optional, returns an empty vector if no keywords are present |
126 | + bool is_aggregator() const; // Optional, returns false if not present |
127 | |
128 | VariantMap appearance_attributes() const; // Optional, returns empty map if no attributes are present |
129 | |
130 | @@ -78,6 +79,7 @@ |
131 | std::vector<std::string> child_scope_ids_; |
132 | int version_; |
133 | std::vector<std::string> keywords_; |
134 | + bool is_aggregator_; |
135 | |
136 | VariantMap appearance_attributes_; |
137 | }; |
138 | |
139 | === modified file 'include/unity/scopes/internal/ScopeMetadataImpl.h' |
140 | --- include/unity/scopes/internal/ScopeMetadataImpl.h 2014-12-03 06:53:40 +0000 |
141 | +++ include/unity/scopes/internal/ScopeMetadataImpl.h 2014-12-08 08:09:05 +0000 |
142 | @@ -60,6 +60,7 @@ |
143 | std::vector<std::string> child_scope_ids() const; // optional (default: empty array) |
144 | int version() const; // optional (default: 0) |
145 | std::vector<std::string> keywords() const; // optional (default: empty array) |
146 | + bool is_aggregator() const; // optional (default: false) |
147 | |
148 | void set_scope_id(std::string const& scope_id); |
149 | void set_proxy(ScopeProxy const& proxy); |
150 | @@ -79,6 +80,7 @@ |
151 | void set_child_scope_ids(std::vector<std::string> const& ids); |
152 | void set_version(int v); |
153 | void set_keywords(std::vector<std::string> const& keywords); |
154 | + void set_is_aggregator(bool is_aggregator); |
155 | |
156 | VariantMap serialize() const; |
157 | void deserialize(VariantMap const& var); |
158 | @@ -106,6 +108,7 @@ |
159 | std::vector<std::string> child_scope_ids_; |
160 | int version_; |
161 | std::vector<std::string> keywords_; |
162 | + std::unique_ptr<bool> is_aggregator_; // Optional, hence a pointer |
163 | }; |
164 | |
165 | } // namespace internal |
166 | |
167 | === modified file 'include/unity/scopes/testing/ScopeMetadataBuilder.h' |
168 | --- include/unity/scopes/testing/ScopeMetadataBuilder.h 2014-12-03 06:53:40 +0000 |
169 | +++ include/unity/scopes/testing/ScopeMetadataBuilder.h 2014-12-08 08:09:05 +0000 |
170 | @@ -98,6 +98,7 @@ |
171 | ScopeMetadataBuilder& child_scope_ids(Optional<std::vector<std::string>> const& value); |
172 | ScopeMetadataBuilder& version(Optional<int> const& value); |
173 | ScopeMetadataBuilder& keywords(Optional<std::vector<std::string>> const& value); |
174 | + ScopeMetadataBuilder& is_aggregator(Optional<bool> const& value); |
175 | |
176 | ScopeMetadata operator()() const; |
177 | |
178 | |
179 | === modified file 'scoperegistry/scoperegistry.cpp' |
180 | --- scoperegistry/scoperegistry.cpp 2014-12-03 06:53:40 +0000 |
181 | +++ scoperegistry/scoperegistry.cpp 2014-12-08 08:09:05 +0000 |
182 | @@ -320,6 +320,7 @@ |
183 | mi->set_child_scope_ids(sc.child_scope_ids()); |
184 | mi->set_version(sc.version()); |
185 | mi->set_keywords(sc.keywords()); |
186 | + mi->set_is_aggregator(sc.is_aggregator()); |
187 | |
188 | // Prepend scope_dir to pageheader logo path if logo path is relative. |
189 | // TODO: Once we have type-safe parsing in the config files, remove |
190 | |
191 | === modified file 'src/scopes/ScopeMetadata.cpp' |
192 | --- src/scopes/ScopeMetadata.cpp 2014-12-03 06:53:40 +0000 |
193 | +++ src/scopes/ScopeMetadata.cpp 2014-12-08 08:09:05 +0000 |
194 | @@ -162,6 +162,11 @@ |
195 | return p->keywords(); |
196 | } |
197 | |
198 | +bool ScopeMetadata::is_aggregator() const |
199 | +{ |
200 | + return p->is_aggregator(); |
201 | +} |
202 | + |
203 | //! @endcond |
204 | |
205 | } // namespace scopes |
206 | |
207 | === modified file 'src/scopes/internal/ScopeConfig.cpp' |
208 | --- src/scopes/internal/ScopeConfig.cpp 2014-12-03 06:53:40 +0000 |
209 | +++ src/scopes/internal/ScopeConfig.cpp 2014-12-08 08:09:05 +0000 |
210 | @@ -58,6 +58,7 @@ |
211 | const string child_scope_ids_key = "ChildScopes"; |
212 | const string version_key = "Version"; |
213 | const string keywords_key = "Keywords"; |
214 | + const string is_aggregator_key = "IsAggregator"; |
215 | |
216 | const string scope_appearance_group = "Appearance"; |
217 | const string fg_color_key = "ForegroundColor"; |
218 | @@ -239,6 +240,15 @@ |
219 | |
220 | try |
221 | { |
222 | + is_aggregator_ = parser()->get_boolean(scope_config_group, is_aggregator_key); |
223 | + } |
224 | + catch (LogicException const&) |
225 | + { |
226 | + is_aggregator_ = false; |
227 | + } |
228 | + |
229 | + try |
230 | + { |
231 | debug_mode_ = parser()->get_boolean(scope_config_group, debug_mode_key); |
232 | } |
233 | catch (LogicException const&) |
234 | @@ -277,7 +287,8 @@ |
235 | debug_mode_key, |
236 | child_scope_ids_key, |
237 | version_key, |
238 | - keywords_key |
239 | + keywords_key, |
240 | + is_aggregator_key |
241 | } |
242 | }, |
243 | { scope_appearance_group, |
244 | @@ -466,6 +477,11 @@ |
245 | return keywords_; |
246 | } |
247 | |
248 | +bool ScopeConfig::is_aggregator() const |
249 | +{ |
250 | + return is_aggregator_; |
251 | +} |
252 | + |
253 | } // namespace internal |
254 | |
255 | } // namespace scopes |
256 | |
257 | === modified file 'src/scopes/internal/ScopeMetadataImpl.cpp' |
258 | --- src/scopes/internal/ScopeMetadataImpl.cpp 2014-12-03 06:53:40 +0000 |
259 | +++ src/scopes/internal/ScopeMetadataImpl.cpp 2014-12-08 08:09:05 +0000 |
260 | @@ -95,6 +95,10 @@ |
261 | { |
262 | location_data_needed_.reset(new bool(*other.location_data_needed_)); |
263 | } |
264 | + if (other.is_aggregator_) |
265 | + { |
266 | + is_aggregator_.reset(new bool(*other.is_aggregator_)); |
267 | + } |
268 | } |
269 | |
270 | ScopeMetadataImpl& ScopeMetadataImpl::operator=(ScopeMetadataImpl const& rhs) |
271 | @@ -120,6 +124,7 @@ |
272 | child_scope_ids_ = rhs.child_scope_ids_; |
273 | version_ = rhs.version_; |
274 | keywords_ = rhs.keywords_; |
275 | + is_aggregator_.reset(rhs.is_aggregator_ ? new bool(*rhs.is_aggregator_) : nullptr); |
276 | } |
277 | return *this; |
278 | } |
279 | @@ -246,6 +251,15 @@ |
280 | return keywords_; |
281 | } |
282 | |
283 | +bool ScopeMetadataImpl::is_aggregator() const |
284 | +{ |
285 | + if (is_aggregator_) |
286 | + { |
287 | + return *is_aggregator_; |
288 | + } |
289 | + return false; |
290 | +} |
291 | + |
292 | void ScopeMetadataImpl::set_scope_id(std::string const& scope_id) |
293 | { |
294 | scope_id_ = scope_id; |
295 | @@ -321,6 +335,11 @@ |
296 | location_data_needed_.reset(new bool(location_data_needed)); |
297 | } |
298 | |
299 | +void ScopeMetadataImpl::set_is_aggregator(bool is_aggregator) |
300 | +{ |
301 | + is_aggregator_.reset(new bool(is_aggregator)); |
302 | +} |
303 | + |
304 | void ScopeMetadataImpl::set_child_scope_ids(std::vector<std::string> const& ids) |
305 | { |
306 | child_scope_ids_ = ids; |
307 | @@ -434,6 +453,10 @@ |
308 | } |
309 | var["keywords"] = Variant(va); |
310 | } |
311 | + if (is_aggregator_) |
312 | + { |
313 | + var["is_aggregator"] = *is_aggregator_; |
314 | + } |
315 | |
316 | return var; |
317 | } |
318 | @@ -588,6 +611,12 @@ |
319 | keywords_.push_back(v.get_string()); |
320 | } |
321 | } |
322 | + |
323 | + it = var.find("is_aggregator"); |
324 | + if (it != var.end()) |
325 | + { |
326 | + is_aggregator_.reset(new bool(it->second.get_bool())); |
327 | + } |
328 | } |
329 | |
330 | ScopeMetadata ScopeMetadataImpl::create(unique_ptr<ScopeMetadataImpl> impl) |
331 | |
332 | === modified file 'src/scopes/testing/ScopeMetadataBuilder.cpp' |
333 | --- src/scopes/testing/ScopeMetadataBuilder.cpp 2014-12-03 06:53:40 +0000 |
334 | +++ src/scopes/testing/ScopeMetadataBuilder.cpp 2014-12-08 08:09:05 +0000 |
335 | @@ -49,6 +49,7 @@ |
336 | Optional<std::vector<std::string>> child_scope_ids; |
337 | Optional<int> version; |
338 | Optional<std::vector<std::string>> keywords; |
339 | + Optional<bool> is_aggregator; |
340 | }; |
341 | |
342 | testing::ScopeMetadataBuilder::ScopeMetadataBuilder() : p(new Private()) |
343 | @@ -167,6 +168,12 @@ |
344 | return *this; |
345 | } |
346 | |
347 | +testing::ScopeMetadataBuilder& testing::ScopeMetadataBuilder::is_aggregator(Optional<bool> const& value) |
348 | +{ |
349 | + p->is_aggregator = value; |
350 | + return *this; |
351 | +} |
352 | + |
353 | unity::scopes::ScopeMetadata testing::ScopeMetadataBuilder::operator()() const |
354 | { |
355 | auto impl = new unity::scopes::internal::ScopeMetadataImpl(Private::invalid_middleware); |
356 | @@ -202,6 +209,8 @@ |
357 | impl->set_version(*p->version); |
358 | if (p->keywords) |
359 | impl->set_keywords(*p->keywords); |
360 | + if (p->is_aggregator) |
361 | + impl->set_is_aggregator(*p->is_aggregator); |
362 | |
363 | return unity::scopes::internal::ScopeMetadataImpl::create( |
364 | std::move( |
365 | |
366 | === modified file 'test/gtest/scopes/Registry/Registry_test.cpp' |
367 | --- test/gtest/scopes/Registry/Registry_test.cpp 2014-12-03 06:53:40 +0000 |
368 | +++ test/gtest/scopes/Registry/Registry_test.cpp 2014-12-08 08:09:05 +0000 |
369 | @@ -116,6 +116,7 @@ |
370 | EXPECT_EQ("music", keywords[0]); |
371 | EXPECT_EQ("news", keywords[1]); |
372 | EXPECT_EQ("foo", keywords[2]); |
373 | + EXPECT_FALSE(meta.is_aggregator()); |
374 | |
375 | auto attrs = meta.appearance_attributes(); |
376 | EXPECT_EQ("fg_color", attrs["foreground-color"].get_string()); |
377 | @@ -149,6 +150,7 @@ |
378 | EXPECT_EQ(0, meta.child_scope_ids().size()); |
379 | EXPECT_EQ(0, meta.keywords().size()); |
380 | EXPECT_EQ(0, meta.version()); |
381 | + EXPECT_FALSE(meta.is_aggregator()); |
382 | } |
383 | |
384 | auto const wait_for_update_time = std::chrono::milliseconds(5000); |
385 | |
386 | === modified file 'test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.ini.in' |
387 | --- test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.ini.in 2014-12-03 06:53:40 +0000 |
388 | +++ test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.ini.in 2014-12-08 08:09:05 +0000 |
389 | @@ -10,6 +10,7 @@ |
390 | ChildScopes = com.foo.bar;com.foo.baz |
391 | Version = 1 |
392 | Keywords = music;news;foo |
393 | +IsAggregator = false |
394 | |
395 | [Appearance] |
396 | ForegroundColor = fg_color |
397 | |
398 | === modified file 'test/gtest/scopes/internal/ScopeConfig/ScopeConfig_test.cpp' |
399 | --- test/gtest/scopes/internal/ScopeConfig/ScopeConfig_test.cpp 2014-12-03 06:53:40 +0000 |
400 | +++ test/gtest/scopes/internal/ScopeConfig/ScopeConfig_test.cpp 2014-12-08 08:09:05 +0000 |
401 | @@ -62,6 +62,8 @@ |
402 | EXPECT_EQ("foo", keywords[0]); |
403 | EXPECT_EQ("bar", keywords[1]); |
404 | |
405 | + EXPECT_TRUE(cfg.is_aggregator()); |
406 | + |
407 | auto attrs = cfg.appearance_attributes(); |
408 | EXPECT_EQ(5, attrs.size()); |
409 | EXPECT_TRUE(attrs["arbitrary_key"].get_bool()); |
410 | @@ -93,6 +95,7 @@ |
411 | EXPECT_FALSE(cfg.location_data_needed()); |
412 | EXPECT_FALSE(cfg.debug_mode()); |
413 | EXPECT_EQ(0, cfg.version()); |
414 | + EXPECT_FALSE(cfg.is_aggregator()); |
415 | |
416 | EXPECT_EQ(0, cfg.appearance_attributes().size()); |
417 | |
418 | |
419 | === modified file 'test/gtest/scopes/internal/ScopeConfig/complete_config.ini.in' |
420 | --- test/gtest/scopes/internal/ScopeConfig/complete_config.ini.in 2014-12-03 06:53:40 +0000 |
421 | +++ test/gtest/scopes/internal/ScopeConfig/complete_config.ini.in 2014-12-08 08:09:05 +0000 |
422 | @@ -20,6 +20,7 @@ |
423 | Version = 1 |
424 | ChildScopes = com.foo.bar;com.foo.bar2;com.foo.boo |
425 | Keywords = foo;bar |
426 | +IsAggregator = true |
427 | |
428 | [Appearance] |
429 | arbitrary_key = true |
430 | |
431 | === modified file 'test/gtest/scopes/internal/ScopeMetadataImpl/ScopeMetadataImpl_test.cpp' |
432 | --- test/gtest/scopes/internal/ScopeMetadataImpl/ScopeMetadataImpl_test.cpp 2014-12-03 06:53:40 +0000 |
433 | +++ test/gtest/scopes/internal/ScopeMetadataImpl/ScopeMetadataImpl_test.cpp 2014-12-08 08:09:05 +0000 |
434 | @@ -134,6 +134,9 @@ |
435 | // when "version" is not set, 0 is returned |
436 | EXPECT_EQ(0, m.version()); |
437 | |
438 | + // when "is_aggregator" is not set, false is returned |
439 | + EXPECT_FALSE(m.is_aggregator()); |
440 | + |
441 | // Check that the copy has the same values as the original |
442 | EXPECT_EQ("scope_id", mi2->scope_id()); |
443 | EXPECT_EQ("identity", mi2->proxy()->identity()); |
444 | @@ -163,6 +166,7 @@ |
445 | mi2->set_location_data_needed(true); |
446 | mi2->set_child_scope_ids(vector<string>{"abc", "def"}); |
447 | mi2->set_keywords(vector<string>{"music", "video", "news"}); |
448 | + mi2->set_is_aggregator(true); |
449 | |
450 | // Make another copy, so we get coverage on the entire copy constructor |
451 | unique_ptr<ScopeMetadataImpl> mi3(new ScopeMetadataImpl(*mi2)); |
452 | @@ -177,6 +181,7 @@ |
453 | EXPECT_TRUE(m.location_data_needed()); |
454 | EXPECT_EQ((vector<string>{"abc", "def"}), m.child_scope_ids()); |
455 | EXPECT_EQ((vector<string>{"music", "video", "news"}), m.keywords()); |
456 | + EXPECT_TRUE(m.is_aggregator()); |
457 | |
458 | // Make another value |
459 | unique_ptr<ScopeMetadataImpl> ti(new ScopeMetadataImpl(&mw)); |
460 | @@ -201,6 +206,7 @@ |
461 | ti->set_location_data_needed(true); |
462 | ti->set_child_scope_ids(vector<string>{"tmp abc", "tmp def"}); |
463 | ti->set_keywords(vector<string>{"music", "video"}); |
464 | + ti->set_is_aggregator(true); |
465 | |
466 | // Check impl assignment operator |
467 | ScopeMetadataImpl ci(&mw); |
468 | @@ -224,6 +230,7 @@ |
469 | EXPECT_EQ((vector<string>{"tmp abc", "tmp def"}), ci.child_scope_ids()); |
470 | EXPECT_EQ(99, ci.version()); |
471 | EXPECT_EQ((vector<string>{"music", "video"}), ci.keywords()); |
472 | + EXPECT_TRUE(ci.is_aggregator()); |
473 | |
474 | // Check public assignment operator |
475 | auto tmp = ScopeMetadataImpl::create(move(ti)); |
476 | @@ -247,6 +254,7 @@ |
477 | EXPECT_TRUE(m.location_data_needed()); |
478 | EXPECT_EQ((vector<string>{"tmp abc", "tmp def"}), m.child_scope_ids()); |
479 | EXPECT_EQ((vector<string>{"music", "video"}), m.keywords()); |
480 | + EXPECT_TRUE(m.is_aggregator()); |
481 | |
482 | // Self-assignment |
483 | tmp = tmp; |
484 | @@ -269,6 +277,7 @@ |
485 | EXPECT_TRUE(tmp.location_data_needed()); |
486 | EXPECT_EQ((vector<string>{"tmp abc", "tmp def"}), tmp.child_scope_ids()); |
487 | EXPECT_EQ((vector<string>{"music", "video"}), tmp.keywords()); |
488 | + EXPECT_TRUE(tmp.is_aggregator()); |
489 | |
490 | // Copy constructor |
491 | ScopeMetadata tmp2(tmp); |
492 | @@ -291,6 +300,7 @@ |
493 | EXPECT_TRUE(tmp2.location_data_needed()); |
494 | EXPECT_EQ((vector<string>{"tmp abc", "tmp def"}), tmp2.child_scope_ids()); |
495 | EXPECT_EQ((vector<string>{"music", "video"}), tmp2.keywords()); |
496 | + EXPECT_TRUE(tmp2.is_aggregator()); |
497 | } |
498 | |
499 | TEST(ScopeMetadataImpl, serialize) |
500 | @@ -323,11 +333,12 @@ |
501 | mi->set_location_data_needed(false); |
502 | mi->set_child_scope_ids({"com.foo.bar", "com.foo.baz"}); |
503 | mi->set_keywords({"news", "games"}); |
504 | + mi->set_is_aggregator(false); |
505 | |
506 | // Check that serialize() sets the map values correctly |
507 | auto m = ScopeMetadataImpl::create(move(mi)); |
508 | auto var = m.serialize(); |
509 | - EXPECT_EQ(18u, var.size()); |
510 | + EXPECT_EQ(19u, var.size()); |
511 | EXPECT_EQ("scope_id", var["scope_id"].get_string()); |
512 | EXPECT_EQ("display_name", var["display_name"].get_string()); |
513 | EXPECT_EQ("description", var["description"].get_string()); |
514 | @@ -351,6 +362,7 @@ |
515 | EXPECT_EQ(2u, var["keywords"].get_array().size()); |
516 | EXPECT_EQ("news", var["keywords"].get_array()[0].get_string()); |
517 | EXPECT_EQ("games", var["keywords"].get_array()[1].get_string()); |
518 | + EXPECT_FALSE(var["is_aggregator"].get_bool()); |
519 | |
520 | // Make another instance from the VariantMap and check its fields |
521 | ScopeMetadataImpl c(var, &mw); |
522 | @@ -378,6 +390,7 @@ |
523 | EXPECT_EQ(2u, c.keywords().size()); |
524 | EXPECT_EQ("news", c.keywords()[0]); |
525 | EXPECT_EQ("games", c.keywords()[1]); |
526 | + EXPECT_FALSE(c.is_aggregator()); |
527 | } |
528 | |
529 | TEST(ScopeMetadataImpl, serialize_exceptions) |
530 | @@ -594,6 +607,7 @@ |
531 | m["appearance_attributes"] = appearance; |
532 | m["results_ttl_type"] = 0; |
533 | m["location_data_needed"] = true; |
534 | + m["is_aggregator"] = true; |
535 | |
536 | ScopeMetadataImpl mi(m, &mw); |
537 | mi.deserialize(m); |
538 | @@ -612,4 +626,5 @@ |
539 | EXPECT_EQ(appearance, mi.appearance_attributes()); |
540 | EXPECT_EQ(ScopeMetadata::ResultsTtlType::None, mi.results_ttl_type()); |
541 | EXPECT_TRUE(mi.location_data_needed()); |
542 | + EXPECT_TRUE(mi.is_aggregator()); |
543 | } |
544 | |
545 | === modified file 'test/gtest/scopes/testing/IsolatedScope/IsolatedScope_test.cpp' |
546 | --- test/gtest/scopes/testing/IsolatedScope/IsolatedScope_test.cpp 2014-12-03 06:53:40 +0000 |
547 | +++ test/gtest/scopes/testing/IsolatedScope/IsolatedScope_test.cpp 2014-12-08 08:09:05 +0000 |
548 | @@ -114,7 +114,8 @@ |
549 | .location_data_needed(true) |
550 | .child_scope_ids(child_scope_ids) |
551 | .version(42) |
552 | - .keywords(keywords); |
553 | + .keywords(keywords) |
554 | + .is_aggregator(true); |
555 | unity::scopes::ScopeMetadata metadata = builder(); |
556 | EXPECT_EQ(scope_id, metadata.scope_id()); |
557 | EXPECT_EQ("display_name", metadata.display_name()); |
558 | @@ -133,6 +134,7 @@ |
559 | EXPECT_EQ(child_scope_ids, metadata.child_scope_ids()); |
560 | EXPECT_EQ(42, metadata.version()); |
561 | EXPECT_EQ(keywords, metadata.keywords()); |
562 | + EXPECT_TRUE(metadata.is_aggregator()); |
563 | } |
564 | |
565 | TEST(ScopeMetadataBuilder, construction_in_case_of_missing_mandatory_arguments_aborts) |
FAILED: Continuous integration, rev:566 jenkins. qa.ubuntu. com/job/ unity-scopes- api-devel- ci/1369/ jenkins. qa.ubuntu. com/job/ unity-scopes- api-devel- vivid-amd64- ci/79/console jenkins. qa.ubuntu. com/job/ unity-scopes- api-devel- vivid-armhf- ci/79/console jenkins. qa.ubuntu. com/job/ unity-scopes- api-devel- vivid-i386- ci/79/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- scopes- api-devel- ci/1369/ rebuild
http://