Merge lp:~jpakkane/unity-scopes-api/simplelogging into lp:unity-scopes-api/devel
- simplelogging
- Merge into devel
Status: | Rejected |
---|---|
Rejected by: | Michi Henning |
Proposed branch: | lp:~jpakkane/unity-scopes-api/simplelogging |
Merge into: | lp:unity-scopes-api/devel |
Diff against target: |
762 lines (+302/-41) 17 files modified
include/unity/scopes/internal/Logging.h (+70/-0) src/scopes/internal/ActivationQueryObject.cpp (+3/-3) src/scopes/internal/AnnotationImpl.cpp (+5/-5) src/scopes/internal/CMakeLists.txt (+1/-0) src/scopes/internal/Logging.cpp (+119/-0) src/scopes/internal/PreviewQueryObject.cpp (+5/-3) src/scopes/internal/QueryBaseImpl.cpp (+2/-2) src/scopes/internal/QueryCtrlImpl.cpp (+2/-2) src/scopes/internal/QueryObject.cpp (+3/-3) src/scopes/internal/ReplyImpl.cpp (+5/-4) src/scopes/internal/ReplyObject.cpp (+5/-5) src/scopes/internal/RuntimeImpl.cpp (+4/-4) src/scopes/internal/ScopeImpl.cpp (+7/-7) src/scopes/internal/ScopeObject.cpp (+3/-3) test/gtest/scopes/internal/CMakeLists.txt (+1/-0) test/gtest/scopes/internal/Logging/CMakeLists.txt (+14/-0) test/gtest/scopes/internal/Logging/Logging_test.cpp (+53/-0) |
To merge this branch: | bzr merge lp:~jpakkane/unity-scopes-api/simplelogging |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michi Henning (community) | Disapprove | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Paweł Stołowski (community) | Needs Fixing | ||
Review via email: mp+209447@code.launchpad.net |
Commit message
A very simple logging class.
Description of the change
A very simple logging class. Mostly a building block for further functionality.
PS Jenkins bot (ps-jenkins) wrote : | # |
Paweł Stołowski (stolowski) wrote : | # |
Why not dumping to std::cerr right away in LogGatherer& LogGatherer:
- 259. By Jussi Pakkanen
-
Simple locking.
Jussi Pakkanen (jpakkane) wrote : | # |
Because dumping immediately causes interleaving for multiple threads.
Updated the MR to provide simple locking.
If we want this to be fully multithreaded we either need to copy the items or create a complex locking mechanism. Since the data sizes are minuscule (less than 1k for >99% of the time) and usage infrequent, let's just copy.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:259
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 260. By Jussi Pakkanen
-
Merged trunk.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:260
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Paweł Stołowski (stolowski) wrote : | # |
199 +static std::mutex print_mutex;
This could be a static private member of LogGatherer, no? I realise it's not exposed anywhere right now, but making it a static member would encapsulate it even more
Could you please provide overloaded << for all basic data types?
Michi Henning (michihenning) wrote : | # |
> Could you please provide overloaded << for all basic data types?
I'd be inclined to hold off with that for the moment. There is no point in adding an operator<< for floats if we don't have any place in the code where we want to log a float. All it means is that we end up having to write more code and tests, for no gain in functionality.
Michi Henning (michihenning) wrote : | # |
LogStream should be provided as an abstract base with only pure virtual functions. That way, we don't couple the logging mechanism to the call sites and we can replace it with something else without recompiling everything that logs something, and the choice of which logger to use can be delayed until run time.
Michi Henning (michihenning) wrote : | # |
196 +namespace internal
197 +{
198 +
199 +static std::mutex print_mutex;
200 +
201 +LogStream errlog;
This doesn't look right. If the mutex is static, it has internal linkage, meaning that each compilation unit will end up with its own separate copy of the mutex, so locking the mutex will not achieve what it's meant to.
If we want to have all source files share the same single mutex, it needs to be a static member variable of the class.
Michi Henning (michihenning) wrote : | # |
> This doesn't look right. If the mutex is static, it has internal linkage,
Ah, sorry, forget it. I confused source file and header file.
Paweł Stołowski (stolowski) wrote : | # |
> > Could you please provide overloaded << for all basic data types?
>
> I'd be inclined to hold off with that for the moment. There is no point in
> adding an operator<< for floats if we don't have any place in the code where
> we want to log a float. All it means is that we end up having to write more
> code and tests, for no gain in functionality.
I think it's worth to have one for bool (and making sure it behaves as if std::boolalpha was set).
Michi Henning (michihenning) wrote : | # |
Bool is fine with me, but let's not get carried away. If we find in two months time that we really want to log a double with formatting, we can still add something then.
Jussi Pakkanen (jpakkane) wrote : | # |
You can totally change the logging framework without recompiling everything. You just change the .cpp file and recompile that (not-yet-done pimpling notwithstanding). There is no need to change the header for that.
As far as runtime goes, there are two things we might want to do then:
1. configure it (e.g. set log levels or the like)
2. change it (e.g. from Boost to glib or what have you)
The first one can be done just by adding some (global?) functions. A virtual base provides no improvements. The latter is something we don't ever need to do. Why on earth would we change between the two at runtime? We'll just pick one and be done with it. Even if for some strange reason we would want to, we can implement 2 in the same way as 1: a configuration option of the class.
Abstract base classes only make sense if you have multiple objects of the same type existing at the same time and need to be used interchangeably. We don't. It's just a simple "write this stuff to the log". It does _not_ need anything fancier because those features just complicate things for no good reason. As an example, let's look at this:
errlog << "Some text";
For this to work, errlog needs to be either a macro that does something magical or a concrete (that is, non-abstract) object. It can _not_ be an abstract base class because such an object is non-constructible. This is also the only way it is used. Thus:
1. we absolutely need a concrete, instantiated object with defined semantics
2. its type does not change at runtime (it behaviour might, but that's just a question of configuration)
Under these conditions, what is the benefit an abstract base class would bring?
("Because maybe we might sometime in the future do something perhaps" is NOT a valid answer, it is handwaving.)
Michi Henning (michihenning) wrote : | # |
We have RuntimeImpl in the code as a handle to anything that the library needs. That gives us the ability to have multiple runtime instances in a process (we do this in the tests, for example), and it allows us to control the life time of each run time.
With a global logger variable, we can't do this anymore, and separate instances of the runtime in the same process will share the same logger.
I think it would be better to have RuntimeImpl own and initialise the logger. I believe that it's possible to get at the RuntimeImpl/Runtime instance from most places in the code. There may be places in value types where we would like to log something and can't get at the Runtime handle. I haven't checked this in detail yet, but I expect there won't be too many places in the code where this is the case. In most of them, we can probably make the logger available if we need it.
At any rate, I'm uncomfortable with having a global variable.
Jussi Pakkanen (jpakkane) wrote : | # |
Not having global variables is a valid goal. To do that we either need to:
1. pass a logging provider to all classes that need logging (tedious, let's not do that)
2. have errlog class determine where the messages should go and configure LogGather to write its stuff there
Option 2 would mean roughly this in pseudocode:
if something
l = LogGatherer(with some options)
else
l = LogGatherer(with some other options)
endif
I would imagine this is what Qt does and why its logging classes are used like this:
qDebug() << "something";
- 261. By Jussi Pakkanen
-
Now with bool support.
Thomas Voß (thomas-voss) wrote : | # |
As this is an implementation detail, why not use google log (see https:/
class Logger
{
public:
enum class Severity
{
error,
warning,
info,
...
};
virtual std::ostream& log(Severity severity) = 0;
};
with a GLog-based implementation would be quite helpful in testing and, later on, in real reporting use-cases.
For the global variable/global function approach: Singleton is an anti-pattern from my POV, and while it might be less tedious to just have a global logger instance, it results in tight coupling and makes isolated component testing really really difficult.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:261
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Jussi Pakkanen (jpakkane) wrote : | # |
If you look at glog, it uses singletons (or macros, which are "global functions" to use your terminology) too. You use it like this:
LOG(INFO) << "Something";
Also, could you give an example of where using a global logging function would make debugging harder? Please be specific, preferably by using sample code.
While you are at it, could you also explain how non-global logging objects should work? As an example let's say we have class A which internally uses class B, which uses class C, which in turn uses class D. Now let's suppose class D needs to write a log message. The questions to answer are:
- what object (not a function as those are forbidden, right?) should it call to send this message
- how is this object passed on to it
- who is the master owner of this object
Thomas Voß (thomas-voss) wrote : | # |
> If you look at glog, it uses singletons (or macros, which are "global
> functions" to use your terminology) too. You use it like this:
>
> LOG(INFO) << "Something";
>
Sure, that's why I proposed a logger interface that can be implemented with the help of GLog to avoid a singleton use.
> Also, could you give an example of where using a global logging function would
> make debugging harder? Please be specific, preferably by using sample code.
>
For testing (which I originally referred to): Somewhere in your implementation (in a .cpp) you have one or multiple lines like:
logerr << "...";
How do you test (easily) that the correct log string is generated? Of course, we could fall back to link time seams here, but I don't think that's a good idea.
> While you are at it, could you also explain how non-global logging objects
> should work? As an example let's say we have class A which internally uses
> class B, which uses class C, which in turn uses class D. Now let's suppose
> class D needs to write a log message. The questions to answer are:
>
> - what object (not a function as those are forbidden, right?) should it call
> to send this message
> - how is this object passed on to it
> - who is the master owner of this object
Hmmm, I might miss something, but D should look like:
class D
{
public:
D(const Logger::Ptr& logger) : logger(logger)
{
}
void do_something()
{
}
private:
Logger::Ptr logger;
};
And yes, the logger dependency would have to be handed down the dependency chain. Nothing wrong with that from my perspective as the logger (and later on a reporter) in fact is a real functional requirement of class D. You will not get rid of that by satisfying it implicitly with a singleton.
The ultimate owner of the logger is the runtime.
Jussi Pakkanen (jpakkane) wrote : | # |
> How do you test (easily) that the correct log string is generated?
By forwarding the log output to a file and inspecting its contents.
> And yes, the logger dependency would have to be handed down the dependency chain.
Please read this:
http://
> Nothing wrong with that from my perspective
But from the perspective of the poor bastards who have to augment, basically, EVERY SINGLE CLASS in the entire source base with extra constructor arguments this is a very big problem. These people have better things to do with their time.
Thomas Voß (thomas-voss) wrote : | # |
> > How do you test (easily) that the correct log string is generated?
>
> By forwarding the log output to a file and inspecting its contents.
>
> > And yes, the logger dependency would have to be handed down the dependency
> chain.
>
> Please read this:
>
> http://
>
I would hold http://
> > Nothing wrong with that from my perspective
>
> But from the perspective of the poor bastards who have to augment, basically,
> EVERY SINGLE CLASS in the entire source base with extra constructor arguments
> this is a very big problem. These people have better things to do with their
> time.
Two things:
(1.) why would every class need to log? Littering production code with logging message sounds like bad idea. Instead, instrumenting an executable with http://
(2.) Under the assumption of non-universal logging (see (1.)), I would strongly assume that the scope of the changes is limited and well-defined in reality as only certain classes would need to be provided with logging capabilities.
Michi Henning (michihenning) wrote : | # |
Cleaning up moldy oldies.
Unmerged revisions
- 261. By Jussi Pakkanen
-
Now with bool support.
- 260. By Jussi Pakkanen
-
Merged trunk.
- 259. By Jussi Pakkanen
-
Simple locking.
- 258. By Jussi Pakkanen
-
Start using the logging class instead of hitting std::cerr directly.
- 257. By Jussi Pakkanen
-
Now with numbers.
- 256. By Jussi Pakkanen
-
Some more test cases.
- 255. By Jussi Pakkanen
-
Very basic output plus some text.
- 254. By Jussi Pakkanen
-
Start work on logging classes.
Preview Diff
1 | === added file 'include/unity/scopes/internal/Logging.h' |
2 | --- include/unity/scopes/internal/Logging.h 1970-01-01 00:00:00 +0000 |
3 | +++ include/unity/scopes/internal/Logging.h 2014-03-06 09:05:05 +0000 |
4 | @@ -0,0 +1,70 @@ |
5 | +/* |
6 | + * Copyright (C) 2014 Canonical Ltd |
7 | + * |
8 | + * This program is free software: you can redistribute it and/or modify |
9 | + * it under the terms of the GNU Lesser General Public License version 3 as |
10 | + * published by the Free Software Foundation. |
11 | + * |
12 | + * This program is distributed in the hope that it will be useful, |
13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | + * GNU Lesser General Public License for more details. |
16 | + * |
17 | + * You should have received a copy of the GNU Lesser General Public License |
18 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | + * |
20 | + * Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com> |
21 | + */ |
22 | + |
23 | +#ifndef UNITY_SCOPES_INTERNAL_LOGGING_H |
24 | +#define UNITY_SCOPES_INTERNAL_LOGGING_H |
25 | + |
26 | +#include <string> |
27 | +#include <vector> |
28 | +#include <unity/util/NonCopyable.h> |
29 | + |
30 | +namespace unity |
31 | +{ |
32 | + |
33 | +namespace scopes |
34 | +{ |
35 | + |
36 | +namespace internal |
37 | +{ |
38 | + |
39 | +class LogGatherer; |
40 | + |
41 | +class LogStream final { |
42 | + NONCOPYABLE(LogStream); |
43 | +public: |
44 | + LogStream(); |
45 | + LogGatherer operator<<(const std::string &s); |
46 | + LogGatherer operator<<(const int i); |
47 | + LogGatherer operator<<(const char *msg); |
48 | + LogGatherer operator<<(const bool i); |
49 | +}; |
50 | + |
51 | +class LogGatherer final { |
52 | + |
53 | +public: |
54 | + |
55 | + LogGatherer(); |
56 | + ~LogGatherer(); |
57 | + LogGatherer& operator<<(const std::string &s); |
58 | + LogGatherer& operator<<(const int i); |
59 | + LogGatherer& operator<<(const bool i); |
60 | + LogGatherer& operator<<(const char *msg); |
61 | + |
62 | +private: |
63 | + std::vector<std::string> strings; |
64 | +}; |
65 | + |
66 | +extern LogStream errlog; |
67 | + |
68 | +} // namespace internal |
69 | + |
70 | +} // namespace scopes |
71 | + |
72 | +} // namespace unity |
73 | + |
74 | +#endif |
75 | |
76 | === modified file 'src/scopes/internal/ActivationQueryObject.cpp' |
77 | --- src/scopes/internal/ActivationQueryObject.cpp 2014-02-27 23:29:10 +0000 |
78 | +++ src/scopes/internal/ActivationQueryObject.cpp 2014-03-06 09:05:05 +0000 |
79 | @@ -21,7 +21,7 @@ |
80 | #include <unity/scopes/ActivationQueryBase.h> |
81 | #include <unity/scopes/internal/MWReply.h> |
82 | #include <unity/scopes/internal/MWQueryCtrl.h> |
83 | -#include <iostream> |
84 | +#include <unity/scopes/internal/Logging.h> |
85 | #include <cassert> |
86 | |
87 | using namespace std; |
88 | @@ -69,13 +69,13 @@ |
89 | { |
90 | // TODO: log error |
91 | reply_->finished(ListenerBase::Error, e.what()); // Oneway, can't block |
92 | - cerr << "ActivationQueryObject::run(): " << e.what() << endl; |
93 | + errlog << "ActivationQueryObject::run(): " << e.what(); |
94 | } |
95 | catch (...) |
96 | { |
97 | // TODO: log error |
98 | reply_->finished(ListenerBase::Error, "unknown exception"); // Oneway, can't block |
99 | - cerr << "ActivationQueryObject::run(): unknown exception" << endl; |
100 | + errlog << "ActivationQueryObject::run(): unknown exception"; |
101 | } |
102 | } |
103 | |
104 | |
105 | === modified file 'src/scopes/internal/AnnotationImpl.cpp' |
106 | --- src/scopes/internal/AnnotationImpl.cpp 2014-02-27 16:58:50 +0000 |
107 | +++ src/scopes/internal/AnnotationImpl.cpp 2014-03-06 09:05:05 +0000 |
108 | @@ -16,9 +16,9 @@ |
109 | */ |
110 | |
111 | #include <unity/scopes/internal/AnnotationImpl.h> |
112 | +#include <unity/scopes/internal/Logging.h> |
113 | #include <unity/UnityExceptions.h> |
114 | #include <sstream> |
115 | -#include <iostream> |
116 | #include <cassert> |
117 | |
118 | namespace unity |
119 | @@ -85,7 +85,7 @@ |
120 | { |
121 | if (annotation_type_ != Annotation::Type::GroupedLink) |
122 | { |
123 | - std::cerr << "Annotation::set_label(): label is allowed in GroupedLink only" << std::endl; |
124 | + errlog << "Annotation::set_label(): label is allowed in GroupedLink only"; |
125 | } |
126 | label_ = label; |
127 | } |
128 | @@ -94,7 +94,7 @@ |
129 | { |
130 | if (annotation_type_ != Annotation::Type::Link) |
131 | { |
132 | - std::cerr << "Annotation::set_icon(): icon is allowed in Link annotations only" << std::endl; |
133 | + errlog << "Annotation::set_icon(): icon is allowed in Link annotations only"; |
134 | } |
135 | icon_ = icon; |
136 | } |
137 | @@ -112,7 +112,7 @@ |
138 | { |
139 | if (annotation_type_ != Annotation::Type::GroupedLink) |
140 | { |
141 | - std::cerr << "Annotation::label(): label is allowed in GroupedLink only" << std::endl; |
142 | + errlog << "Annotation::label(): label is allowed in GroupedLink only"; |
143 | } |
144 | return label_; |
145 | } |
146 | @@ -121,7 +121,7 @@ |
147 | { |
148 | if (annotation_type_ != Annotation::Type::Link) |
149 | { |
150 | - std::cerr << "Annotation::icon(): icon is allowed in Link annotations only" << std::endl; |
151 | + errlog << "Annotation::icon(): icon is allowed in Link annotations only"; |
152 | } |
153 | return icon_; |
154 | } |
155 | |
156 | === modified file 'src/scopes/internal/CMakeLists.txt' |
157 | --- src/scopes/internal/CMakeLists.txt 2014-03-04 05:54:24 +0000 |
158 | +++ src/scopes/internal/CMakeLists.txt 2014-03-06 09:05:05 +0000 |
159 | @@ -25,6 +25,7 @@ |
160 | ${CMAKE_CURRENT_SOURCE_DIR}/FilterStateImpl.cpp |
161 | ${CMAKE_CURRENT_SOURCE_DIR}/JsonCppNode.cpp |
162 | ${CMAKE_CURRENT_SOURCE_DIR}/LinkImpl.cpp |
163 | + ${CMAKE_CURRENT_SOURCE_DIR}/Logging.cpp |
164 | ${CMAKE_CURRENT_SOURCE_DIR}/MiddlewareBase.cpp |
165 | ${CMAKE_CURRENT_SOURCE_DIR}/MiddlewareFactory.cpp |
166 | ${CMAKE_CURRENT_SOURCE_DIR}/MWObject.cpp |
167 | |
168 | === added file 'src/scopes/internal/Logging.cpp' |
169 | --- src/scopes/internal/Logging.cpp 1970-01-01 00:00:00 +0000 |
170 | +++ src/scopes/internal/Logging.cpp 2014-03-06 09:05:05 +0000 |
171 | @@ -0,0 +1,119 @@ |
172 | +/* |
173 | + * Copyright (C) 2014 Canonical Ltd |
174 | + * |
175 | + * This program is free software: you can redistribute it and/or modify |
176 | + * it under the terms of the GNU Lesser General Public License version 3 as |
177 | + * published by the Free Software Foundation. |
178 | + * |
179 | + * This program is distributed in the hope that it will be useful, |
180 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
181 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
182 | + * GNU Lesser General Public License for more details. |
183 | + * |
184 | + * You should have received a copy of the GNU Lesser General Public License |
185 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
186 | + * |
187 | + * Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com> |
188 | + */ |
189 | + |
190 | +#include <unity/scopes/internal/Logging.h> |
191 | +#include <mutex> |
192 | +#include <iostream> |
193 | + |
194 | +namespace unity |
195 | +{ |
196 | + |
197 | +namespace scopes |
198 | +{ |
199 | + |
200 | +namespace internal |
201 | +{ |
202 | + |
203 | +static std::mutex print_mutex; |
204 | + |
205 | +LogStream errlog; |
206 | + |
207 | +LogStream::LogStream() { |
208 | + |
209 | +} |
210 | + |
211 | +LogGatherer LogStream::operator<<(const std::string &s) |
212 | +{ |
213 | + LogGatherer l; |
214 | + l << s; |
215 | + return l; |
216 | +} |
217 | + |
218 | +LogGatherer LogStream::operator<<(const int i) |
219 | +{ |
220 | + LogGatherer l; |
221 | + l << i; |
222 | + return l; |
223 | +} |
224 | + |
225 | +LogGatherer LogStream::operator<<(const bool i) |
226 | +{ |
227 | + LogGatherer l; |
228 | + l << i; |
229 | + return l; |
230 | +} |
231 | + |
232 | +LogGatherer LogStream::operator<<(const char *msg) { |
233 | + LogGatherer l; |
234 | + l << msg; |
235 | + return l; |
236 | +} |
237 | + |
238 | +LogGatherer::LogGatherer() |
239 | +{ |
240 | + |
241 | +} |
242 | + |
243 | +LogGatherer::~LogGatherer() |
244 | +{ |
245 | + std::unique_lock<std::mutex> l(print_mutex); |
246 | + if(strings.empty()) |
247 | + return; |
248 | + try |
249 | + { |
250 | + for(const auto &i : strings) |
251 | + { |
252 | + std::cerr << i; |
253 | + } |
254 | + const std::string &last = strings.back(); |
255 | + if(last.empty() or last.back() != '\n') |
256 | + { |
257 | + std::cerr << std::endl; |
258 | + } |
259 | + } catch(...) { |
260 | + // There's not much we can do in this case. |
261 | + } |
262 | +} |
263 | + |
264 | +LogGatherer& LogGatherer::operator<<(const std::string &s) |
265 | +{ |
266 | + strings.push_back(s); |
267 | + return *this; |
268 | +} |
269 | + |
270 | +LogGatherer& LogGatherer::operator<<(const int i) |
271 | +{ |
272 | + return *this << std::to_string(i); |
273 | +} |
274 | + |
275 | +LogGatherer& LogGatherer::operator<<(const bool i) |
276 | +{ |
277 | + std::string val(i ? "true" : "false"); |
278 | + return *this << val; |
279 | +} |
280 | + |
281 | +LogGatherer& LogGatherer::operator<<(const char *msg) { |
282 | + strings.emplace_back(msg); |
283 | + return *this; |
284 | +} |
285 | + |
286 | +} // namespace internal |
287 | + |
288 | +} // namespace scopes |
289 | + |
290 | +} // namespace unity |
291 | |
292 | === modified file 'src/scopes/internal/PreviewQueryObject.cpp' |
293 | --- src/scopes/internal/PreviewQueryObject.cpp 2014-03-04 03:15:11 +0000 |
294 | +++ src/scopes/internal/PreviewQueryObject.cpp 2014-03-06 09:05:05 +0000 |
295 | @@ -16,6 +16,7 @@ |
296 | * Authored by: Michal Hruby <michal.hruby@canonical.com> |
297 | */ |
298 | |
299 | +#include <unity/scopes/internal/Logging.h> |
300 | #include <unity/scopes/internal/MWQueryCtrl.h> |
301 | #include <unity/scopes/internal/MWReply.h> |
302 | #include <unity/scopes/internal/PreviewQueryObject.h> |
303 | @@ -25,8 +26,9 @@ |
304 | #include <unity/scopes/ListenerBase.h> |
305 | #include <unity/scopes/QueryBase.h> |
306 | #include <unity/scopes/ReplyProxyFwd.h> |
307 | +#include <unity/scopes/SearchReply.h> |
308 | +#include <unity/scopes/PreviewReply.h> |
309 | |
310 | -#include <iostream> |
311 | #include <cassert> |
312 | |
313 | using namespace std; |
314 | @@ -79,13 +81,13 @@ |
315 | pushable_ = false; |
316 | // TODO: log error |
317 | reply_->finished(ListenerBase::Error, e.what()); // Oneway, can't block |
318 | - cerr << "PreviewQueryObject::run(): " << e.what() << endl; |
319 | + errlog << "PreviewQueryObject::run(): " << e.what(); |
320 | } |
321 | catch (...) |
322 | { |
323 | // TODO: log error |
324 | reply_->finished(ListenerBase::Error, "unknown exception"); // Oneway, can't block |
325 | - cerr << "PreviewQueryObject::run(): unknown exception" << endl; |
326 | + errlog << "PreviewQueryObject::run(): unknown exception"; |
327 | } |
328 | } |
329 | |
330 | |
331 | === modified file 'src/scopes/internal/QueryBaseImpl.cpp' |
332 | --- src/scopes/internal/QueryBaseImpl.cpp 2014-02-27 23:00:59 +0000 |
333 | +++ src/scopes/internal/QueryBaseImpl.cpp 2014-03-06 09:05:05 +0000 |
334 | @@ -17,12 +17,12 @@ |
335 | */ |
336 | |
337 | #include <unity/scopes/internal/QueryBaseImpl.h> |
338 | +#include <unity/scopes/internal/Logging.h> |
339 | |
340 | #include <unity/scopes/QueryCtrl.h> |
341 | #include <unity/scopes/Scope.h> |
342 | #include <unity/scopes/SearchMetadata.h> |
343 | |
344 | -#include <iostream> |
345 | #include <cassert> |
346 | |
347 | using namespace std; |
348 | @@ -105,7 +105,7 @@ |
349 | catch (std::bad_cast const& e) // this shouldn't really happen, if it does, that's a bug |
350 | { |
351 | // TODO: log this |
352 | - std::cerr << "QueryBaseImpl()::set_metadata(): " << e.what() << std::endl; |
353 | + errlog << "QueryBaseImpl()::set_metadata(): " << e.what(); |
354 | throw; |
355 | } |
356 | } |
357 | |
358 | === modified file 'src/scopes/internal/QueryCtrlImpl.cpp' |
359 | --- src/scopes/internal/QueryCtrlImpl.cpp 2014-01-23 11:28:34 +0000 |
360 | +++ src/scopes/internal/QueryCtrlImpl.cpp 2014-03-06 09:05:05 +0000 |
361 | @@ -18,6 +18,7 @@ |
362 | |
363 | #include <unity/scopes/internal/QueryCtrlImpl.h> |
364 | |
365 | +#include <unity/scopes/internal/Logging.h> |
366 | #include <unity/scopes/internal/MiddlewareBase.h> |
367 | #include <unity/scopes/internal/MWQueryCtrl.h> |
368 | #include <unity/scopes/internal/MWReply.h> |
369 | @@ -26,7 +27,6 @@ |
370 | #include <unity/scopes/ScopeExceptions.h> |
371 | |
372 | #include <cassert> |
373 | -#include <iostream> // TODO: remove this once logging is added |
374 | |
375 | using namespace std; |
376 | |
377 | @@ -67,7 +67,7 @@ |
378 | } |
379 | catch (std::exception const& e) |
380 | { |
381 | - cerr << e.what() << endl; |
382 | + errlog << e.what(); |
383 | // TODO: log error |
384 | } |
385 | } |
386 | |
387 | === modified file 'src/scopes/internal/QueryObject.cpp' |
388 | --- src/scopes/internal/QueryObject.cpp 2014-03-04 03:15:11 +0000 |
389 | +++ src/scopes/internal/QueryObject.cpp 2014-03-06 09:05:05 +0000 |
390 | @@ -18,6 +18,7 @@ |
391 | |
392 | #include <unity/scopes/internal/QueryObject.h> |
393 | |
394 | +#include <unity/scopes/internal/Logging.h> |
395 | #include <unity/Exception.h> |
396 | #include <unity/scopes/ActivationQueryBase.h> |
397 | #include <unity/scopes/internal/MWQueryCtrl.h> |
398 | @@ -29,7 +30,6 @@ |
399 | #include <unity/scopes/QueryBase.h> |
400 | #include <unity/scopes/SearchQueryBase.h> |
401 | |
402 | -#include <iostream> |
403 | #include <cassert> |
404 | |
405 | using namespace std; |
406 | @@ -116,14 +116,14 @@ |
407 | pushable_ = false; |
408 | // TODO: log error |
409 | reply_->finished(ListenerBase::Error, e.what()); // Oneway, can't block |
410 | - cerr << "ScopeBase::run(): " << e.what() << endl; |
411 | + errlog << "ScopeBase::run(): " << e.what(); |
412 | } |
413 | catch (...) |
414 | { |
415 | pushable_ = false; |
416 | // TODO: log error |
417 | reply_->finished(ListenerBase::Error, "unknown exception"); // Oneway, can't block |
418 | - cerr << "ScopeBase::run(): unknown exception" << endl; |
419 | + errlog << "ScopeBase::run(): unknown exception"; |
420 | } |
421 | } |
422 | |
423 | |
424 | === modified file 'src/scopes/internal/ReplyImpl.cpp' |
425 | --- src/scopes/internal/ReplyImpl.cpp 2014-03-04 06:26:21 +0000 |
426 | +++ src/scopes/internal/ReplyImpl.cpp 2014-03-06 09:05:05 +0000 |
427 | @@ -16,6 +16,7 @@ |
428 | * Authored by: Michi Henning <michi.henning@canonical.com> |
429 | */ |
430 | |
431 | +#include <unity/scopes/internal/Logging.h> |
432 | #include <unity/scopes/internal/ReplyImpl.h> |
433 | |
434 | #include <unity/scopes/Annotation.h> |
435 | @@ -37,7 +38,7 @@ |
436 | |
437 | #include <cassert> |
438 | #include <sstream> |
439 | -#include <iostream> // TODO: remove this once logging is added |
440 | +#include <cassert> |
441 | |
442 | using namespace std; |
443 | |
444 | @@ -262,7 +263,7 @@ |
445 | catch (std::exception const& e) |
446 | { |
447 | // TODO: log error |
448 | - cerr << e.what() << endl; |
449 | + errlog << e.what(); |
450 | } |
451 | } |
452 | } |
453 | @@ -290,7 +291,7 @@ |
454 | error_message = "unknown exception"; |
455 | } |
456 | // TODO: log error |
457 | - cerr << error_message << endl; |
458 | + errlog << error_message; |
459 | |
460 | try |
461 | { |
462 | @@ -299,7 +300,7 @@ |
463 | catch (std::exception const& e) |
464 | { |
465 | // TODO: log error |
466 | - cerr << e.what() << endl; |
467 | + errlog << e.what(); |
468 | } |
469 | } |
470 | |
471 | |
472 | === modified file 'src/scopes/internal/ReplyObject.cpp' |
473 | --- src/scopes/internal/ReplyObject.cpp 2014-02-24 05:04:11 +0000 |
474 | +++ src/scopes/internal/ReplyObject.cpp 2014-03-06 09:05:05 +0000 |
475 | @@ -16,6 +16,7 @@ |
476 | * Authored by: Michi Henning <michi.henning@canonical.com> |
477 | */ |
478 | |
479 | +#include <unity/scopes/internal/Logging.h> |
480 | #include <unity/scopes/internal/ReplyObject.h> |
481 | #include <unity/scopes/internal/ResultReplyObject.h> |
482 | #include <unity/scopes/internal/PreviewReplyObject.h> |
483 | @@ -27,7 +28,6 @@ |
484 | #include <unity/scopes/internal/CategorisedResultImpl.h> |
485 | |
486 | #include <cassert> |
487 | -#include <iostream> // TODO: remove this once logging is added |
488 | |
489 | using namespace std; |
490 | using namespace unity::scopes::internal; |
491 | @@ -50,8 +50,8 @@ |
492 | assert(receiver_base); |
493 | assert(runtime); |
494 | reap_item_ = runtime->reply_reaper()->add([this] { |
495 | - cerr << "No activity on ReplyObject for scope " << this->origin_proxy_ |
496 | - << ": ReplyObject destroyed" << endl; |
497 | + errlog << "No activity on ReplyObject for scope " << this->origin_proxy_ |
498 | + << ": ReplyObject destroyed"; |
499 | this->disconnect(); |
500 | }); |
501 | } |
502 | @@ -162,12 +162,12 @@ |
503 | } |
504 | catch (std::exception const& e) |
505 | { |
506 | - cerr << "ReplyObject::finished(): " << e.what() << endl; |
507 | + errlog << "ReplyObject::finished(): " << e.what(); |
508 | // TODO: log error |
509 | } |
510 | catch (...) |
511 | { |
512 | - cerr << "ReplyObject::finished(): unknown exception" << endl; |
513 | + errlog << "ReplyObject::finished(): unknown exception"; |
514 | // TODO: log error |
515 | } |
516 | } |
517 | |
518 | === modified file 'src/scopes/internal/RuntimeImpl.cpp' |
519 | --- src/scopes/internal/RuntimeImpl.cpp 2014-02-21 05:12:05 +0000 |
520 | +++ src/scopes/internal/RuntimeImpl.cpp 2014-03-06 09:05:05 +0000 |
521 | @@ -19,6 +19,7 @@ |
522 | #include <unity/scopes/internal/RuntimeImpl.h> |
523 | |
524 | #include <unity/scopes/internal/DfltConfig.h> |
525 | +#include <unity/scopes/internal/Logging.h> |
526 | #include <unity/scopes/internal/RegistryConfig.h> |
527 | #include <unity/scopes/internal/RegistryImpl.h> |
528 | #include <unity/scopes/internal/RuntimeConfig.h> |
529 | @@ -30,7 +31,6 @@ |
530 | |
531 | #include <cassert> |
532 | #include <future> |
533 | -#include <iostream> // TODO: remove this once logging is added |
534 | |
535 | |
536 | using namespace std; |
537 | @@ -72,7 +72,7 @@ |
538 | |
539 | if (registry_configfile_.empty() || registry_identity_.empty()) |
540 | { |
541 | - cerr << "Warning: no registry configured" << endl; |
542 | + errlog << "Warning: no registry configured"; |
543 | registry_identity_ = ""; |
544 | } |
545 | else |
546 | @@ -100,12 +100,12 @@ |
547 | } |
548 | catch (std::exception const& e) // LCOV_EXCL_LINE |
549 | { |
550 | - cerr << "~RuntimeImpl(): " << e.what() << endl; |
551 | + errlog << "~RuntimeImpl(): " << e.what(); |
552 | // TODO: log error |
553 | } |
554 | catch (...) // LCOV_EXCL_LINE |
555 | { |
556 | - cerr << "~RuntimeImpl(): unknown exception" << endl; |
557 | + errlog << "~RuntimeImpl(): unknown exception"; |
558 | // TODO: log error |
559 | } |
560 | } |
561 | |
562 | === modified file 'src/scopes/internal/ScopeImpl.cpp' |
563 | --- src/scopes/internal/ScopeImpl.cpp 2014-02-27 23:00:59 +0000 |
564 | +++ src/scopes/internal/ScopeImpl.cpp 2014-03-06 09:05:05 +0000 |
565 | @@ -18,6 +18,7 @@ |
566 | |
567 | #include <unity/scopes/internal/ScopeImpl.h> |
568 | |
569 | +#include <unity/scopes/internal/Logging.h> |
570 | #include <unity/scopes/internal/ResultImpl.h> |
571 | #include <unity/scopes/internal/MiddlewareBase.h> |
572 | #include <unity/scopes/internal/MWScope.h> |
573 | @@ -33,7 +34,6 @@ |
574 | #include <unity/scopes/internal/PreviewReplyObject.h> |
575 | |
576 | #include <cassert> |
577 | -#include <iostream> // TODO: remove this once logging is added |
578 | |
579 | using namespace std; |
580 | |
581 | @@ -134,7 +134,7 @@ |
582 | catch (std::exception const& e) |
583 | { |
584 | // TODO: log error |
585 | - cerr << "activate(): " << e.what() << endl; |
586 | + errlog << "activate(): " << e.what(); |
587 | try |
588 | { |
589 | ro->finished(ListenerBase::Error, e.what()); |
590 | @@ -142,7 +142,7 @@ |
591 | } |
592 | catch (...) |
593 | { |
594 | - cerr << "activate(): unknown exception" << endl; |
595 | + errlog << "activate(): unknown exception"; |
596 | } |
597 | throw; |
598 | } |
599 | @@ -172,7 +172,7 @@ |
600 | catch (std::exception const& e) |
601 | { |
602 | // TODO: log error |
603 | - cerr << "perform_action(): " << e.what() << endl; |
604 | + errlog << "perform_action(): " << e.what(); |
605 | try |
606 | { |
607 | // TODO: if things go wrong, we need to make sure that the reply object |
608 | @@ -182,7 +182,7 @@ |
609 | } |
610 | catch (...) |
611 | { |
612 | - cerr << "perform_action(): unknown exception" << endl; |
613 | + errlog << "perform_action(): unknown exception"; |
614 | } |
615 | throw; |
616 | } |
617 | @@ -216,7 +216,7 @@ |
618 | catch (std::exception const& e) |
619 | { |
620 | // TODO: log error |
621 | - cerr << "preview(): " << e.what() << endl; |
622 | + errlog << "preview(): " << e.what(); |
623 | try |
624 | { |
625 | ro->finished(ListenerBase::Error, e.what()); |
626 | @@ -224,7 +224,7 @@ |
627 | } |
628 | catch (...) |
629 | { |
630 | - cerr << "preview(): unknown exception" << endl; |
631 | + errlog << "preview(): unknown exception"; |
632 | } |
633 | throw; |
634 | } |
635 | |
636 | === modified file 'src/scopes/internal/ScopeObject.cpp' |
637 | --- src/scopes/internal/ScopeObject.cpp 2014-02-27 23:29:10 +0000 |
638 | +++ src/scopes/internal/ScopeObject.cpp 2014-03-06 09:05:05 +0000 |
639 | @@ -19,6 +19,7 @@ |
640 | #include <unity/scopes/internal/ScopeObject.h> |
641 | |
642 | #include <unity/scopes/internal/ActivationQueryObject.h> |
643 | +#include <unity/scopes/internal/Logging.h> |
644 | #include <unity/scopes/internal/MWQuery.h> |
645 | #include <unity/scopes/internal/MWReply.h> |
646 | #include <unity/scopes/internal/PreviewQueryObject.h> |
647 | @@ -29,7 +30,6 @@ |
648 | #include <unity/UnityExceptions.h> |
649 | |
650 | #include <cassert> |
651 | -#include <iostream> // TODO: remove this once logging is added |
652 | #include <sstream> |
653 | |
654 | using namespace std; |
655 | @@ -122,7 +122,7 @@ |
656 | catch (...) |
657 | { |
658 | } |
659 | - cerr << "query(): " << e.what() << endl; |
660 | + errlog << "query(): " << e.what(); |
661 | // TODO: log error |
662 | throw; |
663 | } |
664 | @@ -135,7 +135,7 @@ |
665 | catch (...) |
666 | { |
667 | } |
668 | - cerr << "query(): unknown exception" << endl; |
669 | + errlog << "query(): unknown exception"; |
670 | // TODO: log error |
671 | throw; |
672 | } |
673 | |
674 | === modified file 'test/gtest/scopes/internal/CMakeLists.txt' |
675 | --- test/gtest/scopes/internal/CMakeLists.txt 2014-02-24 14:56:26 +0000 |
676 | +++ test/gtest/scopes/internal/CMakeLists.txt 2014-03-06 09:05:05 +0000 |
677 | @@ -3,6 +3,7 @@ |
678 | add_subdirectory(DynamicLoader) |
679 | add_subdirectory(JsonNode) |
680 | add_subdirectory(lttng) |
681 | +add_subdirectory(Logging) |
682 | add_subdirectory(MiddlewareFactory) |
683 | add_subdirectory(Reaper) |
684 | add_subdirectory(RegistryConfig) |
685 | |
686 | === added directory 'test/gtest/scopes/internal/Logging' |
687 | === added file 'test/gtest/scopes/internal/Logging/CMakeLists.txt' |
688 | --- test/gtest/scopes/internal/Logging/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
689 | +++ test/gtest/scopes/internal/Logging/CMakeLists.txt 2014-03-06 09:05:05 +0000 |
690 | @@ -0,0 +1,14 @@ |
691 | +add_executable( |
692 | + Logging_test |
693 | + Logging_test.cpp |
694 | +) |
695 | + |
696 | +target_link_libraries( |
697 | + Logging_test |
698 | + ${TESTLIBS} |
699 | +) |
700 | + |
701 | +add_test( |
702 | + Logging |
703 | + Logging_test |
704 | +) |
705 | |
706 | === added file 'test/gtest/scopes/internal/Logging/Logging_test.cpp' |
707 | --- test/gtest/scopes/internal/Logging/Logging_test.cpp 1970-01-01 00:00:00 +0000 |
708 | +++ test/gtest/scopes/internal/Logging/Logging_test.cpp 2014-03-06 09:05:05 +0000 |
709 | @@ -0,0 +1,53 @@ |
710 | +/* |
711 | + * Copyright © 2014 Canonical Ltd. |
712 | + * |
713 | + * This program is free software: you can redistribute it and/or modify it |
714 | + * under the terms of the GNU Lesser General Public License version 3, |
715 | + * as published by the Free Software Foundation. |
716 | + * |
717 | + * This program is distributed in the hope that it will be useful, |
718 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
719 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
720 | + * GNU Lesser General Public License for more details. |
721 | + * |
722 | + * You should have received a copy of the GNU Lesser General Public License |
723 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
724 | + * |
725 | + * Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com> |
726 | + */ |
727 | + |
728 | +#include <unity/scopes/internal/Logging.h> |
729 | +#include <unity/UnityExceptions.h> |
730 | +#include <unity/scopes/Variant.h> |
731 | + |
732 | +#include <gtest/gtest.h> |
733 | +#include <memory> |
734 | +#include <algorithm> |
735 | + |
736 | +using namespace testing; |
737 | +using unity::scopes::internal::errlog; |
738 | + |
739 | +namespace |
740 | +{ |
741 | + |
742 | +class LoggingTest : public Test |
743 | +{ |
744 | +public: |
745 | + LoggingTest() |
746 | + { |
747 | + } |
748 | + |
749 | +}; |
750 | + |
751 | +TEST_F(LoggingTest, basic) |
752 | +{ |
753 | + std::string msg("Second message to stderr."); |
754 | + errlog << "First message to stderr."; |
755 | + errlog << msg; |
756 | + errlog << "Piecewise " << "message " << "to stderr.\n"; |
757 | + errlog << 1 << " is the loneliest number. Not " << 2 << ".\n"; |
758 | + errlog << "True is " << true << " and False is " << false << "."; |
759 | +} |
760 | + |
761 | + |
762 | +} // namespace |
FAILED: Continuous integration, rev:258 jenkins. qa.ubuntu. com/job/ unity-scopes- api-devel- ci/224/ jenkins. qa.ubuntu. com/job/ unity-scopes- api-devel- trusty- amd64-ci/ 225/console jenkins. qa.ubuntu. com/job/ unity-scopes- api-devel- trusty- armhf-ci/ 224/console jenkins. qa.ubuntu. com/job/ unity-scopes- api-devel- trusty- i386-ci/ 224/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- scopes- api-devel- ci/224/ rebuild
http://