Merge lp:~michihenning/unity-scopes-api/scope-cache-dir into lp:unity-scopes-api/devel

Proposed by Michi Henning
Status: Merged
Approved by: Michal Hruby
Approved revision: 419
Merged at revision: 423
Proposed branch: lp:~michihenning/unity-scopes-api/scope-cache-dir
Merge into: lp:unity-scopes-api/devel
Diff against target: 2237 lines (+609/-346)
60 files modified
CONFIGFILES (+1/-1)
HACKING (+14/-9)
RELEASE_NOTES.md (+15/-0)
debian/changelog (+5/-2)
debian/libunity-scopes2.symbols (+14/-6)
debian/tests/scopebuild (+5/-54)
debian/tests/scopetest.cpp (+62/-0)
demo/click/scope-click/scope-click.cpp (+1/-1)
demo/scopes/scope-A/scope-A.cpp (+1/-1)
demo/scopes/scope-B/scope-B.cpp (+4/-4)
demo/scopes/scope-C/scope-C.cpp (+1/-1)
demo/scopes/scope-D/scope-D.cpp (+1/-1)
demo/scopes/scope-N/scope-N.cpp (+1/-1)
demo/scopes/scope-S/scope-S.cpp (+1/-1)
doc/tutorial.dox (+3/-3)
include/unity/scopes/AbstractScopeBase.h (+65/-0)
include/unity/scopes/ScopeBase.h (+56/-29)
include/unity/scopes/internal/DfltConfig.h.in (+1/-0)
include/unity/scopes/internal/RuntimeImpl.h (+1/-0)
include/unity/scopes/internal/ScopeBaseImpl.h (+21/-3)
include/unity/scopes/internal/ScopeConfig.h (+12/-12)
include/unity/scopes/internal/ScopeLoader.h (+3/-11)
include/unity/scopes/testing/TypedScopeFixture.h (+6/-6)
scoperegistry/scoperegistry.cpp (+27/-19)
scoperunner/scoperunner.cpp (+20/-43)
smartscopesproxy/smartscopesproxy.cpp (+3/-2)
src/scopes/ScopeBase.cpp (+12/-1)
src/scopes/internal/RegistryConfig.cpp (+1/-1)
src/scopes/internal/RuntimeConfig.cpp (+1/-1)
src/scopes/internal/RuntimeImpl.cpp (+66/-23)
src/scopes/internal/ScopeBaseImpl.cpp (+67/-1)
src/scopes/internal/ScopeConfig.cpp (+7/-7)
src/scopes/internal/ScopeLoader.cpp (+4/-35)
src/scopes/internal/zmq_middleware/ZmqConfig.cpp (+1/-1)
test/CMakeLists.txt (+1/-0)
test/autopkg/CMakeLists.txt (+4/-0)
test/gtest/scopes/Activation/TestScope.h (+1/-1)
test/gtest/scopes/IdleShutdown/SlowSearchScope.cpp (+1/-1)
test/gtest/scopes/IdleShutdown/SlowSearchScope.h (+1/-1)
test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.cpp (+1/-1)
test/gtest/scopes/Registry/scopes/testscopeB/testscopeB.cpp (+1/-1)
test/gtest/scopes/Runtime/PusherScope.h (+5/-6)
test/gtest/scopes/Runtime/SlowCreateScope.h (+5/-6)
test/gtest/scopes/ScopeBase/ScopeBase_test.cpp (+1/-1)
test/gtest/scopes/ScopeBase/scopelib.cpp (+1/-1)
test/gtest/scopes/internal/ScopeConfig/ScopeConfig_test.cpp (+1/-1)
test/gtest/scopes/internal/ScopeConfig/complete_config.ini.in (+1/-0)
test/gtest/scopes/internal/ScopeLoader/MyScope.h (+1/-1)
test/gtest/scopes/internal/ScopeLoader/ScopeA.cpp (+1/-1)
test/gtest/scopes/internal/ScopeLoader/ScopeB.cpp (+1/-1)
test/gtest/scopes/internal/ScopeLoader/ScopeLoader_test.cpp (+20/-26)
test/gtest/scopes/internal/ScopeLoader/ThrowUnityExFromStart.cpp (+1/-1)
test/gtest/scopes/internal/ScopeLoader/ThrowUnknownExFromStart.cpp (+1/-1)
test/gtest/scopes/testing/IsolatedScope/scope.cpp (+32/-5)
test/gtest/scopes/testing/IsolatedScope/scope.h (+15/-3)
test/gtest/scopes/testing/IsolatedScopeBenchmark/IsolatedScopeBenchmark_test.cpp (+1/-1)
test/gtest/scopes/testing/IsolatedScopeBenchmark/scope.cpp (+1/-1)
test/gtest/scopes/testing/IsolatedScopeBenchmark/scope.h (+1/-1)
test/headers/CMakeLists.txt (+6/-3)
test/headers/check_public_headers.py (+1/-1)
To merge this branch: bzr merge lp:~michihenning/unity-scopes-api/scope-cache-dir
Reviewer Review Type Date Requested Status
Michal Hruby (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Jamie Strandboge Approve
Review via email: mp+225773@code.launchpad.net

Commit message

  - Added cache_directory() method to ScopeBase, so a scope can find out where it can write its files.

  - Refactored scoperunner and ScopeLoader. ScopeLoader no longer knows about the registry and
    scoperunner now calls RuntimeImpl::run_scope() to set the scope running, instead of duplicating
    lots of functionality.

  - Removed registry parameter from ScopeBase::start(). The registry is now available via a registry()
    accessor on ScopeBase. The original start() method is still present, but deprecated. The default
    implementation of the new start() method forwards to the old one so, if a scope implements only the
    old one but not the new one, things still work.

  - Made methods on ScopeBase virtual, so the testing framework can override them in a test scope.

Description of the change

  - Added cache_directory() method to ScopeBase, so a scope can find out where it can write its files.

  - Refactored scoperunner and ScopeLoader. ScopeLoader no longer knows about the registry and
    scoperunner now calls RuntimeImpl::run_scope() to set the scope running, instead of duplicating
    lots of functionality.

  - Removed registry parameter from ScopeBase::start(). The registry is now available via a registry()
    accessor on ScopeBase. The original start() method is still present, but deprecated. The default
    implementation of the new start() method forwards to the old one so, if a scope implements only the
    old one but not the new one, things still work.

  - Made methods on ScopeBase virtual, so the testing framework can override them in a test scope.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
403. By Michi Henning

Added encoding = utf-8 to file open(), so the 'ß' in Thomas's headers won't break
the tests :-)

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
Michal Hruby (mhr3) wrote :

43 + $HOME/.local/share/unity-scopes/leaf-fs/<scope_id>
851 + data_dir_ + "/leaf-fs/" + scope_id_

The local content template doesn't exist, so there's no need to try to support it.

42 + $HOME/.local/share/unity-scopes/leaf-net/<scope_id>

Who's responsible for creating this directory? I suppose the leaf could be created by the scope itself (does it have permissions to do that?), but the parents have to be created by something unconfined, so who's doing it? The click hook?

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

41 + $HOME/.local/share/unity-scopes/aggregator/<scope_id>

Same as for leaf-fs, there's no apparmor template for aggregator scopes, so this should really be $HOME/.local/share/unity-scopes/unconfined/<scope_id>

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

> 43 + $HOME/.local/share/unity-scopes/leaf-fs/<scope_id>
> 851 + data_dir_ +
> "/leaf-fs/" + scope_id_
>
> The local content template doesn't exist, so there's no need to try to support
> it.

Not sure what you mean here. We have net, fs, and unconfined scopes. All of these can have a scratch area. I'm going by Jamie's comments here: https://bugs.launchpad.net/unity-scopes-api/+bug/1327426

> 42 + $HOME/.local/share/unity-scopes/leaf-net/<scope_id>
>
> Who's responsible for creating this directory? I suppose the leaf could be
> created by the scope itself (does it have permissions to do that?), but the
> parents have to be created by something unconfined, so who's doing it? The
> click hook?

Yes, the directory needs to be created as part of the installation.

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

> 41 + $HOME/.local/share/unity-scopes/aggregator/<scope_id>
>
> Same as for leaf-fs, there's no apparmor template for aggregator scopes, so
> this should really be $HOME/.local/share/unity-scopes/unconfined/<scope_id>

Referring to: https://bugs.launchpad.net/unity-scopes-api/+bug/1327426

I don't mind whether we call it "aggregator" or "unconfined". Jamie?

Personally, I think "unconfined" is a slightly better name though. I think it better expresses the semantics, and we may want to have unconfined scopes at some point in the future that are not aggregators.

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

There are plans to support the local content scope at some point and so I don't see any harm in using 'leaf-fs' for it. There is no reason why we couldn't also provide an aggregator template for us and trusted 3rd parties to use to help confine the scope somewhat (we just wouldn't make it available to unknown 3rd party developers). As for 'aggregator' vs 'unconfined', I personally like the idea of expressing the functionality there. While 'leaf-net', 'leaf-fs', 'aggregator' or anything else does have to do with what is expressed in the apparmor policy for the specified template, I'm not sure you want to have to worry about what templates are defined and what aren't in your code. Wouldn't it be best to just use these 3 different types so that if we ever supply the templates at a future date nothing in your code has to change?

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

Hi Jamie, not totally sure whether your response is in favour of "aggregator" or "unconfined' here :-) Can you clarify?

As far as the scopes run time is concerned, all we care about is that there are three different kinds of scope who use different locations in the filesystem. So, I wouldn't really care if those locations were called "a", "b", and "c", and whether the directory names are the same as the apparmor policy or not.

Basically, all we need to do is agree on the three names :-)

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

> > 43 + $HOME/.local/share/unity-scopes/leaf-fs/<scope_id>
> > 851 + data_dir_
> +
> > "/leaf-fs/" + scope_id_
> >
> > The local content template doesn't exist, so there's no need to try to
> support
> > it.
>
> Not sure what you mean here. We have net, fs, and unconfined scopes. All of
> these can have a scratch area. I'm going by Jamie's comments here:
> https://bugs.launchpad.net/unity-scopes-api/+bug/1327426

No, we don't support fs scopes, cause there are unresolved security issues with them.

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

374 - std::string scope_directory() const;
377 + virtual std::string scope_directory() const;
412 - VariantMap settings() const;
413 + virtual VariantMap settings() const;

I really don't like these changes, other than tests there's absolutely no reason for these to be virtual and therefore to allow the scope to override them. Can't we do something different, like setting a special envvar for the tests and have the impl look at that first? Yes, making it virtual does make it easily unit-testable, but imo such a test is really just testing itself.

404. By Michi Henning

Fixed broken autopkg test by changing code to match the new API.
Added build and run of the autopkg test to the test target. That
way, we'll at least notice if the code for the autopkg test
no longer compiles/runs.
Update HACKING for autopkg tests with instructions for how
to run the tests in a VM (thanks Saviq!) and a pointer to
the corresponding subdir in the test subtree, so we don't
forget to add new autopkg tests to the local test suite.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
405. By Michi Henning

Merged devel and resolved conflict.

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

Added AbstractScopeBase and made the following
methods final in ScopeBase:

- scope_directory()
- cache_directory()
- registry()
- settings()

This allows the tests to mock a scope implementation
while preventing real scope implementations from overriding
methods they shouldn't override.

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

> I really don't like these changes, other than tests there's absolutely no
> reason for these to be virtual and therefore to allow the scope to override
> them.

The testing frameworks needs to allow a scope to be mocked, so it's not just
our tests. But I agree, the scope author should not be able to override these.

> Can't we do something different, like setting a special envvar for the
> tests and have the impl look at that first? Yes, making it virtual does make
> it easily unit-testable, but imo such a test is really just testing itself.

No more env vars! I'm going to institute a blanket ban on them. The are worse
than global variables: not declared anywhere totally invisible.

I've made the relevant methods final in ScopeBase, so it's no longer possible
to override them.

407. By Michi Henning

Changed "aggregator" to "unconfined" when looking for cache directories.

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

> 41 + $HOME/.local/share/unity-scopes/aggregator/<scope_id>
>
> Same as for leaf-fs, there's no apparmor template for aggregator scopes, so
> this should really be $HOME/.local/share/unity-scopes/unconfined/<scope_id>

OK, it's "unconfined" now. I've left leaf-fs there because Jamie mentioned that confined local content scopes might come back.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
408. By Michi Henning

Fixed symbols file.

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
Michal Hruby (mhr3) wrote :

602 virtual void start(std::string const& scope_id, RegistryProxy const& registry);

The point of keeping this was to preserve ABI compatibility, but with the introduction of AbstractScopeBase that is moot, so feel free to get rid of it.

Also, since it is breaking the ABI, we probably want to merge the 4.9 branch as well before the next "release" to distro?

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

"Hi Jamie, not totally sure whether your response is in favour of "aggregator" or "unconfined' here :-) Can you clarify?"

I preferred leaf-net, leaf-fs and aggregator so that you don't have to change your code if we ever do implement leaf-fs or aggregator policy in the future (note, just because we may never make these available to third party developers, it doesn't mean we won't want apparmor policy for our own stuff).

409. By Michi Henning

Removed deprecated start() method.

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

> 602 virtual void start(std::string const& scope_id, RegistryProxy
> const& registry);
>
> The point of keeping this was to preserve ABI compatibility, but with the
> introduction of AbstractScopeBase that is moot, so feel free to get rid of it.

OK, done.

> Also, since it is breaking the ABI, we probably want to merge the 4.9 branch
> as well before the next "release" to distro?

Is the default gcc in distro 4.9 now? It would be good to merge, yes, but we also need to merge the 4.9 unity-api. And, once we've done that, there will essentially be no going back :-)

The (now inappropriately named) set-env-vars should also be merged in the same batch, because it adds another virtual to AbstractScopeBase.

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

> I preferred leaf-net, leaf-fs and aggregator so that you don't have to change
> your code if we ever do implement leaf-fs or aggregator policy in the future
> (note, just because we may never make these available to third party
> developers, it doesn't mean we won't want apparmor policy for our own stuff).

Would the policy for an aggregator every be different from an unconfined scope?
I guess the question is whether I should use "leaf-fs", "leaf-net", "aggregator", and "unconfined"?

It's really neither here nor there to me--the list can be as long as we like and, if some of the directories in there don't exist, the right things still happen.

For the time being, I'll just check for both "aggregator" and "unconfined". That way, we have our bases covered. Michal, Jamie, please speak up if you think this is wrong or if I'm missing something!

410. By Michi Henning

Added "aggregator" to list of directories looked at for cache_directory().

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
411. By Michi Henning

Fixed symbols file by hand without gcc 4.8 installed. Fingers crossed...

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
412. By Michi Henning

Fixed symbols file using gcc 4.8.

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

> Who's responsible for creating this directory? I suppose the leaf could be
> created by the scope itself (does it have permissions to do that?), but the
> parents have to be created by something unconfined, so who's doing it? The
> click hook?

Yes, the directory needs to be created as part of the installation.

Still not solved afaict, without it, this branch is useless.

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

> Yes, the directory needs to be created as part of the installation.
>
> Still not solved afaict, without it, this branch is useless.

Well, I wouldn't quite say "useless" because the branch will do the right thing once the directory is there :-)

I'll open a separate bug for this because that's really a separate issue.

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

Sorry, didn't mean to sound harsh, but we need the dirs for scopes to be able to use this.

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

> Sorry, didn't mean to sound harsh, but we need the dirs for scopes to be able
> to use this.

Not a problem, relax! :-)

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

OK, so the approach of looking for the scope's data dir and setting cache_directory() to the right value isn't going to work because the click install can't create the directory.

So, next best idea:

The registry can look for each scope in the manifests and parse the JSON to figure out what kind of scope it is looking at. Then it can go to $HOME/.local/unity-scopes and create the scope cache directory if it doesn't exist, with permission 0700. The registry adds the scope cache directory to the scope's metadata, which is available remotely.

On the scope side, during initialization of the run time, we go to the registry and grab the metadata, so cache_directory() can return the correct location.

Down-sides and questions:

- If no registry is running, we have to wait for the metadata() call to time out. Currently, the default timeout is 5 seconds, due to the slow emulator problem. This will probably break some tests, and will be inconvenient during development. The work-around would be to change the default registry timeout to something short, so things don't hang around all the time waiting to time out.

- I can look through /var/lib/apparmor/clicks for JSON files. In there, I find things such as

com.ubuntu.clock_clock_1.0.430.json
com.ubuntu.music_music_1.3.511.json

When I look at the clock one, I see:

{
    "policy_groups": [
        "calendar",
        "networking"
        ],
    "policy_version": 1.1
}

When I look at the music one, I see:

{
    "policy_version": 1.2,
    "template": "unconfined",
    "policy_groups": []
}

So, it's not clear to me what exactly I should be parsing ("template" or "policy_groups") to figure out whether a scope is leaf-net or aggregator/unconfined.

- We have scopes that come pre-installed, scopes installed by the OEM, plus scopes installed by the user(s). Is it sufficient to look through /var/lib/apparmor/clicks to guarantee that I won't be missing any scopes? For the approach I outlined above, I need to be sure that I find something for every local scope.

- I'm questioning the wisdom of what I suggested above. It seems that the registry is forced to do a lot more than it should have to just so it can let a scope know what its writable tmp dir is. Isn't this something that should somehow be available via an apparmor call? Or should there be a way for click to be able to create the directory in the right place?

- There are potentially many cache and settings directories for a single scope (one for each user). When a new user is added to the device, who should create the cache dir and settings dir?

