Merge lp:~michihenning/unity-scopes-api/set-env-vars into lp:unity-scopes-api/devel

Proposed by Michi Henning
Status: Merged
Approved by: Pete Woods
Approved revision: 424
Merged at revision: 429
Proposed branch: lp:~michihenning/unity-scopes-api/set-env-vars
Merge into: lp:unity-scopes-api/devel
Prerequisite: lp:~michihenning/unity-scopes-api/scope-cache-dir
Diff against target: 932 lines (+332/-81)
33 files modified
HACKING (+1/-1)
RELEASE_NOTES.md (+4/-2)
debian/libunity-scopes2.symbols (+2/-1)
include/unity/scopes/AbstractScopeBase.h (+1/-0)
include/unity/scopes/ScopeBase.h (+17/-2)
include/unity/scopes/internal/DynamicLoader.h (+1/-1)
include/unity/scopes/internal/RuntimeImpl.h (+4/-3)
include/unity/scopes/internal/ScopeBaseImpl.h (+6/-0)
scoperunner/scoperunner.cpp (+25/-7)
src/scopes/ScopeBase.cpp (+5/-0)
src/scopes/internal/RegistryObject.cpp (+22/-7)
src/scopes/internal/RuntimeImpl.cpp (+36/-13)
src/scopes/internal/ScopeBaseImpl.cpp (+21/-0)
src/scopes/internal/zmq_middleware/ZmqConfig.cpp (+5/-1)
test/gtest/scopes/IdleShutdown/SlowSearchScope.h (+7/-7)
test/gtest/scopes/Invocation/EmptyScope.h (+5/-6)
test/gtest/scopes/Invocation/TestScope.cpp (+1/-1)
test/gtest/scopes/Invocation/TestScope.h (+5/-6)
test/gtest/scopes/Registry/scopes/testscopeA/CMakeLists.txt (+5/-1)
test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.cpp (+10/-1)
test/gtest/scopes/Runtime/TestScope.h (+5/-6)
test/gtest/scopes/internal/DynamicLoader/DynamicLoader_test.cpp (+3/-3)
test/gtest/scopes/internal/RegistryObject/CMakeLists.txt (+2/-0)
test/gtest/scopes/internal/RegistryObject/RegistryObject_test.cpp (+3/-3)
test/gtest/scopes/internal/RuntimeImpl/CMakeLists.txt (+3/-2)
test/gtest/scopes/internal/RuntimeImpl/Registry.ini.in (+1/-1)
test/gtest/scopes/internal/RuntimeImpl/Runtime.ini.in (+2/-1)
test/gtest/scopes/internal/RuntimeImpl/RuntimeImpl_test.cpp (+43/-5)
test/gtest/scopes/internal/RuntimeImpl/TestScope.cpp (+40/-0)
test/gtest/scopes/internal/RuntimeImpl/TestScope.h (+36/-0)
test/gtest/scopes/internal/RuntimeImpl/TestScope.ini.in (+4/-0)
test/gtest/scopes/testing/IsolatedScope/scope.cpp (+5/-0)
test/gtest/scopes/testing/IsolatedScope/scope.h (+2/-0)
To merge this branch: bzr merge lp:~michihenning/unity-scopes-api/set-env-vars
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Pete Woods (community) Approve
Michal Hruby (community) Needs Information
Review via email: mp+225782@code.launchpad.net

Commit message

Added setting of LD_LIBRARY_PATH to scoperunner and scoperegistry to include <scope_install_dir> and <scope_install_dir>/lib.

Added tmp_directory() method to ScopeBase that returns path under $XDG_RUNTIME_DIR.

Description of the change

Added setting of LD_LIBRARY_PATH to scoperunner and scoperegistry to include <scope_install_dir> and <scope_install_dir>/lib.

Added tmp_directory() method to ScopeBase that returns path under $XDG_RUNTIME_DIR.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Michal Hruby (mhr3) wrote :

8 + {

Am I reading this right that all these envvars are set after the scope module is loaded and the scope itself instantiated? I think that's too late, should be done in the exec call (exec being done by the registry that is).

review: Needs Information
Revision history for this message
Jamie Strandboge (jdstrand) wrote :

TMPDIR is currently set to:
setenv("TMPDIR", cache_dir_.c_str(), 1);

Based on what you set XDG_DATA_HOME and that my recommendation was to set it to 'XDG_DATA_HOME=$HOME/.local/share', it seems that cache_dir_.c_str() is '~/.local/share/' which is not a writable path. TMPDIR should be set like so:

TMPDIR=$XDG_RUNTIME_DIR/confined-scopes/leaf-net/<'name' from click manifest>

We want to have TMPDIR be set to something in /run because if a scope doesn't clean up after itself, at least a reboot will remove the files (this is what we do for apps).

Also, PATH and LD_LIBRARY_PATH are being unconditionally set. They should only be set in the manner you are setting them if they are not already set. If they are set at the time you are setting up the environment, then you should prepend these values to existing values. Example pseudo code:
  if PATH is empty:
     PATH=scope_base->scope_directory().c_str():scope_base->scope_directory().c_str() + "/bin"
  else:
     PATH=scope_base->scope_directory().c_str():scope_base->scope_directory().c_str() + "/bin":$PATH

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

> Am I reading this right that all these envvars are set after the scope module
> is loaded and the scope itself instantiated? I think that's too late, should
> be done in the exec call (exec being done by the registry that is).

The setup is done after the scope's create function is called, but before start() is called (which initialises the scope). It may be possible to do the setup before the create function is called. (I'll have a look at that.)

Note that scopes aren't just run by the registry, but may be started by hand and, with the Go binding, may use their own scoperunner. In other words, there may not be any exec call at all. (That's the case for many of the tests too.)

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

> TMPDIR is currently set to:
> setenv("TMPDIR", cache_dir_.c_str(), 1);
>
> Based on what you set XDG_DATA_HOME and that my recommendation was to set it
> to 'XDG_DATA_HOME=$HOME/.local/share', it seems that cache_dir_.c_str() is
> '~/.local/share/' which is not a writable path.

Not quite. cache_dir_ is $HOME/.local/share/unity-scopes/<scope_type>/<scope_id>

For example: /home/michi/.local/share/unity-scopes/leaf-net/com.triodia.scopes.michiscope

In other words, I was setting TMPDIR to the same location as cache_dir_, which is the scope's writable data directory.

> TMPDIR should be set like so:
>
> TMPDIR=$XDG_RUNTIME_DIR/confined-scopes/leaf-net/<'name' from click manifest>

I can't get at the click manifest. All I have is the scope ID. I *think* that's always the same as the click manifest name?

> We want to have TMPDIR be set to something in /run because if a scope doesn't
> clean up after itself, at least a reboot will remove the files (this is what
> we do for apps).

Yes, I agree with that, something under /run/user/<uid> is better, so it gets cleaned up eventually.

So, I could do:

/run/user/<uid>/confined-scopes/<scope_type>/<scope_id>

For example, TMPDIR would be:

/run/user/1000/confined-scopes/leaf-net/com.triodia.scopes.michiscope

