Home | History | Annotate | Download | only in platform_AddPrinter
      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 
      5 import dbus
      6 import logging
      7 import os
      8 import tempfile
      9 from threading import Thread
     10 
     11 from autotest_lib.client.bin import test, utils
     12 from autotest_lib.client.common_lib import file_utils
     13 from autotest_lib.client.common_lib import error
     14 from autotest_lib.client.common_lib.cros import chrome
     15 from autotest_lib.client.common_lib.cros import dbus_send
     16 from autotest_lib.client.cros import debugd_util
     17 from fake_printer import FakePrinter
     18 
     19 _FAKE_SERVER_JOIN_TIMEOUT = 10
     20 _FAKE_PRINTER_ID = 'FakePrinterID'
     21 
     22 # Values are from platform/system_api/dbus/debugd/dbus-constants.h.
     23 _CUPS_SUCCESS = 0
     24 
     25 class platform_AddPrinter(test.test):
     26     """
     27     Chrome is brought up, and a cups printer that requires the epson
     28     driver to be downloaded as a component is configured.  The test verifies
     29     that the component is downloaded and a subsequent print command works.
     30     """
     31     version = 1
     32 
     33     def initialize(self, ppd_file):
     34         """
     35         Args:
     36         @param ppd_file: ppd file name
     37         """
     38 
     39         # Instantiate Chrome browser.
     40         with tempfile.NamedTemporaryFile() as cap:
     41             file_utils.download_file(chrome.CAP_URL, cap.name)
     42             password = cap.read().rstrip()
     43 
     44         extra_flags = ['--enable-features=CrOSComponent']
     45         self.browser = chrome.Chrome(gaia_login=False,
     46                                      username=chrome.CAP_USERNAME,
     47                                      password=password,
     48                                      extra_browser_args=extra_flags)
     49         self.tab = self.browser.browser.tabs[0]
     50 
     51         # Set file path.
     52         current_dir = os.path.dirname(os.path.realpath(__file__))
     53         self.pdf_path = os.path.join(current_dir,
     54                            'to_print.pdf')
     55         self.printing_log_path = '/tmp/printing_request.log'
     56 
     57         # Download ppd files
     58         self.ppd_file = '/tmp/%s' % ppd_file
     59         file_utils.download_file(
     60             'https://storage.googleapis.com/chromiumos-test-assets-public'
     61             '/platform_AddPrinter/%s' % ppd_file,
     62             self.ppd_file);
     63 
     64         # Start fake printer.
     65         printer = FakePrinter()
     66         self.server_thread = Thread(target = printer.start,
     67                                args = (self.printing_log_path, ))
     68         self.server_thread.start();
     69 
     70     def cleanup(self):
     71         """
     72         Delete downloaded ppd file, fake printer log file, component (if
     73         downloaded);
     74         """
     75         # Remove component.
     76         if hasattr(self, 'component'):
     77           self.delete_component(self.component)
     78 
     79         # Close browser.
     80         if hasattr(self, 'browser'):
     81             self.browser.close()
     82 
     83         # Remove temp files.
     84         if os.path.exists(self.ppd_file):
     85           os.remove(self.ppd_file)
     86         if os.path.exists(self.printing_log_path):
     87           os.remove(self.printing_log_path)
     88 
     89     def load_ppd(self, ppd_path):
     90         """
     91         Returns the contents of a file as a dbus.ByteArray.
     92 
     93         @param file_name: The path of the file.
     94 
     95         """
     96         with open(ppd_path, 'rb') as f:
     97             content = dbus.ByteArray(f.read())
     98             return content
     99 
    100     def add_a_printer(self, ppd_path):
    101         """
    102         Add a printer manually given ppd file.
    103 
    104         Args:
    105         @param ppd_path: path to ppd file
    106 
    107         @raises: error.TestFail if could not setup a printer
    108         """
    109         logging.info('add printer from ppd:' + ppd_path);
    110 
    111         ppd_contents = self.load_ppd(ppd_path)
    112         result = debugd_util.iface().CupsAddManuallyConfiguredPrinter(
    113                                      _FAKE_PRINTER_ID, 'socket://127.0.0.1/',
    114                                                       ppd_contents)
    115         if result != _CUPS_SUCCESS:
    116             raise error.TestFail('valid_config - Could not setup valid '
    117                 'printer %d' % result)
    118 
    119     def print_a_page(self, golden_file_path):
    120         """
    121         Print a page and check print request output
    122 
    123         Args:
    124         @param golden_file_path: path to printing request golden file.
    125 
    126         @raises: error.TestFail if printing request generated cannot be
    127         verified.
    128         """
    129 
    130         # Issue print request.
    131         utils.system_output(
    132             'lp -d %s %s' %
    133             (_FAKE_PRINTER_ID, self.pdf_path)
    134         );
    135         self.server_thread.join(_FAKE_SERVER_JOIN_TIMEOUT)
    136 
    137         # Verify print request with a golden file.
    138         output = utils.system_output(
    139             'cmp %s %s' % (self.printing_log_path, golden_file_path)
    140         )
    141         if output:
    142             raise error.TestFail('ERROR: Printing request is not verified!')
    143         logging.info('cmp output:' + output);
    144 
    145 
    146     def delete_component(self, component):
    147         """
    148         Delete filter component via dbus API
    149 
    150         Args:
    151         @param component: name of component
    152         """
    153         logging.info('delete component:' + component);
    154 
    155         dbus_send.dbus_send(
    156             'org.chromium.ComponentUpdaterService',
    157             'org.chromium.ComponentUpdaterService',
    158             '/org/chromium/ComponentUpdaterService',
    159             'UnloadComponent',
    160             timeout_seconds=20,
    161             user='root',
    162             args=[dbus.String(component)])
    163 
    164     def download_component(self, component):
    165         """
    166         Download filter component via dbus API
    167 
    168         Args:
    169         @param component: name of component
    170 
    171         @raises: error.TestFail is component is not loaded.
    172         """
    173         logging.info('download component:' + component);
    174 
    175         res = dbus_send.dbus_send(
    176             'org.chromium.ComponentUpdaterService',
    177             'org.chromium.ComponentUpdaterService',
    178             '/org/chromium/ComponentUpdaterService',
    179             'LoadComponent',
    180             timeout_seconds=20,
    181             user='root',
    182             args=[dbus.String(component)])
    183 
    184         if res.response == '':
    185           raise error.TestFail('Component could not be loaded.')
    186 
    187     def run_once(self, golden_file, component=None):
    188         """
    189         Args:
    190         @param golden_file: printing request golden file name
    191         """
    192         if component:
    193             self.component = component
    194             self.download_component(self.component)
    195 
    196         current_dir = os.path.dirname(os.path.realpath(__file__))
    197         self.add_a_printer(self.ppd_file)
    198         self.print_a_page(os.path.join(current_dir, golden_file));
    199