332
327
"""The list of notifications shown."""
333
328
return self.bubble.notification.notifications_shown
335
def test_popup_shows_notification(self):
336
"""The popup callback shows notifications."""
337
self.bubble.new_file_found()
339
message = self.aggregator.build_discovery_message()
340
notification = (aggregator.UBUNTUONE_TITLE, message, None, False)
341
self.assertIn(notification, self.get_notifications_shown())
343
def test_popup_resets_progress_bubble(self):
344
"""The popup callback resets the progress bubble."""
345
self.bubble.new_file_found()
347
self.assertTrue(self.aggregator.restart_progress_bubble_called)
330
def test_popup_shows_notification_when_connected(self):
331
"""The popup callback shows notifications."""
332
self.bubble.connection_made()
333
self.bubble.new_file_found()
335
message = self.aggregator.build_discovery_message()
336
notification = (aggregator.UBUNTUONE_TITLE, message, None, False)
337
self.assertIn(notification, self.get_notifications_shown())
339
def test_popup_shows_notification_after_connected(self):
340
"""The popup callback shows notifications."""
341
self.bubble.new_file_found()
342
self.bubble.connection_made()
343
message = self.aggregator.build_discovery_message()
344
notification = (aggregator.UBUNTUONE_TITLE, message, None, False)
345
self.assertIn(notification, self.get_notifications_shown())
347
def test_popup_shows_no_notification_before_connection_made(self):
348
"""The popup callback shows notifications."""
349
self.bubble.new_file_found()
351
message = self.aggregator.build_discovery_message()
352
notification = (aggregator.UBUNTUONE_TITLE, message, None, False)
353
self.assertNotIn(notification, self.get_notifications_shown())
355
def test_popup_shows_no_notification_after_connection_lost(self):
356
"""The popup callback shows notifications."""
357
self.bubble.connection_made()
358
self.bubble.connection_lost()
359
self.bubble.new_file_found()
361
message = self.aggregator.build_discovery_message()
362
notification = (aggregator.UBUNTUONE_TITLE, message, None, False)
363
self.assertNotIn(notification, self.get_notifications_shown())
349
365
def test_notification_is_logged_in_debug(self):
350
366
"""The notification is printed in the debug log."""
367
self.bubble.connection_made()
351
368
self.bubble.new_file_found()
352
369
self.bubble._popup()
353
370
msg = "notification shown: %s" % self.get_notifications_shown()[0][1]
425
448
def test_new_files_found_while_updating_are_shown_after_a_delay(self):
426
449
"""New files found in the updating state are shown after a delay."""
450
self.bubble.connection_made()
427
451
self.bubble.new_file_found()
428
452
self.clock.advance(self.initial_delay)
429
453
self.bubble.new_file_found()
430
454
self.clock.advance(self.updates_delay)
431
455
self.assertEqual(2, len(self.get_notifications_shown()))
433
def test_update_resets_progress_bubble(self):
434
"""The update callback resets the progress bubble."""
435
self.bubble.new_file_found()
437
self.bubble.new_file_found()
438
self.bubble._update()
439
self.assertTrue(self.aggregator.restart_progress_bubble_called)
441
457
def test_update_modifies_notification(self):
442
458
"""The update callback updates notifications."""
459
self.bubble.connection_made()
443
460
self.bubble.new_file_found()
444
461
self.bubble._popup()
445
462
self.bubble.new_file_found()
458
476
self.assertTrue(self.handler.check_debug(msg))
461
class ProgressBubbleTestCase(TestCase):
462
"""Tests for the progress bubble."""
465
"""Initialize this test instance."""
466
self.patch(aggregator, "ToggleableNotification",
467
FakeNotificationSingleton())
468
self.clock = PatchedClock()
469
self.aggregator = FakeStatusAggregator(clock=self.clock)
470
self.bubble = aggregator.ProgressBubble(self.aggregator,
472
self.addCleanup(self.bubble.cleanup)
473
self.smaller_delay = aggregator.ProgressBubble.sleep_delay * 0.8
474
self.right_delay = aggregator.ProgressBubble.sleep_delay
475
self.longer_delay = aggregator.ProgressBubble.sleep_delay * 1.2
477
def test_is_created_successfully(self):
478
"""The progress bubble is created and idle."""
479
self.assertEqual(None, self.bubble.timer)
481
def test_restart_creates_timer(self):
482
"""Restarting creates a timer."""
483
self.bubble.restart()
484
self.assertNotEqual(None, self.bubble.timer)
486
def test_not_shown_initially(self):
487
"""The bubble is not shown initially."""
488
self.bubble.restart()
489
self.assertEqual(None, self.bubble.notification)
491
def test_not_shown_immediately(self):
492
"""The bubble is not shown immediately."""
493
self.bubble.restart()
494
self.clock.advance(self.smaller_delay)
495
self.assertEqual(None, self.bubble.notification)
497
def test_shown_after_delay(self):
498
"""The bubble is shown after the standard delay."""
499
self.bubble.restart()
500
self.clock.advance(self.longer_delay)
501
self.assertEqual(1, len(self.bubble.notification.notifications_shown))
503
def test_not_shown_if_restarted(self):
504
"""The delay is adjusted when restarting."""
505
self.bubble.restart()
506
self.clock.advance(self.smaller_delay)
507
self.bubble.restart()
508
self.clock.advance(self.smaller_delay)
509
self.assertEqual(None, self.bubble.notification)
511
def test_delay_reached_after_restart(self):
512
"""The timeout is still reached after a restart."""
513
self.bubble.restart()
514
self.clock.advance(self.smaller_delay)
515
self.bubble.restart()
516
self.clock.advance(self.longer_delay)
517
self.assertEqual(1, len(self.bubble.notification.notifications_shown))
519
def test_can_be_stopped(self):
520
"""The timeout can be stopped."""
521
self.bubble.restart()
522
self.clock.advance(self.smaller_delay)
524
self.clock.advance(self.longer_delay)
525
self.assertEqual(None, self.bubble.notification)
527
def test_delay_reached_after_stopping_then_restarting(self):
528
"""The timeout is still reached after a stop followed by a restart."""
529
self.bubble.restart()
530
self.clock.advance(self.smaller_delay)
532
self.clock.advance(self.longer_delay)
533
self.bubble.restart()
534
self.clock.advance(self.longer_delay)
535
self.assertEqual(1, len(self.bubble.notification.notifications_shown))
537
def test_restarts_automatically(self):
538
"""The timer is restarted automatically."""
539
self.bubble.restart()
540
self.clock.advance(self.right_delay)
541
self.assertEqual(1, len(self.bubble.notification.notifications_shown))
542
self.clock.advance(self.right_delay)
543
self.assertEqual(2, len(self.bubble.notification.notifications_shown))
546
479
class FinalBubbleTestCase(TestCase):
547
480
"""Test for the final status notification bubble."""
788
721
"""The queue completed all operations."""
789
722
self.queued_commands.clear()
791
def misc_command_queued(self, command):
792
"""A new command was queued."""
793
self.queued_commands.add(command)
795
def misc_command_unqueued(self, command):
796
"""A new command was unqueued."""
797
self.queued_commands.discard(command)
799
724
def get_notification(self):
800
725
"""Create a new toggleable notification object."""
801
726
return self.notification_switch.get_notification()
803
728
def download_started(self, command):
804
729
"""A download just started."""
805
730
self.files_downloading.append(command)
806
self.misc_command_queued(command)
731
self.queued_commands.add(command)
808
733
def download_finished(self, command):
809
734
"""A download just finished."""
810
735
if command in self.files_downloading:
811
736
self.files_downloading.remove(command)
812
self.misc_command_unqueued(command)
737
self.queued_commands.discard(command)
814
739
def upload_started(self, command):
815
740
"""An upload just started."""
816
741
self.files_uploading.append(command)
817
self.misc_command_queued(command)
742
self.queued_commands.add(command)
819
744
def upload_finished(self, command):
820
745
"""An upload just finished."""
821
746
if command in self.files_uploading:
822
747
self.files_uploading.remove(command)
823
self.misc_command_unqueued(command)
748
self.queued_commands.discard(command)
825
750
def connection_made(self):
826
751
"""The client made the connection to the server."""
914
839
qc = self.status_frontend.aggregator.queued_commands
915
840
self.assertNotIn(fake_command, qc)
917
def test_queue_added(self):
918
"""A command was added to the queue."""
919
fake_command = FakeCommand()
920
self.listener.handle_SYS_QUEUE_ADDED(fake_command)
921
qc = self.status_frontend.aggregator.queued_commands
922
self.assertIn(fake_command, qc)
924
def test_queue_removed(self):
925
"""A command has finished and is removed from the queue."""
926
fake_command = FakeCommand()
927
self.listener.handle_SYS_QUEUE_ADDED(fake_command)
928
self.listener.handle_SYS_QUEUE_REMOVED(fake_command)
929
qc = self.status_frontend.aggregator.queued_commands
930
self.assertNotIn(fake_command, qc)
932
842
def test_queue_done(self):
933
843
"""The queue is empty."""
934
844
fake_command = FakeCommand()
1056
966
self.assertNotEqual(None, self.CLASS.MESSAGE_ONE)
1058
def test_many_message_defined(self):
1059
"""The plural message is defined as MESSAGE_MANY."""
1061
self.assertNotEqual(None, self.CLASS.MESSAGE_MANY)
1063
968
def test_one_message_built_correctly(self):
1064
969
"""The message returned by one() is returned ok."""
1066
971
self.assertEqual(self.status.one(), self.CLASS.MESSAGE_ONE)
1068
def test_many_message_built_correctly(self):
1069
"""The message returned by many() is returned ok."""
1072
test_events = [FakeStatus(88)] * count
1073
format_args = {"event_count": count}
1074
expected = self.CLASS.MESSAGE_MANY % format_args
1075
self.assertEqual(self.status.many(test_events), expected)
1078
974
class FilePublishingStatusTestCase(StatusEventTestCase):
1079
975
"""Test the file publishing status class."""
1174
1070
def cleanup(self):
1175
1071
"""Cleanup this instance."""
1178
class FakeProgressBubble(object):
1179
"""A fake ProgressBubble object."""
1184
def __init__(self, status_aggregator, clock=None):
1185
"""Initialize this instance."""
1186
self.status_aggregator = status_aggregator
1189
"""Cleanup this instance."""
1192
"""Start this bubble waiting."""
1196
"""Make this bubble stop."""
1073
def connection_made(self):
1074
"""Connection made."""
1076
def connection_lost(self):
1077
"""Connection lost."""
1199
1080
class FakeFinalBubble(object):
1220
1101
"""Initialize this test instance."""
1221
1102
self.patch(aggregator, "FileDiscoveryBubble",
1222
1103
FakeFileDiscoveryBubble)
1223
self.patch(aggregator, "ProgressBubble",
1225
1104
self.patch(aggregator, "FinalStatusBubble",
1226
1105
FakeFinalBubble)
1227
1106
self.patch(aggregator, "ToggleableNotification",
1228
1107
FakeNotificationSingleton())
1229
1108
self.patch(aggregator, "UbuntuOneLauncher", FakeLauncher)
1230
1109
self.patch(aggregator.session, "Inhibitor", FakeInhibitor)
1231
self.status_frontend = aggregator.StatusFrontend()
1110
clock = PatchedClock()
1111
self.status_frontend = aggregator.StatusFrontend(clock=clock)
1232
1112
self.aggregator = self.status_frontend.aggregator
1233
1113
self.fake_bubble = self.aggregator.file_discovery_bubble
1267
1147
"""Test that the counters start at zero."""
1268
1148
self.assertStatusReset()
1270
def test_misc_command_queue(self):
1271
"""Test that a misc command was queued."""
1273
self.status_frontend.queue_added(fc)
1274
self.assertMiscCommandQueued(fc)
1275
self.assertEqual(0, self.aggregator.progress_bar.progress)
1277
def test_misc_command_unqueue(self):
1278
"""Test that a misc command was unqueued."""
1280
self.status_frontend.queue_added(fc)
1281
self.status_frontend.queue_removed(fc)
1282
self.assertMiscCommandUnqueued(fc)
1283
self.assertEqual(1.0, self.aggregator.progress_bar.progress)
1285
1150
def test_file_download_started(self):
1286
1151
"""Test that a file has started download."""
1287
1152
fc = FakeCommand(path='testfile.txt')
1337
1202
result = self.aggregator.get_discovery_message()
1338
1203
self.assertEqual(expected, result)
1340
def test_get_progress_message(self):
1341
"""Test the message that's shown on the progress bubble."""
1342
self.aggregator.upload_done = 5
1343
self.aggregator.upload_total = 10
1344
self.aggregator.uploading_filename = FILENAME
1345
self.aggregator.download_done = 3
1346
self.aggregator.download_total = 8
1347
self.aggregator.downloading_filename = FILENAME2
1348
self.aggregator.done_counter = 9
1349
self.aggregator.total_counter = 20
1350
percentage = int(100.0 * self.aggregator.done_counter /
1351
self.aggregator.total_counter)
1354
aggregator.files_being_uploaded(
1355
FILENAME, self.aggregator.upload_total) + "\n" +
1356
aggregator.files_being_downloaded(
1357
FILENAME2, self.aggregator.download_total) + "\n" +
1358
aggregator.PROGRESS_COMPLETED) % {
1359
'percentage_completed': percentage}
1361
result = self.aggregator.get_progress_message()
1362
self.assertEqual(expected, result)
1364
def test_get_progress_message_no_uploads(self):
1365
"""The progress message when no uploads are going on."""
1367
self.aggregator.upload_done = 0
1368
self.aggregator.upload_total = 0
1369
self.aggregator.downloading_filename = FILENAME
1370
self.aggregator.download_done = 3
1371
self.aggregator.download_total = 8
1372
self.aggregator.done_counter = 9
1373
self.aggregator.total_counter = 20
1374
percentage = int(100.0 * self.aggregator.done_counter /
1375
self.aggregator.total_counter)
1377
aggregator.files_being_downloaded(
1378
FILENAME, self.aggregator.download_total) + "\n" +
1379
aggregator.PROGRESS_COMPLETED) % {
1380
'percentage_completed': percentage}
1382
result = self.aggregator.get_progress_message()
1383
self.assertEqual(expected, result)
1385
def test_get_progress_message_no_downloads(self):
1386
"""The progress message when no downloads are going on."""
1387
self.aggregator.upload_done = 5
1388
self.aggregator.upload_total = 10
1389
self.aggregator.uploading_filename = FILENAME
1390
self.aggregator.download_done = 0
1391
self.aggregator.download_total = 0
1392
self.aggregator.done_counter = 9
1393
self.aggregator.total_counter = 20
1394
percentage = int(100.0 * self.aggregator.done_counter /
1395
self.aggregator.total_counter)
1397
aggregator.files_being_uploaded(
1398
FILENAME, self.aggregator.upload_total) +
1399
"\n" + aggregator.PROGRESS_COMPLETED) % {
1400
'percentage_completed': percentage}
1402
result = self.aggregator.get_progress_message()
1403
self.assertEqual(expected, result)
1405
def test_get_progress_message_no_total(self):
1406
"""No progress message possible if total counter is zero."""
1407
self.aggregator.total_counter = 0
1408
self.assertRaises(AssertionError, self.aggregator.get_progress_message)
1410
1205
def test_get_final_status_message(self):
1411
1206
"""The final status message."""
1473
1264
self.status_frontend.upload_finished(fc)
1474
1265
old_final_bubble = self.aggregator.final_status_bubble
1475
1266
self.aggregator.queue_done()
1267
self.aggregator.clock.advance(self.aggregator.finished_delay + 1)
1268
self.assertTrue(old_final_bubble.shown)
1270
def test_queue_done_shows_bubble_only_after_delay(self):
1271
"""On queue_done, show final bubble only after a delay."""
1273
self.status_frontend.upload_started(fc)
1274
self.status_frontend.upload_finished(fc)
1275
old_final_bubble = self.aggregator.final_status_bubble
1276
self.aggregator.queue_done()
1277
self.assertFalse(old_final_bubble.shown)
1278
self.aggregator.clock.advance(self.aggregator.finished_delay - 1)
1279
self.assertFalse(old_final_bubble.shown)
1280
self.aggregator.queue_done()
1281
self.assertFalse(old_final_bubble.shown)
1282
self.aggregator.clock.advance(2)
1283
self.assertFalse(old_final_bubble.shown)
1284
self.aggregator.clock.advance(self.aggregator.finished_delay + 1)
1476
1285
self.assertTrue(old_final_bubble.shown)
1478
1287
def test_queue_done_does_not_show_bubble_when_no_transfers_happened(self):
1562
1372
clock.advance(aggregator.FileDiscoveryUpdateState.updates_timeout -
1563
1373
aggregator.FileDiscoveryUpdateState.updates_delay)
1564
1374
sf.upload_finished(upload)
1565
# the progress bubble has no notifications yet
1566
self.assertEqual(None, sf.aggregator.progress_bubble.notification)
1567
clock.advance(aggregator.ProgressBubble.sleep_delay)
1568
# the progress bubble is shown
1569
self.assertEqual(3, len(notifications_shown))
1570
1375
sf.upload_finished(download)
1571
1376
# the progress still is now 100%
1572
1377
self.assertEqual(1.0, sf.aggregator.progress_bar.progress)
1573
# progress, but the progress bubble is not updated immediately
1574
self.assertEqual(3, len(notifications_shown))
1575
clock.advance(aggregator.ProgressBubble.sleep_delay)
1576
# the progress bubble is updated after a delay
1577
self.assertEqual(4, len(notifications_shown))
1578
1378
sf.queue_done()
1579
# the final bubble is shown immediately
1580
self.assertEqual(5, len(notifications_shown))
1581
clock.advance(aggregator.ProgressBubble.sleep_delay * 2)
1582
# no more notifications are shown
1583
self.assertEqual(5, len(notifications_shown))
1379
clock.advance(sf.aggregator.finished_delay + 1)
1380
self.assertEqual(3, len(notifications_shown))
1585
1382
def test_all_together_now_off(self):
1586
1383
"""Make all parts work together, but with notifications off."""
1615
1411
clock.advance(aggregator.FileDiscoveryUpdateState.updates_timeout -
1616
1412
aggregator.FileDiscoveryUpdateState.updates_delay)
1617
1413
sf.upload_finished(upload)
1618
# the progress bubble has no notifications yet
1619
self.assertEqual(None, sf.aggregator.progress_bubble.notification)
1620
clock.advance(aggregator.ProgressBubble.sleep_delay)
1621
self.assertEqual(0, len(notifications_shown))
1622
1414
sf.upload_finished(download)
1623
1415
# the progress still is now 100%
1624
1416
self.assertEqual(1.0, sf.aggregator.progress_bar.progress)
1625
1417
self.assertEqual(0, len(notifications_shown))
1626
clock.advance(aggregator.ProgressBubble.sleep_delay)
1627
self.assertEqual(0, len(notifications_shown))
1628
1418
sf.queue_done()
1629
1419
self.assertEqual(0, len(notifications_shown))
1630
clock.advance(aggregator.ProgressBubble.sleep_delay * 2)
1631
self.assertEqual(0, len(notifications_shown))