Merge lp:~nick-dedekind/ubuntu-settings-components/fix-maximumWaitBufferInterval into lp:~registry/ubuntu-settings-components/trunk

Proposed by Nick Dedekind
Status: Merged
Approved by: Albert Astals Cid
Approved revision: 90
Merged at revision: 88
Proposed branch: lp:~nick-dedekind/ubuntu-settings-components/fix-maximumWaitBufferInterval
Merge into: lp:~registry/ubuntu-settings-components/trunk
Diff against target: 313 lines (+84/-57)
3 files modified
plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.cpp (+60/-41)
plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.h (+5/-2)
tests/qmltests/Components/tst_ServerPropertySynchroniser.qml (+19/-14)
To merge this branch: bzr merge lp:~nick-dedekind/ubuntu-settings-components/fix-maximumWaitBufferInterval
Reviewer Review Type Date Requested Status
Albert Astals Cid (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Registry Administrators Pending
Review via email: mp+257347@code.launchpad.net

Commit message

ServerPropertySynchorniser - Do not update to old server value when the control is no longer buffering.

Description of the change

Fix and test for autopilot failures:
https://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-mako/2076/#showFailuresLink

Do not update to old server value when the control is no longer buffering.

 * Are there any related MPs required for this MP to build/function as expected? Please list.
https://code.launchpad.net/~nick-dedekind/unity8/fix-laggy-indicators-autopilot/+merge/258411

 * Did you perform an exploratory manual test run of your code change and any related functionality?
Yes

 * If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
N/A

 * If you changed the UI, has there been a design review?
N/A

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

better test for max_interval

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Albert Astals Cid (aacid) wrote :

running autopilot3 run unity8.indicators.tests.test_action_latency.TestBuffering.test_slider_buffers_activations
gives me

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/unity8/indicators/tests/test_action_latency.py", line 163, in test_slider_buffers_activations
    NotEquals(final_value)
  File "/usr/lib/python3/dist-packages/testtools/testcase.py", line 423, in assertThat
    raise mismatch_error
testtools.matchers._impl.MismatchError: 1.0 == 1.0

Ran 1 test in 25.957s
FAILED (failures=1)

review: Needs Fixing
90. By Nick Dedekind

Fixed some more problems with activation damping

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Albert Astals Cid (aacid) wrote :

In the krillin phone
  autopilot3 run unity8.indicators.tests.test_action_latency.TestBuffering.test_slider_buffers_activations

Still gives me

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/unity8/indicators/tests/test_action_latency.py", line 163, in test_slider_buffers_activations
    NotEquals(final_value)
  File "/usr/lib/python3/dist-packages/testtools/testcase.py", line 423, in assertThat
    raise mismatch_error
testtools.matchers._impl.MismatchError: 1.0 == 1.0

Am i actually right in thinking this branch has to fix that autopilot test or am i testing the wrong thing?

review: Needs Fixing
Revision history for this message
Albert Astals Cid (aacid) wrote :

Ok, together with the required MP i can confirm this fixes unity8.indicators.tests.test_action_latency.TestClientRevertsToServerValue.test_slider_reverts_on_late_response and unity8.indicators.tests.test_action_latency.TestBuffering.test_slider_buffers_activations

Now to review the code

Revision history for this message
Albert Astals Cid (aacid) wrote :

 * Did you perform an exploratory manual test run of the code change and any related functionality?
Yes

 * Did CI run pass? If not, please explain why.
Yes

 * Did you make sure that the branch does not contain spurious tags?
Yes

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.cpp'
2--- plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.cpp 2015-03-25 09:16:06 +0000
3+++ plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.cpp 2015-05-06 16:32:05 +0000
4@@ -29,10 +29,12 @@
5 , m_connectedServerTarget(nullptr)
6 , m_connectedUserTarget(nullptr)
7 , m_serverSyncTimer(new QTimer(this))
8- , m_bufferTimeout(nullptr)
9+ , m_bufferDamper(nullptr)
10 , m_useWaitBuffer(true)
11- , m_buffering(false)
12+ , m_haveNextActivate(false)
13 , m_bufferedSyncTimeout(false)
14+ , m_serverUpdatedDuringBufferDamping(false)
15+ , m_activateCount(0)
16 {
17 m_serverSyncTimer->setSingleShot(true);
18 m_serverSyncTimer->setInterval(30000);
19@@ -57,8 +59,10 @@
20 m_serverSyncTimer->stop();
21 Q_EMIT syncWaitingChanged(false);
22 }
23- if (m_bufferTimeout) m_bufferTimeout->stop();
24- m_buffering = false;
25+ if (m_bufferDamper) m_bufferDamper->stop();
26+ m_haveNextActivate = false;
27+ m_activateCount = 0;
28+ m_serverUpdatedDuringBufferDamping = false;
29 }
30
31 QObject *ServerPropertySynchroniser::serverTarget() const
32@@ -164,31 +168,31 @@
33
34 int ServerPropertySynchroniser::maximumWaitBufferInterval() const
35 {
36- return m_bufferTimeout ? m_bufferTimeout->interval() : -1;
37+ return m_bufferDamper ? m_bufferDamper->interval() : -1;
38 }
39
40 void ServerPropertySynchroniser::setMaximumWaitBufferInterval(int timeout)
41 {
42 if (timeout >= 0) {
43- if (!m_bufferTimeout) {
44- m_bufferTimeout = new QTimer(this);
45- m_bufferTimeout->setInterval(timeout);
46- m_bufferTimeout->setSingleShot(true);
47- connect(m_bufferTimeout, &QTimer::timeout, this, &ServerPropertySynchroniser::bufferTimedOut);
48-
49- Q_EMIT maximumWaitBufferIntervalChanged(timeout);
50- }
51- else if (timeout != m_bufferTimeout->interval()) {
52- m_bufferTimeout->setInterval(timeout);
53- Q_EMIT maximumWaitBufferIntervalChanged(timeout);
54- }
55-
56- } else if (m_bufferTimeout) {
57- if (m_bufferTimeout->isActive()) {
58- m_buffering = false;
59- }
60- delete m_bufferTimeout;
61- m_bufferTimeout = nullptr;
62+ if (!m_bufferDamper) {
63+ m_bufferDamper = new QTimer(this);
64+ m_bufferDamper->setInterval(timeout);
65+ m_bufferDamper->setSingleShot(true);
66+ connect(m_bufferDamper, &QTimer::timeout, this, &ServerPropertySynchroniser::bufferTimedOut);
67+
68+ Q_EMIT maximumWaitBufferIntervalChanged(timeout);
69+ }
70+ else if (timeout != m_bufferDamper->interval()) {
71+ m_bufferDamper->setInterval(timeout);
72+ Q_EMIT maximumWaitBufferIntervalChanged(timeout);
73+ }
74+
75+ } else if (m_bufferDamper) {
76+ if (m_bufferDamper->isActive()) {
77+ m_haveNextActivate = false;
78+ }
79+ delete m_bufferDamper;
80+ m_bufferDamper = nullptr;
81 Q_EMIT maximumWaitBufferIntervalChanged(timeout);
82 }
83 }
84@@ -219,16 +223,16 @@
85
86 if (m_useWaitBuffer) {
87 // Dampen the activations? Buffer the change.
88- if (m_bufferTimeout) {
89- if (m_bufferTimeout->isActive()) {
90- m_buffering = true;
91+ if (m_bufferDamper) {
92+ if (m_bufferDamper->isActive()) {
93+ m_haveNextActivate = true;
94 m_busy = false;
95 return;
96 }
97- m_bufferTimeout->start();
98- // Not using a buffer timer? Buffer the change till server timeout
99+ m_bufferDamper->start();
100+ // Not using a damp interval? Buffer the change till we get a server response, or timeout
101 } else if (m_serverSyncTimer->isActive()) {
102- m_buffering = true;
103+ m_haveNextActivate = true;
104 m_busy = false;
105 return;
106 }
107@@ -236,6 +240,7 @@
108
109 m_serverSyncTimer->start();
110 Q_EMIT syncWaitingChanged(true);
111+ m_activateCount++;
112
113 // Fire off a change to the server user property value
114 QQmlProperty userProp(m_userTarget, m_userProperty);
115@@ -251,6 +256,7 @@
116 {
117 // if we havent finished constructing the class, then wait
118 if (!m_classComplete) return;
119+ reset();
120
121 if (m_connectedServerTarget) QObject::disconnect(m_connectedServerTarget, 0, this, 0);
122 if (!m_serverTarget || m_serverProperty.isEmpty()) {
123@@ -273,6 +279,7 @@
124 {
125 // if we havent finished constructing the class, then wait
126 if (!m_classComplete) return;
127+ reset();
128
129 if (m_connectedUserTarget) QObject::disconnect(m_connectedUserTarget, 0, this, 0);
130 if (!m_userTarget) {
131@@ -313,13 +320,21 @@
132 if (m_busy) return;
133 m_busy = true;
134
135- bool waitingBufferedServerChange = m_bufferTimeout && m_bufferTimeout->isActive();
136-
137- // If we've been waiting for a sync, stop the wait.
138+ // Are we waiting for a server sync.
139 if (m_serverSyncTimer->isActive()) {
140+ // are we waiting for more from the server? (number of activates sent > number of receives)
141+ if (--m_activateCount > 0) {
142+ // ignore the change and update on server sync timeout.
143+ m_busy = false;
144+ return;
145+ }
146+
147+ // stop the wait
148 m_serverSyncTimer->stop();
149 Q_EMIT syncWaitingChanged(false);
150 }
151+ m_activateCount = 0;
152+ m_serverUpdatedDuringBufferDamping = m_bufferDamper && m_bufferDamper->isActive();
153
154 QQmlProperty userProp(m_userTarget, m_userProperty);
155 QQmlProperty serverProp(m_serverTarget, m_serverProperty);
156@@ -331,8 +346,8 @@
157 // If we've been buffering changes since last change was send,
158 // we verify that what the server gave us is what we want, and send another
159 // activation if not.
160- if (m_buffering) {
161- m_buffering = false;
162+ if (m_haveNextActivate) {
163+ m_haveNextActivate = false;
164 m_busy = false;
165 if (serverProp.read() != userProp.read()) {
166 activate();
167@@ -341,7 +356,7 @@
168 }
169
170 // Don't update until we hit the buffer timeout.
171- if (waitingBufferedServerChange) {
172+ if (m_serverUpdatedDuringBufferDamping) {
173 m_busy = false;
174 return;
175 }
176@@ -353,8 +368,8 @@
177
178 void ServerPropertySynchroniser::serverSyncTimedOut()
179 {
180- if (m_buffering && !m_bufferedSyncTimeout) {
181- m_buffering = false;
182+ if (m_haveNextActivate && !m_bufferedSyncTimeout) {
183+ m_haveNextActivate = false;
184 }
185 Q_EMIT syncWaitingChanged(false);
186 updateUserValue();
187@@ -362,10 +377,13 @@
188
189 void ServerPropertySynchroniser::bufferTimedOut()
190 {
191- if (m_buffering) {
192- m_buffering = false;
193+ if (m_haveNextActivate) {
194+ m_haveNextActivate = false;
195 activate();
196- } else {
197+ }
198+ // if we received a server change while we were in change buffer but don't need to send another activate,
199+ // update to the value we received.
200+ else if (m_serverUpdatedDuringBufferDamping) {
201 // Update the user value.
202 if (m_busy) return;
203 m_busy = true;
204@@ -379,4 +397,5 @@
205 userProp.write(serverProp.read());
206 m_busy = false;
207 }
208+ m_serverUpdatedDuringBufferDamping = false;
209 }
210
211=== modified file 'plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.h'
212--- plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.h 2015-03-25 09:16:06 +0000
213+++ plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.h 2015-05-06 16:32:05 +0000
214@@ -148,10 +148,13 @@
215 QObject* m_connectedUserTarget;
216
217 QTimer* m_serverSyncTimer;
218- QTimer* m_bufferTimeout;
219+ QTimer* m_bufferDamper;
220 bool m_useWaitBuffer;
221- bool m_buffering;
222+ bool m_haveNextActivate;
223 bool m_bufferedSyncTimeout;
224+ bool m_serverUpdatedDuringBufferDamping;
225+
226+ int m_activateCount;
227 };
228
229 #endif // SERVERPROPERTYSYNCHRONISER_H
230
231=== modified file 'tests/qmltests/Components/tst_ServerPropertySynchroniser.qml'
232--- tests/qmltests/Components/tst_ServerPropertySynchroniser.qml 2015-03-25 09:16:06 +0000
233+++ tests/qmltests/Components/tst_ServerPropertySynchroniser.qml 2015-05-06 16:32:05 +0000
234@@ -58,7 +58,7 @@
235 property var changeToValue: undefined
236
237 property Timer timer: Timer {
238- interval: 200
239+ interval: 2000
240
241 onTriggered: {
242 sliderBackend.value = sliderBackend.changeToValue;
243@@ -165,6 +165,7 @@
244 objectName: "sliderSync"
245
246 syncTimeout: 3000
247+ maximumWaitBufferInterval: 50
248
249 userTarget: slider
250 userProperty: "value"
251@@ -276,14 +277,20 @@
252
253 function init() {
254 waitForRendering(root);
255+
256+ switchSync.reset();
257+ checkSync.reset();
258+ sliderSync.reset();
259+ apMenuSync.reset();
260+
261 switchBackend.timer.interval = 100;
262 checkBackend.timer.interval = 100;
263- sliderBackend.timer.interval = 100;
264+ sliderBackend.timer.interval = 200;
265 apBackend.timer.interval = 100;
266
267 switchSync.syncTimeout = 200;
268 checkSync.syncTimeout = 200;
269- sliderSync.syncTimeout = 200;
270+ sliderSync.syncTimeout = 400;
271 apMenuSync.syncTimeout = 200;
272
273 sliderSyncActivatedSpy.clear();
274@@ -300,10 +307,6 @@
275 sliderBackend.value = 50;
276 apBackend.active = false;
277
278- switchSync.reset();
279- checkSync.reset();
280- sliderSync.reset();
281- apMenuSync.reset();
282 sliderSync.maximumWaitBufferInterval = -1
283
284 tryCompare(switchBackend, "inSync", true);
285@@ -350,19 +353,21 @@
286 }
287
288 function test_buffered_change_with_maximum_interval() {
289- sliderSync.maximumWaitBufferInterval = 50;
290+ sliderSync.maximumWaitBufferInterval = 25;
291 sliderSync.syncTimeout = 5000;
292
293 slider.value = 60;
294- compare(sliderSyncActivatedSpy.count, 1, "activated signal should have been sent")
295+ compare(sliderSyncActivatedSpy.count, 1, "activated signal should have been sent");
296 slider.value = 70;
297 slider.value = 80;
298- tryCompare(sliderSyncActivatedSpy, "count", 2, 500, "activated signal should have been sent after max interval")
299+ wait(100); // wait for buffer timeout
300+ tryCompare(sliderSyncActivatedSpy, "count", 2, 1000, "aditional activate signal should have been sent");
301+ compare(slider.value, 80, "value should be set to last activate");
302+
303 slider.value = 90;
304- tryCompare(sliderSyncActivatedSpy, "count", 3, 500, "activated signal should have been sent after max interval")
305- slider.value = 100;
306- tryCompare(sliderSyncActivatedSpy, "count", 4, 500);
307- tryCompare(sliderBackend, "value", 100);
308+ wait(100); // wait for buffer timeout
309+ tryCompare(sliderSyncActivatedSpy, "count", 3, 1000, "aditional activate signal should have been sent");
310+ compare(slider.value, 90, "value should be set to last activate");
311 }
312
313 function test_connect_to_another_object() {

Subscribers

People subscribed via source and target branches

to all changes: