Merge lp:unity-scopes-api/staging into lp:unity-scopes-api
- staging
- Merge into trunk
Proposed by
Paweł Stołowski
Status: | Merged |
---|---|
Approved by: | Pete Woods |
Approved revision: | 284 |
Merged at revision: | 326 |
Proposed branch: | lp:unity-scopes-api/staging |
Merge into: | lp:unity-scopes-api |
Diff against target: |
1359 lines (+414/-183) 24 files modified
CMakeLists.txt (+1/-1) RELEASE_NOTES.md (+4/-0) debian/changelog (+10/-0) debian/libunity-scopes3.symbols (+2/-0) doc/tutorial.dox (+113/-9) include/unity/scopes/Result.h (+6/-0) include/unity/scopes/internal/RegistryObject.h (+7/-0) include/unity/scopes/internal/Utils.h (+2/-0) scoperegistry/scoperegistry.cpp (+8/-19) src/scopes/Result.cpp (+5/-0) src/scopes/internal/RegistryObject.cpp (+38/-5) src/scopes/internal/RuntimeConfig.cpp (+2/-8) src/scopes/internal/RuntimeImpl.cpp (+23/-30) src/scopes/internal/SearchQueryBaseImpl.cpp (+12/-7) src/scopes/internal/Utils.cpp (+63/-24) src/scopes/internal/smartscopes/SmartScopesClient.cpp (+2/-2) test/gtest/scopes/Aggregation/CMakeLists.txt (+0/-39) test/gtest/scopes/OnlineAccountClient/OnlineAccountClient_test.cpp (+2/-0) test/gtest/scopes/Registry/Registry_test.cpp (+1/-1) test/gtest/scopes/internal/RuntimeConfig/CMakeLists.txt (+8/-1) test/gtest/scopes/internal/RuntimeConfig/RuntimeConfig_test.cpp (+35/-35) test/gtest/scopes/internal/Utils/CMakeLists.txt (+1/-0) test/gtest/scopes/internal/Utils/Utils_test.cpp (+68/-2) unity-scopes.map (+1/-0) |
To merge this branch: | bzr merge lp:unity-scopes-api/staging |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Pete Woods (community) | Approve | ||
Review via email:
|
Commit message
Fix LP: 1446499.
Added is_account_login() method to Result.
Documentation updates.
Description of the change
Merge devel.
To post a comment you must log in.
lp:unity-scopes-api/staging
updated
- 284. By Paweł Stołowski
-
Updated changelog.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Pete Woods (pete-woods) : | # |
review:
Approve
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
review:
Approve
(continuous-integration)
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-04-10 07:21:29 +0000 |
3 | +++ CMakeLists.txt 2015-04-23 15:43:14 +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 16) |
9 | +set(UNITY_SCOPES_MICRO 17) |
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-04-10 07:21:29 +0000 |
16 | +++ RELEASE_NOTES.md 2015-04-23 15:43:14 +0000 |
17 | @@ -1,6 +1,10 @@ |
18 | Release notes |
19 | ============= |
20 | |
21 | +Changes in version 0.6.17 |
22 | +========================= |
23 | + - Added is_account_login_result() method to Result class. |
24 | + |
25 | Changes in version 0.6.16 |
26 | ========================= |
27 | - Added support for attaching arbitrary data to CannedQuery. |
28 | |
29 | === modified file 'debian/changelog' |
30 | --- debian/changelog 2015-04-10 18:55:46 +0000 |
31 | +++ debian/changelog 2015-04-23 15:43:14 +0000 |
32 | @@ -1,3 +1,13 @@ |
33 | +unity-scopes-api (0.6.17-0ubuntu1) UNRELEASED; urgency=medium |
34 | + |
35 | + [ Marcus Tomlinson ] |
36 | + * Added is_account_login_result() method to Result class. |
37 | + |
38 | + [ Pawel Stolowski ] |
39 | + * Fix LP: #1446499. |
40 | + |
41 | + -- Marcus Tomlinson <marcus.tomlinson@canonical.com> Wed, 15 Apr 2015 17:22:07 +0200 |
42 | + |
43 | unity-scopes-api (0.6.16+15.04.20150410.3-0ubuntu1) vivid; urgency=medium |
44 | |
45 | [ Pawel Stolowski ] |
46 | |
47 | === modified file 'debian/libunity-scopes3.symbols' |
48 | --- debian/libunity-scopes3.symbols 2015-04-10 18:55:46 +0000 |
49 | +++ debian/libunity-scopes3.symbols 2015-04-23 15:43:14 +0000 |
50 | @@ -379,6 +379,7 @@ |
51 | (c++)"unity::scopes::internal::JsonSettingsSchema::~JsonSettingsSchema()@Base" 0.5.2+14.10.20140709.2 |
52 | (c++)"unity::scopes::internal::JsonSettingsSchema::JsonSettingsSchema()@Base" 0.6.2+rtm+rtm+rtm+14.09.20140818 |
53 | (c++)"unity::scopes::internal::JsonSettingsSchema::JsonSettingsSchema(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.5.2+14.10.20140709.2 |
54 | + (c++)"unity::scopes::internal::make_directories(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)@Base" 0replaceme |
55 | (c++)"unity::scopes::internal::MiddlewareBase::~MiddlewareBase()@Base" 0.4.0+14.04.20140312.1 |
56 | (c++)"unity::scopes::internal::MiddlewareBase::MiddlewareBase(unity::scopes::internal::RuntimeImpl*)@Base" 0.4.0+14.04.20140312.1 |
57 | (c++)"unity::scopes::internal::MiddlewareBase::runtime() const@Base" 0.4.0+14.04.20140312.1 |
58 | @@ -780,6 +781,7 @@ |
59 | (c++)"unity::scopes::Result::direct_activation() const@Base" 0.4.0+14.04.20140312.1 |
60 | (c++)"unity::scopes::Result::dnd_uri() const@Base" 0.4.0+14.04.20140312.1 |
61 | (c++)"unity::scopes::Result::has_stored_result() const@Base" 0.4.0+14.04.20140312.1 |
62 | + (c++)"unity::scopes::Result::is_account_login_result() const@Base" 0replaceme |
63 | (c++)"unity::scopes::Result::operator[](std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1 |
64 | (c++)"unity::scopes::Result::operator[](std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const@Base" 0.4.0+14.04.20140312.1 |
65 | (c++)"unity::scopes::Result::operator=(unity::scopes::Result&&)@Base" 0.4.0+14.04.20140312.1 |
66 | |
67 | === modified file 'doc/tutorial.dox' |
68 | --- doc/tutorial.dox 2015-02-25 05:20:57 +0000 |
69 | +++ doc/tutorial.dox 2015-04-23 15:43:14 +0000 |
70 | @@ -217,6 +217,51 @@ |
71 | do not return more results than indicated by the cardinality. If you more than the requested number of results, you are |
72 | wasting resources. (The scopes run time ignores the additional results.) |
73 | |
74 | +\paragraph handlingaggregation Handling aggregation |
75 | + |
76 | +As previously stated, SearchMetadata contains additional information about the search requests you receive, including |
77 | +the methods: |
78 | + |
79 | +<ul> |
80 | +<li>\link unity::scopes::SearchMetadata::is_aggregated is_aggregated()\endlink - true if the request was initiated by |
81 | + an aggregator, |
82 | +<li>and \link unity::scopes::SearchMetadata::aggregated_keywords aggregated_keywords()\endlink - the list of keywords |
83 | + used by the aggregator to find your scope. |
84 | +</ul> |
85 | + |
86 | +\note Please refer to the <a href="https://developer.ubuntu.com/en/scopes/tutorials/scope-keywords/">Scope Keywords</a> |
87 | +tutorial document for more detail on using keywords in your scope. |
88 | + |
89 | +You can use the is_aggregated() method from within |
90 | +\link unity::scopes::SearchQueryBase::run SearchQueryBase::run()\endlink in order to ensure that an appropriate set of |
91 | +results are returned when queried by an aggregator: |
92 | + |
93 | +\code{.cpp} |
94 | +void MyQuery::run(SearchReplyProxy const& reply) |
95 | +{ |
96 | + if (metadata_.is_aggregated()) |
97 | + { |
98 | + auto category = reply->register_category("agg_cat", |
99 | + "MyScope Featured", |
100 | + agg_icon); |
101 | + do_aggregated_search(reply, category); |
102 | + } |
103 | + else |
104 | + { |
105 | + do_normal_search(reply); |
106 | + } |
107 | +} |
108 | +\endcode |
109 | + |
110 | +You may notice in the code snippet above that for each aggregated search we receive, we register a specific results |
111 | +category. Although aggregators may be willing to accept more than one category from its child scopes, they are only |
112 | +required to accept the first. |
113 | + |
114 | +Thereafter, an aggregator may choose to ignore any additional categories the child scope registers. It is therefore |
115 | +recommended that scope authors follow the above method of handling aggregated searches. It is also recommended that |
116 | +your scope provide a decent category title (e.g. "MyScope Featured"). An aggregator is likely to display this category |
117 | +title as is within its result set, so try to keep it clean and descriptive. |
118 | + |
119 | \paragraph surfacingmode Surfacing mode |
120 | |
121 | The query string may be the empty string. If so, the UI is asking your scope to produce default results |
122 | @@ -549,7 +594,7 @@ |
123 | of this class to each sub-query; the scopes run time invokes callback methods on this class |
124 | to let you know when a new result or status update arrives, and when a query completes. |
125 | |
126 | -\paragraph childscopes Locating child scopes |
127 | +\paragraph childscopes Finding child scopes |
128 | |
129 | To send queries to its child scopes, your scope must obtain a proxy for each child scope. The scopes run time |
130 | runs a registry process. The job of the registry (among other things) is to provide information about available |
131 | @@ -560,13 +605,55 @@ |
132 | \link unity::scopes::ScopeMetadata ScopeMetadata\endlink that describes the scope and also provides access to the |
133 | proxy for the scope. |
134 | |
135 | +You can also aggregate scopes indirectly via keyword(s). Keywords describe the type of content a scope provides (e.g. |
136 | +a scope with the keyword "music" will return music results, the "video" keyword indicates video content, and so on). |
137 | +You can obtain child scopes via keywords by calling \link unity::scopes::Registry::list_if list_if()\endlink on the |
138 | +registry, supplying a predicate function. The return value is a map containing only those scopes for which the predicate |
139 | +returns true. Therefore, your predicate function should return true for all scopes matching the keyword(s) you wish to |
140 | +aggregate. |
141 | + |
142 | +\note Please refer to the <a href="https://developer.ubuntu.com/en/scopes/tutorials/scope-keywords/">Scope Keywords</a> |
143 | +tutorial document for a list of recommended keywords to use. |
144 | + |
145 | +As an aggregator scope author you must provide an implementation of the virtual |
146 | +\link unity::scopes::ScopeBase::find_child_scopes ScopeBase::find_child_scopes()\endlink method. All logic for finding |
147 | +your aggregator's child scopes should be implemented within this method. The return value is of type |
148 | +\link unity::scopes::ChildScopeList ChildScopeList\endlink and must contain an instance of |
149 | +\link unity::scopes::ChildScope ChildScope\endlink for each scope your aggregator may collect results from. |
150 | + |
151 | +Here is how you could implement find_child_scopes() to return all scopes in the registry that contain the keywords |
152 | +"sports" and "news": |
153 | + |
154 | +\code{.cpp} |
155 | +ChildScopeList MyScope::find_child_scopes() const override |
156 | +{ |
157 | + auto sportsnews_scopes = registry()->list_if([](ScopeMetadata const& item) |
158 | + { |
159 | + auto keywords = item.keywords(); |
160 | + return (keywords.find("sports") != keywords.end()) && |
161 | + (keywords.find("news") != keywords.end()); |
162 | + }); |
163 | + |
164 | + ChildScopeList list; |
165 | + for (auto const& sportsnews_scope : sportsnews_scopes) |
166 | + { |
167 | + list.emplace_back(ChildScope{sportsnews_scope.first, // Child scope ID |
168 | + sportsnews_scope.second, // Child scope metadata |
169 | + true, // Default enabled state (when first discovered) |
170 | + {"sports", "news"}}); // Keywords used to aggregate this scope |
171 | + } |
172 | + return list; |
173 | +} |
174 | +\endcode |
175 | + |
176 | \paragraph subquery Sub-queries |
177 | |
178 | To send a query to another scope, use one of the `subsearch()` overloads of \link unity::scopes::SearchQueryBase\endlink |
179 | inside your implementation of |
180 | \link unity::scopes::SearchQueryBase::run SearchQueryBase::run()\endlink. |
181 | -This method requires the proxy to the child scope to query, the query details (\link unity::scopes::CannedQuery CannedQuery\endlink), plus |
182 | -an instance of your `SearchListenerBase` implementation that will receive the query results. |
183 | +This method requires a handle to the child scope to query (either via proxy or ChildScope handle), the query details |
184 | +(\link unity::scopes::CannedQuery CannedQuery\endlink), plus an instance of your `SearchListenerBase` implementation |
185 | +that will receive the query results. |
186 | |
187 | \note `subsearch()` is identical to |
188 | \link unity::scopes::ScopeBase::search search()\endlink but, for `subsearch()`, the scopes run time transparently |
189 | @@ -575,11 +662,19 @@ |
190 | (However, your query class still needs to react to cancellation and should terminate the current query |
191 | is quickly as possible in response to a cancelled message.) |
192 | |
193 | +You should always call \link unity::scopes::ScopeBase::child_scopes ScopeBase::child_scopes()\endlink from within your |
194 | +aggregator's \link unity::scopes::ScopeBase::search search()\endlink method in order to retrieve the latest child |
195 | +scopes list containing the most recent "enabled" states. You can then pass this list into your instantiation of |
196 | +SearchQueryBase for later use. |
197 | + |
198 | +\note An aggregator must respect the "enabled" states of its child scopes, querying only the child scopes that are |
199 | +enabled. |
200 | + |
201 | Here is how you could implement an aggregating scope that passes a query to a single child scope "scope-A": |
202 | |
203 | \code{.cpp} |
204 | |
205 | -void MyScope::start(std::string const& scope_id) override |
206 | +ChildScopeList MyScope::find_child_scopes() const override |
207 | { |
208 | auto reg = registry(); // Up-call into base class |
209 | if (!reg) |
210 | @@ -587,21 +682,23 @@ |
211 | throw ConfigException(scope_id + ": No registry available, cannot locate child scopes"); |
212 | } |
213 | |
214 | + ChildScopeList list; |
215 | try |
216 | { |
217 | auto meta = reg->get_metadata("scope-A"); |
218 | - scope_to_query_ = meta.proxy(); // store the proxy for passing it further in search |
219 | + list.emplace_back(ChildScope{"scope-A", meta}); |
220 | } |
221 | catch (NotFoundException const& e) |
222 | { |
223 | ... |
224 | } |
225 | + return list; |
226 | } |
227 | |
228 | QueryBase::UPtr MyScope::search(CannedQuery const& query, |
229 | SearchMetadata const& metadata) |
230 | { |
231 | - SearchQueryBase::UPtr q(new MyQuery(query, metadata, scope_to_query_)); |
232 | + SearchQueryBase::UPtr q(new MyQuery(query, metadata, child_scopes())); |
233 | return q; |
234 | } |
235 | |
236 | @@ -609,9 +706,13 @@ |
237 | |
238 | void MyQuery::run(SearchReplyProxy const& upstream_reply) |
239 | { |
240 | - auto category = reply->register_category("recommended", "Recommended", icon, ""); |
241 | - SearchListenerBase::SPtr reply(new MyReceiver(upstream_reply, category)); |
242 | - subsearch(scope_to_query_, query_, reply); |
243 | + // Continue only if our child scope is installed AND enabled |
244 | + if (!child_scopes_.empty() && child_scopes_.front().enabled) |
245 | + { |
246 | + auto category = reply->register_category("recommended", "Recommended", icon, ""); |
247 | + SearchListenerBase::SPtr reply(new MyReceiver(upstream_reply, category)); |
248 | + subsearch(child_scopes_.front(), query_, reply); |
249 | + } |
250 | } |
251 | \endcode |
252 | |
253 | @@ -1214,6 +1315,9 @@ |
254 | similar type (E.g. The Music scope will aggregate scopes with the keyword "music", and so on). The value of `Keywords` should specify a |
255 | list of keywords your scope falls under. Like `ChildScopes`, this value must be a semicolon separated list (E.g. `Keywords = music;video`). |
256 | |
257 | +\note Please refer to the <a href="https://developer.ubuntu.com/en/scopes/tutorials/scope-keywords/">Scope Keywords</a> |
258 | +tutorial document for more detail on using keywords in your scope. |
259 | + |
260 | \subsection scopetool The scope tool |
261 | |
262 | The Unity Scope Tool is a stand-alone redering tool that allows you |
263 | |
264 | === modified file 'include/unity/scopes/Result.h' |
265 | --- include/unity/scopes/Result.h 2015-02-25 03:59:07 +0000 |
266 | +++ include/unity/scopes/Result.h 2015-04-23 15:43:14 +0000 |
267 | @@ -229,6 +229,12 @@ |
268 | */ |
269 | VariantMap serialize() const; |
270 | |
271 | + /** |
272 | + \brief Check if this result is an online account login result. |
273 | + \return True if this result is an online account login result. |
274 | + */ |
275 | + bool is_account_login_result() const; |
276 | + |
277 | /// @cond |
278 | protected: |
279 | explicit Result(const VariantMap &variant_map); |
280 | |
281 | === modified file 'include/unity/scopes/internal/RegistryObject.h' |
282 | --- include/unity/scopes/internal/RegistryObject.h 2014-11-26 02:54:41 +0000 |
283 | +++ include/unity/scopes/internal/RegistryObject.h 2015-04-23 15:43:14 +0000 |
284 | @@ -29,6 +29,7 @@ |
285 | #include <condition_variable> |
286 | #include <mutex> |
287 | #include <thread> |
288 | +#include <chrono> |
289 | |
290 | namespace unity |
291 | { |
292 | @@ -152,6 +153,12 @@ |
293 | mutable std::mutex mutex_; |
294 | |
295 | MWPublisher::SPtr publisher_; |
296 | + std::thread publisher_notify_thread_; |
297 | + std::condition_variable publisher_notify_cond_; |
298 | + std::chrono::system_clock::time_point publisher_notify_timepoint_; |
299 | + bool publisher_notify_reset_timer_; |
300 | + bool publisher_notify_exit_; |
301 | + |
302 | MWSubscriber::SPtr ss_list_update_subscriber_; |
303 | std::shared_ptr<core::ScopedConnection> ss_list_update_connection_; |
304 | bool generate_desktop_files_; |
305 | |
306 | === modified file 'include/unity/scopes/internal/Utils.h' |
307 | --- include/unity/scopes/internal/Utils.h 2014-11-17 01:29:26 +0000 |
308 | +++ include/unity/scopes/internal/Utils.h 2015-04-23 15:43:14 +0000 |
309 | @@ -55,6 +55,8 @@ |
310 | |
311 | int safe_system_call(std::string const& command); |
312 | |
313 | +void make_directories(std::string const& path_name, mode_t mode); |
314 | + |
315 | } // namespace internal |
316 | |
317 | } // namespace scopes |
318 | |
319 | === modified file 'scoperegistry/scoperegistry.cpp' |
320 | --- scoperegistry/scoperegistry.cpp 2015-02-17 00:27:08 +0000 |
321 | +++ scoperegistry/scoperegistry.cpp 2015-04-23 15:43:14 +0000 |
322 | @@ -26,13 +26,13 @@ |
323 | #include <unity/scopes/internal/ScopeConfig.h> |
324 | #include <unity/scopes/internal/ScopeImpl.h> |
325 | #include <unity/scopes/internal/ScopeMetadataImpl.h> |
326 | +#include <unity/scopes/internal/Utils.h> |
327 | #include <unity/scopes/ScopeExceptions.h> |
328 | #include <unity/UnityExceptions.h> |
329 | |
330 | +#include <boost/filesystem.hpp> |
331 | #include <boost/algorithm/string.hpp> |
332 | -#include <boost/filesystem/operations.hpp> |
333 | |
334 | -#include <sys/stat.h> // TODO: remove this once hack for creating data root dir is removed |
335 | #include <wordexp.h> |
336 | |
337 | using namespace scoperegistry; |
338 | @@ -535,28 +535,17 @@ |
339 | identity = runtime->registry_identity(); |
340 | ss_reg_id = runtime->ss_registry_identity(); |
341 | |
342 | - // TODO: HACK: We create the root of the cache and app directories for |
343 | - // confined scopes, in case the scope is confined and the dir doesn't |
344 | - // exist yet. This really should be done by the click-installation but, |
345 | - // prior to RTM, we don't rely on that. |
346 | - boost::system::error_code ec; |
347 | - |
348 | + // Make sure that the cache and app directories exist. |
349 | string cache_root = rt_config.cache_directory() + "/leaf-net"; |
350 | - !boost::filesystem::exists(cache_root, ec) && ::mkdir(cache_root.c_str(), 0700); |
351 | + make_directories(cache_root, 0700); |
352 | |
353 | string app_root = rt_config.app_directory(); |
354 | - !boost::filesystem::exists(app_root, ec) && ::mkdir(app_root.c_str(), 0700); |
355 | + make_directories(app_root, 0700); |
356 | } // Release memory for config parser |
357 | |
358 | - // Make sure that the parent directories for confined scope tmp directory exist. |
359 | - { |
360 | - string dir = string("/run/user/") + std::to_string(geteuid()); |
361 | - dir += "/scopes"; |
362 | - boost::system::error_code ec; |
363 | - !boost::filesystem::exists(dir, ec) && ::mkdir(dir.c_str(), 0700 | S_ISVTX); |
364 | - dir += "/leaf-net"; |
365 | - !boost::filesystem::exists(dir, ec) && ::mkdir(dir.c_str(), 0700 | S_ISVTX); |
366 | - } |
367 | + // Make sure that the confined scope tmp directory exists. |
368 | + string tmp_dir = string("/run/user/") + std::to_string(geteuid()) + "/scopes/leaf-net"; |
369 | + make_directories(tmp_dir, 0700); |
370 | |
371 | // Collect the registry config data. |
372 | |
373 | |
374 | === modified file 'src/scopes/Result.cpp' |
375 | --- src/scopes/Result.cpp 2014-02-14 17:00:04 +0000 |
376 | +++ src/scopes/Result.cpp 2015-04-23 15:43:14 +0000 |
377 | @@ -154,6 +154,11 @@ |
378 | return p->serialize(); |
379 | } |
380 | |
381 | +bool Result::is_account_login_result() const |
382 | +{ |
383 | + return p->contains("online_account_details"); |
384 | +} |
385 | + |
386 | //! @endcond |
387 | |
388 | } // namespace scopes |
389 | |
390 | === modified file 'src/scopes/internal/RegistryObject.cpp' |
391 | --- src/scopes/internal/RegistryObject.cpp 2015-01-20 08:25:39 +0000 |
392 | +++ src/scopes/internal/RegistryObject.cpp 2015-04-23 15:43:14 +0000 |
393 | @@ -37,6 +37,7 @@ |
394 | |
395 | static const char* c_debug_dbus_started_cmd = "dbus-send --type=method_call --dest=com.ubuntu.SDKAppLaunch /ScopeRegistryCallback com.ubuntu.SDKAppLaunch.ScopeLoaded"; |
396 | static const char* c_debug_dbus_stopped_cmd = "dbus-send --type=method_call --dest=com.ubuntu.SDKAppLaunch /ScopeRegistryCallback com.ubuntu.SDKAppLaunch.ScopeStopped"; |
397 | +static const std::chrono::seconds removal_notification_delay(5); |
398 | |
399 | namespace unity |
400 | { |
401 | @@ -73,6 +74,8 @@ |
402 | }) |
403 | }, |
404 | executor_(executor), |
405 | + publisher_notify_reset_timer_(false), |
406 | + publisher_notify_exit_(false), |
407 | generate_desktop_files_(generate_desktop_files) |
408 | { |
409 | if (middleware) |
410 | @@ -99,10 +102,14 @@ |
411 | |
412 | RegistryObject::~RegistryObject() |
413 | { |
414 | + if (publisher_notify_thread_.joinable()) |
415 | { |
416 | - // The destructor may be called from an arbitrary |
417 | - // thread, so we need a full fence here. |
418 | - lock_guard<decltype(mutex_)> lock(mutex_); |
419 | + { |
420 | + lock_guard<decltype(mutex_)> lock(mutex_); |
421 | + publisher_notify_exit_ = true; |
422 | + publisher_notify_cond_.notify_one(); |
423 | + } |
424 | + publisher_notify_thread_.join(); |
425 | } |
426 | |
427 | // kill all scope processes |
428 | @@ -322,8 +329,34 @@ |
429 | |
430 | if (publisher_ && erased) |
431 | { |
432 | - // Send a blank message to subscribers to inform them that the registry has been updated |
433 | - publisher_->send_message(""); |
434 | + // Send a blank message to subscribers to inform them that the registry has been updated. |
435 | + // Delay notification so that scope is not seen as removed and then added when updated. |
436 | + lock_guard<decltype(mutex_)> lock(mutex_); |
437 | + |
438 | + if (!publisher_notify_thread_.joinable()) |
439 | + { |
440 | + publisher_notify_timepoint_ = chrono::system_clock::now() + removal_notification_delay; |
441 | + publisher_notify_thread_ = thread([this] |
442 | + { |
443 | + unique_lock<decltype(mutex_)> lock(mutex_); |
444 | + while (!publisher_notify_exit_) |
445 | + { |
446 | + auto pred = [this] |
447 | + { |
448 | + return publisher_notify_exit_ || publisher_notify_reset_timer_; |
449 | + }; |
450 | + if (!publisher_notify_cond_.wait_until(lock, publisher_notify_timepoint_, pred)) // pred is false, but timeout reached |
451 | + { |
452 | + publisher_->send_message(""); |
453 | + publisher_notify_timepoint_ = chrono::system_clock::time_point::max(); |
454 | + } |
455 | + publisher_notify_reset_timer_ = false; |
456 | + } |
457 | + }); |
458 | + } |
459 | + publisher_notify_reset_timer_ = true; |
460 | + publisher_notify_timepoint_ = chrono::system_clock::now() + removal_notification_delay; |
461 | + publisher_notify_cond_.notify_one(); |
462 | } |
463 | |
464 | if (ex) |
465 | |
466 | === modified file 'src/scopes/internal/RuntimeConfig.cpp' |
467 | --- src/scopes/internal/RuntimeConfig.cpp 2015-01-06 02:38:27 +0000 |
468 | +++ src/scopes/internal/RuntimeConfig.cpp 2015-04-23 15:43:14 +0000 |
469 | @@ -19,18 +19,14 @@ |
470 | #include <unity/scopes/internal/RuntimeConfig.h> |
471 | |
472 | #include <unity/scopes/internal/DfltConfig.h> |
473 | +#include <unity/scopes/internal/Utils.h> |
474 | #include <unity/scopes/ScopeExceptions.h> |
475 | |
476 | #include <boost/algorithm/string/classification.hpp> |
477 | #include <boost/algorithm/string/constants.hpp> |
478 | #include <boost/algorithm/string/split.hpp> |
479 | -#include <boost/filesystem.hpp> |
480 | #include <unity/UnityExceptions.h> |
481 | |
482 | -#include <sys/stat.h> |
483 | - |
484 | -#include <stdlib.h> |
485 | - |
486 | using namespace std; |
487 | |
488 | namespace unity |
489 | @@ -343,9 +339,7 @@ |
490 | throw ResourceException("RuntimeConfig::default_log_directory(): $HOME not set"); |
491 | } |
492 | string dir = string(home) + "/" + DFLT_HOME_LOG_SUBDIR; |
493 | - |
494 | - boost::system::error_code ec; |
495 | - !boost::filesystem::exists(dir, ec) && ::mkdir(dir.c_str(), 0700); |
496 | + make_directories(dir, 0700); |
497 | |
498 | return dir; |
499 | } |
500 | |
501 | === modified file 'src/scopes/internal/RuntimeImpl.cpp' |
502 | --- src/scopes/internal/RuntimeImpl.cpp 2015-03-02 03:59:01 +0000 |
503 | +++ src/scopes/internal/RuntimeImpl.cpp 2015-04-23 15:43:14 +0000 |
504 | @@ -30,6 +30,7 @@ |
505 | #include <unity/scopes/internal/ScopeObject.h> |
506 | #include <unity/scopes/internal/SettingsDB.h> |
507 | #include <unity/scopes/internal/UniqueID.h> |
508 | +#include <unity/scopes/internal/Utils.h> |
509 | #include <unity/scopes/ScopeBase.h> |
510 | #include <unity/scopes/ScopeExceptions.h> |
511 | |
512 | @@ -42,7 +43,6 @@ |
513 | #include <future> |
514 | |
515 | #include <sys/apparmor.h> |
516 | -#include <sys/stat.h> |
517 | |
518 | using namespace std; |
519 | using namespace unity::scopes; |
520 | @@ -592,43 +592,39 @@ |
521 | string RuntimeImpl::find_cache_dir() const |
522 | { |
523 | // Create the cache_dir_/<confinement-type>/<id> directories if they don't exist. |
524 | - boost::system::error_code ec; |
525 | - !confined() && !boost::filesystem::exists(cache_dir_, ec) && ::mkdir(cache_dir_.c_str(), 0700); |
526 | string dir = cache_dir_ + "/" + confinement_type(); |
527 | - !confined() && !boost::filesystem::exists(dir, ec) && ::mkdir(dir.c_str(), 0700); |
528 | - |
529 | + if (!confined()) // Avoid apparmor noise |
530 | + { |
531 | + string dir = cache_dir_ + "/" + confinement_type(); |
532 | + make_directories(cache_dir_, 0700); |
533 | + } |
534 | // A confined scope is allowed to create this dir. |
535 | dir += "/" + demangled_id(scope_id_); |
536 | - !boost::filesystem::exists(dir, ec) && ::mkdir(dir.c_str(), 0700); |
537 | - |
538 | + make_directories(dir, 0700); |
539 | return dir; |
540 | } |
541 | |
542 | string RuntimeImpl::find_app_dir() const |
543 | { |
544 | // Create the app_dir_/<id> directories if they don't exist. |
545 | - boost::system::error_code ec; |
546 | - !confined() && !boost::filesystem::exists(app_dir_, ec) && ::mkdir(app_dir_.c_str(), 0700); |
547 | string dir = app_dir_ + "/" + demangled_id(scope_id_); |
548 | - !confined() && !boost::filesystem::exists(dir, ec) && ::mkdir(dir.c_str(), 0700); |
549 | - |
550 | + if (!confined()) // Avoid apparmor noise |
551 | + { |
552 | + make_directories(dir, 0700); |
553 | + } |
554 | return dir; |
555 | } |
556 | |
557 | string RuntimeImpl::find_log_dir(string const& id) const |
558 | { |
559 | - // Create the log_dir_/<confinement-type>/<id>/logs directories if they don't exist. |
560 | - boost::system::error_code ec; |
561 | - !confined() && !boost::filesystem::exists(log_dir_, ec) && ::mkdir(log_dir_.c_str(), 0700); |
562 | string dir = log_dir_ + "/" + confinement_type(); |
563 | - !confined() && !boost::filesystem::exists(dir, ec) && ::mkdir(dir.c_str(), 0700); |
564 | - |
565 | + if (!confined()) // Avoid apparmore noise |
566 | + { |
567 | + make_directories(dir, 0700); |
568 | + } |
569 | // A confined scope is allowed to create this dir. |
570 | - dir += "/" + demangled_id(id); |
571 | - !boost::filesystem::exists(dir, ec) && ::mkdir(dir.c_str(), 0700); |
572 | - dir += "/logs"; |
573 | - !boost::filesystem::exists(dir, ec) && ::mkdir(dir.c_str(), 0700); |
574 | - |
575 | + dir += "/" + demangled_id(id) + "/logs"; |
576 | + make_directories(dir, 0700); |
577 | return dir; |
578 | } |
579 | |
580 | @@ -638,17 +634,14 @@ |
581 | // We need to create any directories under /run/user/<uid> because they might not |
582 | // exist. We set the sticky bit because, without this, things in |
583 | // /run/user may be deleted if not accessed for more than six hours. |
584 | - string dir = string("/run/user/") + std::to_string(geteuid()); |
585 | - dir += "/scopes"; |
586 | - boost::system::error_code ec; |
587 | - !confined() && !boost::filesystem::exists(dir, ec) && ::mkdir(dir.c_str(), 0700 | S_ISVTX); |
588 | - dir += "/" + confinement_type(); |
589 | - !confined() && !boost::filesystem::exists(dir, ec) && ::mkdir(dir.c_str(), 0700 | S_ISVTX); |
590 | - |
591 | + string dir = string("/run/user/") + std::to_string(geteuid()) + "/scopes/" + confinement_type(); |
592 | + if (!confined()) // Avoid apparmor noise |
593 | + { |
594 | + make_directories(dir, 0700); |
595 | + } |
596 | // A confined scope is allowed to create this dir. |
597 | dir += "/" + scope_id_; // Not demangled, use the real scope ID. |
598 | - !boost::filesystem::exists(dir, ec) && ::mkdir(dir.c_str(), 0700 | S_ISVTX); |
599 | - |
600 | + make_directories(dir, 0700); |
601 | return dir; |
602 | } |
603 | |
604 | |
605 | === modified file 'src/scopes/internal/SearchQueryBaseImpl.cpp' |
606 | --- src/scopes/internal/SearchQueryBaseImpl.cpp 2015-04-09 15:59:17 +0000 |
607 | +++ src/scopes/internal/SearchQueryBaseImpl.cpp 2015-04-23 15:43:14 +0000 |
608 | @@ -193,14 +193,19 @@ |
609 | reply->finished(CompletionDetails(CompletionDetails::OK, |
610 | "empty result set due to aggregator loop or repeated query on aggregating scope " |
611 | + get<1>(tuple))); |
612 | + ctrl_proxy = make_shared<QueryCtrlImpl>(nullptr, nullptr); // Dummy proxy in already-cancelled state |
613 | + |
614 | auto scope_impl = dynamic_pointer_cast<ScopeImpl>(scope); |
615 | - auto logger = scope_impl->runtime()->logger(); |
616 | - ctrl_proxy = make_shared<QueryCtrlImpl>(nullptr, nullptr); // Dummy proxy in already-cancelled state |
617 | - BOOST_LOG_SEV(logger, Logger::Warning) |
618 | - << "query loop for query \"" << canned_query_.query_string() |
619 | - << "\", client: " << get<0>(tuple) |
620 | - << ", aggregator: " << get<1>(tuple) |
621 | - << ", receiver: " << get<2>(tuple) << endl; |
622 | + // scope_impl can be nullptr if we use a mock scope: TypedScopeFixture<testing::Scope> |
623 | + if (scope_impl) |
624 | + { |
625 | + auto logger = scope_impl->runtime()->logger(); |
626 | + BOOST_LOG_SEV(logger, Logger::Warning) |
627 | + << "query loop for query \"" << canned_query_.query_string() |
628 | + << "\", client: " << get<0>(tuple) |
629 | + << ", aggregator: " << get<1>(tuple) |
630 | + << ", receiver: " << get<2>(tuple) << endl; |
631 | + } |
632 | } |
633 | else |
634 | { |
635 | |
636 | === modified file 'src/scopes/internal/Utils.cpp' |
637 | --- src/scopes/internal/Utils.cpp 2014-11-17 01:29:26 +0000 |
638 | +++ src/scopes/internal/Utils.cpp 2015-04-23 15:43:14 +0000 |
639 | @@ -20,10 +20,16 @@ |
640 | #include <unity/scopes/ScopeExceptions.h> |
641 | #include <unity/UnityExceptions.h> |
642 | |
643 | +#include <boost/filesystem.hpp> |
644 | + |
645 | #include <iomanip> |
646 | #include <locale> |
647 | #include <mutex> |
648 | |
649 | +#include <sys/stat.h> |
650 | + |
651 | +using namespace std; |
652 | + |
653 | namespace unity |
654 | { |
655 | |
656 | @@ -33,7 +39,7 @@ |
657 | namespace internal |
658 | { |
659 | |
660 | -VariantMap::const_iterator find_or_throw(std::string const& context, VariantMap const& var, std::string const& key) |
661 | +VariantMap::const_iterator find_or_throw(string const& context, VariantMap const& var, string const& key) |
662 | { |
663 | auto it = var.find(key); |
664 | if (it == var.end()) |
665 | @@ -43,14 +49,14 @@ |
666 | return it; |
667 | } |
668 | |
669 | -std::string to_percent_encoding(std::string const& str) |
670 | +string to_percent_encoding(string const& str) |
671 | { |
672 | - std::ostringstream result; |
673 | + ostringstream result; |
674 | for (auto const& c: str) |
675 | { |
676 | if ((!isalnum(c))) |
677 | { |
678 | - result << '%' << std::setw(2) << std::setfill('0') << std::hex << std::uppercase << static_cast<int>(static_cast<unsigned char>(c)) << std::nouppercase; |
679 | + result << '%' << setw(2) << setfill('0') << hex << uppercase << static_cast<int>(static_cast<unsigned char>(c)) << nouppercase; |
680 | } |
681 | else |
682 | { |
683 | @@ -60,9 +66,9 @@ |
684 | return result.str(); |
685 | } |
686 | |
687 | -std::string from_percent_encoding(std::string const& str) |
688 | +string from_percent_encoding(string const& str) |
689 | { |
690 | - std::ostringstream result; |
691 | + ostringstream result; |
692 | for (auto it = str.begin(); it != str.end(); it++) |
693 | { |
694 | auto c = *it; |
695 | @@ -75,16 +81,16 @@ |
696 | c = *it; |
697 | if (++it != str.end()) |
698 | { |
699 | - std::string const hexnum { c, *it }; |
700 | + string const hexnum { c, *it }; |
701 | try |
702 | { |
703 | - auto k = std::stoi(hexnum, nullptr, 16); |
704 | + auto k = stoi(hexnum, nullptr, 16); |
705 | result << static_cast<char>(k); |
706 | valid = true; |
707 | } |
708 | - catch (std::logic_error const& e) // covers both std::invalid_argument and std::out_of_range |
709 | + catch (logic_error const& e) // covers both invalid_argument and out_of_range |
710 | { |
711 | - std::stringstream err; |
712 | + stringstream err; |
713 | err << "from_percent_encoding(): unsupported conversion of '" << hexnum << "'"; |
714 | throw unity::InvalidArgumentException(err.str()); |
715 | } |
716 | @@ -103,33 +109,33 @@ |
717 | return result.str(); |
718 | } |
719 | |
720 | -std::string uncamelcase(std::string const& str) |
721 | +string uncamelcase(string const& str) |
722 | { |
723 | - const std::locale loc(""); |
724 | + const locale loc(""); |
725 | if (str.size() == 0) |
726 | { |
727 | return str; |
728 | } |
729 | auto it = str.begin(); |
730 | - int previous_is_lower = std::islower(*it); |
731 | - std::stringstream res; |
732 | - res << std::tolower(*it, loc); |
733 | + int previous_is_lower = islower(*it); |
734 | + stringstream res; |
735 | + res << tolower(*it, loc); |
736 | ++it; |
737 | while (it != str.end()) |
738 | { |
739 | - if (std::isupper(*it) && previous_is_lower) |
740 | + if (isupper(*it) && previous_is_lower) |
741 | { |
742 | res << "-"; |
743 | } |
744 | - previous_is_lower = std::islower(*it); |
745 | - res << std::tolower(*it, loc); |
746 | + previous_is_lower = islower(*it); |
747 | + res << tolower(*it, loc); |
748 | ++it; |
749 | } |
750 | return res.str(); |
751 | } |
752 | |
753 | template<> |
754 | -bool convert_to<bool>(std::string const& val, Variant& out) |
755 | +bool convert_to<bool>(string const& val, Variant& out) |
756 | { |
757 | if (val == "true") |
758 | { |
759 | @@ -144,11 +150,44 @@ |
760 | return false; |
761 | } |
762 | |
763 | -int safe_system_call(std::string const& command) |
764 | -{ |
765 | - static std::mutex system_mutex; |
766 | - std::lock_guard<std::mutex> lock(system_mutex); |
767 | - return std::system(command.c_str()); |
768 | +int safe_system_call(string const& command) |
769 | +{ |
770 | + static mutex system_mutex; |
771 | + lock_guard<mutex> lock(system_mutex); |
772 | + return system(command.c_str()); |
773 | +} |
774 | + |
775 | +// Recursively create the directories in path, setting permissions to the specified mode |
776 | +// (regardless of the setting of umask). If one or more directories already exist, they |
777 | +// are left unchanged (including their permissions). If a directory cannot be created, |
778 | +// fail silently. |
779 | + |
780 | +void make_directories(string const& path_name, mode_t mode) |
781 | +{ |
782 | + using namespace boost::filesystem; |
783 | + |
784 | + // We can't use boost::create_directories() here because that does not allow control over permissions. |
785 | + auto abs = absolute(path_name); |
786 | + path path_so_far = ""; |
787 | + path::iterator it = abs.begin(); |
788 | + ++it; // No point in trying to create / |
789 | + while (it != abs.end()) |
790 | + { |
791 | + path_so_far += "/"; |
792 | + path_so_far += *it++; |
793 | + string p = path_so_far.native(); |
794 | + if (mkdir(p.c_str(), mode) != 0) |
795 | + { |
796 | + if (errno == EEXIST) |
797 | + { |
798 | + continue; |
799 | + } |
800 | + return; // No point in continuing, we'd fail on all subsequent iterations. |
801 | + } |
802 | + // We just created the dir, make sure it has the requested permissions, |
803 | + // not the permissions modified by umask. |
804 | + chmod(p.c_str(), mode); |
805 | + } |
806 | } |
807 | |
808 | } // namespace internal |
809 | |
810 | === modified file 'src/scopes/internal/smartscopes/SmartScopesClient.cpp' |
811 | --- src/scopes/internal/smartscopes/SmartScopesClient.cpp 2015-01-28 09:03:59 +0000 |
812 | +++ src/scopes/internal/smartscopes/SmartScopesClient.cpp 2015-04-23 15:43:14 +0000 |
813 | @@ -21,6 +21,7 @@ |
814 | #include <unity/scopes/internal/FilterStateImpl.h> |
815 | #include <unity/scopes/internal/RuntimeImpl.h> |
816 | #include <unity/scopes/internal/smartscopes/SmartScopesClient.h> |
817 | +#include <unity/scopes/internal/Utils.h> |
818 | |
819 | #include <unity/scopes/ScopeExceptions.h> |
820 | #include <unity/UnityExceptions.h> |
821 | @@ -34,7 +35,6 @@ |
822 | #include <utility> |
823 | #include <map> |
824 | #include <sstream> |
825 | -#include <sys/stat.h> |
826 | |
827 | static std::string homedir() |
828 | { |
829 | @@ -860,7 +860,7 @@ |
830 | void SmartScopesClient::write_cache(std::string const& scopes_json) |
831 | { |
832 | // make cache directory (fails silently if already exists) |
833 | - mkdir(c_scopes_cache_dir.c_str(), 0755); |
834 | + make_directories(c_scopes_cache_dir, 0755); |
835 | |
836 | // open cache for output |
837 | std::ofstream cache_file(c_scopes_cache_dir + c_scopes_cache_filename); |
838 | |
839 | === added file 'test/gtest/scopes/Aggregation/CMakeLists.txt' |
840 | --- test/gtest/scopes/Aggregation/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
841 | +++ test/gtest/scopes/Aggregation/CMakeLists.txt 2015-04-23 15:43:14 +0000 |
842 | @@ -0,0 +1,39 @@ |
843 | +configure_file(TestRegistry.ini.in ${CMAKE_CURRENT_BINARY_DIR}/TestRegistry.ini) |
844 | +configure_file(Runtime.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini) |
845 | +configure_file(Zmq.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Zmq.ini) |
846 | + |
847 | +add_definitions(-DTEST_RUNTIME_PATH="${CMAKE_CURRENT_BINARY_DIR}") |
848 | +add_definitions(-DTEST_RUNTIME_FILE="${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini") |
849 | +add_definitions(-DTEST_REGISTRY_PATH="${PROJECT_BINARY_DIR}/scoperegistry") |
850 | + |
851 | + |
852 | +add_executable(ChildScopes_test ChildScopes_test.cpp) |
853 | +target_link_libraries(ChildScopes_test ${TESTLIBS}) |
854 | + |
855 | +add_test(ChildScopes ChildScopes_test) |
856 | + |
857 | + |
858 | +add_executable(Keywords_test Keywords_test.cpp) |
859 | +target_link_libraries(Keywords_test ${TESTLIBS}) |
860 | + |
861 | +add_test(Keywords Keywords_test) |
862 | + |
863 | + |
864 | +add_executable(LoopDetection_test LoopDetection_test.cpp AggTestScope.cpp) |
865 | +target_link_libraries(LoopDetection_test ${TESTLIBS}) |
866 | + |
867 | +add_dependencies(LoopDetection_test scoperegistry scoperunner) |
868 | + |
869 | +add_test(LoopDetection LoopDetection_test) |
870 | + |
871 | +set(SCOPE_DIR "${CMAKE_CURRENT_BINARY_DIR}/scopes") |
872 | + |
873 | +foreach (scope A B C D) |
874 | + file(MAKE_DIRECTORY "${SCOPE_DIR}/${scope}") |
875 | + configure_file(AggTestScope.ini.in ${SCOPE_DIR}/${scope}/${scope}.ini) |
876 | + add_library(${scope} MODULE AggTestScope.cpp) |
877 | + set_target_properties(${scope} |
878 | + PROPERTIES |
879 | + LIBRARY_OUTPUT_DIRECTORY "${SCOPE_DIR}/${scope}/" |
880 | + ) |
881 | +endforeach() |
882 | |
883 | === removed file 'test/gtest/scopes/Aggregation/CMakeLists.txt' |
884 | --- test/gtest/scopes/Aggregation/CMakeLists.txt 2015-04-09 15:59:17 +0000 |
885 | +++ test/gtest/scopes/Aggregation/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
886 | @@ -1,39 +0,0 @@ |
887 | -configure_file(TestRegistry.ini.in ${CMAKE_CURRENT_BINARY_DIR}/TestRegistry.ini) |
888 | -configure_file(Runtime.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini) |
889 | -configure_file(Zmq.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Zmq.ini) |
890 | - |
891 | -add_definitions(-DTEST_RUNTIME_PATH="${CMAKE_CURRENT_BINARY_DIR}") |
892 | -add_definitions(-DTEST_RUNTIME_FILE="${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini") |
893 | -add_definitions(-DTEST_REGISTRY_PATH="${PROJECT_BINARY_DIR}/scoperegistry") |
894 | - |
895 | - |
896 | -add_executable(ChildScopes_test ChildScopes_test.cpp) |
897 | -target_link_libraries(ChildScopes_test ${TESTLIBS}) |
898 | - |
899 | -add_test(ChildScopes ChildScopes_test) |
900 | - |
901 | - |
902 | -add_executable(Keywords_test Keywords_test.cpp) |
903 | -target_link_libraries(Keywords_test ${TESTLIBS}) |
904 | - |
905 | -add_test(Keywords Keywords_test) |
906 | - |
907 | - |
908 | -add_executable(LoopDetection_test LoopDetection_test.cpp AggTestScope.cpp) |
909 | -target_link_libraries(LoopDetection_test ${TESTLIBS}) |
910 | - |
911 | -add_dependencies(LoopDetection_test scoperegistry scoperunner) |
912 | - |
913 | -add_test(LoopDetection LoopDetection_test) |
914 | - |
915 | -set(SCOPE_DIR "${CMAKE_CURRENT_BINARY_DIR}/scopes") |
916 | - |
917 | -foreach (scope A B C D) |
918 | - file(MAKE_DIRECTORY "${SCOPE_DIR}/${scope}") |
919 | - configure_file(AggTestScope.ini.in ${SCOPE_DIR}/${scope}/${scope}.ini) |
920 | - add_library(${scope} MODULE AggTestScope.cpp) |
921 | - set_target_properties(${scope} |
922 | - PROPERTIES |
923 | - LIBRARY_OUTPUT_DIRECTORY "${SCOPE_DIR}/${scope}/" |
924 | - ) |
925 | -endforeach() |
926 | |
927 | === modified file 'test/gtest/scopes/OnlineAccountClient/OnlineAccountClient_test.cpp' |
928 | --- test/gtest/scopes/OnlineAccountClient/OnlineAccountClient_test.cpp 2015-01-26 06:02:10 +0000 |
929 | +++ test/gtest/scopes/OnlineAccountClient/OnlineAccountClient_test.cpp 2015-04-23 15:43:14 +0000 |
930 | @@ -307,7 +307,9 @@ |
931 | auto cat = reg.register_category("1", "title", "icon", nullptr, CategoryRenderer()); |
932 | CategorisedResult result(cat); |
933 | |
934 | + EXPECT_FALSE(result.is_account_login_result()); |
935 | oa_client.register_account_login_item(result, CannedQuery("test"), OnlineAccountClient::InvalidateResults, OnlineAccountClient::DoNothing); |
936 | + EXPECT_TRUE(result.is_account_login_result()); |
937 | |
938 | EXPECT_TRUE(result.contains("online_account_details")); |
939 | |
940 | |
941 | === modified file 'test/gtest/scopes/Registry/Registry_test.cpp' |
942 | --- test/gtest/scopes/Registry/Registry_test.cpp 2015-01-27 12:46:11 +0000 |
943 | +++ test/gtest/scopes/Registry/Registry_test.cpp 2015-04-23 15:43:14 +0000 |
944 | @@ -153,7 +153,7 @@ |
945 | EXPECT_FALSE(meta.is_aggregator()); |
946 | } |
947 | |
948 | -auto const wait_for_update_time = std::chrono::milliseconds(5000); |
949 | +auto const wait_for_update_time = std::chrono::milliseconds(10000); |
950 | |
951 | TEST(Registry, scope_state_notify) |
952 | { |
953 | |
954 | === renamed file 'test/gtest/scopes/internal/RuntimeConfig/BadLogDirSize.ini' => 'test/gtest/scopes/internal/RuntimeConfig/BadLogDirSize.ini.in' |
955 | === renamed file 'test/gtest/scopes/internal/RuntimeConfig/BadLogFileSize.ini' => 'test/gtest/scopes/internal/RuntimeConfig/BadLogFileSize.ini.in' |
956 | === renamed file 'test/gtest/scopes/internal/RuntimeConfig/BadMW.ini' => 'test/gtest/scopes/internal/RuntimeConfig/BadMW.ini.in' |
957 | === renamed file 'test/gtest/scopes/internal/RuntimeConfig/BadReapExpiry.ini' => 'test/gtest/scopes/internal/RuntimeConfig/BadReapExpiry.ini.in' |
958 | === renamed file 'test/gtest/scopes/internal/RuntimeConfig/BadReapInterval.ini' => 'test/gtest/scopes/internal/RuntimeConfig/BadReapInterval.ini.in' |
959 | === modified file 'test/gtest/scopes/internal/RuntimeConfig/CMakeLists.txt' |
960 | --- test/gtest/scopes/internal/RuntimeConfig/CMakeLists.txt 2014-06-23 06:53:45 +0000 |
961 | +++ test/gtest/scopes/internal/RuntimeConfig/CMakeLists.txt 2015-04-23 15:43:14 +0000 |
962 | @@ -1,5 +1,12 @@ |
963 | -add_definitions(-DTEST_SRC_DIR="${CMAKE_CURRENT_SOURCE_DIR}") |
964 | +add_definitions(-DTEST_DIR="${CMAKE_CURRENT_BINARY_DIR}") |
965 | add_executable(RuntimeConfig_test RuntimeConfig_test.cpp) |
966 | target_link_libraries(RuntimeConfig_test ${TESTLIBS}) |
967 | |
968 | +file(GLOB ini_files "*.ini.in") |
969 | +foreach(ini_in ${ini_files}) |
970 | + get_filename_component(file ${ini_in} NAME) |
971 | + string(REGEX REPLACE "(.*)\\.in$" "\\1" ini ${file}) |
972 | + configure_file(${file} ${CMAKE_CURRENT_BINARY_DIR}/${ini}) |
973 | +endforeach(ini_in) |
974 | + |
975 | add_test(RuntimeConfig RuntimeConfig_test) |
976 | |
977 | === renamed file 'test/gtest/scopes/internal/RuntimeConfig/CacheDir.ini' => 'test/gtest/scopes/internal/RuntimeConfig/CacheDir.ini.in' |
978 | === renamed file 'test/gtest/scopes/internal/RuntimeConfig/Complete.ini' => 'test/gtest/scopes/internal/RuntimeConfig/Complete.ini.in' |
979 | === renamed file 'test/gtest/scopes/internal/RuntimeConfig/ConfigDir.ini' => 'test/gtest/scopes/internal/RuntimeConfig/ConfigDir.ini.in' |
980 | === renamed file 'test/gtest/scopes/internal/RuntimeConfig/LogDir.ini' => 'test/gtest/scopes/internal/RuntimeConfig/LogDir.ini.in' |
981 | === renamed file 'test/gtest/scopes/internal/RuntimeConfig/NoAppDir.ini' => 'test/gtest/scopes/internal/RuntimeConfig/NoAppDir.ini.in' |
982 | === renamed file 'test/gtest/scopes/internal/RuntimeConfig/NoCacheDir.ini' => 'test/gtest/scopes/internal/RuntimeConfig/NoCacheDir.ini.in' |
983 | === renamed file 'test/gtest/scopes/internal/RuntimeConfig/NoConfigDir.ini' => 'test/gtest/scopes/internal/RuntimeConfig/NoConfigDir.ini.in' |
984 | === renamed file 'test/gtest/scopes/internal/RuntimeConfig/NoLogDir.ini' => 'test/gtest/scopes/internal/RuntimeConfig/NoLogDir.ini.in' |
985 | === modified file 'test/gtest/scopes/internal/RuntimeConfig/RuntimeConfig_test.cpp' |
986 | --- test/gtest/scopes/internal/RuntimeConfig/RuntimeConfig_test.cpp 2015-02-12 23:21:47 +0000 |
987 | +++ test/gtest/scopes/internal/RuntimeConfig/RuntimeConfig_test.cpp 2015-04-23 15:43:14 +0000 |
988 | @@ -32,7 +32,7 @@ |
989 | |
990 | TEST(RuntimeConfig, basic) |
991 | { |
992 | - setenv("HOME", TEST_SRC_DIR, 1); |
993 | + setenv("HOME", TEST_DIR, 1); |
994 | |
995 | RuntimeConfig c(""); |
996 | EXPECT_EQ("Registry", c.registry_identity()); |
997 | @@ -50,7 +50,7 @@ |
998 | |
999 | TEST(RuntimeConfig, complete) |
1000 | { |
1001 | - RuntimeConfig c(TEST_SRC_DIR "/Complete.ini"); |
1002 | + RuntimeConfig c(TEST_DIR "/Complete.ini"); |
1003 | EXPECT_EQ("R.Id", c.registry_identity()); |
1004 | EXPECT_EQ("R.Config", c.registry_configfile()); |
1005 | EXPECT_EQ("SS.R.Id", c.ss_registry_identity()); |
1006 | @@ -70,25 +70,25 @@ |
1007 | |
1008 | TEST(RuntimeConfig, _default_cache_dir) |
1009 | { |
1010 | - setenv("HOME", TEST_SRC_DIR, 1); |
1011 | + setenv("HOME", TEST_DIR, 1); |
1012 | |
1013 | RuntimeConfig c(""); |
1014 | - EXPECT_EQ(TEST_SRC_DIR "/.local/share/unity-scopes", c.cache_directory()); |
1015 | + EXPECT_EQ(TEST_DIR "/.local/share/unity-scopes", c.cache_directory()); |
1016 | } |
1017 | |
1018 | TEST(RuntimeConfig, overridden_cache_dir) |
1019 | { |
1020 | unsetenv("HOME"); |
1021 | |
1022 | - RuntimeConfig c(TEST_SRC_DIR "/CacheDir.ini"); |
1023 | + RuntimeConfig c(TEST_DIR "/CacheDir.ini"); |
1024 | EXPECT_EQ("cachedir", c.cache_directory()); |
1025 | } |
1026 | |
1027 | TEST(RuntimeConfig, overridden_cache_dir_with_home_dir) |
1028 | { |
1029 | - setenv("HOME", TEST_SRC_DIR, 1); |
1030 | + setenv("HOME", TEST_DIR, 1); |
1031 | |
1032 | - RuntimeConfig c(TEST_SRC_DIR "/CacheDir.ini"); |
1033 | + RuntimeConfig c(TEST_DIR "/CacheDir.ini"); |
1034 | EXPECT_EQ("cachedir", c.cache_directory()); |
1035 | } |
1036 | |
1037 | @@ -96,15 +96,15 @@ |
1038 | { |
1039 | unsetenv("HOME"); |
1040 | |
1041 | - RuntimeConfig c(TEST_SRC_DIR "/CacheDir.ini"); |
1042 | + RuntimeConfig c(TEST_DIR "/CacheDir.ini"); |
1043 | EXPECT_EQ("appdir", c.app_directory()); |
1044 | } |
1045 | |
1046 | TEST(RuntimeConfig, overridden_app_dir_with_home_dir) |
1047 | { |
1048 | - setenv("HOME", TEST_SRC_DIR, 1); |
1049 | + setenv("HOME", TEST_DIR, 1); |
1050 | |
1051 | - RuntimeConfig c(TEST_SRC_DIR "/ConfigDir.ini"); |
1052 | + RuntimeConfig c(TEST_DIR "/ConfigDir.ini"); |
1053 | EXPECT_EQ("appdir", c.app_directory()); |
1054 | } |
1055 | |
1056 | @@ -112,15 +112,15 @@ |
1057 | { |
1058 | unsetenv("HOME"); |
1059 | |
1060 | - RuntimeConfig c(TEST_SRC_DIR "/ConfigDir.ini"); |
1061 | + RuntimeConfig c(TEST_DIR "/ConfigDir.ini"); |
1062 | EXPECT_EQ("configdir", c.config_directory()); |
1063 | } |
1064 | |
1065 | TEST(RuntimeConfig, overridden_config_dir_with_home_dir) |
1066 | { |
1067 | - setenv("HOME", TEST_SRC_DIR, 1); |
1068 | + setenv("HOME", TEST_DIR, 1); |
1069 | |
1070 | - RuntimeConfig c(TEST_SRC_DIR "/ConfigDir.ini"); |
1071 | + RuntimeConfig c(TEST_DIR "/ConfigDir.ini"); |
1072 | EXPECT_EQ("configdir", c.config_directory()); |
1073 | } |
1074 | |
1075 | @@ -128,13 +128,13 @@ |
1076 | { |
1077 | unsetenv("HOME"); |
1078 | |
1079 | - RuntimeConfig c(TEST_SRC_DIR "/LogDir.ini"); |
1080 | + RuntimeConfig c(TEST_DIR "/LogDir.ini"); |
1081 | EXPECT_EQ("logdir", c.log_directory()); |
1082 | } |
1083 | |
1084 | TEST(RuntimeConfig, overridden_log_dir_with_home_dir) |
1085 | { |
1086 | - RuntimeConfig c(TEST_SRC_DIR "/LogDir.ini"); |
1087 | + RuntimeConfig c(TEST_DIR "/LogDir.ini"); |
1088 | EXPECT_EQ("logdir", c.log_directory()); |
1089 | } |
1090 | |
1091 | @@ -142,7 +142,7 @@ |
1092 | { |
1093 | setenv("UNITY_SCOPES_LOGDIR", "otherdir", 1); |
1094 | |
1095 | - RuntimeConfig c(TEST_SRC_DIR "/LogDir.ini"); |
1096 | + RuntimeConfig c(TEST_DIR "/LogDir.ini"); |
1097 | EXPECT_EQ("otherdir", c.log_directory()); |
1098 | } |
1099 | |
1100 | @@ -150,7 +150,7 @@ |
1101 | { |
1102 | setenv("UNITY_SCOPES_LOG_TRACECHANNELS", "ABC;XYZ;;DEF", 1); |
1103 | |
1104 | - RuntimeConfig c(TEST_SRC_DIR "/Complete.ini"); |
1105 | + RuntimeConfig c(TEST_DIR "/Complete.ini"); |
1106 | EXPECT_EQ((vector<string>{ "ABC", "XYZ", "DEF"}), c.trace_channels()); |
1107 | } |
1108 | |
1109 | @@ -158,36 +158,36 @@ |
1110 | { |
1111 | try |
1112 | { |
1113 | - RuntimeConfig c(TEST_SRC_DIR "/BadMW.ini"); |
1114 | + RuntimeConfig c(TEST_DIR "/BadMW.ini"); |
1115 | FAIL(); |
1116 | } |
1117 | catch (ConfigException const& e) |
1118 | { |
1119 | - EXPECT_STREQ("unity::scopes::ConfigException: \"" TEST_SRC_DIR "/BadMW.ini\": Illegal value for Default.Middleware: " |
1120 | + EXPECT_STREQ("unity::scopes::ConfigException: \"" TEST_DIR "/BadMW.ini\": Illegal value for Default.Middleware: " |
1121 | "\"Foo\": legal values are \"Zmq\" and \"REST\"", |
1122 | e.what()); |
1123 | } |
1124 | |
1125 | try |
1126 | { |
1127 | - RuntimeConfig c(TEST_SRC_DIR "/BadReapExpiry.ini"); |
1128 | + RuntimeConfig c(TEST_DIR "/BadReapExpiry.ini"); |
1129 | FAIL(); |
1130 | } |
1131 | catch (ConfigException const& e) |
1132 | { |
1133 | - EXPECT_STREQ("unity::scopes::ConfigException: \"" TEST_SRC_DIR "/BadReapExpiry.ini\": Illegal value (0) for " |
1134 | + EXPECT_STREQ("unity::scopes::ConfigException: \"" TEST_DIR "/BadReapExpiry.ini\": Illegal value (0) for " |
1135 | "Reap.Expiry: value must be > 0", |
1136 | e.what()); |
1137 | } |
1138 | |
1139 | try |
1140 | { |
1141 | - RuntimeConfig c(TEST_SRC_DIR "/BadReapInterval.ini"); |
1142 | + RuntimeConfig c(TEST_DIR "/BadReapInterval.ini"); |
1143 | FAIL(); |
1144 | } |
1145 | catch (ConfigException const& e) |
1146 | { |
1147 | - EXPECT_STREQ("unity::scopes::ConfigException: \"" TEST_SRC_DIR "/BadReapInterval.ini\": Illegal value (0) for " |
1148 | + EXPECT_STREQ("unity::scopes::ConfigException: \"" TEST_DIR "/BadReapInterval.ini\": Illegal value (0) for " |
1149 | "Reap.Interval: value must be > 0", |
1150 | e.what()); |
1151 | } |
1152 | @@ -196,12 +196,12 @@ |
1153 | { |
1154 | unsetenv("HOME"); |
1155 | |
1156 | - RuntimeConfig c(TEST_SRC_DIR "/NoCacheDir.ini"); |
1157 | + RuntimeConfig c(TEST_DIR "/NoCacheDir.ini"); |
1158 | FAIL(); |
1159 | } |
1160 | catch (ConfigException const& e) |
1161 | { |
1162 | - EXPECT_STREQ("unity::scopes::ConfigException: \"" TEST_SRC_DIR "/NoCacheDir.ini\": No CacheDir configured and " |
1163 | + EXPECT_STREQ("unity::scopes::ConfigException: \"" TEST_DIR "/NoCacheDir.ini\": No CacheDir configured and " |
1164 | "failed to get default:\n unity::ResourceException: RuntimeConfig::default_cache_directory(): " |
1165 | "$HOME not set", |
1166 | e.what()); |
1167 | @@ -211,12 +211,12 @@ |
1168 | { |
1169 | unsetenv("HOME"); |
1170 | |
1171 | - RuntimeConfig c(TEST_SRC_DIR "/NoConfigDir.ini"); |
1172 | + RuntimeConfig c(TEST_DIR "/NoConfigDir.ini"); |
1173 | FAIL(); |
1174 | } |
1175 | catch (ConfigException const& e) |
1176 | { |
1177 | - EXPECT_STREQ("unity::scopes::ConfigException: \"" TEST_SRC_DIR "/NoConfigDir.ini\": No ConfigDir configured and " |
1178 | + EXPECT_STREQ("unity::scopes::ConfigException: \"" TEST_DIR "/NoConfigDir.ini\": No ConfigDir configured and " |
1179 | "failed to get default:\n unity::ResourceException: RuntimeConfig::default_config_directory(): " |
1180 | "$HOME not set", |
1181 | e.what()); |
1182 | @@ -226,13 +226,13 @@ |
1183 | { |
1184 | unsetenv("HOME"); |
1185 | |
1186 | - RuntimeConfig c(TEST_SRC_DIR "/NoLogDir.ini"); |
1187 | + RuntimeConfig c(TEST_DIR "/NoLogDir.ini"); |
1188 | FAIL(); |
1189 | } |
1190 | catch (ConfigException const& e) |
1191 | { |
1192 | // Using regex here because error message returned by glib changed from Utopic to Vivid. |
1193 | - // The final .* takes care of the difference. Note that, instead of using TEST_SRC_DIR, we |
1194 | + // The final .* takes care of the difference. Note that, instead of using TEST_DIR, we |
1195 | // use .+. That's because, when building with bzr bd, we end up with a '+' in the path, |
1196 | // and that is a regex metacharacter, causing the match to fail. |
1197 | boost::regex r("unity::scopes::ConfigException: \".+/NoLogDir.ini\": " |
1198 | @@ -246,12 +246,12 @@ |
1199 | { |
1200 | unsetenv("HOME"); |
1201 | |
1202 | - RuntimeConfig c(TEST_SRC_DIR "/NoAppDir.ini"); |
1203 | + RuntimeConfig c(TEST_DIR "/NoAppDir.ini"); |
1204 | FAIL(); |
1205 | } |
1206 | catch (ConfigException const& e) |
1207 | { |
1208 | - EXPECT_STREQ("unity::scopes::ConfigException: \"" TEST_SRC_DIR "/NoAppDir.ini\": " |
1209 | + EXPECT_STREQ("unity::scopes::ConfigException: \"" TEST_DIR "/NoAppDir.ini\": " |
1210 | "No AppDir configured and failed to get default:\n" |
1211 | " unity::ResourceException: RuntimeConfig::default_app_directory(): $HOME not set", |
1212 | e.what()); |
1213 | @@ -259,24 +259,24 @@ |
1214 | |
1215 | try |
1216 | { |
1217 | - RuntimeConfig c(TEST_SRC_DIR "/BadLogFileSize.ini"); |
1218 | + RuntimeConfig c(TEST_DIR "/BadLogFileSize.ini"); |
1219 | FAIL(); |
1220 | } |
1221 | catch (ConfigException const& e) |
1222 | { |
1223 | - EXPECT_STREQ("unity::scopes::ConfigException: \"" TEST_SRC_DIR "/BadLogFileSize.ini\": " |
1224 | + EXPECT_STREQ("unity::scopes::ConfigException: \"" TEST_DIR "/BadLogFileSize.ini\": " |
1225 | "Illegal value (999) for Log.MaxFileSize: value must be > 1024", |
1226 | e.what()); |
1227 | } |
1228 | |
1229 | try |
1230 | { |
1231 | - RuntimeConfig c(TEST_SRC_DIR "/BadLogDirSize.ini"); |
1232 | + RuntimeConfig c(TEST_DIR "/BadLogDirSize.ini"); |
1233 | FAIL(); |
1234 | } |
1235 | catch (ConfigException const& e) |
1236 | { |
1237 | - EXPECT_STREQ("unity::scopes::ConfigException: \"" TEST_SRC_DIR "/BadLogDirSize.ini\": " |
1238 | + EXPECT_STREQ("unity::scopes::ConfigException: \"" TEST_DIR "/BadLogDirSize.ini\": " |
1239 | "Illegal value (1024) for Log.MaxDirSize: value must be > Log.MaxFileSize (2048)", |
1240 | e.what()); |
1241 | } |
1242 | |
1243 | === modified file 'test/gtest/scopes/internal/Utils/CMakeLists.txt' |
1244 | --- test/gtest/scopes/internal/Utils/CMakeLists.txt 2014-06-25 14:38:30 +0000 |
1245 | +++ test/gtest/scopes/internal/Utils/CMakeLists.txt 2015-04-23 15:43:14 +0000 |
1246 | @@ -1,4 +1,5 @@ |
1247 | add_executable(Utils_test Utils_test.cpp) |
1248 | +add_definitions(-DTEST_DIR="${CMAKE_CURRENT_BINARY_DIR}") |
1249 | target_link_libraries(Utils_test ${TESTLIBS}) |
1250 | |
1251 | add_test(Utils Utils_test) |
1252 | |
1253 | === modified file 'test/gtest/scopes/internal/Utils/Utils_test.cpp' |
1254 | --- test/gtest/scopes/internal/Utils/Utils_test.cpp 2014-11-17 01:29:26 +0000 |
1255 | +++ test/gtest/scopes/internal/Utils/Utils_test.cpp 2015-04-23 15:43:14 +0000 |
1256 | @@ -17,11 +17,14 @@ |
1257 | */ |
1258 | |
1259 | #include <unity/scopes/internal/Utils.h> |
1260 | + |
1261 | +#include <boost/filesystem.hpp> |
1262 | +#include <gtest/gtest.h> |
1263 | #include <unity/UnityExceptions.h> |
1264 | -#include <gtest/gtest.h> |
1265 | |
1266 | using namespace unity::scopes; |
1267 | using namespace unity::scopes::internal; |
1268 | +using namespace std; |
1269 | |
1270 | TEST(Utils, uncamelcase) |
1271 | { |
1272 | @@ -47,7 +50,7 @@ |
1273 | } |
1274 | { |
1275 | Variant out; |
1276 | - EXPECT_TRUE(convert_to<std::string>("foo", out)); |
1277 | + EXPECT_TRUE(convert_to<string>("foo", out)); |
1278 | EXPECT_EQ("foo", out.get_string()); |
1279 | } |
1280 | { |
1281 | @@ -66,3 +69,66 @@ |
1282 | EXPECT_FALSE(out.get_bool()); |
1283 | } |
1284 | } |
1285 | + |
1286 | +void empty_dir(string const& dir) |
1287 | +{ |
1288 | + namespace fs = boost::filesystem; |
1289 | + try |
1290 | + { |
1291 | + for (fs::directory_iterator end, it(dir); it != end; ++it) |
1292 | + { |
1293 | + remove_all(it->path()); |
1294 | + } |
1295 | + } |
1296 | + catch (...) |
1297 | + { |
1298 | + } |
1299 | +} |
1300 | + |
1301 | +int get_perms(string const& path) |
1302 | +{ |
1303 | + struct stat st; |
1304 | + if (stat(path.c_str(), &st) != 0) |
1305 | + { |
1306 | + string msg = "get_perms(): cannot stat " + path + ": errno = " + to_string(errno); |
1307 | + throw runtime_error(msg); |
1308 | + } |
1309 | + return st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); |
1310 | +} |
1311 | + |
1312 | +TEST(Utils, make_directories) |
1313 | +{ |
1314 | + using namespace std; |
1315 | + |
1316 | + string test_root = TEST_DIR "/dir"; |
1317 | + |
1318 | + empty_dir(test_root); |
1319 | + rmdir(test_root.c_str()); // First time around, make sure that test_root doesn't exist. |
1320 | + |
1321 | + make_directories(test_root, 0700); |
1322 | + EXPECT_EQ(0700, get_perms(test_root)); |
1323 | + |
1324 | + // Do it a second time, to test that it works whether test_root exists or not. |
1325 | + make_directories(test_root, 0700); |
1326 | + EXPECT_EQ(0700, get_perms(test_root)); |
1327 | + |
1328 | + // Change permissions on test_root and make a dir underneath it. |
1329 | + chmod(test_root.c_str(), 0777); |
1330 | + string child = test_root + "/child"; |
1331 | + int old_umask = umask(0000); |
1332 | + make_directories(child, 0555); |
1333 | + umask(old_umask); |
1334 | + |
1335 | + // test_root permissions must still be the same, child must have perm 0555. |
1336 | + EXPECT_EQ(0777, get_perms(test_root)); |
1337 | + EXPECT_EQ(0555, get_perms(child)); |
1338 | + |
1339 | + // Remove permission from child dir. |
1340 | + chmod(child.c_str(), 0000); |
1341 | + |
1342 | + // Check that we fail silently trying to create the grandchild. |
1343 | + string grandchild = child + "/grandchild"; |
1344 | + make_directories(grandchild, 0555); |
1345 | + |
1346 | + chmod(child.c_str(), 0777); // Don't leave the dir behind without permissions. |
1347 | +} |
1348 | |
1349 | === modified file 'unity-scopes.map' |
1350 | --- unity-scopes.map 2014-12-01 14:12:24 +0000 |
1351 | +++ unity-scopes.map 2015-04-23 15:43:14 +0000 |
1352 | @@ -16,6 +16,7 @@ |
1353 | unity::scopes::internal::Executor::*; |
1354 | unity::scopes::internal::IniSettingsSchema::*; |
1355 | unity::scopes::internal::JsonSettingsSchema::*; |
1356 | + unity::scopes::internal::make_directories*; |
1357 | unity::scopes::internal::MiddlewareBase::*; |
1358 | unity::scopes::internal::MiddlewareFactory::*; |
1359 | unity::scopes::internal::RegistryConfig::*; |
PASSED: Continuous integration, rev:283 jenkins. qa.ubuntu. com/job/ unity-scopes- api-ci/ 610/ jenkins. qa.ubuntu. com/job/ unity-scopes- api-vivid- amd64-ci/ 144 jenkins. qa.ubuntu. com/job/ unity-scopes- api-vivid- armhf-ci/ 135 jenkins. qa.ubuntu. com/job/ unity-scopes- api-vivid- armhf-ci/ 135/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ unity-scopes- api-vivid- i386-ci/ 136
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- scopes- api-ci/ 610/rebuild
http://