1# Copyright 2017 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 dbus
6
7from autotest_lib.client.bin import test
8from autotest_lib.client.common_lib import error
9from autotest_lib.client.cros import cups
10from autotest_lib.client.cros import debugd_util
11
12_GENERIC_PPD = 'GenericPostScript.ppd.gz'
13
14# Values are from platform/system_api/dbus/debugd/dbus-constants.h.
15_CUPS_SUCCESS = 0
16_CUPS_INVALID_PPD_ERROR = 2
17_CUPS_LPADMIN_ERROR = 3
18_CUPS_AUTOCONF_FAILURE = 4
19_CUPS_BAD_URI = 5
20
21
22class platform_DebugDaemonCupsAddPrinters(test.test):
23    """
24    Exercise CupsAddManuallyConfiguredPrinter from debugd.
25
26    Exercise the various add printer conditions and verify that the
27    error codes are correct.
28
29    """
30    version = 1
31
32    def load_ppd(self, file_name):
33        """
34        Returns the contents of a file as a dbus.ByteArray.
35
36        @param file_name: The name of the file.
37
38        """
39        abs_path = '%s/%s' % (self.srcdir, file_name)
40        with open(abs_path, 'rb') as f:
41            content = dbus.ByteArray(f.read())
42        return content
43
44    def test_autoconf(self):
45        """
46        Attempt to add an unreachable autoconfigured printer.
47
48        Verifies that upon autoconf failure, the error code is
49        CUPS_AUTOCONF_FAILURE.
50
51        @raises TestFail: If the test failed.
52
53        """
54        autoconfig_result = debugd_util.iface().CupsAddAutoConfiguredPrinter(
55                            'AutoconfPrinter', 'ipp://127.0.0.1/ipp/print')
56        # There's no printer at this address.  Autoconf failure expected.
57        # CUPS_AUTOCONF_FAILURE.
58        if autoconfig_result != _CUPS_AUTOCONF_FAILURE:
59            raise error.TestFail('autoconf - Incorrect error code received: '
60                '%i' % autoconfig_result)
61
62    def test_ppd_error(self, ppd_filename):
63        """
64        Validates that malformed PPDs are rejected.
65
66        The expected error code is CUPS_INVALID_PPD error.
67
68        @raises TestFail: If the test failed.
69
70        """
71        ppd_contents = self.load_ppd(ppd_filename)
72        result = debugd_util.iface().CupsAddManuallyConfiguredPrinter(
73                'ManualPrinterBreaks', 'socket://127.0.0.1/ipp/fake_printer',
74                ppd_contents)
75        # PPD is invalid.  Expect a CUPS_INVALID_PPD error.
76        if result != _CUPS_INVALID_PPD_ERROR:
77            raise error.TestFail('ppd_error - Incorrect error code received '
78                '%d' % result)
79
80    def test_valid_config(self):
81        """
82        Validates that a printer can be installed.
83
84        Verifies that given a valid configuration and a well formed PPD,
85        DebugDaemon reports a CUPS_SUCCESS error code indicating
86        success.
87
88        @raises TestFail: If the result from debugd was not CUPS_SUCCESS.
89
90        """
91        ppd_contents = self.load_ppd(_GENERIC_PPD)
92        result = debugd_util.iface().CupsAddManuallyConfiguredPrinter(
93                 'ManualPrinterGood', 'socket://127.0.0.1/ipp/fake_printer',
94                 ppd_contents)
95        # PPD is valid.  Printer doesn't need to be reachable.  This is
96        # expected to pass with CUPS_SUCCESS.
97        if result != _CUPS_SUCCESS:
98            raise error.TestFail('valid_config - Could not setup valid '
99                'printer %d' % result)
100
101    def test_lpadmin(self):
102        """
103        Verify the error for a failure in lpadmin.
104
105        The failure is reported as CUPS_LPADMIN_FAILURE.
106
107        @raises TestFail: If the error code from debugd is incorrect.
108
109        """
110        ppd_contents = self.load_ppd(_GENERIC_PPD)
111        result = debugd_util.iface().CupsAddManuallyConfiguredPrinter(
112                 'CUPS rejects names with spaces',
113                 'socket://127.0.0.1/ipp/fake_printer',
114                 ppd_contents)
115        if result != _CUPS_LPADMIN_ERROR:
116            raise error.TestFail(
117                'lpadmin - Names with spaces should be rejected by CUPS '
118                '%d' % result)
119
120        result = debugd_util.iface().CupsAddManuallyConfiguredPrinter(
121                 'UnrecognizedProtocol',
122                 'badbadbad://127.0.0.1/ipp/fake_printer',
123                  ppd_contents)
124        if result != _CUPS_BAD_URI:
125            raise error.TestFail(
126                  'lpadmin - Unrecognized protocols should be rejected by '
127                  'CUPS. %d' %
128                  result)
129
130    def run_once(self):
131        """
132        Runs tests based on the designated situation.
133
134        @raises TestError: If an unrecognized situation was used.
135
136        """
137        # Exits test if platform does not have CUPS
138        cups.has_cups_or_die()
139
140        self.test_valid_config()
141        self.test_lpadmin()
142        self.test_autoconf()
143
144        invalid_ppds = ['MissingMagicNumber.ppd.gz', 'InvalidCupsFilter.ppd.gz',
145                        'InvalidCupsPreFilter.ppd.gz']
146        for invalid_ppd in invalid_ppds:
147          self.test_ppd_error(invalid_ppd)
148