My apologies for all the questions, but it seems that I don't have all the pieces of the puzzle yet, so I don't want to rush and implement something only to have it fall over for some reason I don't know about. I'd appreciate any and all feedback!

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

Following up on this:

> - I'm questioning the wisdom of what I suggested above. It seems that the
> registry is forced to do a lot more than it should have to

How is this going to work for apps? I expect that applications also will need a writable area in the file system somewhere. How do apps find out where they can write their files?

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

> On the scope side, during initialization of the run time, we go to the
> registry and grab the metadata, so cache_directory() can return the correct
> location.

Eh, remote call during startup? /me frowns.

>
> Down-sides and questions:
>
> - If no registry is running, we have to wait for the metadata() call to time
> out. Currently, the default timeout is 5 seconds, due to the slow emulator
> problem. This will probably break some tests, and will be inconvenient during
> development. The work-around would be to change the default registry timeout
> to something short, so things don't hang around all the time waiting to time
> out.
>
> - I can look through /var/lib/apparmor/clicks for JSON files. In there, I find
> things such as
>
> com.ubuntu.clock_clock_1.0.430.json
> com.ubuntu.music_music_1.3.511.json
>
> When I look at the clock one, I see:
>
> {
> "policy_groups": [
> "calendar",
> "networking"
> ],
> "policy_version": 1.1
> }
>
> When I look at the music one, I see:
>
> {
> "policy_version": 1.2,
> "template": "unconfined",
> "policy_groups": []
> }
>
> So, it's not clear to me what exactly I should be parsing ("template" or
> "policy_groups") to figure out whether a scope is leaf-net or
> aggregator/unconfined.

According to our tutorial:

> "template": "ubuntu-scope-network"

Is what you should find in the manifest.

> - We have scopes that come pre-installed, scopes installed by the OEM, plus
> scopes installed by the user(s). Is it sufficient to look through
> /var/lib/apparmor/clicks to guarantee that I won't be missing any scopes? For
> the approach I outlined above, I need to be sure that I find something for
> every local scope.

You won't, obviously only click-packaged scopes will have there something.

> - I'm questioning the wisdom of what I suggested above. It seems that the
> registry is forced to do a lot more than it should have to just so it can let
> a scope know what its writable tmp dir is. Isn't this something that should
> somehow be available via an apparmor call? Or should there be a way for click
> to be able to create the directory in the right place?

Sounds reasonable to me, but can't answer that.

>
> - There are potentially many cache and settings directories for a single scope
> (one for each user). When a new user is added to the device, who should create
> the cache dir and settings dir?

The registry again. Afterall it's run per-user.

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

> Following up on this:
>
> > - I'm questioning the wisdom of what I suggested above. It seems that the
> > registry is forced to do a lot more than it should have to
>
> How is this going to work for apps? I expect that applications also will need
> a writable area in the file system somewhere. How do apps find out where they
> can write their files?

https://wiki.ubuntu.com/SecurityTeam/Specifications/ApplicationConfinement but iiuic Qt itself was patched to build the directory based on a few envvars. Imo we should just do the same, afterall the path has to be "prefix + scope_id", and the prefix can be passed as an envvar - it's not like a single process can be both unconfined and leaf-net at the same time.

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

> https://wiki.ubuntu.com/SecurityTeam/Specifications/ApplicationConfinement but
> iiuic Qt itself was patched to build the directory based on a few envvars. Imo
> we should just do the same, afterall the path has to be "prefix + scope_id",
> and the prefix can be passed as an envvar - it's not like a single process can
> be both unconfined and leaf-net at the same time.

I'm still not happy about this, as I mentioned earlier: if we have multiple instances of the run time in a single address space, the setting will be wrong for all but one of them.

But getting the value into the scope is just a side-issue. The real problem is that I don't know how to figure out what to set "prefix" to. It seems I can't even reliably get at all the manifests for pre-installed, OEM, and click scopes.

Jamie, instead of having something like $HOME/.local/share/unity-scopes/leaf-net/<scope_id>, could we get rid of the "leaf-fs"/"leaf-net"/"aggregator"/"confined" sub-directory?

If so, we could just make it $HOME/.local/share/unity-scopes/data_home/<scope_id>.

The core problem here is that I don't know which confinement profile belongs to what scope ID, so I don't know how to set the path correctly. If we have a path that doesn't change depending on the confinement profile, the problem would go away because the prefix would be independent of the confinement type.

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

> > https://wiki.ubuntu.com/SecurityTeam/Specifications/ApplicationConfinement
> but
> > iiuic Qt itself was patched to build the directory based on a few envvars.
> Imo
> > we should just do the same, afterall the path has to be "prefix + scope_id",
> > and the prefix can be passed as an envvar - it's not like a single process
> can
> > be both unconfined and leaf-net at the same time.
>
> I'm still not happy about this, as I mentioned earlier: if we have multiple
> instances of the run time in a single address space, the setting will be wrong
> for all but one of them.

My point was that you can apply only one apparmor profile, so if there are multiple runtimes and scopes in a single process, they either have to share the apparmor template or need to be unconfined, otherwise things won't work anyway. So the prefix is indeed per process, not per runtime.

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

> > https://wiki.ubuntu.com/SecurityTeam/Specifications/ApplicationConfinement
> but
> > iiuic Qt itself was patched to build the directory based on a few envvars.
> Imo
> > we should just do the same, afterall the path has to be "prefix + scope_id",
> > and the prefix can be passed as an envvar - it's not like a single process
> can
> > be both unconfined and leaf-net at the same time.
>
> I'm still not happy about this, as I mentioned earlier: if we have multiple
> instances of the run time in a single address space, the setting will be wrong
> for all but one of them.
>
> But getting the value into the scope is just a side-issue. The real problem is
> that I don't know how to figure out what to set "prefix" to. It seems I can't
> even reliably get at all the manifests for pre-installed, OEM, and click
> scopes.
>
> Jamie, instead of having something like $HOME/.local/share/unity-scopes/leaf-
> net/<scope_id>, could we get rid of the "leaf-fs"/"leaf-
> net"/"aggregator"/"confined" sub-directory?
>
> If so, we could just make it $HOME/.local/share/unity-
> scopes/data_home/<scope_id>.
>
> The core problem here is that I don't know which confinement profile belongs
> to what scope ID, so I don't know how to set the path correctly. If we have a
> path that doesn't change depending on the confinement profile, the problem
> would go away because the prefix would be independent of the confinement type.

As mentioned, that breaks the confinement separation for the case when a scope changes from leaf-fs to leaf-net. We need to have these scope type (eg, leaf-net, leaf-fs) for whenever we confine both types. Putting it in $HOME/.local/share/unity-scopes/<scope_id> or $HOME/.local/share/unity-copes/data_home/<scope_id> breaks that. People have asked what apps do: apps are different because there is no concept of 'local-fs'. All apps are expected to be able to have network access to all the app templates are very tightly confined. leaf-fs and aggregator scopes are very different from apps in that by design they need wide access to the user's data.

Why not just add this to the scope runner .ini file:
[ScopeConfig]
Type=Network # or LocalContent or Aggregator

The downside is the scope author has to keep this in sync with the declared template in the security manifest, but that is something the SDK can help with (not to mention, people shouldn't be changing from one scope type to another except in the most unusual circumstances).

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

> > Who's responsible for creating this directory? I suppose the leaf could be
> > created by the scope itself (does it have permissions to do that?), but the
> > parents have to be created by something unconfined, so who's doing it? The
> > click hook?
>
> Yes, the directory needs to be created as part of the installation.
>
> Still not solved afaict, without it, this branch is useless.

The leaf-net, leaf-fs, or aggregator directories can all be unconditionally created by the scope click hook if they don't already exist. The scope click hook could also consider a new 'Type' field added to ScopeConfig (see below for discussion), but I don't think it needs to (just create all 3 and be done with it).

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

> > I preferred leaf-net, leaf-fs and aggregator so that you don't have to
> change
> > your code if we ever do implement leaf-fs or aggregator policy in the future
> > (note, just because we may never make these available to third party
> > developers, it doesn't mean we won't want apparmor policy for our own
> stuff).
>
> Would the policy for an aggregator every be different from an unconfined
> scope?
> I guess the question is whether I should use "leaf-fs", "leaf-net",
> "aggregator", and "unconfined"?
>
> It's really neither here nor there to me--the list can be as long as we like
> and, if some of the directories in there don't exist, the right things still
> happen.
>
> For the time being, I'll just check for both "aggregator" and "unconfined".
> That way, we have our bases covered. Michal, Jamie, please speak up if you
> think this is wrong or if I'm missing something!

I think it is conceivable that an aggregator can be confined, especially when considering that we might want to confine it for code execution, etc even if the aggregator is still only for trusted 3rd parties. I don't think the scopes team should worry about what confinement goes with what-- just worry about keeping the types (leaf-net, leaf-fs, aggregator, whatever) separate and don't let them share writable when changing between them with the understanding that confinement will enforce this separation.

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

> > Following up on this:
> >
> > > - I'm questioning the wisdom of what I suggested above. It seems that the
> > > registry is forced to do a lot more than it should have to
> >
> > How is this going to work for apps? I expect that applications also will
> need
> > a writable area in the file system somewhere. How do apps find out where
> they
> > can write their files?
>
> https://wiki.ubuntu.com/SecurityTeam/Specifications/ApplicationConfinement but
> iiuic Qt itself was patched to build the directory based on a few envvars. Imo
> we should just do the same, afterall the path has to be "prefix + scope_id",
> and the prefix can be passed as an envvar - it's not like a single process can
> be both unconfined and leaf-net at the same time.

The app toolkits all understand XDG We make sure all the XDG directories are set correctly to *system* values, not app-specific values. Then have the app declare its applicationName. The toolkits all known how to known to append applicationName to the XDG directories (this is standard practice going back years and years). Applications can then use QStandardPath to query for these values.

As mentioned, apps are quite different than scopes and there is no concept of 'an app has wide filesystem/data access but no network access). All apps are assumed that they may have networking and therefore all apps are very tightly confined wrt filesystem/data access, so there is no need draw a distinction between app templates like we are for scope templates.

We can use the same idea for scopes though-- just like applications declare their applicationName in their QML and that adjusts their application directories, scopes can declare in their .ini file what scope type they are which will adjust their writable scope directory.

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

> My point was that you can apply only one apparmor profile, so if there are
> multiple runtimes and scopes in a single process, they either have to share
> the apparmor template or need to be unconfined, otherwise things won't work
> anyway. So the prefix is indeed per process, not per runtime.

Ah, yes, that's true. I'm still trying to avoid environment variables though,
for the simple reason that they are global hidden state. The less we use
env vars, the better, IMO.

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

> > Yes, the directory needs to be created as part of the installation.
> >
> > Still not solved afaict, without it, this branch is useless.
>
> The leaf-net, leaf-fs, or aggregator directories can all be unconditionally
> created by the scope click hook if they don't already exist. The scope click
> hook could also consider a new 'Type' field added to ScopeConfig (see below
> for discussion), but I don't think it needs to (just create all 3 and be done
> with it).

One thing I don't understand here: because the dir is underneath $HOME, that means the click hook would have to create the dir for *all* users of the device? What if a user is added later, after a scope was installed? In that case, whatever script runs to add a user would have to make sure that this directory is create along with everything else.

Unless I'm missing something, this seems brittle to me.

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

> I think it is conceivable that an aggregator can be confined, especially when
> considering that we might want to confine it for code execution, etc even if
> the aggregator is still only for trusted 3rd parties. I don't think the scopes
> team should worry about what confinement goes with what-- just worry about
> keeping the types (leaf-net, leaf-fs, aggregator, whatever) separate and don't
> let them share writable when changing between them with the understanding that
> confinement will enforce this separation.

Yes, I like this. The less we tie the semantics together, the better.

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

> > The core problem here is that I don't know which confinement profile belongs
> > to what scope ID, so I don't know how to set the path correctly. If we have
> a
> > path that doesn't change depending on the confinement profile, the problem
> > would go away because the prefix would be independent of the confinement
> type.
>
> As mentioned, that breaks the confinement separation for the case when a scope
> changes from leaf-fs to leaf-net. We need to have these scope type (eg, leaf-
> net, leaf-fs) for whenever we confine both types. Putting it in
> $HOME/.local/share/unity-scopes/<scope_id> or $HOME/.local/share/unity-
> copes/data_home/<scope_id> breaks that.

Right, yes, this makes sense, thanks!

> Why not just add this to the scope runner .ini file:
> [ScopeConfig]
> Type=Network # or LocalContent or Aggregator

I think this approach has merit, at least to tidy us over until after RTM. I could make the setting optional, with the default being Type=Network. That means the setting would effectively be invisible to scope authors (though still documented), and only aggregators (us, mostly) would need to set it.

The path would be set accordingly, as "leaf-net" or "unconfined".

Directory creation can be done by the scoperunner, I think: if the directory doesn't exist, it'll be created on the fly.

> The downside is the scope author has to keep this in sync with the declared
> template in the security manifest, but that is something the SDK can help with
> (not to mention, people shouldn't be changing from one scope type to another
> except in the most unusual circumstances).

Seeing that, at the moment, we have only two policies for scopes, I don't think that's a big deal. Longer term, once we have a fancier Apparmor query API, we should be able to ditch the config item again and just rely on what we learn from the query API. What I would like to have from the API is functionality that allows me to ask the question "what is the root of my writable data area?"

Ideally, I should get an answer even if that directory doesn't exist yet. And, if it doesn't exist, I should still be able to create that (and only that) directory. That way, the scoperunner wouldn't have to do anything on behalf of the scope before exec'ing it. Instead, the scope, after it was exec'd (and is confined already), could still create its own data directory if it doesn't exist.

413. By Michi Henning

Changed the way cache_directory() is set. New config setting
in <scope_id>.ini, ConfinementType, now determines the
confinement type, which is part of the path for the cache
directory. scoperegistry creates the cache directory if
it doesn't exist.

414. By Michi Henning

Merged devel.

415. By Michi Henning

Updated symbols file.

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

OK, latest version now uses a ConfinementType setting in <scope_id>.ini.

The setting can be either "leaf-net" or "unconfined".

The default is "leaf-net", so scope authors are unaffected. If an unconfined scope wants to use the cache dir, it needs to set this to "unconfined".

cache_directory() returns the appropriate path, with the type substituted:

$HOME/.local/share/unity-scopes/<type>/<scope_id>

The registry creates the directory if it doesn't exist, with permissions 0700.

For now, I think this is good enough. It gets us off the hook until Apparmor can provide a fancier query API.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Jamie Strandboge (jdstrand) wrote :

> > > Yes, the directory needs to be created as part of the installation.
> > >
> > > Still not solved afaict, without it, this branch is useless.
> >
> > The leaf-net, leaf-fs, or aggregator directories can all be unconditionally
> > created by the scope click hook if they don't already exist. The scope click
> > hook could also consider a new 'Type' field added to ScopeConfig (see below
> > for discussion), but I don't think it needs to (just create all 3 and be
> done
> > with it).
>
> One thing I don't understand here: because the dir is underneath $HOME, that
> means the click hook would have to create the dir for *all* users of the
> device? What if a user is added later, after a scope was installed? In that
> case, whatever script runs to add a user would have to make sure that this
> directory is create along with everything else.
>
> Unless I'm missing something, this seems brittle to me.

That is the job of the click hook system. We don't support multi-user yet, but when we do, click user hooks will have to be run anyway. When the click user hooks are run on adding a new user, you get this for free.

In other words-- running click user hooks (of which the scope is but one) have to be solved for the case you mentioned anyway. Nothing special has to be done for scopes when it is.

Revision history for this message
Jamie Strandboge (jdstrand) wrote :
Download full text (3.1 KiB)

> > > The core problem here is that I don't know which confinement profile
> belongs
> > > to what scope ID, so I don't know how to set the path correctly. If we
> have
> > a
> > > path that doesn't change depending on the confinement profile, the problem
> > > would go away because the prefix would be independent of the confinement
> > type.
> >
> > As mentioned, that breaks the confinement separation for the case when a
> scope
> > changes from leaf-fs to leaf-net. We need to have these scope type (eg,
> leaf-
> > net, leaf-fs) for whenever we confine both types. Putting it in
> > $HOME/.local/share/unity-scopes/<scope_id> or $HOME/.local/share/unity-
> > copes/data_home/<scope_id> breaks that.
>
> Right, yes, this makes sense, thanks!
>
> > Why not just add this to the scope runner .ini file:
> > [ScopeConfig]
> > Type=Network # or LocalContent or Aggregator
>
> I think this approach has merit, at least to tidy us over until after RTM. I
> could make the setting optional, with the default being Type=Network. That
> means the setting would effectively be invisible to scope authors (though
> still documented), and only aggregators (us, mostly) would need to set it.
>
> The path would be set accordingly, as "leaf-net" or "unconfined".
>
> Directory creation can be done by the scoperunner, I think: if the directory
> doesn't exist, it'll be created on the fly.
>
> > The downside is the scope author has to keep this in sync with the declared
> > template in the security manifest, but that is something the SDK can help
> with
> > (not to mention, people shouldn't be changing from one scope type to another
> > except in the most unusual circumstances).
>
> Seeing that, at the moment, we have only two policies for scopes, I don't
> think that's a big deal. Longer term, once we have a fancier Apparmor query
> API, we should be able to ditch the config item again and just rely on what we
> learn from the query API. What I would like to have from the API is
> functionality that allows me to ask the question "what is the root of my
> writable data area?"
>
> Ideally, I should get an answer even if that directory doesn't exist yet. And,
> if it doesn't exist, I should still be able to create that (and only that)
> directory. That way, the scoperunner wouldn't have to do anything on behalf of
> the scope before exec'ing it. Instead, the scope, after it was exec'd (and is
> confined already), could still create its own data directory if it doesn't
> exist.

