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