Whether to substitute "leaf-net", "leaf-fs", or "aggregator" (or "unconfined", if we prefer that) would depend on what cache directory I found earlier: if the cache directory contains "leaf-fs", TMPDIR would contain "leaf-fs" too.

One other thing though… Does it makes sense to have XDG_RUNTIME_DIR set to /run/user/<uid>?
Considering that this is not a location the scope can write to, wouldn't it be better to set
XDG_RUNTIME_DIR to /run/user/1000/confined-scopes/leaf-net/com.triodia.scopes.michiscope,
and TMPDIR to /run/user/1000/confined-scopes/leaf-net/com.triodia.scopes.michiscope/tmp?

Aargh… What should an *unconfined* scope have in that path? Surely not "confined-scopes"?
Would it be better to use just "scopes" whether a scope is confined or not? E.g, for a leaf-net scope:

/run/user/1000/scopes/leaf-net/com.triodia.scopes.michiscope

And for an aggregator:

/run/user/1000/scopes/aggregator/com.triodia.scopes.michiscope (or possibly "unconfined" instead of "aggregator")

Would that work?

There is also the issue with deeply-nested paths under /run/user/<uid>. As you say, things under /run/user/<uid> may be periodically removed. I assume this means that I should create the directory hierarchy (whichever one we settle on) under /run/user/<uid> if it does not exist? (For now, I'll be creating the directories, with permission 0700.)

> Also, PATH and LD_LIBRARY_PATH are being unconditionally set. They should only
> be set in the manner you are setting them if they are not already set.

I wasn't sure whether it's a good idea to rely on the environment that is inherited by the scoperunner, which is why I smashed these two variables. I'll change the code to prepend to LD_LIBRARY_PATH and PATH instead.

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

The scope's tmp dir is now available via ScopeBase::tmp_directory().

I've removed the environment variable settings, except for LD_LIBRARY_PATH,
which is set by the registry and the scoperunner.

The scope loader uses immediate binding, so we get a sensible error message
if a symbol cannot be resolved when the run time is created, rather than
having the scope fall over after it has been started due to a library
it depends on not being found.

I'm not setting LD_LIBRARY_PATH in RuntimeImpl::run_scope().

It's not impossible to do this, but hard:
getenv()/setenv() are not thread-safe. To do this properly, I'd have
to read the current LD_LIBRARY_PATH setting, modify it for the scope about
to be run and, once the scope has launched (or not), restore the previous
setting again, all while holding a lock. Otherwise, if more than
one run time instance is created in the same process, each for a different
scope, LD_LIBRARY_PATH would grow by two directories for each scope.

What this means is that a custom scope runner will have to set LD_LIBRARY_PATH
to include <scope_config_dir> and <scope_config_dir>/lib before instantiating
the run time. Seeing that we won't write scope runners by the dozen, I suspect
this is the more sensible course of action.

There is no need to set PATH. The scope *knows* what it has installed and where,
so there is no need to add anything special to the PATH just for the scope.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michal Hruby (mhr3) wrote :

23 - (c++)"unity::scopes::Category::Category(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unity::scopes::CategoryRenderer const&)@Base" 0.4.0+14.04.20140312.1
24 + (c++)"unity::scopes::Category::Category(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unity::scopes::CategoryRenderer const&)@Base" 0replaceme

Something wrong here, it just replaced the version with 0replaceme, revert pls.

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

The latest version uses the "try-and-see-what-you-get" approach.

If the scope is unconfined, the two directories below data_dir (unconfined/<scope_id>) are created automatically (if possible). If the directory exists, an attempt is made to create a tmp file. If that succeeds, the scope is unconfined. Otherwise, the scope is confined (leaf-net).

The click installation will have to create <data_dir>/leaf-net. If the scope's profile allows the scope to create <data_dir>/leaf-net/<scope_id>, it will do so. Otherwise, the click installation will have to create that directory for the scope.

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

Could someone review this please?

Revision history for this message
Pete Woods (pete-woods) :
review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Pete Woods (pete-woods) wrote :

D'oh! Merge fail!

424. By Michi Henning

Merged devel and resolved conflicts.

Revision history for this message
Michal Hruby (mhr3) wrote :

Could you also update the description and commit message please? Seems like this isn't doing much with environment variables anymore.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
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 'HACKING'
2--- HACKING 2014-07-10 00:24:33 +0000
3+++ HACKING 2014-07-30 20:39:51 +0000
4@@ -125,7 +125,7 @@
5 $ make formatcode
6
7 Thread and address sanitizer
8-----------------
9+----------------------------
10
11 Set SANITIZER to "thread" or "address" to build with the
12 corresponding sanitizer enabled.
13
14=== modified file 'RELEASE_NOTES.md'
15--- RELEASE_NOTES.md 2014-07-28 13:45:38 +0000
16+++ RELEASE_NOTES.md 2014-07-30 20:39:51 +0000
17@@ -3,10 +3,12 @@
18
19 Changes in version 0.6.0
20 ========================
21+ - Added tmp_directory() method to ScopeBase, so a scope can find out where it can write temporary files.
22+
23+ - Added cache_directory() method to ScopeBase, so a scope can find out where it can write its files.
24+
25 - Upgraded finished() callback to be more flexible and expandable.
26
27- - Added cache_directory() method to ScopeBase, so a scope can find out where it can write its files.
28-
29 - Refactored scoperunner and ScopeLoader. ScopeLoader no longer knows about the registry and
30 scoperunner now calls RuntimeImpl::run_scope() to set the scope running, instead of duplicating
31 lots of functionality.
32
33=== modified file 'debian/libunity-scopes2.symbols'
34--- debian/libunity-scopes2.symbols 2014-07-29 10:22:45 +0000
35+++ debian/libunity-scopes2.symbols 2014-07-30 20:39:51 +0000
36@@ -753,7 +753,7 @@
37 (c++)"unity::scopes::internal::RuntimeImpl::reply_reaper() const@Base" 0.4.0+14.04.20140312.1
38 (c++)"unity::scopes::internal::RuntimeImpl::ss_configfile() const@Base" 0.4.4+14.10.20140508
39 (c++)"unity::scopes::internal::RuntimeImpl::waiter_thread(std::shared_ptr<unity::scopes::internal::ThreadSafeQueue<std::future<void> > > const&) const@Base" 0.4.3+14.10.20140428
40- (c++)"unity::scopes::internal::RuntimeImpl::find_cache_dir() const@Base" 0replaceme
41+ (c++)"unity::scopes::internal::RuntimeImpl::find_cache_dir(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&) const@Base" 0replaceme
42 (c++)"unity::scopes::internal::RuntimeImpl::proxy_to_string(std::shared_ptr<unity::scopes::Object> const&) const@Base" 0.4.0+14.04.20140312.1
43 (c++)"unity::scopes::internal::RuntimeImpl::string_to_proxy(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const@Base" 0.4.0+14.04.20140312.1
44 (c++)"unity::scopes::internal::RuntimeImpl::registry_identity() const@Base" 0.4.0+14.04.20140312.1
45@@ -837,6 +837,7 @@
46 (c++)"unity::scopes::internal::StateReceiverObject::state_received() const@Base" 0.4.2+14.04.20140404.2
47 (c++)"unity::scopes::QueryBase::valid() const@Base" 0.4.3+14.10.20140428
48 (c++)"unity::scopes::QueryBase::settings() const@Base" 0replaceme
49+ (c++)"unity::scopes::ScopeBase::tmp_directory() const@Base" 0replaceme
50 (c++)"unity::scopes::ScopeBase::cache_directory() const@Base" 0replaceme
51 (c++)"unity::scopes::ScopeBase::scope_directory() const@Base" 0.4.2+14.04.20140404.2
52 (c++)"unity::scopes::ScopeBase::registry() const@Base" 0replaceme
53
54=== modified file 'include/unity/scopes/AbstractScopeBase.h'
55--- include/unity/scopes/AbstractScopeBase.h 2014-07-10 02:22:23 +0000
56+++ include/unity/scopes/AbstractScopeBase.h 2014-07-30 20:39:51 +0000
57@@ -53,6 +53,7 @@
58 virtual PreviewQueryBase::UPtr preview(Result const& result, ActionMetadata const& metadata) = 0;
59 virtual std::string scope_directory() const = 0;
60 virtual std::string cache_directory() const = 0;
61+ virtual std::string tmp_directory() const = 0;
62 virtual unity::scopes::RegistryProxy registry() const = 0;
63 virtual VariantMap settings() const = 0;
64 /// @endcond
65
66=== modified file 'include/unity/scopes/ScopeBase.h'
67--- include/unity/scopes/ScopeBase.h 2014-07-10 22:53:35 +0000
68+++ include/unity/scopes/ScopeBase.h 2014-07-30 20:39:51 +0000
69@@ -90,6 +90,7 @@
70 virtual void start(std::string const& scope_id); // Optional
71 virtual void stop(); // Optional
72 virtual void run(); // Optional
73+ // ...
74 };
75 ~~~
76
77@@ -261,15 +262,29 @@
78 \note The cache directory is available only after this ScopeBase is instantiated; do not
79 call this method from the constructor!
80
81- \return The root directory of the filesystem sub-tree that is writable for the scope.
82+ \return The root directory of a filesystem sub-tree that is writable for the scope.
83 \throws LogicException if called from the constructor of this instance.
84 */
85 virtual std::string cache_directory() const final;
86
87 /**
88+ \brief Returns a tmp directory that is (exclusively) writable for the scope.
89+
90+ This directory is periodically cleaned of unused files. The exact amount of time
91+ may vary, but is on the order of a few hours.
92+
93+ \note The tmp directory is available only after this ScopeBase is instantiated; do not
94+ call this method from the constructor!
95+
96+ \return A directory for temporary files.
97+ \throws LogicException if called from the constructor of this instance.
98+ */
99+ virtual std::string tmp_directory() const final;
100+
101+ /**
102 \brief Returns the proxy to the registry.
103
104- \note The registr proxy is available only after this ScopeBase is instantiated; do not
105+ \note The registry proxy is available only after this ScopeBase is instantiated; do not
106 call this method from the constructor!
107
108 \return The proxy to the registry.
109
110=== modified file 'include/unity/scopes/internal/DynamicLoader.h'
111--- include/unity/scopes/internal/DynamicLoader.h 2014-02-18 05:04:01 +0000
112+++ include/unity/scopes/internal/DynamicLoader.h 2014-07-30 20:39:51 +0000
113@@ -86,7 +86,7 @@
114 automatic, noclose
115 };
116
117- static UPtr create(std::string const& path, Binding b = Binding::lazy, Unload ul = Unload::automatic);
118+ static UPtr create(std::string const& path, Binding b = Binding::now, Unload ul = Unload::automatic);
119
120 typedef void (*VoidFunc)();
121 VoidFunc find_function(std::string const& symbol);
122
123=== modified file 'include/unity/scopes/internal/RuntimeImpl.h'
124--- include/unity/scopes/internal/RuntimeImpl.h 2014-07-22 08:02:32 +0000
125+++ include/unity/scopes/internal/RuntimeImpl.h 2014-07-30 20:39:51 +0000
126@@ -53,8 +53,8 @@
127 Reaper::SPtr reply_reaper() const;
128 ThreadPool::SPtr async_pool() const;
129 ThreadSafeQueue<std::future<void>>::SPtr future_queue() const;
130- void run_scope(ScopeBase* const scope_base, std::string const& scope_ini_file);
131- void run_scope(ScopeBase* const scope_base, std::string const& runtime_ini_file, std::string const& scope_ini_file);
132+ void run_scope(ScopeBase* scope_base, std::string const& scope_ini_file);
133+ void run_scope(ScopeBase* scope_base, std::string const& runtime_ini_file, std::string const& scope_ini_file);
134
135 ObjectProxy string_to_proxy(std::string const& s) const;
136 std::string proxy_to_string(ObjectProxy const& proxy) const;
137@@ -64,7 +64,7 @@
138 private:
139 RuntimeImpl(std::string const& scope_id, std::string const& configfile);
140 void waiter_thread(ThreadSafeQueue<std::future<void>>::SPtr const& queue) const noexcept;
141- std::string find_cache_dir() const;
142+ std::string find_cache_dir(std::string& confinement_type) const;
143
144 bool destroyed_;
145 std::string scope_id_;
146@@ -78,6 +78,7 @@
147 int reap_expiry_;
148 int reap_interval_;
149 std::string data_dir_;
150+ std::string tmp_dir_;
151 mutable Reaper::SPtr reply_reaper_;
152 mutable ThreadPool::SPtr async_pool_; // Pool of invocation threads for async query creation
153 mutable ThreadSafeQueue<std::future<void>>::SPtr future_queue_;
154
155=== modified file 'include/unity/scopes/internal/ScopeBaseImpl.h'
156--- include/unity/scopes/internal/ScopeBaseImpl.h 2014-07-04 05:50:16 +0000
157+++ include/unity/scopes/internal/ScopeBaseImpl.h 2014-07-30 20:39:51 +0000
158@@ -48,6 +48,9 @@
159 void set_cache_directory(std::string const& path);
160 std::string cache_directory() const;
161
162+ void set_tmp_directory(std::string const& path);
163+ std::string tmp_directory() const;
164+
165 void set_registry(RegistryProxy const& registry);
166 RegistryProxy registry() const;
167
168@@ -62,6 +65,9 @@
169 std::string cache_directory_;
170 bool cache_dir_initialized_;
171
172+ std::string tmp_directory_;
173+ bool tmp_dir_initialized_;
174+
175 unity::scopes::RegistryProxy registry_;
176 bool registry_initialized_;
177
178
179=== modified file 'scoperunner/scoperunner.cpp'
180--- scoperunner/scoperunner.cpp 2014-07-29 10:22:45 +0000
181+++ scoperunner/scoperunner.cpp 2014-07-30 20:39:51 +0000
182@@ -29,8 +29,10 @@
183 #include <unity/UnityExceptions.h>
184
185 #include <unity/scopes/internal/max_align_clang_bug.h> // TODO: remove this once clang 3.5.2 is released
186-#include <boost/filesystem/path.hpp>
187+#include <boost/algorithm/string.hpp>
188+#include <boost/filesystem.hpp>
189 #include <core/posix/signal.h>
190+#include <core/posix/this_process.h>
191
192 #include <cassert>
193 #include <future>
194@@ -69,13 +71,29 @@
195 std::thread trap_worker([trap]() { trap->run(); });
196
197 // Figure out what the scope ID is from the name of the scope config file.
198- filesystem::path scope_config_path(scope_config);
199+ auto scope_config_path = filesystem::canonical(scope_config);
200 string lib_dir = scope_config_path.parent_path().native();
201 string scope_id = scope_config_path.stem().native();
202
203- if (!lib_dir.empty())
204 {
205- lib_dir += '/';
206+ // Make sure we set LD_LIBRARY_PATH to include <lib_dir> and <lib_dir>/lib
207+ // before loading the scope's .so.
208+ string scope_ld_lib_path = lib_dir + ":" + lib_dir + "/lib";
209+ string ld_lib_path = core::posix::this_process::env::get("LD_LIBRARY_PATH", "");
210+ if (!starts_with(ld_lib_path, lib_dir))
211+ {
212+ scope_ld_lib_path = scope_ld_lib_path + (ld_lib_path.empty() ? "" : (":" + ld_lib_path));
213+ try
214+ {
215+ // No overwrite option for this_process::env::set(), need to unset first
216+ core::posix::this_process::env::unset_or_throw("LD_LIBRARY_PATH");
217+ core::posix::this_process::env::set_or_throw("LD_LIBRARY_PATH", scope_ld_lib_path);
218+ }
219+ catch (std::exception const&)
220+ {
221+ throw unity::ResourceException("cannot set LD_LIBRARY_PATH for scope " + scope_id);
222+ }
223+ }
224 }
225
226 int exit_status = 1;
227@@ -83,9 +101,9 @@
228 {
229 // For a scope_id "Fred", we look for the library as "libFred.so", "Fred.so", and "scope.so".
230 vector<string> libs;
231- libs.push_back(lib_dir + "lib" + scope_id + ".so");
232- libs.push_back(lib_dir + scope_id + ".so");
233- libs.push_back(lib_dir + "scope.so");
234+ libs.push_back(lib_dir + "/lib" + scope_id + ".so");
235+ libs.push_back(lib_dir + "/" + scope_id + ".so");
236+ libs.push_back(lib_dir + "/scope.so");
237 string failed_libs;
238 ScopeLoader::SPtr loader;
239 exception_ptr ep;
240
241=== modified file 'src/scopes/ScopeBase.cpp'
242--- src/scopes/ScopeBase.cpp 2014-07-10 22:53:35 +0000
243+++ src/scopes/ScopeBase.cpp 2014-07-30 20:39:51 +0000
244@@ -82,6 +82,11 @@
245 return p->cache_directory();
246 }
247
248+std::string ScopeBase::tmp_directory() const
249+{
250+ return p->tmp_directory();
251+}
252+
253 RegistryProxy ScopeBase::registry() const
254 {
255 return p->registry();
256
257=== modified file 'src/scopes/internal/RegistryObject.cpp'
258--- src/scopes/internal/RegistryObject.cpp 2014-07-28 03:51:36 +0000
259+++ src/scopes/internal/RegistryObject.cpp 2014-07-30 20:39:51 +0000
260@@ -24,6 +24,8 @@
261 #include <unity/UnityExceptions.h>
262 #include <unity/util/ResourcePtr.h>
263
264+#include <boost/algorithm/string.hpp>
265+#include <boost/filesystem.hpp>
266 #include <core/posix/child_process.h>
267 #include <core/posix/exec.h>
268
269@@ -413,13 +415,26 @@
270 argv.insert(argv.end(), {exec_data_.runtime_config, exec_data_.scope_config});
271 }
272
273- std::map<std::string, std::string> env;
274- core::posix::this_process::env::for_each([&env](const std::string& key, const std::string& value)
275- {
276- env.insert(std::make_pair(key, value));
277- });
278-
279- {
280+ {
281+ // Copy current env vars into env.
282+ std::map<std::string, std::string> env;
283+ core::posix::this_process::env::for_each([&env](const std::string& key, const std::string& value)
284+ {
285+ env.insert(std::make_pair(key, value));
286+ });
287+
288+ // Make sure we set LD_LIBRARY_PATH to include <lib_dir> and <lib_dir>/lib
289+ // before exec'ing the scope.
290+ auto scope_config_path = boost::filesystem::canonical(exec_data_.scope_config);
291+ string lib_dir = scope_config_path.parent_path().native();
292+ string scope_ld_lib_path = lib_dir + ":" + lib_dir + "/lib";
293+ string ld_lib_path = core::posix::this_process::env::get("LD_LIBRARY_PATH", "");
294+ if (!boost::algorithm::starts_with(ld_lib_path, lib_dir))
295+ {
296+ scope_ld_lib_path = scope_ld_lib_path + (ld_lib_path.empty() ? "" : (":" + ld_lib_path));
297+ }
298+ env["LD_LIBRARY_PATH"] = scope_ld_lib_path; // Overwrite any LD_LIBRARY_PATH entry that may already be there.
299+
300 process_ = executor->exec(program, argv, env,
301 core::posix::StandardStream::stdin | core::posix::StandardStream::stdout,
302 exec_data_.confinement_profile);
303
304=== modified file 'src/scopes/internal/RuntimeImpl.cpp'
305--- src/scopes/internal/RuntimeImpl.cpp 2014-07-29 10:22:45 +0000
306+++ src/scopes/internal/RuntimeImpl.cpp 2014-07-30 20:39:51 +0000
307@@ -280,12 +280,12 @@
308 return future_queue_; // Immutable
309 }
310
311-void RuntimeImpl::run_scope(ScopeBase *const scope_base, string const& scope_ini_file)
312+void RuntimeImpl::run_scope(ScopeBase* scope_base, string const& scope_ini_file)
313 {
314 run_scope(scope_base, "", scope_ini_file);
315 }
316
317-void RuntimeImpl::run_scope(ScopeBase *const scope_base, string const& runtime_ini_file, string const& scope_ini_file)
318+void RuntimeImpl::run_scope(ScopeBase* scope_base, string const& runtime_ini_file, string const& scope_ini_file)
319 {
320 if (!scope_base)
321 {
322@@ -301,7 +301,7 @@
323 auto mw = factory()->create(scope_id_, reg_conf.mw_kind(), reg_conf.mw_configfile());
324
325 {
326- boost::filesystem::path dir = boost::filesystem::path(scope_ini_file).parent_path();
327+ boost::filesystem::path dir = boost::filesystem::canonical(scope_ini_file).parent_path();
328 scope_base->p->set_scope_directory(dir.native());
329 }
330
331@@ -328,7 +328,23 @@
332
333 scope_base->p->set_registry(registry_);
334
335- scope_base->p->set_cache_directory(find_cache_dir());
336+ string confinement_type;
337+ scope_base->p->set_cache_directory(find_cache_dir(confinement_type));
338+
339+ {
340+ // Set tmp dir.
341+ // We need to create any directories under /run/user/<uid> because they might not
342+ // exist. (/run/user/<uid> gets cleaned out periodically.)
343+ string path = string("/run/user/") + std::to_string(geteuid());
344+ path += "/scopes";
345+ ::mkdir(path.c_str(), 0700);
346+ path += "/" + confinement_type;
347+ ::mkdir(path.c_str(), 0700);
348+ path += "/" + scope_id_;
349+ ::mkdir(path.c_str(), 0700);
350+
351+ scope_base->p->set_tmp_directory(path);
352+ }
353
354 scope_base->start(scope_id_);
355
356@@ -391,7 +407,7 @@
357 }
358 }
359
360-string RuntimeImpl::find_cache_dir() const
361+string RuntimeImpl::find_cache_dir(string& confinement_type) const
362 {
363 // TODO: HACK: Until we get a fancier Apparmor query API, we try
364 // to create the scope cache dir and figure out whether
365@@ -403,13 +419,18 @@
366 // Otherwise, the scope must be confined, in which case
367 // we create <data_dir>/leaf-net and <data_dir>/leaf-net/<scope_id_>.
368
369- string cache_dir = data_dir_ + "/unconfined/" + scope_id_;
370+ ::mkdir(data_dir_.c_str(), 0700); // We don't care if this fails.
371+
372+ // Assume we are unconfined initially.
373+ confinement_type = "unconfined";
374+ string dir = data_dir_ + "/" + confinement_type;
375
376 // The following two mkdir() calls will fail if the scope is confined or
377 // the directories exist already.
378- ::mkdir((data_dir_ + "/unconfined").c_str(), 0700);
379- ::mkdir(cache_dir.c_str(), 0700);
380- string tmp = cache_dir + "/.unconfined_scope_XXXXXX";
381+ ::mkdir(dir.c_str(), 0700);
382+ dir += "/" + scope_id_;
383+ ::mkdir(dir.c_str(), 0700);
384+ string tmp = dir + "/.scope_tmp_XXXXXX";
385 int fd = mkstemp(const_cast<char*>(tmp.c_str())); // mkstemp() modifies its argument
386 if (fd != -1)
387 {
388@@ -420,11 +441,13 @@
389 else
390 {
391 // mkstemp() failed, the scope must be confined.
392- ::mkdir((data_dir_ + "/leaf-net").c_str(), 0700);
393- ::mkdir(cache_dir.c_str(), 0700);
394- cache_dir = data_dir_ + "/leaf-net/" + scope_id_;
395+ confinement_type = "leaf-net";
396+ dir = data_dir_ + "/" + confinement_type;
397+ ::mkdir(dir.c_str(), 0700);
398+ dir += "/" + scope_id_;
399+ ::mkdir(dir.c_str(), 0700);
400 }
401- return cache_dir;
402+ return dir;
403 }
404
405 } // namespace internal
406
407=== modified file 'src/scopes/internal/ScopeBaseImpl.cpp'
408--- src/scopes/internal/ScopeBaseImpl.cpp 2014-07-04 05:50:16 +0000
409+++ src/scopes/internal/ScopeBaseImpl.cpp 2014-07-30 20:39:51 +0000
410@@ -82,6 +82,27 @@
411 return cache_directory_;
412 }
413
414+void ScopeBaseImpl::set_tmp_directory(std::string const& path)
415+{
416+ lock_guard<mutex> lock(mutex_);
417+ tmp_directory_ = path;
418+ tmp_dir_initialized_ = true;
419+}
420+
421+std::string ScopeBaseImpl::tmp_directory() const
422+{
423+ lock_guard<mutex> lock(mutex_);
424+ if (!tmp_dir_initialized_)
425+ {
426+ throw LogicException("ScopeBase::tmp_directory() cannot be called from constructor");
427+ }
428+ if (tmp_directory_.empty())
429+ {
430+ throw ConfigException("ScopeBase::tmp_directory(): no tmp directory available");
431+ }
432+ return tmp_directory_;
433+}
434+
435 void ScopeBaseImpl::set_registry(RegistryProxy const& registry)
436 {
437 lock_guard<mutex> lock(mutex_);
438
439=== modified file 'src/scopes/internal/zmq_middleware/ZmqConfig.cpp'
440--- src/scopes/internal/zmq_middleware/ZmqConfig.cpp 2014-07-25 01:23:02 +0000
441+++ src/scopes/internal/zmq_middleware/ZmqConfig.cpp 2014-07-30 20:39:51 +0000
442@@ -55,7 +55,7 @@
443
444 // Set the endpoint directory if it was not set explicitly.
445 // We look for the XDG_RUNTIME_DIR env variable. If that is not
446- // set, we give up.
447+ // set correctly, we give up.
448 if (endpoint_dir_.empty())
449 {
450 char* xdg_runtime_dir = secure_getenv("XDG_RUNTIME_DIR");
451@@ -64,6 +64,10 @@
452 throw ConfigException("No endpoint directories specified, and XDG_RUNTIME_DIR "
453 "environment variable not set");
454 }
455+ if (*xdg_runtime_dir != '/')
456+ {
457+ throw ConfigException("Invalid XDG_RUNTIME_DIR: path must be absolute");
458+ }
459 endpoint_dir_ = string(xdg_runtime_dir) + "/zmq";
460 }
461
462
463=== modified file 'test/gtest/scopes/IdleShutdown/SlowSearchScope.h'
464--- test/gtest/scopes/IdleShutdown/SlowSearchScope.h 2014-07-04 03:26:15 +0000
465+++ test/gtest/scopes/IdleShutdown/SlowSearchScope.h 2014-07-30 20:39:51 +0000
466@@ -21,20 +21,20 @@
467
468 #include <unity/scopes/ScopeBase.h>
469
470-using namespace std;
471-using namespace unity::scopes;
472-
473-class SlowSearchScope : public ScopeBase
474+class SlowSearchScope : public unity::scopes::ScopeBase
475 {
476 public:
477- virtual void start(string const&) override;
478+ virtual void start(std::string const&) override;
479
480 virtual void stop() override;
481
482 virtual void run() override;
483
484- virtual SearchQueryBase::UPtr search(CannedQuery const &, SearchMetadata const &) override;
485- virtual PreviewQueryBase::UPtr preview(Result const&, ActionMetadata const &) override;
486+ virtual unity::scopes::SearchQueryBase::UPtr search(unity::scopes::CannedQuery const &,
487+ unity::scopes::SearchMetadata const &) override;
488+
489+ virtual unity::scopes::PreviewQueryBase::UPtr preview(unity::scopes::Result const&,
490+ unity::scopes::ActionMetadata const &) override;
491 };
492
493 #endif
494
495=== modified file 'test/gtest/scopes/Invocation/EmptyScope.h'
496--- test/gtest/scopes/Invocation/EmptyScope.h 2014-07-24 13:51:38 +0000
497+++ test/gtest/scopes/Invocation/EmptyScope.h 2014-07-30 20:39:51 +0000
498@@ -21,14 +21,13 @@
499
500 #include <unity/scopes/ScopeBase.h>
501
502-using namespace std;
503-using namespace unity::scopes;
504-
505-class EmptyScope : public ScopeBase
506+class EmptyScope : public unity::scopes::ScopeBase
507 {
508 public:
509- virtual SearchQueryBase::UPtr search(CannedQuery const &, SearchMetadata const &) override;
510- virtual PreviewQueryBase::UPtr preview(Result const&, ActionMetadata const &) override;
511+ virtual unity::scopes::SearchQueryBase::UPtr search(unity::scopes::CannedQuery const&,
512+ unity::scopes::SearchMetadata const&) override;
513+ virtual unity::scopes::PreviewQueryBase::UPtr preview(unity::scopes::Result const&,
514+ unity::scopes::ActionMetadata const&) override;
515 };
516
517 #endif
518
519=== modified file 'test/gtest/scopes/Invocation/TestScope.cpp'
520--- test/gtest/scopes/Invocation/TestScope.cpp 2014-07-24 15:00:18 +0000
521+++ test/gtest/scopes/Invocation/TestScope.cpp 2014-07-30 20:39:51 +0000
522@@ -76,7 +76,7 @@
523 return SearchQueryBase::UPtr(new TestQuery(query, metadata));
524 }
525
526-PreviewQueryBase::UPtr TestScope::preview(Result const&, ActionMetadata const &)
527+PreviewQueryBase::UPtr TestScope::preview(Result const&, ActionMetadata const&)
528 {
529 return nullptr; // unused
530 }
531
532=== modified file 'test/gtest/scopes/Invocation/TestScope.h'
533--- test/gtest/scopes/Invocation/TestScope.h 2014-07-24 13:51:38 +0000
534+++ test/gtest/scopes/Invocation/TestScope.h 2014-07-30 20:39:51 +0000
535@@ -21,14 +21,13 @@
536
537 #include <unity/scopes/ScopeBase.h>
538
539-using namespace std;
540-using namespace unity::scopes;
541-
542-class TestScope : public ScopeBase
543+class TestScope : public unity::scopes::ScopeBase
544 {
545 public:
546- virtual SearchQueryBase::UPtr search(CannedQuery const &, SearchMetadata const &) override;
547- virtual PreviewQueryBase::UPtr preview(Result const&, ActionMetadata const &) override;
548+ virtual unity::scopes::SearchQueryBase::UPtr search(unity::scopes::CannedQuery const&,
549+ unity::scopes::SearchMetadata const&) override;
550+ virtual unity::scopes::PreviewQueryBase::UPtr preview(unity::scopes::Result const&,
551+ unity::scopes::ActionMetadata const&) override;
552 };
553
554 #endif
555
556=== modified file 'test/gtest/scopes/Registry/scopes/testscopeA/CMakeLists.txt'
557--- test/gtest/scopes/Registry/scopes/testscopeA/CMakeLists.txt 2014-07-01 08:39:17 +0000
558+++ test/gtest/scopes/Registry/scopes/testscopeA/CMakeLists.txt 2014-07-30 20:39:51 +0000
559@@ -1,3 +1,7 @@
560-add_library(testscopeA MODULE testscopeA.cpp)
561 configure_file(testscopeA.ini.in testscopeA.ini)
562 configure_file(testscopeA-settings.ini.in testscopeA-settings.ini)
563+
564+add_definitions(-DSCOPE_CONFIG_PATH="${CMAKE_CURRENT_BINARY_DIR}")
565+
566+add_library(testscopeA MODULE testscopeA.cpp)
567+target_link_libraries(testscopeA ${LIBGTEST})
568
569=== modified file 'test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.cpp'
570--- test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.cpp 2014-07-04 03:26:15 +0000
571+++ test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.cpp 2014-07-30 20:39:51 +0000
572@@ -22,6 +22,8 @@
573 #include <unity/scopes/PreviewWidget.h>
574 #include <unity/scopes/SearchReply.h>
575
576+#include <boost/algorithm/string.hpp>
577+
578 #define EXPORT __attribute__ ((visibility ("default")))
579
580 using namespace std;
581@@ -64,7 +66,14 @@
582 class MyScope : public ScopeBase
583 {
584 public:
585- virtual void start(string const&) override {}
586+ virtual void start(string const&) override
587+ {
588+ string ld_lib_path = getenv("LD_LIBRARY_PATH");
589+ string expected_path_prefix = string(SCOPE_CONFIG_PATH) + ":" + SCOPE_CONFIG_PATH + "/lib";
590+ // We don't use gtest here because then the scope would have to link against it,
591+ // but libgtest.a isn't compiled with -fPIC.
592+ assert(boost::algorithm::starts_with(ld_lib_path, expected_path_prefix));
593+ }
594
595 virtual void stop() override {}
596
597
598=== modified file 'test/gtest/scopes/Runtime/TestScope.h'
599--- test/gtest/scopes/Runtime/TestScope.h 2014-07-24 13:51:38 +0000
600+++ test/gtest/scopes/Runtime/TestScope.h 2014-07-30 20:39:51 +0000
601@@ -21,14 +21,13 @@
602
603 #include <unity/scopes/ScopeBase.h>
604
605-using namespace std;
606-using namespace unity::scopes;
607-
608-class TestScope : public ScopeBase
609+class TestScope : public unity::scopes::ScopeBase
610 {
611 public:
612- virtual SearchQueryBase::UPtr search(CannedQuery const&, SearchMetadata const&) override;
613- virtual PreviewQueryBase::UPtr preview(Result const&, ActionMetadata const&) override;
614+ virtual unity::scopes::SearchQueryBase::UPtr search(unity::scopes::CannedQuery const&,
615+ unity::scopes::SearchMetadata const&) override;
616+ virtual unity::scopes::PreviewQueryBase::UPtr preview(unity::scopes::Result const&,
617+ unity::scopes::ActionMetadata const&) override;
618 };
619
620 #endif
621
622=== modified file 'test/gtest/scopes/internal/DynamicLoader/DynamicLoader_test.cpp'
623--- test/gtest/scopes/internal/DynamicLoader/DynamicLoader_test.cpp 2014-07-25 07:29:19 +0000
624+++ test/gtest/scopes/internal/DynamicLoader/DynamicLoader_test.cpp 2014-07-30 20:39:51 +0000
625@@ -61,15 +61,15 @@
626 TEST(DynamicLoader, flags)
627 {
628 {
629- DynamicLoader::UPtr dl = DynamicLoader::create(badlib);
630- DynamicLoader::VoidFunc f = dl->find_function("test_function"); // Must work despite unreslved().
631+ DynamicLoader::UPtr dl = DynamicLoader::create(badlib, DynamicLoader::Binding::lazy);
632+ DynamicLoader::VoidFunc f = dl->find_function("test_function"); // Must work despite unresolved().
633 EXPECT_NE(nullptr, f);
634 }
635
636 try
637 {
638 // Must fail because of unresolved symbol.
639- DynamicLoader::UPtr dl = DynamicLoader::create(badlib, DynamicLoader::Binding::now);
640+ DynamicLoader::UPtr dl = DynamicLoader::create(badlib);
641 }
642 catch (unity::ResourceException const& e)
643 {
644
645=== modified file 'test/gtest/scopes/internal/RegistryObject/CMakeLists.txt'
646--- test/gtest/scopes/internal/RegistryObject/CMakeLists.txt 2014-05-07 04:48:26 +0000
647+++ test/gtest/scopes/internal/RegistryObject/CMakeLists.txt 2014-07-30 20:39:51 +0000
648@@ -1,3 +1,5 @@
649+configure_file(scope.ini.in scope.ini)
650+
651 add_executable(RegistryObject_test RegistryObject_test.cpp)
652 target_link_libraries(RegistryObject_test ${TESTLIBS})
653
654
655=== modified file 'test/gtest/scopes/internal/RegistryObject/RegistryObject_test.cpp'
656--- test/gtest/scopes/internal/RegistryObject/RegistryObject_test.cpp 2014-06-04 17:49:34 +0000
657+++ test/gtest/scopes/internal/RegistryObject/RegistryObject_test.cpp 2014-07-30 20:39:51 +0000
658@@ -160,7 +160,7 @@
659 exec_data.scope_id = "scope-id";
660 exec_data.scoperunner_path = "/path/scoperunner";
661 exec_data.runtime_config = "/path/runtime.ini";
662- exec_data.scope_config = "/path/scope.ini";
663+ exec_data.scope_config = "scope.ini";
664 exec_data.confinement_profile = confinement_profile;
665 exec_data.timeout_ms = 1500;
666
667@@ -188,7 +188,7 @@
668 {
669 EXPECT_CALL(*executor,
670 exec("/path/scoperunner", vector<string>
671- { "/path/runtime.ini", "/path/scope.ini"}, _,
672+ { "/path/runtime.ini", "scope.ini"}, _,
673 StandardStream::stdin | StandardStream::stdout,
674 string())).WillOnce(
675 Invoke(this, &TestRegistryObject::mock_exec));
676@@ -200,7 +200,7 @@
677 {
678 EXPECT_CALL(*executor,
679 exec("/path/scoperunner", vector<string>
680- { "/path/runtime.ini", "/path/scope.ini"}, _,
681+ { "/path/runtime.ini", "scope.ini"}, _,
682 StandardStream::stdin | StandardStream::stdout,
683 "confinement profile")).WillOnce(
684 Invoke(this, &TestRegistryObject::mock_exec));
685
686=== added file 'test/gtest/scopes/internal/RegistryObject/scope.ini.in'
687=== modified file 'test/gtest/scopes/internal/RuntimeImpl/CMakeLists.txt'
688--- test/gtest/scopes/internal/RuntimeImpl/CMakeLists.txt 2014-07-07 23:53:36 +0000
689+++ test/gtest/scopes/internal/RuntimeImpl/CMakeLists.txt 2014-07-30 20:39:51 +0000
690@@ -1,9 +1,10 @@
691-configure_file(Zmq.ini.in Zmq.ini)
692 configure_file(Registry.ini.in Registry.ini)
693 configure_file(Runtime.ini.in Runtime.ini)
694+configure_file(TestScope.ini.in TestScope.ini)
695+configure_file(Zmq.ini.in Zmq.ini)
696
697 add_definitions(-DTEST_DIR="${CMAKE_CURRENT_BINARY_DIR}")
698-add_executable(RuntimeImpl_test RuntimeImpl_test.cpp)
699+add_executable(RuntimeImpl_test RuntimeImpl_test.cpp TestScope.cpp)
700 target_link_libraries(RuntimeImpl_test ${TESTLIBS})
701
702 add_test(RuntimeImpl RuntimeImpl_test)
703
704=== modified file 'test/gtest/scopes/internal/RuntimeImpl/Registry.ini.in'
705--- test/gtest/scopes/internal/RuntimeImpl/Registry.ini.in 2014-05-01 02:58:33 +0000
706+++ test/gtest/scopes/internal/RuntimeImpl/Registry.ini.in 2014-07-30 20:39:51 +0000
707@@ -1,6 +1,6 @@
708 [Registry]
709 Middleware = Zmq
710-Zmq.ConfigFile = Zmq.ini
711+Zmq.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/Zmq.ini
712 Scoperunner.Path = /SomePath
713 Scope.InstallDir = /tmp
714 Scope.InstallDir = /tmp
715
716=== modified file 'test/gtest/scopes/internal/RuntimeImpl/Runtime.ini.in'
717--- test/gtest/scopes/internal/RuntimeImpl/Runtime.ini.in 2014-02-03 11:30:02 +0000
718+++ test/gtest/scopes/internal/RuntimeImpl/Runtime.ini.in 2014-07-30 20:39:51 +0000
719@@ -2,4 +2,5 @@
720 Registry.Identity = Registry
721 Registry.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/Registry.ini
722 Default.Middleware = Zmq
723-Zmq.ConfigFile = Zmq.ini
724+Zmq.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/Zmq.ini
725+DataDir = @CMAKE_CURRENT_BINARY_DIR@/cache_dir
726
727=== modified file 'test/gtest/scopes/internal/RuntimeImpl/RuntimeImpl_test.cpp'
728--- test/gtest/scopes/internal/RuntimeImpl/RuntimeImpl_test.cpp 2014-07-10 00:37:18 +0000
729+++ test/gtest/scopes/internal/RuntimeImpl/RuntimeImpl_test.cpp 2014-07-30 20:39:51 +0000
730@@ -17,11 +17,17 @@
731 */
732
733 #include <unity/scopes/internal/RuntimeImpl.h>
734+#include <unity/scopes/ScopeExceptions.h>
735 #include <unity/UnityExceptions.h>
736-#include <unity/scopes/ScopeExceptions.h>
737-
738+
739+#include "TestScope.h"
740+
741+#include <boost/algorithm/string.hpp>
742+#include <boost/filesystem.hpp>
743 #include <gtest/gtest.h>
744
745+#include <fcntl.h>
746+
747 using namespace std;
748 using namespace unity;
749 using namespace unity::scopes;
750@@ -29,9 +35,13 @@
751
752 TEST(RuntimeImpl, basic)
753 {
754- RuntimeImpl::UPtr rt = RuntimeImpl::create("testscope", TEST_DIR "/Runtime.ini");
755+ // Make sure we start out with a clean slate.
756+ boost::filesystem::remove_all(TEST_DIR "/cache_dir");
757+
758+ RuntimeImpl::UPtr rt = RuntimeImpl::create("TestScope", TEST_DIR "/Runtime.ini");
759
760 EXPECT_TRUE(rt->registry().get() != nullptr);
761+ EXPECT_TRUE(rt->registry()->identity() == "Registry");
762 EXPECT_TRUE(rt->factory());
763 EXPECT_EQ(TEST_DIR "/Registry.ini", rt->registry_configfile());
764
765@@ -65,13 +75,41 @@
766 {
767 try
768 {
769- RuntimeImpl::UPtr rt = RuntimeImpl::create("testscope", "NoSuchFile.ini");
770+ RuntimeImpl::UPtr rt = RuntimeImpl::create("TestScope", "NoSuchFile.ini");
771 }
772 catch (ConfigException const& e)
773 {
774- EXPECT_STREQ("unity::scopes::ConfigException: Cannot instantiate run time for testscope, "
775+ EXPECT_STREQ("unity::scopes::ConfigException: Cannot instantiate run time for TestScope, "
776 "config file: NoSuchFile.ini:\n"
777 " unity::FileException: Could not load ini file NoSuchFile.ini: No such file or directory (errno = 4)",
778 e.what());
779 }
780 }
781+
782+void testscope_thread(Runtime::SPtr const& rt, TestScope* testscope, string const& runtime_ini_file)
783+{
784+ rt->run_scope(testscope, runtime_ini_file, TEST_DIR "/TestScope.ini");
785+}
786+
787+TEST(RuntimeImpl, directories)
788+{
789+
790+ {
791+ Runtime::SPtr rt = move(Runtime::create_scope_runtime("TestScope", TEST_DIR "/Runtime.ini"));
792+ TestScope testscope;
793+ std::thread testscope_t(testscope_thread, rt, &testscope, TEST_DIR "/Runtime.ini");
794+
795+ // Give thread some time to start up.
796+ this_thread::sleep_for(chrono::milliseconds(200));
797+
798+ EXPECT_EQ(TEST_DIR, testscope.scope_directory());
799+
800+ string tmpdir = "/run/user/" + to_string(geteuid()) + "/scopes/unconfined/TestScope";
801+ EXPECT_EQ(tmpdir, testscope.tmp_directory());
802+
803+ EXPECT_EQ(TEST_DIR "/cache_dir/unconfined/TestScope", testscope.cache_directory());
804+
805+ rt->destroy();
806+ testscope_t.join();
807+ }
808+}
809
810=== added file 'test/gtest/scopes/internal/RuntimeImpl/TestScope.cpp'
811--- test/gtest/scopes/internal/RuntimeImpl/TestScope.cpp 1970-01-01 00:00:00 +0000
812+++ test/gtest/scopes/internal/RuntimeImpl/TestScope.cpp 2014-07-30 20:39:51 +0000
813@@ -0,0 +1,40 @@
814+/*
815+ * Copyright (C) 2014 Canonical Ltd
816+ *
817+ * This program is free software: you can redistribute it and/or modify
818+ * it under the terms of the GNU Lesser General Public License version 3 as
819+ * published by the Free Software Foundation.
820+ *
821+ * This program is distributed in the hope that it will be useful,
822+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
823+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
824+ * GNU Lesser General Public License for more details.
825+ *
826+ * You should have received a copy of the GNU Lesser General Public License
827+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
828+ *
829+ * Authored by: Michi Henning <michi.henning@canonical.com>
830+ */
831+
832+#include "TestScope.h"
833+
834+using namespace std;
835+using namespace unity::scopes;
836+
837+void TestScope::start(string const&)
838+{
839+}
840+
841+SearchQueryBase::UPtr TestScope::search(CannedQuery const&, SearchMetadata const&)
842+{
843+ // Never called
844+ abort();
845+ return nullptr;
846+}
847+
848+PreviewQueryBase::UPtr TestScope::preview(Result const&, ActionMetadata const&)
849+{
850+ // Never called
851+ abort();
852+ return nullptr;
853+}
854
855=== added file 'test/gtest/scopes/internal/RuntimeImpl/TestScope.h'
856--- test/gtest/scopes/internal/RuntimeImpl/TestScope.h 1970-01-01 00:00:00 +0000
857+++ test/gtest/scopes/internal/RuntimeImpl/TestScope.h 2014-07-30 20:39:51 +0000
858@@ -0,0 +1,36 @@
859+/*
860+ * Copyright (C) 2014 Canonical Ltd
861+ *
862+ * This program is free software: you can redistribute it and/or modify
863+ * it under the terms of the GNU Lesser General Public License version 3 as
864+ * published by the Free Software Foundation.
865+ *
866+ * This program is distributed in the hope that it will be useful,
867+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
868+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
869+ * GNU Lesser General Public License for more details.
870+ *
871+ * You should have received a copy of the GNU Lesser General Public License
872+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
873+ *
874+ * Authored by: Michi Henning <michi.henning@canonical.com>
875+ */
876+
877+#ifndef TEST_TESTSCOPE_H
878+#define TEST_TESTSCOPE_H
879+
880+#include <unity/scopes/ScopeBase.h>
881+
882+class TestScope : public unity::scopes::ScopeBase
883+{
884+public:
885+ virtual void start(std::string const&);
886+
887+ virtual unity::scopes::SearchQueryBase::UPtr search(unity::scopes::CannedQuery const&,
888+ unity::scopes::SearchMetadata const&) override;
889+
890+ virtual unity::scopes::PreviewQueryBase::UPtr preview(unity::scopes::Result const&,
891+ unity::scopes::ActionMetadata const&) override;
892+};
893+
894+#endif
895
896=== added file 'test/gtest/scopes/internal/RuntimeImpl/TestScope.ini.in'
897--- test/gtest/scopes/internal/RuntimeImpl/TestScope.ini.in 1970-01-01 00:00:00 +0000
898+++ test/gtest/scopes/internal/RuntimeImpl/TestScope.ini.in 2014-07-30 20:39:51 +0000
899@@ -0,0 +1,4 @@
900+[ScopeConfig]
901+DisplayName = TestScope
902+Description = Scope to test environment variable settings
903+Author = Michi Henning
904
905=== modified file 'test/gtest/scopes/testing/IsolatedScope/scope.cpp'
906--- test/gtest/scopes/testing/IsolatedScope/scope.cpp 2014-07-28 13:38:58 +0000
907+++ test/gtest/scopes/testing/IsolatedScope/scope.cpp 2014-07-30 20:39:51 +0000
908@@ -227,6 +227,11 @@
909 return "";
910 }
911
912+std::string testing::Scope::tmp_directory() const
913+{
914+ return "";
915+}
916+
917 unity::scopes::RegistryProxy testing::Scope::registry() const
918 {
919 return registry_;
920
921=== modified file 'test/gtest/scopes/testing/IsolatedScope/scope.h'
922--- test/gtest/scopes/testing/IsolatedScope/scope.h 2014-07-10 02:22:23 +0000
923+++ test/gtest/scopes/testing/IsolatedScope/scope.h 2014-07-30 20:39:51 +0000
924@@ -57,6 +57,8 @@
925
926 std::string cache_directory() const override;
927
928+ std::string tmp_directory() const override;
929+
930 unity::scopes::RegistryProxy registry() const override;
931
932 unity::scopes::VariantMap settings() const override;

Subscribers

People subscribed via source and target branches

to all changes: