~unity-api-team/unity-scopes-api/child-scopes-option

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
#
# Copyright (C) 2013 Canonical Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License version 3 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Authored by: Michi Henning <michi.henning@canonical.com>
#

-------------------------------------------------------------------------------------
NOTE: Before making changes to the code, please read the README file in its entirety!
-------------------------------------------------------------------------------------


Building the code
-----------------

By default, the code is built in release mode. To build a debug version, use

    $ mkdir builddebug
    $ cd builddebug
    $ cmake -DCMAKE_BUILD_TYPE=debug ..
    $ make

For a release version, use -DCMAKE_BUILD_TYPE=release

Running the tests
-----------------

    $ make
    $ make test

Note that "make test" alone is dangerous because it does not rebuild
any tests if either the library or the test files themselves need
rebuilding. It's not possible to fix this with cmake because cmake cannot
add build dependencies to built-in targets. To make sure that everything
is up-to-date, run "make" before running "make test"!

To run the tests with valgrind:

    $ make valgrind

Coverage
--------

To build with the flags for coverage testing enabled and get coverage:

    $ mkdir buildcoverage
    $ cd buildcoverage
    $ cmake -DCMAKE_BUILD_TYPE=coverage
    $ make
    $ make test
    $ make coverage

Note that, with gcc 4.7.2 and cmake 2.8.10, you may get a bunch of
warnings. To fix this, you can build cmake 2.8.10 with the following patch:

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=61ace1df2616e472d056b302e4269cbf112fb020#patch1

Unfortunately, it is not possibly to get 100% coverage for some files,
mainly due to gcc's generation of two destructors for dynamic and non-
dynamic instances. For abstract base classes and for classes that
prevent stack and static allocation, this causes one of the destructors
to be reported as uncovered.

There are also issues with some functions in header files that are
incorrectly reported as uncovered due to inlining, as well as
the impossibility of covering defensive assert(false) statements,
such as an assert in the default branch of a switch, where the
switch is meant to handle all possible cases explicitly.

If you run a binary and get lots of warnings about a "merge mismatch for summaries",
this is caused by having made changes to the source that add or remove code
that was previously run, so the new coverage output cannot sensibly be merged
into the old coverage output. You can get rid of this problem by running

    $ make clean-coverage

This deletes all the .gcda files, allowing the merge to succeed again.

If lcov complains about unrecognized lines involving '=====',
you can patch geninfo and gcovr as explained here:

https://bugs.launchpad.net/gcovr/+bug/1086695/comments/2

To run the static C++ checks:

    $ make cppcheck

Code style
----------

We use a format tool that fixes a whole lot of issues
regarding code style. The formatting changes made by
the tool are generally sensible (even though they may not be your
personal preference in all case). If there is a case where the formatting
really messes things up, consider re-arranging the code to avoid the problem.
The convenience of running the entire code base through the pretty-printer
far outweighs any minor glitches with pretty printing, and it means that
we get consistent code style for free, rather than endlessly having to
watch out for formatting issues during code reviews.

To format specific files:

    ${CMAKE_BINARY_DIR}/tools/formatcode x.cpp x.h

If no arguments are provided, formatcode reads stdin and writes
stdout, so you can easily pipe code into the tool from within an
editor. For example, to reformat the entire file in vi (assuming
${CMAKE_BINARY_DIR}/tools is in your PATH):

    1G!Gformatcode

To re-format all source and header files in the tree:

    $ make formatcode

Thread and address sanitizer
----------------------------

Set SANITIZER to "thread" or "address" to build with the
corresponding sanitizer enabled.

zmq (as 3.2.3 and 4.0.3) causes a large number of warnings from
thread sanitizer. It appears impossible to avoid these; they
are caused by issues in the zmq library. The tsan-suppress file
supresses the benign race conditions we currently know about. To
run the tests (from the build directory) with these suppressions
enabled, use:

    $ TSAN_OPTIONS="suppressions=../tsan-suppress" make test

Updating symbols file
---------------------

To easily spot new/removed/changed symbols in the library, the debian
package is maintaining a .symbols file which lists all exported symbols
present in the library .so. If you add new public symbols to the library,
it's necessary to refresh the symbols file, otherwise the package will
fail to build. The easiest way to do that is using bzr-builddeb:

    $ bzr bd -- -us -uc -j8  # Don't sign source package or changes file, 8 compiles in parallel
    $ # this will exit with an error if symbols file isn't up-to-date
    $ cd ../build-area/unity-scopes-api-[version]
    $ ./obj-[arch]/tools/symbol_diff

This creates a diff of the symbols in /tmp/symbols.diff.
(The demangled symbols from the debian build are in ./new_symbols.)

