Merge lp:~pete-woods/unity-action-api/automatic-quit-action into lp:unity-action-api
- automatic-quit-action
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Antti Kaijanmäki | ||||
Approved revision: | 40 | ||||
Merged at revision: | 32 | ||||
Proposed branch: | lp:~pete-woods/unity-action-api/automatic-quit-action | ||||
Merge into: | lp:unity-action-api | ||||
Diff against target: |
484 lines (+217/-24) 9 files modified
CMakeLists.txt (+5/-0) debian/changelog (+7/-0) include/unity/action/unity-action-manager.h (+2/-0) qml/Ubuntu/Unity/Action/plugin.cpp (+7/-1) src/CMakeLists.txt (+1/-1) src/unity-action-manager.cpp (+59/-7) test/cpp/tst_actionmanager.cpp (+14/-14) test/qml/CMakeLists.txt (+14/-1) test/qml/tst_api1.1.qml (+108/-0) |
||||
To merge this branch: | bzr merge lp:~pete-woods/unity-action-api/automatic-quit-action | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Antti Kaijanmäki (community) | Approve | ||
Review via email: mp+202653@code.launchpad.net |
Commit message
Add automatic quit action to HUD toolbar
Description of the change
Add automatic quit action to HUD toolbar
- 34. By Pete Woods
-
Increment minor version number for QML action manager
PS Jenkins bot (ps-jenkins) wrote : | # |
- 35. By Pete Woods
-
Add extra check target that prints the log on fail
- 36. By Pete Woods
-
Make the CPP tests pass
- 37. By Pete Woods
-
Make the QML tests pass
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:37
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 38. By Pete Woods
-
Handle global actions with specialisation
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:38
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 39. By Pete Woods
-
Rename the _quit() signal to quit()
- 40. By Pete Woods
-
Missed the test case!
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:39
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:40
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2013-07-11 23:17:56 +0000 |
3 | +++ CMakeLists.txt 2014-01-30 13:56:31 +0000 |
4 | @@ -130,6 +130,11 @@ |
5 | if(${ENABLE_TESTING}) |
6 | enable_testing() |
7 | add_subdirectory(test) |
8 | + |
9 | + ADD_CUSTOM_TARGET( |
10 | + check |
11 | + ${CMAKE_CTEST_COMMAND} --force-new-ctest-process --output-on-failure |
12 | + ) |
13 | endif() |
14 | |
15 | include(EnableCoverageReport) |
16 | |
17 | === modified file 'debian/changelog' |
18 | --- debian/changelog 2013-07-16 08:42:31 +0000 |
19 | +++ debian/changelog 2014-01-30 13:56:31 +0000 |
20 | @@ -1,3 +1,10 @@ |
21 | +unity-action-api (1.1.0-0ubuntu1) UNRELEASED; urgency=medium |
22 | + |
23 | + [ Pete Woods ] |
24 | + * Add automatic quit action to HUD toolbar. |
25 | + |
26 | + -- Pete Woods <pete.woods@canonical.com> Wed, 22 Jan 2014 10:50:34 +0000 |
27 | + |
28 | unity-action-api (1.0.0+13.10.20130716-0ubuntu1) saucy; urgency=low |
29 | |
30 | [ Antti Kaijanmäki ] |
31 | |
32 | === modified file 'include/unity/action/unity-action-manager.h' |
33 | --- include/unity/action/unity-action-manager.h 2013-07-11 13:57:36 +0000 |
34 | +++ include/unity/action/unity-action-manager.h 2014-01-30 13:56:31 +0000 |
35 | @@ -57,6 +57,8 @@ |
36 | void localContextsChanged(); |
37 | void actionsChanged(); |
38 | |
39 | + Q_REVISION(1) void quit(); |
40 | + |
41 | private: |
42 | class Private; |
43 | QScopedPointer<Private> d; |
44 | |
45 | === modified file 'qml/Ubuntu/Unity/Action/plugin.cpp' |
46 | --- qml/Ubuntu/Unity/Action/plugin.cpp 2013-07-12 12:55:39 +0000 |
47 | +++ qml/Ubuntu/Unity/Action/plugin.cpp 2014-01-30 13:56:31 +0000 |
48 | @@ -34,19 +34,25 @@ |
49 | |
50 | qmlRegisterType<unity::action::Action> (); |
51 | qmlRegisterType<unity::action::qml::Action> (uri, 1, 0, "Action"); |
52 | + qmlRegisterType<unity::action::qml::Action> (uri, 1, 1, "Action"); |
53 | qmlRegisterType<unity::action::PreviewAction> (); |
54 | qmlRegisterType<unity::action::qml::PreviewAction> (uri, 1, 0, "PreviewAction"); |
55 | + qmlRegisterType<unity::action::qml::PreviewAction> (uri, 1, 1, "PreviewAction"); |
56 | |
57 | qmlRegisterType<unity::action::PreviewParameter> (); |
58 | qmlRegisterType<unity::action::PreviewRangeParameter> (uri, 1, 0, "PreviewRangeParameter"); |
59 | + qmlRegisterType<unity::action::PreviewRangeParameter> (uri, 1, 1, "PreviewRangeParameter"); |
60 | |
61 | // Don't provide menu item just yet. |
62 | //qmlRegisterType<unity::action::MenuItem> (uri, 1, 0, "MenuItem"); |
63 | |
64 | qmlRegisterType<unity::action::ActionContext> (); |
65 | qmlRegisterType<unity::action::qml::ActionContext> (uri, 1, 0, "ActionContext"); |
66 | - qmlRegisterType<unity::action::ActionManager> (); |
67 | + qmlRegisterType<unity::action::qml::ActionContext> (uri, 1, 1, "ActionContext"); |
68 | + qmlRegisterType<unity::action::ActionManager> (uri, 1, 0, ""); |
69 | + qmlRegisterType<unity::action::ActionManager, 1> (uri, 1, 1, ""); |
70 | qmlRegisterType<unity::action::qml::ActionManager> (uri, 1, 0, "ActionManager"); |
71 | + qmlRegisterType<unity::action::qml::ActionManager, 1> (uri, 1, 1, "ActionManager"); |
72 | |
73 | } |
74 | |
75 | |
76 | === modified file 'src/CMakeLists.txt' |
77 | --- src/CMakeLists.txt 2013-07-15 15:24:36 +0000 |
78 | +++ src/CMakeLists.txt 2014-01-30 13:56:31 +0000 |
79 | @@ -47,7 +47,7 @@ |
80 | |
81 | |
82 | set(API_VERSION_MAJOR 1) |
83 | -set(API_VERSION_MINOR 0) |
84 | +set(API_VERSION_MINOR 1) |
85 | |
86 | set(SO_VERSION ${API_VERSION_MAJOR}) |
87 | |
88 | |
89 | === modified file 'src/unity-action-manager.cpp' |
90 | --- src/unity-action-manager.cpp 2013-07-15 18:06:26 +0000 |
91 | +++ src/unity-action-manager.cpp 2014-01-30 13:56:31 +0000 |
92 | @@ -22,6 +22,9 @@ |
93 | |
94 | #include <QSet> |
95 | #include <QDebug> |
96 | +#include <QCoreApplication> |
97 | + |
98 | +#include <libintl.h> |
99 | |
100 | // needed for gio includes. |
101 | #undef signals |
102 | @@ -198,6 +201,33 @@ |
103 | a.desc == b.desc; |
104 | } |
105 | |
106 | +namespace { |
107 | +class QuitAction: public Action { |
108 | + Q_OBJECT |
109 | +}; |
110 | + |
111 | +class GlobalActionContext: public ActionContext { |
112 | +public: |
113 | + GlobalActionContext(QObject *parent = 0) : |
114 | + ActionContext(parent) { |
115 | + } |
116 | + |
117 | + void addBuiltInAction(Action *action) { |
118 | + built_in_actions << action; |
119 | + } |
120 | + |
121 | + QSet<Action *> allActions() { |
122 | + return actions() + built_in_actions; |
123 | + } |
124 | +private: |
125 | + QSet<Action *> built_in_actions; |
126 | +}; |
127 | + |
128 | +static inline char * _(const char *__msgid) { |
129 | + return gettext(__msgid); |
130 | +} |
131 | +} |
132 | + |
133 | //! \private |
134 | class Q_DECL_HIDDEN unity::action::ActionManager::Private : public QObject |
135 | { |
136 | @@ -208,9 +238,11 @@ |
137 | |
138 | QSet<Action *> actions; |
139 | |
140 | - ActionContext *globalContext; |
141 | + GlobalActionContext *globalContext; |
142 | QSet<ActionContext *> localContexts; |
143 | |
144 | + QScopedPointer<Action> quitAction; |
145 | + |
146 | ActionContext *activeLocalContext; |
147 | |
148 | QHash<ActionContext *, ContextData> contextData; |
149 | @@ -225,7 +257,7 @@ |
150 | Private(ActionManager *mgr) |
151 | : q(mgr) |
152 | { |
153 | - globalContext = new ActionContext(); |
154 | + globalContext = new GlobalActionContext(); |
155 | hudManager = 0; |
156 | } |
157 | ~Private() { |
158 | @@ -337,7 +369,14 @@ |
159 | |
160 | d->actionGroup = g_simple_action_group_new(); |
161 | |
162 | + d->quitAction.reset(new QuitAction()); |
163 | + d->quitAction->setText(_("Quit")); |
164 | + d->quitAction->setDescription(_("Quit the application")); |
165 | + d->quitAction->setKeywords(_("Exit;Close")); |
166 | + connect(d->quitAction.data(), SIGNAL(triggered(QVariant)), this, SIGNAL(quit())); |
167 | + |
168 | d->createContext(d->globalContext); |
169 | + d->globalContext->addBuiltInAction(d->quitAction.data()); |
170 | d->updateContext(d->globalContext); |
171 | hud_manager_switch_window_context(d->hudManager, |
172 | d->contextData[d->globalContext].publisher); |
173 | @@ -631,7 +670,7 @@ |
174 | // current actions in global context and |
175 | // in the active local context |
176 | |
177 | - QSet<Action *> globalActions = globalContext->actions(); |
178 | + QSet<Action *> globalActions = globalContext->allActions(); |
179 | QSet<Action *> localActions; |
180 | if (activeLocalContext) |
181 | localActions = activeLocalContext->actions(); |
182 | @@ -704,7 +743,12 @@ |
183 | ContextData &cdata = contextData[context]; |
184 | |
185 | QSet<Action *> oldActions = cdata.actions; |
186 | - QSet<Action *> currentActions = context->actions(); |
187 | + QSet<Action *> currentActions; |
188 | + if(context == globalContext) { |
189 | + currentActions = globalContext->allActions(); |
190 | + } else { |
191 | + currentActions = context->actions(); |
192 | + } |
193 | QSet<Action *> removedActions = oldActions - currentActions; |
194 | |
195 | foreach (Action *action, currentActions) { |
196 | @@ -774,7 +818,7 @@ |
197 | const ContextData &cdata = contextData[context]; |
198 | |
199 | |
200 | - QSet<Action *> currentActions = context->actions() + globalContext->actions(); |
201 | + QSet<Action *> currentActions = context->actions() + globalContext->allActions(); |
202 | QSet<Action *> newActions = currentActions - oldActions; |
203 | QSet<Action *> removedActions = oldActions - currentActions; |
204 | |
205 | @@ -821,8 +865,9 @@ |
206 | << "\tin the client code. "; |
207 | globalContext->disconnect(this); |
208 | destroyContext(globalContext); |
209 | - globalContext = new ActionContext(); |
210 | + globalContext = new GlobalActionContext(); |
211 | createContext(globalContext); |
212 | + globalContext->addBuiltInAction(quitAction.data()); |
213 | updateContext(globalContext); |
214 | connect(globalContext, SIGNAL(actionsChanged()), this, SLOT(contextActionsChanged())); |
215 | connect(globalContext, SIGNAL(activeChanged(bool)), this, SLOT(contextActiveChanged(bool))); |
216 | @@ -1022,6 +1067,13 @@ |
217 | "commitLabel", |
218 | g_variant_new_string(qPrintable(previewAction->commitLabel()))); |
219 | } |
220 | + |
221 | + QuitAction *quitAction = qobject_cast<QuitAction *>(action); |
222 | + if (quitAction != 0) { |
223 | + hud_action_description_set_attribute_value(desc, |
224 | + "hud-toolbar-item", |
225 | + g_variant_new_string("quit")); |
226 | + } |
227 | } |
228 | |
229 | void |
230 | @@ -1038,7 +1090,7 @@ |
231 | g_signal_handlers_disconnect_by_data(G_OBJECT(adata.gaction), action); |
232 | g_clear_object(&adata.gaction); |
233 | adata.gaction = (GSimpleAction *)g_object_ref(tmpdata.gaction); |
234 | - if (globalContext->actions().contains(action) || |
235 | + if (globalContext->allActions().contains(action) || |
236 | (activeLocalContext != 0 && activeLocalContext->actions().contains(action))) { |
237 | updateActionGroup(); |
238 | } |
239 | |
240 | === modified file 'test/cpp/tst_actionmanager.cpp' |
241 | --- test/cpp/tst_actionmanager.cpp 2013-07-09 10:38:33 +0000 |
242 | +++ test/cpp/tst_actionmanager.cpp 2014-01-30 13:56:31 +0000 |
243 | @@ -59,8 +59,8 @@ |
244 | TestActionManager::cleanup() |
245 | { |
246 | // after each test make sure the manager is left in a clean state |
247 | - Q_ASSERT(manager->actions().isEmpty()); |
248 | - Q_ASSERT(manager->localContexts().isEmpty()); |
249 | + QVERIFY(manager->actions().count() == 1); |
250 | + QVERIFY(manager->localContexts().isEmpty()); |
251 | } |
252 | |
253 | |
254 | @@ -168,7 +168,7 @@ |
255 | manager->removeLocalContext(ctx1); |
256 | manager->removeLocalContext(ctx2); |
257 | manager->removeLocalContext(ctx3); |
258 | - QVERIFY(manager->actions().count() == 0); |
259 | + QVERIFY(manager->actions().count() == 1); |
260 | } |
261 | |
262 | void |
263 | @@ -345,27 +345,27 @@ |
264 | manager->addLocalContext(ctx2); |
265 | |
266 | QSignalSpy spy(manager, SIGNAL(actionsChanged())); |
267 | - QCOMPARE(manager->actions().count(), 5); |
268 | + QCOMPARE(manager->actions().count(), 6); |
269 | |
270 | // delete action1 directly from globalContext |
271 | delete action1; |
272 | QCOMPARE(spy.count(), 1); |
273 | QVERIFY(!manager->actions().contains(action1)); |
274 | - QCOMPARE(manager->actions().count(), 4); |
275 | + QCOMPARE(manager->actions().count(), 5); |
276 | action1 = 0; |
277 | |
278 | // delete action2 directly from ctx1 |
279 | delete action2; |
280 | QCOMPARE(spy.count(), 2); |
281 | QVERIFY(!manager->actions().contains(action2)); |
282 | - QCOMPARE(manager->actions().count(), 3); |
283 | + QCOMPARE(manager->actions().count(), 4); |
284 | action2 = 0; |
285 | |
286 | // remove action3 indirectly by destroying ctx1 |
287 | delete ctx1; |
288 | QCOMPARE(spy.count(), 3); |
289 | QVERIFY(!manager->actions().contains(action3)); |
290 | - QCOMPARE(manager->actions().count(), 2); |
291 | + QCOMPARE(manager->actions().count(), 3); |
292 | ctx1 = 0; |
293 | action3 = 0; |
294 | |
295 | @@ -374,7 +374,7 @@ |
296 | QCOMPARE(spy.count(), 5); // actionsChanged() gets called multiple times (once per each action in a context) |
297 | QVERIFY(!manager->actions().contains(action4)); |
298 | QVERIFY(!manager->actions().contains(action5)); |
299 | - QCOMPARE(manager->actions().count(), 0); |
300 | + QCOMPARE(manager->actions().count(), 1); |
301 | QVERIFY(manager->localContexts().isEmpty()); |
302 | ctx2 = 0; |
303 | action4 = 0; |
304 | @@ -413,32 +413,32 @@ |
305 | |
306 | // 3 actions have been added in total |
307 | QCOMPARE(spy.count(), 3); |
308 | - QCOMPARE(manager->actions().count(), 3); |
309 | + QCOMPARE(manager->actions().count(), 4); |
310 | |
311 | spy.clear(); |
312 | manager->removeLocalContext(ctx2); // removes only action3, action1 is shared. |
313 | QCOMPARE(spy.count(), 1); |
314 | - QCOMPARE(manager->actions().count(), 2); |
315 | + QCOMPARE(manager->actions().count(), 3); |
316 | // and now add it back |
317 | manager->addLocalContext(ctx2); |
318 | QCOMPARE(spy.count(), 2); |
319 | - QCOMPARE(manager->actions().count(), 3); |
320 | + QCOMPARE(manager->actions().count(), 4); |
321 | |
322 | spy.clear(); |
323 | gctx->removeAction(action1); |
324 | QCOMPARE(spy.count(), 0); |
325 | - QCOMPARE(manager->actions().count(), 3); |
326 | + QCOMPARE(manager->actions().count(), 4); |
327 | QVERIFY(manager->actions().contains(action1)); |
328 | |
329 | ctx1->removeAction(action1); |
330 | QCOMPARE(spy.count(), 0); |
331 | - QCOMPARE(manager->actions().count(), 3); |
332 | + QCOMPARE(manager->actions().count(), 4); |
333 | QVERIFY(manager->actions().contains(action1)); |
334 | |
335 | // remove the action from the last context |
336 | ctx2->removeAction(action1); |
337 | QCOMPARE(spy.count(), 1); |
338 | - QCOMPARE(manager->actions().count(), 2); |
339 | + QCOMPARE(manager->actions().count(), 3); |
340 | QVERIFY(!manager->actions().contains(action1)); |
341 | |
342 | manager->removeLocalContext(ctx1); |
343 | |
344 | === modified file 'test/qml/CMakeLists.txt' |
345 | --- test/qml/CMakeLists.txt 2013-06-18 09:48:41 +0000 |
346 | +++ test/qml/CMakeLists.txt 2014-01-30 13:56:31 +0000 |
347 | @@ -1,4 +1,5 @@ |
348 | add_custom_target(qmlunittests) |
349 | +add_custom_target(qmlunittests_1_1) |
350 | |
351 | find_program(qmltestrunner_exe qmltestrunner) |
352 | |
353 | @@ -16,4 +17,16 @@ |
354 | |
355 | add_custom_target(qmltest_api ${qmltest_command}) |
356 | add_dependencies(qmlunittests qmltest_api) |
357 | -add_test(qmlunittests ${qmltest_command}) |
358 | \ No newline at end of file |
359 | +add_test(qmlunittests ${qmltest_command}) |
360 | + |
361 | +set(qmltest1_1_command |
362 | + dbus-test-runner -t env -p "QT_QPA_PLATFORM=minimal" |
363 | + -p ${qmltestrunner_exe} -p -input -p ${CMAKE_CURRENT_SOURCE_DIR}/tst_api1.1.qml |
364 | + -p -import -p ${CMAKE_CURRENT_BINARY_DIR}/../../qml |
365 | + -p -o -p ${CMAKE_BINARY_DIR}/testapi.xml,xunitxml |
366 | + -p -o -p -,txt |
367 | +) |
368 | + |
369 | +add_custom_target(qmltest_1_1_api ${qmltest1_1_command}) |
370 | +add_dependencies(qmlunittests_1_1 qmltest_1_1_api) |
371 | +add_test(qmlunittests_1_1 ${qmltest1_1_command}) |
372 | |
373 | === added file 'test/qml/tst_api1.1.qml' |
374 | --- test/qml/tst_api1.1.qml 1970-01-01 00:00:00 +0000 |
375 | +++ test/qml/tst_api1.1.qml 2014-01-30 13:56:31 +0000 |
376 | @@ -0,0 +1,108 @@ |
377 | +/* This file is part of unity-action-api |
378 | + * Copyright 2013 Canonical Ltd. |
379 | + * |
380 | + * unity-action-api is free software: you can redistribute it and/or modify it |
381 | + * under the terms of the GNU Lesser General Public License version 3, |
382 | + * as published by the Free Software Foundation. |
383 | + * |
384 | + * unity-action-api is distributed in the hope that it will be useful, but |
385 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
386 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
387 | + * PURPOSE. See the GNU Lesser General Public License for more details. |
388 | + * |
389 | + * You should have received a copy of the GNU Lesser General Public License |
390 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
391 | + */ |
392 | + |
393 | +import Ubuntu.Unity.Action 1.1 |
394 | +import QtQuick 2.0 |
395 | +import QtTest 1.0 |
396 | + |
397 | +/* This test will make sure there are no unintentional changes to the |
398 | + * schemantics of the API (default properties work as expected, etc) |
399 | + * so that any files written to the prior release of the library |
400 | + * will not bail out when loaded resulting in client applications failing |
401 | + * to start. |
402 | + */ |
403 | +Item { |
404 | + |
405 | + ActionManager { |
406 | + id: manager |
407 | + |
408 | + localContexts: [ctx1, ctx2] |
409 | + |
410 | + onQuit: {} |
411 | + |
412 | + Action { |
413 | + id: globalaction |
414 | + name: "NewMessage" |
415 | + text: "Write New Message" |
416 | + iconName: "email-new-message" |
417 | + description: "Write a new Message" |
418 | + keywords: "Compose;Send" |
419 | + enabled: true |
420 | + parameterType: Action.String |
421 | + onTriggered: {} |
422 | + } |
423 | + } |
424 | + |
425 | + ActionContext { |
426 | + id: ctx1 |
427 | + |
428 | + Action { |
429 | + id: myaction1 |
430 | + text: "Foo" |
431 | + onTriggered: {} |
432 | + } |
433 | + } |
434 | + |
435 | + ActionContext { |
436 | + id: ctx2 |
437 | + |
438 | + PreviewAction { |
439 | + id: previewaction |
440 | + text: "Color Balance" |
441 | + commitLabel: "Apply" |
442 | + |
443 | + onStarted: {} |
444 | + onResetted: {} |
445 | + onCancelled: {} |
446 | + onTriggered: {} |
447 | + |
448 | + PreviewRangeParameter { |
449 | + text: "lorem ipsum" |
450 | + value: 0 |
451 | + minimumValue: -100 |
452 | + maximumValue: 100 |
453 | + onValueChanged: {} |
454 | + } |
455 | + } |
456 | + } |
457 | + |
458 | + |
459 | +/* |
460 | + MenuItem { |
461 | + action: myaction1 |
462 | + text: "New Message" |
463 | + iconName: "menu-new-message" |
464 | + target: "user@corporation.tld" |
465 | + visible: true |
466 | + enabled: false |
467 | + } |
468 | +*/ |
469 | + |
470 | + Component.onCompleted: { |
471 | + ctx2.active = true |
472 | + } |
473 | + |
474 | + |
475 | + TestCase { |
476 | + name: "API Test" |
477 | + id: test_api |
478 | + |
479 | + function test_api() { |
480 | + // just make sure this file can be loaded properly by the QmlEngine. |
481 | + verify(1) |
482 | + } |
483 | + } |
484 | +} |
FAILED: Continuous integration, rev:34 jenkins. qa.ubuntu. com/job/ unity-action- api-ci/ 46/ jenkins. qa.ubuntu. com/job/ unity-action- api-trusty- amd64-ci/ 2/console jenkins. qa.ubuntu. com/job/ unity-action- api-trusty- armhf-ci/ 2/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- action- api-ci/ 46/rebuild
http://