~didrocks/ubuntuone-client/use_result_var

« back to all changes in this revision

Viewing changes to tests/syncdaemon/test_vm.py

  • Committer: Bazaar Package Importer
  • Author(s): Rodney Dawes
  • Date: 2011-02-11 16:18:11 UTC
  • mto: This revision was merged to the branch mainline in revision 67.
  • Revision ID: james.westby@ubuntu.com-20110211161811-n18dj9lde7dxqjzr
Tags: upstream-1.5.4
Import upstream version 1.5.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
65
65
class BaseVolumeManagerTests(BaseTwistedTestCase):
66
66
    """ Bas TestCase for Volume Manager tests """
67
67
 
 
68
    timeout = 5
 
69
 
68
70
    def setUp(self):
69
71
        """ setup the test """
70
72
        BaseTwistedTestCase.setUp(self)
121
123
        event_q.subscribe(listener)
122
124
        return listener
123
125
 
124
 
    def _create_udf(self, id, node_id, suggested_path, subscribed=True,
125
 
                    generation=None, free_bytes=100):
 
126
    def _create_udf(self, volume_id=None, node_id=None,
 
127
                    suggested_path='~/Documents',
 
128
                    subscribed=True, generation=None, free_bytes=100):
126
129
        """Create an UDF and returns it and the volume"""
127
130
        with environ('HOME', self.home_dir):
128
131
            path = get_udf_path(suggested_path)
129
132
        # make sure suggested_path is unicode
130
133
        if isinstance(suggested_path, str):
131
134
            suggested_path = suggested_path.decode('utf-8')