NOTE: We currently have one architecture-specific symbol:

(c++|arch=amd64)"unity::scopes::internal::RegistryObject::ScopeExecData::ScopeExecData(unity::scopes::internal::RegistryObject::ScopeExecData const&)@Base" 0.6.6+14.10.20140916

We need this because the copy-constructor is inlined on i386 and armhf.

The above script can't cope with the arch tag at the moment. Until we get
around to fixing this, you need to delete the corresponding change from
the diff output before applying the diff as a patch. The offending diff
will look something like this:

@@ -377,7 +378,7 @@
  (c++)"unity::scopes::internal::RegistryObject::remove_desktop_file(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.6.6+14.10.20140916
  (c++)"unity::scopes::internal::RegistryObject::remove_local_scope(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1
  (c++)"unity::scopes::internal::RegistryObject::ScopeExecData::~ScopeExecData()@Base" 0.4.2+14.04.20140404.2
- (c++|arch=amd64)"unity::scopes::internal::RegistryObject::ScopeExecData::ScopeExecData(unity::scopes::internal::RegistryObject::ScopeExecData const&)@Base" 0.6.6+14.10.20140916
+ (c++)"unity::scopes::internal::RegistryObject::ScopeExecData::ScopeExecData(unity::scopes::internal::RegistryObject::ScopeExecData const&)@Base" 0replaceme
 (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::clear_handle_unlocked()@Base" 0.4.2+14.04.20140404.2
 (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::exec(core::posix::ChildProcess::DeathObserver&, std::shared_ptr<unity::scopes::internal::Executor>)@Base" 0.4.3+14.10.20140428
 (c++)"unity::scopes::internal::RegistryObject::ScopeProcess::expand_custom_exec()@Base" 0.5.0+14.10.20140619

Review any other changes in /tmp/symbols.diff. If they are OK:

    $ cd -
    $ patch -p0 < /tmp/symbols.diff

ABI compliance test
-------------------
To use this, install abi-compliance-checker package from the archives.

You can use abi-compliance-checker to test whether a particular build
is ABI compatible with another build. The tool does some source-level
analysis in addition to checking library symbols, so it catches things
that are potentially dangerous, but won't be picked up by just looking
at the symbol table.

Assume you have built devel in src/devel, and you have a later build
in src/mybranch and want to check that mybranch is still compatible.
To run the compliance test:

$ cd src
$ abi-compliance-checker -lib libunity-scopes.so -old devel/build/test/abi-compliance/abi.xml -new mybranch/build/test/abi-compliance/abi.xml

The script will take about two minutes to run.

You will get a message about compilation errors. These are caused by a Qt macro and
can be ignored. (The log file in src/logs/libunity-scopes.so/[version]/log.txt
contains the details.)

Now point your browser at 

src/compat_reports/libunity-scopes.so/[version]_to_[version]/compat_report.html

The report provides a nicely layed-out page with all the details.

Debugging IPC
-------------

There are lots of messages being passed between the various scope processes,
and therefore it might be sometimes useful to see those to help with debugging.
There is a special monitoring code that is enabled if you pass
-DIPC_MONITORING=ON to cmake. When you build the library with this code,
the messages can be introspected using the python scripts in the tools directory.

Note that the tools require python dependencies that are otherwise not required
for regular builds, to get those, grab python-zmq and python-capnproto.

As of time of writing this, python-capnproto is not present in the distro,
so get it from https://github.com/jparyani/pycapnp.git, also note that the master
branch is compatible with capnproto 0.3, not 0.4 which we're using, so you need
to switch to the "feature/v0.4" branch.

Once you have the extra python dependencies you need to run:

    $ ./zmq-monitor-host.py &

This runs a monitor proxy that forwards the monitored messages from all publishers
to all subscribers.
Then you can run a subscriber that will display content of the messages:

    $ ./zmq-parser.py

Autopkg test suite
------------------

Scopes comes with an autopkg smoke test.

http://packaging.ubuntu.com/html/auto-pkg-test.html

Running the test manually is simple. After building and installing the
new packages, just run 'sh debian/tests/scopebuild'.

To run the autopkg tests the same way Jenkins does, without installing
the packages, follow the instructions here:

http://packaging.ubuntu.com/html/auto-pkg-test.html

When adding new tests to debian/tests, be sure that the new tests
are built and run by adding them to tests/autopkg. Doing this doesn't
run the tests exactly the same way as on Jenkins because they will
be built and run against the headers and library in the build area,
rather than against the installed packages. But it provides a basic
sanity check for them. Without this, it's very easy to make a breaking
change to the API and forgetting to update the autopkg tests too,
meaning that the failure will show up only in Jenkins, but not
when running the tests locally.