The libapparmor query API won't be able to answer 'what is the base of my writable area'. It will be able to say 'can I write to $HOME/.local/share/unity-scopes/leaf-net/<scope_id>' or 'can I write to $HOME/.local/share/unity-scopes/leaf-fs/<scope_id>' so you can determine which is your writable area.

IMPORTANT: I think this is understood, the confined process will be able to create the '<scope id>' subdirectory (eg, $HOME/.local/share/unity-scopes/leaf-net/<scope_id>), so the scoperunner/API can do that. The confined process will *not* be able to create the 'scope type' directory (eg, $HOME/.local/share/unity-scopes/leaf-net), which is why I said the scope click user hook could just make su...

Read more...

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

I am going to approve this, for my part. I did glance through the code and made a couple of inline comments. While I do think the approach here couples the scope type with security policy more than is required, I understand that this is temporary until we have the libapparmor query interface up and running for files. For now, we only have leaf-net and unconfined and this MR handles that. By the looks of it, it shouldn't be difficult to transition away from ConfinementType when you move to the apparmor query API, and after you do, maintenance of that bit of code shouldn't be much more than managing an 'if/else if/else' statement.

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

> IMPORTANT: I think this is understood, the confined process will be able to
> create the '<scope id>' subdirectory (eg, $HOME/.local/share/unity-scopes
> /leaf-net/<scope_id>), so the scoperunner/API can do that.

This actually wasn't clear, if that's the case, I think the scope itself should just try to create / open the dir and use that, then we don't need a new config item that would just be deprecated as soon as possible. (and scoperegistry can just create the parent dirs unconditionally)

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

> > IMPORTANT: I think this is understood, the confined process will be able to
> > create the '<scope id>' subdirectory (eg, $HOME/.local/share/unity-scopes
> > /leaf-net/<scope_id>), so the scoperunner/API can do that.
>
> This actually wasn't clear, if that's the case, I think the scope itself
> should just try to create / open the dir and use that, then we don't need a
> new config item that would just be deprecated as soon as possible. (and
> scoperegistry can just create the parent dirs unconditionally)

As long as the process creating the $HOME/.local/share/unity-scopes/leaf-net/ is unconfined, it doesn't matter who creates it. However, don't you still need the config item for the API to know what to return to the confined process so it can create $HOME/.local/share/unity-scopes/leaf-net/<scope_id>?

416. By Michi Henning

Backed out changes for config file setting. Using the
try-and-make-conclusions-if-it-doesn't-work approach now.

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

Merged devel and resolved conflicts.

418. By Michi Henning

scoperegistry now creates the root of the data directory for confined
scopes, e.g. $HOME/.local/share/unity-scopes/leaf-net.

The directory <scope_id> within that directory is created by
each confined scope itself when the scope is run.
(The scope's Apparmor profile allows this.)

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

The registry now creates the leaf-net directory in case it isn't there already, e.g

$HOME/.local/share/unity-scopes/leaf-net

The <scope_id> subdir under that is created by each confined scope itself when it
is run.

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)
419. By Michi Henning

Merged devel and resolved conflicts.

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

