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