~launchpad-pqm/launchpad/devel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# Copyright 2009 Canonical Ltd.  This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).

"""
Fixtures for running the Google test webservice.
"""

__metaclass__ = type

__all__ = ['GoogleServiceTestSetup']


import errno
import os
import signal

from lp.services.googlesearch import googletestservice


class GoogleServiceTestSetup:
    """Set up the Google web service stub for use in functional tests.
    """


    # XXX gary 2008-12-06 bug=305858: Spurious test failures discovered on
    # buildbot, builds 40 and 43. The locations of the failures are marked
    # below with " # SPURIOUS FAILURE". To reinstate, add the text below back
    # to the docstring above.  Note that the test that uses this setup,
    # google-service-stub.txt, is also disabled.  See
    # canonical/launchpad/ftests/test_system_documentation.py.
    """
    >>> from lp.services.googlesearch.googletestservice import (
    ...     service_is_available)
    >>> from canonical.config import config

    >>> assert not service_is_available()  # Sanity check. # SPURIOUS FAILURE

    >>> GoogleServiceTestSetup().setUp()

    After setUp is called, a Google test service instance is running.

    >>> assert service_is_available()
    >>> assert GoogleServiceTestSetup.service is not None

    After tearDown is called, the service is shut down.

    >>> GoogleServiceTestSetup().tearDown()

    >>> assert not service_is_available()
    >>> assert GoogleServiceTestSetup.service is None

    The fixture can be started and stopped multiple time in succession:

    >>> GoogleServiceTestSetup().setUp()
    >>> assert service_is_available()

    Having a service instance already running doesn't prevent a new
    service from starting.  The old instance is killed off and replaced
    by the new one.

    >>> old_pid = GoogleServiceTestSetup.service.pid
    >>> GoogleServiceTestSetup().setUp() # SPURIOUS FAILURE
    >>> GoogleServiceTestSetup.service.pid != old_pid
    True

    Tidy up.

    >>> GoogleServiceTestSetup().tearDown()
    >>> assert not service_is_available()

    """

    service = None  # A reference to our running service.

    def setUp(self):
        self.startService()

    def tearDown(self):
        self.stopService()

    @classmethod
    def startService(cls):
        """Start the webservice."""
        googletestservice.kill_running_process()
        cls.service = googletestservice.start_as_process()
        assert cls.service, "The Search service process did not start."
        try:
            googletestservice.wait_for_service()
        except RuntimeError:
            # The service didn't start itself soon enough.  We must
            # make sure to kill any errant processes that may be
            # hanging around.
            cls.stopService()
            raise

    @classmethod
    def stopService(cls):
        """Shut down the webservice instance."""
        if cls.service:
            try:
                os.kill(cls.service.pid, signal.SIGTERM)
            except OSError, error:
                if error.errno != errno.ESRCH:
                    raise
                # The process with the given pid doesn't exist, so there's
                # nothing to kill or wait for.
            else:
                cls.service.wait()
        cls.service = None