Merge lp:~nataliabidart/ubuntuone-client/does-not-exist-to-u1fsfsm into lp:ubuntuone-client
- does-not-exist-to-u1fsfsm
- Merge into trunk
Proposed by
Natalia Bidart
Status: | Merged |
---|---|
Approved by: | Facundo Batista |
Approved revision: | not available |
Merged at revision: | not available |
Proposed branch: | lp:~nataliabidart/ubuntuone-client/does-not-exist-to-u1fsfsm |
Merge into: | lp:ubuntuone-client |
Diff against target: |
354 lines (+190/-20) 7 files modified
contrib/testing/testcase.py (+13/-0) tests/syncdaemon/test_action_queue.py (+65/-14) tests/syncdaemon/test_sync.py (+44/-2) ubuntuone/syncdaemon/action_queue.py (+7/-2) ubuntuone/syncdaemon/event_queue.py (+1/-0) ubuntuone/syncdaemon/sync.py (+8/-2) ubuntuone/syncdaemon/u1fsfsm.py (+52/-0) |
To merge this branch: | bzr merge lp:~nataliabidart/ubuntuone-client/does-not-exist-to-u1fsfsm |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Facundo Batista (community) | Approve | ||
Rick McBride (community) | Approve | ||
Review via email: mp+19057@code.launchpad.net |
Commit message
Added a new event AQ_DOWNLOAD_
Description of the change
To post a comment you must log in.
Revision history for this message
Natalia Bidart (nataliabidart) wrote : | # |
- 367. By Natalia Bidart
-
Removing server hash from AQ_DOWNLOAD_
DOES_NOT_ EXIST parameters. - 368. By Natalia Bidart
-
Removing server_hash from event definition.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'contrib/testing/testcase.py' |
2 | --- contrib/testing/testcase.py 2010-01-28 21:24:26 +0000 |
3 | +++ contrib/testing/testcase.py 2010-02-11 13:18:15 +0000 |
4 | @@ -602,3 +602,16 @@ |
5 | def handle_default(self, event_name, *args, **kwargs): |
6 | """Keep record of every event.""" |
7 | self.events.append((event_name, args, kwargs)) |
8 | + |
9 | + |
10 | +def noop(*args, **kwargs): |
11 | + """No op.""" |
12 | + |
13 | + |
14 | +class DummyClass(object): |
15 | + """Dummy class, does nothing.""" |
16 | + |
17 | + def __getattribute__(self, name): |
18 | + """Any attribute is a no-op.""" |
19 | + return noop |
20 | + |
21 | |
22 | === modified file 'tests/syncdaemon/test_action_queue.py' |
23 | --- tests/syncdaemon/test_action_queue.py 2010-01-29 18:09:48 +0000 |
24 | +++ tests/syncdaemon/test_action_queue.py 2010-02-11 13:18:15 +0000 |
25 | @@ -32,7 +32,7 @@ |
26 | |
27 | from contrib.testing.testcase import ( |
28 | BaseTwistedTestCase, FakeMain, |
29 | - MementoHandler, |
30 | + MementoHandler, DummyClass |
31 | ) |
32 | |
33 | from ubuntuone.storageprotocol import client, volumes |
34 | @@ -40,7 +40,7 @@ |
35 | from ubuntuone.syncdaemon.main import Main |
36 | from ubuntuone.syncdaemon.action_queue import ( |
37 | ActionQueue, ActionQueueCommand, CreateUDF, DeleteVolume, ListVolumes, |
38 | - NoisyRequestQueue, RequestQueue |
39 | + NoisyRequestQueue, RequestQueue, ListDir |
40 | ) |
41 | from ubuntuone.syncdaemon.event_queue import EventQueue, EVENTS |
42 | from ubuntuone.syncdaemon.volume_manager import UDF |
43 | @@ -187,18 +187,6 @@ |
44 | ]) |
45 | |
46 | |
47 | -def noop(*args, **kwargs): |
48 | - """No op.""" |
49 | - |
50 | - |
51 | -class DummyClass(object): |
52 | - """Dummy class, does nothing.""" |
53 | - |
54 | - def __getattribute__(self, name): |
55 | - """Any attribute is a no-op.""" |
56 | - return noop |
57 | - |
58 | - |
59 | class FakedTwistedTestCase(unittest.TestCase): |
60 | """Helper for by-pass Twisted.""" |
61 | |
62 | @@ -581,3 +569,66 @@ |
63 | self.action_queue._node_state_callback(**kwargs) |
64 | self.assertEquals([('SV_HASH_NEW', (), kwargs)], |
65 | self.action_queue.event_queue.events) |
66 | + |
67 | + |
68 | +class ListDirTestCase(FakedTwistedTestCase): |
69 | + """Test for ListDir ActionQueueCommand.""" |
70 | + |
71 | + def setUp(self): |
72 | + """Init.""" |
73 | + super(ListDirTestCase, self).setUp() |
74 | + |
75 | + request_queue = RequestQueue(name='FOO', action_queue=self.factory) |
76 | + self.command = ListDir(request_queue, share_id='a_share_id', |
77 | + node_id='a_node_id', server_hash='a_server_hash', |
78 | + fileobj_factory=lambda: None) |
79 | + self.command.start_unqueued() |
80 | + |
81 | + def test_failure_with_CANCELLED(self): |
82 | + """AQ_DOWNLOAD_CANCELLED is pushed.""" |
83 | + msg = 'CANCELLED' |
84 | + failure = Failure(DefaultException(msg)) |
85 | + res = self.command.handle_failure(failure=failure) |
86 | + kwargs = dict(share_id='a_share_id', node_id='a_node_id', |
87 | + server_hash='a_server_hash') |
88 | + events = [('AQ_DOWNLOAD_CANCELLED', (), kwargs)] |
89 | + self.assertEquals(events, self.command.action_queue.event_queue.events) |
90 | + self.assertTrue(res is None) |
91 | + |
92 | + def test_failure_without_CANCELLED(self): |
93 | + """AQ_DOWNLOAD_ERROR with proper error is pushed.""" |
94 | + msg = 'NOT_CANCELLED' |
95 | + failure = Failure(DefaultException(msg)) |
96 | + res = self.command.handle_failure(failure=failure) |
97 | + kwargs = dict(share_id='a_share_id', node_id='a_node_id', |
98 | + server_hash='a_server_hash', error=msg) |
99 | + events = [('AQ_DOWNLOAD_ERROR', (), kwargs)] |
100 | + self.assertEquals(events, self.command.action_queue.event_queue.events) |
101 | + self.assertTrue(res is None) |
102 | + |
103 | + def test_failure_with_DOES_NOT_EXIST(self): |
104 | + """AQ_DOWNLOAD_DOES_NOT_EXIST is pushed.""" |
105 | + msg = 'DOES_NOT_EXIST' |
106 | + failure = Failure(DefaultException(msg)) |
107 | + res = self.command.handle_failure(failure=failure) |
108 | + kwargs = dict(share_id='a_share_id', node_id='a_node_id') |
109 | + events = [('AQ_DOWNLOAD_DOES_NOT_EXIST', (), kwargs)] |
110 | + self.assertEquals(events, self.command.action_queue.event_queue.events) |
111 | + self.assertTrue(res is None) |
112 | + |
113 | + def test_failure_without_DOES_NOT_EXIST(self): |
114 | + """AQ_DOWNLOAD_ERROR with proper error is pushed.""" |
115 | + msg = 'DOES_EXIST' |
116 | + failure = Failure(DefaultException(msg)) |
117 | + res = self.command.handle_failure(failure=failure) |
118 | + kwargs = dict(share_id='a_share_id', node_id='a_node_id', |
119 | + server_hash='a_server_hash', error=msg) |
120 | + events = [('AQ_DOWNLOAD_ERROR', (), kwargs)] |
121 | + self.assertEquals(events, self.command.action_queue.event_queue.events) |
122 | + self.assertTrue(res is None) |
123 | + |
124 | + def test_AQ_DOWNLOAD_DOES_NOT_EXIST_is_valid_event(self): |
125 | + """AQ_DOWNLOAD_DOES_NOT_EXIST is a valdi event.""" |
126 | + event = 'AQ_DOWNLOAD_DOES_NOT_EXIST' |
127 | + self.assertTrue(event in EVENTS) |
128 | + self.assertEquals(('share_id', 'node_id'), EVENTS[event]) |
129 | |
130 | === modified file 'tests/syncdaemon/test_sync.py' |
131 | --- tests/syncdaemon/test_sync.py 2010-01-22 20:31:51 +0000 |
132 | +++ tests/syncdaemon/test_sync.py 2010-02-11 13:18:15 +0000 |
133 | @@ -30,13 +30,13 @@ |
134 | from contrib.testing.testcase import ( |
135 | FakeVolumeManager, |
136 | BaseTwistedTestCase, |
137 | - MementoHandler, |
138 | + MementoHandler, DummyClass |
139 | ) |
140 | |
141 | from ubuntuone.syncdaemon.dbus_interface import DBusInterface |
142 | from ubuntuone.syncdaemon.filesystem_manager import FileSystemManager |
143 | from ubuntuone.syncdaemon.main import Main |
144 | -from ubuntuone.syncdaemon.sync import FSKey |
145 | +from ubuntuone.syncdaemon.sync import FSKey, Sync, SyncStateMachineRunner |
146 | from ubuntuone.syncdaemon.volume_manager import Share |
147 | from ubuntuone.syncdaemon.event_queue import EventQueue |
148 | |
149 | @@ -181,7 +181,10 @@ |
150 | |
151 | |
152 | class TestSync(BaseTwistedTestCase): |
153 | + """Test for Sync.""" |
154 | + |
155 | def setUp(self): |
156 | + """Init.""" |
157 | BaseTwistedTestCase.setUp(self) |
158 | self.root = self.mktemp('root') |
159 | self.shares = self.mktemp('shares') |
160 | @@ -204,6 +207,7 @@ |
161 | dbus.service.BusName.__del__ = lambda _: None |
162 | |
163 | def tearDown(self): |
164 | + """Clean up.""" |
165 | self.main.shutdown() |
166 | shutil.rmtree(self.root) |
167 | shutil.rmtree(self.shares) |
168 | @@ -215,6 +219,7 @@ |
169 | BaseTwistedTestCase.tearDown(self) |
170 | |
171 | def test_deleting_open_files_is_no_cause_for_despair(self): |
172 | + """test_deleting_open_files_is_no_cause_for_despair.""" |
173 | def cb(_): |
174 | d0 = self.main.wait_for('HQ_HASH_NEW') |
175 | f = file(self.root + '/a_file', 'w') |
176 | @@ -229,6 +234,7 @@ |
177 | return d |
178 | |
179 | def test_stomp_deleted_file_is_no_cause_for_despair_either(self): |
180 | + """test_stomp_deleted_file_is_no_cause_for_despair_either.""" |
181 | def cb(_): |
182 | d0 = self.main.wait_for('HQ_HASH_NEW') |
183 | f = file(self.root + '/a_file', 'w') |
184 | @@ -241,3 +247,39 @@ |
185 | self.main.start() |
186 | d.addCallback(cb) |
187 | return d |
188 | + |
189 | + def test_handle_AQ_DOWNLOAD_DOES_NOT_EXIST(self): |
190 | + """handle_AQ_DOWNLOAD_DOES_NOT_EXIST.""" |
191 | + sync = Sync(main=self.main) |
192 | + self.called = False |
193 | + |
194 | + def faked_nothing(ssmr, event, params, *args): |
195 | + """Wrap SSMR.nothing to test.""" |
196 | + self.called = True |
197 | + |
198 | + SyncStateMachineRunner.nothing = faked_nothing |
199 | + kwargs = dict(share_id='share_id', node_id='node_id') |
200 | + sync.handle_AQ_DOWNLOAD_DOES_NOT_EXIST(**kwargs) |
201 | + self.assertTrue(self.called, 'nothing was called') |
202 | + |
203 | + |
204 | +class SyncStateMachineRunnerTestCase(BaseTwistedTestCase): |
205 | + """Tests for the SyncStateMachineRunner.""" |
206 | + |
207 | + def setUp(self): |
208 | + """Init.""" |
209 | + BaseTwistedTestCase.setUp(self) |
210 | + self.ssmr = SyncStateMachineRunner(fsm=None, main=None, |
211 | + key=DummyClass(), logger=None) |
212 | + |
213 | + def tearDown(self): |
214 | + """Clean up.""" |
215 | + self.ssmr = None |
216 | + BaseTwistedTestCase.tearDown(self) |
217 | + |
218 | + def test_delete_file(self): |
219 | + """delete_file can be called with or without the server hash.""" |
220 | + self.ssmr.delete_file(event='AQ_DOWNLOAD_ERROR', params=None) |
221 | + |
222 | + self.ssmr.delete_file(event='AQ_DOWNLOAD_ERROR', params=None, |
223 | + server_hash='') |
224 | |
225 | === modified file 'ubuntuone/syncdaemon/action_queue.py' |
226 | --- ubuntuone/syncdaemon/action_queue.py 2010-02-10 19:10:37 +0000 |
227 | +++ ubuntuone/syncdaemon/action_queue.py 2010-02-11 13:18:15 +0000 |
228 | @@ -2168,14 +2168,19 @@ |
229 | downloading[self.share_id, self.node_id]['command'] is self: |
230 | del downloading[self.share_id, self.node_id] |
231 | self.reset_fileobj() |
232 | - if failure.getErrorMessage() == 'CANCELLED': |
233 | + error_msg = failure.getErrorMessage() |
234 | + if error_msg == 'CANCELLED': |
235 | self.action_queue.event_queue.push('AQ_DOWNLOAD_CANCELLED', |
236 | share_id=self.share_id, |
237 | node_id=self.node_id, |
238 | server_hash=self.server_hash) |
239 | + elif error_msg == 'DOES_NOT_EXIST': |
240 | + self.action_queue.event_queue.push('AQ_DOWNLOAD_DOES_NOT_EXIST', |
241 | + share_id=self.share_id, |
242 | + node_id=self.node_id) |
243 | else: |
244 | self.action_queue.event_queue.push('AQ_DOWNLOAD_ERROR', |
245 | - error=failure.getErrorMessage(), |
246 | + error=error_msg, |
247 | share_id=self.share_id, |
248 | node_id=self.node_id, |
249 | server_hash=self.server_hash) |
250 | |
251 | === modified file 'ubuntuone/syncdaemon/event_queue.py' |
252 | --- ubuntuone/syncdaemon/event_queue.py 2010-02-09 14:06:50 +0000 |
253 | +++ ubuntuone/syncdaemon/event_queue.py 2010-02-11 13:18:15 +0000 |
254 | @@ -56,6 +56,7 @@ |
255 | 'AQ_DOWNLOAD_FINISHED': ('share_id', 'node_id', 'server_hash'), |
256 | 'AQ_DOWNLOAD_ERROR': ('share_id', 'node_id', 'server_hash', 'error'), |
257 | 'AQ_DOWNLOAD_CANCELLED': ('share_id', 'node_id', 'server_hash'), |
258 | + 'AQ_DOWNLOAD_DOES_NOT_EXIST': ('share_id', 'node_id'), |
259 | 'AQ_UPLOAD_STARTED' : ('share_id', 'node_id', 'hash'), |
260 | 'AQ_UPLOAD_FINISHED': ('share_id', 'node_id', 'hash'), |
261 | 'AQ_UPLOAD_ERROR': ('share_id', 'node_id', 'error', 'hash'), |
262 | |
263 | === modified file 'ubuntuone/syncdaemon/sync.py' |
264 | --- ubuntuone/syncdaemon/sync.py 2010-02-10 19:10:37 +0000 |
265 | +++ ubuntuone/syncdaemon/sync.py 2010-02-11 13:18:15 +0000 |
266 | @@ -737,8 +737,7 @@ |
267 | self.key.remove_partial() |
268 | self.key.upload_finished(hash) |
269 | |
270 | - |
271 | - def delete_file(self, event, params): |
272 | + def delete_file(self, event, params, *args, **kwargs): |
273 | """server file was deleted.""" |
274 | try: |
275 | self.key.delete_file() |
276 | @@ -945,6 +944,13 @@ |
277 | ssmr = SyncStateMachineRunner(self.fsm, self.m, key, log) |
278 | ssmr.signal_event_with_hash("AQ_DOWNLOAD_CANCELLED", server_hash) |
279 | |
280 | + def handle_AQ_DOWNLOAD_DOES_NOT_EXIST(self, share_id, node_id): |
281 | + """on AQ_DOWNLOAD_DOES_NOT_EXIST.""" |
282 | + key = FSKey(self.m.fs, share_id=share_id, node_id=node_id) |
283 | + log = FileLogger(self.logger, key) |
284 | + ssmr = SyncStateMachineRunner(self.fsm, self.m, key, log) |
285 | + ssmr.on_event("AQ_DOWNLOAD_DOES_NOT_EXIST", {}, share_id, node_id) |
286 | + |
287 | def handle_FS_FILE_CREATE(self, path): |
288 | """on FS_FILE_CREATE""" |
289 | key = FSKey(self.m.fs, path=path) |
290 | |
291 | === modified file 'ubuntuone/syncdaemon/u1fsfsm.ods' |
292 | Binary files ubuntuone/syncdaemon/u1fsfsm.ods 2010-01-22 17:25:09 +0000 and ubuntuone/syncdaemon/u1fsfsm.ods 2010-02-11 13:18:15 +0000 differ |
293 | === modified file 'ubuntuone/syncdaemon/u1fsfsm.py' |
294 | --- ubuntuone/syncdaemon/u1fsfsm.py 2010-01-22 17:25:09 +0000 |
295 | +++ ubuntuone/syncdaemon/u1fsfsm.py 2010-02-11 13:18:15 +0000 |
296 | @@ -365,6 +365,58 @@ |
297 | 'STATE_OUT': {u'changed': u'=', |
298 | u'has_metadata': u'=', |
299 | u'is_directory': u'='}}], |
300 | + u'AQ_DOWNLOAD_DOES_NOT_EXIST': [{'ACTION': u'', |
301 | + 'ACTION_FUNC': u'delete_file', |
302 | + 'COMMENTS': u"Directory doesn't exist anymore, remove it", |
303 | + 'PARAMETERS': {u'hash_eq_local_hash': u'NA', |
304 | + u'hash_eq_server_hash': u'NA', |
305 | + u'not_authorized': u'NA', |
306 | + u'not_available': u'NA'}, |
307 | + 'STATE': {u'changed': u'*', |
308 | + u'has_metadata': u'T', |
309 | + u'is_directory': u'T'}, |
310 | + 'STATE_OUT': {u'changed': u'NA', |
311 | + u'has_metadata': u'F', |
312 | + u'is_directory': u'NA'}}, |
313 | + {'ACTION': u'', |
314 | + 'ACTION_FUNC': u'delete_file', |
315 | + 'COMMENTS': u"File doesn't exist anymore, remove it", |
316 | + 'PARAMETERS': {u'hash_eq_local_hash': u'NA', |
317 | + u'hash_eq_server_hash': u'NA', |
318 | + u'not_authorized': u'NA', |
319 | + u'not_available': u'NA'}, |
320 | + 'STATE': {u'changed': u'!LOCAL', |
321 | + u'has_metadata': u'T', |
322 | + u'is_directory': u'F'}, |
323 | + 'STATE_OUT': {u'changed': u'NA', |
324 | + u'has_metadata': u'F', |
325 | + u'is_directory': u'NA'}}, |
326 | + {'ACTION': u'', |
327 | + 'ACTION_FUNC': u'conflict_and_delete', |
328 | + 'COMMENTS': u"File doesn't exist on server, but has local changes", |
329 | + 'PARAMETERS': {u'hash_eq_local_hash': u'NA', |
330 | + u'hash_eq_server_hash': u'NA', |
331 | + u'not_authorized': u'NA', |
332 | + u'not_available': u'NA'}, |
333 | + 'STATE': {u'changed': u'LOCAL', |
334 | + u'has_metadata': u'T', |
335 | + u'is_directory': u'F'}, |
336 | + 'STATE_OUT': {u'changed': u'NA', |
337 | + u'has_metadata': u'F', |
338 | + u'is_directory': u'NA'}}, |
339 | + {'ACTION': u'pass', |
340 | + 'ACTION_FUNC': u'nothing', |
341 | + 'COMMENTS': u'', |
342 | + 'PARAMETERS': {u'hash_eq_local_hash': u'NA', |
343 | + u'hash_eq_server_hash': u'NA', |
344 | + u'not_authorized': u'NA', |
345 | + u'not_available': u'NA'}, |
346 | + 'STATE': {u'changed': u'*', |
347 | + u'has_metadata': u'F', |
348 | + u'is_directory': u'*'}, |
349 | + 'STATE_OUT': {u'changed': u'=', |
350 | + u'has_metadata': u'=', |
351 | + u'is_directory': u'='}}], |
352 | u'AQ_DOWNLOAD_ERROR': [{'ACTION': u'md.remove_partial(uuid);', |
353 | 'ACTION_FUNC': u'remove_partial', |
354 | 'COMMENTS': u'error while downloading, remove the partial file', |
Added a new event AQ_DOWNLOAD_ DOES_NOT_ EXIST so responses from the server with the error DOES_NOT_EXIST is correctly handled on the client.
Also binded proper handlers on u1fsfsm.ods spreadsheet.