~ubuntu-branches/ubuntu/oneiric/landscape-client/oneiric-proposed

« back to all changes in this revision

Viewing changes to landscape/package/tests/test_reporter.py

  • Committer: Package Import Robot
  • Author(s): Andreas Hasenack
  • Date: 2012-06-19 14:55:03 UTC
  • mfrom: (1.2.11)
  • Revision ID: package-import@ubuntu.com-20120619145503-nw5y5w4sthf6rnus
Tags: 12.05-0ubuntu0.11.10
* New upstream release 12.05 (r561 in trunk) (LP: #1004678).
* Make all subpackages that depend on each other require the exact same
  version, instead of >= $version.
* Added python-gi to client depends starting natty.
* Make change-packages also handle package holds (LP: #972489).
* Fix typo in glade file (LP: #983096).
* Tidy up apt facade (LP: #985493).
* Remove SmartFacade and its tests, no longer used (LP: #996269).
* Remove check for apt version, since we won't release this for
  Hardy where that check matters (LP: #996837).
* Remove methods that were smart specific. We no longer use smart
  (LP: #996841).
* Remove smart-update helper binary. We no longer use smart
  (LP: #997408).
* Remove test-mixins that were useful only during the apt-to-smart
  code migration. Now with smart gone, they are no longer necessary
  (LP: #997760).
* Build the packages from precise onward, not just precise.
* Assorted packaging fixes:
  - Switched to format 3.0 (quilt).
  - Added source lintian overrides, with comments.
  - Updated debian/rules:
    - Added build-arch and build-indep dummy target.
    - Build the GUI packages from precise onwards, and not just on precise.
    - Re-enable dh_lintian.
    - Strip the binaries (dh_strip), and also call dh_shlibdeps for the
      automatic shlibs dependency.
    - Added python-gi from natty onwards.
  - Used __Choices instead of _Choices in landscape-common.templates, it's
    better for translators.
  - Updated standard version to 3.8.2, the version from Lucid (oldest one
    we support)
  - Added shlibs depends.
  - Dropped deprecated ${Source-Version} and replaced it with
    ${binary:Version}
  - Require exact version of the sibling package instead of >=.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
import glob
2
1
import sys
3
2
import os
4
3
import unittest
17
16
    PackageReporter, HASH_ID_REQUEST_TIMEOUT, main, find_reporter_command,
18
17
    PackageReporterConfiguration, FakeGlobalReporter, FakeReporter)
19
18
from landscape.package import reporter
20
 
from landscape.package.facade import AptFacade, has_new_enough_apt
 
19
from landscape.package.facade import AptFacade
21
20
from landscape.package.tests.helpers import (
22
 
    SmartFacadeHelper, AptFacadeHelper, SimpleRepositoryHelper,
 
21
    AptFacadeHelper, SimpleRepositoryHelper,
23
22
    HASH1, HASH2, HASH3, PKGNAME1)
24
23
from landscape.tests.helpers import (
25
24
    LandscapeTest, BrokerServiceHelper, EnvironSaverHelper)
30
29
 
31
30
class PackageReporterConfigurationTest(unittest.TestCase):
32
31
 
33
 
    def test_force_smart_update_option(self):
 
32
    def test_force_apt_update_option(self):
34
33
        """
35
 
        The L{PackageReporterConfiguration} supports a '--force-smart-update'
 
34
        The L{PackageReporterConfiguration} supports a '--force-apt-update'
36
35
        command line option.
37
36
        """
38
37
        config = PackageReporterConfiguration()
39
 
        self.assertFalse(config.force_smart_update)
40
 
        config.load(["--force-smart-update"])
41
 
        self.assertTrue(config.force_smart_update)
42
 
 
43
 
 
44
 
class PackageReporterTestMixin(object):
 
38
        self.assertFalse(config.force_apt_update)
 
39
        config.load(["--force-apt-update"])
 
40
        self.assertTrue(config.force_apt_update)
 
41
 
 
42
 
 
43
class PackageReporterAptTest(LandscapeTest):
 
44
 
 
45
    helpers = [AptFacadeHelper, SimpleRepositoryHelper, BrokerServiceHelper]
 
46
 
 
47
    Facade = AptFacade
 
48
 
 
49
    def setUp(self):
 
50
 
 
51
        def set_up(ignored):
 
52
            self.store = PackageStore(self.makeFile())
 
53
            self.config = PackageReporterConfiguration()
 
54
            self.reporter = PackageReporter(
 
55
                self.store, self.facade, self.remote, self.config)
 
56
            self.config.data_path = self.makeDir()
 
57
            os.mkdir(self.config.package_directory)
 
58
 
 
59
        result = super(PackageReporterAptTest, self).setUp()
 
60
        return result.addCallback(set_up)
 
61
 
 
62
    def _clear_repository(self):
 
63
        """Remove all packages from self.repository."""
 
64
        create_file(self.repository_dir + "/Packages", "")
 
65
 
 
66
    def set_pkg1_upgradable(self):
 
67
        """Make it so that package "name1" is considered to be upgradable.
 
68
 
 
69
        Return the hash of the package that upgrades "name1".
 
70
        """
 
71
        self._add_package_to_deb_dir(
 
72
            self.repository_dir, "name1", version="version2")
 
73
        self.facade.reload_channels()
 
74
        name1_upgrade = sorted(self.facade.get_packages_by_name("name1"))[1]
 
75
        return self.facade.get_package_hash(name1_upgrade)
 
76
 
 
77
    def set_pkg1_installed(self):
 
78
        """Make it so that package "name1" is considered installed."""
 
79
        self._install_deb_file(os.path.join(self.repository_dir, PKGNAME1))
 
80
 
 
81
    def _make_fake_apt_update(self, out="output", err="error", code=0):
 
82
        """Create a fake apt-update executable"""
 
83
        self.reporter.apt_update_filename = self.makeFile(
 
84
            "#!/bin/sh\n"
 
85
            "echo -n %s\n"
 
86
            "echo -n %s >&2\n"
 
87
            "exit %d" % (out, err, code))
 
88
        os.chmod(self.reporter.apt_update_filename, 0755)
45
89
 
46
90
    def test_set_package_ids_with_all_known(self):
47
91
        self.store.add_hash_id_request(["hash1", "hash2"])
497
541
 
498
542
        return result
499
543
 
500
 
    def test_run_smart_update(self):
501
 
        """
502
 
        The L{PackageReporter.run_smart_update} method should run smart-update
503
 
        with the proper arguments.
504
 
        """
505
 
        self.reporter.sources_list_filename = "/I/Dont/Exist"
506
 
        self.reporter.sources_list_directory = "/I/Dont/Exist"
507
 
        self.reporter.smart_update_filename = self.makeFile(
508
 
            "#!/bin/sh\necho -n $@")
509
 
        os.chmod(self.reporter.smart_update_filename, 0755)
510
 
        debug_mock = self.mocker.replace("logging.debug")
511
 
        debug_mock("'%s' exited with status 0 (out='--after %d', err=''" % (
512
 
            self.reporter.smart_update_filename,
513
 
            self.reporter.smart_update_interval))
514
 
        warning_mock = self.mocker.replace("logging.warning")
515
 
        self.expect(warning_mock(ANY)).count(0)
516
 
        self.mocker.replay()
517
 
        deferred = Deferred()
518
 
 
519
 
        def do_test():
520
 
 
521
 
            result = self.reporter.run_smart_update()
522
 
 
523
 
            def callback((out, err, code)):
524
 
                interval = self.reporter.smart_update_interval
525
 
                self.assertEqual(err, "")
526
 
                self.assertEqual(out, "--after %d" % interval)
527
 
                self.assertEqual(code, 0)
528
 
            result.addCallback(callback)
529
 
            result.chainDeferred(deferred)
530
 
 
531
 
        reactor.callWhenRunning(do_test)
532
 
        return deferred
533
 
 
534
 
    def test_run_smart_update_with_force_smart_update(self):
535
 
        """
536
 
        L{PackageReporter.run_smart_update} forces a smart-update run if
537
 
        the '--force-smart-update' command line option was passed.
538
 
 
539
 
        """
540
 
        self.config.load(["--force-smart-update"])
541
 
        self.reporter.smart_update_filename = self.makeFile(
542
 
            "#!/bin/sh\necho -n $@")
543
 
        os.chmod(self.reporter.smart_update_filename, 0755)
544
 
 
545
 
        deferred = Deferred()
546
 
 
547
 
        def do_test():
548
 
            result = self.reporter.run_smart_update()
549
 
 
550
 
            def callback((out, err, code)):
551
 
                self.assertEqual(out, "")
552
 
            result.addCallback(callback)
553
 
            result.chainDeferred(deferred)
554
 
 
555
 
        reactor.callWhenRunning(do_test)
556
 
        return deferred
557
 
 
558
544
    def test_wb_apt_sources_have_changed(self):
559
545
        """
560
546
        The L{PackageReporter._apt_sources_have_changed} method returns a bool
581
567
                      content="deb http://foo ./")
582
568
        self.assertTrue(self.reporter._apt_sources_have_changed())
583
569
 
584
 
    def test_run_smart_update_with_force_smart_update_if_sources_changed(self):
585
 
        """
586
 
        L{PackageReporter.run_smart_update} forces a smart-update run if
587
 
        the APT sources.list file has changed.
588
 
 
589
 
        """
590
 
        self.assertEqual(self.reporter.sources_list_filename,
591
 
                         "/etc/apt/sources.list")
592
 
        self.reporter.sources_list_filename = self.makeFile("deb ftp://url ./")
593
 
        self.reporter.smart_update_filename = self.makeFile(
594
 
            "#!/bin/sh\necho -n $@")
595
 
        os.chmod(self.reporter.smart_update_filename, 0755)
596
 
 
597
 
        deferred = Deferred()
598
 
 
599
 
        def do_test():
600
 
            result = self.reporter.run_smart_update()
601
 
 
602
 
            def callback((out, err, code)):
603
 
                # Smart update was called without the --after parameter
604
 
                self.assertEqual(out, "")
605
 
            result.addCallback(callback)
606
 
            result.chainDeferred(deferred)
607
 
 
608
 
        reactor.callWhenRunning(do_test)
609
 
        return deferred
610
 
 
611
 
    def test_run_smart_update_warns_about_failures(self):
612
 
        """
613
 
        The L{PackageReporter.run_smart_update} method should log a warning
614
 
        in case smart-update terminates with a non-zero exit code other than 1.
615
 
        """
616
 
        self.reporter.smart_update_filename = self.makeFile(
617
 
            "#!/bin/sh\necho -n error >&2\necho -n output\nexit 2")
618
 
        os.chmod(self.reporter.smart_update_filename, 0755)
619
 
        logging_mock = self.mocker.replace("logging.warning")
620
 
        logging_mock("'%s' exited with status 2"
621
 
                     " (error)" % self.reporter.smart_update_filename)
622
 
        self.mocker.replay()
623
 
        deferred = Deferred()
624
 
 
625
 
        def do_test():
626
 
            result = self.reporter.run_smart_update()
627
 
 
628
 
            def callback((out, err, code)):
629
 
                self.assertEqual(out, "output")
630
 
                self.assertEqual(err, "error")
631
 
                self.assertEqual(code, 2)
632
 
            result.addCallback(callback)
633
 
            result.chainDeferred(deferred)
634
 
 
635
 
        reactor.callWhenRunning(do_test)
636
 
        return deferred
637
 
 
638
 
    def test_run_smart_update_report_smart_failure(self):
639
 
        """
640
 
        If L{PackageReporter.run_smart_update} fails, a message is sent to the
641
 
        server reporting the error, to be able to fix the problem centrally.
642
 
        """
643
 
        message_store = self.broker_service.message_store
644
 
        message_store.set_accepted_types(["package-reporter-result"])
645
 
        self.reporter.smart_update_filename = self.makeFile(
646
 
            "#!/bin/sh\necho -n error >&2\necho -n output\nexit 2")
647
 
        os.chmod(self.reporter.smart_update_filename, 0755)
648
 
        deferred = Deferred()
649
 
 
650
 
        def do_test():
651
 
            result = self.reporter.run_smart_update()
652
 
 
653
 
            def callback(ignore):
654
 
                self.assertMessages(message_store.get_pending_messages(),
655
 
                    [{"type": "package-reporter-result",
656
 
                      "code": 2, "err": u"error"}])
657
 
            result.addCallback(callback)
658
 
            result.chainDeferred(deferred)
659
 
 
660
 
        reactor.callWhenRunning(do_test)
661
 
        return deferred
662
 
 
663
 
    def test_run_smart_update_report_no_sources(self):
664
 
        """
665
 
        L{PackageReporter.run_smart_update} reports a failure if smart
666
 
        succeeds but there are no APT sources defined. Smart doesn't
667
 
        fail if there are no sources, but we fake a failure in order to
668
 
        re-use the PackageReporterAlert on the server.
669
 
        """
670
 
        self.facade.reset_channels()
671
 
        message_store = self.broker_service.message_store
672
 
        message_store.set_accepted_types(["package-reporter-result"])
673
 
        self.reporter.smart_update_filename = self.makeFile(
674
 
            "#!/bin/sh\necho -n error >&2\necho -n output\nexit 0")
675
 
        os.chmod(self.reporter.smart_update_filename, 0755)
676
 
        deferred = Deferred()
677
 
 
678
 
        def do_test():
679
 
            result = self.reporter.run_smart_update()
680
 
 
681
 
            def callback(ignore):
682
 
                error = "There are no APT sources configured in %s or %s." % (
683
 
                    self.reporter.sources_list_filename,
684
 
                    self.reporter.sources_list_directory)
685
 
                self.assertMessages(message_store.get_pending_messages(),
686
 
                    [{"type": "package-reporter-result",
687
 
                      "code": 1, "err": error}])
688
 
            result.addCallback(callback)
689
 
            result.chainDeferred(deferred)
690
 
 
691
 
        reactor.callWhenRunning(do_test)
692
 
        return deferred
693
 
 
694
 
    def test_run_smart_update_report_smart_failure_no_sources(self):
695
 
        """
696
 
        If L{PackageReporter.run_smart_update} fails and there are no
697
 
        APT sources configured, the Smart error takes precedence.
698
 
        """
699
 
        self.facade.reset_channels()
700
 
        message_store = self.broker_service.message_store
701
 
        message_store.set_accepted_types(["package-reporter-result"])
702
 
        self.reporter.smart_update_filename = self.makeFile(
703
 
            "#!/bin/sh\necho -n error >&2\necho -n output\nexit 2")
704
 
        os.chmod(self.reporter.smart_update_filename, 0755)
705
 
        deferred = Deferred()
706
 
 
707
 
        def do_test():
708
 
            result = self.reporter.run_smart_update()
709
 
 
710
 
            def callback(ignore):
711
 
                self.assertMessages(message_store.get_pending_messages(),
712
 
                    [{"type": "package-reporter-result",
713
 
                      "code": 2, "err": u"error"}])
714
 
            result.addCallback(callback)
715
 
            result.chainDeferred(deferred)
716
 
 
717
 
        reactor.callWhenRunning(do_test)
718
 
        return deferred
719
 
 
720
 
    def test_run_smart_update_report_success(self):
721
 
        """
722
 
        L{PackageReporter.run_smart_update} also reports success to be able to
723
 
        know the proper state of the client.
724
 
        """
725
 
        message_store = self.broker_service.message_store
726
 
        message_store.set_accepted_types(["package-reporter-result"])
727
 
        self.reporter.smart_update_filename = self.makeFile(
728
 
            "#!/bin/sh\necho -n error >&2\necho -n output\nexit 0")
729
 
        os.chmod(self.reporter.smart_update_filename, 0755)
730
 
        deferred = Deferred()
731
 
 
732
 
        def do_test():
733
 
            result = self.reporter.run_smart_update()
734
 
 
735
 
            def callback(ignore):
736
 
                self.assertMessages(message_store.get_pending_messages(),
737
 
                    [{"type": "package-reporter-result",
738
 
                      "code": 0, "err": u"error"}])
739
 
            result.addCallback(callback)
740
 
            result.chainDeferred(deferred)
741
 
 
742
 
        reactor.callWhenRunning(do_test)
743
 
        return deferred
744
 
 
745
 
    def test_run_smart_update_warns_exit_code_1_and_non_empty_stderr(self):
746
 
        """
747
 
        The L{PackageReporter.run_smart_update} method should log a warning
748
 
        in case smart-update terminates with exit code 1 and non empty stderr.
749
 
        """
750
 
        self.reporter.smart_update_filename = self.makeFile(
751
 
            "#!/bin/sh\necho -n \"error  \" >&2\nexit 1")
752
 
        os.chmod(self.reporter.smart_update_filename, 0755)
753
 
        logging_mock = self.mocker.replace("logging.warning")
754
 
        logging_mock("'%s' exited with status 1"
755
 
                     " (error  )" % self.reporter.smart_update_filename)
756
 
        self.mocker.replay()
757
 
        deferred = Deferred()
758
 
 
759
 
        def do_test():
760
 
            result = self.reporter.run_smart_update()
761
 
 
762
 
            def callback((out, err, code)):
763
 
                self.assertEqual(out, "")
764
 
                self.assertEqual(err, "error  ")
765
 
                self.assertEqual(code, 1)
766
 
            result.addCallback(callback)
767
 
            result.chainDeferred(deferred)
768
 
 
769
 
        reactor.callWhenRunning(do_test)
770
 
        return deferred
771
 
 
772
 
    def test_run_smart_update_ignores_exit_code_1_and_empty_output(self):
773
 
        """
774
 
        The L{PackageReporter.run_smart_update} method should not log anything
775
 
        in case smart-update terminates with exit code 1 and output containing
776
 
        only a newline character.
777
 
        """
778
 
        self.reporter.smart_update_filename = self.makeFile(
779
 
            "#!/bin/sh\necho\nexit 1")
780
 
        os.chmod(self.reporter.smart_update_filename, 0755)
781
 
        logging_mock = self.mocker.replace("logging.warning")
782
 
        self.expect(logging_mock(ANY)).count(0)
783
 
        self.mocker.replay()
784
 
        deferred = Deferred()
785
 
 
786
 
        def do_test():
787
 
 
788
 
            result = self.reporter.run_smart_update()
789
 
 
790
 
            def callback((out, err, code)):
791
 
                self.assertEqual(out, "\n")
792
 
                self.assertEqual(err, "")
793
 
                self.assertEqual(code, 1)
794
 
            result.addCallback(callback)
795
 
            result.chainDeferred(deferred)
796
 
 
797
 
        reactor.callWhenRunning(do_test)
798
 
        return deferred
799
 
 
800
 
    def test_run_smart_update_touches_stamp_file(self):
801
 
        """
802
 
        The L{PackageReporter.run_smart_update} method touches a stamp file
803
 
        after running the smart-update wrapper.
804
 
        """
805
 
        self.reporter.sources_list_filename = "/I/Dont/Exist"
806
 
        self.reporter.smart_update_filename = "/bin/true"
807
 
        deferred = Deferred()
808
 
 
809
 
        def do_test():
810
 
 
811
 
            result = self.reporter.run_smart_update()
812
 
 
813
 
            def callback(ignored):
814
 
                self.assertTrue(
815
 
                    os.path.exists(self.config.update_stamp_filename))
816
 
            result.addCallback(callback)
817
 
            result.chainDeferred(deferred)
818
 
 
819
 
        reactor.callWhenRunning(do_test)
820
 
        return deferred
821
 
 
822
570
    def test_remove_expired_hash_id_request(self):
823
571
        request = self.store.add_hash_id_request(["hash1"])
824
572
        request.message_id = 9999
1133
881
 
1134
882
        upgrade_hash = self.set_pkg1_upgradable()
1135
883
        self.set_pkg1_installed()
1136
 
        # Don't reload for SmartFacade, since the hash of pkg2 will be
1137
 
        # changed, resulting in that name2 will be considered not
1138
 
        # available..
1139
 
        if isinstance(self.facade, AptFacade):
1140
 
            self.facade.reload_channels()
 
884
        self.facade.reload_channels()
1141
885
 
1142
886
        self.store.set_hash_ids(
1143
887
            {HASH1: 1, upgrade_hash: 2, HASH3: 3})
1193
937
        result = self.reporter.detect_packages_changes()
1194
938
        return result.addCallback(got_result)
1195
939
 
1196
 
    def test_detect_changes_considers_packages_and_locks_changes(self):
 
940
    def test_detect_changes_considers_packages_changes(self):
1197
941
        """
1198
 
        The L{PackageReporter.detect_changes} method considers both package and
1199
 
        package locks changes. It also releases smart locks by calling the
1200
 
        L{SmartFacade.deinit} method.
 
942
        The L{PackageReporter.detect_changes} method package changes.
1201
943
        """
1202
944
        reporter_mock = self.mocker.patch(self.reporter)
1203
945
        reporter_mock.detect_packages_changes()
1204
946
        self.mocker.result(succeed(True))
1205
 
        reporter_mock.detect_package_locks_changes()
1206
 
        self.mocker.result(succeed(True))
1207
 
 
1208
 
        facade_mock = self.mocker.patch(self.facade)
1209
 
        facade_mock.deinit()
1210
947
 
1211
948
        self.mocker.replay()
1212
949
        return self.reporter.detect_changes()
1219
956
        """
1220
957
        reporter_mock = self.mocker.patch(self.reporter)
1221
958
        reporter_mock.detect_packages_changes()
1222
 
        self.mocker.result(succeed(False))
1223
 
        reporter_mock.detect_package_locks_changes()
1224
959
        self.mocker.result(succeed(True))
1225
960
        callback = self.mocker.mock()
1226
961
        callback()
1236
971
 
1237
972
        results = [Deferred() for i in range(7)]
1238
973
 
1239
 
        # Either the Apt or Smart cache will be updated, not both.
1240
 
        if isinstance(self.facade, AptFacade):
1241
 
            reporter_mock.run_apt_update()
1242
 
        else:
1243
 
            reporter_mock.run_smart_update()
 
974
        reporter_mock.run_apt_update()
1244
975
        self.mocker.result(results[0])
1245
976
 
1246
977
        reporter_mock.fetch_hash_id_db()
1306
1037
        This is done in the reporter so that we know it happens when
1307
1038
        no other reporter is possibly running at the same time.
1308
1039
        """
 
1040
        self._add_system_package("foo")
 
1041
        self.facade.reload_channels()
 
1042
        [foo] = self.facade.get_packages_by_name("foo")
 
1043
        foo_hash = self.facade.get_package_hash(foo)
 
1044
        self.facade.set_package_hold(foo)
 
1045
        self.facade.reload_channels()
1309
1046
        message_store = self.broker_service.message_store
1310
1047
        message_store.set_accepted_types(["package-locks"])
1311
 
        self.store.set_hash_ids({HASH1: 3, HASH2: 4})
 
1048
        self.store.set_hash_ids({foo_hash: 3, HASH2: 4})
1312
1049
        self.store.add_available([1])
1313
1050
        self.store.add_available_upgrades([2])
1314
1051
        self.store.add_installed([2])
1315
1052
        self.store.add_locked([3])
1316
 
        self.store.add_package_locks([("name1", None, None)])
1317
 
        if self.facade.supports_package_locks:
1318
 
            self.facade.set_package_lock("name1")
1319
1053
        request1 = self.store.add_hash_id_request(["hash3"])
1320
1054
        request2 = self.store.add_hash_id_request(["hash4"])
1321
1055
 
1328
1062
        self.assertEqual(self.store.get_available_upgrades(), [2])
1329
1063
        self.assertEqual(self.store.get_available(), [1])
1330
1064
        self.assertEqual(self.store.get_installed(), [2])
1331
 
        # XXX: Don't check get_locked() and get_package_locks() until
1332
 
        # package locks are implemented in AptFacade.
1333
 
        if not isinstance(self.facade, AptFacade):
1334
 
            self.assertEqual(self.store.get_locked(), [3])
1335
 
            self.assertEqual(
1336
 
                self.store.get_package_locks(), [("name1", "", "")])
1337
1065
        self.assertEqual(self.store.get_hash_id_request(request1.id).id,
1338
1066
                         request1.id)
1339
1067
 
1344
1072
        def check_result(result):
1345
1073
 
1346
1074
            # The hashes should not go away.
1347
 
            hash1 = self.store.get_hash_id(HASH1)
 
1075
            hash1 = self.store.get_hash_id(foo_hash)
1348
1076
            hash2 = self.store.get_hash_id(HASH2)
1349
1077
            self.assertEqual([hash1, hash2], [3, 4])
1350
1078
 
1353
1081
 
1354
1082
            # After running the resychronize task, detect_packages_changes is
1355
1083
            # called, and the existing known hashes are made available.
1356
 
            self.assertEqual(self.store.get_available(), [3, 4])
1357
 
            self.assertEqual(self.store.get_installed(), [])
1358
 
            # XXX: Don't check get_locked() until package locks are
1359
 
            # implemented in AptFacade.
1360
 
            if not isinstance(self.facade, AptFacade):
1361
 
                self.assertEqual(self.store.get_locked(), [3])
 
1084
            self.assertEqual(self.store.get_available(), [4])
 
1085
            self.assertEqual(self.store.get_installed(), [3])
 
1086
            self.assertEqual(self.store.get_locked(), [3])
1362
1087
 
1363
1088
            # The two original hash id requests should be still there, and
1364
1089
            # a new hash id request should also be detected for HASH3.
1371
1096
                elif request.id == request2.id:
1372
1097
                    self.assertEqual(request.hashes, ["hash4"])
1373
1098
                elif not new_request_found:
1374
 
                    self.assertEqual(request.hashes, [HASH3])
 
1099
                    self.assertEqual(request.hashes, [HASH3, HASH1])
1375
1100
                else:
1376
1101
                    self.fail("Unexpected hash-id request!")
1377
1102
            self.assertEqual(requests_count, 3)
1378
1103
 
1379
 
            # XXX: Don't check for package-locks messages until package
1380
 
            # locks are implemented in AptFacade.
1381
 
            if not isinstance(self.facade, AptFacade):
1382
 
                self.assertMessages(message_store.get_pending_messages(),
1383
 
                                    [{"type": "package-locks",
1384
 
                                      "created": [("name1", "", "")]}])
1385
 
 
1386
1104
        deferred.addCallback(check_result)
1387
1105
        return deferred
1388
1106
 
1389
 
 
1390
 
class PackageReporterSmartTest(LandscapeTest, PackageReporterTestMixin):
1391
 
 
1392
 
    helpers = [SmartFacadeHelper, BrokerServiceHelper]
1393
 
 
1394
 
    def setUp(self):
1395
 
 
1396
 
        def set_up(ignored):
1397
 
            self.store = PackageStore(self.makeFile())
1398
 
            self.config = PackageReporterConfiguration()
1399
 
            self.reporter = PackageReporter(
1400
 
                self.store, self.facade, self.remote, self.config)
1401
 
            self.config.data_path = self.makeDir()
1402
 
            os.mkdir(self.config.package_directory)
1403
 
 
1404
 
        result = super(PackageReporterSmartTest, self).setUp()
1405
 
        return result.addCallback(set_up)
1406
 
 
1407
 
    def _clear_repository(self):
1408
 
        """Remove all packages from self.repository."""
1409
 
        for filename in glob.glob(self.repository_dir + "/*"):
1410
 
            os.unlink(filename)
1411
 
 
1412
 
    def set_pkg1_upgradable(self):
1413
 
        """Make it so that package "name1" is considered to be upgradable.
1414
 
 
1415
 
        Return the hash of the package that upgrades "name1".
1416
 
        """
1417
 
        previous = self.Facade.channels_reloaded
1418
 
 
1419
 
        def callback(self):
1420
 
            from smart.backends.deb.base import DebUpgrades
1421
 
            previous(self)
1422
 
            pkg2 = self.get_packages_by_name("name2")[0]
1423
 
            pkg2.upgrades += (DebUpgrades("name1", "=", "version1-release1"),)
1424
 
            self.reload_cache()  # Relink relations.
1425
 
        self.Facade.channels_reloaded = callback
1426
 
        return HASH2
1427
 
 
1428
 
    def set_pkg1_installed(self):
1429
 
        """Make it so that package "name1" is considered installed."""
1430
 
        previous = self.Facade.channels_reloaded
1431
 
 
1432
 
        def callback(self):
1433
 
            previous(self)
1434
 
            self.get_packages_by_name("name1")[0].installed = True
1435
 
        self.Facade.channels_reloaded = callback
1436
 
 
1437
 
    def test_detect_packages_changes_with_locked(self):
1438
 
        """
1439
 
        If Smart indicates locked packages we didn't know about, report
1440
 
        them to the server.
1441
 
        """
1442
 
        message_store = self.broker_service.message_store
1443
 
        message_store.set_accepted_types(["packages"])
1444
 
 
1445
 
        self.facade.set_package_lock("name1")
1446
 
        self.facade.set_package_lock("name2", ">=", "version2")
1447
 
 
1448
 
        self.store.set_hash_ids({HASH1: 1, HASH2: 2})
1449
 
        self.store.add_available([1, 2])
1450
 
 
1451
 
        def got_result(result):
1452
 
            self.assertMessages(message_store.get_pending_messages(),
1453
 
                                [{"type": "packages", "locked": [1, 2]}])
1454
 
            self.assertEqual(sorted(self.store.get_locked()), [1, 2])
1455
 
 
1456
 
        result = self.reporter.detect_packages_changes()
1457
 
        return result.addCallback(got_result)
1458
 
 
1459
 
    def test_detect_packages_changes_with_locked_and_ranges(self):
1460
 
        """
1461
 
        Ranges are used when reporting changes to 3 or more locked packages
1462
 
        having consecutive ids.
1463
 
        """
1464
 
        message_store = self.broker_service.message_store
1465
 
        message_store.set_accepted_types(["packages"])
1466
 
 
1467
 
        self.facade.set_package_lock("name1")
1468
 
        self.facade.set_package_lock("name2", ">=", "version2")
1469
 
        self.facade.set_package_lock("name3", "<", "version4")
1470
 
 
1471
 
        self.store.set_hash_ids({HASH1: 1, HASH2: 2, HASH3: 3})
1472
 
        self.store.add_available([1, 2, 3])
1473
 
 
1474
 
        def got_result(result):
1475
 
            self.assertMessages(message_store.get_pending_messages(),
1476
 
                                [{"type": "packages", "locked": [(1, 3)]}])
1477
 
            self.assertEqual(sorted(self.store.get_locked()), [1, 2, 3])
1478
 
 
1479
 
        result = self.reporter.detect_packages_changes()
1480
 
        return result.addCallback(got_result)
1481
 
 
1482
 
    def test_detect_packages_changes_with_locked_with_unknown_hash(self):
1483
 
        """
1484
 
        Locked packages whose hashes are unknown don't get reported.
1485
 
        """
1486
 
        self.facade.set_package_lock("name1")
1487
 
 
1488
 
        def got_result(result):
1489
 
            self.assertEqual(self.store.get_locked(), [])
1490
 
 
1491
 
        result = self.reporter.detect_packages_changes()
1492
 
        return result.addCallback(got_result)
1493
 
 
1494
 
    def test_detect_packages_changes_with_locked_and_previously_known(self):
1495
 
        """
1496
 
        We don't report locked packages we already know about.
1497
 
        """
1498
 
        message_store = self.broker_service.message_store
1499
 
        message_store.set_accepted_types(["packages"])
1500
 
 
1501
 
        self.facade.set_package_lock("name1")
1502
 
        self.facade.set_package_lock("name2", ">=", "version2")
1503
 
 
1504
 
        self.store.set_hash_ids({HASH1: 1, HASH2: 2})
1505
 
        self.store.add_available([1, 2])
1506
 
        self.store.add_locked([1])
1507
 
 
1508
 
        def got_result(result):
1509
 
            self.assertMessages(message_store.get_pending_messages(),
1510
 
                                [{"type": "packages", "locked": [2]}])
1511
 
 
1512
 
            self.assertEqual(sorted(self.store.get_locked()), [1, 2])
1513
 
 
1514
 
        result = self.reporter.detect_packages_changes()
1515
 
        return result.addCallback(got_result)
1516
 
 
1517
 
    def test_detect_packages_changes_with_not_locked(self):
1518
 
        """
1519
 
        We report when a package was previously locked and isn't anymore.
1520
 
        """
1521
 
        message_store = self.broker_service.message_store
1522
 
        message_store.set_accepted_types(["packages"])
1523
 
 
1524
 
        self.store.set_hash_ids({HASH1: 1})
1525
 
        self.store.add_available([1])
1526
 
        self.store.add_locked([1])
1527
 
 
1528
 
        def got_result(result):
1529
 
            self.assertMessages(message_store.get_pending_messages(),
1530
 
                                [{"type": "packages", "not-locked": [1]}])
1531
 
            self.assertEqual(self.store.get_locked(), [])
1532
 
 
1533
 
        result = self.reporter.detect_packages_changes()
1534
 
        return result.addCallback(got_result)
1535
 
 
1536
 
    def test_detect_package_locks_changes_with_create_locks(self):
1537
 
        """
1538
 
        If Smart indicates package locks we didn't know about, report
1539
 
        them to the server.
1540
 
        """
1541
 
        message_store = self.broker_service.message_store
1542
 
        message_store.set_accepted_types(["package-locks"])
1543
 
 
1544
 
        self.facade.set_package_lock("name")
1545
 
 
1546
 
        logging_mock = self.mocker.replace("logging.info")
1547
 
        logging_mock("Queuing message with changes in known package locks:"
1548
 
                     " 1 created, 0 deleted.")
1549
 
        self.mocker.replay()
1550
 
 
1551
 
        def got_result(result):
1552
 
            self.assertMessages(message_store.get_pending_messages(),
1553
 
                                [{"type": "package-locks",
1554
 
                                  "created": [("name", "", "")]}])
1555
 
            self.assertEqual(self.store.get_package_locks(),
1556
 
                             [("name", "", "")])
1557
 
 
1558
 
        result = self.reporter.detect_package_locks_changes()
1559
 
        return result.addCallback(got_result)
1560
 
 
1561
 
    def test_detect_package_locks_changes_with_already_known_locks(self):
1562
 
        """
1563
 
        We don't report changes about locks we already know about.
1564
 
        """
1565
 
        message_store = self.broker_service.message_store
1566
 
        message_store.set_accepted_types(["package-locks"])
1567
 
 
1568
 
        self.facade.set_package_lock("name1")
1569
 
        self.facade.set_package_lock("name2", "<", "1.2")
1570
 
 
1571
 
        self.store.add_package_locks([("name1", "", "")])
1572
 
 
1573
 
        logging_mock = self.mocker.replace("logging.info")
1574
 
        logging_mock("Queuing message with changes in known package locks:"
1575
 
                     " 1 created, 0 deleted.")
1576
 
        self.mocker.replay()
1577
 
 
1578
 
        def got_result(result):
1579
 
            self.assertMessages(message_store.get_pending_messages(),
1580
 
                                [{"type": "package-locks",
1581
 
                                  "created": [("name2", "<", "1.2")]}])
1582
 
            self.assertEqual(sorted(self.store.get_package_locks()),
1583
 
                             [("name1", "", ""),
1584
 
                              ("name2", "<", "1.2")])
1585
 
 
1586
 
        result = self.reporter.detect_package_locks_changes()
1587
 
        return result.addCallback(got_result)
1588
 
 
1589
 
    def test_detect_package_locks_changes_with_deleted_locks(self):
1590
 
        """
1591
 
        If Smart indicates newly unset package locks, report them to the
1592
 
        server.
1593
 
        """
1594
 
        message_store = self.broker_service.message_store
1595
 
        message_store.set_accepted_types(["package-locks"])
1596
 
 
1597
 
        self.store.add_package_locks([("name1", "", "")])
1598
 
 
1599
 
        logging_mock = self.mocker.replace("logging.info")
1600
 
        logging_mock("Queuing message with changes in known package locks:"
1601
 
                     " 0 created, 1 deleted.")
1602
 
        self.mocker.replay()
1603
 
 
1604
 
        def got_result(result):
1605
 
            self.assertMessages(message_store.get_pending_messages(),
1606
 
                                [{"type": "package-locks",
1607
 
                                  "deleted": [("name1", "", "")]}])
1608
 
            self.assertEqual(self.store.get_package_locks(), [])
1609
 
 
1610
 
        result = self.reporter.detect_package_locks_changes()
1611
 
        return result.addCallback(got_result)
1612
 
 
1613
 
    def test_detect_package_locks_changes_with_locked_already_known(self):
1614
 
        """
1615
 
        If we didn't detect any change in the package locks, we don't send any
1616
 
        message, and we return a deferred resulting in C{False}.
1617
 
        """
1618
 
        message_store = self.broker_service.message_store
1619
 
        message_store.set_accepted_types(["package-locks"])
1620
 
 
1621
 
        self.facade.set_package_lock("name1")
1622
 
        self.store.add_package_locks([("name1", "", "")])
1623
 
 
1624
 
        def got_result(result):
1625
 
            self.assertFalse(result)
1626
 
            self.assertMessages(message_store.get_pending_messages(), [])
1627
 
 
1628
 
        result = self.reporter.detect_packages_changes()
1629
 
        return result.addCallback(got_result)
1630
 
 
1631
 
 
1632
 
class PackageReporterAptTest(LandscapeTest, PackageReporterTestMixin):
1633
 
 
1634
 
    if not has_new_enough_apt:
1635
 
        skip = "Can't use AptFacade on hardy"
1636
 
 
1637
 
    helpers = [AptFacadeHelper, SimpleRepositoryHelper, BrokerServiceHelper]
1638
 
 
1639
 
    Facade = AptFacade
1640
 
 
1641
 
    def setUp(self):
1642
 
 
1643
 
        def set_up(ignored):
1644
 
            self.store = PackageStore(self.makeFile())
1645
 
            self.config = PackageReporterConfiguration()
1646
 
            self.reporter = PackageReporter(
1647
 
                self.store, self.facade, self.remote, self.config)
1648
 
            self.config.data_path = self.makeDir()
1649
 
            os.mkdir(self.config.package_directory)
1650
 
 
1651
 
        result = super(PackageReporterAptTest, self).setUp()
1652
 
        return result.addCallback(set_up)
1653
 
 
1654
 
    def _clear_repository(self):
1655
 
        """Remove all packages from self.repository."""
1656
 
        create_file(self.repository_dir + "/Packages", "")
1657
 
 
1658
 
    def set_pkg1_upgradable(self):
1659
 
        """Make it so that package "name1" is considered to be upgradable.
1660
 
 
1661
 
        Return the hash of the package that upgrades "name1".
1662
 
        """
1663
 
        self._add_package_to_deb_dir(
1664
 
            self.repository_dir, "name1", version="version2")
1665
 
        self.facade.reload_channels()
1666
 
        name1_upgrade = sorted(self.facade.get_packages_by_name("name1"))[1]
1667
 
        return self.facade.get_package_hash(name1_upgrade)
1668
 
 
1669
 
    def set_pkg1_installed(self):
1670
 
        """Make it so that package "name1" is considered installed."""
1671
 
        self._install_deb_file(os.path.join(self.repository_dir, PKGNAME1))
1672
 
 
1673
 
    def _make_fake_apt_update(self, out="output", err="error", code=0):
1674
 
        """Create a fake apt-update executable"""
1675
 
        self.reporter.apt_update_filename = self.makeFile(
1676
 
            "#!/bin/sh\n"
1677
 
            "echo -n %s\n"
1678
 
            "echo -n %s >&2\n"
1679
 
            "exit %d" % (out, err, code))
1680
 
        os.chmod(self.reporter.apt_update_filename, 0755)
1681
 
 
1682
1107
    def test_run_apt_update(self):
1683
1108
        """
1684
1109
        The L{PackageReporter.run_apt_update} method should run apt-update.
1708
1133
        reactor.callWhenRunning(do_test)
1709
1134
        return deferred
1710
1135
 
1711
 
    def test_run_apt_update_with_force_smart_update(self):
 
1136
    def test_run_apt_update_with_force_apt_update(self):
1712
1137
        """
1713
1138
        L{PackageReporter.run_apt_update} forces an apt-update run if the
1714
 
        '--force-smart-update' command line option was passed.
 
1139
        '--force-apt-update' command line option was passed.
1715
1140
        """
1716
1141
        self.makeFile("", path=self.config.update_stamp_filename)
1717
 
        self.config.load(["--force-smart-update"])
 
1142
        self.config.load(["--force-apt-update"])
1718
1143
        self._make_fake_apt_update()
1719
1144
 
1720
1145
        deferred = Deferred()
1730
1155
        reactor.callWhenRunning(do_test)
1731
1156
        return deferred
1732
1157
 
1733
 
    def test_run_apt_update_with_force_smart_update_if_sources_changed(self):
 
1158
    def test_run_apt_update_with_force_apt_update_if_sources_changed(self):
1734
1159
        """
1735
1160
        L{PackageReporter.run_apt_update} forces an apt-update run if the APT
1736
1161
        sources.list file has changed.
1929
1354
        return deferred
1930
1355
 
1931
1356
 
1932
 
class GlobalPackageReporterTestMixin(object):
 
1357
class GlobalPackageReporterAptTest(LandscapeTest):
 
1358
 
 
1359
    helpers = [AptFacadeHelper, SimpleRepositoryHelper, BrokerServiceHelper]
 
1360
 
 
1361
    def setUp(self):
 
1362
 
 
1363
        def set_up(ignored):
 
1364
            self.store = FakePackageStore(self.makeFile())
 
1365
            self.config = PackageReporterConfiguration()
 
1366
            self.reporter = FakeGlobalReporter(
 
1367
                self.store, self.facade, self.remote, self.config)
 
1368
            self.config.data_path = self.makeDir()
 
1369
            os.mkdir(self.config.package_directory)
 
1370
 
 
1371
        result = super(GlobalPackageReporterAptTest, self).setUp()
 
1372
        return result.addCallback(set_up)
1933
1373
 
1934
1374
    def test_store_messages(self):
1935
1375
        """
1937
1377
        """
1938
1378
        message_store = self.broker_service.message_store
1939
1379
        message_store.set_accepted_types(["package-reporter-result"])
1940
 
        self.reporter.smart_update_filename = self.makeFile(
 
1380
        self.reporter.apt_update_filename = self.makeFile(
1941
1381
            "#!/bin/sh\necho -n error >&2\necho -n output\nexit 0")
1942
 
        os.chmod(self.reporter.smart_update_filename, 0755)
 
1382
        os.chmod(self.reporter.apt_update_filename, 0755)
1943
1383
        deferred = Deferred()
1944
1384
 
1945
1385
        def do_test():
1946
 
            result = self.reporter.run_smart_update()
 
1386
            result = self.reporter.run_apt_update()
1947
1387
 
1948
1388
            def callback(ignore):
1949
1389
                message = {"type": "package-reporter-result",
1962
1402
        return deferred
1963
1403
 
1964
1404
 
1965
 
class GlobalPackageReporterAptTest(LandscapeTest,
1966
 
                                   GlobalPackageReporterTestMixin):
1967
 
 
1968
 
    if not has_new_enough_apt:
1969
 
        skip = "Can't use AptFacade on hardy"
1970
 
 
1971
 
    helpers = [AptFacadeHelper, SimpleRepositoryHelper, BrokerServiceHelper]
1972
 
 
1973
 
    def setUp(self):
1974
 
 
1975
 
        def set_up(ignored):
1976
 
            self.store = FakePackageStore(self.makeFile())
1977
 
            self.config = PackageReporterConfiguration()
1978
 
            self.reporter = FakeGlobalReporter(
1979
 
                self.store, self.facade, self.remote, self.config)
1980
 
            self.config.data_path = self.makeDir()
1981
 
            os.mkdir(self.config.package_directory)
1982
 
 
1983
 
        result = super(GlobalPackageReporterAptTest, self).setUp()
1984
 
        return result.addCallback(set_up)
1985
 
 
1986
 
 
1987
 
class GlobalPackageReporterSmartTest(LandscapeTest,
1988
 
                                     GlobalPackageReporterTestMixin):
1989
 
 
1990
 
    helpers = [SmartFacadeHelper, BrokerServiceHelper]
1991
 
 
1992
 
    def setUp(self):
1993
 
 
1994
 
        def set_up(ignored):
1995
 
            self.store = FakePackageStore(self.makeFile())
1996
 
            self.config = PackageReporterConfiguration()
1997
 
            self.reporter = FakeGlobalReporter(
1998
 
                self.store, self.facade, self.remote, self.config)
1999
 
            self.config.data_path = self.makeDir()
2000
 
            os.mkdir(self.config.package_directory)
2001
 
 
2002
 
        result = super(GlobalPackageReporterSmartTest, self).setUp()
2003
 
        return result.addCallback(set_up)
2004
 
 
2005
 
 
2006
1405
class FakePackageReporterTest(LandscapeTest):
2007
1406
 
2008
1407
    helpers = [EnvironSaverHelper, BrokerServiceHelper]