~didrocks/ubuntuone-client/use_result_var

« back to all changes in this revision

Viewing changes to tests/status/test_aggregator.py

  • Committer: Bazaar Package Importer
  • Author(s): Rodney Dawes
  • Date: 2011-02-23 18:34:09 UTC
  • mfrom: (1.1.45 upstream)
  • Revision ID: james.westby@ubuntu.com-20110223183409-535o7yo165wbjmca
Tags: 1.5.5-0ubuntu1
* New upstream release.
  - Subscribing to a RO share will not download content (LP: #712528)
  - Can't synchronize "~/Ubuntu One Music" (LP: #714976)
  - Syncdaemon needs to show progress in Unity launcher (LP: #702116)
  - Notifications say "your cloud" (LP: #715887)
  - No longer requires python-libproxy
  - Recommend unity and indicator libs by default

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 
20
20
import logging
21
21
 
 
22
from twisted.internet import defer
22
23
from twisted.internet.task import Clock
23
24
from twisted.trial.unittest import TestCase
24
25
 
 
26
from contrib.testing.testcase import BaseTwistedTestCase
25
27
from ubuntuone.devtools.handlers import MementoHandler
26
28
from ubuntuone.status import aggregator
27
29
from ubuntuone.status.notification import AbstractNotification
34
36
    """Patch the clock to fix twisted bug #4823."""
35
37
 
36
38
    def advance(self, amount):
 
39
        """Sort the calls before advancing the clock."""
37
40
        self.calls.sort(lambda a, b: cmp(a.getTime(), b.getTime()))
38
41
        Clock.advance(self, amount)
39
42
 
131
134
    def __init__(self, application_name="fake app"):
132
135
        """Initialize this instance."""
133
136
        self.notifications_shown = []
 
137
        self.notification_switch = None
134
138
        self.application_name = application_name
135
139
 
136
140
    def send_notification(self, title, message, icon=None, append=False):
137
141
        """Show a notification to the user."""
 
142
        if (self.notification_switch is not None
 
143
            and not self.notification_switch.enabled):
 
144
            return
138
145
        self.notifications_shown.append((title, message, icon, append))
139
146
        return len(self.notifications_shown) - 1
140
147
 
141
 
    def update_notification(self, notification, new_title, new_message,
 
148
    def update_notification(self, notification_id, new_title, new_message,
142
149
                            new_icon=None):
143
150
        """Update the notification with a new message body."""
 
151
        if (self.notification_switch is not None
 
152
            and not self.notification_switch.enabled):
 
153
            return
 
154
        if notification_id is None:
 
155
            return
144
156
        title, old_message, icon, append = self.notifications_shown[
145
 
            notification]
 
157
            notification_id]
146
158
        if new_icon is not None:
147
159
            icon = new_icon
148
160
        # we store it as a new notification, to ease testing
154
166
    """Builds a notification singleton, that logs all notifications shown."""
155
167
    instance = FakeNotification()
156
168
 
157
 
    def get_instance():
 
169
    def get_instance(notification_switch):
158
170
        """Returns the single instance."""
 
171
        instance.notification_switch = notification_switch
159
172
        return instance
160
173
 
161
174
    return get_instance
191
204
        self.discovered = 0
192
205
        self.completed = 0
193
206
        self.restart_progress_bubble_called = False
 
207
        self.notification_switch = aggregator.NotificationSwitch()
194
208
 
195
209
    def get_discovery_message(self):
196
210
        """Return the file discovery message."""
219
233
        """Reset the progress bubble."""
220
234
        self.restart_progress_bubble_called = True
221
235
 
 
236
    def build_notification(self):
 
237
        """Create a new toggleable notification object."""
 
238
        return self.notification_switch.build_notification()
 
239
 
 
240
 
 
241
class ToggleableNotificationTestCase(TestCase):
 
242
    """Test the ToggleableNotification class."""
 
243
 
 
244
    def setUp(self):
 
245
        """Initialize this test instance."""
 
246
        self.patch(aggregator, "Notification", FakeNotification)
 
247
        self.notification_switch = aggregator.NotificationSwitch()
 
248
        self.toggleable = self.notification_switch.build_notification()
 
249
 
 
250
    def assertShown(self, notification):
 
251
        """Assert that the notification was shown."""
 
252
        self.assertIn(notification,
 
253
                      self.toggleable.notification.notifications_shown)
 
254
 
 
255
    def assertNotShown(self, notification):
 
256
        """Assert that the notification was shown."""
 
257
        self.assertNotIn(notification,
 
258
                         self.toggleable.notification.notifications_shown)
 
259
 
 
260
    def test_send_notification_passes_thru(self):
 
261
        """The send_notification method passes thru."""
 
262
        args = (1, 2, 3, 4)
 
263
        self.toggleable.send_notification(*args)
 
264
        self.assertShown(args)
 
265
 
 
266
    def test_update_notification_passes_thru(self):
 
267
        """The update_notification method passes thru."""
 
268
        show_args = ("title", "body", "icon", "append")
 
269
        update_args = ("other title", "other body")
 
270
        expected = update_args + show_args[2:]
 
271
        notification_id = self.toggleable.send_notification(*show_args)
 
272
        self.toggleable.update_notification(notification_id, *update_args)
 
273
        self.assertShown(expected)
 
274
 
 
275
    def test_send_notification_honored_when_enabled(self):
 
276
        """The send_notification method is honored when enabled."""
 
277
        self.notification_switch.enable_notifications()
 
278
        args = (aggregator.UBUNTUONE_TITLE, "hello", None, False)
 
279
        self.toggleable.send_notification(*args)
 
280
        self.assertShown(args)
 
281
 
 
282
    def test_send_notification_ignored_when_disabled(self):
 
283
        """The send_notification method is ignored when disabled."""
 
284
        self.notification_switch.disable_notifications()
 
285
        args = (aggregator.UBUNTUONE_TITLE, "hello", None, False)
 
286
        self.toggleable.send_notification(*args)
 
287
        self.assertNotShown(args)
 
288
 
 
289
    def test_update_notification_honored_when_enabled(self):
 
290
        """The update_notification method is honored when enabled."""
 
291
        self.notification_switch.enable_notifications()
 
292
        show_args = ("title", "body", "icon", "append")
 
293
        update_args = ("other title", "other body")
 
294
        expected = update_args + show_args[2:]
 
295
        notification_id = self.toggleable.send_notification(*show_args)
 
296
        self.toggleable.update_notification(notification_id, *update_args)
 
297
        self.assertShown(expected)
 
298
 
 
299
    def test_update_notification_ignored_when_disabled(self):
 
300
        """The update_notification method is ignored when disabled."""
 
301
        self.notification_switch.disable_notifications()
 
302
        show_args = ("title", "body", "icon", "append")
 
303
        update_args = ("other title", "other body")
 
304
        expected = update_args + show_args[2:]
 
305
        notification_id = self.toggleable.send_notification(*show_args)
 
306
        self.toggleable.update_notification(notification_id, *update_args)
 
307
        self.assertNotShown(expected)
 
308
 
 
309
    def test_update_after_disabled_show(self):
 
310
        """An update is ignored if the corresponding show was disabled."""
 
311
        self.notification_switch.disable_notifications()
 
312
        show_args = ("title", "body", "icon", "append")
 
313
        update_args = ("other title", "other body")
 
314
        expected = update_args + show_args[2:]
 
315
        notification_id = self.toggleable.send_notification(*show_args)
 
316
        self.notification_switch.enable_notifications()
 
317
        self.toggleable.update_notification(notification_id, *update_args)
 
318
        self.assertNotShown(expected)
 
319
 
 
320
 
 
321
class NotificationSwitchTestCase(TestCase):
 
322
    """Test the NotificationSwitch class."""
 
323
 
 
324
    def setUp(self):
 
325
        """Initialize this test instance."""
 
326
        self.notification_switch = aggregator.NotificationSwitch()
 
327
 
 
328
    def test_build_notification(self):
 
329
        """A new notification instance is returned."""
 
330
        notification = self.notification_switch.build_notification()
 
331
        self.assertEqual(notification.notification_switch,
 
332
                         self.notification_switch)
 
333
 
 
334
    def test_enable_notifications(self):
 
335
        """The switch is turned on."""
 
336
        self.notification_switch.enable_notifications()
 
337
        self.assertTrue(self.notification_switch.enabled)
 
338
 
 
339
    def test_disable_notifications(self):
 
340
        """The switch is turned off."""
 
341
        self.notification_switch.disable_notifications()
 
342
        self.assertFalse(self.notification_switch.enabled)
 
343
 
222
344
 
223
345
class FileDiscoveryBubbleTestCase(TestCase):
224
346
    """Test the FileDiscoveryBubble class."""
225
347
 
226
348
    def setUp(self):
227
349
        """Initialize this test instance."""
228
 
        self.patch(aggregator, "Notification", FakeNotificationSingleton())
 
350
        self.patch(aggregator, "ToggleableNotification",
 
351
                   FakeNotificationSingleton())
229
352
        self.clock = PatchedClock()
230
353
        self.aggregator = FakeStatusAggregator(clock=self.clock)
231
354
        self.bubble = aggregator.FileDiscoveryBubble(self.aggregator,
383
506
 
384
507
    def setUp(self):
385
508
        """Initialize this test instance."""
386
 
        self.patch(aggregator, "Notification", FakeNotificationSingleton())
 
509
        self.patch(aggregator, "ToggleableNotification",
 
510
                   FakeNotificationSingleton())
387
511
        self.clock = PatchedClock()
388
512
        self.aggregator = FakeStatusAggregator(clock=self.clock)
389
513
        self.bubble = aggregator.ProgressBubble(self.aggregator,
467
591
 
468
592
    def setUp(self):
469
593
        """Initialize this test instance."""
470
 
        self.patch(aggregator, "Notification", FakeNotificationSingleton())
 
594
        self.patch(aggregator, "ToggleableNotification",
 
595
                   FakeNotificationSingleton())
471
596
        self.clock = PatchedClock()
472
597
        self.aggregator = FakeStatusAggregator(clock=self.clock)
473
598
        self.bubble = aggregator.FinalStatusBubble(self.aggregator)
483
608
        self.assertEqual(1, len(self.bubble.notification.notifications_shown))
484
609
 
485
610
 
 
611
class FakeLauncher(object):
 
612
    """A fake UbuntuOneLauncher."""
 
613
 
 
614
    progress_visible = False
 
615
    progress = 0.0
 
616
    emblem_visible = False
 
617
    emblem = None
 
618
 
 
619
    def show_progressbar(self):
 
620
        """The progressbar is shown."""
 
621
        self.progress_visible = True
 
622
 
 
623
    def hide_progressbar(self):
 
624
        """The progressbar is hidden."""
 
625
        self.progress_visible = False
 
626
 
 
627
    def set_progress(self, value):
 
628
        """The progressbar value is changed."""
 
629
        self.progress = value
 
630
 
 
631
    def show_warning_emblem(self):
 
632
        """Show a warning emblem."""
 
633
        self.emblem_visible = True
 
634
 
 
635
    def hide_emblem(self):
 
636
        """Hide the current emblem."""
 
637
        self.emblem_visible = False
 
638
 
 
639
 
 
640
class FakeInhibitor(object):
 
641
    """A fake session inhibitor."""
 
642
 
 
643
    def inhibit(self, flags, reason):
 
644
        """Inhibit some events with a given reason."""
 
645
        self.flags = flags
 
646
        return defer.succeed(self)
 
647
 
 
648
    def cancel(self):
 
649
        """Cancel the inhibition for the current cookie."""
 
650
        self.flags = 0
 
651
        return defer.succeed(self)
 
652
 
 
653
 
486
654
class ProgressBarTestCase(TestCase):
487
655
    """Tests for the progress bar."""
488
656
 
489
657
    def setUp(self):
490
658
        """Initialize this test instance."""
 
659
        self.patch(aggregator, "UbuntuOneLauncher", FakeLauncher)
 
660
        self.patch(aggregator.session, "Inhibitor", FakeInhibitor)
491
661
        self.clock = PatchedClock()
492
662
        self.bar = aggregator.ProgressBar(clock=self.clock)
493
663
        self.addCleanup(self.bar.cleanup)
496
666
 
497
667
        def fake_timeout(result):
498
668
            """A fake _timeout method."""
499
 
            self.timeout_calls.append(self.bar.percentage)
 
669
            self.timeout_calls.append(self.bar.progress)
500
670
            original_timeout(result)
501
671
 
502
672
        self.patch(self.bar, "_timeout", fake_timeout)
505
675
        """The progress bar is shown when progress is made."""
506
676
        self.bar.progress_made(50, 100)
507
677
        self.assertTrue(self.bar.visible)
 
678
        self.assertTrue(self.bar.launcher.progress_visible)
508
679
 
509
680
    def test_progress_made_updates_counter(self):
510
681
        """Progress made updates the counter."""
511
682
        self.bar.progress_made(50, 100)
512
 
        self.assertEqual(self.bar.percentage, 50.0)
 
683
        self.assertEqual(self.bar.progress, 0.5)
513
684
 
514
685
    def test_no_timer_set_initially(self):
515
686
        """There's no timer set initially."""
520
691
        self.bar.progress_made(50, 100)
521
692
        self.assertNotEqual(self.bar.timer, None)
522
693
 
 
694
    def test_cleanup_resets_timer(self):
 
695
        """The cleanup method resets the timer."""
 
696
        self.bar.progress_made(50, 100)
 
697
        self.bar.cleanup()
 
698
        self.assertEqual(self.bar.timer, None)
 
699
 
523
700
    def test_progress_made_not_updated_initially(self):
524
701
        """Progress made is not updated initially."""
525
702
        self.bar.progress_made(50, 100)
526
703
        self.assertEqual(0, len(self.timeout_calls))
 
704
        self.assertEqual(0.0, self.bar.launcher.progress)
527
705
 
528
706
    def test_progress_made_updated_after_a_delay(self):
529
707
        """The progressbar is updated after a delay."""
530
708
        self.bar.progress_made(50, 100)
531
709
        self.clock.advance(aggregator.ProgressBar.updates_delay)
532
 
        self.assertIn(50.0, self.timeout_calls)
 
710
        self.assertIn(0.5, self.timeout_calls)
 
711
        self.assertEqual(0.5, self.bar.launcher.progress)
533
712
 
534
713
    def test_progress_updates_are_aggregated(self):
535
714
        """The progressbar is updated after a delay."""
543
722
        """The progressbar updates are continuous."""
544
723
        self.bar.progress_made(50, 100)
545
724
        self.clock.advance(aggregator.ProgressBar.updates_delay)
 
725
        self.assertEqual(0.5, self.bar.launcher.progress)
546
726
        self.bar.progress_made(60, 100)
547
727
        self.clock.advance(aggregator.ProgressBar.updates_delay)
 
728
        self.assertEqual(0.6, self.bar.launcher.progress)
548
729
        self.assertEqual(2, len(self.timeout_calls))
549
730
 
550
731
    def test_hidden_when_completed(self):
552
733
        self.bar.progress_made(50, 100)
553
734
        self.bar.completed()
554
735
        self.assertFalse(self.bar.visible)
555
 
 
556
 
    def test_disable(self):
557
 
        """The bar pulse is disabled."""
558
 
        self.bar.enable()
559
 
        self.bar.disable()
560
 
        self.assertFalse(self.bar.pulsating)
561
 
 
562
 
    def test_enable(self):
563
 
        """The bar pulse is enabled."""
564
 
        self.bar.disable()
565
 
        self.bar.enable()
566
 
        self.assertTrue(self.bar.pulsating)
 
736
        self.assertFalse(self.bar.launcher.progress_visible)
 
737
 
 
738
    @defer.inlineCallbacks
 
739
    def test_progress_made_inhibits_logout_suspend(self):
 
740
        """Suspend and logout are inhibited when the progressbar is shown."""
 
741
        self.bar.progress_made(50, 100)
 
742
        expected = aggregator.session.INHIBIT_LOGOUT_SUSPEND
 
743
        inhibitor = yield self.bar.inhibitor_defer
 
744
        self.assertEqual(inhibitor.flags, expected)
 
745
 
 
746
    @defer.inlineCallbacks
 
747
    def test_completed_uninhibits_logout_suspend(self):
 
748
        """Suspend and logout are uninhibited when all has completed."""
 
749
        self.bar.progress_made(50, 100)
 
750
        d = self.bar.inhibitor_defer
 
751
        self.bar.completed()
 
752
        inhibitor = yield d
 
753
        self.assertEqual(inhibitor.flags, 0)
 
754
 
 
755
    def test_show_warning_emblem(self):
 
756
        """The warning emblem is shown."""
 
757
        self.bar.hide_emblem()
 
758
        self.bar.show_warning_emblem()
 
759
        self.assertTrue(self.bar.emblem_visible)
 
760
        self.assertTrue(self.bar.launcher.emblem_visible)
 
761
 
 
762
    def test_hide_emblem(self):
 
763
        """The emblem is hidden."""
 
764
        self.bar.show_warning_emblem()
 
765
        self.bar.hide_emblem()
 
766
        self.assertFalse(self.bar.emblem_visible)
 
767
        self.assertFalse(self.bar.launcher.emblem_visible)
567
768
 
568
769
 
569
770
class FakeDelayedBuffer(object):
610
811
    def __init__(self, clock):
611
812
        """Initialize this fake instance."""
612
813
        self.queued_commands = set()
 
814
        self.notification_switch = aggregator.NotificationSwitch()
 
815
        self.connected = False
613
816
 
614
817
    def queue_done(self):
615
818
        """The queue completed all operations."""
623
826
        """A new command was unqueued."""
624
827
        self.queued_commands.discard(command)
625
828
 
 
829
    def build_notification(self):
 
830
        """Create a new toggleable notification object."""
 
831
        return self.notification_switch.build_notification()
 
832
 
626
833
    download_started = misc_command_queued
627
834
    download_finished = misc_command_unqueued
628
835
    upload_started = misc_command_queued
629
836
    upload_finished = misc_command_unqueued
630
837
 
631
 
 
632
 
class StatusFrontendTestCase(TestCase):
 
838
    def connection_made(self):
 
839
       """The client made the connection to the server."""
 
840
       self.connected = True
 
841
 
 
842
    def connection_lost(self):
 
843
       """The client lost the connection to the server."""
 
844
       self.connected = False
 
845
 
 
846
 
 
847
class StatusFrontendTestCase(BaseTwistedTestCase):
633
848
    """Test the status frontend."""
634
849
 
635
850
    def setUp(self):
636
851
        """Initialize this test instance."""
 
852
        BaseTwistedTestCase.setUp(self)
637
853
        self.patch(aggregator, "StatusAggregator", FakeAggregator)
638
 
        self.patch(aggregator, "Notification", FakeNotificationSingleton())
 
854
        self.patch(aggregator, "ToggleableNotification",
 
855
                   FakeNotificationSingleton())
639
856
        self.patch(aggregator, "Messaging", FakeMessaging)
640
857
        self.fakefsm = None
641
858
        self.fakevm = FakeVolumeManager()
744
961
            1, len(self.status_frontend.notification.notifications_shown))
745
962
        self.assertEqual(
746
963
            (aggregator.UBUNTUONE_TITLE,
747
 
             'New cloud folder available: <%s> shared by <%s>' % (
 
964
             "New cloud folder available: '%s' shared by %s" % (
748
965
                 'None', FAKE_SENDER), None, False),
749
966
            self.status_frontend.notification.notifications_shown[0])
750
967
        msg = self.status_frontend.messaging.messages_shown[FAKE_SENDER]
760
977
        self.assertEqual(
761
978
            1, len(self.status_frontend.notification.notifications_shown))
762
979
        self.assertEqual(
763
 
            (aggregator.UBUNTUONE_TITLE, 'New cloud folder available: None',
 
980
            (aggregator.UBUNTUONE_TITLE, "New cloud folder available: 'None'",
764
981
             None, False),
765
982
            self.status_frontend.notification.notifications_shown[0])
766
983
        self.assertEqual(
783
1000
        self.assertEqual(
784
1001
            2, len(self.status_frontend.notification.notifications_shown))
785
1002
        self.assertEqual(
786
 
            (aggregator.UBUNTUONE_TITLE, 'New cloud folder available: None',
 
1003
            (aggregator.UBUNTUONE_TITLE, "New cloud folder available: 'None'",
787
1004
             None, False),
788
1005
            self.status_frontend.notification.notifications_shown[0])
789
1006
        self.assertEqual(
790
 
            (aggregator.UBUNTUONE_TITLE, 'New cloud folder available: None',
 
1007
            (aggregator.UBUNTUONE_TITLE, "New cloud folder available: 'None'",
791
1008
             None, False),
792
1009
            self.status_frontend.notification.notifications_shown[1])
793
1010
        self.assertEqual(
807
1024
 
808
1025
    def test_server_connection_lost(self):
809
1026
        """The client connected to the server."""
 
1027
        self.status_frontend.aggregator.connected = True
810
1028
        self.listener.handle_SYS_CONNECTION_LOST()
811
1029
        self.assertEqual(
812
1030
            1, len(self.status_frontend.notification.notifications_shown))
814
1032
            (aggregator.UBUNTUONE_TITLE,
815
1033
             aggregator.ConnectionLostStatus.MESSAGE_ONE, None, False),
816
1034
            self.status_frontend.notification.notifications_shown[0])
 
1035
        self.assertFalse(self.status_frontend.aggregator.connected)
817
1036
 
818
1037
    def test_server_connection_made(self):
819
1038
        """The client connected to the server."""
 
1039
        self.status_frontend.aggregator.connected = False
820
1040
        self.listener.handle_SYS_CONNECTION_MADE()
821
1041
        self.assertEqual(
822
1042
            1, len(self.status_frontend.notification.notifications_shown))
824
1044
            (aggregator.UBUNTUONE_TITLE,
825
1045
             aggregator.ConnectionMadeStatus.MESSAGE_ONE, None, False),
826
1046
            self.status_frontend.notification.notifications_shown[0])
 
1047
        self.assertTrue(self.status_frontend.aggregator.connected)
 
1048
 
 
1049
    def test_set_show_all_notifications(self):
 
1050
        """Test the set_show_all_notifications method."""
 
1051
        self.status_frontend.set_show_all_notifications(False)
 
1052
        self.assertFalse(self.status_frontend.aggregator.
 
1053
                         notification_switch.enabled)
827
1054
 
828
1055
 
829
1056
class StatusEventTestCase(TestCase):
830
1057
    """Test the status event class and children."""
831
1058
 
832
1059
    CLASS = aggregator.StatusEvent
833
 
    CLASS_ARGS = ()
 
1060
    CLASS_KWARGS = {}
834
1061
    status = None
835
1062
 
836
1063
    def setUp(self):
837
1064
        """Initialize this test instance."""
838
1065
        if type(self) == StatusEventTestCase:
839
 
            self.assertRaises(AssertionError, self.CLASS, *self.CLASS_ARGS)
 
1066
            self.assertRaises(AssertionError, self.CLASS, **self.CLASS_KWARGS)
840
1067
        else:
841
 
            self.status = self.CLASS(*self.CLASS_ARGS)
 
1068
            self.status = self.CLASS(**self.CLASS_KWARGS)
842
1069
 
843
1070
    def test_one_message_defined(self):
844
1071
        """The singular message is defined as MESSAGE_ONE."""
860
1087
        if self.status:
861
1088
            count = 99
862
1089
            test_events = [FakeStatus(88)] * count
863
 
            expected = self.CLASS.MESSAGE_MANY % count
 
1090
            format_args = {"event_count": count}
 
1091
            expected = self.CLASS.MESSAGE_MANY % format_args
864
1092
            self.assertEqual(self.status.many(test_events), expected)
865
1093
 
866
1094
 
868
1096
    """Test the file publishing status class."""
869
1097
 
870
1098
    CLASS = aggregator.FilePublishingStatus
871
 
    CLASS_ARGS = ("http://fake_public/url",)
 
1099
    CLASS_KWARGS = {"new_public_url": "http://fake_public/url"}
872
1100
 
873
1101
    def test_one_message_built_correctly(self):
874
1102
        """The message returned by one() should include the url."""
875
 
        expected = self.CLASS.MESSAGE_ONE % self.status.args
 
1103
        expected = self.CLASS.MESSAGE_ONE % self.status.kwargs
876
1104
        self.assertEqual(self.status.one(), expected)
877
1105
 
878
1106
 
880
1108
    """Test the file unpublishing status class."""
881
1109
 
882
1110
    CLASS = aggregator.FileUnpublishingStatus
883
 
    CLASS_ARGS = (None,)
 
1111
    CLASS_KWARGS = {"old_public_url": None}
884
1112
 
885
1113
 
886
1114
class ShareAvailableEventTestCase(StatusEventTestCase):
891
1119
    SAMPLE_SHARE = Share(accepted=False, name=FOLDER_NAME,
892
1120
                         other_visible_name=OTHER_USER_NAME)
893
1121
    CLASS = aggregator.ShareAvailableStatus
894
 
    CLASS_ARGS = (SAMPLE_SHARE,)
 
1122
    CLASS_KWARGS = {"share": SAMPLE_SHARE}
895
1123
 
896
1124
    def test_one_message_built_correctly(self):
897
1125
        """one() must return the folder name and user name."""
898
 
        params = (self.FOLDER_NAME, self.OTHER_USER_NAME)
899
 
        expected = self.CLASS.MESSAGE_ONE % params
 
1126
        format_args = {
 
1127
            "folder_name": self.FOLDER_NAME,
 
1128
            "other_user_name": self.OTHER_USER_NAME,
 
1129
        }
 
1130
        expected = self.CLASS.MESSAGE_ONE % format_args
900
1131
        self.assertEqual(self.status.one(), expected)
901
1132
 
902
1133
 
906
1137
    FOLDER_NAME = "folder name"
907
1138
    SAMPLE_UDF = UDF(subscribed=False, suggested_path=FOLDER_NAME)
908
1139
    CLASS = aggregator.UDFAvailableStatus
909
 
    CLASS_ARGS = (SAMPLE_UDF,)
 
1140
    CLASS_KWARGS = {'udf': SAMPLE_UDF}
910
1141
 
911
1142
    def test_one_message_built_correctly(self):
912
1143
        """one() must return the folder name."""
913
 
        params = (self.FOLDER_NAME,)
914
 
        expected = self.CLASS.MESSAGE_ONE % params
 
1144
        format_args = {"folder_name": self.FOLDER_NAME}
 
1145
        expected = self.CLASS.MESSAGE_ONE % format_args
915
1146
        self.assertEqual(self.status.one(), expected)
916
1147
 
917
1148
 
919
1150
    """Test the event when the connection is lost."""
920
1151
 
921
1152
    CLASS = aggregator.ConnectionLostStatus
922
 
    CLASS_ARGS = ()
923
1153
 
924
1154
    def test_many_message_built_correctly(self):
925
1155
        """The message returned by many() is returned ok."""
934
1164
    """Test the event when the connection is made."""
935
1165
 
936
1166
    CLASS = aggregator.ConnectionMadeStatus
937
 
    CLASS_ARGS = ()
938
1167
 
939
1168
 
940
1169
class FakeStatus(aggregator.StatusEvent):
1012
1241
                   FakeProgressBubble)
1013
1242
        self.patch(aggregator, "FinalStatusBubble",
1014
1243
                   FakeFinalBubble)
 
1244
        self.patch(aggregator, "ToggleableNotification",
 
1245
                   FakeNotificationSingleton())
 
1246
        self.patch(aggregator, "UbuntuOneLauncher", FakeLauncher)
 
1247
        self.patch(aggregator.session, "Inhibitor", FakeInhibitor)
1015
1248
        self.status_frontend = aggregator.StatusFrontend()
1016
1249
        self.aggregator = self.status_frontend.aggregator
1017
1250
        self.fake_bubble = self.aggregator.file_discovery_bubble
1056
1289
        fc = FakeCommand()
1057
1290
        self.status_frontend.queue_added(fc)
1058
1291
        self.assertMiscCommandQueued(fc)
1059
 
        self.assertEqual(0, self.aggregator.progress_bar.percentage)
 
1292
        self.assertEqual(0, self.aggregator.progress_bar.progress)
1060
1293
 
1061
1294
    def test_misc_command_unqueue(self):
1062
1295
        """Test that a misc command was unqueued."""
1064
1297
        self.status_frontend.queue_added(fc)
1065
1298
        self.status_frontend.queue_removed(fc)
1066
1299
        self.assertMiscCommandUnqueued(fc)
1067
 
        self.assertEqual(100.0, self.aggregator.progress_bar.percentage)
 
1300
        self.assertEqual(1.0, self.aggregator.progress_bar.progress)
1068
1301
 
1069
1302
    def test_file_download_started(self):
1070
1303
        """Test that a file has started download."""
1102
1335
        """Test the message that's shown on the discovery bubble."""
1103
1336
        uploading = 10
1104
1337
        downloading = 8
 
1338
        upload_fmt = {"total_uploading_files": uploading}
 
1339
        download_fmt = {"total_downloading_files": downloading}
1105
1340
        self.aggregator.files_uploading.extend(range(uploading))
1106
1341
        self.aggregator.files_downloading.extend(range(downloading))
1107
 
        expected = (aggregator.FILES_UPLOADING % uploading + "\n" +
1108
 
                    aggregator.FILES_DOWNLOADING % downloading)
 
1342
        expected = (aggregator.FILES_UPLOADING % upload_fmt + "\n" +
 
1343
                    aggregator.FILES_DOWNLOADING % download_fmt)
1109
1344
        result = self.aggregator.get_discovery_message()
1110
1345
        self.assertEqual(expected, result)
1111
1346
 
1117
1352
        self.aggregator.download_total = 8
1118
1353
        self.aggregator.done_counter = 9
1119
1354
        self.aggregator.total_counter = 20
1120
 
        expected = (aggregator.PROGRESS_UPLOADED % (5, 10) + " " +
1121
 
                    aggregator.PROGRESS_DOWNLOADED % (3, 8) + " " +
1122
 
                    aggregator.PROGRESS_COMPLETED % int(100.0 * 9 / 20))
 
1355
        percentage = int(100.0 * self.aggregator.done_counter /
 
1356
                         self.aggregator.total_counter)
 
1357
        format_args = {
 
1358
            "total_uploading_files": self.aggregator.upload_total,
 
1359
            "total_downloading_files": self.aggregator.download_total,
 
1360
            "percentage_completed": percentage,
 
1361
        }
 
1362
 
 
1363
        format_string = (aggregator.FILES_UPLOADING + "\n" +
 
1364
                         aggregator.FILES_DOWNLOADING + "\n" +
 
1365
                         aggregator.PROGRESS_COMPLETED)
 
1366
 
 
1367
        expected = format_string % format_args
1123
1368
        result = self.aggregator.get_progress_message()
1124
1369
        self.assertEqual(expected, result)
1125
1370
 
1131
1376
        self.aggregator.download_total = 8
1132
1377
        self.aggregator.done_counter = 9
1133
1378
        self.aggregator.total_counter = 20
1134
 
        expected = (aggregator.PROGRESS_DOWNLOADED % (3, 8) + " " +
1135
 
                    aggregator.PROGRESS_COMPLETED % int(100.0 * 9 / 20))
 
1379
        percentage = int(100.0 * self.aggregator.done_counter /
 
1380
                         self.aggregator.total_counter)
 
1381
        format_args = {
 
1382
            "total_downloading_files": self.aggregator.download_total,
 
1383
            "percentage_completed": percentage,
 
1384
        }
 
1385
 
 
1386
        format_string = (aggregator.FILES_DOWNLOADING + "\n" +
 
1387
                         aggregator.PROGRESS_COMPLETED)
 
1388
 
 
1389
        expected = format_string % format_args
1136
1390
        result = self.aggregator.get_progress_message()
1137
1391
        self.assertEqual(expected, result)
1138
1392
 
1144
1398
        self.aggregator.download_total = 0
1145
1399
        self.aggregator.done_counter = 9
1146
1400
        self.aggregator.total_counter = 20
1147
 
        expected = (aggregator.PROGRESS_UPLOADED % (5, 10) + " " +
1148
 
                    aggregator.PROGRESS_COMPLETED % int(100.0 * 9 / 20))
 
1401
        percentage = int(100.0 * self.aggregator.done_counter /
 
1402
                         self.aggregator.total_counter)
 
1403
        format_args = {
 
1404
            "total_uploading_files": self.aggregator.upload_total,
 
1405
            "percentage_completed": percentage,
 
1406
        }
 
1407
 
 
1408
        format_string = (aggregator.FILES_UPLOADING + "\n" +
 
1409
                         aggregator.PROGRESS_COMPLETED)
 
1410
 
 
1411
        expected = format_string % format_args
1149
1412
        result = self.aggregator.get_progress_message()
1150
1413
        self.assertEqual(expected, result)
1151
1414
 
1158
1421
        """The final status message."""
1159
1422
        done = (5, 10)
1160
1423
        self.aggregator.upload_done, self.aggregator.download_done = done
1161
 
        expected = (aggregator.FINAL_COMPLETED + "\n" +
1162
 
                    aggregator.FINAL_UPLOADED % done[0] + "\n" +
1163
 
                    aggregator.FINAL_DOWNLOADED % done[1])
 
1424
 
 
1425
        format_args = {
 
1426
            "total_uploaded_files": self.aggregator.upload_done,
 
1427
            "total_downloaded_files": self.aggregator.download_done,
 
1428
        }
 
1429
 
 
1430
        format_string = (aggregator.FINAL_COMPLETED + "\n" +
 
1431
                         aggregator.FINAL_UPLOADED + "\n" +
 
1432
                         aggregator.FINAL_DOWNLOADED)
 
1433
 
 
1434
        expected = format_string % format_args
1164
1435
        result = self.aggregator.get_final_status_message()
1165
1436
        self.assertEqual(expected, result)
1166
1437
 
1168
1439
        """The final status message when there were no uploads."""
1169
1440
        done = (0, 12)
1170
1441
        self.aggregator.upload_done, self.aggregator.download_done = done
1171
 
        expected = (aggregator.FINAL_COMPLETED + "\n" +
1172
 
                    aggregator.FINAL_DOWNLOADED % done[1])
 
1442
 
 
1443
        format_args = {
 
1444
            "total_downloaded_files": self.aggregator.download_done,
 
1445
        }
 
1446
 
 
1447
        format_string = (aggregator.FINAL_COMPLETED + "\n" +
 
1448
                         aggregator.FINAL_DOWNLOADED)
 
1449
 
 
1450
        expected = format_string % format_args
1173
1451
        result = self.aggregator.get_final_status_message()
1174
1452
        self.assertEqual(expected, result)
1175
1453
 
1177
1455
        """The final status message when there were no downloads."""
1178
1456
        done = (8, 0)
1179
1457
        self.aggregator.upload_done, self.aggregator.download_done = done
1180
 
        expected = (aggregator.FINAL_COMPLETED + "\n" +
1181
 
                    aggregator.FINAL_UPLOADED % done[0])
 
1458
 
 
1459
        format_args = {
 
1460
            "total_uploaded_files": self.aggregator.upload_done,
 
1461
        }
 
1462
 
 
1463
        format_string = (aggregator.FINAL_COMPLETED + "\n" +
 
1464
                         aggregator.FINAL_UPLOADED)
 
1465
 
 
1466
        expected = format_string % format_args
1182
1467
        result = self.aggregator.get_final_status_message()
1183
1468
        self.assertEqual(expected, result)
1184
1469
 
1187
1472
        self.aggregator.restart_progress_bubble()
1188
1473
        self.assertTrue(self.aggregator.progress_bubble.started)
1189
1474
 
1190
 
    def test_queue_done(self):
1191
 
        """On queue done, show final bubble and reset counters."""
1192
 
        fc = FakeCommand()
1193
 
        self.status_frontend.upload_started(fc)
1194
 
        old_final_bubble = self.aggregator.final_status_bubble
1195
 
        self.aggregator.queue_done()
1196
 
        self.assertTrue(old_final_bubble.shown)
 
1475
    def test_queue_done_shows_bubble_when_downloads_happened(self):
 
1476
        """On queue done, show final bubble if downloads happened."""
 
1477
        fc = FakeCommand()
 
1478
        self.status_frontend.download_started(fc)
 
1479
        self.status_frontend.download_finished(fc)
 
1480
        old_final_bubble = self.aggregator.final_status_bubble
 
1481
        self.aggregator.queue_done()
 
1482
        self.assertTrue(old_final_bubble.shown)
 
1483
 
 
1484
    def test_queue_done_shows_bubble_when_uploads_happened(self):
 
1485
        """On queue done, show final bubble if uploads happened."""
 
1486
        fc = FakeCommand()
 
1487
        self.status_frontend.upload_started(fc)
 
1488
        self.status_frontend.upload_finished(fc)
 
1489
        old_final_bubble = self.aggregator.final_status_bubble
 
1490
        self.aggregator.queue_done()
 
1491
        self.assertTrue(old_final_bubble.shown)
 
1492
 
 
1493
    def test_queue_done_does_not_show_bubble_when_no_transfers_happened(self):
 
1494
        """On queue done, don't show final bubble if no transfers happened."""
 
1495
        fc = FakeCommand()
 
1496
        self.status_frontend.upload_started(fc)
 
1497
        old_final_bubble = self.aggregator.final_status_bubble
 
1498
        self.aggregator.queue_done()
 
1499
        self.assertFalse(old_final_bubble.shown)
 
1500
 
 
1501
    def test_queue_done_resets_status_and_hides_progressbar(self):
 
1502
        """On queue done, reset counters and hide progressbar."""
 
1503
        fc = FakeCommand()
 
1504
        self.status_frontend.upload_started(fc)
 
1505
        self.aggregator.queue_done()
1197
1506
        self.assertStatusReset()
1198
 
        self.assertEqual(0.0, self.aggregator.progress_bar.percentage)
 
1507
        self.assertEqual(0.0, self.aggregator.progress_bar.progress)
1199
1508
        self.assertFalse(self.aggregator.progress_bar.visible)
1200
1509
 
 
1510
    def test_connection_lost(self):
 
1511
        """The connection to the server was lost."""
 
1512
        self.status_frontend.server_connection_lost()
 
1513
        self.assertTrue(self.aggregator.progress_bar.emblem_visible)
 
1514
 
 
1515
    def test_connection_made(self):
 
1516
        """The connection to the server was made."""
 
1517
        self.status_frontend.server_connection_made()
 
1518
        self.assertFalse(self.aggregator.progress_bar.emblem_visible)
 
1519
 
1201
1520
 
1202
1521
class StatusGrouperTestCase(TestCase):
1203
1522
    """Tests for the group_statuses function."""
1227
1546
 
1228
1547
    def test_all_together_now(self):
1229
1548
        """Make all parts work together."""
1230
 
        self.patch(aggregator, "Notification", FakeNotificationSingleton())
 
1549
        self.patch(aggregator, "ToggleableNotification",
 
1550
                   FakeNotificationSingleton())
 
1551
        self.patch(aggregator, "UbuntuOneLauncher", FakeLauncher)
 
1552
        self.patch(aggregator.session, "Inhibitor", FakeInhibitor)
1231
1553
        clock = PatchedClock()
1232
1554
        upload = FakeCommand()
1233
1555
        sf = aggregator.StatusFrontend(clock=clock)
 
1556
        sf.set_show_all_notifications(True)
 
1557
 
1234
1558
        clock.advance(aggregator.ProgressBubble.sleep_delay)
1235
1559
        # the progress bar is not visible yet
1236
1560
        self.assertFalse(sf.aggregator.progress_bar.visible)
1248
1572
        sf.download_started(download)
1249
1573
        self.assertEqual(1, len(notifications_shown))
1250
1574
        # the progress still is zero
1251
 
        self.assertEqual(0.0, sf.aggregator.progress_bar.percentage)
 
1575
        self.assertEqual(0.0, sf.aggregator.progress_bar.progress)
1252
1576
        clock.advance(aggregator.FileDiscoveryUpdateState.updates_delay)
1253
1577
        # files count update
1254
1578
        self.assertEqual(2, len(notifications_shown))
1262
1586
        self.assertEqual(3, len(notifications_shown))
1263
1587
        sf.upload_finished(download)
1264
1588
        # the progress still is now 100%
1265
 
        self.assertEqual(100.0, sf.aggregator.progress_bar.percentage)
 
1589
        self.assertEqual(1.0, sf.aggregator.progress_bar.progress)
1266
1590
        # progress, but the progress bubble is not updated immediately
1267
1591
        self.assertEqual(3, len(notifications_shown))
1268
1592
        clock.advance(aggregator.ProgressBubble.sleep_delay)
1274
1598
        clock.advance(aggregator.ProgressBubble.sleep_delay * 2)
1275
1599
        # no more notifications are shown
1276
1600
        self.assertEqual(5, len(notifications_shown))
 
1601
 
 
1602
    def test_all_together_now_off(self):
 
1603
        """Make all parts work together, but with notifications off."""
 
1604
        self.patch(aggregator, "ToggleableNotification",
 
1605
                   FakeNotificationSingleton())
 
1606
        self.patch(aggregator, "UbuntuOneLauncher", FakeLauncher)
 
1607
        self.patch(aggregator.session, "Inhibitor", FakeInhibitor)
 
1608
        clock = PatchedClock()
 
1609
        upload = FakeCommand()
 
1610
        sf = aggregator.StatusFrontend(clock=clock)
 
1611
        sf.set_show_all_notifications(False)
 
1612
 
 
1613
        clock.advance(aggregator.ProgressBubble.sleep_delay)
 
1614
        # the progress bar is not visible yet
 
1615
        self.assertFalse(sf.aggregator.progress_bar.visible)
 
1616
        sf.upload_started(upload)
 
1617
        # the progress bar is now shown
 
1618
        self.assertTrue(sf.aggregator.progress_bar.visible)
 
1619
        notifications_shown = (sf.aggregator.file_discovery_bubble.
 
1620
                                             notification.notifications_shown)
 
1621
        # no notifications shown, never
 
1622
        self.assertEqual(0, len(notifications_shown))
 
1623
        clock.advance(aggregator.FileDiscoveryGatheringState.initial_delay)
 
1624
        self.assertEqual(0, len(notifications_shown))
 
1625
        download = FakeCommand()
 
1626
        sf.download_started(download)
 
1627
        self.assertEqual(0, len(notifications_shown))
 
1628
        # the progress still is zero
 
1629
        self.assertEqual(0.0, sf.aggregator.progress_bar.progress)
 
1630
        clock.advance(aggregator.FileDiscoveryUpdateState.updates_delay)
 
1631
        self.assertEqual(0, len(notifications_shown))
 
1632
        clock.advance(aggregator.FileDiscoveryUpdateState.updates_timeout -
 
1633
                      aggregator.FileDiscoveryUpdateState.updates_delay)
 
1634
        sf.upload_finished(upload)
 
1635
        # the progress bubble has no notifications yet
 
1636
        self.assertEqual(None, sf.aggregator.progress_bubble.notification)
 
1637
        clock.advance(aggregator.ProgressBubble.sleep_delay)
 
1638
        self.assertEqual(0, len(notifications_shown))
 
1639
        sf.upload_finished(download)
 
1640
        # the progress still is now 100%
 
1641
        self.assertEqual(1.0, sf.aggregator.progress_bar.progress)
 
1642
        self.assertEqual(0, len(notifications_shown))
 
1643
        clock.advance(aggregator.ProgressBubble.sleep_delay)
 
1644
        self.assertEqual(0, len(notifications_shown))
 
1645
        sf.queue_done()
 
1646
        self.assertEqual(0, len(notifications_shown))
 
1647
        clock.advance(aggregator.ProgressBubble.sleep_delay * 2)
 
1648
        self.assertEqual(0, len(notifications_shown))