Merge lp:~charlesk/indicator-display/adbd-client-test-failure into lp:indicator-display
- adbd-client-test-failure
- Merge into trunk.16.10
Status: | Merged |
---|---|
Approved by: | dobey |
Approved revision: | 40 |
Merged at revision: | 21 |
Proposed branch: | lp:~charlesk/indicator-display/adbd-client-test-failure |
Merge into: | lp:indicator-display |
Diff against target: |
1012 lines (+474/-170) 14 files modified
src/adbd-client.cpp (+16/-9) src/greeter.cpp (+132/-82) src/greeter.h (+8/-2) src/usb-manager.cpp (+65/-48) src/usb-snap.cpp (+1/-0) tests/integration/usb-manager-test.cpp (+11/-5) tests/unit/CMakeLists.txt (+5/-0) tests/unit/adbd-client-test.cpp (+3/-2) tests/unit/greeter-test.cpp (+159/-0) tests/unit/usb-snap-test.cpp (+4/-9) tests/utils/adbd-server.h (+9/-11) tests/utils/gtest-print-helpers.h (+18/-0) tests/utils/mock-greeter.h (+2/-2) tests/utils/mock-unity-greeter.py (+41/-0) |
To merge this branch: | bzr merge lp:~charlesk/indicator-display/adbd-client-test-failure |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
dobey (community) | Approve | ||
unity-api-1-bot | continuous-integration | Approve | |
Review via email: mp+306399@code.launchpad.net |
Commit message
Fix test error in adbd-client-test
Description of the change
1. port Greeter communication bugfix from 15.04 branch
2. adbd-client thread improvements:
- use a std::atomic for m_pkresponse_ready
- check for thread.joinable() before calling thread.join()
- remove pessimization of getting mutex lock before calling condition variable.
unity-api-1-bot (unity-api-1-bot) wrote : | # |
- 21. By Charles Kerr
-
in PKIdleData, take the std::string argument as a const& to make cppcheck happy on yakkety
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 22. By Charles Kerr
-
in adbd-client's dtor, check the worker thread's joinable() state before calling join() on it
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:21
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:22
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 23. By Charles Kerr
-
adbd-client's std::condition_
variable: :wait() call seems to be the system_error culprit, so wrapping in try-catch to be cautious
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:23
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 24. By Charles Kerr
-
add a plethora of log statements to help figure out what's causing the silo test failures
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:24
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 25. By Charles Kerr
-
GAdbdClient:
:Impl:: on_public_ key_response( ) doesn't need a condition variable wait, so use std::lock_guard rather than std::unique_lock
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:25
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 26. By Charles Kerr
-
fix r25 copypaste error, lock on the correct mutex
- 27. By Charles Kerr
-
The notifying thread does not need to hold the lock on the same mutex as the one held by the waiting thread(s); in fact doing so is a pessimization.
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:27
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 28. By Charles Kerr
-
more g_debug() tracers
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:28
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 29. By Charles Kerr
-
in AdbdClientDest, explicitly disconnect the core::Signals at the end of the test
- 30. By Charles Kerr
-
in AdbdClientTest, raise the test timeout interval from 2s to 5s
- 31. By Charles Kerr
-
in UsbSnapTest, explicitly disconnect the core::Signals at the end of the test
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:31
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 32. By Charles Kerr
-
more g_debug() tracers
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:32
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 33. By Charles Kerr
-
tweak the debug tracers
- 34. By Charles Kerr
-
keep piling 'em on
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:34
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 35. By Charles Kerr
-
sync with lp:~charlesk/indicator-display/lp-1572545-prompt-in-lockscreen
- 36. By Charles Kerr
-
fix tyop
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:35
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:36
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 37. By Charles Kerr
-
use a std::atomic for adbd-client's m_pkresponse_ready
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:37
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 38. By Charles Kerr
-
remove the temporary tracers from r34 and r35
- 39. By Charles Kerr
-
remove dead code
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:39
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
dobey (dobey) wrote : | # |
Generally looks OK to me, but I noticed many uses of if or if/else without curly braces around a single result statement. I think it'd be better to use braces or convert these statements to the ternary operator.
- 40. By Charles Kerr
-
add block braces as suggested by dobey
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:40
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | === modified file 'src/adbd-client.cpp' | |||
2 | --- src/adbd-client.cpp 2016-03-24 16:01:16 +0000 | |||
3 | +++ src/adbd-client.cpp 2016-10-21 11:40:57 +0000 | |||
4 | @@ -23,6 +23,7 @@ | |||
5 | 23 | #include <gio/gunixsocketaddress.h> | 23 | #include <gio/gunixsocketaddress.h> |
6 | 24 | 24 | ||
7 | 25 | #include <algorithm> | 25 | #include <algorithm> |
8 | 26 | #include <atomic> | ||
9 | 26 | #include <cctype> | 27 | #include <cctype> |
10 | 27 | #include <cstring> | 28 | #include <cstring> |
11 | 28 | #include <chrono> | 29 | #include <chrono> |
12 | @@ -48,7 +49,9 @@ | |||
13 | 48 | g_cancellable_cancel(m_cancellable); | 49 | g_cancellable_cancel(m_cancellable); |
14 | 49 | m_pkresponse_cv.notify_one(); | 50 | m_pkresponse_cv.notify_one(); |
15 | 50 | m_sleep_cv.notify_one(); | 51 | m_sleep_cv.notify_one(); |
17 | 51 | m_worker_thread.join(); | 52 | if (m_worker_thread.joinable()) { |
18 | 53 | m_worker_thread.join(); | ||
19 | 54 | } | ||
20 | 52 | g_clear_object(&m_cancellable); | 55 | g_clear_object(&m_cancellable); |
21 | 53 | } | 56 | } |
22 | 54 | 57 | ||
23 | @@ -66,7 +69,7 @@ | |||
24 | 66 | GCancellable* cancellable = nullptr; | 69 | GCancellable* cancellable = nullptr; |
25 | 67 | const std::string public_key; | 70 | const std::string public_key; |
26 | 68 | 71 | ||
28 | 69 | PKIdleData(Impl* self_, GCancellable* cancellable_, std::string public_key_): | 72 | PKIdleData(Impl* self_, GCancellable* cancellable_, const std::string& public_key_): |
29 | 70 | self(self_), | 73 | self(self_), |
30 | 71 | cancellable(G_CANCELLABLE(g_object_ref(cancellable_))), | 74 | cancellable(G_CANCELLABLE(g_object_ref(cancellable_))), |
31 | 72 | public_key(public_key_) {} | 75 | public_key(public_key_) {} |
32 | @@ -104,8 +107,9 @@ | |||
33 | 104 | 107 | ||
34 | 105 | void on_public_key_response(PKResponse response) | 108 | void on_public_key_response(PKResponse response) |
35 | 106 | { | 109 | { |
36 | 110 | g_debug("%s thread %p got response %d", G_STRLOC, g_thread_self(), int(response)); | ||
37 | 111 | |||
38 | 107 | // set m_pkresponse and wake up the waiting worker thread | 112 | // set m_pkresponse and wake up the waiting worker thread |
39 | 108 | std::unique_lock<std::mutex> lk(m_pkresponse_mutex); | ||
40 | 109 | m_pkresponse = response; | 113 | m_pkresponse = response; |
41 | 110 | m_pkresponse_ready = true; | 114 | m_pkresponse_ready = true; |
42 | 111 | m_pkresponse_cv.notify_one(); | 115 | m_pkresponse_cv.notify_one(); |
43 | @@ -121,11 +125,11 @@ | |||
44 | 121 | 125 | ||
45 | 122 | while (!g_cancellable_is_cancelled(m_cancellable)) | 126 | while (!g_cancellable_is_cancelled(m_cancellable)) |
46 | 123 | { | 127 | { |
48 | 124 | g_debug("%s creating a client socket to '%s'", G_STRLOC, socket_path.c_str()); | 128 | g_debug("%s thread %p creating a client socket to '%s'", G_STRLOC, g_thread_self(), socket_path.c_str()); |
49 | 125 | auto socket = create_client_socket(socket_path); | 129 | auto socket = create_client_socket(socket_path); |
50 | 126 | bool got_valid_req = false; | 130 | bool got_valid_req = false; |
51 | 127 | 131 | ||
53 | 128 | g_debug("%s calling read_request", G_STRLOC); | 132 | g_debug("%s thread %p calling read_request", g_thread_self(), G_STRLOC); |
54 | 129 | std::string reqstr; | 133 | std::string reqstr; |
55 | 130 | if (socket != nullptr) | 134 | if (socket != nullptr) |
56 | 131 | reqstr = read_request(socket); | 135 | reqstr = read_request(socket); |
57 | @@ -135,22 +139,25 @@ | |||
58 | 135 | if (reqstr.substr(0,2) == "PK") { | 139 | if (reqstr.substr(0,2) == "PK") { |
59 | 136 | PKResponse response = PKResponse::DENY; | 140 | PKResponse response = PKResponse::DENY; |
60 | 137 | const auto public_key = reqstr.substr(2); | 141 | const auto public_key = reqstr.substr(2); |
62 | 138 | g_debug("%s got pk [%s]", G_STRLOC, public_key.c_str()); | 142 | g_debug("%s thread %p got pk [%s]", G_STRLOC, g_thread_self(), public_key.c_str()); |
63 | 139 | if (!public_key.empty()) { | 143 | if (!public_key.empty()) { |
64 | 140 | got_valid_req = true; | 144 | got_valid_req = true; |
65 | 141 | std::unique_lock<std::mutex> lk(m_pkresponse_mutex); | 145 | std::unique_lock<std::mutex> lk(m_pkresponse_mutex); |
66 | 142 | m_pkresponse_ready = false; | 146 | m_pkresponse_ready = false; |
67 | 147 | m_pkresponse = AdbdClient::PKResponse::DENY; | ||
68 | 143 | pass_public_key_to_main_thread(public_key); | 148 | pass_public_key_to_main_thread(public_key); |
69 | 144 | m_pkresponse_cv.wait(lk, [this](){ | 149 | m_pkresponse_cv.wait(lk, [this](){ |
70 | 145 | return m_pkresponse_ready || g_cancellable_is_cancelled(m_cancellable); | 150 | return m_pkresponse_ready || g_cancellable_is_cancelled(m_cancellable); |
71 | 146 | }); | 151 | }); |
72 | 147 | response = m_pkresponse; | 152 | response = m_pkresponse; |
74 | 148 | g_debug("%s got response '%d', is-cancelled %d", G_STRLOC, | 153 | g_debug("%s thread %p got response '%d', is-cancelled %d", G_STRLOC, |
75 | 154 | g_thread_self(), | ||
76 | 149 | int(response), | 155 | int(response), |
77 | 150 | int(g_cancellable_is_cancelled(m_cancellable))); | 156 | int(g_cancellable_is_cancelled(m_cancellable))); |
78 | 151 | } | 157 | } |
80 | 152 | if (!g_cancellable_is_cancelled(m_cancellable)) | 158 | if (!g_cancellable_is_cancelled(m_cancellable)) { |
81 | 153 | send_pk_response(socket, response); | 159 | send_pk_response(socket, response); |
82 | 160 | } | ||
83 | 154 | } else if (!reqstr.empty()) { | 161 | } else if (!reqstr.empty()) { |
84 | 155 | g_warning("Invalid ADB request: [%s]", reqstr.c_str()); | 162 | g_warning("Invalid ADB request: [%s]", reqstr.c_str()); |
85 | 156 | } | 163 | } |
86 | @@ -270,7 +277,7 @@ | |||
87 | 270 | 277 | ||
88 | 271 | std::mutex m_pkresponse_mutex; | 278 | std::mutex m_pkresponse_mutex; |
89 | 272 | std::condition_variable m_pkresponse_cv; | 279 | std::condition_variable m_pkresponse_cv; |
91 | 273 | bool m_pkresponse_ready = false; | 280 | std::atomic<bool> m_pkresponse_ready {false}; |
92 | 274 | PKResponse m_pkresponse = PKResponse::DENY; | 281 | PKResponse m_pkresponse = PKResponse::DENY; |
93 | 275 | }; | 282 | }; |
94 | 276 | 283 | ||
95 | 277 | 284 | ||
96 | === modified file 'src/greeter.cpp' | |||
97 | --- src/greeter.cpp 2016-03-22 13:15:38 +0000 | |||
98 | +++ src/greeter.cpp 2016-10-21 11:40:57 +0000 | |||
99 | @@ -26,117 +26,167 @@ | |||
100 | 26 | { | 26 | { |
101 | 27 | public: | 27 | public: |
102 | 28 | 28 | ||
123 | 29 | Impl(): | 29 | Impl() |
124 | 30 | m_cancellable{g_cancellable_new()} | 30 | { |
125 | 31 | { | 31 | m_cancellable.reset( |
126 | 32 | g_bus_get(G_BUS_TYPE_SESSION, m_cancellable, on_bus_ready_static, this); | 32 | g_cancellable_new(), |
127 | 33 | } | 33 | [](GCancellable* o){ |
128 | 34 | 34 | g_cancellable_cancel(o); | |
129 | 35 | ~Impl() | 35 | g_clear_object(&o); |
130 | 36 | { | 36 | } |
131 | 37 | g_cancellable_cancel(m_cancellable); | 37 | ); |
132 | 38 | g_clear_object(&m_cancellable); | 38 | |
133 | 39 | 39 | g_bus_get(G_BUS_TYPE_SESSION, m_cancellable.get(), on_bus_ready, this); | |
134 | 40 | if (m_subscription_id != 0) | 40 | } |
135 | 41 | g_dbus_connection_signal_unsubscribe (m_bus, m_subscription_id); | 41 | |
136 | 42 | 42 | ~Impl() =default; | |
137 | 43 | g_clear_object(&m_bus); | 43 | |
138 | 44 | } | 44 | core::Property<State>& state() |
139 | 45 | 45 | { | |
140 | 46 | core::Property<bool>& is_active() | 46 | return m_state; |
121 | 47 | { | ||
122 | 48 | return m_is_active; | ||
141 | 49 | } | 47 | } |
142 | 50 | 48 | ||
143 | 51 | private: | 49 | private: |
144 | 52 | 50 | ||
146 | 53 | static void on_bus_ready_static(GObject* /*source*/, GAsyncResult* res, gpointer gself) | 51 | void set_state(const State& state) |
147 | 52 | { | ||
148 | 53 | m_state.set(state); | ||
149 | 54 | } | ||
150 | 55 | |||
151 | 56 | static void on_bus_ready( | ||
152 | 57 | GObject* /*source*/, | ||
153 | 58 | GAsyncResult* res, | ||
154 | 59 | gpointer gself) | ||
155 | 54 | { | 60 | { |
156 | 55 | GError* error {}; | 61 | GError* error {}; |
159 | 56 | auto bus = g_bus_get_finish (res, &error); | 62 | auto bus = g_bus_get_finish(res, &error); |
160 | 57 | if (error != nullptr) { | 63 | if (error != nullptr) |
161 | 64 | { | ||
162 | 58 | if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) | 65 | if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
164 | 59 | g_warning("UsbSnap: Error getting session bus: %s", error->message); | 66 | g_warning("Greeter: Error getting bus: %s", error->message); |
165 | 60 | g_clear_error(&error); | 67 | g_clear_error(&error); |
202 | 61 | } else { | 68 | } |
203 | 62 | static_cast<Impl*>(gself)->on_bus_ready(bus); | 69 | else |
204 | 63 | } | 70 | { |
205 | 64 | g_clear_object(&bus); | 71 | auto self = static_cast<Impl*>(gself); |
206 | 65 | } | 72 | |
207 | 66 | 73 | const auto watcher_id = g_bus_watch_name_on_connection( | |
208 | 67 | void on_bus_ready(GDBusConnection* bus) | 74 | bus, |
209 | 68 | { | 75 | DBusNames::UnityGreeter::NAME, |
210 | 69 | m_bus = G_DBUS_CONNECTION(g_object_ref(G_OBJECT(bus))); | 76 | G_BUS_NAME_WATCHER_FLAGS_AUTO_START, |
211 | 70 | 77 | on_greeter_appeared, | |
212 | 71 | g_dbus_connection_call(m_bus, | 78 | on_greeter_vanished, |
213 | 72 | DBusNames::UnityGreeter::NAME, | 79 | gself, |
214 | 73 | DBusNames::UnityGreeter::PATH, | 80 | nullptr); |
215 | 74 | DBusNames::Properties::INTERFACE, | 81 | |
216 | 75 | "Get", | 82 | const auto subscription_id = g_dbus_connection_signal_subscribe( |
217 | 76 | g_variant_new("(ss)", DBusNames::UnityGreeter::INTERFACE, "IsActive"), | 83 | bus, |
218 | 77 | G_VARIANT_TYPE("(v)"), | 84 | DBusNames::UnityGreeter::NAME, |
219 | 78 | G_DBUS_CALL_FLAGS_NONE, | 85 | DBusNames::Properties::INTERFACE, |
220 | 79 | -1, | 86 | DBusNames::Properties::PropertiesChanged::NAME, |
221 | 80 | m_cancellable, | 87 | DBusNames::UnityGreeter::PATH, |
222 | 81 | on_get_is_active_ready, | 88 | DBusNames::UnityGreeter::INTERFACE, |
223 | 82 | this); | 89 | G_DBUS_SIGNAL_FLAGS_NONE, |
224 | 83 | 90 | on_properties_changed_signal, | |
225 | 84 | m_subscription_id = g_dbus_connection_signal_subscribe(m_bus, | 91 | gself, |
226 | 85 | DBusNames::UnityGreeter::NAME, | 92 | nullptr); |
227 | 86 | DBusNames::Properties::INTERFACE, | 93 | |
228 | 87 | DBusNames::Properties::PropertiesChanged::NAME, | 94 | self->m_bus.reset( |
229 | 88 | DBusNames::UnityGreeter::PATH, | 95 | bus, |
230 | 89 | DBusNames::UnityGreeter::INTERFACE, | 96 | [watcher_id, subscription_id](GDBusConnection* o){ |
231 | 90 | G_DBUS_SIGNAL_FLAGS_NONE, | 97 | g_bus_unwatch_name(watcher_id); |
232 | 91 | on_properties_changed_signal, | 98 | g_dbus_connection_signal_unsubscribe(o, subscription_id); |
233 | 92 | this, | 99 | g_clear_object(&o); |
234 | 93 | nullptr); | 100 | } |
235 | 94 | } | 101 | ); |
236 | 95 | 102 | } | |
237 | 96 | static void on_get_is_active_ready(GObject* source, GAsyncResult* res, gpointer gself) | 103 | } |
238 | 104 | |||
239 | 105 | static void on_greeter_appeared( | ||
240 | 106 | GDBusConnection* bus, | ||
241 | 107 | const char* /*name*/, | ||
242 | 108 | const char* name_owner, | ||
243 | 109 | gpointer gself) | ||
244 | 110 | { | ||
245 | 111 | auto self = static_cast<Impl*>(gself); | ||
246 | 112 | |||
247 | 113 | self->m_owner = name_owner; | ||
248 | 114 | |||
249 | 115 | g_dbus_connection_call( | ||
250 | 116 | bus, | ||
251 | 117 | DBusNames::UnityGreeter::NAME, | ||
252 | 118 | DBusNames::UnityGreeter::PATH, | ||
253 | 119 | DBusNames::Properties::INTERFACE, | ||
254 | 120 | "Get", | ||
255 | 121 | g_variant_new("(ss)", DBusNames::UnityGreeter::INTERFACE, "IsActive"), | ||
256 | 122 | G_VARIANT_TYPE("(v)"), | ||
257 | 123 | G_DBUS_CALL_FLAGS_NONE, | ||
258 | 124 | -1, | ||
259 | 125 | self->m_cancellable.get(), | ||
260 | 126 | on_get_is_active_ready, | ||
261 | 127 | gself); | ||
262 | 128 | } | ||
263 | 129 | |||
264 | 130 | static void on_greeter_vanished( | ||
265 | 131 | GDBusConnection* /*bus*/, | ||
266 | 132 | const char* /*name*/, | ||
267 | 133 | gpointer gself) | ||
268 | 134 | { | ||
269 | 135 | auto self = static_cast<Impl*>(gself); | ||
270 | 136 | |||
271 | 137 | self->m_owner.clear(); | ||
272 | 138 | self->set_state(State::UNAVAILABLE); | ||
273 | 139 | } | ||
274 | 140 | |||
275 | 141 | static void on_get_is_active_ready( | ||
276 | 142 | GObject* source, | ||
277 | 143 | GAsyncResult* res, | ||
278 | 144 | gpointer gself) | ||
279 | 97 | { | 145 | { |
280 | 98 | GError* error {}; | 146 | GError* error {}; |
281 | 99 | auto v = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), res, &error); | 147 | auto v = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), res, &error); |
282 | 100 | if (error != nullptr) { | 148 | if (error != nullptr) { |
285 | 101 | if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) | 149 | if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { |
286 | 102 | g_warning("UsbSnap: Error getting session bus: %s", error->message); | 150 | g_warning("Greeter: Error getting IsActive property: %s", error->message); |
287 | 151 | } | ||
288 | 103 | g_clear_error(&error); | 152 | g_clear_error(&error); |
289 | 104 | } else { | 153 | } else { |
290 | 105 | GVariant* is_active {}; | 154 | GVariant* is_active {}; |
291 | 106 | g_variant_get_child(v, 0, "v", &is_active); | 155 | g_variant_get_child(v, 0, "v", &is_active); |
293 | 107 | static_cast<Impl*>(gself)->m_is_active.set(g_variant_get_boolean(is_active)); | 156 | static_cast<Impl*>(gself)->set_state(g_variant_get_boolean(is_active) ? State::ACTIVE : State::INACTIVE); |
294 | 108 | g_clear_pointer(&is_active, g_variant_unref); | 157 | g_clear_pointer(&is_active, g_variant_unref); |
295 | 109 | } | 158 | } |
296 | 110 | g_clear_pointer(&v, g_variant_unref); | 159 | g_clear_pointer(&v, g_variant_unref); |
297 | 111 | } | 160 | } |
298 | 112 | 161 | ||
306 | 113 | static void on_properties_changed_signal(GDBusConnection* /*connection*/, | 162 | static void on_properties_changed_signal( |
307 | 114 | const gchar* /*sender_name*/, | 163 | GDBusConnection* /*bus*/, |
308 | 115 | const gchar* object_path, | 164 | const gchar* sender_name, |
309 | 116 | const gchar* interface_name, | 165 | const gchar* object_path, |
310 | 117 | const gchar* signal_name, | 166 | const gchar* interface_name, |
311 | 118 | GVariant* parameters, | 167 | const gchar* signal_name, |
312 | 119 | gpointer gself) | 168 | GVariant* parameters, |
313 | 169 | gpointer gself) | ||
314 | 120 | { | 170 | { |
315 | 171 | auto self = static_cast<Impl*>(gself); | ||
316 | 172 | |||
317 | 173 | g_return_if_fail(!g_strcmp0(sender_name, self->m_owner.c_str())); | ||
318 | 121 | g_return_if_fail(!g_strcmp0(object_path, DBusNames::UnityGreeter::PATH)); | 174 | g_return_if_fail(!g_strcmp0(object_path, DBusNames::UnityGreeter::PATH)); |
319 | 122 | g_return_if_fail(!g_strcmp0(interface_name, DBusNames::Properties::INTERFACE)); | 175 | g_return_if_fail(!g_strcmp0(interface_name, DBusNames::Properties::INTERFACE)); |
320 | 123 | g_return_if_fail(!g_strcmp0(signal_name, DBusNames::Properties::PropertiesChanged::NAME)); | 176 | g_return_if_fail(!g_strcmp0(signal_name, DBusNames::Properties::PropertiesChanged::NAME)); |
321 | 124 | g_return_if_fail(g_variant_is_of_type(parameters, G_VARIANT_TYPE(DBusNames::Properties::PropertiesChanged::ARGS_VARIANT_TYPE))); | 177 | g_return_if_fail(g_variant_is_of_type(parameters, G_VARIANT_TYPE(DBusNames::Properties::PropertiesChanged::ARGS_VARIANT_TYPE))); |
322 | 125 | 178 | ||
324 | 126 | auto v = g_variant_get_child_value (parameters, 1); | 179 | auto v = g_variant_get_child_value(parameters, 1); |
325 | 127 | gboolean is_active {}; | 180 | gboolean is_active {}; |
326 | 128 | if (g_variant_lookup(v, "IsActive", "b", &is_active)) | 181 | if (g_variant_lookup(v, "IsActive", "b", &is_active)) |
331 | 129 | { | 182 | self->set_state(is_active ? State::ACTIVE : State::INACTIVE); |
328 | 130 | g_debug("%s is_active changed to %d", G_STRLOC, int(is_active)); | ||
329 | 131 | static_cast<Impl*>(gself)->m_is_active.set(is_active); | ||
330 | 132 | } | ||
332 | 133 | g_clear_pointer(&v, g_variant_unref); | 183 | g_clear_pointer(&v, g_variant_unref); |
333 | 134 | } | 184 | } |
334 | 135 | 185 | ||
339 | 136 | core::Property<bool> m_is_active; | 186 | core::Property<State> m_state {State::UNAVAILABLE}; |
340 | 137 | GCancellable* m_cancellable {}; | 187 | std::shared_ptr<GCancellable> m_cancellable; |
341 | 138 | GDBusConnection* m_bus {}; | 188 | std::shared_ptr<GDBusConnection> m_bus; |
342 | 139 | unsigned int m_subscription_id {}; | 189 | std::string m_owner; |
343 | 140 | }; | 190 | }; |
344 | 141 | 191 | ||
345 | 142 | /*** | 192 | /*** |
346 | @@ -154,8 +204,8 @@ | |||
347 | 154 | 204 | ||
348 | 155 | UnityGreeter::~UnityGreeter() =default; | 205 | UnityGreeter::~UnityGreeter() =default; |
349 | 156 | 206 | ||
352 | 157 | core::Property<bool>& | 207 | core::Property<Greeter::State>& |
353 | 158 | UnityGreeter::is_active() | 208 | UnityGreeter::state() |
354 | 159 | { | 209 | { |
356 | 160 | return impl->is_active(); | 210 | return impl->state(); |
357 | 161 | } | 211 | } |
358 | 162 | 212 | ||
359 | === modified file 'src/greeter.h' | |||
360 | --- src/greeter.h 2016-03-21 23:15:05 +0000 | |||
361 | +++ src/greeter.h 2016-10-21 11:40:57 +0000 | |||
362 | @@ -29,7 +29,13 @@ | |||
363 | 29 | public: | 29 | public: |
364 | 30 | Greeter(); | 30 | Greeter(); |
365 | 31 | virtual ~Greeter(); | 31 | virtual ~Greeter(); |
367 | 32 | virtual core::Property<bool>& is_active() =0; | 32 | |
368 | 33 | enum class State { UNAVAILABLE, INACTIVE, ACTIVE }; | ||
369 | 34 | static inline const char* state_str(const State& state) { | ||
370 | 35 | static constexpr char const * state_str[] = { "Unavailable", "Inactive", "Active" }; | ||
371 | 36 | return state_str[int(state)]; | ||
372 | 37 | } | ||
373 | 38 | virtual core::Property<State>& state() =0; | ||
374 | 33 | }; | 39 | }; |
375 | 34 | 40 | ||
376 | 35 | 41 | ||
377 | @@ -38,7 +44,7 @@ | |||
378 | 38 | public: | 44 | public: |
379 | 39 | UnityGreeter(); | 45 | UnityGreeter(); |
380 | 40 | virtual ~UnityGreeter(); | 46 | virtual ~UnityGreeter(); |
382 | 41 | core::Property<bool>& is_active() override; | 47 | core::Property<State>& state() override; |
383 | 42 | 48 | ||
384 | 43 | protected: | 49 | protected: |
385 | 44 | class Impl; | 50 | class Impl; |
386 | 45 | 51 | ||
387 | === modified file 'src/usb-manager.cpp' | |||
388 | --- src/usb-manager.cpp 2016-03-23 19:44:23 +0000 | |||
389 | +++ src/usb-manager.cpp 2016-10-21 11:40:57 +0000 | |||
390 | @@ -46,72 +46,89 @@ | |||
391 | 46 | m_greeter{greeter} | 46 | m_greeter{greeter} |
392 | 47 | { | 47 | { |
393 | 48 | m_usb_monitor->on_usb_disconnected().connect([this](const std::string& /*usb_name*/) { | 48 | m_usb_monitor->on_usb_disconnected().connect([this](const std::string& /*usb_name*/) { |
402 | 49 | restart(); | 49 | m_req.reset(); |
403 | 50 | }); | 50 | }); |
404 | 51 | 51 | ||
405 | 52 | m_greeter->is_active().changed().connect([this](bool /*is_active*/) { | 52 | m_greeter->state().changed().connect([this](const Greeter::State& state) { |
406 | 53 | maybe_snap(); | 53 | if (state == Greeter::State::INACTIVE) { |
407 | 54 | }); | 54 | maybe_snap(); |
408 | 55 | 55 | } else { | |
409 | 56 | restart(); | 56 | stop_snap(); |
410 | 57 | } | ||
411 | 58 | }); | ||
412 | 59 | |||
413 | 60 | // create a new adbd client | ||
414 | 61 | m_adbd_client.reset(new GAdbdClient{m_socket_path}); | ||
415 | 62 | m_adbd_client->on_pk_request().connect( | ||
416 | 63 | [this](const AdbdClient::PKRequest& req) { | ||
417 | 64 | g_debug("%s got pk request: %s, calling maybe_snap()", G_STRLOC, req.fingerprint.c_str()); | ||
418 | 65 | |||
419 | 66 | m_response = AdbdClient::PKResponse::DENY; // set the fallback response | ||
420 | 67 | m_req.reset( | ||
421 | 68 | new AdbdClient::PKRequest(req), | ||
422 | 69 | [this](AdbdClient::PKRequest* r) { | ||
423 | 70 | stop_snap(); | ||
424 | 71 | r->respond(m_response); | ||
425 | 72 | delete r; | ||
426 | 73 | } | ||
427 | 74 | ); | ||
428 | 75 | maybe_snap(); | ||
429 | 76 | } | ||
430 | 77 | ); | ||
431 | 57 | } | 78 | } |
432 | 58 | 79 | ||
433 | 59 | ~Impl() | 80 | ~Impl() |
434 | 60 | { | 81 | { |
439 | 61 | if (m_restart_idle_tag) | 82 | if (m_request_complete_idle_tag) { |
440 | 62 | g_source_remove(m_restart_idle_tag); | 83 | g_source_remove(m_request_complete_idle_tag); |
441 | 63 | 84 | } | |
438 | 64 | clear(); | ||
442 | 65 | } | 85 | } |
443 | 66 | 86 | ||
444 | 67 | private: | 87 | private: |
445 | 68 | 88 | ||
447 | 69 | void clear() | 89 | void stop_snap() |
448 | 70 | { | 90 | { |
449 | 71 | // clear out old state | ||
450 | 72 | m_snap_connections.clear(); | 91 | m_snap_connections.clear(); |
451 | 73 | m_snap.reset(); | 92 | m_snap.reset(); |
452 | 74 | m_req = decltype(m_req)(); | ||
453 | 75 | m_adbd_client.reset(); | ||
454 | 76 | } | ||
455 | 77 | |||
456 | 78 | void restart() | ||
457 | 79 | { | ||
458 | 80 | clear(); | ||
459 | 81 | |||
460 | 82 | // set a new client | ||
461 | 83 | m_adbd_client.reset(new GAdbdClient{m_socket_path}); | ||
462 | 84 | m_adbd_client->on_pk_request().connect( | ||
463 | 85 | [this](const AdbdClient::PKRequest& req) { | ||
464 | 86 | g_debug("%s got pk request: %s", G_STRLOC, req.fingerprint.c_str()); | ||
465 | 87 | m_req = req; | ||
466 | 88 | maybe_snap(); | ||
467 | 89 | } | ||
468 | 90 | ); | ||
469 | 91 | } | 93 | } |
470 | 92 | 94 | ||
471 | 93 | void maybe_snap() | 95 | void maybe_snap() |
472 | 94 | { | 96 | { |
476 | 95 | // don't prompt in the greeter! | 97 | // only prompt if there's something to prompt about |
477 | 96 | if (!m_req.public_key.empty() && !m_greeter->is_active().get()) | 98 | if (!m_req) { |
478 | 97 | snap(); | 99 | return; |
479 | 100 | } | ||
480 | 101 | |||
481 | 102 | // only prompt in an unlocked session | ||
482 | 103 | if (m_greeter->state().get() != Greeter::State::INACTIVE) { | ||
483 | 104 | return; | ||
484 | 105 | } | ||
485 | 106 | |||
486 | 107 | snap(); | ||
487 | 98 | } | 108 | } |
488 | 99 | 109 | ||
489 | 100 | void snap() | 110 | void snap() |
490 | 101 | { | 111 | { |
492 | 102 | m_snap = std::make_shared<UsbSnap>(m_req.fingerprint); | 112 | m_snap = std::make_shared<UsbSnap>(m_req->fingerprint); |
493 | 103 | m_snap_connections.insert((*m_snap).on_user_response().connect( | 113 | m_snap_connections.insert((*m_snap).on_user_response().connect( |
494 | 104 | [this](AdbdClient::PKResponse response, bool remember_choice){ | 114 | [this](AdbdClient::PKResponse response, bool remember_choice){ |
505 | 105 | g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); | 115 | |
506 | 106 | m_req.respond(response); | 116 | if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) { |
507 | 107 | if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) | 117 | write_public_key(m_req->public_key); |
508 | 108 | write_public_key(m_req.public_key); | 118 | } |
509 | 109 | m_restart_idle_tag = g_idle_add([](gpointer gself){ | 119 | |
510 | 110 | auto self = static_cast<Impl*>(gself); | 120 | m_response = response; |
511 | 111 | self->m_restart_idle_tag = 0; | 121 | |
512 | 112 | self->restart(); | 122 | // defer finishing the request into an idle func because |
513 | 113 | return G_SOURCE_REMOVE; | 123 | // ScopedConnections can't be destroyed inside their callbacks |
514 | 114 | }, this); | 124 | if (m_request_complete_idle_tag == 0) { |
515 | 125 | m_request_complete_idle_tag = g_idle_add([](gpointer gself){ | ||
516 | 126 | auto self = static_cast<Impl*>(gself); | ||
517 | 127 | self->m_request_complete_idle_tag = 0; | ||
518 | 128 | self->m_req.reset(); | ||
519 | 129 | return G_SOURCE_REMOVE; | ||
520 | 130 | }, this); | ||
521 | 131 | } | ||
522 | 115 | } | 132 | } |
523 | 116 | )); | 133 | )); |
524 | 117 | } | 134 | } |
525 | @@ -152,12 +169,13 @@ | |||
526 | 152 | const std::shared_ptr<UsbMonitor> m_usb_monitor; | 169 | const std::shared_ptr<UsbMonitor> m_usb_monitor; |
527 | 153 | const std::shared_ptr<Greeter> m_greeter; | 170 | const std::shared_ptr<Greeter> m_greeter; |
528 | 154 | 171 | ||
530 | 155 | unsigned int m_restart_idle_tag {}; | 172 | unsigned int m_request_complete_idle_tag {}; |
531 | 156 | 173 | ||
532 | 157 | std::shared_ptr<GAdbdClient> m_adbd_client; | 174 | std::shared_ptr<GAdbdClient> m_adbd_client; |
533 | 158 | AdbdClient::PKRequest m_req; | ||
534 | 159 | std::shared_ptr<UsbSnap> m_snap; | 175 | std::shared_ptr<UsbSnap> m_snap; |
535 | 160 | std::set<core::ScopedConnection> m_snap_connections; | 176 | std::set<core::ScopedConnection> m_snap_connections; |
536 | 177 | AdbdClient::PKResponse m_response {AdbdClient::PKResponse::DENY}; | ||
537 | 178 | std::shared_ptr<AdbdClient::PKRequest> m_req; | ||
538 | 161 | }; | 179 | }; |
539 | 162 | 180 | ||
540 | 163 | /*** | 181 | /*** |
541 | @@ -177,4 +195,3 @@ | |||
542 | 177 | UsbManager::~UsbManager() | 195 | UsbManager::~UsbManager() |
543 | 178 | { | 196 | { |
544 | 179 | } | 197 | } |
545 | 180 | |||
546 | 181 | 198 | ||
547 | === modified file 'src/usb-snap.cpp' | |||
548 | --- src/usb-snap.cpp 2016-03-23 17:16:06 +0000 | |||
549 | +++ src/usb-snap.cpp 2016-10-21 11:40:57 +0000 | |||
550 | @@ -208,6 +208,7 @@ | |||
551 | 208 | const bool remember_this_choice = response == AdbdClient::PKResponse::ALLOW; | 208 | const bool remember_this_choice = response == AdbdClient::PKResponse::ALLOW; |
552 | 209 | 209 | ||
553 | 210 | m_on_user_response(response, remember_this_choice); | 210 | m_on_user_response(response, remember_this_choice); |
554 | 211 | m_notification_id = 0; | ||
555 | 211 | } | 212 | } |
556 | 212 | 213 | ||
557 | 213 | void on_notification_closed(uint32_t close_reason) | 214 | void on_notification_closed(uint32_t close_reason) |
558 | 214 | 215 | ||
559 | === modified file 'tests/integration/usb-manager-test.cpp' | |||
560 | --- tests/integration/usb-manager-test.cpp 2016-03-23 17:16:06 +0000 | |||
561 | +++ tests/integration/usb-manager-test.cpp 2016-10-21 11:40:57 +0000 | |||
562 | @@ -143,7 +143,7 @@ | |||
563 | 143 | ); | 143 | ); |
564 | 144 | 144 | ||
565 | 145 | // confirm that the AdbdServer got the right response | 145 | // confirm that the AdbdServer got the right response |
567 | 146 | wait_for([adbd_server](){return !adbd_server->m_responses.empty();}, 2000); | 146 | wait_for([adbd_server](){return !adbd_server->m_responses.empty();}, 5000); |
568 | 147 | ASSERT_EQ(1, adbd_server->m_responses.size()); | 147 | ASSERT_EQ(1, adbd_server->m_responses.size()); |
569 | 148 | EXPECT_EQ("OK", adbd_server->m_responses.front()); | 148 | EXPECT_EQ("OK", adbd_server->m_responses.front()); |
570 | 149 | 149 | ||
571 | @@ -163,13 +163,16 @@ | |||
572 | 163 | const std::shared_ptr<std::string> public_keys_path {new std::string{*m_tmpdir+"/adb_keys"}, file_deleter}; | 163 | const std::shared_ptr<std::string> public_keys_path {new std::string{*m_tmpdir+"/adb_keys"}, file_deleter}; |
573 | 164 | 164 | ||
574 | 165 | // start a mock AdbdServer ready to submit a request | 165 | // start a mock AdbdServer ready to submit a request |
575 | 166 | const size_t N_TESTS {3}; | ||
576 | 166 | const std::string public_key {"public_key"}; | 167 | const std::string public_key {"public_key"}; |
578 | 167 | auto adbd_server = std::make_shared<GAdbdServer>(*socket_path, std::vector<std::string>{"PK"+public_key}); | 168 | const std::vector<std::string> requests(N_TESTS, "PK"+public_key); |
579 | 169 | const std::vector<std::string> expected_responses(N_TESTS, "NO"); | ||
580 | 170 | auto adbd_server = std::make_shared<GAdbdServer>(*socket_path, requests); | ||
581 | 168 | 171 | ||
582 | 169 | // set up a UsbManager to process the request | 172 | // set up a UsbManager to process the request |
583 | 170 | auto usb_manager = std::make_shared<UsbManager>(*socket_path, *public_keys_path, m_usb_monitor, m_greeter); | 173 | auto usb_manager = std::make_shared<UsbManager>(*socket_path, *public_keys_path, m_usb_monitor, m_greeter); |
584 | 171 | 174 | ||
586 | 172 | for (int i=0; i<3; i++) | 175 | for (std::remove_const<decltype(N_TESTS)>::type i=0; i<N_TESTS; ++i) |
587 | 173 | { | 176 | { |
588 | 174 | // add a signal spy to listen to the notification daemon | 177 | // add a signal spy to listen to the notification daemon |
589 | 175 | QSignalSpy notificationsSpy( | 178 | QSignalSpy notificationsSpy( |
590 | @@ -194,6 +197,9 @@ | |||
591 | 194 | EXPECT_EQ("CloseNotification", notificationsSpy.at(0).at(0)); | 197 | EXPECT_EQ("CloseNotification", notificationsSpy.at(0).at(0)); |
592 | 195 | notificationsSpy.clear(); | 198 | notificationsSpy.clear(); |
593 | 196 | } | 199 | } |
594 | 200 | |||
595 | 201 | EXPECT_TRUE(wait_for([adbd_server, N_TESTS](){return adbd_server->m_responses.size() == N_TESTS;}, 5000)); | ||
596 | 202 | EXPECT_EQ(expected_responses, adbd_server->m_responses); | ||
597 | 197 | } | 203 | } |
598 | 198 | 204 | ||
599 | 199 | TEST_F(UsbManagerFixture, Greeter) | 205 | TEST_F(UsbManagerFixture, Greeter) |
600 | @@ -206,7 +212,7 @@ | |||
601 | 206 | auto adbd_server = std::make_shared<GAdbdServer>(*socket_path, std::vector<std::string>{"PK"+public_key}); | 212 | auto adbd_server = std::make_shared<GAdbdServer>(*socket_path, std::vector<std::string>{"PK"+public_key}); |
602 | 207 | 213 | ||
603 | 208 | // set up a UsbManager to process the request | 214 | // set up a UsbManager to process the request |
605 | 209 | m_greeter->m_is_active.set(true); | 215 | m_greeter->m_state.set(Greeter::State::ACTIVE); |
606 | 210 | auto usb_manager = std::make_shared<UsbManager>(*socket_path, *public_keys_path, m_usb_monitor, m_greeter); | 216 | auto usb_manager = std::make_shared<UsbManager>(*socket_path, *public_keys_path, m_usb_monitor, m_greeter); |
607 | 211 | 217 | ||
608 | 212 | // add a signal spy to listen to the notification daemon | 218 | // add a signal spy to listen to the notification daemon |
609 | @@ -219,7 +225,7 @@ | |||
610 | 219 | EXPECT_FALSE(notificationsSpy.wait(2000)); | 225 | EXPECT_FALSE(notificationsSpy.wait(2000)); |
611 | 220 | 226 | ||
612 | 221 | // disable the greeter, the notification should appear | 227 | // disable the greeter, the notification should appear |
614 | 222 | m_greeter->m_is_active.set(false); | 228 | m_greeter->m_state.set(Greeter::State::INACTIVE); |
615 | 223 | wait_for_signals(notificationsSpy, 1); | 229 | wait_for_signals(notificationsSpy, 1); |
616 | 224 | EXPECT_EQ("Notify", notificationsSpy.at(0).at(0)); | 230 | EXPECT_EQ("Notify", notificationsSpy.at(0).at(0)); |
617 | 225 | notificationsSpy.clear(); | 231 | notificationsSpy.clear(); |
618 | 226 | 232 | ||
619 | === modified file 'tests/unit/CMakeLists.txt' | |||
620 | --- tests/unit/CMakeLists.txt 2016-03-16 00:25:33 +0000 | |||
621 | +++ tests/unit/CMakeLists.txt 2016-10-21 11:40:57 +0000 | |||
622 | @@ -14,6 +14,10 @@ | |||
623 | 14 | ${GMOCK_LIBRARIES} | 14 | ${GMOCK_LIBRARIES} |
624 | 15 | ) | 15 | ) |
625 | 16 | 16 | ||
626 | 17 | add_definitions( | ||
627 | 18 | -DGREETER_TEMPLATE="${CMAKE_SOURCE_DIR}/tests/utils/mock-unity-greeter.py" | ||
628 | 19 | ) | ||
629 | 20 | |||
630 | 17 | function(add_test_by_name name) | 21 | function(add_test_by_name name) |
631 | 18 | set(TEST_NAME ${name}) | 22 | set(TEST_NAME ${name}) |
632 | 19 | add_executable (${TEST_NAME} ${TEST_NAME}.cpp) | 23 | add_executable (${TEST_NAME} ${TEST_NAME}.cpp) |
633 | @@ -31,4 +35,5 @@ | |||
634 | 31 | set_property(TEST ${TEST_NAME} APPEND PROPERTY ENVIRONMENT ${CTEST_ENVIRONMENT}) | 35 | set_property(TEST ${TEST_NAME} APPEND PROPERTY ENVIRONMENT ${CTEST_ENVIRONMENT}) |
635 | 32 | target_link_libraries(${TEST_NAME} ${SERVICE_LINK_LIBRARIES} ${QT_LINK_LIBRARIES} ${TEST_LINK_LIBRARIES} ${THREAD_LINK_LIBRARIES}) | 36 | target_link_libraries(${TEST_NAME} ${SERVICE_LINK_LIBRARIES} ${QT_LINK_LIBRARIES} ${TEST_LINK_LIBRARIES} ${THREAD_LINK_LIBRARIES}) |
636 | 33 | endfunction() | 37 | endfunction() |
637 | 38 | add_qt_test_by_name(greeter-test) | ||
638 | 34 | add_qt_test_by_name(usb-snap-test) | 39 | add_qt_test_by_name(usb-snap-test) |
639 | 35 | 40 | ||
640 | === modified file 'tests/unit/adbd-client-test.cpp' | |||
641 | --- tests/unit/adbd-client-test.cpp 2016-03-17 15:24:41 +0000 | |||
642 | +++ tests/unit/adbd-client-test.cpp 2016-10-21 11:40:57 +0000 | |||
643 | @@ -73,7 +73,7 @@ | |||
644 | 73 | // start an AdbdClient that listens for PKRequests | 73 | // start an AdbdClient that listens for PKRequests |
645 | 74 | std::string pk; | 74 | std::string pk; |
646 | 75 | auto adbd_client = std::make_shared<GAdbdClient>(socket_path); | 75 | auto adbd_client = std::make_shared<GAdbdClient>(socket_path); |
648 | 76 | adbd_client->on_pk_request().connect([&pk, main_thread, test](const AdbdClient::PKRequest& req){ | 76 | auto connection = adbd_client->on_pk_request().connect([&pk, main_thread, test](const AdbdClient::PKRequest& req){ |
649 | 77 | EXPECT_EQ(main_thread, g_thread_self()); | 77 | EXPECT_EQ(main_thread, g_thread_self()); |
650 | 78 | g_message("in on_pk_request with %s", req.public_key.c_str()); | 78 | g_message("in on_pk_request with %s", req.public_key.c_str()); |
651 | 79 | pk = req.public_key; | 79 | pk = req.public_key; |
652 | @@ -82,12 +82,13 @@ | |||
653 | 82 | 82 | ||
654 | 83 | // start a mock AdbdServer with to fire test key requests and wait for a response | 83 | // start a mock AdbdServer with to fire test key requests and wait for a response |
655 | 84 | auto adbd_server = std::make_shared<GAdbdServer>(socket_path, std::vector<std::string>{test.request}); | 84 | auto adbd_server = std::make_shared<GAdbdServer>(socket_path, std::vector<std::string>{test.request}); |
657 | 85 | wait_for([adbd_server](){return !adbd_server->m_responses.empty();}, 2000); | 85 | wait_for([adbd_server](){return !adbd_server->m_responses.empty();}, 5000); |
658 | 86 | EXPECT_EQ(test.expected_pk, pk); | 86 | EXPECT_EQ(test.expected_pk, pk); |
659 | 87 | ASSERT_EQ(1, adbd_server->m_responses.size()); | 87 | ASSERT_EQ(1, adbd_server->m_responses.size()); |
660 | 88 | EXPECT_EQ(test.expected_response, adbd_server->m_responses.front()); | 88 | EXPECT_EQ(test.expected_response, adbd_server->m_responses.front()); |
661 | 89 | 89 | ||
662 | 90 | // cleanup | 90 | // cleanup |
663 | 91 | connection.disconnect(); | ||
664 | 91 | adbd_client.reset(); | 92 | adbd_client.reset(); |
665 | 92 | adbd_server.reset(); | 93 | adbd_server.reset(); |
666 | 93 | g_unlink(socket_path.c_str()); | 94 | g_unlink(socket_path.c_str()); |
667 | 94 | 95 | ||
668 | === added file 'tests/unit/greeter-test.cpp' | |||
669 | --- tests/unit/greeter-test.cpp 1970-01-01 00:00:00 +0000 | |||
670 | +++ tests/unit/greeter-test.cpp 2016-10-21 11:40:57 +0000 | |||
671 | @@ -0,0 +1,159 @@ | |||
672 | 1 | /* | ||
673 | 2 | * Copyright 2016 Canonical Ltd. | ||
674 | 3 | * | ||
675 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
676 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
677 | 6 | * by the Free Software Foundation. | ||
678 | 7 | * | ||
679 | 8 | * This program is distributed in the hope that it will be useful, but | ||
680 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
681 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
682 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
683 | 12 | * | ||
684 | 13 | * You should have received a copy of the GNU General Public License along | ||
685 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
686 | 15 | * | ||
687 | 16 | * Authors: | ||
688 | 17 | * Charles Kerr <charles.kerr@canonical.com> | ||
689 | 18 | */ | ||
690 | 19 | |||
691 | 20 | #include <tests/utils/qt-fixture.h> | ||
692 | 21 | #include <tests/utils/gtest-print-helpers.h> | ||
693 | 22 | |||
694 | 23 | #include <src/dbus-names.h> | ||
695 | 24 | #include <src/greeter.h> | ||
696 | 25 | |||
697 | 26 | #include <libqtdbustest/DBusTestRunner.h> | ||
698 | 27 | #include <libqtdbustest/QProcessDBusService.h> | ||
699 | 28 | #include <libqtdbusmock/DBusMock.h> | ||
700 | 29 | |||
701 | 30 | class GreeterFixture: public QtFixture | ||
702 | 31 | { | ||
703 | 32 | private: | ||
704 | 33 | |||
705 | 34 | using super = QtFixture; | ||
706 | 35 | |||
707 | 36 | public: | ||
708 | 37 | |||
709 | 38 | GreeterFixture() =default; | ||
710 | 39 | ~GreeterFixture() =default; | ||
711 | 40 | |||
712 | 41 | protected: | ||
713 | 42 | |||
714 | 43 | std::shared_ptr<QtDBusTest::DBusTestRunner> m_dbus_runner; | ||
715 | 44 | std::shared_ptr<QtDBusMock::DBusMock> m_dbus_mock; | ||
716 | 45 | GDBusConnection* m_bus {}; | ||
717 | 46 | |||
718 | 47 | void SetUp() override | ||
719 | 48 | { | ||
720 | 49 | super::SetUp(); | ||
721 | 50 | |||
722 | 51 | // use a fresh bus for each test run | ||
723 | 52 | m_dbus_runner.reset(new QtDBusTest::DBusTestRunner()); | ||
724 | 53 | m_dbus_mock.reset(new QtDBusMock::DBusMock(*m_dbus_runner.get())); | ||
725 | 54 | |||
726 | 55 | GError* error {}; | ||
727 | 56 | m_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, nullptr, &error); | ||
728 | 57 | g_assert_no_error(error); | ||
729 | 58 | g_dbus_connection_set_exit_on_close(m_bus, FALSE); | ||
730 | 59 | } | ||
731 | 60 | |||
732 | 61 | void TearDown() override | ||
733 | 62 | { | ||
734 | 63 | g_clear_object(&m_bus); | ||
735 | 64 | |||
736 | 65 | super::TearDown(); | ||
737 | 66 | } | ||
738 | 67 | |||
739 | 68 | void start_greeter_service(bool is_active) | ||
740 | 69 | { | ||
741 | 70 | // set a watcher to look for our mock greeter to appear | ||
742 | 71 | bool owned {}; | ||
743 | 72 | QDBusServiceWatcher watcher( | ||
744 | 73 | DBusNames::UnityGreeter::NAME, | ||
745 | 74 | m_dbus_runner->sessionConnection() | ||
746 | 75 | ); | ||
747 | 76 | QObject::connect( | ||
748 | 77 | &watcher, | ||
749 | 78 | &QDBusServiceWatcher::serviceRegistered, | ||
750 | 79 | [&owned](const QString&){owned = true;} | ||
751 | 80 | ); | ||
752 | 81 | |||
753 | 82 | // start the mock greeter | ||
754 | 83 | QVariantMap parameters; | ||
755 | 84 | parameters["IsActive"] = QVariant(is_active); | ||
756 | 85 | m_dbus_mock->registerTemplate( | ||
757 | 86 | DBusNames::UnityGreeter::NAME, | ||
758 | 87 | GREETER_TEMPLATE, | ||
759 | 88 | parameters, | ||
760 | 89 | QDBusConnection::SessionBus | ||
761 | 90 | ); | ||
762 | 91 | m_dbus_runner->startServices(); | ||
763 | 92 | |||
764 | 93 | // wait for the watcher | ||
765 | 94 | ASSERT_TRUE(wait_for([&owned]{return owned;})); | ||
766 | 95 | } | ||
767 | 96 | }; | ||
768 | 97 | |||
769 | 98 | #define ASSERT_PROPERTY_EQ_EVENTUALLY(expected_in, property_in) \ | ||
770 | 99 | do { \ | ||
771 | 100 | const auto& e = expected_in; \ | ||
772 | 101 | const auto& p = property_in; \ | ||
773 | 102 | ASSERT_TRUE(wait_for([e, &p](){return e == p.get();})) \ | ||
774 | 103 | << "expected " << e << " but got " << p.get(); \ | ||
775 | 104 | } while(0) | ||
776 | 105 | |||
777 | 106 | /** | ||
778 | 107 | * Test startup timing by looking at four different cases: | ||
779 | 108 | * [unity greeter shows up on bus (before, after) we start listening] | ||
780 | 109 | * x [unity greeter is (active, inactive)] | ||
781 | 110 | */ | ||
782 | 111 | |||
783 | 112 | TEST_F(GreeterFixture, ActiveServiceStartsBeforeWatcher) | ||
784 | 113 | { | ||
785 | 114 | constexpr bool is_active {true}; | ||
786 | 115 | constexpr Greeter::State expected {Greeter::State::ACTIVE}; | ||
787 | 116 | |||
788 | 117 | start_greeter_service(is_active); | ||
789 | 118 | |||
790 | 119 | UnityGreeter greeter; | ||
791 | 120 | |||
792 | 121 | ASSERT_PROPERTY_EQ_EVENTUALLY(expected, greeter.state()); | ||
793 | 122 | } | ||
794 | 123 | |||
795 | 124 | TEST_F(GreeterFixture, WatcherStartsBeforeActiveService) | ||
796 | 125 | { | ||
797 | 126 | constexpr bool is_active {true}; | ||
798 | 127 | constexpr Greeter::State expected {Greeter::State::ACTIVE}; | ||
799 | 128 | |||
800 | 129 | UnityGreeter greeter; | ||
801 | 130 | |||
802 | 131 | start_greeter_service(is_active); | ||
803 | 132 | |||
804 | 133 | ASSERT_PROPERTY_EQ_EVENTUALLY(expected, greeter.state()); | ||
805 | 134 | } | ||
806 | 135 | |||
807 | 136 | TEST_F(GreeterFixture, InactiveServiceStartsBeforeWatcher) | ||
808 | 137 | { | ||
809 | 138 | constexpr bool is_active {false}; | ||
810 | 139 | constexpr Greeter::State expected {Greeter::State::INACTIVE}; | ||
811 | 140 | |||
812 | 141 | start_greeter_service(is_active); | ||
813 | 142 | |||
814 | 143 | UnityGreeter greeter; | ||
815 | 144 | |||
816 | 145 | ASSERT_PROPERTY_EQ_EVENTUALLY(expected, greeter.state()); | ||
817 | 146 | } | ||
818 | 147 | |||
819 | 148 | TEST_F(GreeterFixture, WatcherStartsBeforeInactiveService) | ||
820 | 149 | { | ||
821 | 150 | constexpr bool is_active {false}; | ||
822 | 151 | constexpr Greeter::State expected {Greeter::State::INACTIVE}; | ||
823 | 152 | |||
824 | 153 | UnityGreeter greeter; | ||
825 | 154 | |||
826 | 155 | start_greeter_service(is_active); | ||
827 | 156 | |||
828 | 157 | ASSERT_PROPERTY_EQ_EVENTUALLY(expected, greeter.state()); | ||
829 | 158 | } | ||
830 | 159 | |||
831 | 0 | 160 | ||
832 | === modified file 'tests/unit/usb-snap-test.cpp' | |||
833 | --- tests/unit/usb-snap-test.cpp 2016-03-23 17:16:06 +0000 | |||
834 | +++ tests/unit/usb-snap-test.cpp 2016-10-21 11:40:57 +0000 | |||
835 | @@ -88,7 +88,7 @@ | |||
836 | 88 | auto snap = std::make_shared<UsbSnap>(test.fingerprint); | 88 | auto snap = std::make_shared<UsbSnap>(test.fingerprint); |
837 | 89 | AdbdClient::PKResponse user_response {}; | 89 | AdbdClient::PKResponse user_response {}; |
838 | 90 | bool user_response_set = false; | 90 | bool user_response_set = false; |
840 | 91 | snap->on_user_response().connect([&user_response,&user_response_set](AdbdClient::PKResponse response, bool /*remember*/){ | 91 | auto connection = snap->on_user_response().connect([&user_response,&user_response_set](AdbdClient::PKResponse response, bool /*remember*/){ |
841 | 92 | user_response = response; | 92 | user_response = response; |
842 | 93 | user_response_set = true; | 93 | user_response_set = true; |
843 | 94 | }); | 94 | }); |
844 | @@ -130,14 +130,9 @@ | |||
845 | 130 | EXPECT_TRUE(user_response_set); | 130 | EXPECT_TRUE(user_response_set); |
846 | 131 | ASSERT_EQ(test.expected_response, user_response); | 131 | ASSERT_EQ(test.expected_response, user_response); |
847 | 132 | 132 | ||
849 | 133 | // confirm that the snap dtor cleans up the notification | 133 | // confirm that the snap dtor doesn't try to close |
850 | 134 | // the notification that's already been closed by user choice | ||
851 | 134 | snap.reset(); | 135 | snap.reset(); |
859 | 135 | wait_for_signals(notificationsSpy, 1); | 136 | EXPECT_FALSE(notificationsSpy.wait(1000)); |
853 | 136 | { | ||
854 | 137 | QVariantList const& call(notificationsSpy.at(0)); | ||
855 | 138 | EXPECT_EQ("CloseNotification", call.at(0)); | ||
856 | 139 | QVariantList const& args(call.at(1).toList()); | ||
857 | 140 | EXPECT_EQ(id, args.at(0)); | ||
858 | 141 | } | ||
860 | 142 | } | 137 | } |
861 | 143 | } | 138 | } |
862 | 144 | 139 | ||
863 | === modified file 'tests/utils/adbd-server.h' | |||
864 | --- tests/utils/adbd-server.h 2016-03-24 16:01:16 +0000 | |||
865 | +++ tests/utils/adbd-server.h 2016-10-21 11:40:57 +0000 | |||
866 | @@ -38,7 +38,7 @@ | |||
867 | 38 | GAdbdServer(const std::string& socket_path, | 38 | GAdbdServer(const std::string& socket_path, |
868 | 39 | const std::vector<std::string>& requests): | 39 | const std::vector<std::string>& requests): |
869 | 40 | m_requests{requests}, | 40 | m_requests{requests}, |
871 | 41 | m_socket_path{socket_path}, | 41 | m_server_socket{create_server_socket(socket_path)}, |
872 | 42 | m_cancellable{g_cancellable_new()}, | 42 | m_cancellable{g_cancellable_new()}, |
873 | 43 | m_worker_thread{&GAdbdServer::worker_func, this} | 43 | m_worker_thread{&GAdbdServer::worker_func, this} |
874 | 44 | { | 44 | { |
875 | @@ -50,6 +50,7 @@ | |||
876 | 50 | g_cancellable_cancel(m_cancellable); | 50 | g_cancellable_cancel(m_cancellable); |
877 | 51 | m_worker_thread.join(); | 51 | m_worker_thread.join(); |
878 | 52 | g_clear_object(&m_cancellable); | 52 | g_clear_object(&m_cancellable); |
879 | 53 | g_clear_object(&m_server_socket); | ||
880 | 53 | } | 54 | } |
881 | 54 | 55 | ||
882 | 55 | const std::vector<std::string> m_requests; | 56 | const std::vector<std::string> m_requests; |
883 | @@ -59,18 +60,14 @@ | |||
884 | 59 | 60 | ||
885 | 60 | void worker_func() // runs in worker thread | 61 | void worker_func() // runs in worker thread |
886 | 61 | { | 62 | { |
887 | 62 | auto server_socket = create_server_socket(m_socket_path); | ||
888 | 63 | auto requests = m_requests; | 63 | auto requests = m_requests; |
889 | 64 | 64 | ||
890 | 65 | GError* error {}; | ||
891 | 66 | g_socket_listen (server_socket, &error); | ||
892 | 67 | g_assert_no_error (error); | ||
893 | 68 | |||
894 | 69 | while (!g_cancellable_is_cancelled(m_cancellable) && !requests.empty()) | 65 | while (!g_cancellable_is_cancelled(m_cancellable) && !requests.empty()) |
895 | 70 | { | 66 | { |
896 | 71 | // wait for a client connection | 67 | // wait for a client connection |
897 | 72 | g_message("GAdbdServer::Impl::worker_func() calling g_socket_accept()"); | 68 | g_message("GAdbdServer::Impl::worker_func() calling g_socket_accept()"); |
899 | 73 | auto client_socket = g_socket_accept(server_socket, m_cancellable, &error); | 69 | GError* error {}; |
900 | 70 | auto client_socket = g_socket_accept(m_server_socket, m_cancellable, &error); | ||
901 | 74 | if (error != nullptr) { | 71 | if (error != nullptr) { |
902 | 75 | if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) | 72 | if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
903 | 76 | g_message("GAdbdServer: Error accepting socket connection: %s", error->message); | 73 | g_message("GAdbdServer: Error accepting socket connection: %s", error->message); |
904 | @@ -121,8 +118,6 @@ | |||
905 | 121 | // cleanup | 118 | // cleanup |
906 | 122 | g_clear_object(&client_socket); | 119 | g_clear_object(&client_socket); |
907 | 123 | } | 120 | } |
908 | 124 | |||
909 | 125 | g_clear_object(&server_socket); | ||
910 | 126 | } | 121 | } |
911 | 127 | 122 | ||
912 | 128 | // bind to a local domain socket | 123 | // bind to a local domain socket |
913 | @@ -139,11 +134,14 @@ | |||
914 | 139 | g_assert_no_error (error); | 134 | g_assert_no_error (error); |
915 | 140 | g_clear_object (&address); | 135 | g_clear_object (&address); |
916 | 141 | 136 | ||
917 | 137 | g_socket_listen (socket, &error); | ||
918 | 138 | g_assert_no_error (error); | ||
919 | 139 | |||
920 | 142 | return socket; | 140 | return socket; |
921 | 143 | } | 141 | } |
922 | 144 | 142 | ||
925 | 145 | const std::string m_socket_path; | 143 | GSocket* m_server_socket {}; |
926 | 146 | GCancellable* m_cancellable = nullptr; | 144 | GCancellable* m_cancellable {}; |
927 | 147 | std::thread m_worker_thread; | 145 | std::thread m_worker_thread; |
928 | 148 | }; | 146 | }; |
929 | 149 | 147 | ||
930 | 150 | 148 | ||
931 | === added file 'tests/utils/gtest-print-helpers.h' | |||
932 | --- tests/utils/gtest-print-helpers.h 1970-01-01 00:00:00 +0000 | |||
933 | +++ tests/utils/gtest-print-helpers.h 2016-10-21 11:40:57 +0000 | |||
934 | @@ -0,0 +1,18 @@ | |||
935 | 1 | |||
936 | 2 | #pragma once | ||
937 | 3 | |||
938 | 4 | #include <src/greeter.h> | ||
939 | 5 | |||
940 | 6 | inline void PrintTo(const Greeter::State& state, std::ostream* os) { | ||
941 | 7 | switch(state) { | ||
942 | 8 | case Greeter::State::ACTIVE: *os << "Active"; break; | ||
943 | 9 | case Greeter::State::INACTIVE: *os << "Inactive"; break; | ||
944 | 10 | case Greeter::State::UNAVAILABLE: *os << "Unavailable"; break; | ||
945 | 11 | } | ||
946 | 12 | } | ||
947 | 13 | |||
948 | 14 | inline std::ostream& operator<<(std::ostream& os, const Greeter::State& state) { | ||
949 | 15 | PrintTo(state, &os); | ||
950 | 16 | return os; | ||
951 | 17 | } | ||
952 | 18 | |||
953 | 0 | 19 | ||
954 | === modified file 'tests/utils/mock-greeter.h' | |||
955 | --- tests/utils/mock-greeter.h 2016-03-22 20:39:36 +0000 | |||
956 | +++ tests/utils/mock-greeter.h 2016-10-21 11:40:57 +0000 | |||
957 | @@ -26,7 +26,7 @@ | |||
958 | 26 | public: | 26 | public: |
959 | 27 | MockGreeter() =default; | 27 | MockGreeter() =default; |
960 | 28 | virtual ~MockGreeter() =default; | 28 | virtual ~MockGreeter() =default; |
963 | 29 | core::Property<bool>& is_active() override {return m_is_active;} | 29 | core::Property<Greeter::State>& state() override {return m_state;} |
964 | 30 | core::Property<bool> m_is_active {false}; | 30 | core::Property<Greeter::State> m_state {State::INACTIVE}; |
965 | 31 | }; | 31 | }; |
966 | 32 | 32 | ||
967 | 33 | 33 | ||
968 | === added file 'tests/utils/mock-unity-greeter.py' | |||
969 | --- tests/utils/mock-unity-greeter.py 1970-01-01 00:00:00 +0000 | |||
970 | +++ tests/utils/mock-unity-greeter.py 2016-10-21 11:40:57 +0000 | |||
971 | @@ -0,0 +1,41 @@ | |||
972 | 1 | '''unity greeter mock template | ||
973 | 2 | |||
974 | 3 | Very basic template that just mocks the greeter is-active flag | ||
975 | 4 | ''' | ||
976 | 5 | |||
977 | 6 | # This program is free software; you can redistribute it and/or modify it under | ||
978 | 7 | # the terms of the GNU Lesser General Public License as published by the Free | ||
979 | 8 | # Software Foundation; either version 3 of the License, or (at your option) any | ||
980 | 9 | # later version. See http://www.gnu.org/copyleft/lgpl.html for the full text | ||
981 | 10 | # of the license. | ||
982 | 11 | |||
983 | 12 | __author__ = 'Charles Kerr' | ||
984 | 13 | __email__ = 'charles.kerr@canonical.com' | ||
985 | 14 | __copyright__ = '(c) 2016 Canonical Ltd.' | ||
986 | 15 | __license__ = 'LGPL 3+' | ||
987 | 16 | |||
988 | 17 | import dbus | ||
989 | 18 | import os | ||
990 | 19 | |||
991 | 20 | from dbusmock import MOCK_IFACE, mockobject | ||
992 | 21 | |||
993 | 22 | BUS_NAME = 'com.canonical.UnityGreeter' | ||
994 | 23 | MAIN_OBJ = '/' | ||
995 | 24 | MAIN_IFACE = 'com.canonical.UnityGreeter' | ||
996 | 25 | SYSTEM_BUS = False | ||
997 | 26 | |||
998 | 27 | |||
999 | 28 | def load(mock, parameters): | ||
1000 | 29 | mock.AddMethods( | ||
1001 | 30 | MAIN_IFACE, [ | ||
1002 | 31 | ('HideGreeter', '', '', 'self.Set("com.canonical.UnityGreeter", "IsActive", False)'), | ||
1003 | 32 | ('ShowGreeter', '', '', 'self.Set("com.canonical.UnityGreeter", "IsActive", True)') | ||
1004 | 33 | ] | ||
1005 | 34 | ) | ||
1006 | 35 | mock.AddProperties( | ||
1007 | 36 | MAIN_IFACE, | ||
1008 | 37 | dbus.Dictionary({ | ||
1009 | 38 | 'IsActive': parameters.get('IsActive', False), | ||
1010 | 39 | }, signature='sv') | ||
1011 | 40 | ) | ||
1012 | 41 |
FAILED: Continuous integration, rev:20 /jenkins. canonical. com/unity- api-1/job/ lp-indicator- display- ci/4/ /jenkins. canonical. com/unity- api-1/job/ build/719/ console /jenkins. canonical. com/unity- api-1/job/ build-0- fetch/725 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 533 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 533/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 533 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 533/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 533/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 533 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 533/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 533 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 533/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 533/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 533 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 533/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 533 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 533/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= yakkety/ 533/console
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild: /jenkins. canonical. com/unity- api-1/job/ lp-indicator- display- ci/4/rebuild
https:/