132
 
        volume = volumes.UDFVolume(id, node_id, generation,
 
135
 
 
136
        if volume_id is None:
 
137
            volume_id = str(uuid.uuid4())
 
138
        if node_id is None:
 
139
            node_id = str(uuid.uuid4())
 
140
 
 
141
        volume = volumes.UDFVolume(volume_id, node_id, generation,
133
142
                                   free_bytes, suggested_path)
134
143
        udf = UDF.from_udf_volume(volume, path)
135
144
        udf.subscribed = subscribed
136
145
        udf.generation = generation
137
 
        return udf, volume
 
146
        return udf
 
147
 
 
148
    def _create_share_volume(self, volume_id=None, node_id=None,
 
149
                             name='fake_share', generation=None, free_bytes=10,
 
150
                             access_level='View', accepted=True,
 
151
                             other_visible_name='visible_username'):
 
152
        """Return a new ShareVolume."""
 
153
        if volume_id is None:
 
154
            volume_id = str(uuid.uuid4())
 
155
        if node_id is None:
 
156
            node_id = str(uuid.uuid4())
 
157
 
 
158
        share_volume = volumes.ShareVolume(volume_id=volume_id,
 
159
                            node_id=node_id, generation=generation,
 
160
                            free_bytes=free_bytes, direction='to_me',
 
161
                            share_name=name, other_username='username',
 
162
                            other_visible_name=other_visible_name,
 
163
                            accepted=accepted, access_level=access_level)
 
164
        return share_volume
 
165
 
 
166
    def _create_share(self, volume_id=None, node_id=None, name='fake_share',
 
167
                      generation=None, free_bytes=1024,
 
168
                      access_level='View', accepted=True, subscribed=False,
 
169
                      other_visible_name='visible_username'):
 
170
        """Return a new Share."""
 
171
        share_volume = self._create_share_volume(volume_id=volume_id,
 
172
             node_id=node_id, name=name, generation=generation,
 
173
             free_bytes=free_bytes, access_level=access_level,
 
174
             accepted=accepted, other_visible_name=other_visible_name)
 
175
        dir_name = get_share_path(share_volume)
 
176
        share_path = os.path.join(self.shares_dir, dir_name)
 
177
        share = Share.from_share_volume(share_volume, share_path)
 
178
        share.subscribed = subscribed
 
179
        share.accepted = accepted
 
180
        return share
138
181
 
139
182
 
140
183
class VolumeManagerTests(BaseVolumeManagerTests):
175
218
        self.vm._got_root('other_root_uuid')
176
219
        yield d
177
220
 
178
 
    def test_add_share(self):
179
 
        """ test the add_share method. """
180
 
        # initialize the the root
181
 
        self.vm._got_root('root_uuid')
182
 
        share_path = os.path.join(self.shares_dir, 'fake_share')
183
 
        share = Share(path=share_path, volume_id='share_id')
184
 
        self.vm.add_share(share)
185
 
        self.assertIn(share.volume_id, self.vm.shares)
186
 
 
 
221
 
 
222
class VolumeManagerSharesTests(BaseVolumeManagerTests):
 
223
    """Tests for Volume Manager Shares management."""
 
224
 
 
225
    def test_share_is_equal(self):
 
226
        """Test for share comparison."""
 
227
        share1 = self._create_share(volume_id='volume_id', node_id='node_id',
 
228
                                    subscribed=True)
 
229
        share2 = self._create_share(volume_id='volume_id', node_id='node_id',
 
230
                                    subscribed=True)
 
231
 
 
232
        self.assertEqual(share1, share2)
 
233
 
 
234
    def test_share_is_not_equal(self):
 
235
        """Test for share comparison."""
 
236
        share1 = self._create_share(volume_id='volume_id', node_id='node_id',
 
237
                                    subscribed=True)
 
238
        share2 = self._create_share(volume_id='volume_id', node_id='node_id',
 
239
                                    subscribed=False)
 
240
 
 
241
        self.assertNotEqual(share1, share2)
 
242
 
 
243
    @defer.inlineCallbacks
 
244
    def test_add_share_access_level_view(self):
 
245
        """Test for add_share for a View share."""
 
246
        share = self._create_share(access_level='View', subscribed=False)
 
247
        yield self.vm.add_share(share)
 
248
 
 
249
        dir_name = get_share_path(share)
 
250
        share_path = os.path.join(self.shares_dir, dir_name)
 
251
        self.assertEqual(share_path, share.path)
 
252
        self.assertEqual(2, len(self.vm.shares))  # root and share
 
253
        self.assertIn(share.volume_id, self.vm.shares)
 
254
 
 
255
        # check that the share is in the fsm metadata
 
256
        mdobj = self.main.fs.get_by_path(share.path)
 
257
        self.assertEqual(mdobj.node_id, share.node_id)
 
258
        self.assertEqual(mdobj.share_id, share.volume_id)
 
259
 
 
260
        # check that there isn't a watch in the share (subscribed is False)
 
261
        self.assertFalse(self.main.event_q.has_watch(share.path))
 
262
 
 
263
        # remove the share
 
264
        self.vm.share_deleted(share.volume_id)
 
265
 
 
266
        # add it again, but this time with subscribed = True
 
267
        share.subscribed = True
 
268
        yield self.vm.add_share(share)
 
269
 
 
270
        self.assertEqual(share_path, share.path)
 
271
        self.assertEqual(2, len(self.vm.shares))
 
272
        self.assertIn(share.volume_id, self.vm.shares)
 
273
 
 
274
        # check that the share is in the fsm metadata
 
275
        mdobj = self.main.fs.get_by_path(share.path)
 
276
        self.assertEqual(mdobj.node_id, share.node_id)
 
277
        self.assertEqual(mdobj.share_id, share.volume_id)
 
278
 
 
279
        # check that there isn't a watch in the share (subscribed is False)
 
280
        self.assertFalse(self.main.event_q.has_watch(share.path))
 
281
 
 
282
    @defer.inlineCallbacks
 
283
    def test_add_share_access_level_modify(self):
 
284
        """Test for add_share for a Modify share."""
 
285
        share = self._create_share(access_level='Modify', subscribed=False)
 
286
        yield self.vm.add_share(share)
 
287
 
 
288
        dir_name = get_share_path(share)
 
289
        share_path = os.path.join(self.shares_dir, dir_name)
 
290
        self.assertEqual(share_path, share.path)
 
291
        self.assertEqual(2, len(self.vm.shares))  # root and share
 
292
        self.assertIn(share.volume_id, self.vm.shares)
 
293
 
 
294
        # check that the share is in the fsm metadata
 
295
        mdobj = self.main.fs.get_by_path(share.path)
 
296
        self.assertEqual(mdobj.node_id, share.node_id)
 
297
        self.assertEqual(mdobj.share_id, share.volume_id)
 
298
 
 
299
        # check that there isn't a watch in the share (subscribed is False)
 
300
        self.assertFalse(self.main.event_q.has_watch(share.path))
 
301
 
 
302
        # remove the share
 
303
        self.vm.share_deleted(share.volume_id)
 
304
 
 
305
        # add it again, but this time with subscribed = True
 
306
        share.subscribed = True
 
307
        yield self.vm.add_share(share)
 
308
 
 
309
        self.assertEqual(share_path, share.path)
 
310
        self.assertEqual(2, len(self.vm.shares))
 
311
        self.assertIn(share.volume_id, self.vm.shares)
 
312
 
 
313
        # check that the share is in the fsm metadata
 
314
        mdobj = self.main.fs.get_by_path(share.path)
 
315
        self.assertEqual(mdobj.node_id, share.node_id)
 
316
        self.assertEqual(mdobj.share_id, share.volume_id)
 
317
 
 
318
        # check that there is a watch in the share
 
319
        self.assertTrue(self.main.event_q.has_watch(share.path))
 
320
 
 
321
    @defer.inlineCallbacks
 
322
    def test_add_share_view_does_not_local_scan_share(self):
 
323
        """Test that add_share does not scan the View share."""
 
324
        share = self._create_share(access_level='View', subscribed=True)
 
325
 
 
326
        self.patch(self.main.lr, 'scan_dir', lambda *a, **kw: self.fail(a))
 
327
        server_rescan_d = defer.Deferred()
 
328
        self.main.action_q.rescan_from_scratch = server_rescan_d.callback
 
329
 
 
330
        yield self.vm.add_share(share)
 
331
 
 
332
        yield server_rescan_d
 
333
 
 
334
        self.assertEqual(2, len(self.vm.shares))
 
335
        mdobj = self.main.fs.get_by_path(share.path)
 
336
        # check that the share is in the fsm metadata
 
337
        self.assertEqual(mdobj.node_id, share.node_id)
 
338
        self.assertEqual(mdobj.share_id, share.volume_id)
 
339
        self.assertTrue(share.subscribed)
 
340
        self.assertFalse(self.main.event_q.has_watch(share.path))
 
341
 
 
342
    @defer.inlineCallbacks
 
343
    def test_add_share_modify_scans_share(self):
 
344
        """Test that add_share scans the share."""
 
345
        share = self._create_share(access_level='Modify', subscribed=True)
 
346
 
 
347
        scan_d = defer.Deferred()
 
348
 
 
349
        def fake_scan_dir(mdid, path, udfmode):
 
350
            """A fake scan share that check the arguments."""
 
351
            mdobj = self.main.fs.get_by_path(share.path)
 
352
            # check that the share is in the fsm metadata
 
353
            self.assertEqual(mdobj.node_id, share.node_id)
 
354
            self.assertEqual(mdobj.share_id, share.volume_id)
 
355
            self.assertEqual(mdid, mdobj.mdid)
 
356
            self.assertEqual(path, share.path)
 
357
            self.assertTrue(udfmode)
 
358
            scan_d.callback(None)
 
359
            return scan_d
 
360
 
 
361
        self.patch(self.main.lr, 'scan_dir', fake_scan_dir)
 
362
 
 
363
        scratch_d = defer.Deferred()
 
364
        def fake_rescan_from_scratch(volume_id):
 
365
            """A fake scan share that check the arguments."""
 
366
            self.assertEqual(share.volume_id, volume_id)
 
367
            scratch_d.callback(None)
 
368
            return scratch_d
 
369
        self.main.action_q.rescan_from_scratch = fake_rescan_from_scratch
 
370
 
 
371
        yield self.vm.add_share(share)
 
372
        yield scan_d
 
373
        yield scratch_d
 
374
 
 
375
        self.assertEqual(2, len(self.vm.shares))
 
376
        self.assertTrue(share.subscribed)
 
377
        self.assertTrue(self.main.event_q.has_watch(share.path))
 
378
 
 
379
    @defer.inlineCallbacks
187
380
    def test_share_deleted(self):
188
 
        """ Check that a share is deleted from the share mapping. """
189
 
        # initialize the the root
190
 
        self.vm._got_root('root_uuid')
191
 
        share_path = os.path.join(self.shares_dir, 'fake_share')
192
 
        share = Share(path=share_path, volume_id='share_id')
193
 
        self.vm.add_share(share)
 
381
        """Test for share_deleted when empty."""
 
382
        share = self._create_share()
 
383
        yield self.vm.add_share(share)
 
384
 
 
385
        self.assertEqual(2, len(self.vm.shares))  # root and share
194
386
        self.assertIn(share.volume_id, self.vm.shares)
 
387
 
195
388
        self.vm.share_deleted(share.volume_id)
 
389
 
 
390
        self.assertEqual(1, len(self.vm.shares))
196
391
        self.assertNotIn(share.volume_id, self.vm.shares)
197
392
 
 
393
        # check that the share isn't in the fsm metadata
 
394
        self.assertRaises(KeyError, self.main.fs.get_by_path, share.path)
 
395
        # check that there isn't a watch in the share
 
396
        self.assertFalse(self.main.event_q.has_watch(share.path))
 
397
 
 
398
    @defer.inlineCallbacks
198
399
    def test_share_deleted_with_content(self):
199
 
        """ Check that a share is deleted from the share mapping. """
200
 
        # initialize the the root
201
 
        self.vm._got_root('root_uuid')
202
 
        share_path = os.path.join(self.shares_dir, 'fake_share')
203
 
        share = Share(path=share_path, volume_id='share_id',
204
 
                      node_id='share_node_id', access_level='Modify',
205
 
                      accepted=True)
206
 
        self.vm.add_share(share)
 
400
        """Test for share_deleted when non empty."""
 
401
        share = self._create_share(access_level='Modify',
 
402
                                   accepted=True, subscribed=True)
 
403
        yield self.vm.add_share(share)
 
404
        self.assertEqual(2, len(self.vm.shares))
 
405
 
207
406
        # create a few files and directories
208
407
        dirs = ['dir', 'dir/subdir', 'dir/empty_dir']
209
408
        for i, dir in enumerate(dirs):
213
412
                    os.makedirs(path)
214
413
            self.main.fs.create(path, share.volume_id, is_dir=True)
215
414
            self.main.fs.set_node_id(path, 'dir_node_id'+str(i))
 
415
            # add a inotify watch to the dir
216
416
            self.main.event_q.add_watch(path)
217
417
        files = ['a_file', 'dir/file', 'dir/subdir/file']
218
418
        for i, file in enumerate(files):
221
421
            self.main.fs.set_node_id(path, 'file_node_id'+str(i))
222
422
 
223
423
        paths = list(self.main.fs.get_paths_starting_with(share.path))
 
424
        self.assertEqual(len(paths), len(dirs+files)+1)
224
425
        for path, is_dir in paths:
225
426
            self.assertTrue(self.main.fs.get_by_path(path))
226
427
            if is_dir:
233
434
            if is_dir:
234
435
                self.assertFalse(self.main.event_q.has_watch(path), path)
235
436
 
 
437
        self.assertEqual(1, len(self.vm.shares))
 
438
        # check that the share isn't in the fsm metadata
 
439
        self.assertRaises(KeyError, self.main.fs.get_by_path, share.path)
 
440
        # check that there isn't a watch in the share
 
441
        self.assertFalse(self.main.event_q.has_watch(share.path))
 
442
        # check that there isn't any share childs around
 
443
        for path, _ in paths:
 
444
            self.assertRaises(KeyError, self.main.fs.get_by_path, path)
 
445
        # get the childs (should be an empty list)
 
446
        paths = self.main.fs.get_paths_starting_with(share.path)
 
447
        self.assertEqual(0, len(paths))
 
448
 
 
449
    @defer.inlineCallbacks
236
450
    def test_share_changed(self):
237
451
        """Check that VM.share_changed updates the access_level."""
238
452
        share_holder = NotifyShareHolder.from_params('share_id', None,
244
458
        share_path = os.path.join(self.shares_dir, share_holder.share_name)
245
459
        share = Share(path=share_path, volume_id=share_holder.share_id,
246
460
                      access_level='View')
247
 
        self.vm.add_share(share)
 
461
        yield self.vm.add_share(share)
248
462
        self.vm.share_changed(share_holder)
249
463
        self.assertEqual('Modify',
250
464
                         self.vm.shares[share.volume_id].access_level)
278
492
        self.assertEqual('fake_share', share.name)
279
493
        self.assertEqual('fake_share_uuid', share.node_id)
280
494
 
 
495
    @defer.inlineCallbacks
281
496
    def test_handle_SV_SHARE_CHANGED(self):
282
497
        """ test the handling of the AQ_SHARE_LIST event. """
283
498
        share_id = uuid.uuid4()
291
506
        share_path = os.path.join(self.shares_dir, share_holder.share_name)
292
507
        share = Share(path=share_path, volume_id=str(share_holder.share_id),
293
508
                      access_level='View')
294
 
        self.vm.add_share(share)
 
509
        yield self.vm.add_share(share)
295
510
        self.vm.handle_SV_SHARE_CHANGED(info=share_holder)
296
511
        self.assertEquals('Modify', self.vm.shares[str(share_id)].access_level)
297
512
        self.vm.handle_SV_SHARE_DELETED(share_holder.share_id)
298
513
        self.assertNotIn('share_id', self.vm.shares)
299
514
 
 
515
    @defer.inlineCallbacks
300
516
    def test_persistence(self):
301
517
        """ Test that the persistence of shares works as expected. """
302
518
        # create the folders layout
303
 
        share_path = os.path.join(self.shares_dir, 'my_share')
304
 
        share = Share(path=share_path, volume_id='a_share_id', access_level='View')
305
 
        self.vm.add_share(share)
 
519
        share = self._create_share()
 
520
        yield self.vm.add_share(share)
306
521
        other_vm = VolumeManager(self.main)
307
522
        for key in self.vm.shares:
308
523
            self.assertEquals(self.vm.shares[key].__dict__,
330
545
        response = ListShares(None)
331
546
        response.shares = [share_response, shared_response]
332
547
        self.vm.handle_AQ_SHARES_LIST(response)
333
 
        self.assertEquals(2, len(self.vm.shares)) # the new shares and root
334
 
        self.assertEquals(1, len(self.vm.shared)) # the new shares and root
 
548
        self.assertEqual(2, len(self.vm.shares)) # the new share and root
 
549
        self.assertEqual(1, len(self.vm.shared)) # the new shared
335
550
        shared = self.vm.shared[str(shared_id)]
336
551
        self.assertEquals('fake_shared', shared.name)
337
552
        # check that the uuid is stored in fs
436
651
        self.main.fs.create(path, "")
437
652
        self.main.fs.set_node_id(path, 'node_id')
438
653
        share = Shared(path=path, volume_id='share_id', node_id="node_id")
439
 
        self.vm.add_shared(share)
 
654
        yield self.vm.add_shared(share)
440
655
 
441
656
        def fake_delete_share(share_id):
442
657
            """Fake delete_share."""
458
673
        self.main.fs.create(path, "")
459
674
        self.main.fs.set_node_id(path, 'node_id')
460
675
        share = Shared(path=path, volume_id='share_id', node_id="node_id")
461
 
        self.vm.add_shared(share)
 
676
        yield self.vm.add_shared(share)
462
677
 
463
678
        def fake_delete_share(share_id):
464
679
            """Fake delete_share that always fails."""
486
701
        self.assertEqual(events[0],
487
702
                         dict(share_id='fake_share_id', error='DOES_NOT_EXIST'))
488
703
 
 
704
    @defer.inlineCallbacks
489
705
    def test_accept_share(self):
490
706
        """ Test the accept_share method. """
491
707
        d = defer.Deferred()
492
708
        self.vm._got_root('root_uuid')
493
709
        share_path = os.path.join(self.shares_dir, 'fake_share')
494
710
        share = Share(path=share_path, volume_id='share_id', node_id="node_id")
495
 
        self.vm.add_share(share)
 
711
        yield self.vm.add_share(share)
496
712
        self.assertIn(share.volume_id, self.vm.shares)
497
713
        self.assertEquals(False, share.accepted)
498
714
        # helper method, pylint: disable-msg=C0111
506
722
            self.assertEquals('Yes', answer)
507
723
        d.addCallback(callback)
508
724
        self.vm.accept_share(share.volume_id, True)
509
 
        return d
 
725
        yield d
510
726
 
511
727
    def test_handle_AQ_SHARES_LIST_shared_missing_md(self):
512
728
        """test the handling of the AQ_SHARE_LIST event, when the md
529
745
        self.assertEquals(shared_response.subtree, shared.node_id)
530
746
        self.assertEquals(None, shared.path)
531
747
 
 
748
    @defer.inlineCallbacks
532
749
    def test_handle_SV_SHARE_ANSWERED(self):
533
750
        """ test the handling of the AQ_SHARE_ANSWERED. """
534
751
        path = os.path.join(self.vm.root.path, 'shared_path')
539
756
        self.vm._got_root('root_uuid')
540
757
        # add the shared folder
541
758
        share = Share(path=path, volume_id='share_id', access_level='View')
542
 
        self.vm.add_shared(share)
 
759
        yield self.vm.add_shared(share)
543
760
        self.assertEquals(False, self.vm.shared['share_id'].accepted)
544
761
        # check that a answer notify of a missing share don't blowup
545
762
        self.vm.handle_SV_SHARE_ANSWERED('share_id', 'Yes')
692
909
        self.vm.handle_SYS_QUOTA_EXCEEDED(request.ROOT, 11221)
693
910
        self.assertEqual(self.vm.get_volume(request.ROOT).free_bytes, 11221)
694
911
 
 
912
    @defer.inlineCallbacks
695
913
    def test_handle_SYS_QUOTA_EXCEEDED_udf(self):
696
914
        """Test that it updates the free space when error is on an UDF."""
697
915
        # create the udf
700
918
        volume_id = str(uuid.uuid4())
701
919
        volume = volumes.UDFVolume(volume_id, 'udf_node_id', None, 0, u"~/UDF")
702
920
        udf = UDF.from_udf_volume(volume, path)
703
 
        self.vm.add_udf(udf)
 
921
        yield self.vm.add_udf(udf)
704
922
 
705
923
        # call the handler
706
924
        self.vm.handle_SYS_QUOTA_EXCEEDED(volume_id, 1122)
708
926
        # but check the free bytes from root, that is who stores this info
709
927
        self.assertEqual(self.vm.get_volume(request.ROOT).free_bytes, 1122)
710
928
 
 
929
    @defer.inlineCallbacks
711
930
    def test_handle_SYS_QUOTA_EXCEEDED_share(self):
712
931
        """Test that it updates the free space when error is on a share."""
713
932
        # build the share
714
933
        share_id = str(uuid.uuid4())
715
 
        share_volume = volumes.ShareVolume(share_id, 'fake_share_uuid', None,
716
 
                                           10, 'to_me', 'fake_share', 'usern',
717
 
                                           'visible_username', True, 'Modify')
718
 
        dir_name = get_share_path(share_volume.share_name,
719
 
                                  share_volume.other_visible_name)
720
 
        share_path = os.path.join(self.main.shares_dir, dir_name)
721
 
        share = Share.from_share_volume(share_volume, share_path)
722
 
        self.vm.add_share(share)
 
934
        share = self._create_share(volume_id=share_id)
 
935
        yield self.vm.add_share(share)
723
936
 
724
937
        # call and check
725
938
        self.vm.handle_SYS_QUOTA_EXCEEDED(share_id, 1122)
728
941
    @defer.inlineCallbacks
729
942
    def test_handle_AQ_ANSWER_SHARE_OK(self):
730
943
        """Test for handle_AQ_ANSWER_SHARE_OK."""
731
 
        share_id = uuid.uuid4()
732
 
        share_volume = volumes.ShareVolume(share_id, 'fake_share_uuid', None,
733
 
                                           10, 'to_me', 'fake_share', 'usern',
734
 
                                           'visible_username', False, 'View')
735
 
        dir_name = get_share_path(share_volume.share_name,
736
 
                                  share_volume.other_visible_name)
737
 
        share_path = os.path.join(self.main.shares_dir, dir_name)
738
 
        share = Share.from_share_volume(share_volume, share_path)
 
944
        share = self._create_share()
739
945
 
740
946
        scratch_d = defer.Deferred()
741
947
        def fake_rescan_from_scratch(volume_id):
744
950
            scratch_d.callback(None)
745
951
        self.main.action_q.rescan_from_scratch = fake_rescan_from_scratch
746
952
 
747
 
        self.vm.add_share(share)
 
953
        yield self.vm.add_share(share)
748
954
        self.vm.handle_AQ_ANSWER_SHARE_OK(share.volume_id, 'Yes')
749
955
        yield scratch_d
750
956
        share = self.vm.get_volume(share.volume_id)
761
967
        self.main.fs.create(path, "")
762
968
        self.main.fs.set_node_id(path, 'node_id')
763
969
        share = Shared(path=path, volume_id='share_id', node_id="node_id")
764
 
        self.vm.add_shared(share)
 
970
        yield self.vm.add_shared(share)
765
971
        d = defer.Deferred()
766
972
        self._listen_for('VM_SHARE_DELETED', d.callback, 1, collect=True)
767
973
        self.main.event_q.push('AQ_DELETE_SHARE_OK', share_id='share_id')
775
981
        self.main.fs.create(path, "")
776
982
        self.main.fs.set_node_id(path, 'node_id')
777
983
        share = Shared(path=path, volume_id='share_id', node_id="node_id")
778
 
        self.vm.add_shared(share)
 
984
        yield self.vm.add_shared(share)
779
985
        d = defer.Deferred()
780
986
        self._listen_for('VM_SHARE_DELETE_ERROR', d.callback, 1, collect=True)
781
987
        self.main.event_q.push('AQ_DELETE_SHARE_ERROR',
794
1000
                self.assertEqual(set(defined_args[1:]), set(evtargs))
795
1001
 
796
1002
 
 
1003
class ViewSharesSubscriptionTests(BaseVolumeManagerTests):
 
1004
    """Test Shares subscription operations when access_level is View."""
 
1005
 
 
1006
    access_level = 'View'
 
1007
 
 
1008
    @defer.inlineCallbacks
 
1009
    def test_subscribe_share(self):
 
1010
        """Test subscribe_share method."""
 
1011
        share = self._create_share(access_level=self.access_level,
 
1012
                                   subscribed=False)
 
1013
        yield self.vm.add_share(share)
 
1014
        self.assertFalse(self.vm.shares[share.volume_id].subscribed)
 
1015
        # subscribe to it
 
1016
        yield self.vm.subscribe_share(share.volume_id)
 
1017
        self.assertTrue(self.vm.shares[share.volume_id].subscribed)
 
1018
 
 
1019
    @defer.inlineCallbacks
 
1020
    def test_subscribe_share_missing_path(self):
 
1021
        """Test subscribe_share with a missing path """
 
1022
        share = self._create_share(access_level=self.access_level,
 
1023
                                   subscribed=False)
 
1024
        yield self.vm.add_share(share)
 
1025
        self.assertFalse(os.path.exists(share.path))
 
1026
        self.assertFalse(self.vm.shares[share.id].subscribed)
 
1027
        # subscribe to it
 
1028
        yield self.vm.subscribe_share(share.id)
 
1029
        self.assertTrue(self.vm.shares[share.id].subscribed)
 
1030
        self.assertTrue(os.path.exists(share.path))
 
1031
 
 
1032
    @defer.inlineCallbacks
 
1033
    def test_subscribe_share_missing_volume(self):
 
1034
        """Test subscribe_share with a invalid volume_id."""
 
1035
        try:
 
1036
            yield self.vm.subscribe_share('invalid_share_id')
 
1037
        except VolumeDoesNotExist, e:
 
1038
            self.assertEquals('DOES_NOT_EXIST', e.args[0])
 
1039
            self.assertEquals('invalid_share_id', e.args[1])
 
1040
        else:
 
1041
            self.fail('Must get a VolumeDoesNotExist!')
 
1042
 
 
1043
    @defer.inlineCallbacks
 
1044
    def test_unsubscribe_share(self):
 
1045
        """Test unsubscribe_share method."""
 
1046
        share = self._create_share(access_level=self.access_level,
 
1047
                                   subscribed=True)
 
1048
        yield self.vm.add_share(share)
 
1049
        self.assertTrue(self.vm.shares[share.volume_id].subscribed)
 
1050
        # unsubscribe from it
 
1051
        self.vm.unsubscribe_share(share.volume_id)
 
1052
        self.assertFalse(self.vm.shares[share.volume_id].subscribed)
 
1053
 
 
1054
    @defer.inlineCallbacks
 
1055
    def test_unsubscribe_share_with_content(self):
 
1056
        """Test unsubscribe_share method in a share with content."""
 
1057
        share = self._create_share(access_level=self.access_level,
 
1058
                                   subscribed=True)
 
1059
        yield self.vm.add_share(share)
 
1060
 
 
1061
        self.assertTrue(self.vm.shares[share.volume_id].subscribed)
 
1062
        # create a few files and directories
 
1063
        dirs = ['dir', 'dir/subdir', 'dir/empty_dir']
 
1064
        for i, dir in enumerate(dirs):
 
1065
            path = os.path.join(share.path, dir)
 
1066
            with allow_writes(os.path.split(share.path)[0]):
 
1067
                with allow_writes(share.path):
 
1068
                    if not os.path.exists(path):
 
1069
                        os.makedirs(path)
 
1070
            self.main.fs.create(path, share.volume_id, is_dir=True)
 
1071
            self.main.fs.set_node_id(path, 'dir_node_id'+str(i))
 
1072
            # add a inotify watch to the dir
 
1073
            self.main.event_q.add_watch(path)
 
1074
        files = ['a_file', 'dir/file', 'dir/subdir/file']
 
1075
        for i, file in enumerate(files):
 
1076
            path = os.path.join(share.path, file)
 
1077
            with allow_writes(os.path.split(share.path)[0]):
 
1078
                with allow_writes(share.path):
 
1079
                    open(path, 'w').close()
 
1080
            self.main.fs.create(path, share.volume_id)
 
1081
            self.main.fs.set_node_id(path, 'file_node_id'+str(i))
 
1082
        paths = self.main.fs.get_paths_starting_with(share.path)
 
1083
        self.assertEquals(len(paths), len(dirs+files)+1)
 
1084
 
 
1085
        # unsubscribe from it
 
1086
        self.vm.unsubscribe_share(share.volume_id)
 
1087
 
 
1088
        self.assertEquals(2, len(self.vm.shares))  # share and root
 
1089
        self.assertFalse(self.vm.shares[share.volume_id].subscribed)
 
1090
        # check that the share is in the fsm metadata
 
1091
        self.assertTrue(self.main.fs.get_by_path(share.path))
 
1092
        # get the childs (should be an empty list)
 
1093
        paths = list(self.main.fs.get_paths_starting_with(share.path))
 
1094
        self.assertEquals(len(dirs+files)+1, len(paths))
 
1095
        # check that there isn't a watch in the share
 
1096
        self.assertFalse(self.main.event_q.has_watch(share.path))
 
1097
        # check that the childs don't have a watch
 
1098
        for path, is_dir in paths:
 
1099
            if is_dir:
 
1100
                self.assertFalse(self.main.event_q.has_watch(path))
 
1101
 
 
1102
 
 
1103
class ModifySharesSubscriptionTests(ViewSharesSubscriptionTests):
 
1104
    """Test Shares subscription operations when access_level is Modify."""
 
1105
 
 
1106
    access_level = 'Modify'
 
1107
 
 
1108
    @defer.inlineCallbacks
 
1109
    def test_subscribe_share_missing_fsm_md(self):
 
1110
        """Test subscribe_share with a missing node in fsm."""
 
1111
        share = self._create_share(access_level=self.access_level,
 
1112
                                   subscribed=False)
 
1113
        yield self.vm.add_share(share)
 
1114
        self.assertFalse(os.path.exists(share.path))
 
1115
        self.assertFalse(self.vm.shares[share.id].subscribed)
 
1116
        yield self.vm.subscribe_share(share.id)
 
1117
        yield self.vm.unsubscribe_share(share.id)
 
1118
        # delete the fsm metadata
 
1119
        self.main.fs.delete_metadata(share.path)
 
1120
        # subscribe to it and fail!
 
1121
        try:
 
1122
            yield self.vm.subscribe_share(share.id)
 
1123
        except KeyError, e:
 
1124
            self.assertIn(share.path, e.args[0])
 
1125
        else:
 
1126
            self.fail('Must get a KeyError!')
 
1127
 
 
1128
    @defer.inlineCallbacks
 
1129
    def _test_subscribe_share_generations(self, share):
 
1130
        """Test subscribe_share with a generation."""
 
1131
        scratch_d = defer.Deferred()
 
1132
        def fake_rescan_from_scratch(volume_id):
 
1133
            """A fake rescan_from_scratch that check the arguments."""
 
1134
            self.assertEquals(share.volume_id, volume_id)
 
1135
            scratch_d.callback(None)
 
1136
        self.main.action_q.rescan_from_scratch = fake_rescan_from_scratch
 
1137
        # subscribe to it
 
1138
        yield self.vm.subscribe_share(share.volume_id)
 
1139
        yield scratch_d
 
1140
        self.assertTrue(self.vm.shares[share.volume_id].subscribed)
 
1141
 
 
1142
    @defer.inlineCallbacks
 
1143
    def test_subscribe_share_valid_generation(self):
 
1144
        """Test subscribe_share with a valid generation."""
 
1145
        share = self._create_share(access_level=self.access_level,
 
1146
                                   subscribed=False)
 
1147
        yield self.vm.add_share(share)
 
1148
        self.assertFalse(self.vm.shares[share.volume_id].subscribed)
 
1149
        # update share generation
 
1150
        self.vm.update_generation(share.volume_id, 0)
 
1151
        yield self._test_subscribe_share_generations(share)
 
1152
 
 
1153
    @defer.inlineCallbacks
 
1154
    def test_subscribe_share_without_generation(self):
 
1155
        """Test subscribe_share without a valid generation."""
 
1156
        share = self._create_share(access_level=self.access_level,
 
1157
                                   subscribed=False)
 
1158
        yield self.vm.add_share(share)
 
1159
        self.assertFalse(self.vm.shares[share.volume_id].subscribed)
 
1160
        # update share generation
 
1161
        self.vm.update_generation(share.volume_id, None)
 
1162
        yield self._test_subscribe_share_generations(share)
 
1163
 
 
1164
    @defer.inlineCallbacks
 
1165
    def test_unsubscribe_subscribe_share_with_content(self):
 
1166
        """Test for re-subscribing to a share."""
 
1167
        share = self._create_share(access_level=self.access_level,
 
1168
                                   subscribed=True)
 
1169
        yield self.vm.add_share(share)
 
1170
        self.main.event_q.rm_watch(share.path)
 
1171
        self.assertTrue(self.vm.shares[share.volume_id].subscribed)
 
1172
        # create a few files and directories
 
1173
        dirs = ['dir', 'dir/subdir', 'dir/empty_dir']
 
1174
        for i, dir in enumerate(dirs):
 
1175
            path = os.path.join(share.path, dir)
 
1176
            with allow_writes(os.path.split(share.path)[0]):
 
1177
                with allow_writes(share.path):
 
1178
                    if not os.path.exists(path):
 
1179
                        os.makedirs(path)
 
1180
            self.main.fs.create(path, share.volume_id, is_dir=True)
 
1181
            self.main.fs.set_node_id(path, 'dir_node_id'+str(i))
 
1182
        files = ['a_file', 'dir/file', 'dir/subdir/file']
 
1183
        for i, path in enumerate(files):
 
1184
            path = os.path.join(share.path, path)
 
1185
            with allow_writes(os.path.split(share.path)[0]):
 
1186
                with allow_writes(share.path):
 
1187
                    open(path, 'w').close()
 
1188
            self.main.fs.create(path, share.volume_id)
 
1189
            self.main.fs.set_node_id(path, 'file_node_id'+str(i))
 
1190
        paths = list(self.main.fs.get_paths_starting_with(share.path))
 
1191
        # add a inotify watch to the dirs
 
1192
        for path, is_dir in paths:
 
1193
            if is_dir:
 
1194
                self.main.event_q.add_watch(path)
 
1195
        self.assertEquals(len(paths), len(dirs+files)+1, paths)
 
1196
 
 
1197
        # unsubscribe from it
 
1198
        self.vm.unsubscribe_share(share.volume_id)
 
1199
 
 
1200
        self.assertEquals(2, len(self.vm.shares))  # share and root
 
1201
        self.assertFalse(self.vm.shares[share.volume_id].subscribed)
 
1202
        # check that the share is in the fsm metadata
 
1203
        self.assertTrue(self.main.fs.get_by_path(share.path))
 
1204
        # check that there isn't a watch in the share
 
1205
        self.assertFalse(self.main.event_q.has_watch(share.path))
 
1206
        # check that the childs don't have a watch
 
1207
        for path, is_dir in paths:
 
1208
            if is_dir:
 
1209
                self.assertFalse(self.main.event_q.has_watch(path))
 
1210
        # check the childs
 
1211
        paths = self.main.fs.get_paths_starting_with(share.path)
 
1212
        self.assertEquals(len(dirs+files)+1, len(paths))
 
1213
        # resubscribe to it
 
1214
        yield self.vm.subscribe_share(share.volume_id)
 
1215
        paths = list(self.main.fs.get_paths_starting_with(share.path))
 
1216
        # we should only have the dirs, as the files metadata is
 
1217
        # delete by local rescan (both hashes are '')
 
1218
        self.assertEquals(len(dirs)+1, len(paths))
 
1219
        # check that there is a watch in the share
 
1220
        self.assertTrue(self.main.event_q.has_watch(share.path))
 
1221
        # check that the child dirs have a watch
 
1222
        for path, is_dir in paths:
 
1223
            if is_dir:
 
1224
                self.assertTrue(self.main.event_q.has_watch(path),
 
1225
                                '%s has a watch' % path)
 
1226
                self.vm._remove_watch(path)
 
1227
 
 
1228
 
797
1229
class VolumeManagerUnicodeTests(BaseVolumeManagerTests):
798
1230
    """Tests for Volume Manager unicode capabilities."""
799
1231
 
813
1245
        # check
814
1246
        share = self.vm.shares['share_id']
815
1247
        shouldbe_dir = os.path.join(self.shares_dir,
816
 
                                    u"montón".encode("utf8") + " from visible")
 
1248
                                    get_share_path(share_response))
817
1249
        self.assertEquals(shouldbe_dir, share.path)
818
1250
 
819
1251
    def test_handle_SHARES_visible_username(self):
832
1264
        # check
833
1265
        share = self.vm.shares['share_id']
834
1266
        shouldbe_dir = os.path.join(self.shares_dir,
835
 
                            "sharename from " + u"Darío Toño".encode("utf8"))
 
1267
                                    get_share_path(share_response))
836
1268
        self.assertEquals(shouldbe_dir, share.path)
837
1269
 
838
1270
    def test_handle_SV_SHARE_CHANGED_sharename(self):
844
1276
        self.vm._got_root('root_uuid')
845
1277
        self.vm.handle_SV_SHARE_CHANGED(info=share_holder)
846
1278
        shouldbe_dir = os.path.join(self.shares_dir,
847
 
                                    u"año".encode("utf8") + " from visible")
 
1279
                                    get_share_path(share_holder))
848
1280
        self.assertEquals(shouldbe_dir, self.vm.shares['share_id'].path)
849
1281
 
850
1282
    def test_handle_SV_SHARE_CHANGED_visible(self):
856
1288
        self.vm._got_root('root_uuid')
857
1289
        self.vm.handle_SV_SHARE_CHANGED(info=share_holder)
858
1290
        shouldbe_dir = os.path.join(self.shares_dir,
859
 
                                    "share from " + u"Ramón".encode("utf8"))
 
1291
                                    get_share_path(share_holder))
860
1292
        self.assertEquals(shouldbe_dir, self.vm.shares['share_id'].path)
861
1293
 
862
1294
 
863
1295
class VolumeManagerVolumesTests(BaseVolumeManagerTests):
864
1296
    """Test UDF/Volumes bits of the VolumeManager."""
865
1297
 
866
 
    timeout = 5
867
 
 
868
1298
    def setUp(self):
869
1299
        """Setup the test."""
870
1300
        BaseVolumeManagerTests.setUp(self)
878
1308
        expected = [u'~', u'~/Documents', u'~/Documents/Reading',
879
1309
                    u'~/Documents/Reading/Books']
880
1310
        with environ('HOME', self.home_dir):
881
 
            udf, volume = self._create_udf('uid', 'nid', suggested_path)
 
1311
            udf = self._create_udf(suggested_path=suggested_path)
882
1312
            self.assertEquals(map(os.path.expanduser, expected), udf.ancestors)
883
1313
 
884
1314
    @defer.inlineCallbacks
885
1315
    def test_add_udf(self):
886
1316
        """Test for VolumeManager.add_udf."""
887
1317
        suggested_path = "suggested_path"
888
 
        udf, volume = self._create_udf(uuid.uuid4(), 'udf_node_id',
889
 
                                       '~/' + suggested_path, subscribed=False)
 
1318
        udf = self._create_udf(suggested_path='~/' + suggested_path,
 
1319
                               subscribed=False)
890
1320
        yield self.vm.add_udf(udf)
891
1321
        self.assertEquals(os.path.join(self.home_dir, suggested_path),
892
1322
                          udf.path)
893
1323
        self.assertEquals(1, len(self.vm.udfs))
894
1324
        # check that the UDF is in the fsm metadata
895
1325
        mdobj = self.main.fs.get_by_path(udf.path)
896
 
        self.assertEquals(mdobj.node_id, 'udf_node_id')
897
 
        self.assertEquals(mdobj.share_id, udf.volume_id)
 
1326
        self.assertEqual(mdobj.node_id, udf.node_id)
 
1327
        self.assertEqual(mdobj.share_id, udf.volume_id)
898
1328
        # check that there isn't a watch in the UDF (we aren't
899
1329
        # subscribed to it)
900
1330
        self.assertFalse(self.main.event_q.has_watch(udf.path))
908
1338
        self.assertEquals(1, len(self.vm.udfs))
909
1339
        # check that the UDF is in the fsm metadata
910
1340
        mdobj = self.main.fs.get_by_path(udf.path)
911
 
        self.assertEquals(mdobj.node_id, 'udf_node_id')
912
 
        self.assertEquals(mdobj.share_id, udf.volume_id)
 
1341
        self.assertEqual(mdobj.node_id, udf.node_id)
 
1342
        self.assertEqual(mdobj.share_id, udf.volume_id)
913
1343
        # check that there is a watch in the UDF
914
1344
        self.assertTrue(self.main.event_q.has_watch(udf.path))
915
1345
 
916
1346
    @defer.inlineCallbacks
917
1347
    def test_add_udf_calls_AQ(self):
918
1348
        """Test that VolumeManager.add_udf calls AQ.rescan_from_scratch."""
919
 
        suggested_path = "suggested_path"
920
 
        udf, volume = self._create_udf(uuid.uuid4(), 'udf_node_id',
921
 
                                       '~/' + suggested_path, subscribed=True)
 
1349
        udf = self._create_udf(subscribed=True)
922
1350
        scratch_d = defer.Deferred()
923
1351
        def fake_rescan_from_scratch(volume_id):
924
1352
            """A fake rescan_from_scratch that check the arguments."""
928
1356
 
929
1357
        yield self.vm.add_udf(udf)
930
1358
        yield scratch_d
931
 
        self.assertEquals(os.path.join(self.home_dir, suggested_path),
932
 
                          udf.path)
 
1359
 
933
1360
        self.assertEquals(1, len(self.vm.udfs))
934
1361
        # check that the UDF is in the fsm metadata
935
1362
        mdobj = self.main.fs.get_by_path(udf.path)
936
 
        self.assertEquals(mdobj.node_id, 'udf_node_id')
937
 
        self.assertEquals(mdobj.share_id, udf.volume_id)
 
1363
        self.assertEqual(mdobj.node_id, udf.node_id)
 
1364
        self.assertEqual(mdobj.share_id, udf.volume_id)
938
1365
        self.assertTrue(self.main.event_q.has_watch(udf.path))
939
1366
 
940
1367
    @defer.inlineCallbacks
941
1368
    def test_udf_deleted(self):
942
1369
        """Test for VolumeManager.udf_deleted."""
943
 
        suggested_path = "suggested_path"
944
 
        udf, volume = self._create_udf(uuid.uuid4(), 'udf_node_id',
945
 
                                       '~/' + suggested_path)
 
1370
        udf = self._create_udf()
946
1371
        yield self.vm.add_udf(udf)
947
1372
        self.assertEquals(1, len(self.vm.udfs))
948
1373
        self.vm.udf_deleted(udf.volume_id)
959
1384
        contains files and directories.
960
1385
 
961
1386
        """
962
 
        suggested_path = "suggested_path"
963
 
        udf, volume = self._create_udf(uuid.uuid4(), 'udf_node_id',
964
 
                                       '~/' + suggested_path, subscribed=True)
 
1387
        udf = self._create_udf(subscribed=True)
965
1388
        yield self.vm.add_udf(udf)
966
1389
        self.assertEquals(1, len(self.vm.udfs))
967
1390
        # create a few files and directories
999
1422
        """Test for VolumeManager.get_volume."""
1000
1423
        # create a Share
1001
1424
        share_id = uuid.uuid4()
1002
 
        share_volume = volumes.ShareVolume(share_id, 'fake_share_uuid', None,
1003
 
                                           10, 'to_me', 'fake_share',
1004
 
                                           'username', 'visible_username',
1005
 
                                           True, 'View')
1006
 
        dir_name = get_share_path(share_volume.share_name,
1007
 
                                  share_volume.other_visible_name)
1008
 
        share_path = os.path.join(self.main.shares_dir, dir_name)
1009
 
        share = Share.from_share_volume(share_volume, share_path)
 
1425
        share = self._create_share(volume_id=share_id)
1010
1426
        # create a UDF
1011
1427
        udf_id = uuid.uuid4()
1012
 
        udf, volume = self._create_udf(udf_id, 'udf_node_id', '~/UDF')
 
1428
        udf = self._create_udf(volume_id=udf_id)
1013
1429
        yield self.vm.add_udf(udf)
1014
 
        self.vm.add_share(share)
 
1430
        yield self.vm.add_share(share)
1015
1431
        self.assertEqual(1, len(self.vm.udfs))
1016
1432
        self.assertEqual(2, len(self.vm.shares))
1017
1433
        self.assertEqual(udf.volume_id,
1023
1439
class HandleListVolumesTestCase(BaseVolumeManagerTests):
1024
1440
    """Test the handling of the AQ_LIST_VOLUMES event."""
1025
1441
 
1026
 
    timeout = 5
1027
 
 
1028
1442
    def setUp(self):
1029
1443
        """Setup the test."""
1030
1444
        BaseVolumeManagerTests.setUp(self)
1039
1453
    def test_handle_AQ_LIST_VOLUMES(self):
1040
1454
        """Test the handling of the AQ_LIST_VOLUMES event."""
1041
1455
        share_id = uuid.uuid4()
1042
 
        share_volume = volumes.ShareVolume(share_id, 'fake_share_uuid', None,
1043
 
                                           10, 'to_me', 'fake_share',
1044
 
                                           'username', 'visible_username',
1045
 
                                           True, 'View')
 
1456
        share_volume = self._create_share_volume(volume_id=share_id,
 
1457
             name='fake_share', node_id='fake_share_uuid')
1046
1458
        udf_id = uuid.uuid4()
1047
1459
        udf_volume = volumes.UDFVolume(udf_id, 'udf_uuid', None, 100, u'~/UDF')
1048
1460
        root_volume = volumes.RootVolume(uuid.uuid4(), 17, 10)
1110
1522
    def test_handle_AQ_LIST_VOLUMES_unicode(self):
1111
1523
        """Test the handling of the AQ_LIST_VOLUMES event."""
1112
1524
        share_id = uuid.uuid4()
1113
 
        share_volume = volumes.ShareVolume(share_id, 'fake_share_uuid', None,
1114
 
                                           10, 'to_me', u'ñoño',
1115
 
                                           'username', u'visible_username',
1116
 
                                           True, 'View')
 
1525
        name = u'ñoño'
 
1526
        share_volume = self._create_share_volume(volume_id=share_id, name=name,
 
1527
                                                 node_id='fake_share_uuid')
1117
1528
        udf_id = uuid.uuid4()
1118
1529
        udf_volume = volumes.UDFVolume(udf_id, 'udf_uuid', None, 10, u'~/ñoño')
1119
1530
        # initialize the the root
1131
1542
        self.assertIn(str(share_id), self.vm.shares)
1132
1543
        self.assertIn(str(udf_id), self.vm.udfs)
1133
1544
        share = self.vm.shares[str(share_id)]
1134
 
        self.assertEqual(u'ñoño', share.name)
 
1545
        self.assertEqual(name, share.name)
1135
1546
        self.assertEqual('fake_share_uuid', share.node_id)
1136
1547
        udf = self.vm.udfs[str(udf_id)]
1137
1548
        self.assertEqual('udf_uuid', udf.node_id)
1156
1567
    def _test_handle_AQ_LIST_VOLUMES_accepted_share(self, auto_subscribe):
1157
1568
        """Test handle_AQ_LIST_VOLUMES event with an accepted share."""
1158
1569
        user_conf = config.get_user_config()
1159
 
        user_conf.set_udf_autosubscribe(auto_subscribe)
1160
 
 
1161
 
        # start the test
1162
 
        share_id = uuid.uuid4()
1163
 
        share_response = ShareResponse.from_params(share_id, 'to_me',
1164
 
                                                   'fake_share_uuid_to_me',
1165
 
                                                   'fake_share_to_me',
1166
 
                                                   'username_1',
1167
 
                                                   'visible_username_1', False,
1168
 
                                                   'View')
1169
 
        shared_id = uuid.uuid4()
1170
 
        shared_response = ShareResponse.from_params(shared_id, 'from_me',
1171
 
                                                   'fake_share_uuid',
1172
 
                                                   'fake_share', 'username',
1173
 
                                                   'visible_username', True,
1174
 
                                                   'View')
1175
 
        shares_response = ListShares(None)
1176
 
        shares_response.shares = [shared_response, share_response]
1177
 
        self.vm.handle_AQ_SHARES_LIST(shares_response)
1178
 
 
1179
 
        # check
1180
 
        self.assertIn(str(share_id), self.vm.shares)
1181
 
        self.assertFalse(self.vm.shares[str(share_id)].active)
1182
 
        self.assertIn(str(shared_id), self.vm.shared)
 
1570
        user_conf.set_share_autosubscribe(auto_subscribe)
 
1571
 
 
1572
        # handle_AQ_SHARES_LIST is tested on test_handle_AQ_SHARES_LIST
1183
1573
 
1184
1574
        # create a volume list
1185
 
        udf_id = uuid.uuid4()
1186
 
        udf_volume = volumes.UDFVolume(udf_id, 'udf_uuid', None, 100, u'~/UDF')
1187
1575
        root_volume = volumes.RootVolume(uuid.uuid4(), 17, 10)
1188
 
        share_volume = volumes.ShareVolume(share_id, 'fake_share_uuid', 10,
1189
 
                                           10, 'to_me', 'fake_share',
1190
 
                                           'username', 'visible_username',
1191
 
                                           True, 'View')
1192
 
        response = [share_volume, udf_volume, root_volume]
1193
 
        d1 = defer.Deferred()
1194
 
        d2 = defer.Deferred()
 
1576
        share_id = uuid.uuid4()
 
1577
        share_volume = self._create_share_volume(volume_id=share_id,
 
1578
             node_id='fake_share_uuid', generation=10, accepted=True)
 
1579
        response = [share_volume, root_volume]
 
1580
 
1195
1581
        share_created_d = defer.Deferred()
1196
 
        self.vm.refresh_volumes = lambda: d1.errback('refresh_volumes called!')
1197
 
        self._listen_for('VM_UDF_CREATED', d1.callback)
1198
 
        self._listen_for('SV_VOLUME_NEW_GENERATION', d2.callback, 2, collect=True)
 
1582
        vol_new_gen_d = defer.Deferred()
 
1583
 
 
1584
        self.vm.refresh_volumes = lambda: self.fail('refresh_volumes called!')
1199
1585
        # listen for VM_SHARE_CREATED event for the new share
1200
1586
        self._listen_for('VM_SHARE_CREATED', share_created_d.callback)
1201
 
        # use a custom home
 
1587
        if auto_subscribe:
 
1588
            expected_events = [{'generation': 10, 'volume_id': str(share_id)},
 
1589
                               {'generation': 17, 'volume_id': ''}]
 
1590
            self.patch(self.vm, '_scan_share',
 
1591
                       lambda *a, **kw: defer.succeed(None))
 
1592
            self._listen_for('SV_VOLUME_NEW_GENERATION',
 
1593
                             vol_new_gen_d.callback, 2, collect=True)
 
1594
        else:
 
1595
            expected_events = {'generation': 17, 'volume_id': ''}
 
1596
            self.patch(self.vm, '_scan_share', lambda *a, **kw: self.fail(a))
 
1597
            self._listen_for('SV_VOLUME_NEW_GENERATION',
 
1598
                             vol_new_gen_d.callback)
 
1599
 
 
1600
        # use a custom home, and trigger the operation
1202
1601
        with environ('HOME', self.home_dir):
1203
1602
            self.vm.handle_AQ_LIST_VOLUMES(response)
1204
1603
 
1205
 
        yield d1
1206
 
        events = yield d2
1207
1604
        yield share_created_d
 
1605
        events = yield vol_new_gen_d
1208
1606
 
1209
 
        expected_events = [{'generation': 10, 'volume_id': str(share_id)},
1210
 
                           {'generation': 17, 'volume_id': ''}]
1211
1607
        self.assertEqual(events, expected_events)
1212
1608
 
 
1609
        def check():
 
1610
            """The test itself."""
 
1611
            self.assertEqual(2, len(self.vm.shares)) # the share and the root
 
1612
            # check that the share is in the shares dict
 
1613
            self.assertIn(str(share_id), self.vm.shares)
 
1614
            share = self.vm.shares[str(share_id)]
 
1615
            self.assertEqual('fake_share', share.name)
 
1616
            self.assertEqual('fake_share_uuid', share.node_id)
 
1617
            self.assertTrue(share.accepted, "The share is accepted")
 
1618
            if auto_subscribe:
 
1619
                # root and share
 
1620
                self.assertEqual(2, len(list(self.vm.get_volumes())))
 
1621
                self.assertTrue(share.active)
 
1622
            else:  # share was added to VM, but isn't active
 
1623
                self.assertEqual(1, len(list(self.vm.get_volumes())))
 
1624
                self.assertFalse(share.active)
 
1625
 
 
1626
        check()
 
1627
 
 
1628
        # root was already checked on test_handle_AQ_LIST_VOLUMES_root
 
1629
 
 
1630
        # now send the same list again and check using a custom home
 
1631
        with environ('HOME', self.home_dir):
 
1632
            self.vm.handle_AQ_LIST_VOLUMES(response)
 
1633
 
 
1634
        check()
 
1635
 
 
1636
    @defer.inlineCallbacks
 
1637
    def test_handle_AQ_LIST_VOLUMES_accepted_share_with_autosubscribe(self):
 
1638
        """Test handle_AQ_LIST_VOLUMES event with an active share."""
 
1639
        yield self._test_handle_AQ_LIST_VOLUMES_accepted_share(True)
 
1640
 
 
1641
    @defer.inlineCallbacks
 
1642
    def test_handle_AQ_LIST_VOLUMES_accepted_share_without_autosubscribe(self):
 
1643
        """Test handle_AQ_LIST_VOLUMES event with an inactive share."""
 
1644
        yield self._test_handle_AQ_LIST_VOLUMES_accepted_share(False)
 
1645
 
 
1646
    @defer.inlineCallbacks
 
1647
    def _test_handle_AQ_LIST_VOLUMES_udf(self, auto_subscribe):
 
1648
        """Test handle_AQ_LIST_VOLUMES event with an udf."""
 
1649
        user_conf = config.get_user_config()
 
1650
        user_conf.set_udf_autosubscribe(auto_subscribe)
 
1651
 
 
1652
        # create a volume list
 
1653
        udf_id = uuid.uuid4()
 
1654
        udf_volume = volumes.UDFVolume(udf_id, 'udf_uuid', 23, 100, u'~/UDF')
 
1655
        root_volume = volumes.RootVolume(uuid.uuid4(), 17, 10)
 
1656
        response = [udf_volume, root_volume]
 
1657
 
 
1658
        self.vm.refresh_volumes = lambda: self.fail('refresh_volumes called!')
 
1659
 
 
1660
        udf_created_d = defer.Deferred()
 
1661
        vol_new_gen_d = defer.Deferred()
 
1662
 
 
1663
        # listen for VM_UDF_CREATED event for the new UDF
 
1664
        self._listen_for('VM_UDF_CREATED', udf_created_d.callback)
1213
1665
        if auto_subscribe:
1214
 
            # root, share and udf
1215
 
            self.assertEqual(3, len(list(self.vm.get_volumes())))
 
1666
            expected_events = [{'generation': 23, 'volume_id': str(udf_id)},
 
1667
                               {'generation': 17, 'volume_id': ''}]
 
1668
            self.patch(self.vm, '_scan_udf', defer.succeed)
 
1669
            self._listen_for('SV_VOLUME_NEW_GENERATION',
 
1670
                             vol_new_gen_d.callback, 2, collect=True)
 
1671
        else:
 
1672
            expected_events = {'generation': 17, 'volume_id': ''}
 
1673
            self.patch(self.vm, '_scan_udf', self.fail)
 
1674
            self._listen_for('SV_VOLUME_NEW_GENERATION',
 
1675
                             vol_new_gen_d.callback)
 
1676
 
 
1677
        # use a custom home, and trigger the operation
 
1678
        with environ('HOME', self.home_dir):
 
1679
            self.vm.handle_AQ_LIST_VOLUMES(response)
 
1680
 
 
1681
        yield udf_created_d
 
1682
        events = yield vol_new_gen_d
 
1683
 
 
1684
        self.assertEqual(events, expected_events)
 
1685
 
 
1686
        def check():
 
1687
            """The test itself."""
1216
1688
            self.assertEqual(1, len(self.vm.udfs)) # the new udf
 
1689
            # check that the UDF is in the udfs dict
1217
1690
            self.assertIn(str(udf_id), self.vm.udfs)
1218
1691
            udf = self.vm.udfs[str(udf_id)]
1219
1692
            self.assertEqual('udf_uuid', udf.node_id)
1220
1693
            self.assertEqual(os.path.join(self.home_dir, 'UDF'), udf.path)
1221
 
        else:  # udf was not added to VM
1222
 
            self.assertEqual(2, len(list(self.vm.get_volumes())))
1223
 
            self.assertEqual(1, len(self.vm.udfs)) # the new udf
1224
 
            self.assertFalse(self.vm.udfs.values()[0].active)
1225
 
 
1226
 
        self.assertEqual(2, len(self.vm.shares)) # the share and the root
1227
 
        # check that the share is in the shares dict
1228
 
        self.assertIn(str(share_id), self.vm.shares)
1229
 
        share = self.vm.shares[str(share_id)]
1230
 
        self.assertEqual('fake_share_to_me', share.name)
1231
 
        self.assertEqual('fake_share_uuid_to_me', share.node_id)
1232
 
        self.assertTrue(share.accepted, "The share isn't accepted")
1233
 
        # check that the root it's there, have right node_id and generation
1234
 
        self.assertIn(request.ROOT, self.vm.shares)
1235
 
        root = self.vm.shares[request.ROOT]
1236
 
        self.assertEqual(root.node_id, str(root_volume.node_id))
1237
 
 
1238
 
        # now send the same list again and check
1239
 
        # use a custom home
 
1694
            if auto_subscribe:
 
1695
                # root and udf
 
1696
                self.assertEqual(2, len(list(self.vm.get_volumes())))
 
1697
                self.assertTrue(udf.active)
 
1698
            else:  # udf was added to VM, but isn't active
 
1699
                self.assertEqual(1, len(list(self.vm.get_volumes())))
 
1700
                self.assertFalse(udf.active)
 
1701
 
 
1702
        check()
 
1703
 
 
1704
        # root was already checked on test_handle_AQ_LIST_VOLUMES_root
 
1705
 
 
1706
        # now send the same list again and check using a custom home
1240
1707
        with environ('HOME', self.home_dir):
1241
1708
            self.vm.handle_AQ_LIST_VOLUMES(response)
1242
1709
 
1243
 
        self.assertEqual(2, len(self.vm.shares)) # the share and root
1244
 
        if auto_subscribe:
1245
 
            # root, share and udf
1246
 
            self.assertEqual(1, len(self.vm.udfs)) # one udf
1247
 
            self.assertEqual(3, len(list(self.vm.get_volumes())))
1248
 
        else:  # udf was added to VM, but isn't active
1249
 
            self.assertEqual(2, len(list(self.vm.get_volumes())))
1250
 
            self.assertEqual(1, len(self.vm.udfs)) # the new udf
1251
 
            self.assertFalse(self.vm.udfs.values()[0].active)
1252
 
 
1253
 
    @defer.inlineCallbacks
1254
 
    def test_handle_AQ_LIST_VOLUMES_accepted_share_with_autosubscribe(self):
1255
 
        """Test handle_AQ_LIST_VOLUMES event with an accepted share.
1256
 
 
1257
 
        The setting udf_autosubscribe will be set.
1258
 
 
1259
 
        """
1260
 
        yield self._test_handle_AQ_LIST_VOLUMES_accepted_share(True)
1261
 
 
1262
 
    @defer.inlineCallbacks
1263
 
    def test_handle_AQ_LIST_VOLUMES_accepted_share_without_autosubscribe(self):
1264
 
        """Test handle_AQ_LIST_VOLUMES event with an accepted share.
1265
 
 
1266
 
        The setting udf_autosubscribe will not be set.
1267
 
 
1268
 
        """
1269
 
        yield self._test_handle_AQ_LIST_VOLUMES_accepted_share(False)
 
1710
        check()
 
1711
 
 
1712
    @defer.inlineCallbacks
 
1713
    def test_handle_AQ_LIST_VOLUMES_udf_with_autosubscribe(self):
 
1714
        """Test handle_AQ_LIST_VOLUMES event with an active udf."""
 
1715
        yield self._test_handle_AQ_LIST_VOLUMES_udf(True)
 
1716
 
 
1717
    @defer.inlineCallbacks
 
1718
    def test_handle_AQ_LIST_VOLUMES_udf_without_autosubscribe(self):
 
1719
        """Test handle_AQ_LIST_VOLUMES event with an inactive udf."""
 
1720
        yield self._test_handle_AQ_LIST_VOLUMES_udf(False)
1270
1721
 
1271
1722
 
1272
1723
class VolumeManagerOperationsTests(BaseVolumeManagerTests):
1273
1724
    """Test UDF/Volumes operations."""
1274
1725
 
1275
 
    timeout = 5
1276
 
 
1277
1726
    def setUp(self):
1278
1727
        """Setup the test."""
1279
1728
        BaseVolumeManagerTests.setUp(self)
1364
1813
        AQ_DELETE_VOLUME_OK is correctly handled.
1365
1814
 
1366
1815
        """
1367
 
        suggested_path = "suggested_path"
1368
 
        udf, volume = self._create_udf(uuid.uuid4(), 'udf_node_id',
1369
 
                                       '~/' + suggested_path, subscribed=False)
 
1816
        udf = self._create_udf(subscribed=False)
1370
1817
        yield self.vm.add_udf(udf)
1371
 
        share_id = uuid.uuid4()
1372
 
        share_volume = volumes.ShareVolume(share_id, 'fake_share_uuid', None,
1373
 
                                           10, 'to_me', u'ñoño',
1374
 
                                           'username', u'visible_username',
1375
 
                                           True, 'View')
1376
 
        dir_name = get_share_path(share_volume.share_name,
1377
 
                                  share_volume.other_visible_name)
1378
 
        share_path = os.path.join(self.main.shares_dir, dir_name)
1379
 
        share = Share.from_share_volume(share_volume, share_path)
1380
 
        self.vm.add_share(share)
 
1818
        share = self._create_share()
 
1819
        yield self.vm.add_share(share)
1381
1820
        d = defer.Deferred()
1382
1821
        # patch AQ.delete_volume
1383
1822
        def delete_volume(volume_id, path):
1416
1855
    @defer.inlineCallbacks
1417
1856
    def test_delete_volume_aq_args(self):
1418
1857
        """Test that VolumeManager.delete_volume calls AQ.delete_volume."""
1419
 
        suggested_path = "suggested_path"
1420
 
        udf, volume = self._create_udf(uuid.uuid4(), 'udf_node_id',
1421
 
                                       '~/' + suggested_path, subscribed=False)
 
1858
        udf = self._create_udf(subscribed=False)
1422
1859
        yield self.vm.add_udf(udf)
1423
1860
        d = defer.Deferred()
1424
1861
        # patch AQ.delete_volume
1437
1874
    def test_subscribe_udf(self):
1438
1875
        """Test VolumeManager.subscribe_udf method."""
1439
1876
        # create and add a UDF
1440
 
        suggested_path = "suggested_path"
1441
 
        udf, volume = self._create_udf(uuid.uuid4(), 'udf_node_id',
1442
 
                                       '~/' + suggested_path, subscribed=False)
 
1877
        udf = self._create_udf(subscribed=False)
1443
1878
        yield self.vm.add_udf(udf)
1444
1879
        self.assertFalse(self.vm.udfs[udf.volume_id].subscribed)
1445
1880
        # subscribe to it
1450
1885
    def test_subscribe_udf_missing_path(self):
1451
1886
        """Test VolumeManager.subscribe_udf with a missing path """
1452
1887
        # create and add a UDF
1453
 
        suggested_path = "suggested_path"
1454
 
        udf, volume = self._create_udf(uuid.uuid4(), 'udf_node_id',
1455
 
                                       '~/' + suggested_path, subscribed=False)
 
1888
        udf = self._create_udf(subscribed=False)
1456
1889
        yield self.vm.add_udf(udf)
1457
1890
        self.assertFalse(os.path.exists(udf.path))
1458
1891
        self.assertFalse(self.vm.udfs[udf.id].subscribed)
1465
1898
    def test_subscribe_udf_missing_fsm_md(self):
1466
1899
        """Test VolumeManager.subscribe_udf with a missing node in fsm."""
1467
1900
        # create and add a UDF
1468
 
        suggested_path = "suggested_path"
1469
 
        udf, volume = self._create_udf(uuid.uuid4(), 'udf_node_id',
1470
 
                                       '~/' + suggested_path, subscribed=False)
 
1901
        udf = self._create_udf(subscribed=False)
1471
1902
        yield self.vm.add_udf(udf)
1472
1903
        self.assertFalse(os.path.exists(udf.path))
1473
1904
        self.assertFalse(self.vm.udfs[udf.id].subscribed)
1512
1943
    @defer.inlineCallbacks
1513
1944
    def test_subscribe_udf_valid_generation(self):
1514
1945
        """Test subscribe_udf with a valid generation."""
1515
 
        suggested_path = "suggested_path"
1516
 
        udf, _ = self._create_udf(uuid.uuid4(), 'udf_node_id',
1517
 
                                       '~/' + suggested_path,
1518
 
                                       subscribed=False)
 
1946
        udf = self._create_udf(subscribed=False)
1519
1947
        yield self.vm.add_udf(udf)
1520
1948
        self.assertFalse(self.vm.udfs[udf.volume_id].subscribed)
1521
1949
        # update udf generation
1526
1954
    def test_subscribe_udf_without_generation(self):
1527
1955
        """Test subscribe_udf without a valid generation."""
1528
1956
        # create and add a UDF
1529
 
        suggested_path = "suggested_path"
1530
 
        udf, _ = self._create_udf(uuid.uuid4(), 'udf_node_id',
1531
 
                                       '~/' + suggested_path,
1532
 
                                       subscribed=False)
 
1957
        udf = self._create_udf(subscribed=False)
1533
1958
        yield self.vm.add_udf(udf)
1534
1959
        self.assertFalse(self.vm.udfs[udf.volume_id].subscribed)
1535
1960
        # update udf generation
1540
1965
    def test_unsubscribe_udf(self):
1541
1966
        """Test VolumeManager.unsubscribe_udf method."""
1542
1967
        # create and add a UDF
1543
 
        suggested_path = "suggested_path"
1544
 
        udf, volume = self._create_udf(uuid.uuid4(), 'udf_node_id',
1545
 
                                       '~/' + suggested_path, subscribed=True)
 
1968
        udf = self._create_udf(subscribed=True)
1546
1969
        yield self.vm.add_udf(udf)
1547
1970
        self.assertTrue(self.vm.udfs[udf.volume_id].subscribed)
1548
1971
        # unsubscribe from it
1553
1976
    def test_unsubscribe_udf_with_content(self):
1554
1977
        """Test VolumeManager.unsubscribe_udf method in a UDF with content."""
1555
1978
        # create and add a UDF
1556
 
        suggested_path = "suggested_path"
1557
 
        udf, volume = self._create_udf(uuid.uuid4(), 'udf_node_id',
1558
 
                                       '~/' + suggested_path, subscribed=True)
 
1979
        udf = self._create_udf(subscribed=True)
1559
1980
        yield self.vm.add_udf(udf)
1560
1981
        self.assertTrue(self.vm.udfs[udf.volume_id].subscribed)
1561
1982
        # create a few files and directories
1598
2019
    def test_unsubscribe_subscribe_udf_with_content(self):
1599
2020
        """Test for re-subscribing to a UDF."""
1600
2021
        # create and add a UDF
1601
 
        suggested_path = "suggested_path"
1602
 
        udf, volume = self._create_udf(uuid.uuid4(), 'udf_node_id',
1603
 
                                       '~/' + suggested_path, subscribed=True)
 
2022
        udf = self._create_udf(subscribed=True)
1604
2023
        yield self.vm.add_udf(udf)
1605
2024
        self.main.event_q.rm_watch(udf.path)
1606
2025
        self.assertTrue(self.vm.udfs[udf.volume_id].subscribed)
1660
2079
        """Test for VolumeManager._cleanup_volumes"""
1661
2080
        share_path = os.path.join(self.shares_dir, 'fake_share')
1662
2081
        share = Share(path=share_path, volume_id='share_id')
1663
 
        self.vm.add_share(share)
1664
 
        suggested_path = "suggested_path"
1665
 
        udf, volume = self._create_udf(uuid.uuid4(), 'udf_node_id',
1666
 
                                       '~/' + suggested_path, subscribed=True)
 
2082
        yield self.vm.add_share(share)
 
2083
        udf = self._create_udf(subscribed=True)
1667
2084
        yield self.vm.add_udf(udf)
1668
2085
        self.assertIn(share.volume_id, self.vm.shares)
1669
2086
        self.assertIn(udf.volume_id, self.vm.udfs)
1673
2090
        self.vm._cleanup_volumes(udfs=[])
1674
2091
        self.assertNotIn(udf.volume_id, self.vm.udfs)
1675
2092
        # all at once
1676
 
        self.vm.add_share(share)
 
2093
        yield self.vm.add_share(share)
1677
2094
        yield self.vm.add_udf(udf)
1678
2095
        self.assertIn(share.volume_id, self.vm.shares)
1679
2096
        self.assertIn(udf.volume_id, self.vm.udfs)
1681
2098
        self.assertNotIn(share.volume_id, self.vm.shares)
1682
2099
        self.assertNotIn(udf.volume_id, self.vm.udfs)
1683
2100
 
 
2101
    @defer.inlineCallbacks
1684
2102
    def test_cleanup_shared(self):
1685
2103
        """Test for VolumeManager._cleanup_shared"""
1686
2104
        shared_path = os.path.join(self.root_dir, 'fake_shared')
1687
2105
        shared = Share(path=shared_path, volume_id='shared_id')
1688
 
        self.vm.add_shared(shared)
 
2106
        yield self.vm.add_shared(shared)
1689
2107
        self.assertIn(shared.volume_id, self.vm.shared)
1690
2108
        self.vm._cleanup_shared([shared.volume_id])
1691
2109
        self.assertIn(shared.volume_id, self.vm.shared)
1692
2110
        self.vm._cleanup_shared([])
1693
2111
        self.assertNotIn(shared.volume_id, self.vm.shared)
1694
2112
 
 
2113
    @defer.inlineCallbacks
1695
2114
    def test_cleanup_shares(self):
1696
2115
        """Test for VolumeManager._cleanup_shares"""
1697
2116
        share_path = os.path.join(self.shares_dir, 'fake_share')
1698
2117
        share = Share(path=share_path, volume_id='share_id')
1699
2118
        share_2_path = os.path.join(self.root_dir, 'fake_share_2')
1700
2119
        share_2 = Share(path=share_2_path, volume_id='share_2_id')
1701
 
        self.vm.add_share(share)
1702
 
        self.vm.add_share(share_2)
 
2120
        yield self.vm.add_share(share)
 
2121
        yield self.vm.add_share(share_2)
1703
2122
        self.assertIn(share.volume_id, self.vm.shares)
1704
2123
        self.assertIn(share_2.volume_id, self.vm.shares)
1705
2124
        self.vm._cleanup_shares([])
1706
2125
        self.assertNotIn(share.volume_id, self.vm.shares)
1707
2126
        self.assertNotIn(share_2.volume_id, self.vm.shares)
1708
 
        self.vm.add_share(share)
1709
 
        self.vm.add_share(share_2)
 
2127
        yield self.vm.add_share(share)
 
2128
        yield self.vm.add_share(share_2)
1710
2129
        self.vm._cleanup_shares([share.volume_id])
1711
2130
        self.assertIn(share.volume_id, self.vm.shares)
1712
2131
        self.assertNotIn(share_2.volume_id, self.vm.shares)
1713
 
        self.vm.add_share(share)
1714
 
        self.vm.add_share(share_2)
 
2132
        yield self.vm.add_share(share)
 
2133
        yield self.vm.add_share(share_2)
1715
2134
        self.vm._cleanup_shares([share.volume_id, share_2.volume_id])
1716
2135
        self.assertIn(share.volume_id, self.vm.shares)
1717
2136
        self.assertIn(share_2.volume_id, self.vm.shares)
1770
2189
    @defer.inlineCallbacks
1771
2190
    def test_handle_AQ_DELETE_VOLUME_OK(self):
1772
2191
        """Test for handle_AQ_DELETE_VOLUME_OK."""
1773
 
        suggested_path = "suggested_path"
1774
 
        udf, volume = self._create_udf(uuid.uuid4(), 'udf_node_id',
1775
 
                                       '~/' + suggested_path, subscribed=False)
 
2192
        udf = self._create_udf(subscribed=False)
1776
2193
        yield self.vm.add_udf(udf)
1777
2194
        d = defer.Deferred()
1778
2195
        # patch AQ.delete_volume
1797
2214
    @defer.inlineCallbacks
1798
2215
    def test_handle_AQ_DELETE_VOLUME_ERROR(self):
1799
2216
        """Test for handle_AQ_DELETE_VOLUME_ERROR."""
1800
 
        suggested_path = "suggested_path"
1801
 
        udf, volume = self._create_udf(uuid.uuid4(), 'udf_node_id',
1802
 
                                       '~/' + suggested_path, subscribed=False)
 
2217
        udf = self._create_udf(subscribed=False)
1803
2218
        yield self.vm.add_udf(udf)
1804
2219
        d = defer.Deferred()
1805
2220
        # patch AQ.delete_volume
1829
2244
        self.assertTrue(self.handler.check_warning("missing volume id"))
1830
2245
 
1831
2246
    @defer.inlineCallbacks
1832
 
    def test_handle_SV_VOLUME_CREATED_share(self):
 
2247
    def _test_handle_SV_VOLUME_CREATED_share(self, auto_subscribe):
1833
2248
        """Test for handle_SV_VOLUME_CREATED with shares."""
 
2249
        user_conf = config.get_user_config()
 
2250
        user_conf.set_share_autosubscribe(auto_subscribe)
 
2251
 
1834
2252
        # start the test
1835
 
        share_id = uuid.uuid4()
1836
 
        share_volume = volumes.ShareVolume(
1837
 
            share_id, 'fake_share_uuid', None, 10, 'to_me', u'ñoño',
1838
 
            'username', u'visible_username',
1839
 
            False, # this is how the protocol send it
1840
 
            'View')
 
2253
        share_volume = self._create_share_volume(accepted=False, access_level='Modify')
1841
2254
        # initialize the the root
1842
2255
        self.vm._got_root('root_uuid')
1843
 
        d = defer.Deferred()
1844
 
        self._listen_for('VM_SHARE_CREATED', d.callback)
1845
 
        rescan_cb = defer.Deferred()
1846
 
        self.patch(self.main.action_q, 'rescan_from_scratch', rescan_cb.callback)
 
2256
 
 
2257
        share_created_d = defer.Deferred()
 
2258
        self._listen_for('VM_SHARE_CREATED', share_created_d.callback)
 
2259
 
 
2260
        local_scan_d = defer.Deferred()
 
2261
        server_rescan_d = defer.Deferred()
 
2262
 
 
2263
        if auto_subscribe:
 
2264
            self.patch(self.main.lr, 'scan_dir',
 
2265
                       lambda *a, **kw: local_scan_d.callback(a))
 
2266
            self.patch(self.main.action_q, 'rescan_from_scratch',
 
2267
                       server_rescan_d.callback)
 
2268
        else:
 
2269
            self.patch(self.main.lr, 'scan_dir', lambda *a: self.fail(a))
 
2270
            self.patch(self.main.action_q, 'rescan_from_scratch', self.fail)
 
2271
 
1847
2272
        # fire SV_VOLUME_CREATED with a share
1848
2273
        with environ('HOME', self.home_dir):
1849
2274
            self.vm.handle_SV_VOLUME_CREATED(share_volume)
1850
 
        info = yield d
 
2275
 
 
2276
        info = yield share_created_d
1851
2277
        share_id = info['share_id']
1852
2278
        share = self.vm.get_volume(share_id)
1853
2279
        self.assertEquals(share.volume_id, str(share_id))
1854
2280
        self.assertIn(str(share_id), self.vm.shares)
1855
 
        # check that rescan_from_scratch is called
1856
 
        vol_id = yield rescan_cb
1857
 
        self.assertEqual(vol_id, share.volume_id)
 
2281
 
 
2282
        if auto_subscribe:
 
2283
            self.assertTrue(share.subscribed)
 
2284
            self.assertTrue(os.path.exists(share.path))
 
2285
            # check that scan_dir and rescan_from_scratch is called
 
2286
            yield local_scan_d
 
2287
            vol_id = yield server_rescan_d
 
2288
            self.assertEqual(vol_id, share.volume_id)
 
2289
        else:
 
2290
            self.assertFalse(share.subscribed)
 
2291
            self.assertFalse(os.path.exists(share.path))
 
2292
 
 
2293
    def test_handle_SV_VOLUME_CREATED_share_subscribe(self):
 
2294
        """Test SV_VOLUME_CREATED with share auto_subscribe """
 
2295
        return self._test_handle_SV_VOLUME_CREATED_share(True)
 
2296
 
 
2297
    def test_handle_SV_VOLUME_CREATED_share_no_subscribe(self):
 
2298
        """Test SV_VOLUME_CREATED without share auto_subscribe """
 
2299
        return self._test_handle_SV_VOLUME_CREATED_share(False)
1858
2300
 
1859
2301
    @defer.inlineCallbacks
1860
2302
    def _test_handle_SV_VOLUME_CREATED_udf(self, auto_subscribe):
1899
2341
    @defer.inlineCallbacks
1900
2342
    def test_handle_SV_VOLUME_DELETED(self):
1901
2343
        """Test for handle_SV_VOLUME_DELETED."""
1902
 
        share_id = uuid.uuid4()
1903
 
        share_volume = volumes.ShareVolume(share_id, 'fake_share_uuid', None,
1904
 
                                           10, 'to_me', u'ñoño',
1905
 
                                           'username', u'visible_username',
1906
 
                                           True, 'View')
1907
 
        dir_name = get_share_path(share_volume.share_name,
1908
 
                                  share_volume.other_visible_name)
1909
 
        share_path = os.path.join(self.main.shares_dir, dir_name)
1910
 
        share = Share.from_share_volume(share_volume, share_path)
 
2344
        share = self._create_share()
1911
2345
        # create a UDF
 
2346
        suggested_path = u'~/ñoño'
 
2347
        with environ('HOME', self.home_dir):
 
2348
            path = get_udf_path(suggested_path)
1912
2349
        udf_id = uuid.uuid4()
1913
 
        udf, udf_volume = self._create_udf(udf_id, 'udf_uuid', u'~/ñoño')
 
2350
        udf_volume = volumes.UDFVolume(udf_id, 'udf_uuid', None, 10,
 
2351
                                       suggested_path)
 
2352
        udf = UDF.from_udf_volume(udf_volume, path)
1914
2353
        yield self.vm.add_udf(udf)
1915
 
        self.vm.add_share(share)
 
2354
        yield self.vm.add_share(share)
1916
2355
        # initialize the the root
1917
2356
        self.vm._got_root('root_uuid')
1918
2357
        d = defer.Deferred()
1929
2368
        self._listen_for('VM_VOLUME_DELETED', share_deferred.callback)
1930
2369
        # fire SV_VOLUME_DELETED with a share
1931
2370
        with environ('HOME', self.home_dir):
1932
 
            self.vm.handle_SV_VOLUME_DELETED(share_volume.volume_id)
 
2371
            self.vm.handle_SV_VOLUME_DELETED(share.volume_id)
1933
2372
        share_info = yield share_deferred
1934
 
        share = share_info['volume']
1935
 
        self.assertEquals(share.volume_id, str(share_id))
 
2373
        new_share = share_info['volume']
 
2374
        self.assertEquals(new_share.volume_id, share.volume_id)
1936
2375
        self.assertNotIn(str(share.volume_id), self.vm.shares)
1937
2376
 
1938
2377
    @defer.inlineCallbacks
1939
2378
    def test_get_volumes(self):
1940
 
        """Tests for VolumeManager.get_volumes."""
 
2379
        """Tests for VolumeManager.get_volumes.
 
2380
 
 
2381
        This is a legacy test where all the volume types are mixed. Dedicated
 
2382
        tests in a per volume basis follow below.
 
2383
 
 
2384
        """
1941
2385
        share_path = os.path.join(self.shares_dir, 'fake_share')
1942
2386
        share_modify = Share(path=share_path, volume_id='share_id',
1943
2387
                             node_id=str(uuid.uuid4()),
1944
 
                             access_level='Modify', accepted=True)
 
2388
                             access_level='Modify', accepted=True,
 
2389
                             subscribed=True)
1945
2390
        share_no_accepted_path = os.path.join(self.shares_dir, 'fake_share')
1946
2391
        share_no_accepted = Share(path=share_no_accepted_path,
1947
2392
                               node_id=str(uuid.uuid4()),
1948
2393
                               volume_id='accepted_share_id',
1949
 
                               access_level='Modify', accepted=False)
 
2394
                               access_level='Modify', accepted=False,
 
2395
                               subscribed=True)
1950
2396
        share_view = Share(path=share_path, volume_id='share_id_view',
1951
 
                           access_level='View', accepted=True)
1952
 
        self.vm.add_share(share_modify)
1953
 
        self.vm.add_share(share_view)
1954
 
        self.vm.add_share(share_no_accepted)
 
2397
                           access_level='View', accepted=True,
 
2398
                           subscribed=True)
 
2399
        yield self.vm.add_share(share_modify)
 
2400
        yield self.vm.add_share(share_view)
 
2401
        yield self.vm.add_share(share_no_accepted)
1955
2402
        shared_path = os.path.join(self.root_dir, 'fake_shared')
1956
 
        shared = Share(path=shared_path, volume_id='shared_id')
1957
 
        self.vm.add_shared(shared)
1958
 
        suggested_path = "suggested_path"
1959
 
        udf_subscribed, _ = self._create_udf(uuid.uuid4(), 'udf_node_id',
1960
 
                                       '~/' + suggested_path, subscribed=True)
1961
 
        udf_unsubscribed, _ = self._create_udf(uuid.uuid4(), 'udf_node_id',
1962
 
                                       '~/' + suggested_path, subscribed=False)
 
2403
        shared = Shared(path=shared_path, volume_id='shared_id')
 
2404
        yield self.vm.add_shared(shared)
 
2405
        udf_subscribed = self._create_udf(subscribed=True)
 
2406
        udf_unsubscribed = self._create_udf(subscribed=False)
1963
2407
        yield self.vm.add_udf(udf_subscribed)
1964
2408
        yield self.vm.add_udf(udf_unsubscribed)
1965
2409
        volumes = list(self.vm.get_volumes())
1979
2423
        self.assertIn(udf_subscribed.id, all_volumes_ids)
1980
2424
        self.assertIn(udf_unsubscribed.id, all_volumes_ids)
1981
2425
 
 
2426
    @defer.inlineCallbacks
 
2427
    def test_get_volumes_shared(self):
 
2428
        """Tests for VolumeManager.get_volumes."""
 
2429
        shared_path = os.path.join(self.root_dir, 'fake_shared')
 
2430
        shared = Shared(path=shared_path, volume_id='shared_id')
 
2431
        yield self.vm.add_shared(shared)
 
2432
 
 
2433
        volumes = list(self.vm.get_volumes())
 
2434
        volumes_ids = [v.id for v in volumes]
 
2435
        self.assertNotIn(shared.id, volumes_ids)
 
2436
 
 
2437
        all_volumes = list(self.vm.get_volumes(all_volumes=True))
 
2438
        all_volumes_ids = [v.id for v in all_volumes]
 
2439
        self.assertNotIn(shared.id, all_volumes_ids)
 
2440
 
 
2441
    @defer.inlineCallbacks
 
2442
    def test_get_volumes_share_active_modify(self):
 
2443
        """Tests for VolumeManager.get_volumes."""
 
2444
        share = self._create_share(access_level='Modify',
 
2445
                                   accepted=True, subscribed=True)
 
2446
        yield self.vm.add_share(share)
 
2447
 
 
2448
        volumes = list(self.vm.get_volumes())
 
2449
        volumes_ids = [v.id for v in volumes]
 
2450
        self.assertIn(share.id, volumes_ids)
 
2451
 
 
2452
        all_volumes = list(self.vm.get_volumes(all_volumes=True))
 
2453
        all_volumes_ids = [v.id for v in all_volumes]
 
2454
        self.assertIn(share.id, all_volumes_ids)
 
2455
 
 
2456
    @defer.inlineCallbacks
 
2457
    def test_get_volumes_share_active_view(self):
 
2458
        """Tests for VolumeManager.get_volumes."""
 
2459
        share = self._create_share(access_level='View',
 
2460
                                   accepted=True, subscribed=True)
 
2461
        yield self.vm.add_share(share)
 
2462
 
 
2463
        volumes = list(self.vm.get_volumes())
 
2464
        volumes_ids = [v.id for v in volumes]
 
2465
        self.assertIn(share.id, volumes_ids)
 
2466
 
 
2467
        all_volumes = list(self.vm.get_volumes(all_volumes=True))
 
2468
        all_volumes_ids = [v.id for v in all_volumes]
 
2469
        self.assertIn(share.id, all_volumes_ids)
 
2470
 
 
2471
    @defer.inlineCallbacks
 
2472
    def test_get_volumes_share_inactive(self):
 
2473
        """Tests for VolumeManager.get_volumes."""
 
2474
        share_no_accepted = self._create_share(accepted=False,
 
2475
                                               subscribed=True)
 
2476
        yield self.vm.add_share(share_no_accepted)
 
2477
        share_no_subscribed = self._create_share(accepted=True,
 
2478
                                                 subscribed=False)
 
2479
        yield self.vm.add_share(share_no_subscribed)
 
2480
 
 
2481
        volumes = list(self.vm.get_volumes())
 
2482
        volumes_ids = [v.id for v in volumes]
 
2483
        self.assertNotIn(share_no_accepted.id, volumes_ids)
 
2484
        self.assertNotIn(share_no_subscribed.id, volumes_ids)
 
2485
 
 
2486
        all_volumes = list(self.vm.get_volumes(all_volumes=True))
 
2487
        all_volumes_ids = [v.id for v in all_volumes]
 
2488
        self.assertIn(share_no_accepted.id, all_volumes_ids)
 
2489
        self.assertIn(share_no_subscribed.id, all_volumes_ids)
 
2490
 
 
2491
    @defer.inlineCallbacks
 
2492
    def test_get_volumes_udf_inactive(self):
 
2493
        """Tests for VolumeManager.get_volumes."""
 
2494
        udf = self._create_udf(subscribed=False)
 
2495
        yield self.vm.add_udf(udf)
 
2496
 
 
2497
        volumes = list(self.vm.get_volumes())
 
2498
        volumes_ids = [v.id for v in volumes]
 
2499
        self.assertNotIn(udf.id, volumes_ids)
 
2500
 
 
2501
        all_volumes = list(self.vm.get_volumes(all_volumes=True))
 
2502
        all_volumes_ids = [v.id for v in all_volumes]
 
2503
        self.assertIn(udf.id, all_volumes_ids)
 
2504
 
 
2505
    @defer.inlineCallbacks
 
2506
    def test_get_volumes_udf_active(self):
 
2507
        """Tests for VolumeManager.get_volumes."""
 
2508
        udf = self._create_udf(subscribed=True)
 
2509
        yield self.vm.add_udf(udf)
 
2510
 
 
2511
        volumes = list(self.vm.get_volumes())
 
2512
        volumes_ids = [v.id for v in volumes]
 
2513
        self.assertIn(udf.id, volumes_ids)
 
2514
 
 
2515
        all_volumes = list(self.vm.get_volumes(all_volumes=True))
 
2516
        all_volumes_ids = [v.id for v in all_volumes]
 
2517
        self.assertIn(udf.id, all_volumes_ids)
 
2518
 
1982
2519
    def test_udf_can_write(self):
1983
2520
        """Test that UDF class match Share.can_write() API."""
1984
 
        suggested_path = "suggested_path"
1985
 
        udf, volume = self._create_udf(uuid.uuid4(), 'udf_node_id',
1986
 
                                       '~/' + suggested_path, subscribed=False)
 
2521
        udf = self._create_udf(subscribed=False)
1987
2522
        self.assertTrue(udf.can_write())
1988
2523
 
1989
2524
    def test_udf_from_udf_volume(self):
1999
2534
 
2000
2535
    def test_share_from_share_volume(self):
2001
2536
        """Test for Share.from_share_volume."""
2002
 
        volume = volumes.ShareVolume(uuid.uuid4(), uuid.uuid4(), None, 10,
2003
 
                                     "to_me", u"share_name", u"other_username",
2004
 
                                     u"other_visible_name", True, 'Modify')
2005
 
        dir_name = get_share_path(volume.share_name,
2006
 
                                  volume.other_visible_name)
2007
 
        path = os.path.join(self.main.shares_dir, dir_name)
2008
 
        share = Share.from_share_volume(volume, path)
 
2537
        share = self._create_share()
2009
2538
        self.assertTrue(isinstance(share.id, basestring))
2010
2539
        self.assertTrue(isinstance(share.node_id, basestring))
2011
2540
 
2047
2576
    @defer.inlineCallbacks
2048
2577
    def test_no_UDFs_inside_udf(self):
2049
2578
        """Test that a UDF can't be created inside a UDF."""
2050
 
        udf, _ = self._create_udf(uuid.uuid4(), uuid.uuid4(),
2051
 
                               '~/a/b/c', subscribed=True)
 
2579
        udf = self._create_udf(subscribed=True)
2052
2580
        udf_child = os.path.join(udf.path, 'd')
2053
2581
        yield self.vm.add_udf(udf)
2054
2582
        # patch FakeAQ
2069
2597
    @defer.inlineCallbacks
2070
2598
    def test_no_UDFs_as_UDF_parent(self):
2071
2599
        """Test that a UDF can't be created if there is a UDF inside."""
2072
 
        udf, _ = self._create_udf(uuid.uuid4(), uuid.uuid4(),
2073
 
                               '~/a/b/c', subscribed=True)
 
2600
        udf = self._create_udf(subscribed=True)
2074
2601
        yield self.vm.add_udf(udf)
2075
2602
        udf_parent_path = os.path.dirname(udf.path)
2076
2603
        # patch FakeAQ
2096
2623
        user_conf = config.get_user_config()
2097
2624
        user_conf.set_udf_autosubscribe(True)
2098
2625
 
2099
 
        share_id = uuid.uuid4()
2100
 
        share_volume = volumes.ShareVolume(share_id, 'fake_share_uuid', None,
2101
 
                                           10, 'to_me', 'fake_share', 'username',
2102
 
                                           'visible_username', True, 'View')
 
2626
        share_volume = self._create_share_volume()
2103
2627
        udf_id = uuid.uuid4()
2104
2628
        udf_volume = volumes.UDFVolume(udf_id, 'udf_uuid', None, 10, u'~/UDF')
2105
2629
        root_volume = volumes.RootVolume(uuid.uuid4(), None, 10)
2128
2652
    @defer.inlineCallbacks
2129
2653
    def test_handle_SV_FREE_SPACE(self):
2130
2654
        """Test for VolumeManager.handle_SV_FREE_SPACE."""
2131
 
        # create a Share
2132
 
        share_id = uuid.uuid4()
2133
 
        share_volume = volumes.ShareVolume(share_id, 'fake_share_uuid', None,
2134
 
                                           None, 'to_me', 'fake_share', 'username',
2135
 
                                           'visible_username', True, 'View')
2136
 
        dir_name = get_share_path(share_volume.share_name,
2137
 
                                  share_volume.other_visible_name)
2138
 
        share_path = os.path.join(self.main.shares_dir, dir_name)
2139
 
        share = Share.from_share_volume(share_volume, share_path)
 
2655
        share = self._create_share(free_bytes=None)
2140
2656
        # get the root
2141
2657
        root = self.vm.get_volume(request.ROOT)
2142
2658
        self.vm._got_root('root_uuid')
2143
2659
        # create a UDF
2144
 
        udf_id = uuid.uuid4()
2145
 
        udf, volume = self._create_udf(udf_id, 'udf_node_id', '~/UDF')
2146
 
        self.vm.add_share(share)
 
2660
        udf = self._create_udf()
 
2661
        yield self.vm.add_share(share)
2147
2662
        yield self.vm.add_udf(udf)
2148
2663
        # override AQ.check_conditions
2149
2664
        d = defer.Deferred()
2172
2687
    @defer.inlineCallbacks
2173
2688
    def test_update_and_get_free_space(self):
2174
2689
        """Test for VolumeManager.update_free_space and get_free_space."""
2175
 
        share_id = uuid.uuid4()
2176
 
        share_volume = volumes.ShareVolume(share_id, 'fake_share_uuid', None,
2177
 
                                           None, 'to_me', 'fake_share', 'username',
2178
 
                                           'visible_username', True, 'View')
2179
 
        dir_name = get_share_path(share_volume.share_name,
2180
 
                                  share_volume.other_visible_name)
2181
 
        share_path = os.path.join(self.main.shares_dir, dir_name)
2182
 
        share = Share.from_share_volume(share_volume, share_path)
 
2690
        share = self._create_share(free_bytes=None)
2183
2691
        # get the root
2184
2692
        root = self.vm.get_volume(request.ROOT)
2185
2693
        self.vm._got_root('root_node_id')
2186
2694
        # create a UDF
2187
 
        udf_id = uuid.uuid4()
2188
 
        udf, volume = self._create_udf(udf_id, 'udf_node_id', '~/UDF')
2189
 
        self.vm.add_share(share)
 
2695
        udf = self._create_udf()
 
2696
        yield self.vm.add_share(share)
2190
2697
        yield self.vm.add_udf(udf)
2191
2698
        self.assertEquals(None, self.vm.get_free_space(share.volume_id))
2192
2699
        self.assertEquals(None, self.vm.get_free_space(udf.volume_id))
2271
2778
    @defer.inlineCallbacks
2272
2779
    def test_server_rescan(self):
2273
2780
        """Test the server_rescan method."""
2274
 
        share_id = uuid.uuid4()
2275
 
        share_volume = volumes.ShareVolume(share_id, 'fake_share_uuid', 1, 100,
2276
 
                                           'to_me', 'fake_share', 'username',
2277
 
                                           'visible_username', True, 'View')
 
2781
        share_volume = self._create_share_volume()
2278
2782
        udf_id = uuid.uuid4()
2279
2783
        udf_volume = volumes.UDFVolume(udf_id, 'udf_node_id', 1, 200, u'~/UDF')
2280
2784
        root_id = uuid.uuid4()
2285
2789
        self.main.action_q.query_volumes = lambda: defer.succeed(response)
2286
2790
        vol_rescan_d = defer.Deferred()
2287
2791
        self._listen_for('SV_VOLUME_NEW_GENERATION',
2288
 
                         vol_rescan_d.callback, 2, True)
2289
 
        server_rescan_d = defer.Deferred()
2290
 
        self._listen_for('SYS_SERVER_RESCAN_DONE', server_rescan_d.callback)
2291
 
        with environ('HOME', self.home_dir):
2292
 
            yield self.vm.server_rescan()
2293
 
        yield server_rescan_d
2294
 
        events = yield vol_rescan_d
2295
 
        events_dict = dict((event['volume_id'], event['generation'])
2296
 
                           for event in events)
2297
 
        self.assertIn(str(share_id), events_dict)
2298
 
        # new udfs server rescan is triggered after local rescan.
2299
 
        self.assertNotIn(str(udf_id), events_dict)
2300
 
        self.assertIn(request.ROOT, events_dict)
2301
 
        self.assertEquals(1, events_dict[str(share_id)])
2302
 
        self.assertEquals(1, events_dict[request.ROOT])
 
2792
                         vol_rescan_d.callback)  # autosubscribe is False
 
2793
        server_rescan_d = defer.Deferred()
 
2794
        self._listen_for('SYS_SERVER_RESCAN_DONE', server_rescan_d.callback)
 
2795
        with environ('HOME', self.home_dir):
 
2796
            yield self.vm.server_rescan()
 
2797
        yield server_rescan_d
 
2798
        events = yield vol_rescan_d
 
2799
 
 
2800
        self.assertEqual({'generation': 1, 'volume_id': ''}, events)
 
2801
 
 
2802
    @defer.inlineCallbacks
 
2803
    def test_server_rescan_with_share_autosubscribe(self):
 
2804
        """Test the server_rescan method."""
 
2805
        user_conf = config.get_user_config()
 
2806
        user_conf.set_share_autosubscribe(True)
 
2807
 
 
2808
        share_id = uuid.uuid4()
 
2809
        share_volume = self._create_share_volume(volume_id=share_id,
 
2810
                                                 generation=17)
 
2811
        udf_id = uuid.uuid4()
 
2812
        udf_volume = volumes.UDFVolume(udf_id, 'udf_node_id', 13, 200, u'~/UDF')
 
2813
        root_id = uuid.uuid4()
 
2814
        root_volume = volumes.RootVolume(root_id, 1, 500)
 
2815
        response = [share_volume, udf_volume, root_volume]
 
2816
 
 
2817
        # patch the fake action queue
 
2818
        self.main.action_q.query_volumes = lambda: defer.succeed(response)
 
2819
        self.patch(self.vm, '_scan_volume', lambda *a, **kw: defer.succeed(a))
 
2820
 
 
2821
        vol_rescan_d = defer.Deferred()
 
2822
        self._listen_for('SV_VOLUME_NEW_GENERATION',
 
2823
                         vol_rescan_d.callback, 2, collect=True)
 
2824
        server_rescan_d = defer.Deferred()
 
2825
        self._listen_for('SYS_SERVER_RESCAN_DONE', server_rescan_d.callback)
 
2826
        with environ('HOME', self.home_dir):
 
2827
            yield self.vm.server_rescan()
 
2828
 
 
2829
        yield server_rescan_d
 
2830
        events = yield vol_rescan_d
 
2831
 
 
2832
        expected_events = [{'generation': 17, 'volume_id': str(share_id)},
 
2833
                           {'generation': 1, 'volume_id': ''}]
 
2834
        self.assertEqual(expected_events, events)
 
2835
 
 
2836
    @defer.inlineCallbacks
 
2837
    def test_server_rescan_with_udf_autosubscribe(self):
 
2838
        """Test the server_rescan method."""
 
2839
        user_conf = config.get_user_config()
 
2840
        user_conf.set_udf_autosubscribe(True)
 
2841
 
 
2842
        share_volume = self._create_share_volume()
 
2843
        udf_id = uuid.uuid4()
 
2844
        udf_volume = volumes.UDFVolume(udf_id, 'udf_node_id', 13, 200, u'~/UDF')
 
2845
        root_id = uuid.uuid4()
 
2846
        root_volume = volumes.RootVolume(root_id, 1, 500)
 
2847
        response = [share_volume, udf_volume, root_volume]
 
2848
 
 
2849
        # patch the fake action queue
 
2850
        self.main.action_q.query_volumes = lambda: defer.succeed(response)
 
2851
 
 
2852
        self.patch(self.vm, '_scan_volume', defer.succeed)
 
2853
 
 
2854
        vol_rescan_d = defer.Deferred()
 
2855
        self._listen_for('SV_VOLUME_NEW_GENERATION',
 
2856
                         vol_rescan_d.callback, 2, collect=True)
 
2857
        server_rescan_d = defer.Deferred()
 
2858
        self._listen_for('SYS_SERVER_RESCAN_DONE', server_rescan_d.callback)
 
2859
        with environ('HOME', self.home_dir):
 
2860
            yield self.vm.server_rescan()
 
2861
 
 
2862
        yield server_rescan_d
 
2863
        events = yield vol_rescan_d
 
2864
 
 
2865
        expected_events = [{'generation': 13, 'volume_id': str(udf_id)},
 
2866
                           {'generation': 1, 'volume_id': ''}]
 
2867
        self.assertEqual(expected_events, events)
 
2868
 
 
2869
    @defer.inlineCallbacks
 
2870
    def test_server_rescan_with_autosubscribe(self):
 
2871
        """Test the server_rescan method."""
 
2872
        user_conf = config.get_user_config()
 
2873
        user_conf.set_udf_autosubscribe(True)
 
2874
        user_conf.set_share_autosubscribe(True)
 
2875
 
 
2876
        share_id = uuid.uuid4()
 
2877
        share_volume = self._create_share_volume(volume_id=share_id,
 
2878
                                                 generation=17)
 
2879
        udf_id = uuid.uuid4()
 
2880
        udf_volume = volumes.UDFVolume(udf_id, 'udf_node_id', 13, 200, u'~/UDF')
 
2881
        root_id = uuid.uuid4()
 
2882
        root_volume = volumes.RootVolume(root_id, 1, 500)
 
2883
        response = [share_volume, udf_volume, root_volume]
 
2884
 
 
2885
        # patch the fake action queue
 
2886
        self.main.action_q.query_volumes = lambda: defer.succeed(response)
 
2887
        self.patch(self.vm, '_scan_volume', lambda *a, **kw: defer.succeed(a))
 
2888
 
 
2889
        vol_rescan_d = defer.Deferred()
 
2890
        self._listen_for('SV_VOLUME_NEW_GENERATION',
 
2891
                         vol_rescan_d.callback, 3, collect=True)
 
2892
        server_rescan_d = defer.Deferred()
 
2893
        self._listen_for('SYS_SERVER_RESCAN_DONE', server_rescan_d.callback)
 
2894
        with environ('HOME', self.home_dir):
 
2895
            yield self.vm.server_rescan()
 
2896
 
 
2897
        yield server_rescan_d
 
2898
        events = yield vol_rescan_d
 
2899
 
 
2900
        expected_events = [{'generation': 17, 'volume_id': str(share_id)},
 
2901
                           {'generation': 13, 'volume_id': str(udf_id)},
 
2902
                           {'generation': 1, 'volume_id': ''}]
 
2903
        self.assertEqual(expected_events, events)
2303
2904
 
2304
2905
    @defer.inlineCallbacks
2305
2906
    def test_server_rescan_error(self):
2347
2948
        # the UDF part makes sense if UDF autosubscribe is True
2348
2949
        user_conf = config.get_user_config()
2349
2950
        user_conf.set_udf_autosubscribe(True)
2350
 
        share_id = uuid.uuid4()
2351
 
        share_volume = volumes.ShareVolume(share_id, 'fake_share_uuid', 1, 100,
2352
 
                                           'to_me', 'fake_share', 'username',
2353
 
                                           'visible_username', True, 'View')
 
2951
        share_volume = self._create_share_volume()
2354
2952
        udf_id = uuid.uuid4()
2355
2953
        udf_volume = volumes.UDFVolume(udf_id, 'udf_node_id', 1, 200, u'~/UDF')
2356
2954
        root_id = uuid.uuid4()
2384
2982
        self.assertEquals(0, len(self.vm.udfs))
2385
2983
        self.assertEquals(2, len(self.vm.shares))
2386
2984
 
2387
 
 
2388
2985
    @defer.inlineCallbacks
2389
2986
    def test_server_rescan_clean_dead_shares(self):
2390
2987
        """Test cleanup of dead volumes after server_rescan method."""
2391
2988
        # the UDF part makes sense if UDF autosubscribe is True
2392
2989
        user_conf = config.get_user_config()
2393
2990
        user_conf.set_udf_autosubscribe(True)
2394
 
        share_id = uuid.uuid4()
2395
 
        share_volume = volumes.ShareVolume(share_id, 'fake_share_uuid', 1, 100,
2396
 
                                           'to_me', 'fake_share', 'username',
2397
 
                                           'visible_username', True, 'View')
 
2991
        share_volume = self._create_share_volume()
2398
2992
        udf_id = uuid.uuid4()
2399
2993
        udf_volume = volumes.UDFVolume(udf_id, 'udf_node_id', 1, 200, u'~/UDF')
2400
2994
        root_id = uuid.uuid4()
2402
2996
        response = [share_volume, udf_volume, root_volume]
2403
2997
        # patch fake action queue
2404
2998
        self.main.action_q.query_volumes = lambda: defer.succeed(response)
 
2999
        self.patch(self.main.lr, 'scan_dir', lambda *a, **kw: defer.succeed(a))
 
3000
        self.patch(self.main.action_q, 'rescan_from_scratch', defer.succeed)
2405
3001
        server_rescan_d = defer.Deferred()
2406
3002
        self._listen_for('SYS_SERVER_RESCAN_DONE', server_rescan_d.callback)
 
3003
        udf_created_d = defer.Deferred()
 
3004
        # wait for the VM_UDF_CREATED event in order to properly shutdown
 
3005
        # (local rescan/udf scan is running)
 
3006
        self._listen_for('VM_UDF_CREATED', udf_created_d.callback)
2407
3007
        with environ('HOME', self.home_dir):
2408
3008
            yield self.vm.server_rescan()
2409
3009
        yield server_rescan_d
 
3010
        yield udf_created_d
2410
3011
        self.assertIn(request.ROOT, self.vm.shares)
2411
3012
        self.assertIn(str(udf_volume.volume_id), self.vm.udfs)
2412
3013
        self.assertEquals(1, len(self.vm.udfs))
2429
3030
        # the UDF part makes sense if UDF autosubscribe is True
2430
3031
        user_conf = config.get_user_config()
2431
3032
        user_conf.set_udf_autosubscribe(True)
 
3033
        user_conf.set_share_autosubscribe(True)
2432
3034
 
2433
3035
        share_id = uuid.uuid4()
2434
 
        share_volume = volumes.ShareVolume(share_id, 'fake_share_uuid', 1, 100,
2435
 
                                           'to_me', 'fake_share', 'username',
2436
 
                                           'visible_username', True, 'View')
 
3036
        share_volume = self._create_share_volume(volume_id=share_id, generation=1)
2437
3037
        udf_id = uuid.uuid4()
2438
3038
        udf_volume = volumes.UDFVolume(udf_id, 'udf_node_id', 1, 200, u'~/UDF')
2439
3039
        root_id = uuid.uuid4()
2548
3148
    @defer.inlineCallbacks
2549
3149
    def test_volumes_rescan_cb_inactive_volume(self):
2550
3150
        """Test _volumes_rescan_cb with inactive volume."""
 
3151
        suggested_path = u'~/ñoño/ñandú'
 
3152
        with environ('HOME', self.home_dir):
 
3153
            path = get_udf_path(suggested_path)
2551
3154
        udf_id = uuid.uuid4()
2552
 
        udf, udf_volume = self._create_udf(udf_id, uuid.uuid4(), '~/UDF')
2553
 
        udf_volume.generation = 10
 
3155
        udf_volume = volumes.UDFVolume(udf_id, uuid.uuid4(), 10, 100,
 
3156
                                       suggested_path)
 
3157
        udf = UDF.from_udf_volume(udf_volume, path)
2554
3158
        root_id = uuid.uuid4()
2555
3159
        root_volume = volumes.RootVolume(root_id, 1, 500)
2556
3160
        response = [udf_volume, root_volume]
2558
3162
        # unsubscribe the udf
2559
3163
        self.vm.unsubscribe_udf(udf.volume_id)
2560
3164
        d = defer.Deferred()
2561
 
        self._listen_for('SV_VOLUME_NEW_GENERATION', d.callback, 1)
 
3165
        self._listen_for('SV_VOLUME_NEW_GENERATION', d.callback)
2562
3166
        with environ('HOME', self.home_dir):
2563
3167
            self.vm._volumes_rescan_cb(response)
2564
3168
        event = yield d
2574
3178
        user_conf = config.get_user_config()
2575
3179
        user_conf.set_udf_autosubscribe(True)
2576
3180
 
 
3181
        # create a UDF
 
3182
        suggested_path = u'~/ñoño/ñandú'
 
3183
        with environ('HOME', self.home_dir):
 
3184
            path = get_udf_path(suggested_path)
2577
3185
        udf_id = uuid.uuid4()
2578
 
        udf, udf_volume = self._create_udf(udf_id, uuid.uuid4(), '~/UDF')
2579
 
        udf_volume.generation = 10
 
3186
        udf_volume = volumes.UDFVolume(udf_id, 'udf_uuid', 10, 100,
 
3187
                                       suggested_path)
 
3188
        udf = UDF.from_udf_volume(udf_volume, path)
 
3189
        udf.subscribed = True
 
3190
 
2580
3191
        root_id = uuid.uuid4()
2581
3192
        root_volume = volumes.RootVolume(root_id, 1, 500)
2582
3193
        response = [udf_volume, root_volume]
2585
3196
        self.main.fs.delete_metadata(udf.path)
2586
3197
        d = defer.Deferred()
2587
3198
        self._listen_for('SV_VOLUME_NEW_GENERATION', d.callback, 2, collect=True)
 
3199
        self.patch(self.vm, '_scan_volume', defer.succeed)
2588
3200
        with environ('HOME', self.home_dir):
2589
3201
            self.vm._volumes_rescan_cb(response)
2590
3202
        events = yield d
2602
3214
    @defer.inlineCallbacks
2603
3215
    def test_volumes_rescan_cb_active_udf(self):
2604
3216
        """Test _volumes_rescan_cb with an active UDF and no-autosubscribe."""
 
3217
        # create a UDF
 
3218
        suggested_path = u'~/ñoño/ñandú'
 
3219
        with environ('HOME', self.home_dir):
 
3220
            path = get_udf_path(suggested_path)
2605
3221
        udf_id = uuid.uuid4()
2606
 
        udf, udf_volume = self._create_udf(udf_id, uuid.uuid4(), '~/UDF')
2607
 
        udf_volume.generation = 10
 
3222
        udf_volume = volumes.UDFVolume(udf_id, 'udf_uuid', None, 10,
 
3223
                                       suggested_path)
 
3224
        udf = UDF.from_udf_volume(udf_volume, path)
 
3225
 
2608
3226
        root_id = uuid.uuid4()
2609
3227
        root_volume = volumes.RootVolume(root_id, 1, 500)
2610
3228
        response = [udf_volume, root_volume]
2621
3239
    @defer.inlineCallbacks
2622
3240
    def test_update_generation(self):
2623
3241
        """Test for the update_generation method."""
2624
 
        share_id = uuid.uuid4()
2625
 
        share_volume = volumes.ShareVolume(share_id, 'fake_share_uuid', None,
2626
 
                                           10, 'to_me', 'fake_share', 'username',
2627
 
                                           'visible_username', True, 'View')
2628
 
        dir_name = get_share_path(share_volume.share_name,
2629
 
                                  share_volume.other_visible_name)
2630
 
        share_path = os.path.join(self.main.shares_dir, dir_name)
2631
 
        share = Share.from_share_volume(share_volume, share_path)
 
3242
        share = self._create_share()
2632
3243
        # get the root
2633
3244
        root = self.vm.get_volume(request.ROOT)
2634
3245
        self.vm._got_root('root_node_id')
2635
3246
        # create a UDF
2636
 
        udf_id = uuid.uuid4()
2637
 
        udf, _ = self._create_udf(udf_id, 'udf_node_id', '~/UDF')
2638
 
        self.vm.add_share(share)
 
3247
        udf = self._create_udf()
 
3248
        yield self.vm.add_share(share)
2639
3249
        yield self.vm.add_udf(udf)
2640
3250
        self.assertEqual(None, udf.generation)
2641
3251
        self.assertEqual(None, share.generation)
2657
3267
    def test_handle_SV_VOLUME_NEW_GENERATION_udf(self):
2658
3268
        """Test handle_SV_VOLUME_NEW_GENERATION for udf."""
2659
3269
        # create a UDF
2660
 
        udf_id = uuid.uuid4()
2661
 
        udf, udf_volume = self._create_udf(udf_id, 'udf_node_id', '~/UDF')
 
3270
        udf = self._create_udf()
2662
3271
        yield self.vm.add_udf(udf)
2663
3272
        self.vm.update_generation(udf.volume_id, 10)
2664
3273
        d = defer.Deferred()
2674
3283
    def test_handle_SV_VOLUME_NEW_GENERATION_udf_from_scratch(self):
2675
3284
        """Test handle_SV_VOLUME_NEW_GENERATION for udf."""
2676
3285
        # create a UDF
2677
 
        udf_id = uuid.uuid4()
2678
 
        udf, udf_volume = self._create_udf(udf_id, 'udf_node_id', '~/UDF')
 
3286
        udf = self._create_udf()
2679
3287
        yield self.vm.add_udf(udf)
2680
3288
        self.vm.update_generation(udf.volume_id, None)
2681
3289
        d = defer.Deferred()
2689
3297
    def test_handle_SV_VOLUME_NEW_GENERATION_udf_eq(self):
2690
3298
        """Test handle_SV_VOLUME_NEW_GENERATION for udf."""
2691
3299
        # get the root
2692
 
        udf_id = uuid.uuid4()
2693
 
        udf, udf_volume = self._create_udf(udf_id, 'udf_node_id', '~/UDF')
 
3300
        udf = self._create_udf()
2694
3301
        yield self.vm.add_udf(udf)
2695
3302
        self.vm.update_generation(udf.volume_id, 100)
2696
3303
        self.main.event_q.push('SV_VOLUME_NEW_GENERATION',
2697
3304
                               volume_id=udf.volume_id, generation=100)
2698
 
        self.assertEqual(1, len(self.handler.records))
2699
 
        msg = 'Got SV_VOLUME_NEW_GENERATION(%r, %r) but volume' + \
2700
 
                ' is at generation: %r'
2701
 
        self.assertEqual(msg % (udf.volume_id, 100, 100),
2702
 
                         self.handler.records[0].message)
 
3305
        msg = ('Got SV_VOLUME_NEW_GENERATION(%r, %r) but volume'
 
3306
               ' is at generation: %r') % (udf.volume_id, 100, 100)
 
3307
        self.assertTrue(self.handler.check_info(msg))
 
3308
 
 
3309
    @defer.inlineCallbacks
 
3310
    def test_handle_SV_VOLUME_NEW_GENERATION_udf_inactive(self):
 
3311
        """Test handle_SV_VOLUME_NEW_GENERATION for an inactive udf."""
 
3312
        udf = self._create_udf(subscribed=False)
 
3313
        yield self.vm.add_udf(udf)
 
3314
 
 
3315
        gen = 10
 
3316
        self.vm.update_generation(udf.volume_id, gen)
 
3317
 
 
3318
        self.patch(self.main.action_q, 'get_delta', lambda *a: defer.fail(a))
 
3319
        self.main.event_q.push('SV_VOLUME_NEW_GENERATION',
 
3320
                               volume_id=udf.volume_id, generation=100)
 
3321
 
 
3322
        self.assertEqual(gen, self.vm.get_volume(udf.volume_id).generation)
 
3323
        msgs = ('SV_VOLUME_NEW_GENERATION', udf.volume_id, 'not active')
 
3324
        self.assertTrue(self.handler.check_info(*msgs), 'logging was made')
2703
3325
 
2704
3326
    @defer.inlineCallbacks
2705
3327
    def test_handle_SV_VOLUME_NEW_GENERATION_root(self):
2748
3370
    @defer.inlineCallbacks
2749
3371
    def test_handle_SV_VOLUME_NEW_GENERATION_share(self):
2750
3372
        """Test handle_SV_VOLUME_NEW_GENERATION for a share."""
2751
 
        share_id = uuid.uuid4()
2752
 
        share_volume = volumes.ShareVolume(share_id, 'fake_share_uuid', None,
2753
 
                                           10, 'to_me', 'fake_share', 'username',
2754
 
                                           'visible_username', True, 'View')
2755
 
        dir_name = get_share_path(share_volume.share_name,
2756
 
                                  share_volume.other_visible_name)
2757
 
        share_path = os.path.join(self.main.shares_dir, dir_name)
2758
 
        share = Share.from_share_volume(share_volume, share_path)
2759
 
        self.vm.add_share(share)
 
3373
        share = self._create_share(subscribed=True)
 
3374
        yield self.vm.add_share(share)
2760
3375
        self.vm.update_generation(share.volume_id, 10)
2761
3376
        d = defer.Deferred()
2762
3377
        self.patch(self.main.action_q, 'get_delta', lambda v, g: d.callback((v, g)))
2770
3385
    @defer.inlineCallbacks
2771
3386
    def test_handle_SV_VOLUME_NEW_GENERATION_share_from_scratch(self):
2772
3387
        """Test handle_SV_VOLUME_NEW_GENERATION for a share."""
2773
 
        share_id = uuid.uuid4()
2774
 
        share_volume = volumes.ShareVolume(share_id, 'fake_share_uuid', None,
2775
 
                                           10, 'to_me', 'fake_share', 'username',
2776
 
                                           'visible_username', True, 'View')
2777
 
        dir_name = get_share_path(share_volume.share_name,
2778
 
                                  share_volume.other_visible_name)
2779
 
        share_path = os.path.join(self.main.shares_dir, dir_name)
2780
 
        share = Share.from_share_volume(share_volume, share_path)
2781
 
        self.vm.add_share(share)
 
3388
        share = self._create_share(subscribed=True)
 
3389
        yield self.vm.add_share(share)
2782
3390
        self.vm.update_generation(share.volume_id, None)
2783
3391
        d = defer.Deferred()
2784
3392
        self.patch(self.main.action_q, 'rescan_from_scratch', d.callback)
2789
3397
 
2790
3398
    def test_handle_SV_VOLUME_NEW_GENERATION_share_eq(self):
2791
3399
        """Test handle_SV_VOLUME_NEW_GENERATION for a share."""
2792
 
        share_id = uuid.uuid4()
2793
 
        share_volume = volumes.ShareVolume(share_id, 'fake_share_uuid', None,
2794
 
                                           10, 'to_me', 'fake_share', 'username',
2795
 
                                           'visible_username', True, 'View')
2796
 
        dir_name = get_share_path(share_volume.share_name,
2797
 
                                  share_volume.other_visible_name)
2798
 
        share_path = os.path.join(self.main.shares_dir, dir_name)
2799
 
        share = Share.from_share_volume(share_volume, share_path)
2800
 
        self.vm.add_share(share)
 
3400
        share = self._create_share(subscribed=True)
 
3401
        yield self.vm.add_share(share)
2801
3402
        self.vm.update_generation(share.volume_id, 100)
2802
3403
        self.main.event_q.push('SV_VOLUME_NEW_GENERATION',
2803
3404
                               volume_id=share.volume_id, generation=100)
2805
3406
                        'Got SV_VOLUME_NEW_GENERATION(%r, %r) but volume '
2806
3407
                        'is at generation: %r' % (share.volume_id, 100, 100)))
2807
3408
 
 
3409
    @defer.inlineCallbacks
 
3410
    def test_handle_SV_VOLUME_NEW_GENERATION_share_inactive(self):
 
3411
        """Test handle_SV_VOLUME_NEW_GENERATION for an inactive share."""
 
3412
        share = self._create_share(subscribed=False)
 
3413
        yield self.vm.add_share(share)
 
3414
 
 
3415
        gen = 10
 
3416
        self.vm.update_generation(share.volume_id, gen)
 
3417
 
 
3418
        self.patch(self.main.action_q, 'get_delta', lambda *a: defer.fail(a))
 
3419
        self.main.event_q.push('SV_VOLUME_NEW_GENERATION',
 
3420
                               volume_id=share.volume_id, generation=100)
 
3421
 
 
3422
        self.assertEqual(gen, self.vm.get_volume(share.volume_id).generation)
 
3423
        msgs = ('SV_VOLUME_NEW_GENERATION', share.volume_id, 'not active')
 
3424
        self.assertTrue(self.handler.check_info(*msgs), 'logging was made')
 
3425
 
2808
3426
    def test_handle_SV_VOLUME_NEW_GENERATION_no_volume(self):
2809
3427
        """Test handle_SV_VOLUME_NEW_GENERATION for a volume we don't have."""
2810
3428
        called = []
2817
3435
    def test_handle_AQ_DELTA_NOT_POSSIBLE(self):
2818
3436
        """Test for handle_AQ_DELTA_NOT_POSSIBLE."""
2819
3437
        share_id = uuid.uuid4()
2820
 
        share_volume = volumes.ShareVolume(share_id, 'fake_share_uuid', None,
2821
 
                                           10, 'to_me', 'fake_share', 'username',
2822
 
                                           'visible_username', True, 'View')
2823
 
        dir_name = get_share_path(share_volume.share_name,
2824
 
                                  share_volume.other_visible_name)
2825
 
        share_path = os.path.join(self.main.shares_dir, dir_name)
2826
 
        share = Share.from_share_volume(share_volume, share_path)
 
3438
        share = self._create_share(volume_id=share_id)
2827
3439
        # get the root
2828
3440
        root = self.vm.get_volume(request.ROOT)
2829
3441
        self.vm._got_root('root_node_id')
2830
3442
        # create a UDF
2831
3443
        udf_id = uuid.uuid4()
2832
 
        udf, _ = self._create_udf(udf_id, 'udf_node_id', '~/UDF')
2833
 
        self.vm.add_share(share)
 
3444
        udf = self._create_udf(volume_id=udf_id)
 
3445
        yield self.vm.add_share(share)
2834
3446
        yield self.vm.add_udf(udf)
2835
3447
        # patch AQ.rescan_from_scratch
2836
3448
        calls = []
2856
3468
 
2857
3469
        This tests the case of a receiving shared directory inside a UDF.
2858
3470
        """
2859
 
        udf_id = uuid.uuid4()
2860
 
        udf, _ = self._create_udf(udf_id, str(uuid.uuid4()), '~/UDF')
 
3471
        udf = self._create_udf()
2861
3472
        yield self.vm.add_udf(udf)
2862
3473
        share_id = uuid.uuid4()
2863
3474
        share_response = ShareResponse.from_params(