Merge lp:~facundo/magicicada-protocol/publicfiles into lp:magicicada-protocol
- publicfiles
- Merge into trunk
Proposed by
Facundo Batista
Status: | Merged |
---|---|
Approved by: | Natalia Bidart |
Approved revision: | 170 |
Merged at revision: | 169 |
Proposed branch: | lp:~facundo/magicicada-protocol/publicfiles |
Merge into: | lp:magicicada-protocol |
Diff against target: |
715 lines (+406/-59) 5 files modified
tests/test_client.py (+182/-49) tests/test_public_file_info.py (+74/-0) ubuntuone/storageprotocol/client.py (+71/-8) ubuntuone/storageprotocol/protocol.proto (+24/-2) ubuntuone/storageprotocol/public_file_info.py (+55/-0) |
To merge this branch: | bzr merge lp:~facundo/magicicada-protocol/publicfiles |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Natalia Bidart | Approve | ||
Review via email: mp+310154@code.launchpad.net |
Commit message
Protocol infrastructure to support public files change and listing.
Description of the change
Protocol infrastructure to support public files change and listing.
To post a comment you must log in.
Revision history for this message
Natalia Bidart (nataliabidart) : | # |
Revision history for this message
Facundo Batista (facundo) wrote : | # |
- 170. By Facundo Batista
-
Import order.
Revision history for this message
Natalia Bidart (nataliabidart) wrote : | # |
LGTM Thanks!
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'tests/test_client.py' | |||
2 | --- tests/test_client.py 2016-09-19 02:00:32 +0000 | |||
3 | +++ tests/test_client.py 2016-11-15 23:38:26 +0000 | |||
4 | @@ -1,6 +1,7 @@ | |||
5 | 1 | # -*- coding: utf-8 -*- | 1 | # -*- coding: utf-8 -*- |
8 | 2 | # | 2 | |
9 | 3 | # Copyright (C) 2009-2015 Canonical Ltd. | 3 | # Copyright 2009-2015 Canonical Ltd. |
10 | 4 | # Copyright 2016 Chicharreros (https://launchpad.net/~chicharreros) | ||
11 | 4 | # | 5 | # |
12 | 5 | # This program is free software: you can redistribute it and/or modify it | 6 | # This program is free software: you can redistribute it and/or modify it |
13 | 6 | # under the terms of the GNU Affero General Public License version 3, | 7 | # under the terms of the GNU Affero General Public License version 3, |
14 | @@ -26,6 +27,7 @@ | |||
15 | 26 | # do not wish to do so, delete this exception statement from your | 27 | # do not wish to do so, delete this exception statement from your |
16 | 27 | # version. If you delete this exception statement from all source | 28 | # version. If you delete this exception statement from all source |
17 | 28 | # files in the program, then also delete it here. | 29 | # files in the program, then also delete it here. |
18 | 30 | |||
19 | 29 | """Tests for the protocol client.""" | 31 | """Tests for the protocol client.""" |
20 | 30 | 32 | ||
21 | 31 | import StringIO | 33 | import StringIO |
22 | @@ -42,8 +44,20 @@ | |||
23 | 42 | 44 | ||
24 | 43 | from ubuntuone.storageprotocol import protocol_pb2, sharersp, delta, request | 45 | from ubuntuone.storageprotocol import protocol_pb2, sharersp, delta, request |
25 | 44 | from ubuntuone.storageprotocol.client import ( | 46 | from ubuntuone.storageprotocol.client import ( |
28 | 45 | StorageClient, CreateUDF, ListVolumes, DeleteVolume, GetDelta, Unlink, | 47 | Authenticate, |
29 | 46 | Authenticate, MakeFile, MakeDir, PutContent, Move, BytesMessageProducer, | 48 | BytesMessageProducer, |
30 | 49 | ChangePublicAccess, | ||
31 | 50 | CreateUDF, | ||
32 | 51 | DeleteVolume, | ||
33 | 52 | GetDelta, | ||
34 | 53 | ListPublicFiles, | ||
35 | 54 | ListVolumes, | ||
36 | 55 | MakeDir, | ||
37 | 56 | MakeFile, | ||
38 | 57 | Move, | ||
39 | 58 | PutContent, | ||
40 | 59 | StorageClient, | ||
41 | 60 | Unlink, | ||
42 | 47 | ) | 61 | ) |
43 | 48 | 62 | ||
44 | 49 | from ubuntuone.storageprotocol import volumes | 63 | from ubuntuone.storageprotocol import volumes |
45 | @@ -61,6 +75,7 @@ | |||
46 | 61 | NODE = uuid.UUID('FEDCBA98-7654-3211-2345-6789ABCDEF12') | 75 | NODE = uuid.UUID('FEDCBA98-7654-3211-2345-6789ABCDEF12') |
47 | 62 | USER = u'Dude' | 76 | USER = u'Dude' |
48 | 63 | GENERATION = 999 | 77 | GENERATION = 999 |
49 | 78 | PUBLIC_URL = "http://magicicada/someid" | ||
50 | 64 | 79 | ||
51 | 65 | 80 | ||
52 | 66 | class FakedError(Exception): | 81 | class FakedError(Exception): |
53 | @@ -308,7 +323,7 @@ | |||
54 | 308 | self.client.set_share_change_callback(a_callback) | 323 | self.client.set_share_change_callback(a_callback) |
55 | 309 | self.assertTrue(self.client._share_change_callback is a_callback) | 324 | self.assertTrue(self.client._share_change_callback is a_callback) |
56 | 310 | self.client.handle_NOTIFY_SHARE(proto_msg) | 325 | self.client.handle_NOTIFY_SHARE(proto_msg) |
58 | 311 | self.assertEquals(self.share_notif.share_id, share_resp.share_id) | 326 | self.assertEqual(self.share_notif.share_id, share_resp.share_id) |
59 | 312 | 327 | ||
60 | 313 | def test_share_delete_callback(self): | 328 | def test_share_delete_callback(self): |
61 | 314 | """Test share_delete callback usage.""" | 329 | """Test share_delete callback usage.""" |
62 | @@ -329,7 +344,7 @@ | |||
63 | 329 | self.client.set_share_delete_callback(a_callback) | 344 | self.client.set_share_delete_callback(a_callback) |
64 | 330 | self.assertTrue(self.client._share_delete_callback is a_callback) | 345 | self.assertTrue(self.client._share_delete_callback is a_callback) |
65 | 331 | self.client.handle_SHARE_DELETED(proto_msg) | 346 | self.client.handle_SHARE_DELETED(proto_msg) |
67 | 332 | self.assertEquals(self.deleted_share_id, share_id) | 347 | self.assertEqual(self.deleted_share_id, share_id) |
68 | 333 | 348 | ||
69 | 334 | def test_share_answer_callback(self): | 349 | def test_share_answer_callback(self): |
70 | 335 | """Test share_answer callback usage.""" | 350 | """Test share_answer callback usage.""" |
71 | @@ -351,8 +366,8 @@ | |||
72 | 351 | self.client.set_share_answer_callback(a_callback) | 366 | self.client.set_share_answer_callback(a_callback) |
73 | 352 | self.assertTrue(self.client._share_answer_callback is a_callback) | 367 | self.assertTrue(self.client._share_answer_callback is a_callback) |
74 | 353 | self.client.handle_SHARE_ACCEPTED(proto_msg) | 368 | self.client.handle_SHARE_ACCEPTED(proto_msg) |
77 | 354 | self.assertEquals(self.answer[0], share_id) | 369 | self.assertEqual(self.answer[0], share_id) |
78 | 355 | self.assertEquals(self.answer[1], "Yes") | 370 | self.assertEqual(self.answer[1], "Yes") |
79 | 356 | 371 | ||
80 | 357 | def test_handle_volume_new_generation_uuid(self): | 372 | def test_handle_volume_new_generation_uuid(self): |
81 | 358 | """Test handle_VOLUME_NEW_GENERATION with an uuid id.""" | 373 | """Test handle_VOLUME_NEW_GENERATION with an uuid id.""" |
82 | @@ -415,7 +430,7 @@ | |||
83 | 415 | root = volumes.RootVolume.from_msg(message.volume_created.root) | 430 | root = volumes.RootVolume.from_msg(message.volume_created.root) |
84 | 416 | 431 | ||
85 | 417 | self.client.handle_VOLUME_CREATED(message) | 432 | self.client.handle_VOLUME_CREATED(message) |
87 | 418 | self.assertEquals(root, self.volume) | 433 | self.assertEqual(root, self.volume) |
88 | 419 | 434 | ||
89 | 420 | def test_handle_udf_created_passes_a_udf(self): | 435 | def test_handle_udf_created_passes_a_udf(self): |
90 | 421 | """Test handle_VOLUME_CREATED parameter passing.""" | 436 | """Test handle_VOLUME_CREATED parameter passing.""" |
91 | @@ -431,7 +446,7 @@ | |||
92 | 431 | udf = volumes.UDFVolume.from_msg(message.volume_created.udf) | 446 | udf = volumes.UDFVolume.from_msg(message.volume_created.udf) |
93 | 432 | 447 | ||
94 | 433 | self.client.handle_VOLUME_CREATED(message) | 448 | self.client.handle_VOLUME_CREATED(message) |
96 | 434 | self.assertEquals(udf, self.volume) | 449 | self.assertEqual(udf, self.volume) |
97 | 435 | 450 | ||
98 | 436 | def test_handle_share_created_passes_a_share(self): | 451 | def test_handle_share_created_passes_a_share(self): |
99 | 437 | """Test handle_VOLUME_CREATED parameter passing.""" | 452 | """Test handle_VOLUME_CREATED parameter passing.""" |
100 | @@ -447,7 +462,7 @@ | |||
101 | 447 | share = volumes.ShareVolume.from_msg(message.volume_created.share) | 462 | share = volumes.ShareVolume.from_msg(message.volume_created.share) |
102 | 448 | 463 | ||
103 | 449 | self.client.handle_VOLUME_CREATED(message) | 464 | self.client.handle_VOLUME_CREATED(message) |
105 | 450 | self.assertEquals(share, self.volume) | 465 | self.assertEqual(share, self.volume) |
106 | 451 | 466 | ||
107 | 452 | def test_handle_volume_created_if_callback_is_none(self): | 467 | def test_handle_volume_created_if_callback_is_none(self): |
108 | 453 | """Test handle_VOLUME_CREATED if callback is none.""" | 468 | """Test handle_VOLUME_CREATED if callback is none.""" |
109 | @@ -478,7 +493,7 @@ | |||
110 | 478 | message.volume_deleted.volume = str(VOLUME) | 493 | message.volume_deleted.volume = str(VOLUME) |
111 | 479 | self.client.handle_VOLUME_DELETED(message) | 494 | self.client.handle_VOLUME_DELETED(message) |
112 | 480 | 495 | ||
114 | 481 | self.assertEquals(VOLUME, self.volume) | 496 | self.assertEqual(VOLUME, self.volume) |
115 | 482 | 497 | ||
116 | 483 | def test_handle_volume_deleted_if_none(self): | 498 | def test_handle_volume_deleted_if_none(self): |
117 | 484 | """Test handle_VOLUME_DELETED if callback is none.""" | 499 | """Test handle_VOLUME_DELETED if callback is none.""" |
118 | @@ -515,8 +530,8 @@ | |||
119 | 515 | 530 | ||
120 | 516 | def test_init(self): | 531 | def test_init(self): |
121 | 517 | """Test request creation.""" | 532 | """Test request creation.""" |
124 | 518 | self.assertEquals(PATH, self.request.path) | 533 | self.assertEqual(PATH, self.request.path) |
125 | 519 | self.assertEquals(NAME, self.request.name) | 534 | self.assertEqual(NAME, self.request.name) |
126 | 520 | self.assertTrue(self.request.volume_id is None) | 535 | self.assertTrue(self.request.volume_id is None) |
127 | 521 | self.assertTrue(self.request.node_id is None) | 536 | self.assertTrue(self.request.node_id is None) |
128 | 522 | 537 | ||
129 | @@ -524,11 +539,11 @@ | |||
130 | 524 | """Test request start.""" | 539 | """Test request start.""" |
131 | 525 | self.request.start() | 540 | self.request.start() |
132 | 526 | 541 | ||
134 | 527 | self.assertEquals(1, len(self.request.protocol.messages)) | 542 | self.assertEqual(1, len(self.request.protocol.messages)) |
135 | 528 | actual_msg, = self.request.protocol.messages | 543 | actual_msg, = self.request.protocol.messages |
139 | 529 | self.assertEquals(protocol_pb2.Message.CREATE_UDF, actual_msg.type) | 544 | self.assertEqual(protocol_pb2.Message.CREATE_UDF, actual_msg.type) |
140 | 530 | self.assertEquals(self.request.path, actual_msg.create_udf.path) | 545 | self.assertEqual(self.request.path, actual_msg.create_udf.path) |
141 | 531 | self.assertEquals(self.request.name, actual_msg.create_udf.name) | 546 | self.assertEqual(self.request.name, actual_msg.create_udf.name) |
142 | 532 | 547 | ||
143 | 533 | def test_process_message_error(self): | 548 | def test_process_message_error(self): |
144 | 534 | """Test request processMessage on error.""" | 549 | """Test request processMessage on error.""" |
145 | @@ -544,8 +559,8 @@ | |||
146 | 544 | message.volume_created.udf.node = str(NODE) | 559 | message.volume_created.udf.node = str(NODE) |
147 | 545 | self.request.processMessage(message) | 560 | self.request.processMessage(message) |
148 | 546 | 561 | ||
151 | 547 | self.assertEquals(str(VOLUME), self.request.volume_id, 'volume set') | 562 | self.assertEqual(str(VOLUME), self.request.volume_id, 'volume set') |
152 | 548 | self.assertEquals(str(NODE), self.request.node_id, 'node set') | 563 | self.assertEqual(str(NODE), self.request.node_id, 'node set') |
153 | 549 | self.assertTrue(self.done_called, 'done() was called') | 564 | self.assertTrue(self.done_called, 'done() was called') |
154 | 550 | 565 | ||
155 | 551 | 566 | ||
156 | @@ -566,15 +581,15 @@ | |||
157 | 566 | 581 | ||
158 | 567 | def test_init(self): | 582 | def test_init(self): |
159 | 568 | """Test request creation.""" | 583 | """Test request creation.""" |
161 | 569 | self.assertEquals([], self.request.volumes) | 584 | self.assertEqual([], self.request.volumes) |
162 | 570 | 585 | ||
163 | 571 | def test_start(self): | 586 | def test_start(self): |
164 | 572 | """Test request start.""" | 587 | """Test request start.""" |
165 | 573 | self.request.start() | 588 | self.request.start() |
166 | 574 | 589 | ||
168 | 575 | self.assertEquals(1, len(self.request.protocol.messages)) | 590 | self.assertEqual(1, len(self.request.protocol.messages)) |
169 | 576 | actual_msg, = self.request.protocol.messages | 591 | actual_msg, = self.request.protocol.messages |
171 | 577 | self.assertEquals(protocol_pb2.Message.LIST_VOLUMES, actual_msg.type) | 592 | self.assertEqual(protocol_pb2.Message.LIST_VOLUMES, actual_msg.type) |
172 | 578 | 593 | ||
173 | 579 | def test_process_message_error(self): | 594 | def test_process_message_error(self): |
174 | 580 | """Test request processMessage on error.""" | 595 | """Test request processMessage on error.""" |
175 | @@ -598,10 +613,9 @@ | |||
176 | 598 | root = volumes.RootVolume.from_msg(message.list_volumes.root) | 613 | root = volumes.RootVolume.from_msg(message.list_volumes.root) |
177 | 599 | self.request.processMessage(message) | 614 | self.request.processMessage(message) |
178 | 600 | 615 | ||
183 | 601 | self.assertEquals(3, len(self.request.volumes), | 616 | self.assertEqual(3, len(self.request.volumes), '3 volumes stored') |
184 | 602 | '3 volumes stored') | 617 | self.assertEqual([udf, share, root], self.request.volumes, |
185 | 603 | self.assertEquals([udf, share, root], self.request.volumes, | 618 | 'volumes stored') |
182 | 604 | 'volumes stored') | ||
186 | 605 | 619 | ||
187 | 606 | message = protocol_pb2.Message() | 620 | message = protocol_pb2.Message() |
188 | 607 | message.type = protocol_pb2.Message.VOLUMES_END | 621 | message.type = protocol_pb2.Message.VOLUMES_END |
189 | @@ -622,7 +636,7 @@ | |||
190 | 622 | self.request.processMessage(message) | 636 | self.request.processMessage(message) |
191 | 623 | 637 | ||
192 | 624 | self.request.start() | 638 | self.request.start() |
194 | 625 | self.assertEquals([], self.request.volumes) | 639 | self.assertEqual([], self.request.volumes) |
195 | 626 | 640 | ||
196 | 627 | 641 | ||
197 | 628 | class DeleteVolumeTestCase(RequestTestCase): | 642 | class DeleteVolumeTestCase(RequestTestCase): |
198 | @@ -642,17 +656,17 @@ | |||
199 | 642 | 656 | ||
200 | 643 | def test_init(self): | 657 | def test_init(self): |
201 | 644 | """Test request creation.""" | 658 | """Test request creation.""" |
203 | 645 | self.assertEquals(str(VOLUME), self.request.volume_id) | 659 | self.assertEqual(str(VOLUME), self.request.volume_id) |
204 | 646 | 660 | ||
205 | 647 | def test_start(self): | 661 | def test_start(self): |
206 | 648 | """Test request start.""" | 662 | """Test request start.""" |
207 | 649 | self.request.start() | 663 | self.request.start() |
208 | 650 | 664 | ||
210 | 651 | self.assertEquals(1, len(self.request.protocol.messages)) | 665 | self.assertEqual(1, len(self.request.protocol.messages)) |
211 | 652 | actual_msg, = self.request.protocol.messages | 666 | actual_msg, = self.request.protocol.messages |
215 | 653 | self.assertEquals(protocol_pb2.Message.DELETE_VOLUME, actual_msg.type) | 667 | self.assertEqual(protocol_pb2.Message.DELETE_VOLUME, actual_msg.type) |
216 | 654 | self.assertEquals(self.request.volume_id, | 668 | self.assertEqual(self.request.volume_id, |
217 | 655 | actual_msg.delete_volume.volume) | 669 | actual_msg.delete_volume.volume) |
218 | 656 | 670 | ||
219 | 657 | def test_process_message_error(self): | 671 | def test_process_message_error(self): |
220 | 658 | """Test request processMessage on error.""" | 672 | """Test request processMessage on error.""" |
221 | @@ -685,17 +699,17 @@ | |||
222 | 685 | 699 | ||
223 | 686 | def test_init(self): | 700 | def test_init(self): |
224 | 687 | """Test request creation.""" | 701 | """Test request creation.""" |
226 | 688 | self.assertEquals(str(SHARE), self.request.share_id) | 702 | self.assertEqual(str(SHARE), self.request.share_id) |
227 | 689 | 703 | ||
228 | 690 | def test_start(self): | 704 | def test_start(self): |
229 | 691 | """Test request start.""" | 705 | """Test request start.""" |
230 | 692 | self.request.start() | 706 | self.request.start() |
231 | 693 | 707 | ||
233 | 694 | self.assertEquals(1, len(self.request.protocol.messages)) | 708 | self.assertEqual(1, len(self.request.protocol.messages)) |
234 | 695 | actual_msg, = self.request.protocol.messages | 709 | actual_msg, = self.request.protocol.messages |
238 | 696 | self.assertEquals(protocol_pb2.Message.GET_DELTA, actual_msg.type) | 710 | self.assertEqual(protocol_pb2.Message.GET_DELTA, actual_msg.type) |
239 | 697 | self.assertEquals(self.request.share_id, | 711 | self.assertEqual(self.request.share_id, |
240 | 698 | actual_msg.get_delta.share) | 712 | actual_msg.get_delta.share) |
241 | 699 | 713 | ||
242 | 700 | def test_process_message_error(self): | 714 | def test_process_message_error(self): |
243 | 701 | """Test request processMessage on error.""" | 715 | """Test request processMessage on error.""" |
244 | @@ -712,11 +726,11 @@ | |||
245 | 712 | self.request.processMessage(message) | 726 | self.request.processMessage(message) |
246 | 713 | 727 | ||
247 | 714 | self.assertTrue(self.done_called, 'done() was called') | 728 | self.assertTrue(self.done_called, 'done() was called') |
253 | 715 | self.assertEquals(self.request.end_generation, | 729 | self.assertEqual(self.request.end_generation, |
254 | 716 | message.delta_end.generation) | 730 | message.delta_end.generation) |
255 | 717 | self.assertEquals(self.request.full, message.delta_end.full) | 731 | self.assertEqual(self.request.full, message.delta_end.full) |
256 | 718 | self.assertEquals(self.request.free_bytes, | 732 | self.assertEqual(self.request.free_bytes, |
257 | 719 | message.delta_end.free_bytes) | 733 | message.delta_end.free_bytes) |
258 | 720 | 734 | ||
259 | 721 | def test_process_message_content(self): | 735 | def test_process_message_content(self): |
260 | 722 | """Test request processMessage for content.""" | 736 | """Test request processMessage for content.""" |
261 | @@ -748,11 +762,11 @@ | |||
262 | 748 | self.request.done = was_called(self, 'done_called') | 762 | self.request.done = was_called(self, 'done_called') |
263 | 749 | self.request.start() | 763 | self.request.start() |
264 | 750 | 764 | ||
266 | 751 | self.assertEquals(1, len(self.request.protocol.messages)) | 765 | self.assertEqual(1, len(self.request.protocol.messages)) |
267 | 752 | actual_msg, = self.request.protocol.messages | 766 | actual_msg, = self.request.protocol.messages |
271 | 753 | self.assertEquals(protocol_pb2.Message.GET_DELTA, actual_msg.type) | 767 | self.assertEqual(protocol_pb2.Message.GET_DELTA, actual_msg.type) |
272 | 754 | self.assertEquals(self.request.share_id, | 768 | self.assertEqual(self.request.share_id, |
273 | 755 | actual_msg.get_delta.share) | 769 | actual_msg.get_delta.share) |
274 | 756 | 770 | ||
275 | 757 | 771 | ||
276 | 758 | class TestAuth(RequestTestCase): | 772 | class TestAuth(RequestTestCase): |
277 | @@ -958,5 +972,124 @@ | |||
278 | 958 | return d | 972 | return d |
279 | 959 | 973 | ||
280 | 960 | 974 | ||
283 | 961 | if __name__ == '__main__': | 975 | class ChangePublicAccessTestCase(RequestTestCase): |
284 | 962 | unittest.main() | 976 | """Test cases for ChangePublicAccess op.""" |
285 | 977 | |||
286 | 978 | request_class = ChangePublicAccess | ||
287 | 979 | |||
288 | 980 | @defer.inlineCallbacks | ||
289 | 981 | def setUp(self): | ||
290 | 982 | """Initialize testing protocol.""" | ||
291 | 983 | yield super(ChangePublicAccessTestCase, self).setUp() | ||
292 | 984 | self.protocol = FakedProtocol() | ||
293 | 985 | self.request = self.request_class( | ||
294 | 986 | self.protocol, share_id=SHARE, node_id=NODE, is_public=True) | ||
295 | 987 | self.request.error = faked_error | ||
296 | 988 | self.done_called = False | ||
297 | 989 | self.request.done = was_called(self, 'done_called') | ||
298 | 990 | |||
299 | 991 | def test_init(self): | ||
300 | 992 | """Test request creation.""" | ||
301 | 993 | self.assertEqual(self.request.share_id, str(SHARE)) | ||
302 | 994 | self.assertEqual(self.request.node_id, str(NODE)) | ||
303 | 995 | self.assertTrue(self.request.is_public) | ||
304 | 996 | |||
305 | 997 | def test_start(self): | ||
306 | 998 | """Test request start.""" | ||
307 | 999 | self.request.start() | ||
308 | 1000 | |||
309 | 1001 | self.assertEqual(1, len(self.request.protocol.messages)) | ||
310 | 1002 | actual_msg, = self.request.protocol.messages | ||
311 | 1003 | self.assertEqual(actual_msg.type, | ||
312 | 1004 | protocol_pb2.Message.CHANGE_PUBLIC_ACCESS) | ||
313 | 1005 | self.assertEqual(actual_msg.change_public_access.share, | ||
314 | 1006 | self.request.share_id) | ||
315 | 1007 | self.assertEqual(actual_msg.change_public_access.node, | ||
316 | 1008 | self.request.node_id) | ||
317 | 1009 | self.assertTrue(actual_msg.change_public_access.is_public) | ||
318 | 1010 | |||
319 | 1011 | def test_process_message_error(self): | ||
320 | 1012 | """Test request processMessage on error.""" | ||
321 | 1013 | message = protocol_pb2.Message() | ||
322 | 1014 | self.assertRaises(FakedError, self.request.processMessage, message) | ||
323 | 1015 | self.assertIsNone(self.request.public_url) | ||
324 | 1016 | |||
325 | 1017 | def test_process_message_ok(self): | ||
326 | 1018 | """Test request processMessage on sucess.""" | ||
327 | 1019 | message = protocol_pb2.Message() | ||
328 | 1020 | message.type = protocol_pb2.Message.OK | ||
329 | 1021 | message.public_url = PUBLIC_URL | ||
330 | 1022 | self.request.processMessage(message) | ||
331 | 1023 | |||
332 | 1024 | self.assertTrue(self.done_called, 'done() was called') | ||
333 | 1025 | self.assertIsNotNone(self.request.public_url) | ||
334 | 1026 | |||
335 | 1027 | |||
336 | 1028 | class ListPublicFilesTestCase(RequestTestCase): | ||
337 | 1029 | """Test cases for ListPublicFiles op.""" | ||
338 | 1030 | |||
339 | 1031 | request_class = ListPublicFiles | ||
340 | 1032 | |||
341 | 1033 | @defer.inlineCallbacks | ||
342 | 1034 | def setUp(self): | ||
343 | 1035 | """Initialize testing protocol.""" | ||
344 | 1036 | yield super(ListPublicFilesTestCase, self).setUp() | ||
345 | 1037 | self.protocol = FakedProtocol() | ||
346 | 1038 | self.request = self.request_class(self.protocol) | ||
347 | 1039 | self.request.error = faked_error | ||
348 | 1040 | self.done_called = False | ||
349 | 1041 | self.request.done = was_called(self, 'done_called') | ||
350 | 1042 | |||
351 | 1043 | def test_start(self): | ||
352 | 1044 | """Test request start.""" | ||
353 | 1045 | self.request.start() | ||
354 | 1046 | |||
355 | 1047 | self.assertEqual(1, len(self.request.protocol.messages)) | ||
356 | 1048 | actual_msg, = self.request.protocol.messages | ||
357 | 1049 | self.assertEqual(actual_msg.type, | ||
358 | 1050 | protocol_pb2.Message.LIST_PUBLIC_FILES) | ||
359 | 1051 | |||
360 | 1052 | def test_process_message_error(self): | ||
361 | 1053 | """Test request processMessage on error.""" | ||
362 | 1054 | message = protocol_pb2.Message() | ||
363 | 1055 | self.assertRaises(FakedError, self.request.processMessage, message) | ||
364 | 1056 | self.assertEqual(self.request.public_files, []) | ||
365 | 1057 | |||
366 | 1058 | def test_process_message_ok(self): | ||
367 | 1059 | """Test request processMessage on sucess.""" | ||
368 | 1060 | # send two nodes | ||
369 | 1061 | message = protocol_pb2.Message() | ||
370 | 1062 | message.type = protocol_pb2.Message.PUBLIC_FILE_INFO | ||
371 | 1063 | message.public_file_info.share = 'share_id' | ||
372 | 1064 | message.public_file_info.node = 'node_id_1' | ||
373 | 1065 | message.public_file_info.is_public = True | ||
374 | 1066 | message.public_file_info.public_url = "test url 123" | ||
375 | 1067 | self.request.processMessage(message) | ||
376 | 1068 | |||
377 | 1069 | message = protocol_pb2.Message() | ||
378 | 1070 | message.type = protocol_pb2.Message.PUBLIC_FILE_INFO | ||
379 | 1071 | message.public_file_info.share = 'share_id' | ||
380 | 1072 | message.public_file_info.node = 'node_id_2' | ||
381 | 1073 | message.public_file_info.is_public = True | ||
382 | 1074 | message.public_file_info.public_url = "test url 456" | ||
383 | 1075 | self.request.processMessage(message) | ||
384 | 1076 | |||
385 | 1077 | # finish | ||
386 | 1078 | message = protocol_pb2.Message() | ||
387 | 1079 | message.type = protocol_pb2.Message.PUBLIC_FILE_INFO_END | ||
388 | 1080 | self.request.processMessage(message) | ||
389 | 1081 | |||
390 | 1082 | # check | ||
391 | 1083 | self.assertTrue(self.done_called, 'done() was called') | ||
392 | 1084 | node1, node2 = self.request.public_files | ||
393 | 1085 | print("NNNNNNNNNNNNO 1", node1) | ||
394 | 1086 | |||
395 | 1087 | self.assertEqual(node1.share_id, 'share_id') | ||
396 | 1088 | self.assertEqual(node1.node_id, 'node_id_1') | ||
397 | 1089 | self.assertEqual(node1.is_public, True) | ||
398 | 1090 | self.assertEqual(node1.public_url, 'test url 123') | ||
399 | 1091 | |||
400 | 1092 | self.assertEqual(node2.share_id, 'share_id') | ||
401 | 1093 | self.assertEqual(node2.node_id, 'node_id_2') | ||
402 | 1094 | self.assertEqual(node2.is_public, True) | ||
403 | 1095 | self.assertEqual(node2.public_url, 'test url 456') | ||
404 | 963 | 1096 | ||
405 | === added file 'tests/test_public_file_info.py' | |||
406 | --- tests/test_public_file_info.py 1970-01-01 00:00:00 +0000 | |||
407 | +++ tests/test_public_file_info.py 2016-11-15 23:38:26 +0000 | |||
408 | @@ -0,0 +1,74 @@ | |||
409 | 1 | # -*- coding: utf-8 -*- | ||
410 | 2 | |||
411 | 3 | # Copyright 2016 Chicharreros (https://launchpad.net/~chicharreros) | ||
412 | 4 | # | ||
413 | 5 | # This program is free software: you can redistribute it and/or modify it | ||
414 | 6 | # under the terms of the GNU Affero General Public License version 3, | ||
415 | 7 | # as published by the Free Software Foundation. | ||
416 | 8 | # | ||
417 | 9 | # This program is distributed in the hope that it will be useful, but | ||
418 | 10 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
419 | 11 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
420 | 12 | # PURPOSE. See the GNU Affero General Public License for more details. | ||
421 | 13 | # | ||
422 | 14 | # You should have received a copy of the GNU Affero General Public License | ||
423 | 15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
424 | 16 | # | ||
425 | 17 | # In addition, as a special exception, the copyright holders give | ||
426 | 18 | # permission to link the code of portions of this program with the | ||
427 | 19 | # OpenSSL library under certain conditions as described in each | ||
428 | 20 | # individual source file, and distribute linked combinations | ||
429 | 21 | # including the two. | ||
430 | 22 | # You must obey the GNU General Public License in all respects | ||
431 | 23 | # for all of the code used other than OpenSSL. If you modify | ||
432 | 24 | # file(s) with this exception, you may extend this exception to your | ||
433 | 25 | # version of the file(s), but you are not obligated to do so. If you | ||
434 | 26 | # do not wish to do so, delete this exception statement from your | ||
435 | 27 | # version. If you delete this exception statement from all source | ||
436 | 28 | # files in the program, then also delete it here. | ||
437 | 29 | |||
438 | 30 | """Tests for generation node data type.""" | ||
439 | 31 | |||
440 | 32 | import unittest | ||
441 | 33 | |||
442 | 34 | from ubuntuone.storageprotocol import protocol_pb2, public_file_info, request | ||
443 | 35 | |||
444 | 36 | SHARE = "share_id" | ||
445 | 37 | NODE = "node_id" | ||
446 | 38 | PUBLIC_URL = "test public url" | ||
447 | 39 | |||
448 | 40 | |||
449 | 41 | def get_message(): | ||
450 | 42 | """Returns a PUBLIC_FILE_INFO message with sample data in the fields.""" | ||
451 | 43 | message = protocol_pb2.Message() | ||
452 | 44 | message.type = protocol_pb2.Message.PUBLIC_FILE_INFO | ||
453 | 45 | message.public_file_info.share = str(SHARE) | ||
454 | 46 | message.public_file_info.node = str(NODE) | ||
455 | 47 | message.public_file_info.is_public = True | ||
456 | 48 | message.public_file_info.public_url = PUBLIC_URL | ||
457 | 49 | return message | ||
458 | 50 | |||
459 | 51 | |||
460 | 52 | class DeltaTestCase(unittest.TestCase): | ||
461 | 53 | """Check Delta data type.""" | ||
462 | 54 | |||
463 | 55 | def test_correct_attributes(self): | ||
464 | 56 | """Assert over attribute correctness.""" | ||
465 | 57 | m = public_file_info.PublicFileInfo.from_message(get_message()) | ||
466 | 58 | self.assertEqual(m.share_id, SHARE) | ||
467 | 59 | self.assertEqual(m.node_id, NODE) | ||
468 | 60 | self.assertEqual(m.is_public, True) | ||
469 | 61 | self.assertEqual(m.public_url, PUBLIC_URL) | ||
470 | 62 | |||
471 | 63 | def test_is_equal(self): | ||
472 | 64 | """Test object equality.""" | ||
473 | 65 | m = public_file_info.PublicFileInfo.from_message(get_message()) | ||
474 | 66 | m2 = public_file_info.PublicFileInfo.from_message(get_message()) | ||
475 | 67 | self.assertEqual(m, m2) | ||
476 | 68 | |||
477 | 69 | def test_root_share_id(self): | ||
478 | 70 | """Test that DeltaInfo.from_message works with request.ROOT.""" | ||
479 | 71 | msg = get_message() | ||
480 | 72 | msg.public_file_info.share = request.ROOT | ||
481 | 73 | m = public_file_info.PublicFileInfo.from_message(msg) | ||
482 | 74 | self.assertEqual(m.share_id, request.ROOT) | ||
483 | 0 | 75 | ||
484 | === modified file 'ubuntuone/storageprotocol/client.py' | |||
485 | --- ubuntuone/storageprotocol/client.py 2016-10-11 19:01:04 +0000 | |||
486 | +++ ubuntuone/storageprotocol/client.py 2016-11-15 23:38:26 +0000 | |||
487 | @@ -1,12 +1,5 @@ | |||
488 | 1 | # ubuntuone.storageprotocol.client - the storage protocol client | ||
489 | 2 | # | ||
490 | 3 | # Author: Lucio Torre <lucio.torre@canonical.com> | ||
491 | 4 | # Author: Natalia B. Bidart <natalia.bidart@canonical.com> | ||
492 | 5 | # Author: Guillermo Gonzalez <guillermo.gonzalez@canonical.com> | ||
493 | 6 | # Author: Facundo Batista <facundo@canonical.com> | ||
494 | 7 | # Author: Alejandro J. Cura <alecu@canonical.com> | ||
495 | 8 | # | ||
496 | 9 | # Copyright 2009-2015 Canonical Ltd. | 1 | # Copyright 2009-2015 Canonical Ltd. |
497 | 2 | # Copyright 2016 Chicharreros (https://launchpad.net/~chicharreros) | ||
498 | 10 | # | 3 | # |
499 | 11 | # This program is free software: you can redistribute it and/or modify it | 4 | # This program is free software: you can redistribute it and/or modify it |
500 | 12 | # under the terms of the GNU Affero General Public License version 3, | 5 | # under the terms of the GNU Affero General Public License version 3, |
501 | @@ -32,6 +25,7 @@ | |||
502 | 32 | # do not wish to do so, delete this exception statement from your | 25 | # do not wish to do so, delete this exception statement from your |
503 | 33 | # version. If you delete this exception statement from all source | 26 | # version. If you delete this exception statement from all source |
504 | 34 | # files in the program, then also delete it here. | 27 | # files in the program, then also delete it here. |
505 | 28 | |||
506 | 35 | """The storage protocol client.""" | 29 | """The storage protocol client.""" |
507 | 36 | 30 | ||
508 | 37 | import logging | 31 | import logging |
509 | @@ -47,6 +41,7 @@ | |||
510 | 47 | from ubuntuone.storageprotocol import ( | 41 | from ubuntuone.storageprotocol import ( |
511 | 48 | delta, | 42 | delta, |
512 | 49 | protocol_pb2, | 43 | protocol_pb2, |
513 | 44 | public_file_info, | ||
514 | 50 | request, | 45 | request, |
515 | 51 | sharersp, | 46 | sharersp, |
516 | 52 | volumes, | 47 | volumes, |
517 | @@ -538,6 +533,18 @@ | |||
518 | 538 | p.start() | 533 | p.start() |
519 | 539 | return p.deferred | 534 | return p.deferred |
520 | 540 | 535 | ||
521 | 536 | def change_public_access(self, share_id, node_id, is_public): | ||
522 | 537 | """Change the public access of a file.""" | ||
523 | 538 | p = ChangePublicAccess(self, share_id, node_id, is_public) | ||
524 | 539 | p.start() | ||
525 | 540 | return p.deferred | ||
526 | 541 | |||
527 | 542 | def list_public_files(self): | ||
528 | 543 | """List the public files.""" | ||
529 | 544 | p = ListPublicFiles(self) | ||
530 | 545 | p.start() | ||
531 | 546 | return p.deferred | ||
532 | 547 | |||
533 | 541 | def delete_volume(self, volume_id): | 548 | def delete_volume(self, volume_id): |
534 | 542 | """Delete 'volume' on the server, removing the associated tree. | 549 | """Delete 'volume' on the server, removing the associated tree. |
535 | 543 | 550 | ||
536 | @@ -961,6 +968,62 @@ | |||
537 | 961 | self._default_process_message(message) | 968 | self._default_process_message(message) |
538 | 962 | 969 | ||
539 | 963 | 970 | ||
540 | 971 | class ChangePublicAccess(request.Request): | ||
541 | 972 | """Change the public access of a file.""" | ||
542 | 973 | |||
543 | 974 | __slots__ = ('share_id', 'node_id', 'is_public', 'public_url') | ||
544 | 975 | |||
545 | 976 | def __init__(self, protocol, share_id, node_id, is_public): | ||
546 | 977 | request.Request.__init__(self, protocol) | ||
547 | 978 | self.public_url = None | ||
548 | 979 | |||
549 | 980 | self.share_id = str(share_id) | ||
550 | 981 | self.node_id = str(node_id) | ||
551 | 982 | self.is_public = is_public | ||
552 | 983 | |||
553 | 984 | def _start(self): | ||
554 | 985 | message = protocol_pb2.Message() | ||
555 | 986 | message.type = protocol_pb2.Message.CHANGE_PUBLIC_ACCESS | ||
556 | 987 | message.change_public_access.share = self.share_id | ||
557 | 988 | message.change_public_access.node = self.node_id | ||
558 | 989 | message.change_public_access.is_public = self.is_public | ||
559 | 990 | self.sendMessage(message) | ||
560 | 991 | |||
561 | 992 | def processMessage(self, message): | ||
562 | 993 | if message.type == protocol_pb2.Message.OK: | ||
563 | 994 | self.public_url = message.public_url | ||
564 | 995 | self.done() | ||
565 | 996 | else: | ||
566 | 997 | self._default_process_message(message) | ||
567 | 998 | |||
568 | 999 | |||
569 | 1000 | class ListPublicFiles(request.Request): | ||
570 | 1001 | """List all the public files for an user.""" | ||
571 | 1002 | |||
572 | 1003 | __slots__ = ('public_files',) | ||
573 | 1004 | |||
574 | 1005 | def __init__(self, protocol): | ||
575 | 1006 | """List volumes.""" | ||
576 | 1007 | request.Request.__init__(self, protocol) | ||
577 | 1008 | self.public_files = [] | ||
578 | 1009 | |||
579 | 1010 | def _start(self): | ||
580 | 1011 | """Send the LIST_PUBLIC_FILES message to the server.""" | ||
581 | 1012 | message = protocol_pb2.Message() | ||
582 | 1013 | message.type = protocol_pb2.Message.LIST_PUBLIC_FILES | ||
583 | 1014 | self.sendMessage(message) | ||
584 | 1015 | |||
585 | 1016 | def processMessage(self, message): | ||
586 | 1017 | """Process the answer from the server.""" | ||
587 | 1018 | if message.type == protocol_pb2.Message.PUBLIC_FILE_INFO: | ||
588 | 1019 | info = public_file_info.PublicFileInfo.from_message(message) | ||
589 | 1020 | self.public_files.append(info) | ||
590 | 1021 | elif message.type == protocol_pb2.Message.PUBLIC_FILE_INFO_END: | ||
591 | 1022 | self.done() | ||
592 | 1023 | else: | ||
593 | 1024 | self._default_process_message(message) | ||
594 | 1025 | |||
595 | 1026 | |||
596 | 964 | class Move(request.Request): | 1027 | class Move(request.Request): |
597 | 965 | """Move a node. | 1028 | """Move a node. |
598 | 966 | 1029 | ||
599 | 967 | 1030 | ||
600 | === modified file 'ubuntuone/storageprotocol/protocol.proto' | |||
601 | --- ubuntuone/storageprotocol/protocol.proto 2012-03-29 20:28:09 +0000 | |||
602 | +++ ubuntuone/storageprotocol/protocol.proto 2016-11-15 23:38:26 +0000 | |||
603 | @@ -1,7 +1,6 @@ | |||
604 | 1 | /* | 1 | /* |
605 | 2 | ubuntuone.storageprotocol.protocol_pb2 - storage protocol | ||
606 | 3 | |||
607 | 4 | Copyright 2009-2012 Canonical Ltd. | 2 | Copyright 2009-2012 Canonical Ltd. |
608 | 3 | Copyright 2016 Chicharreros (https://launchpad.net/~chicharreros) | ||
609 | 5 | 4 | ||
610 | 6 | This program is free software: you can redistribute it and/or modify it | 5 | This program is free software: you can redistribute it and/or modify it |
611 | 7 | under the terms of the GNU Affero General Public License version 3, | 6 | under the terms of the GNU Affero General Public License version 3, |
612 | @@ -97,6 +96,11 @@ | |||
613 | 97 | GET_DELTA = 51; // ask for a delta | 96 | GET_DELTA = 51; // ask for a delta |
614 | 98 | DELTA_INFO = 52; // a row of the delta | 97 | DELTA_INFO = 52; // a row of the delta |
615 | 99 | DELTA_END = 53; // marks the end of a delta | 98 | DELTA_END = 53; // marks the end of a delta |
616 | 99 | |||
617 | 100 | CHANGE_PUBLIC_ACCESS = 55; // change the public access of a file | ||
618 | 101 | PUBLIC_FILE_INFO = 56; // information for a public file | ||
619 | 102 | PUBLIC_FILE_INFO_END = 57; // marks the end of a bunch of public file infos | ||
620 | 103 | LIST_PUBLIC_FILES = 58; // get the list of public files for the user | ||
621 | 100 | } | 104 | } |
622 | 101 | 105 | ||
623 | 102 | required MessageType type = 2; // The type of the message contained | 106 | required MessageType type = 2; // The type of the message contained |
624 | @@ -159,6 +163,11 @@ | |||
625 | 159 | optional GetDelta get_delta = 38; | 163 | optional GetDelta get_delta = 38; |
626 | 160 | optional DeltaInfo delta_info = 39; | 164 | optional DeltaInfo delta_info = 39; |
627 | 161 | optional DeltaEnd delta_end = 40; | 165 | optional DeltaEnd delta_end = 40; |
628 | 166 | |||
629 | 167 | // public files | ||
630 | 168 | optional ChangePublicAccess change_public_access = 45; | ||
631 | 169 | optional bytes public_url = 46; | ||
632 | 170 | optional PublicFileInfo public_file_info = 47; | ||
633 | 162 | } | 171 | } |
634 | 163 | 172 | ||
635 | 164 | message Error { | 173 | message Error { |
636 | @@ -481,6 +490,19 @@ | |||
637 | 481 | optional uint64 free_bytes = 3; // this will be just a hint if full == False | 490 | optional uint64 free_bytes = 3; // this will be just a hint if full == False |
638 | 482 | } | 491 | } |
639 | 483 | 492 | ||
640 | 493 | message ChangePublicAccess { | ||
641 | 494 | optional bytes share = 1; | ||
642 | 495 | optional bytes node = 2; | ||
643 | 496 | optional bool is_public = 3; | ||
644 | 497 | } | ||
645 | 498 | |||
646 | 499 | message PublicFileInfo { | ||
647 | 500 | optional bytes share = 1; | ||
648 | 501 | optional bytes node = 2; | ||
649 | 502 | optional bool is_public = 3; | ||
650 | 503 | optional bytes public_url = 4; | ||
651 | 504 | } | ||
652 | 505 | |||
653 | 484 | /* | 506 | /* |
654 | 485 | == changes == | 507 | == changes == |
655 | 486 | 508 | ||
656 | 487 | 509 | ||
657 | === added file 'ubuntuone/storageprotocol/public_file_info.py' | |||
658 | --- ubuntuone/storageprotocol/public_file_info.py 1970-01-01 00:00:00 +0000 | |||
659 | +++ ubuntuone/storageprotocol/public_file_info.py 2016-11-15 23:38:26 +0000 | |||
660 | @@ -0,0 +1,55 @@ | |||
661 | 1 | # Copyright 2016 Chicharreros (https://launchpad.net/~chicharreros) | ||
662 | 2 | # | ||
663 | 3 | # This program is free software: you can redistribute it and/or modify it | ||
664 | 4 | # under the terms of the GNU Affero General Public License version 3, | ||
665 | 5 | # as published by the Free Software Foundation. | ||
666 | 6 | # | ||
667 | 7 | # This program is distributed in the hope that it will be useful, but | ||
668 | 8 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
669 | 9 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
670 | 10 | # PURPOSE. See the GNU Affero General Public License for more details. | ||
671 | 11 | # | ||
672 | 12 | # You should have received a copy of the GNU Affero General Public License | ||
673 | 13 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
674 | 14 | # | ||
675 | 15 | # In addition, as a special exception, the copyright holders give | ||
676 | 16 | # permission to link the code of portions of this program with the | ||
677 | 17 | # OpenSSL library under certain conditions as described in each | ||
678 | 18 | # individual source file, and distribute linked combinations | ||
679 | 19 | # including the two. | ||
680 | 20 | # You must obey the GNU General Public License in all respects | ||
681 | 21 | # for all of the code used other than OpenSSL. If you modify | ||
682 | 22 | # file(s) with this exception, you may extend this exception to your | ||
683 | 23 | # version of the file(s), but you are not obligated to do so. If you | ||
684 | 24 | # do not wish to do so, delete this exception statement from your | ||
685 | 25 | # version. If you delete this exception statement from all source | ||
686 | 26 | # files in the program, then also delete it here. | ||
687 | 27 | |||
688 | 28 | """Wrapper class for public file information.""" | ||
689 | 29 | |||
690 | 30 | |||
691 | 31 | class PublicFileInfo(object): | ||
692 | 32 | """Hold the public file object information.""" | ||
693 | 33 | |||
694 | 34 | def __init__(self, share_id, node_id, is_public, public_url): | ||
695 | 35 | self.share_id = share_id | ||
696 | 36 | self.node_id = node_id | ||
697 | 37 | self.is_public = is_public | ||
698 | 38 | self.public_url = public_url | ||
699 | 39 | |||
700 | 40 | @classmethod | ||
701 | 41 | def from_message(cls, message): | ||
702 | 42 | """Creates the object using the information from a message.""" | ||
703 | 43 | info = message.public_file_info | ||
704 | 44 | result = cls( | ||
705 | 45 | share_id=info.share, | ||
706 | 46 | node_id=info.node, | ||
707 | 47 | is_public=info.is_public, | ||
708 | 48 | public_url=info.public_url) | ||
709 | 49 | return result | ||
710 | 50 | |||
711 | 51 | def __eq__(self, other): | ||
712 | 52 | if not isinstance(other, self.__class__): | ||
713 | 53 | return False | ||
714 | 54 | |||
715 | 55 | return self.__dict__ == other.__dict__ |
Comments addressed