Let's merge this and fix any remaining issues afterwards, it's been sitting here for far too long.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CONFIGFILES'
2--- CONFIGFILES 2014-07-21 06:34:24 +0000
3+++ CONFIGFILES 2014-07-28 11:21:43 +0000
4@@ -92,7 +92,7 @@
5
6 - DataDir
7
8- The parent directory under the run time writes scope-specific data files
9+ The parent directory under which the run time writes scope-specific data files
10 (such as settings).
11
12 The default value is $HOME/.local/share/unity-scopes.
13
14=== modified file 'HACKING'
15--- HACKING 2014-06-26 15:53:22 +0000
16+++ HACKING 2014-07-28 11:21:43 +0000
17@@ -193,12 +193,17 @@
18 Running the test manually is simple. After building and installing the
19 new packages, just run 'sh debian/tests/scopebuild'.
20
21-When making API breaks, make sure to check if autopkg test scripts
22-need changing. The point of autopkg is not to exercise the API
23-thoroughly, so it should not need changing all that often.
24-
25-At the moment it is unclear if these tests are executed during Jenkins
26-builds. This will lead to autopkgtest failing later if scopes' API is
27-changed in a backwards incompatible way. If this happens the test
28-needs to be fixed either by updating the test or backing out the API
29-breaking change.
30+To run the autopkg tests the same way Jenkins does, without installing
31+the packages, follow the instructions here:
32+
33+http://packaging.ubuntu.com/html/auto-pkg-test.html
34+
35+When adding new tests to debian/tests, be sure that the new tests
36+are built and run by adding them to tests/autopkg. Doing this doesn't
37+run the tests exactly the same way as on Jenkins because they will
38+be built and run against the headers and library in the build area,
39+rather than against the installed packages. But it provides a basic
40+sanity check for them. Without this, it's very easy to make a breaking
41+change to the API and forgetting to update the autopkg tests too,
42+meaning that the failure will show up only in Jenkins, but not
43+when running the tests locally.
44
45=== modified file 'RELEASE_NOTES.md'
46--- RELEASE_NOTES.md 2014-07-24 12:12:13 +0000
47+++ RELEASE_NOTES.md 2014-07-28 11:21:43 +0000
48@@ -3,8 +3,23 @@
49
50 Changes in version 0.6.0
51 ========================
52+ - Added cache_directory() method to ScopeBase, so a scope can find out where it can write its files.
53+
54+ - Refactored scoperunner and ScopeLoader. ScopeLoader no longer knows about the registry and
55+ scoperunner now calls RuntimeImpl::run_scope() to set the scope running, instead of duplicating
56+ lots of functionality.
57+
58+ - Removed registry parameter from ScopeBase::start(). The registry is now available via a registry()
59+ accessor on ScopeBase. The original start() method is still present, but deprecated. The default
60+ implementation of the new start() method forwards to the old one so, if a scope implements only the
61+ old one but not the new one, things still work.
62+
63+ - Made methods on ScopeBase virtual, so the testing framework can override them in a test scope.
64+
65 - Added support for additional query reply info.
66+
67 - Introduced QueryMetadata base for shared functionality of *Metadata classes.
68+
69 - Added set_internet_connectivity() and internet_connectivity() to QueryMetadata.
70
71 Changes in version 0.5.2
72
73=== modified file 'debian/changelog'
74--- debian/changelog 2014-07-28 10:02:00 +0000
75+++ debian/changelog 2014-07-28 11:21:43 +0000
76@@ -1,10 +1,13 @@
77 unity-scopes-api (0.6.0-0ubuntu1) UNRELEASED; urgency=medium
78
79- * Added support for additional query reply info.
80+ * Added cache_directory() method and refactored scoperunner and RuntimeImpl.
81+
82+ [ Marcus Tomlinson ]
83 * Introduced QueryMetadata base for shared functionality of *Metadata classes.
84 * Added set_internet_connectivity() and internet_connectivity() to QueryMetadata.
85+ * Added support for additional query reply info.
86
87- -- Marcus Tomlinson <marcus.tomlinson@canonical.com> Mon, 21 Jul 2014 09:14:39 +0200
88+ -- Michi Henning <michi.henning@canonical.com> Mon, 07 Jul 2014 14:34:04 +1000
89
90 unity-scopes-api (0.5.2+14.10.20140723-0ubuntu1) utopic; urgency=low
91
92
93=== modified file 'debian/libunity-scopes2.symbols'
94--- debian/libunity-scopes2.symbols 2014-07-28 10:02:00 +0000
95+++ debian/libunity-scopes2.symbols 2014-07-28 11:21:43 +0000
96@@ -408,8 +408,10 @@
97 (c++)"unity::scopes::testing::Benchmark::Result::load_from(std::basic_istream<char, std::char_traits<char> >&)@Base" 0.4.0+14.04.20140312.1
98 (c++)"unity::scopes::testing::operator==(unity::scopes::testing::Benchmark::Result const&, unity::scopes::testing::Benchmark::Result const&)@Base" 0.4.0+14.04.20140312.1
99 (c++)"unity::scopes::testing::operator<<(std::basic_ostream<char, std::char_traits<char> >&, unity::scopes::testing::Benchmark::Result const&)@Base" 0.4.0+14.04.20140312.1
100- (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
101+ (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
102+ (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&, std::shared_ptr<unity::scopes::CannedQuery const> const&, unity::scopes::CategoryRenderer const&)@Base" 0replaceme
103 (c++)"unity::scopes::Category::Category(std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, unity::scopes::Variant, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unity::scopes::Variant> > > const&)@Base" 0.4.0+14.04.20140312.1
104+ (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
105 (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&, std::shared_ptr<unity::scopes::CannedQuery const> const&, unity::scopes::CategoryRenderer const&)@Base" 0.5.2+14.10.20140709.2
106 (c++)"unity::scopes::Category::Category(std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, unity::scopes::Variant, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unity::scopes::Variant> > > const&)@Base" 0.4.0+14.04.20140312.1
107 (c++)"unity::scopes::Category::~Category()@Base" 0.4.0+14.04.20140312.1
108@@ -424,11 +426,11 @@
109 (c++)"unity::scopes::internal::ScopeConfig::parse_appearance_attribute(std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, unity::scopes::Variant, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unity::scopes::Variant> > >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.5.2+14.10.20140709.2
110 (c++)"unity::scopes::internal::ScopeConfig::ScopeConfig(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1
111 (c++)"unity::scopes::internal::ScopeConfig::~ScopeConfig()@Base" 0.4.0+14.04.20140312.1
112- (c++)"unity::scopes::internal::ScopeLoader::load(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<unity::scopes::Registry> const&)@Base" 0.5.2+14.10.20140709.2
113+ (c++)"unity::scopes::internal::ScopeLoader::load(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0replaceme
114 (c++)"unity::scopes::internal::ScopeLoader::stop()@Base" 0.4.0+14.04.20140312.1
115 (c++)"unity::scopes::internal::ScopeLoader::start()@Base" 0.4.0+14.04.20140312.1
116 (c++)"unity::scopes::internal::ScopeLoader::unload()@Base" 0.4.0+14.04.20140312.1
117- (c++)"unity::scopes::internal::ScopeLoader::ScopeLoader(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&, std::shared_ptr<unity::scopes::Registry> const&)@Base" 0.5.2+14.10.20140709.2
118+ (c++)"unity::scopes::internal::ScopeLoader::ScopeLoader(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0replaceme
119 (c++)"unity::scopes::internal::ScopeLoader::~ScopeLoader()@Base" 0.4.0+14.04.20140312.1
120 (c++)"unity::scopes::internal::ScopeObject::perform_action(unity::scopes::Result const&, unity::scopes::ActionMetadata const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<unity::scopes::internal::MWReply> const&, unity::scopes::internal::InvokeInfo const&)@Base" 0.4.0+14.04.20140312.1
121 (c++)"unity::scopes::internal::ScopeObject::query(std::shared_ptr<unity::scopes::internal::MWReply> const&, unity::scopes::internal::MiddlewareBase*, std::function<std::shared_ptr<unity::scopes::QueryBase> ()> const&, std::function<std::shared_ptr<unity::scopes::internal::QueryObjectBase> (std::shared_ptr<unity::scopes::QueryBase>, std::shared_ptr<unity::scopes::internal::MWQueryCtrl>)> const&)@Base" 0.4.0+14.04.20140312.1
122@@ -545,7 +547,7 @@
123 (c++)"unity::scopes::ScopeBase::runtime_version(int&, int&, int&)@Base" 0.4.0+14.04.20140312.1
124 (c++)"unity::scopes::ScopeBase::run()@Base" 0.4.0+14.04.20140312.1
125 (c++)"unity::scopes::ScopeBase::stop()@Base" 0.5.0+14.10.20140619
126- (c++)"unity::scopes::ScopeBase::start(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<unity::scopes::Registry> const&)@Base" 0.5.0+14.10.20140619
127+ (c++)"unity::scopes::ScopeBase::start(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0replaceme
128 (c++)"unity::scopes::ScopeBase::activate(unity::scopes::Result const&, unity::scopes::ActionMetadata const&)@Base" 0.4.0+14.04.20140312.1
129 (c++)"unity::scopes::ScopeBase::ScopeBase()@Base" 0.4.0+14.04.20140312.1
130 (c++)"unity::scopes::ScopeBase::~ScopeBase()@Base" 0.4.0+14.04.20140312.1
131@@ -733,6 +735,7 @@
132 (c++)"unity::scopes::internal::RuntimeImpl::reply_reaper() const@Base" 0.4.0+14.04.20140312.1
133 (c++)"unity::scopes::internal::RuntimeImpl::ss_configfile() const@Base" 0.4.4+14.10.20140508
134 (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
135+ (c++)"unity::scopes::internal::RuntimeImpl::find_cache_dir() const@Base" 0replaceme
136 (c++)"unity::scopes::internal::RuntimeImpl::proxy_to_string(std::shared_ptr<unity::scopes::Object> const&) const@Base" 0.4.0+14.04.20140312.1
137 (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
138 (c++)"unity::scopes::internal::RuntimeImpl::registry_identity() const@Base" 0.4.0+14.04.20140312.1
139@@ -815,9 +818,11 @@
140 (c++)"unity::scopes::internal::JsonSettingsSchema::definitions() const@Base" 0.5.2+14.10.20140709.2
141 (c++)"unity::scopes::internal::StateReceiverObject::state_received() const@Base" 0.4.2+14.04.20140404.2
142 (c++)"unity::scopes::QueryBase::valid() const@Base" 0.4.3+14.10.20140428
143- (c++)"unity::scopes::QueryBase::settings() const@Base" 0.5.2+14.10.20140709.2
144+ (c++)"unity::scopes::QueryBase::settings() const@Base" 0replaceme
145+ (c++)"unity::scopes::ScopeBase::cache_directory() const@Base" 0replaceme
146 (c++)"unity::scopes::ScopeBase::scope_directory() const@Base" 0.4.2+14.04.20140404.2
147- (c++)"unity::scopes::ScopeBase::settings() const@Base" 0.5.2+14.10.20140709.2
148+ (c++)"unity::scopes::ScopeBase::registry() const@Base" 0replaceme
149+ (c++)"unity::scopes::ScopeBase::settings() const@Base" 0replaceme
150 (c++)"typeinfo for unity::scopes::FilterBase@Base" 0.4.0+14.04.20140312.1
151 (c++)"typeinfo for unity::scopes::SearchReply@Base" 0.4.0+14.04.20140312.1
152 (c++)"typeinfo for unity::scopes::ListenerBase@Base" 0.4.0+14.04.20140312.1
153@@ -838,6 +843,7 @@
154 (c++)"typeinfo for unity::scopes::CategoryRenderer@Base" 0.4.0+14.04.20140312.1
155 (c++)"typeinfo for unity::scopes::PreviewQueryBase@Base" 0.4.0+14.04.20140312.1
156 (c++)"typeinfo for unity::scopes::TimeoutException@Base" 0.4.0+14.04.20140312.1
157+ (c++)"typeinfo for unity::scopes::AbstractScopeBase@Base" 0replaceme
158 (c++)"typeinfo for unity::scopes::CategorisedResult@Base" 0.4.0+14.04.20140312.1
159 (c++)"typeinfo for unity::scopes::NotFoundException@Base" 0.4.0+14.04.20140312.1
160 (c++)"typeinfo for unity::scopes::SearchListenerBase@Base" 0.4.0+14.04.20140312.1
161@@ -883,6 +889,7 @@
162 (c++)"typeinfo name for unity::scopes::CategoryRenderer@Base" 0.4.0+14.04.20140312.1
163 (c++)"typeinfo name for unity::scopes::PreviewQueryBase@Base" 0.4.0+14.04.20140312.1
164 (c++)"typeinfo name for unity::scopes::TimeoutException@Base" 0.4.0+14.04.20140312.1
165+ (c++)"typeinfo name for unity::scopes::AbstractScopeBase@Base" 0replaceme
166 (c++)"typeinfo name for unity::scopes::CategorisedResult@Base" 0.4.0+14.04.20140312.1
167 (c++)"typeinfo name for unity::scopes::NotFoundException@Base" 0.4.0+14.04.20140312.1
168 (c++)"typeinfo name for unity::scopes::SearchListenerBase@Base" 0.4.0+14.04.20140312.1
169@@ -939,6 +946,7 @@
170 (c++)"vtable for unity::scopes::CategoryRenderer@Base" 0.4.0+14.04.20140312.1
171 (c++)"vtable for unity::scopes::PreviewQueryBase@Base" 0.4.0+14.04.20140312.1
172 (c++)"vtable for unity::scopes::TimeoutException@Base" 0.4.0+14.04.20140312.1
173+ (c++)"vtable for unity::scopes::AbstractScopeBase@Base" 0replaceme
174 (c++)"vtable for unity::scopes::CategorisedResult@Base" 0.4.0+14.04.20140312.1
175 (c++)"vtable for unity::scopes::NotFoundException@Base" 0.4.0+14.04.20140312.1
176 (c++)"vtable for unity::scopes::SearchListenerBase@Base" 0.4.0+14.04.20140312.1
177
178=== modified file 'debian/tests/scopebuild'
179--- debian/tests/scopebuild 2014-06-03 12:49:04 +0000
180+++ debian/tests/scopebuild 2014-07-28 11:21:43 +0000
181@@ -9,60 +9,11 @@
182
183 WORKDIR=$(mktemp -d)
184 trap "rm -rf $WORKDIR" 0 INT QUIT ABRT PIPE TERM
185+cp scopetest.cpp $WORKDIR
186 cd $WORKDIR
187-cat <<EOF > scopetest.cpp
188-#include <unity/scopes/ScopeBase.h>
189-#include <unity/scopes/QueryBase.h>
190-#include <unity/scopes/ReplyProxyFwd.h>
191-#include <unity/scopes/QueryBase.h>
192-#include <unity/scopes/PreviewQueryBase.h>
193-
194-class DemoScope : public unity::scopes::ScopeBase
195-{
196-public:
197- virtual int start(std::string const&, unity::scopes::RegistryProxy const&) override;
198-
199- virtual void stop() override;
200-
201- unity::scopes::PreviewQueryBase::UPtr preview(const unity::scopes::Result&,
202- const unity::scopes::ActionMetadata&) override;
203-
204- virtual unity::scopes::SearchQueryBase::UPtr search(unity::scopes::CannedQuery const& q,
205- unity::scopes::SearchMetadata const&) override;
206-};
207-
208-using namespace unity::scopes;
209-
210-int DemoScope::start(std::string const&, unity::scopes::RegistryProxy const&)
211-{
212- return 0;
213-}
214-
215-void DemoScope::stop()
216-{
217-}
218-
219-SearchQueryBase::UPtr DemoScope::search(unity::scopes::CannedQuery const &q,
220- unity::scopes::SearchMetadata const&)
221-{
222- unity::scopes::SearchQueryBase::UPtr query(nullptr);
223- return query;
224-}
225-
226-PreviewQueryBase::UPtr DemoScope::preview(Result const& result, ActionMetadata const& /*metadata*/) {
227- unity::scopes::PreviewQueryBase::UPtr preview(nullptr);
228- return preview;
229-}
230-
231-int main(int, char**)
232-{
233- DemoScope d;
234- return 0;
235-}
236-EOF
237-
238-g++ -std=c++11 -o scopebin scopetest.cpp `pkg-config --cflags --libs libunity-scopes`
239+
240+g++ -std=c++11 -o scopetest scopetest.cpp `pkg-config --cflags --libs libunity-scopes`
241 echo "Scope build: OK"
242-[ -x scopebin ]
243-./scopebin
244+[ -x scopetest ]
245+./scopetest
246 echo "Scope run: OK"
247
248=== added file 'debian/tests/scopetest.cpp'
249--- debian/tests/scopetest.cpp 1970-01-01 00:00:00 +0000
250+++ debian/tests/scopetest.cpp 2014-07-28 11:21:43 +0000
251@@ -0,0 +1,62 @@
252+/*
253+ * Copyright (C) 2014 Canonical Ltd
254+ *
255+ * This program is free software: you can redistribute it and/or modify
256+ * it under the terms of the GNU Lesser General Public License version 3 as
257+ * published by the Free Software Foundation.
258+ *
259+ * This program is distributed in the hope that it will be useful,
260+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
261+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
262+ * GNU Lesser General Public License for more details.
263+ *
264+ * You should have received a copy of the GNU Lesser General Public License
265+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
266+ */
267+
268+#include <unity/scopes/PreviewQueryBase.h>
269+#include <unity/scopes/QueryBase.h>
270+#include <unity/scopes/ReplyProxyFwd.h>
271+#include <unity/scopes/ScopeBase.h>
272+
273+class DemoScope : public unity::scopes::ScopeBase
274+{
275+public:
276+ virtual void start(std::string const&) override;
277+
278+ virtual void stop() override;
279+
280+ virtual unity::scopes::PreviewQueryBase::UPtr preview(const unity::scopes::Result&,
281+ const unity::scopes::ActionMetadata&) override;
282+
283+ virtual unity::scopes::SearchQueryBase::UPtr search(unity::scopes::CannedQuery const& q,
284+ unity::scopes::SearchMetadata const&) override;
285+};
286+
287+using namespace unity::scopes;
288+
289+void DemoScope::start(std::string const&)
290+{
291+}
292+
293+void DemoScope::stop()
294+{
295+}
296+
297+SearchQueryBase::UPtr DemoScope::search(unity::scopes::CannedQuery const& /*q*/,
298+ unity::scopes::SearchMetadata const&)
299+{
300+ unity::scopes::SearchQueryBase::UPtr query(nullptr);
301+ return query;
302+}
303+
304+PreviewQueryBase::UPtr DemoScope::preview(Result const& /*result*/, ActionMetadata const& /*metadata*/) {
305+ unity::scopes::PreviewQueryBase::UPtr preview(nullptr);
306+ return preview;
307+}
308+
309+int main(int, char**)
310+{
311+ DemoScope d;
312+ return 0;
313+}
314
315=== modified file 'demo/click/scope-click/scope-click.cpp'
316--- demo/click/scope-click/scope-click.cpp 2014-06-17 11:20:48 +0000
317+++ demo/click/scope-click/scope-click.cpp 2014-07-28 11:21:43 +0000
318@@ -56,7 +56,7 @@
319 class MyScope : public ScopeBase
320 {
321 public:
322- virtual void start(string const&, RegistryProxy const&) override {}
323+ virtual void start(string const&) override {}
324
325 virtual void stop() override {}
326
327
328=== modified file 'demo/scopes/scope-A/scope-A.cpp'
329--- demo/scopes/scope-A/scope-A.cpp 2014-06-25 16:41:51 +0000
330+++ demo/scopes/scope-A/scope-A.cpp 2014-07-28 11:21:43 +0000
331@@ -160,7 +160,7 @@
332 class MyScope : public ScopeBase
333 {
334 public:
335- virtual void start(string const& scope_id, RegistryProxy const&) override
336+ virtual void start(string const& scope_id) override
337 {
338 scope_id_ = scope_id;
339 }
340
341=== modified file 'demo/scopes/scope-B/scope-B.cpp'
342--- demo/scopes/scope-B/scope-B.cpp 2014-06-17 11:20:48 +0000
343+++ demo/scopes/scope-B/scope-B.cpp 2014-07-28 11:21:43 +0000
344@@ -140,18 +140,18 @@
345 class MyScope : public ScopeBase
346 {
347 public:
348- virtual void start(string const& scope_id, RegistryProxy const& registry) override
349+ virtual void start(string const& scope_id) override
350 {
351 scope_id_ = scope_id;
352
353- if (!registry)
354+ if (!registry())
355 {
356 throw ConfigException(scope_id + ": No registry available, cannot locate child scopes");
357 }
358 // Lock up scopes C and D in the registry and remember their proxies.
359- auto meta_c = registry->get_metadata("scope-C");
360+ auto meta_c = registry()->get_metadata("scope-C");
361 scope_c_ = meta_c.proxy();
362- auto meta_d = registry->get_metadata("scope-D");
363+ auto meta_d = registry()->get_metadata("scope-D");
364 scope_d_ = meta_d.proxy();
365 }
366
367
368=== modified file 'demo/scopes/scope-C/scope-C.cpp'
369--- demo/scopes/scope-C/scope-C.cpp 2014-06-17 11:20:48 +0000
370+++ demo/scopes/scope-C/scope-C.cpp 2014-07-28 11:21:43 +0000
371@@ -184,7 +184,7 @@
372 class MyScope : public ScopeBase
373 {
374 public:
375- virtual void start(string const& scope_id, RegistryProxy const&) override
376+ virtual void start(string const& scope_id) override
377 {
378 scope_id_ = scope_id;
379 }
380
381=== modified file 'demo/scopes/scope-D/scope-D.cpp'
382--- demo/scopes/scope-D/scope-D.cpp 2014-06-17 11:20:48 +0000
383+++ demo/scopes/scope-D/scope-D.cpp 2014-07-28 11:21:43 +0000
384@@ -183,7 +183,7 @@
385 class MyScope : public ScopeBase
386 {
387 public:
388- virtual void start(string const& scope_id, RegistryProxy const&) override
389+ virtual void start(string const& scope_id) override
390 {
391 scope_id_ = scope_id;
392 }
393
394=== modified file 'demo/scopes/scope-N/scope-N.cpp'
395--- demo/scopes/scope-N/scope-N.cpp 2014-06-17 11:20:48 +0000
396+++ demo/scopes/scope-N/scope-N.cpp 2014-07-28 11:21:43 +0000
397@@ -68,7 +68,7 @@
398 class MyScope : public ScopeBase
399 {
400 public:
401- virtual void start(string const& scope_id, RegistryProxy const&) override
402+ virtual void start(string const& scope_id) override
403 {
404 scope_id_ = scope_id;
405 }
406
407=== modified file 'demo/scopes/scope-S/scope-S.cpp'
408--- demo/scopes/scope-S/scope-S.cpp 2014-06-17 11:20:48 +0000
409+++ demo/scopes/scope-S/scope-S.cpp 2014-07-28 11:21:43 +0000
410@@ -85,7 +85,7 @@
411 class MyScope : public ScopeBase
412 {
413 public:
414- virtual void start(string const& scope_id, RegistryProxy const&) override
415+ virtual void start(string const& scope_id) override
416 {
417 scope_id_ = scope_id;
418 }
419
420=== modified file 'doc/tutorial.dox'
421--- doc/tutorial.dox 2014-07-22 10:38:18 +0000
422+++ doc/tutorial.dox 2014-07-28 11:21:43 +0000
423@@ -615,10 +615,10 @@
424 With the above classes a test case that checks if MyScope calls appropriate methods of unity::scopes::SearchReply may look like this (note that it just checks
425 if proper methods get called and uses _ matchers that match any values; put actual values in there for stricts checks):
426 \code{.cpp}
427-typedef unity::scopes::testing::TypedScopeFixture<MyScope> TestScopeFixutre;
428+typedef unity::scopes::testing::TypedScopeFixture<MyScope> TestScopeFixture;
429 using namespace ::testing;
430
431-TEST_F(TestScopeFixutre, search_results)
432+TEST_F(TestScopeFixture, search_results)
433 {
434 const unity::scopes::CategoryRenderer renderer;
435
436@@ -724,7 +724,7 @@
437 The `ScopeConfig` group is mandatory and must contain settings for at least `DisplayName`, `Description`, and `Author`.
438 `DisplayName` and `Description` can (and should) be localized. For example:
439
440-`Description[de] = Fu&szlig;ballergebnisse`
441+`Description[de_DE] = Fu&szlig;ballergebnisse`
442
443 In addition to allowing the registry to make the scope available, this information controls how the scope appears
444 in the "Scopes" scope.
445
446=== added file 'include/unity/scopes/AbstractScopeBase.h'
447--- include/unity/scopes/AbstractScopeBase.h 1970-01-01 00:00:00 +0000
448+++ include/unity/scopes/AbstractScopeBase.h 2014-07-28 11:21:43 +0000
449@@ -0,0 +1,65 @@
450+/*
451+ * Copyright (C) 2014 Canonical Ltd
452+ *
453+ * This program is free software: you can redistribute it and/or modify
454+ * it under the terms of the GNU Lesser General Public License version 3 as
455+ * published by the Free Software Foundation.
456+ *
457+ * This program is distributed in the hope that it will be useful,
458+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
459+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
460+ * GNU Lesser General Public License for more details.
461+ *
462+ * You should have received a copy of the GNU Lesser General Public License
463+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
464+ *
465+ * Authored by: Michi Henning <michi.henning@canonical.com>
466+ */
467+
468+#ifndef UNITY_SCOPES_ABSTRACTSCOPEBASE_H
469+#define UNITY_SCOPES_ABSTRACTSCOPEBASE_H
470+
471+#include <unity/scopes/ActivationQueryBase.h>
472+#include <unity/scopes/PreviewQueryBase.h>
473+#include <unity/scopes/Registry.h>
474+#include <unity/scopes/SearchQueryBase.h>
475+
476+namespace unity
477+{
478+
479+namespace scopes
480+{
481+
482+/**
483+\brief Abstract base class for a scope implementation.
484+
485+This class allows a scope to be replaced by a mock implementation.
486+See unity::scopes::ScopeBase for documentation of the member functions.
487+*/
488+
489+class AbstractScopeBase
490+{
491+public:
492+/// @cond
493+ virtual void start(std::string const& scope_id) = 0;
494+ virtual void stop() = 0;
495+ virtual void run() = 0;
496+ virtual SearchQueryBase::UPtr search(CannedQuery const& query, SearchMetadata const& metadata) = 0;
497+ virtual ActivationQueryBase::UPtr activate(Result const& result, ActionMetadata const& metadata) = 0;
498+ virtual ActivationQueryBase::UPtr perform_action(Result const& result,
499+ ActionMetadata const& metadata,
500+ std::string const& widget_id,
501+ std::string const& action_id) = 0;
502+ virtual PreviewQueryBase::UPtr preview(Result const& result, ActionMetadata const& metadata) = 0;
503+ virtual std::string scope_directory() const = 0;
504+ virtual std::string cache_directory() const = 0;
505+ virtual unity::scopes::RegistryProxy registry() const = 0;
506+ virtual VariantMap settings() const = 0;
507+/// @endcond
508+};
509+
510+} // namespace scopes
511+
512+} // namespace unity
513+
514+#endif
515
516=== modified file 'include/unity/scopes/ScopeBase.h'
517--- include/unity/scopes/ScopeBase.h 2014-06-24 11:11:11 +0000
518+++ include/unity/scopes/ScopeBase.h 2014-07-28 11:21:43 +0000
519@@ -19,14 +19,10 @@
520 #ifndef UNITY_SCOPES_SCOPEBASE_H
521 #define UNITY_SCOPES_SCOPEBASE_H
522
523-#include <unity/scopes/SearchQueryBase.h>
524-#include <unity/scopes/PreviewQueryBase.h>
525-#include <unity/scopes/RegistryProxyFwd.h>
526-#include <unity/scopes/ActivationQueryBase.h>
527-#include <unity/scopes/Version.h>
528-#include <unity/scopes/Result.h>
529+#include <unity/scopes/AbstractScopeBase.h>
530 #include <unity/scopes/ActionMetadata.h>
531 #include <unity/scopes/SearchMetadata.h>
532+#include <unity/scopes/Version.h>
533
534 /**
535 \brief Expands to the identifier of the scope create function. @hideinitializer
536@@ -68,9 +64,10 @@
537
538 namespace internal
539 {
540+
541 class ScopeBaseImpl;
542-class ScopeLoader;
543 class RuntimeImpl;
544+
545 }
546
547 /**
548@@ -90,9 +87,9 @@
549 MyScope();
550 virtual ~MyScope();
551
552- virtual void start(); // Optional
553- virtual void stop(); // Optional
554- virtual void run(); // Optional
555+ virtual void start(std::string const& scope_id); // Optional
556+ virtual void stop(); // Optional
557+ virtual void run(); // Optional
558 };
559 ~~~
560
561@@ -134,7 +131,7 @@
562 call to stop() in a timely manner.
563 */
564
565-class ScopeBase
566+class ScopeBase : public AbstractScopeBase
567 {
568 public:
569 /// @cond
570@@ -150,11 +147,8 @@
571 The call to start() is made by the same thread that calls the create function.
572
573 \param scope_id The name of the scope as defined by the scope's configuration file.
574-
575- \param registry A proxy to the scope registry. This parameter is provided for aggregating
576- scopes that need to retrieve proxies to their child scopes.
577 */
578- virtual void start(std::string const& scope_id, RegistryProxy const& registry);
579+ virtual void start(std::string const& scope_id);
580
581 /**
582 \brief Called by the scopes run time when the scope should shut down.
583@@ -184,7 +178,7 @@
584 /**
585 \brief Called by the scopes run time when a scope needs to instantiate a query.
586
587- This method must return an instance that is derived from QueryBase. The implementation
588+ This method must return an instance that is derived from `QueryBase`. The implementation
589 of this method must return in a timely manner, that is, it should perform only minimal
590 initialization that is guaranteed to complete quickly. The call to search() is made
591 by an arbitrary thread.
592@@ -197,7 +191,7 @@
593 /**
594 \brief Called by the scopes run time when a scope needs to respond to a result activation request.
595
596- This method must return an instance that is derived from ActivationQueryBase. The implementation
597+ This method must return an instance that is derived from `ActivationQueryBase`. The implementation
598 of this method must return in a timely manner, that is, it should perform only minimal
599 initialization that is guaranteed to complete quickly. The call to activate() is made
600 by an arbitrary thread.
601@@ -206,13 +200,13 @@
602 \param result The result that should be activated.
603 \param metadata additional data sent by the client.
604 \return The activation instance.
605- */
606+ */
607 virtual ActivationQueryBase::UPtr activate(Result const& result, ActionMetadata const& metadata);
608
609 /**
610 \brief Invoked when a scope is requested to handle a preview action.
611
612- This method must return an instance that is derived from ActivationQueryBase. The implementation
613+ This method must return an instance that is derived from `ActivationQueryBase`. The implementation
614 of this method must return in a timely manner, that is, it should perform only minimal
615 initialization that is guaranteed to complete quickly. The call to activate() is made
616 by an arbitrary thread.
617@@ -223,20 +217,23 @@
618 \param widget_id The identifier of the 'actions' widget of the activated action.
619 \param action_id The identifier of the action that was activated.
620 \return The activation instance.
621- */
622- virtual ActivationQueryBase::UPtr perform_action(Result const& result, ActionMetadata const& metadata, std::string const& widget_id, std::string const& action_id);
623+ */
624+ virtual ActivationQueryBase::UPtr perform_action(Result const& result,
625+ ActionMetadata const& metadata,
626+ std::string const& widget_id,
627+ std::string const& action_id);
628
629 /**
630 \brief Invoked when a scope is requested to create a preview for a particular result.
631
632- This method must return an instance that is derived from PreviewQueryBase. The implementation
633+ This method must return an instance that is derived from `PreviewQueryBase`. The implementation
634 of this method must return in a timely manner, that is, it should perform only minimal
635 initialization that is guaranteed to complete quickly. The call to activate() is made
636 by an arbitrary thread.
637 \param result The result that should be previewed.
638 \param metadata Additional data sent by the client.
639 \return The preview instance.
640- */
641+ */
642 virtual PreviewQueryBase::UPtr preview(Result const& result, ActionMetadata const& metadata) = 0;
643
644 /**
645@@ -251,8 +248,34 @@
646 call this method from the constructor!
647
648 \return The scope's configuration directory.
649- */
650- std::string scope_directory() const;
651+ \throws LogicException if called from the constructor of this instance.
652+ */
653+ virtual std::string scope_directory() const final;
654+
655+ /**
656+ \brief Returns a directory that is (exclusively) writable for the scope.
657+
658+ This directory allows scopes to store persistent information, such
659+ as cached content or similar.
660+
661+ \note The cache directory is available only after this ScopeBase is instantiated; do not
662+ call this method from the constructor!
663+
664+ \return The root directory of the filesystem sub-tree that is writable for the scope.
665+ \throws LogicException if called from the constructor of this instance.
666+ */
667+ virtual std::string cache_directory() const final;
668+
669+ /**
670+ \brief Returns the proxy to the registry.
671+
672+ \note The registr proxy is available only after this ScopeBase is instantiated; do not
673+ call this method from the constructor!
674+
675+ \return The proxy to the registry.
676+ \throws LogicException if called from the constructor of this instance.
677+ */
678+ virtual unity::scopes::RegistryProxy registry() const final;
679
680 /**
681 \brief Returns a dictionary with the scope's current settings.
682@@ -266,8 +289,9 @@
683 call this method from the constructor!
684
685 \return The scope's current settings.
686+ \throws LogicException if called from the constructor of this instance.
687 */
688- VariantMap settings() const;
689+ virtual VariantMap settings() const final;
690
691 protected:
692 /// @cond
693@@ -275,9 +299,8 @@
694 private:
695 std::unique_ptr<internal::ScopeBaseImpl> p;
696
697- friend class internal::ScopeLoader;
698+ friend class internal::RuntimeImpl;
699 friend class internal::ScopeObject;
700- friend class internal::RuntimeImpl;
701 /// @endcond
702 };
703
704@@ -287,13 +310,17 @@
705
706 /**
707 \brief The function called by the scopes run time to initialize the scope.
708-It must return a pointer to an instance derived from ScopeBase. The returned
709+It must return a pointer to an instance derived from `ScopeBase`. The returned
710 instance need not be heap-allocated, but must remain in scope until the
711 destroy function is called by the scopes run time.
712
713 If this function throws an exception, the destroy function will _not_ be called. If this function returns NULL,
714 the destroy function _will_ be called with NULL as its argument.
715
716+\note The only purpose of the create function is to return the an instance.
717+Do not do anything in the implementation that might block, and do
718+not attempt to call any methods on `ScopeBase` from the constructor.
719+
720 \return The pointer to the ScopeBase instance.
721 */
722 extern "C" unity::scopes::ScopeBase* UNITY_SCOPE_CREATE_FUNCTION();
723
724=== modified file 'include/unity/scopes/internal/DfltConfig.h.in'
725--- include/unity/scopes/internal/DfltConfig.h.in 2014-07-21 06:34:24 +0000
726+++ include/unity/scopes/internal/DfltConfig.h.in 2014-07-28 11:21:43 +0000
727@@ -39,6 +39,7 @@
728 static constexpr char const* DFLT_MIDDLEWARE_INI = DFLT_ZMQ_MIDDLEWARE_INI;
729 static constexpr char const* DFLT_SCOPE_INSTALL_DIR = "@CMAKE_INSTALL_PREFIX@/@LIB_INSTALL_PREFIX@/@UNITY_SCOPES_LIB@";
730 static constexpr char const* DFLT_OEM_INSTALL_DIR = "/custom/@LIB_INSTALL_PREFIX@/@UNITY_SCOPES_LIB@";
731+static constexpr char const* DFLT_CONFINEMENT_TYPE = "leaf-net";
732
733 static constexpr int DFLT_SS_HTTP_TIMEOUT = 20; // seconds
734 static constexpr int DFLT_SS_REG_REFRESH_RATE = 86400; // 24 hours as seconds
735
736=== modified file 'include/unity/scopes/internal/RuntimeImpl.h'
737--- include/unity/scopes/internal/RuntimeImpl.h 2014-06-24 03:05:19 +0000
738+++ include/unity/scopes/internal/RuntimeImpl.h 2014-07-28 11:21:43 +0000
739@@ -64,6 +64,7 @@
740 private:
741 RuntimeImpl(std::string const& scope_id, std::string const& configfile);
742 void waiter_thread(ThreadSafeQueue<std::future<void>>::SPtr const& queue) const noexcept;
743+ std::string find_cache_dir() const;
744
745 bool destroyed_;
746 std::string scope_id_;
747
748=== modified file 'include/unity/scopes/internal/ScopeBaseImpl.h'
749--- include/unity/scopes/internal/ScopeBaseImpl.h 2014-06-24 03:05:19 +0000
750+++ include/unity/scopes/internal/ScopeBaseImpl.h 2014-07-28 11:21:43 +0000
751@@ -19,9 +19,9 @@
752 #ifndef UNITY_SCOPES_INTERNAL_SCOPEBASEIMPL_H
753 #define UNITY_SCOPES_INTERNAL_SCOPEBASEIMPL_H
754
755+#include <unity/scopes/RegistryProxyFwd.h>
756 #include <unity/scopes/Variant.h>
757
758-#include <memory>
759 #include <mutex>
760 #include <string>
761
762@@ -39,17 +39,35 @@
763 class ScopeBaseImpl final
764 {
765 public:
766- ScopeBaseImpl() = default;
767+ ScopeBaseImpl();
768 ~ScopeBaseImpl() = default;
769- void set_scope_directory(std::string const &path);
770+
771+ void set_scope_directory(std::string const& path);
772 std::string scope_directory() const;
773+
774+ void set_cache_directory(std::string const& path);
775+ std::string cache_directory() const;
776+
777+ void set_registry(RegistryProxy const& registry);
778+ RegistryProxy registry() const;
779+
780 std::shared_ptr<unity::scopes::internal::SettingsDB> settings_db() const;
781 void set_settings_db(std::shared_ptr<unity::scopes::internal::SettingsDB> const& db);
782 unity::scopes::VariantMap settings() const;
783
784 private:
785 std::string scope_directory_;
786+ bool scope_dir_initialized_;
787+
788+ std::string cache_directory_;
789+ bool cache_dir_initialized_;
790+
791+ unity::scopes::RegistryProxy registry_;
792+ bool registry_initialized_;
793+
794 std::shared_ptr<unity::scopes::internal::SettingsDB> db_;
795+ bool settings_db_initialized_;
796+
797 mutable std::mutex mutex_;
798 };
799
800
801=== modified file 'include/unity/scopes/internal/ScopeConfig.h'
802--- include/unity/scopes/internal/ScopeConfig.h 2014-06-26 12:49:46 +0000
803+++ include/unity/scopes/internal/ScopeConfig.h 2014-07-28 11:21:43 +0000
804@@ -39,18 +39,18 @@
805 ScopeConfig(std::string const& configfile);
806 ~ScopeConfig();
807
808- bool overrideable() const; // Optional, returns false if not present
809- std::string display_name() const; // Mandatory, localizable
810- std::string description() const; // Mandatory, localizable
811- std::string author() const; // Mandatory
812- std::string art() const; // Optional, throws NotFoundException if not present
813- std::string icon() const; // Optional, throws NotFoundException if not present
814- std::string search_hint() const; // Optional, localizable, throws NotFoundException if not present
815- std::string hot_key() const; // Optional, throws NotFoundException if not present
816- bool invisible() const; // Optional, returns false if not present
817- bool location_data_needed() const; // Optional, returns false if not present
818- std::string scope_runner() const; // Optional, throws NotFoundException if not present
819- int idle_timeout() const; // Optional, returns default value if not present
820+ bool overrideable() const; // Optional, returns false if not present
821+ std::string display_name() const; // Mandatory, localizable
822+ std::string description() const; // Mandatory, localizable
823+ std::string author() const; // Mandatory
824+ std::string art() const; // Optional, throws NotFoundException if not present
825+ std::string icon() const; // Optional, throws NotFoundException if not present
826+ std::string search_hint() const; // Optional, localizable, throws NotFoundException if not present
827+ std::string hot_key() const; // Optional, throws NotFoundException if not present
828+ bool invisible() const; // Optional, returns false if not present
829+ bool location_data_needed() const; // Optional, returns false if not present
830+ std::string scope_runner() const; // Optional, throws NotFoundException if not present
831+ int idle_timeout() const; // Optional, returns default value if not present
832 ScopeMetadata::ResultsTtlType results_ttl_type() const; // Optional, returns none if not present
833
834 VariantMap appearance_attributes() const; // Optional, returns empty map if no attributes are present
835
836=== modified file 'include/unity/scopes/internal/ScopeLoader.h'
837--- include/unity/scopes/internal/ScopeLoader.h 2014-07-02 05:17:19 +0000
838+++ include/unity/scopes/internal/ScopeLoader.h 2014-07-28 11:21:43 +0000
839@@ -40,12 +40,8 @@
840 NONCOPYABLE(ScopeLoader);
841 UNITY_DEFINES_PTRS(ScopeLoader);
842
843- // Creates a ScopeLoader for a scope with the given ID, library, and settings dir. We pass in the registry proxy
844- // so we can pass it to the scope's start method.
845- static UPtr load(std::string const& scope_id,
846- std::string const& libpath,
847- std::string const& data_dir,
848- RegistryProxy const& registry);
849+ // Creates a ScopeLoader for a scope with the given ID and library.
850+ static UPtr load(std::string const& scope_id, std::string const& libpath);
851
852 // unload() explicitly finalizes the scope. This is called by the destructor too, but calling it explicity
853 // allows the caller to receive any exceptions that may have been produced by the scope thread.
854@@ -67,14 +63,10 @@
855 ~ScopeLoader();
856
857 private:
858- ScopeLoader(std::string const& scope_id,
859- std::string const& libpath,
860- std::string const& data_dir,
861- RegistryProxy const& registry);
862+ ScopeLoader(std::string const& scope_id, std::string const& path);
863
864 std::string scope_id_;
865 unity::scopes::internal::DynamicLoader::UPtr dyn_loader_;
866- unity::scopes::RegistryProxy registry_;
867 std::exception_ptr exception_;
868
869 std::thread scope_thread_;
870
871=== modified file 'include/unity/scopes/testing/TypedScopeFixture.h'
872--- include/unity/scopes/testing/TypedScopeFixture.h 2014-06-17 09:27:49 +0000
873+++ include/unity/scopes/testing/TypedScopeFixture.h 2014-07-28 11:21:43 +0000
874@@ -46,9 +46,9 @@
875 return "unknown";
876 }
877
878- inline static std::shared_ptr<Scope> construct()
879+ inline static std::shared_ptr<Scope> construct(RegistryProxy const& r)
880 {
881- return std::make_shared<Scope>();
882+ return std::make_shared<Scope>(r);
883 }
884 };
885
886@@ -57,14 +57,14 @@
887 {
888 public:
889 TypedScopeFixture()
890- : scope(ScopeTraits<Scope>::construct()),
891- registry_proxy(&registry, [](unity::scopes::Registry*) {})
892+ : registry_proxy(&registry, [](unity::scopes::Registry*) {})
893+ , scope(ScopeTraits<Scope>::construct(registry_proxy))
894 {
895 }
896
897 void SetUp()
898 {
899- EXPECT_NO_THROW(scope->start(ScopeTraits<Scope>::name(), registry_proxy));
900+ EXPECT_NO_THROW(scope->start(ScopeTraits<Scope>::name()));
901 EXPECT_NO_THROW(scope->run());
902 }
903
904@@ -74,9 +74,9 @@
905 }
906
907 protected:
908- std::shared_ptr<Scope> scope;
909 unity::scopes::testing::MockRegistry registry;
910 unity::scopes::RegistryProxy registry_proxy;
911+ std::shared_ptr<Scope> scope;
912 };
913
914 /// @endcond
915
916=== modified file 'scoperegistry/scoperegistry.cpp'
917--- scoperegistry/scoperegistry.cpp 2014-07-22 10:48:57 +0000
918+++ scoperegistry/scoperegistry.cpp 2014-07-28 11:21:43 +0000
919@@ -35,7 +35,6 @@
920
921 #include <boost/algorithm/string.hpp>
922 #include <boost/filesystem/operations.hpp>
923-#include <boost/filesystem/path.hpp>
924
925 #include <algorithm>
926 #include <cassert>
927@@ -43,11 +42,8 @@
928 #include <iostream>
929 #include <map>
930 #include <set>
931-#include <sstream>
932-
933-#include <libgen.h>
934-#include <unistd.h>
935-
936+
937+#include <sys/stat.h> // TODO: remove this once hack for creating data root dir is removed
938
939 using namespace scoperegistry;
940 using namespace std;
941@@ -464,11 +460,23 @@
942 SignalThreadWrapper signal_handler_wrapper;
943
944 // And finally creating our runtime.
945- RuntimeConfig rt_config(config_file);
946- RuntimeImpl::UPtr runtime = RuntimeImpl::create(rt_config.registry_identity(), config_file);
947-
948- string identity = runtime->registry_identity();
949- string ss_reg_id = runtime->ss_registry_identity();
950+ string identity;
951+ string ss_reg_id;
952+ RuntimeImpl::UPtr runtime;
953+ {
954+ RuntimeConfig rt_config(config_file);
955+ runtime = RuntimeImpl::create(rt_config.registry_identity(), config_file);
956+
957+ identity = runtime->registry_identity();
958+ ss_reg_id = runtime->ss_registry_identity();
959+
960+ // TODO: HACK: We create the root of the data directory for confined scopes,
961+ // in case the scope is confined and the dir doesn't exist
962+ // yet. This really should be done by the click-installation but,
963+ // prior to RTM, we don't rely on that.
964+ string data_root = rt_config.data_directory() + "/leaf-net";
965+ ::mkdir(data_root.c_str(), 0700);
966+ } // Release memory for config parser
967
968 // Collect the registry config data.
969
970@@ -539,9 +547,8 @@
971 }
972
973 // Configure watches for scope install directories
974- ScopesWatcher local_scopes_watcher(registry,
975- [registry, &middleware, &scoperunner_path, &config_file, process_timeout]
976- (pair<string, string> const& scope)
977+ auto local_watch_lambda = [registry, &middleware, &scoperunner_path, &config_file, process_timeout]
978+ (pair<string, string> const& scope)
979 {
980 try
981 {
982@@ -551,13 +558,13 @@
983 {
984 error("ignoring installed scope \"" + scope.first + "\": cannot create metadata: " + e.what());
985 }
986- });
987+ };
988+ ScopesWatcher local_scopes_watcher(registry, local_watch_lambda);
989 local_scopes_watcher.add_install_dir(scope_installdir);
990 local_scopes_watcher.add_install_dir(oem_installdir);
991
992- ScopesWatcher click_scopes_watcher(registry,
993- [registry, &middleware, &scoperunner_path, &config_file, process_timeout]
994- (pair<string, string> const& scope)
995+ auto click_watch_lambda = [registry, &middleware, &scoperunner_path, &config_file, process_timeout]
996+ (pair<string, string> const& scope)
997 {
998 try
999 {
1000@@ -567,7 +574,8 @@
1001 {
1002 error("ignoring installed scope \"" + scope.first + "\": cannot create metadata: " + e.what());
1003 }
1004- });
1005+ };
1006+ ScopesWatcher click_scopes_watcher(registry, click_watch_lambda);
1007 click_scopes_watcher.add_install_dir(click_installdir);
1008
1009 // Let's add the registry's state receiver to the middleware so that scopes can inform
1010
1011=== modified file 'scoperunner/scoperunner.cpp'
1012--- scoperunner/scoperunner.cpp 2014-07-21 15:37:57 +0000
1013+++ scoperunner/scoperunner.cpp 2014-07-28 11:21:43 +0000
1014@@ -38,8 +38,6 @@
1015 #include <unordered_map>
1016 #include <vector>
1017
1018-#include <libgen.h>
1019-
1020 using namespace std;
1021 using namespace unity::scopes;
1022 using namespace unity::scopes::internal;
1023@@ -59,7 +57,7 @@
1024 // Run the scope specified by the config_file in a separate thread and wait for the thread to finish.
1025 // Return exit status for main to use.
1026
1027-int run_scope(std::string const& runtime_config, std::string const& scope_configfile)
1028+int run_scope(std::string const& runtime_config, std::string const& scope_config)
1029 {
1030 auto trap = core::posix::trap_signals_for_all_subsequent_threads(
1031 {
1032@@ -69,16 +67,11 @@
1033
1034 std::thread trap_worker([trap]() { trap->run(); });
1035
1036- // Retrieve the registry middleware and create a proxy to its state receiver
1037- RuntimeConfig rt_config(runtime_config);
1038- RegistryConfig reg_conf(rt_config.registry_identity(), rt_config.registry_configfile());
1039- auto reg_runtime = RuntimeImpl::create(rt_config.registry_identity(), runtime_config);
1040- auto reg_mw = reg_runtime->factory()->find(reg_runtime->registry_identity(), reg_conf.mw_kind());
1041- auto reg_state_receiver = reg_mw->create_state_receiver_proxy("StateReceiver");
1042-
1043- filesystem::path scope_config_path(scope_configfile);
1044+ // Figure out what the scope ID is from the name of the scope config file.
1045+ filesystem::path scope_config_path(scope_config);
1046 string lib_dir = scope_config_path.parent_path().native();
1047 string scope_id = scope_config_path.stem().native();
1048+
1049 if (!lib_dir.empty())
1050 {
1051 lib_dir += '/';
1052@@ -87,11 +80,6 @@
1053 int exit_status = 1;
1054 try
1055 {
1056- // Instantiate the run time, create the middleware, load the scope from its
1057- // shared library, and call the scope's start() method.
1058- auto rt = RuntimeImpl::create(scope_id, runtime_config);
1059- auto mw = rt->factory()->create(scope_id, reg_conf.mw_kind(), reg_conf.mw_configfile());
1060-
1061 // For a scope_id "Fred", we look for the library as "libFred.so", "Fred.so", and "scope.so".
1062 vector<string> libs;
1063 libs.push_back(lib_dir + "lib" + scope_id + ".so");
1064@@ -104,7 +92,7 @@
1065 {
1066 try
1067 {
1068- loader = ScopeLoader::load(scope_id, lib, rt_config.data_directory(), rt->registry());
1069+ loader = ScopeLoader::load(scope_id, lib);
1070 }
1071 catch (unity::ResourceException& e)
1072 {
1073@@ -123,35 +111,24 @@
1074 e.remember(ep);
1075 throw e;
1076 }
1077- loader->start();
1078-
1079- // Give a thread to the scope to do with as it likes. If the scope doesn't want to use it and
1080- // immediately returns from run(), that's fine.
1081- auto run_future = std::async(launch::async, [loader] { loader->scope_base()->run(); });
1082-
1083- // Create a servant for the scope and register the servant.
1084- ScopeConfig scope_config(scope_configfile);
1085- auto scope = unique_ptr<ScopeObject>(new ScopeObject(rt.get(), loader->scope_base()));
1086- auto proxy = mw->add_scope_object(scope_id, move(scope), scope_config.idle_timeout() * 1000);
1087-
1088- trap->signal_raised().connect([mw](core::posix::Signal)
1089+
1090+ static mutex rt_mutex;
1091+ RuntimeImpl::SPtr rt;
1092+
1093+ // Signal handler to shut down the run time on receipt of a signal.
1094+ trap->signal_raised().connect([rt](core::posix::Signal)
1095 {
1096- mw->stop();
1097+ lock_guard<mutex> lock(rt_mutex);
1098+ rt->destroy();
1099 });
1100
1101- // Inform the registry that this scope is now ready to process requests
1102- reg_state_receiver->push_state(scope_id, StateReceiverObject::State::ScopeReady);
1103-
1104- mw->wait_for_shutdown();
1105-
1106- // Inform the registry that this scope is shutting down
1107- reg_state_receiver->push_state(scope_id, StateReceiverObject::State::ScopeStopping);
1108-
1109- loader->stop();
1110-
1111- // Collect exit status from the run thread. If this throws, the ScopeLoader
1112- // destructor will still call stop() on the scope.
1113- run_future.get();
1114+ // Instantiate the run time and run the scope.
1115+ {
1116+ lock_guard<mutex> lock(rt_mutex);
1117+ rt = RuntimeImpl::create(scope_id, runtime_config);
1118+ }
1119+
1120+ rt->run_scope(loader->scope_base(), runtime_config, scope_config);
1121
1122 exit_status = 0;
1123 }
1124
1125=== modified file 'smartscopesproxy/smartscopesproxy.cpp'
1126--- smartscopesproxy/smartscopesproxy.cpp 2014-06-30 07:20:30 +0000
1127+++ smartscopesproxy/smartscopesproxy.cpp 2014-07-28 11:21:43 +0000
1128@@ -27,9 +27,10 @@
1129 #include <core/posix/signal.h>
1130
1131 #include <cassert>
1132+#include <iostream>
1133+
1134+#include <libgen.h>
1135 #include <signal.h>
1136-#include <libgen.h>
1137-#include <iostream>
1138 #include <unistd.h>
1139
1140 using namespace unity::scopes;
1141
1142=== modified file 'src/scopes/ScopeBase.cpp'
1143--- src/scopes/ScopeBase.cpp 2014-06-24 11:11:11 +0000
1144+++ src/scopes/ScopeBase.cpp 2014-07-28 11:21:43 +0000
1145@@ -18,6 +18,7 @@
1146
1147 #include <unity/scopes/ScopeBase.h>
1148 #include <unity/scopes/ActivationQueryBase.h>
1149+#include <unity/scopes/Registry.h>
1150 #include <unity/scopes/internal/ScopeBaseImpl.h>
1151
1152 namespace unity
1153@@ -39,7 +40,7 @@
1154
1155 //! @endcond
1156
1157-void ScopeBase::start(std::string const&, RegistryProxy const&)
1158+void ScopeBase::start(std::string const&)
1159 {
1160 // Intentionally empty: default "do nothing" implementation.
1161 }
1162@@ -76,6 +77,16 @@
1163 return p->scope_directory();
1164 }
1165
1166+std::string ScopeBase::cache_directory() const
1167+{
1168+ return p->cache_directory();
1169+}
1170+
1171+RegistryProxy ScopeBase::registry() const
1172+{
1173+ return p->registry();
1174+}
1175+
1176 unity::scopes::VariantMap ScopeBase::settings() const
1177 {
1178 return p->settings();
1179
1180=== modified file 'src/scopes/internal/RegistryConfig.cpp'
1181--- src/scopes/internal/RegistryConfig.cpp 2014-05-09 06:36:46 +0000
1182+++ src/scopes/internal/RegistryConfig.cpp 2014-07-28 11:21:43 +0000
1183@@ -78,7 +78,7 @@
1184 throw_ex("Illegal value (" + to_string(process_timeout_) + ") for " + process_timeout_key + ": value must be 10-5000 ms");
1185 }
1186
1187- const KnownEntries known_entries = {
1188+ KnownEntries const known_entries = {
1189 { registry_config_group,
1190 {
1191 mw_kind_key,
1192
1193=== modified file 'src/scopes/internal/RuntimeConfig.cpp'
1194--- src/scopes/internal/RuntimeConfig.cpp 2014-07-07 05:22:26 +0000
1195+++ src/scopes/internal/RuntimeConfig.cpp 2014-07-28 11:21:43 +0000
1196@@ -104,7 +104,7 @@
1197 }
1198 }
1199
1200- const KnownEntries known_entries = {
1201+ KnownEntries const known_entries = {
1202 { runtime_config_group,
1203 {
1204 registry_identity_key,
1205
1206=== modified file 'src/scopes/internal/RuntimeImpl.cpp'
1207--- src/scopes/internal/RuntimeImpl.cpp 2014-07-21 15:37:57 +0000
1208+++ src/scopes/internal/RuntimeImpl.cpp 2014-07-28 11:21:43 +0000
1209@@ -35,8 +35,7 @@
1210
1211 #include <boost/filesystem.hpp>
1212
1213-#include <signal.h>
1214-#include <libgen.h>
1215+#include <boost/filesystem.hpp>
1216
1217 #include <cassert>
1218 #include <cstring>
1219@@ -301,27 +300,37 @@
1220 auto mw = factory()->create(scope_id_, reg_conf.mw_kind(), reg_conf.mw_configfile());
1221
1222 {
1223- boost::filesystem::path inip(scope_ini_file);
1224- boost::filesystem::path scope_dir(inip.parent_path());
1225- scope_base->p->set_scope_directory(inip.native());
1226+ boost::filesystem::path dir = boost::filesystem::path(scope_ini_file).parent_path();
1227+ scope_base->p->set_scope_directory(dir.native());
1228 }
1229
1230- // Try to open the scope settings database, if any.
1231- string settings_dir = data_dir_ + "/" + scope_id_;
1232- string scope_dir = scope_base->scope_directory();
1233- string settings_db = settings_dir + "/settings.db";
1234- string settings_schema = scope_dir + "/" + scope_id_ + "-settings.ini";
1235- if (boost::filesystem::exists(settings_schema))
1236 {
1237- // Make sure the settings directories exist. (No permission for group and others; data might be sensitive.)
1238- ::mkdir(data_dir_.c_str(), 0700);
1239- ::mkdir(settings_dir.c_str(), 0700);
1240+ // Try to open the scope settings database, if any.
1241+ string settings_dir = data_dir_ + "/" + scope_id_;
1242+ string scope_dir = scope_base->scope_directory();
1243+ string settings_db = settings_dir + "/settings.db";
1244+ string settings_schema = scope_dir + "/" + scope_id_ + "-settings.ini";
1245+ if (boost::filesystem::exists(settings_schema))
1246+ {
1247+ // Make sure the settings directories exist. (No permission for group and others; data might be sensitive.)
1248+ ::mkdir(data_dir_.c_str(), 0700);
1249+ ::mkdir(settings_dir.c_str(), 0700);
1250
1251- shared_ptr<SettingsDB> db(SettingsDB::create_from_ini_file(settings_db, settings_schema));
1252- scope_base->p->set_settings_db(db);
1253+ shared_ptr<SettingsDB> db(SettingsDB::create_from_ini_file(settings_db, settings_schema));
1254+ scope_base->p->set_settings_db(db);
1255+ }
1256+ else
1257+ {
1258+ scope_base->p->set_settings_db(nullptr);
1259+ }
1260 }
1261
1262- scope_base->start(scope_id_, registry());
1263+ scope_base->p->set_registry(registry_);
1264+
1265+ scope_base->p->set_cache_directory(find_cache_dir());
1266+
1267+ scope_base->start(scope_id_);
1268+
1269 // Ensure the scope gets stopped.
1270 unique_ptr<ScopeBase, void(*)(ScopeBase*)> cleanup_scope(scope_base, [](ScopeBase *scope_base) { scope_base->stop(); });
1271
1272@@ -332,15 +341,13 @@
1273
1274 // Create a servant for the scope and register the servant.
1275 auto scope = unique_ptr<internal::ScopeObject>(new internal::ScopeObject(this, scope_base));
1276+ int idle_timeout_ms = 0;
1277 if (!scope_ini_file.empty())
1278 {
1279 ScopeConfig scope_config(scope_ini_file);
1280- mw->add_scope_object(scope_id_, move(scope), scope_config.idle_timeout() * 1000);
1281- }
1282- else
1283- {
1284- mw->add_scope_object(scope_id_, move(scope));
1285- }
1286+ idle_timeout_ms = scope_config.idle_timeout() * 1000;
1287+ }
1288+ mw->add_scope_object(scope_id_, move(scope), idle_timeout_ms);
1289
1290 // Inform the registry that this scope is now ready to process requests
1291 reg_state_receiver->push_state(scope_id_, StateReceiverObject::State::ScopeReady);
1292@@ -383,6 +390,42 @@
1293 }
1294 }
1295
1296+string RuntimeImpl::find_cache_dir() const
1297+{
1298+ // TODO: HACK: Until we get a fancier Apparmor query API, we try
1299+ // to create the scope cache dir and figure out whether
1300+ // whether we are confined or unconfined. We first try to
1301+ // create <data_dir>/unconfined and <data_dir>/unconfined/<scope_id_>,
1302+ // in case they don't exist. Then we try to create a file in
1303+ // <data_dir>unconfined/<scope_id_>. If that works, we unlink
1304+ // the file again and can conclude that the scope is unconfined.
1305+ // Otherwise, the scope must be confined, in which case
1306+ // we create <data_dir>/leaf-net and <data_dir>/leaf-net/<scope_id_>.
1307+
1308+ string cache_dir = data_dir_ + "/unconfined/" + scope_id_;
1309+
1310+ // The following two mkdir() calls will fail if the scope is confined or
1311+ // the directories exist already.
1312+ ::mkdir((data_dir_ + "/unconfined").c_str(), 0700);
1313+ ::mkdir(cache_dir.c_str(), 0700);
1314+ string tmp = cache_dir + "/.unconfined_scope_XXXXXX";
1315+ int fd = mkstemp(const_cast<char*>(tmp.c_str())); // mkstemp() modifies its argument
1316+ if (fd != -1)
1317+ {
1318+ // If mkstemp succeeded, the scope is unconfined.
1319+ assert(::unlink(tmp.c_str()) == 0);
1320+ ::close(fd);
1321+ }
1322+ else
1323+ {
1324+ // mkstemp() failed, the scope must be confined.
1325+ ::mkdir((data_dir_ + "/leaf-net").c_str(), 0700);
1326+ ::mkdir(cache_dir.c_str(), 0700);
1327+ cache_dir = data_dir_ + "/leaf-net/" + scope_id_;
1328+ }
1329+ return cache_dir;
1330+}
1331+
1332 } // namespace internal
1333
1334 } // namespace scopes
1335
1336=== modified file 'src/scopes/internal/ScopeBaseImpl.cpp'
1337--- src/scopes/internal/ScopeBaseImpl.cpp 2014-06-24 03:05:19 +0000
1338+++ src/scopes/internal/ScopeBaseImpl.cpp 2014-07-28 11:21:43 +0000
1339@@ -17,8 +17,12 @@
1340 */
1341
1342 #include <unity/scopes/internal/ScopeBaseImpl.h>
1343+
1344+#include <unity/UnityExceptions.h>
1345 #include <unity/scopes/internal/SettingsDB.h>
1346+#include <unity/scopes/ScopeExceptions.h>
1347
1348+using namespace unity;
1349 using namespace unity::scopes;
1350 using namespace std;
1351
1352@@ -31,21 +35,78 @@
1353 namespace internal
1354 {
1355
1356-void ScopeBaseImpl::set_scope_directory(std::string const &path)
1357+ScopeBaseImpl::ScopeBaseImpl()
1358+ : scope_dir_initialized_(false)
1359+ , cache_dir_initialized_(false)
1360+ , registry_initialized_(false)
1361+ , settings_db_initialized_(false)
1362+{
1363+}
1364+
1365+void ScopeBaseImpl::set_scope_directory(std::string const& path)
1366 {
1367 lock_guard<mutex> lock(mutex_);
1368 scope_directory_ = path;
1369+ scope_dir_initialized_ = true;
1370 }
1371
1372 std::string ScopeBaseImpl::scope_directory() const
1373 {
1374 lock_guard<mutex> lock(mutex_);
1375+ if (!scope_dir_initialized_)
1376+ {
1377+ throw LogicException("ScopeBase::scope_directory() cannot be called from constructor");
1378+ }
1379+ // scope_dir_ is never empty, except for tests, so we don't throw if it is empty here.
1380 return scope_directory_;
1381 }
1382
1383+void ScopeBaseImpl::set_cache_directory(std::string const& path)
1384+{
1385+ lock_guard<mutex> lock(mutex_);
1386+ cache_directory_ = path;
1387+ cache_dir_initialized_ = true;
1388+}
1389+
1390+std::string ScopeBaseImpl::cache_directory() const
1391+{
1392+ lock_guard<mutex> lock(mutex_);
1393+ if (!cache_dir_initialized_)
1394+ {
1395+ throw LogicException("ScopeBase::cache_directory() cannot be called from constructor");
1396+ }
1397+ if (cache_directory_.empty())
1398+ {
1399+ throw ConfigException("ScopeBase::cache_directory(): no cache directory available");
1400+ }
1401+ return cache_directory_;
1402+}
1403+
1404+void ScopeBaseImpl::set_registry(RegistryProxy const& registry)
1405+{
1406+ lock_guard<mutex> lock(mutex_);
1407+ registry_ = registry;
1408+ registry_initialized_ = true;
1409+}
1410+
1411+RegistryProxy ScopeBaseImpl::registry() const
1412+{
1413+ lock_guard<mutex> lock(mutex_);
1414+ if (!registry_initialized_)
1415+ {
1416+ throw LogicException("ScopeBase::registry() cannot be called from constructor");
1417+ }
1418+ // registry_ can be a null proxy.
1419+ return registry_;
1420+}
1421+
1422 SettingsDB::SPtr ScopeBaseImpl::settings_db() const
1423 {
1424 lock_guard<mutex> lock(mutex_);
1425+ if (!settings_db_initialized_)
1426+ {
1427+ throw LogicException("ScopeBase::settings_db() cannot be called from constructor");
1428+ }
1429 return db_;
1430 }
1431
1432@@ -53,11 +114,16 @@
1433 {
1434 lock_guard<mutex> lock(mutex_);
1435 db_ = db;
1436+ settings_db_initialized_ = true;
1437 }
1438
1439 VariantMap ScopeBaseImpl::settings() const
1440 {
1441 lock_guard<mutex> lock(mutex_);
1442+ if (!settings_db_initialized_)
1443+ {
1444+ throw LogicException("ScopeBase::settings_db() cannot be called from constructor");
1445+ }
1446 return db_ ? db_->settings() : VariantMap();
1447 }
1448
1449
1450=== modified file 'src/scopes/internal/ScopeConfig.cpp'
1451--- src/scopes/internal/ScopeConfig.cpp 2014-07-24 13:08:48 +0000
1452+++ src/scopes/internal/ScopeConfig.cpp 2014-07-28 11:21:43 +0000
1453@@ -54,7 +54,7 @@
1454 const string location_data_needed_key = "LocationDataNeeded";
1455 const string scoperunner_key = "ScopeRunner";
1456 const string idle_timeout_key = "IdleTimeout";
1457- const string results_ttl_str = "ResultsTtlType";
1458+ const string results_ttl_key = "ResultsTtlType";
1459
1460 const string scope_appearance_group = "Appearance";
1461 const string fg_color_key = "ForegroundColor";
1462@@ -141,8 +141,8 @@
1463 // custom scope runner executable is optional
1464 try
1465 {
1466- string key = parser()->get_string(scope_config_group, scoperunner_key);
1467- scope_runner_.reset(new string(key));
1468+ string scope_runner = parser()->get_string(scope_config_group, scoperunner_key);
1469+ scope_runner_.reset(new string(scope_runner));
1470 }
1471 catch (LogicException const&)
1472 {
1473@@ -162,7 +162,7 @@
1474 results_ttl_type_ = ScopeMetadata::ResultsTtlType::None;
1475 try
1476 {
1477- string orig = parser()->get_string(scope_config_group, results_ttl_str);
1478+ string orig = parser()->get_string(scope_config_group, results_ttl_key);
1479 string ttl = orig;
1480 to_lower(ttl);
1481 if (ttl.empty() || ttl == "none")
1482@@ -182,7 +182,7 @@
1483 }
1484 else
1485 {
1486- throw_ex("Illegal value (" + orig + ") for " + results_ttl_str);
1487+ throw_ex("Illegal value (\"" + orig + "\") for " + results_ttl_key);
1488 }
1489 }
1490 catch (LogicException const&)
1491@@ -201,7 +201,7 @@
1492 {
1493 }
1494
1495- const KnownEntries known_entries = {
1496+ KnownEntries const known_entries = {
1497 { scope_config_group,
1498 {
1499 overrideable_key,
1500@@ -216,7 +216,7 @@
1501 location_data_needed_key,
1502 scoperunner_key,
1503 idle_timeout_key,
1504- results_ttl_str
1505+ results_ttl_key
1506 }
1507 },
1508 { scope_appearance_group,
1509
1510=== modified file 'src/scopes/internal/ScopeLoader.cpp'
1511--- src/scopes/internal/ScopeLoader.cpp 2014-07-02 05:17:19 +0000
1512+++ src/scopes/internal/ScopeLoader.cpp 2014-07-28 11:21:43 +0000
1513@@ -23,11 +23,7 @@
1514 #include <unity/scopes/Version.h>
1515 #include <unity/UnityExceptions.h>
1516
1517-#include <boost/filesystem.hpp>
1518-
1519 #include <cassert>
1520-#include <libgen.h>
1521-#include <sys/stat.h>
1522
1523 using namespace std;
1524 using namespace unity::scopes;
1525@@ -42,13 +38,9 @@
1526 namespace internal
1527 {
1528
1529-ScopeLoader::ScopeLoader(string const& scope_id,
1530- string const& libpath,
1531- string const& data_dir,
1532- RegistryProxy const& registry) :
1533+ScopeLoader::ScopeLoader(string const& scope_id, string const& libpath) :
1534 scope_id_(scope_id),
1535 dyn_loader_(DynamicLoader::create(libpath, DynamicLoader::Binding::now, DynamicLoader::Unload::noclose)),
1536- registry_(registry),
1537 scope_base_(nullptr, reinterpret_cast<DestroyFunction>(dyn_loader_->find_function(UNITY_SCOPE_DESTROY_SYMSTR))),
1538 scope_state_(ScopeState::Stopped)
1539 {
1540@@ -62,26 +54,6 @@
1541 {
1542 throw unity::ResourceException("Scope " + scope_id_ + " returned nullptr from " + UNITY_SCOPE_CREATE_SYMSTR);
1543 }
1544-
1545- {
1546- boost::filesystem::path libp(libpath);
1547- boost::filesystem::path scope_dir(libp.parent_path());
1548- scope_base_->p->set_scope_directory(scope_dir.native());
1549- }
1550-
1551- string settings_dir = data_dir + "/" + scope_id;
1552- string scope_dir = scope_base_->scope_directory();
1553- string settings_db = settings_dir + "/settings.db";
1554- string settings_schema = scope_dir + "/" + scope_id + "-settings.ini";
1555- if (boost::filesystem::exists(settings_schema))
1556- {
1557- // Make sure the settings directories exist. (No permission for group and others; data might be sensitive.)
1558- ::mkdir(data_dir.c_str(), 0700);
1559- ::mkdir(settings_dir.c_str(), 0700);
1560-
1561- shared_ptr<SettingsDB> db(SettingsDB::create_from_ini_file(settings_db, settings_schema));
1562- scope_base_->p->set_settings_db(db);
1563- }
1564 }
1565
1566 ScopeLoader::~ScopeLoader()
1567@@ -95,12 +67,9 @@
1568 }
1569 }
1570
1571-ScopeLoader::UPtr ScopeLoader::load(string const& scope_id,
1572- string const& libpath,
1573- string const& data_dir,
1574- RegistryProxy const& registry)
1575+ScopeLoader::UPtr ScopeLoader::load(string const& scope_id, string const& libpath)
1576 {
1577- return UPtr(new ScopeLoader(scope_id, libpath, data_dir, registry));
1578+ return UPtr(new ScopeLoader(scope_id, libpath));
1579 }
1580
1581 void ScopeLoader::unload()
1582@@ -142,7 +111,7 @@
1583
1584 try
1585 {
1586- scope_base_->start(scope_id_, registry_);
1587+ scope_base_->start(scope_id_);
1588 }
1589 catch (...)
1590 {
1591
1592=== modified file 'src/scopes/internal/zmq_middleware/ZmqConfig.cpp'
1593--- src/scopes/internal/zmq_middleware/ZmqConfig.cpp 2014-07-22 04:01:45 +0000
1594+++ src/scopes/internal/zmq_middleware/ZmqConfig.cpp 2014-07-28 11:21:43 +0000
1595@@ -88,7 +88,7 @@
1596 registry_endpoint_dir_ = get_optional_string(zmq_config_group, registry_endpoint_dir_key);
1597 ss_registry_endpoint_dir_ = get_optional_string(zmq_config_group, ss_registry_endpoint_dir_key);
1598
1599- const KnownEntries known_entries = {
1600+ KnownEntries const known_entries = {
1601 { zmq_config_group,
1602 {
1603 endpoint_dir_key,
1604
1605=== modified file 'test/CMakeLists.txt'
1606--- test/CMakeLists.txt 2014-07-07 23:53:36 +0000
1607+++ test/CMakeLists.txt 2014-07-28 11:21:43 +0000
1608@@ -4,3 +4,4 @@
1609 endif()
1610 add_subdirectory(copyright)
1611 add_subdirectory(whitespace)
1612+add_subdirectory(autopkg)
1613
1614=== added directory 'test/autopkg'
1615=== added file 'test/autopkg/CMakeLists.txt'
1616--- test/autopkg/CMakeLists.txt 1970-01-01 00:00:00 +0000
1617+++ test/autopkg/CMakeLists.txt 2014-07-28 11:21:43 +0000
1618@@ -0,0 +1,4 @@
1619+add_executable(scopetest ${CMAKE_SOURCE_DIR}/debian/tests/scopetest.cpp)
1620+target_link_libraries(scopetest ${UNITY_SCOPES_LIB} ${OTHER_LIBS})
1621+
1622+add_test(autopkg-scopetest scopetest)
1623
1624=== modified file 'test/gtest/scopes/Activation/TestScope.h'
1625--- test/gtest/scopes/Activation/TestScope.h 2014-06-17 11:20:48 +0000
1626+++ test/gtest/scopes/Activation/TestScope.h 2014-07-28 11:21:43 +0000
1627@@ -98,7 +98,7 @@
1628 class TestScope : public ScopeBase
1629 {
1630 public:
1631- virtual void start(std::string const&, RegistryProxy const &) override {}
1632+ virtual void start(std::string const&) override {}
1633
1634 virtual void stop() override {}
1635
1636
1637=== modified file 'test/gtest/scopes/IdleShutdown/SlowSearchScope.cpp'
1638--- test/gtest/scopes/IdleShutdown/SlowSearchScope.cpp 2014-06-17 11:20:48 +0000
1639+++ test/gtest/scopes/IdleShutdown/SlowSearchScope.cpp 2014-07-28 11:21:43 +0000
1640@@ -50,7 +50,7 @@
1641
1642 } // namespace
1643
1644-void SlowSearchScope::start(string const&, RegistryProxy const &)
1645+void SlowSearchScope::start(string const&)
1646 {
1647 }
1648
1649
1650=== modified file 'test/gtest/scopes/IdleShutdown/SlowSearchScope.h'
1651--- test/gtest/scopes/IdleShutdown/SlowSearchScope.h 2014-06-17 09:27:49 +0000
1652+++ test/gtest/scopes/IdleShutdown/SlowSearchScope.h 2014-07-28 11:21:43 +0000
1653@@ -27,7 +27,7 @@
1654 class SlowSearchScope : public ScopeBase
1655 {
1656 public:
1657- virtual void start(string const&, RegistryProxy const &) override;
1658+ virtual void start(string const&) override;
1659
1660 virtual void stop() override;
1661
1662
1663=== modified file 'test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.cpp'
1664--- test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.cpp 2014-06-17 11:20:48 +0000
1665+++ test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.cpp 2014-07-28 11:21:43 +0000
1666@@ -64,7 +64,7 @@
1667 class MyScope : public ScopeBase
1668 {
1669 public:
1670- virtual void start(string const&, RegistryProxy const&) override {}
1671+ virtual void start(string const&) override {}
1672
1673 virtual void stop() override {}
1674
1675
1676=== modified file 'test/gtest/scopes/Registry/scopes/testscopeB/testscopeB.cpp'
1677--- test/gtest/scopes/Registry/scopes/testscopeB/testscopeB.cpp 2014-06-17 11:20:48 +0000
1678+++ test/gtest/scopes/Registry/scopes/testscopeB/testscopeB.cpp 2014-07-28 11:21:43 +0000
1679@@ -77,7 +77,7 @@
1680 class MyScope : public ScopeBase
1681 {
1682 public:
1683- virtual void start(string const&, RegistryProxy const&) override {}
1684+ virtual void start(string const&) override {}
1685
1686 virtual void stop() override {}
1687
1688
1689=== modified file 'test/gtest/scopes/Runtime/PusherScope.h'
1690--- test/gtest/scopes/Runtime/PusherScope.h 2014-07-24 13:51:38 +0000
1691+++ test/gtest/scopes/Runtime/PusherScope.h 2014-07-28 11:21:43 +0000
1692@@ -21,14 +21,13 @@
1693
1694 #include <unity/scopes/ScopeBase.h>
1695
1696-using namespace std;
1697-using namespace unity::scopes;
1698-
1699-class PusherScope : public ScopeBase
1700+class PusherScope : public unity::scopes::ScopeBase
1701 {
1702 public:
1703- virtual SearchQueryBase::UPtr search(CannedQuery const&, SearchMetadata const&) override;
1704- virtual PreviewQueryBase::UPtr preview(Result const& result, ActionMetadata const& metadata) override;
1705+ virtual unity::scopes::SearchQueryBase::UPtr search(unity::scopes::CannedQuery const&,
1706+ unity::scopes::SearchMetadata const&) override;
1707+ virtual unity::scopes::PreviewQueryBase::UPtr preview(unity::scopes::Result const&,
1708+ unity::scopes::ActionMetadata const&) override;
1709 };
1710
1711 #endif
1712
1713=== modified file 'test/gtest/scopes/Runtime/SlowCreateScope.h'
1714--- test/gtest/scopes/Runtime/SlowCreateScope.h 2014-07-24 13:51:38 +0000
1715+++ test/gtest/scopes/Runtime/SlowCreateScope.h 2014-07-28 11:21:43 +0000
1716@@ -21,14 +21,13 @@
1717
1718 #include <unity/scopes/ScopeBase.h>
1719
1720-using namespace std;
1721-using namespace unity::scopes;
1722-
1723-class SlowCreateScope : public ScopeBase
1724+class SlowCreateScope : public unity::scopes::ScopeBase
1725 {
1726 public:
1727- virtual SearchQueryBase::UPtr search(CannedQuery const&, SearchMetadata const&) override;
1728- virtual PreviewQueryBase::UPtr preview(Result const&, ActionMetadata const&) override;
1729+ virtual unity::scopes::SearchQueryBase::UPtr search(unity::scopes::CannedQuery const&,
1730+ unity::scopes::SearchMetadata const&) override;
1731+ virtual unity::scopes::PreviewQueryBase::UPtr preview(unity::scopes::Result const&,
1732+ unity::scopes::ActionMetadata const&) override;
1733 };
1734
1735 #endif
1736
1737=== modified file 'test/gtest/scopes/ScopeBase/ScopeBase_test.cpp'
1738--- test/gtest/scopes/ScopeBase/ScopeBase_test.cpp 2014-07-07 23:53:36 +0000
1739+++ test/gtest/scopes/ScopeBase/ScopeBase_test.cpp 2014-07-28 11:21:43 +0000
1740@@ -65,7 +65,7 @@
1741 EXPECT_EQ(UNITY_SCOPES_VERSION_MINOR, vminor);
1742 EXPECT_EQ(UNITY_SCOPES_VERSION_MICRO, vmicro);
1743
1744- b->start("some_scope", nullptr);
1745+ b->start("some_scope");
1746 b->stop();
1747 destroy(b);
1748 }
1749
1750=== modified file 'test/gtest/scopes/ScopeBase/scopelib.cpp'
1751--- test/gtest/scopes/ScopeBase/scopelib.cpp 2014-06-17 09:27:49 +0000
1752+++ test/gtest/scopes/ScopeBase/scopelib.cpp 2014-07-28 11:21:43 +0000
1753@@ -25,7 +25,7 @@
1754 public:
1755 MyScope() {}
1756
1757- virtual void start(std::string const&, unity::scopes::RegistryProxy const&) override {}
1758+ virtual void start(std::string const&) override {}
1759 virtual void stop() override {}
1760 virtual void run() override {}
1761
1762
1763=== modified file 'test/gtest/scopes/internal/ScopeConfig/ScopeConfig_test.cpp'
1764--- test/gtest/scopes/internal/ScopeConfig/ScopeConfig_test.cpp 2014-06-27 02:19:43 +0000
1765+++ test/gtest/scopes/internal/ScopeConfig/ScopeConfig_test.cpp 2014-07-28 11:21:43 +0000
1766@@ -125,7 +125,7 @@
1767 }
1768 catch(ConfigException const& e)
1769 {
1770- boost::regex r("unity::scopes::ConfigException: \".*\": Illegal value \\(blah\\) for ResultsTtlType");
1771+ boost::regex r("unity::scopes::ConfigException: \".*\": Illegal value \\(\"blah\"\\) for ResultsTtlType");
1772 EXPECT_TRUE(boost::regex_match(e.what(), r));
1773 }
1774 }
1775
1776=== modified file 'test/gtest/scopes/internal/ScopeConfig/complete_config.ini.in'
1777--- test/gtest/scopes/internal/ScopeConfig/complete_config.ini.in 2014-06-26 12:49:46 +0000
1778+++ test/gtest/scopes/internal/ScopeConfig/complete_config.ini.in 2014-07-28 11:21:43 +0000
1779@@ -15,6 +15,7 @@
1780 IdleTimeout = 300
1781 ResultsTtlType = large
1782 LocationDataNeeded = true
1783+ConfinementType = unconfined
1784
1785 [Appearance]
1786 arbitrary_key = true
1787
1788=== modified file 'test/gtest/scopes/internal/ScopeLoader/MyScope.h'
1789--- test/gtest/scopes/internal/ScopeLoader/MyScope.h 2014-06-17 09:27:49 +0000
1790+++ test/gtest/scopes/internal/ScopeLoader/MyScope.h 2014-07-28 11:21:43 +0000
1791@@ -31,7 +31,7 @@
1792 MyScope() {}
1793 virtual ~MyScope() {}
1794
1795- virtual void start(std::string const&, unity::scopes::RegistryProxy const&) override
1796+ virtual void start(std::string const&) override
1797 {
1798 inc_start();
1799 }
1800
1801=== modified file 'test/gtest/scopes/internal/ScopeLoader/ScopeA.cpp'
1802--- test/gtest/scopes/internal/ScopeLoader/ScopeA.cpp 2014-06-17 09:27:49 +0000
1803+++ test/gtest/scopes/internal/ScopeLoader/ScopeA.cpp 2014-07-28 11:21:43 +0000
1804@@ -30,7 +30,7 @@
1805 class ScopeA : public MyScope
1806 {
1807 public:
1808- virtual void start(std::string const&, unity::scopes::RegistryProxy const&) override
1809+ virtual void start(std::string const&) override
1810 {
1811 inc_start();
1812 }
1813
1814=== modified file 'test/gtest/scopes/internal/ScopeLoader/ScopeB.cpp'
1815--- test/gtest/scopes/internal/ScopeLoader/ScopeB.cpp 2014-06-17 09:27:49 +0000
1816+++ test/gtest/scopes/internal/ScopeLoader/ScopeB.cpp 2014-07-28 11:21:43 +0000
1817@@ -30,7 +30,7 @@
1818 class ScopeA : public MyScope
1819 {
1820 public:
1821- virtual void start(std::string const&, unity::scopes::RegistryProxy const&) override
1822+ virtual void start(std::string const&) override
1823 {
1824 inc_start();
1825 }
1826
1827=== modified file 'test/gtest/scopes/internal/ScopeLoader/ScopeLoader_test.cpp'
1828--- test/gtest/scopes/internal/ScopeLoader/ScopeLoader_test.cpp 2014-07-01 08:39:17 +0000
1829+++ test/gtest/scopes/internal/ScopeLoader/ScopeLoader_test.cpp 2014-07-28 11:21:43 +0000
1830@@ -47,11 +47,6 @@
1831 char const* scopeB = TEST_DIR "/libScopeB.so";
1832 }
1833
1834-// Need to make a dummy registry proxy because, if we pass a null shared_ptr to load(),
1835-// load() throws an exception.
1836-
1837-RegistryProxy registry(make_shared<RegistryImpl>(nullptr, (RuntimeImpl*)0x1));
1838-
1839 // Basic test.
1840
1841 TEST(ScopeLoader, basic)
1842@@ -59,13 +54,12 @@
1843 reset_counters();
1844
1845 {
1846- ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib, TEST_DIR, registry);
1847+ ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib);
1848 EXPECT_EQ(1, num_create());
1849 EXPECT_EQ(0, num_destroy());
1850
1851 EXPECT_EQ("testScope", sl->scope_id());
1852 EXPECT_EQ(scope_lib, sl->libpath());
1853- EXPECT_EQ(TEST_DIR, sl->scope_base()->scope_directory());
1854 }
1855 EXPECT_EQ(1, num_create());
1856 EXPECT_EQ(1, num_destroy());
1857@@ -78,7 +72,7 @@
1858 reset_counters();
1859
1860 {
1861- ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib, TEST_DIR, registry);
1862+ ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib);
1863
1864 // Check that calling stop on a stopped thread does nothing.
1865 sl->stop();
1866@@ -116,7 +110,7 @@
1867 reset_counters();
1868
1869 {
1870- ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib, TEST_DIR, registry);
1871+ ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib);
1872
1873 sl->start();
1874 EXPECT_EQ(1, num_start());
1875@@ -136,7 +130,7 @@
1876
1877 try
1878 {
1879- ScopeLoader::UPtr sl = ScopeLoader::load("testScope", "no_such_lib", TEST_DIR, registry);
1880+ ScopeLoader::UPtr sl = ScopeLoader::load("testScope", "no_such_lib");
1881 FAIL();
1882 }
1883 catch (unity::Exception const& e)
1884@@ -156,7 +150,7 @@
1885
1886 try
1887 {
1888- ScopeLoader::UPtr sl = ScopeLoader::load("testScope", no_destroy_lib, TEST_DIR, registry);
1889+ ScopeLoader::UPtr sl = ScopeLoader::load("testScope", no_destroy_lib);
1890 FAIL();
1891 }
1892 catch (unity::Exception const& e)
1893@@ -176,7 +170,7 @@
1894
1895 try
1896 {
1897- ScopeLoader::UPtr sl = ScopeLoader::load("testScope", null_return_lib, TEST_DIR, registry);
1898+ ScopeLoader::UPtr sl = ScopeLoader::load("testScope", null_return_lib);
1899 FAIL();
1900 }
1901 catch (unity::Exception const& e)
1902@@ -197,7 +191,7 @@
1903
1904 try
1905 {
1906- ScopeLoader::UPtr sl = ScopeLoader::load("testScope", null_return_lib, TEST_DIR, registry);
1907+ ScopeLoader::UPtr sl = ScopeLoader::load("testScope", null_return_lib);
1908 sl->unload();
1909 FAIL();
1910 }
1911@@ -217,7 +211,7 @@
1912 {
1913 reset_counters();
1914 {
1915- ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_start_lib, TEST_DIR, registry);
1916+ ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_start_lib);
1917 try
1918 {
1919 sl->start();
1920@@ -242,7 +236,7 @@
1921 {
1922 reset_counters();
1923 {
1924- ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_start_lib, TEST_DIR, registry);
1925+ ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_start_lib);
1926 try
1927 {
1928 sl->start();
1929@@ -266,7 +260,7 @@
1930 {
1931 reset_counters();
1932 {
1933- ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unknown_ex_from_start_lib, TEST_DIR, registry);
1934+ ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unknown_ex_from_start_lib);
1935 try
1936 {
1937 sl->start();
1938@@ -293,7 +287,7 @@
1939 reset_counters();
1940 try
1941 {
1942- ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_stop_lib, TEST_DIR, registry);
1943+ ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_stop_lib);
1944 sl->start();
1945 sl->stop();
1946 EXPECT_EQ(1, num_start());
1947@@ -319,7 +313,7 @@
1948 reset_counters();
1949 try
1950 {
1951- ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_std_ex_from_stop_lib, TEST_DIR, registry);
1952+ ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_std_ex_from_stop_lib);
1953 sl->start();
1954 sl->stop();
1955 EXPECT_EQ(1, num_start());
1956@@ -345,7 +339,7 @@
1957 reset_counters();
1958 try
1959 {
1960- ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unknown_ex_from_stop_lib, TEST_DIR, registry);
1961+ ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unknown_ex_from_stop_lib);
1962 sl->start();
1963 sl->stop();
1964 EXPECT_EQ(1, num_start());
1965@@ -369,7 +363,7 @@
1966 {
1967 reset_counters();
1968
1969- ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib, TEST_DIR, registry);
1970+ ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib);
1971 sl->start();
1972 sl->stop();
1973 sl->unload();
1974@@ -387,7 +381,7 @@
1975 {
1976 reset_counters();
1977
1978- ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_stop_lib, TEST_DIR, registry);
1979+ ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_stop_lib);
1980 sl->start();
1981 try
1982 {
1983@@ -418,7 +412,7 @@
1984 {
1985 reset_counters();
1986
1987- ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib, TEST_DIR, registry);
1988+ ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib);
1989 sl->start();
1990 sl->unload();
1991 try
1992@@ -438,7 +432,7 @@
1993 {
1994 reset_counters();
1995
1996- ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib, TEST_DIR, registry);
1997+ ScopeLoader::UPtr sl = ScopeLoader::load("testScope", scope_lib);
1998 sl->start();
1999 sl->unload();
2000 try
2001@@ -458,7 +452,7 @@
2002 {
2003 reset_counters();
2004
2005- ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_start_lib, TEST_DIR, registry);
2006+ ScopeLoader::UPtr sl = ScopeLoader::load("testScope", throw_unity_ex_from_start_lib);
2007 try
2008 {
2009 sl->start();
2010@@ -495,12 +489,12 @@
2011 reset_counters();
2012 clear_vars();
2013
2014- ScopeLoader::UPtr slA = ScopeLoader::load("scopeA", scopeA, TEST_DIR, registry);
2015+ ScopeLoader::UPtr slA = ScopeLoader::load("scopeA", scopeA);
2016 slA->start();
2017 EXPECT_EQ(1, num_create());
2018 EXPECT_EQ(1, num_start());
2019
2020- ScopeLoader::UPtr slB = ScopeLoader::load("scopeB", scopeB, TEST_DIR, registry);
2021+ ScopeLoader::UPtr slB = ScopeLoader::load("scopeB", scopeB);
2022 slB->start();
2023 EXPECT_EQ(2, num_create());
2024 EXPECT_EQ(2, num_start());
2025
2026=== modified file 'test/gtest/scopes/internal/ScopeLoader/ThrowUnityExFromStart.cpp'
2027--- test/gtest/scopes/internal/ScopeLoader/ThrowUnityExFromStart.cpp 2014-06-17 09:27:49 +0000
2028+++ test/gtest/scopes/internal/ScopeLoader/ThrowUnityExFromStart.cpp 2014-07-28 11:21:43 +0000
2029@@ -29,7 +29,7 @@
2030 class EXPORT MyThrowingScope : public MyScope
2031 {
2032 public:
2033- virtual void start(std::string const&, unity::scopes::RegistryProxy const&) override
2034+ virtual void start(std::string const&) override
2035 {
2036 inc_start();
2037 throw unity::LogicException("start failure");
2038
2039=== modified file 'test/gtest/scopes/internal/ScopeLoader/ThrowUnknownExFromStart.cpp'
2040--- test/gtest/scopes/internal/ScopeLoader/ThrowUnknownExFromStart.cpp 2014-06-17 09:27:49 +0000
2041+++ test/gtest/scopes/internal/ScopeLoader/ThrowUnknownExFromStart.cpp 2014-07-28 11:21:43 +0000
2042@@ -28,7 +28,7 @@
2043 class EXPORT MyThrowingScope : public MyScope
2044 {
2045 public:
2046- virtual void start(std::string const&, unity::scopes::RegistryProxy const&) override
2047+ virtual void start(std::string const&) override
2048 {
2049 inc_start();
2050 throw 42;
2051
2052=== modified file 'test/gtest/scopes/testing/IsolatedScope/scope.cpp'
2053--- test/gtest/scopes/testing/IsolatedScope/scope.cpp 2014-06-18 09:50:21 +0000
2054+++ test/gtest/scopes/testing/IsolatedScope/scope.cpp 2014-07-28 11:21:43 +0000
2055@@ -91,7 +91,8 @@
2056 {
2057 public:
2058 Query(unity::scopes::CannedQuery const& query, unity::scopes::SearchMetadata const& metadata, unity::scopes::RegistryProxy const& registry)
2059- : unity::scopes::SearchQueryBase(query, metadata), registry_(registry)
2060+ : unity::scopes::SearchQueryBase(query, metadata)
2061+ , registry_(registry)
2062 {
2063 }
2064
2065@@ -167,9 +168,15 @@
2066
2067 } // namespace testing
2068
2069-void testing::Scope::start(std::string const&, unity::scopes::RegistryProxy const &registry)
2070-{
2071- registry_ = registry;
2072+testing::Scope::Scope(unity::scopes::RegistryProxy const& r)
2073+ : registry_(r)
2074+{
2075+}
2076+
2077+testing::Scope::~Scope() = default;
2078+
2079+void testing::Scope::start(std::string const&)
2080+{
2081 }
2082
2083 void testing::Scope::stop()
2084@@ -184,7 +191,7 @@
2085 unity::scopes::CannedQuery const& query,
2086 unity::scopes::SearchMetadata const &metadata)
2087 {
2088- return unity::scopes::SearchQueryBase::UPtr(new testing::Query(query, metadata, registry_));
2089+ return unity::scopes::SearchQueryBase::UPtr(new testing::Query(query, metadata, registry()));
2090 }
2091
2092 unity::scopes::ActivationQueryBase::UPtr testing::Scope::activate(
2093@@ -209,3 +216,23 @@
2094 {
2095 return unity::scopes::PreviewQueryBase::UPtr(new testing::Preview(result, metadata));
2096 }
2097+
2098+std::string testing::Scope::scope_directory() const
2099+{
2100+ return "";
2101+}
2102+
2103+std::string testing::Scope::cache_directory() const
2104+{
2105+ return "";
2106+}
2107+
2108+unity::scopes::RegistryProxy testing::Scope::registry() const
2109+{
2110+ return registry_;
2111+}
2112+
2113+unity::scopes::VariantMap testing::Scope::settings() const
2114+{
2115+ return unity::scopes::VariantMap();
2116+}
2117
2118=== modified file 'test/gtest/scopes/testing/IsolatedScope/scope.h'
2119--- test/gtest/scopes/testing/IsolatedScope/scope.h 2014-06-18 09:50:21 +0000
2120+++ test/gtest/scopes/testing/IsolatedScope/scope.h 2014-07-28 11:21:43 +0000
2121@@ -17,15 +17,19 @@
2122 * Thomas Voß <thomas.voss@canonical.com>
2123 */
2124
2125-#include <unity/scopes/ScopeBase.h>
2126+#include <unity/scopes/AbstractScopeBase.h>
2127+#include <unity/scopes/testing/MockRegistry.h>
2128
2129 namespace testing
2130 {
2131
2132-class Scope : public unity::scopes::ScopeBase
2133+class Scope : public unity::scopes::AbstractScopeBase
2134 {
2135 public:
2136- void start(std::string const&, unity::scopes::RegistryProxy const &) override;
2137+ Scope(unity::scopes::RegistryProxy const&);
2138+ virtual ~Scope();
2139+
2140+ void start(std::string const&) override;
2141
2142 void stop() override;
2143
2144@@ -49,6 +53,14 @@
2145 unity::scopes::Result const&,
2146 unity::scopes::ActionMetadata const &) override;
2147
2148+ std::string scope_directory() const override;
2149+
2150+ std::string cache_directory() const override;
2151+
2152+ unity::scopes::RegistryProxy registry() const override;
2153+
2154+ unity::scopes::VariantMap settings() const override;
2155+
2156 unity::scopes::RegistryProxy registry_;
2157 };
2158
2159
2160=== modified file 'test/gtest/scopes/testing/IsolatedScopeBenchmark/IsolatedScopeBenchmark_test.cpp'
2161--- test/gtest/scopes/testing/IsolatedScopeBenchmark/IsolatedScopeBenchmark_test.cpp 2014-04-03 12:57:25 +0000
2162+++ test/gtest/scopes/testing/IsolatedScopeBenchmark/IsolatedScopeBenchmark_test.cpp 2014-07-28 11:21:43 +0000
2163@@ -55,7 +55,7 @@
2164 return "BenchmarkingScope";
2165 }
2166
2167- inline static std::shared_ptr<::testing::Scope> construct()
2168+ inline static std::shared_ptr<::testing::Scope> construct(unity::scopes::RegistryProxy const&)
2169 {
2170 return std::make_shared<::testing::Scope>(mean, variance);
2171 }
2172
2173=== modified file 'test/gtest/scopes/testing/IsolatedScopeBenchmark/scope.cpp'
2174--- test/gtest/scopes/testing/IsolatedScopeBenchmark/scope.cpp 2014-06-17 11:20:48 +0000
2175+++ test/gtest/scopes/testing/IsolatedScopeBenchmark/scope.cpp 2014-07-28 11:21:43 +0000
2176@@ -155,7 +155,7 @@
2177 {
2178 }
2179
2180-void testing::Scope::start(std::string const&, unity::scopes::RegistryProxy const &)
2181+void testing::Scope::start(std::string const&)
2182 {
2183 }
2184
2185
2186=== modified file 'test/gtest/scopes/testing/IsolatedScopeBenchmark/scope.h'
2187--- test/gtest/scopes/testing/IsolatedScopeBenchmark/scope.h 2014-06-17 09:27:49 +0000
2188+++ test/gtest/scopes/testing/IsolatedScopeBenchmark/scope.h 2014-07-28 11:21:43 +0000
2189@@ -30,7 +30,7 @@
2190 public:
2191 Scope(const std::chrono::milliseconds& mean, const std::chrono::milliseconds& variance);
2192
2193- void start(std::string const&, unity::scopes::RegistryProxy const &) override;
2194+ void start(std::string const&) override;
2195
2196 void stop() override;
2197
2198
2199=== modified file 'test/headers/CMakeLists.txt'
2200--- test/headers/CMakeLists.txt 2014-01-24 09:55:09 +0000
2201+++ test/headers/CMakeLists.txt 2014-07-28 11:21:43 +0000
2202@@ -6,6 +6,7 @@
2203
2204 set(subdirs
2205 unity/scopes
2206+ unity/scopes/testing
2207 )
2208 foreach(dir ${OTHER_INCLUDE_DIRS})
2209 set(other_inc_dirs "${other_inc_dirs} -I${dir}")
2210@@ -26,9 +27,11 @@
2211 ${public_inc_dir} ${CMAKE_CXX_COMPILER} "${CMAKE_CXX_COMPILER_ARG1} -fsyntax-only -I${root_inc_dir} -I${public_inc_dir} ${other_inc_dirs} ${CMAKE_CXX_FLAGS}")
2212
2213 # Test that each internal header compiles stand-alone.
2214- add_test(stand-alone-${location}-internal-headers
2215- ${CMAKE_CURRENT_SOURCE_DIR}/compile_headers.py
2216- ${internal_inc_dir} ${CMAKE_CXX_COMPILER} "${CMAKE_CXX_COMPILER_ARG1} -fsyntax-only -I${root_inc_dir} -I${internal_inc_dir} ${other_inc_dirs} ${CMAKE_CXX_FLAGS}")
2217+ if (IS_DIRECTORY ${internal_inc_dir})
2218+ add_test(stand-alone-${location}-internal-headers
2219+ ${CMAKE_CURRENT_SOURCE_DIR}/compile_headers.py
2220+ ${internal_inc_dir} ${CMAKE_CXX_COMPILER} "${CMAKE_CXX_COMPILER_ARG1} -fsyntax-only -I${root_inc_dir} -I${internal_inc_dir} ${other_inc_dirs} ${CMAKE_CXX_FLAGS}")
2221+ endif()
2222
2223 # Test that no public header includes an internal header
2224 add_test(clean-public-${location}-headers ${CMAKE_CURRENT_SOURCE_DIR}/check_public_headers.py ${public_inc_dir})
2225
2226=== modified file 'test/headers/check_public_headers.py'
2227--- test/headers/check_public_headers.py 2013-06-27 08:38:02 +0000
2228+++ test/headers/check_public_headers.py 2014-07-28 11:21:43 +0000
2229@@ -53,7 +53,7 @@
2230 for hdr in hdrs:
2231 try:
2232 hdr_name = os.path.join(hdr_dir, hdr)
2233- file = open(hdr_name, "r")
2234+ file = open(hdr_name, 'r', encoding = 'utf=8')
2235 except OSError as e:
2236 error("cannot open \"" + hdr_name + "\": " + e.strerror)
2237 sys.exit(1)

Subscribers

People subscribed via source and target branches

to all changes: