1# Copyright 2016 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import os.path
6import time
7
8from autotest_lib.client.bin import test, utils
9from autotest_lib.client.common_lib import error
10from autotest_lib.client.common_lib import utils as sys_utils
11from autotest_lib.client.cros import upstart
12
13
14class platform_CUPSDaemon(test.test):
15    """
16    Runs some sanity tests for cupsd and the upstart-socket-bridge
17    socket-activation.
18    """
19    version = 1
20
21    _CUPS_SOCK_PATH = '/run/cups/cups.sock'
22
23
24    def check_cups_is_responding(self):
25        """
26        Run a basic sanity test to be sure CUPS is operating.
27        """
28
29        # Try a simple CUPS command; timeout/fail if it takes too long (i.e.,
30        # socket may exist, but it may not get passed off to cupsd properly).
31        utils.system_output('lpstat -W all', timeout=10)
32
33
34    def wait_for_path_exists(self, path, timeout=5):
35        """
36        Wait for a path to exist, with timeout.
37
38        @param path: path to look for
39        @param timeout: time to wait, in seconds
40
41        @return true if path is found; false otherwise
42        """
43        while timeout > 0:
44            if os.path.exists(path):
45                return True
46
47            time.sleep(1)
48            timeout -= 1
49
50        return os.path.exists(path)
51
52
53    def run_upstart_tests(self):
54        """
55        Run some sanity tests for cupsd and the upstart-socket-bridge
56        socket-activation.
57        """
58        if not upstart.has_service('cupsd'):
59            raise error.TestNAError('No cupsd service found')
60
61        upstart.ensure_running('upstart-socket-bridge')
62
63        if not self.wait_for_path_exists(self._CUPS_SOCK_PATH):
64            raise error.TestFail('Missing CUPS socket: %s', self._CUPS_SOCK_PATH)
65
66        # Make sure CUPS is stopped, so we can test on-demand launch.
67        if upstart.is_running('cupsd'):
68            upstart.stop_job('cupsd')
69
70        self.check_cups_is_responding()
71
72        # Now try stopping socket bridge, to see it clean up its files.
73        upstart.stop_job('upstart-socket-bridge')
74        upstart.stop_job('cupsd')
75
76        if os.path.exists(self._CUPS_SOCK_PATH):
77            raise error.TestFail('CUPS socket was not cleaned up: %s', self._CUPS_SOCK_PATH)
78
79        # Create dummy file, to see if upstart-socket-bridge will clear it out
80        # properly.
81        utils.system('touch %s' % self._CUPS_SOCK_PATH)
82
83        upstart.restart_job('upstart-socket-bridge')
84
85        if not os.path.exists(self._CUPS_SOCK_PATH):
86            raise error.TestFail('Missing CUPS socket: %s', self._CUPS_SOCK_PATH)
87
88        self.check_cups_is_responding()
89
90
91    def run_systemd_tests(self):
92        """
93        Check if cupsd is running and responsive.
94        """
95        # Check to see if the service is running.
96        if sys_utils.get_service_pid('cups') == 0:
97            # Try to start it.
98            if sys_utils.start_service('cups', ignore_status=True) != 0:
99                raise error.TestNAError('No cupsd service found')
100
101        sys_utils.stop_service('cups', ignore_status=False)
102        sys_utils.start_service('cups.socket', ignore_status=False)
103
104        if not self.wait_for_path_exists(self._CUPS_SOCK_PATH):
105            raise error.TestFail('Missing CUPS socket: %s', self._CUPS_SOCK_PATH)
106
107        # Test that cupsd is automatically launched through socket activation.
108        self.check_cups_is_responding()
109
110        sys_utils.stop_service('cups', ignore_status=False)
111        sys_utils.stop_service('cups.socket', ignore_status=False)
112
113        # Dummy file to test that cups.socket handles lingering file properly.
114        utils.system('touch %s' % self._CUPS_SOCK_PATH)
115
116        sys_utils.start_service('cups.socket', ignore_status=False)
117
118        if not os.path.exists(self._CUPS_SOCK_PATH):
119            raise error.TestFail('Missing CUPS socket: %s', self._CUPS_SOCK_PATH)
120
121        self.check_cups_is_responding()
122
123
124    def run_once(self):
125        """
126        Run some sanity tests for cupsd.
127        """
128        if sys_utils.has_systemd():
129            self.run_systemd_tests()
130        else:
131            self.run_upstart_tests()
132