Home | History | Annotate | Download | only in firmware_TouchMTB
      1 # Copyright (c) 2012 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 """Some utility classes and functions."""
      6 
      7 import glob
      8 import os
      9 import re
     10 import sys
     11 import time
     12 
     13 import common_util
     14 import test_conf as conf
     15 
     16 
     17 def get_display_name():
     18     """Return the display name."""
     19     return ':0'
     20 
     21 
     22 def get_screen_size():
     23     """Get the screen size using xwininfo."""
     24     cmd = 'DISPLAY=:0 xwininfo -root'
     25     wininfo = common_util.simple_system_output(cmd)
     26     # the geometry string looks like:
     27     #     "  -geometry 3840x1200+0+0"
     28     geometry_pattern = re.compile('\s*-geometry\s*(\d+)x(\d+)+.*', re.I)
     29     for line in wininfo.splitlines():
     30         result = geometry_pattern.search(line)
     31         if result:
     32             width = int(result.group(1))
     33             height = int(result.group(2))
     34             return (width, height)
     35     return None
     36 
     37 
     38 def get_current_time_str():
     39     """Get the string of current time."""
     40     time_format = '%Y%m%d_%H%M%S'
     41     return time.strftime(time_format, time.gmtime())
     42 
     43 
     44 def get_board():
     45     """Get board of the Chromebook machine."""
     46     with open('/etc/lsb-release') as lsb:
     47         context = lsb.read()
     48     board = None
     49     if context is not None:
     50         for line in context.splitlines():
     51             if line.startswith('CHROMEOS_RELEASE_BOARD'):
     52                 board_str = line.split('=')[1]
     53                 if '-' in board_str:
     54                     board = board_str.split('-')[1]
     55                 elif '_' in board_str:
     56                     board = board_str.split('_')[1]
     57                 else:
     58                     board = board_str
     59                 # Some boards, e.g. alex, may have board name as alex32
     60                 board = re.search('(\D+)\d*', board, re.I).group(1)
     61                 break
     62     return board
     63 
     64 
     65 def get_board_from_filename(filename):
     66     """Get the board name from a given string which is usually a log file.
     67 
     68     A log file looks like:
     69         touch_firmware_report-lumpy-fw_11.27-complete-20130610_150540.log
     70 
     71     @param filename: the filename used to extract the board
     72     """
     73     pieces = filename.split('-')
     74     return pieces[1] if len(pieces) >= 2 else None
     75 
     76 def get_board_from_directory(directory):
     77     """Get the board name from the log in the replay directory.
     78 
     79     @param directory: the log directory
     80     """
     81     log_files = glob.glob(os.path.join(conf.log_root_dir, directory, '*.log'))
     82     for log_file in log_files:
     83         board = get_board_from_filename(os.path.basename(log_file))
     84         if board:
     85             return board
     86     return None
     87 
     88 
     89 def get_cpu():
     90     """Get the processor of the machine."""
     91     return common_util.simple_system_output('uname -m')
     92 
     93 
     94 def install_pygtk():
     95     """A temporary dirty hack of installing pygtk related packages."""
     96     pygtk_dict = {'x86_64': ['pygtk_x86_64.tbz2', 'lib64'],
     97                   'i686': ['pygtk_x86_32.tbz2', 'lib'],
     98                   'armv7l': ['pygtk_armv7l.tbz2', 'lib'],
     99     }
    100     pygtk_info = pygtk_dict.get(get_cpu().lower())
    101 
    102     if get_board() is None:
    103         print 'This does not look like a chromebook.'
    104     elif pygtk_info:
    105         cmd_remount = 'mount -o remount,rw /'
    106         if common_util.simple_system(cmd_remount) == 0:
    107             pygtk_tarball, lib_path = pygtk_info
    108             cmd_untar = 'tar -jxf pygtk/%s -C /' % pygtk_tarball
    109             if common_util.simple_system(cmd_untar) == 0:
    110                 # Need to add the gtk path manually. Otherwise, the path
    111                 # may not be in the sys.path for the first time when the
    112                 # tarball is extracted.
    113                 gtk_path = ('/usr/local/%s/python2.7/site-packages/gtk-2.0' %
    114                             lib_path)
    115                 sys.path.append(gtk_path)
    116                 print 'Successful installation of pygtk.'
    117                 return True
    118             else:
    119                 print 'Error: Failed to install pygtk.'
    120         else:
    121             print 'Failed to remount. Have you removed the write protect?'
    122     else:
    123         print 'The pygtk is only supported for %s so far.' % pygtk_dict.keys()
    124         print 'The other cpus will be supported on demand.'
    125         print 'The plan is to remove gtk totally and upgrade to Chrome browser.'
    126     return False
    127 
    128 
    129 def get_fw_and_date(filename):
    130     """Get the firmware version and the test date from a log directory
    131        or a log file.
    132 
    133     An example html filename looks like
    134         'touch_firmware_report-link-fw_1.0.170-manual-20130426_064849.log'
    135         return (fw_1.0.170, 20130426_064849)
    136 
    137     An example log directory looks like
    138         '20130422_020631-fw_1.0.170-manual'
    139         return (fw_1.0.170, 20130422_020631)
    140     """
    141     # The firmware could be fw_1.0.170 or fw_1.0.AA which always comes with
    142     # 'fw_' as its prefix. The character '-' is used to separate components
    143     # in the filename.
    144     result = re.search('-(%s[^-]+?)-' % conf.fw_prefix, filename)
    145     fw = result.group(1) if result else None
    146 
    147     result = re.search('(\d{8}_\d{6})[-.]', filename)
    148     date = result.group(1) if result else None
    149 
    150     return (fw, date)
    151 
    152 
    153 def create_log_dir(firmware_version, mode):
    154     """Create a directory to save the report and device event files."""
    155     dir_basename = conf.filename.sep.join([get_current_time_str(),
    156                                            conf.fw_prefix + firmware_version,
    157                                            mode])
    158     log_root_dir = conf.log_root_dir
    159     log_dir = os.path.join(log_root_dir, dir_basename)
    160     latest_symlink = os.path.join(log_root_dir, 'latest')
    161 
    162     # Create the log directory.
    163     try:
    164         os.makedirs(log_dir)
    165     except OSError, e:
    166         print 'Error in create the directory (%s): %s' % (log_dir, e)
    167         sys.exit(1)
    168 
    169     # Set up the latest symbolic link to the newly created log directory.
    170     try:
    171         if os.path.islink(latest_symlink):
    172             os.remove(latest_symlink)
    173         os.symlink(log_dir, latest_symlink)
    174     except OSError, e:
    175         print 'Error in setup latest symlink (%s): %s' % (latest_symlink, e)
    176         sys.exit(1)
    177     return log_dir
    178 
    179 
    180 def stop_power_management():
    181     """Stop the power daemon management."""
    182     ret_d = common_util.simple_system('stop -q powerd')
    183     if ret_d:
    184         print 'Error in stopping powerd.'
    185         print 'The screen may dim during the test.'
    186 
    187 
    188 def start_power_management():
    189     """Start the power daemon management."""
    190     ret_d = common_util.simple_system('start -q powerd')
    191     if ret_d:
    192         print 'Error in starting powerd.'
    193         print 'The screen may not go into suspend mode.'
    194         print 'If this is a problem, you could reboot the machine.'
    195 
    196 
    197 class GestureList:
    198     """A class defines the gesture list."""
    199 
    200     def __init__(self, gesture_names=None):
    201         self.gesture_names = (gesture_names if gesture_names
    202                                             else conf.gesture_names_complete)
    203 
    204     def get_gesture_list(self, key=None):
    205         """Get the list of Gesture objects based on the gesture names."""
    206         gesture_dict = conf.get_gesture_dict()
    207         gesture_list = []
    208         for name in self.gesture_names:
    209             gesture = gesture_dict.get(name)
    210             if gesture is None:
    211                 msg = 'Error: the gesture "%s" is not defined in the config.'
    212                 print msg % name
    213                 return []
    214             gesture_list.append(gesture)
    215         return sorted(gesture_list, key=key) if key else gesture_list
    216 
    217 
    218 class Output:
    219     """A class to handle outputs to the window and to the report."""
    220     def __init__(self, log_dir, report_name, win, report_html):
    221         self.log_dir = log_dir
    222         self.report_name = report_name
    223         self.report = open(report_name, 'w')
    224         self.win = win
    225         self.prefix_space = ' ' * 4
    226         self.msg = None
    227         self.report_html = report_html
    228 
    229     def __del__(self):
    230         self.stop()
    231 
    232     def stop(self):
    233         """Close the report file and print it on stdout."""
    234         self.report.close()
    235         with open(self.report_name) as f:
    236             for line in f.read().splitlines():
    237                 print line
    238         report_msg = '\n*** This test report is saved in the file: %s\n'
    239         print report_msg % self.report_name
    240 
    241     def get_prefix_space(self):
    242         """Get the prefix space when printing the report."""
    243         return self.prefix_space
    244 
    245     def print_report_line(self, msg):
    246         """Print the line with proper indentation."""
    247         self.report.write(self.prefix_space + str(msg) + os.linesep)
    248 
    249     def print_window(self, msg):
    250         """Print the message to the result window."""
    251         if type(msg) is list:
    252             msg = os.linesep.join(msg)
    253         self.win.set_result(msg)
    254         print msg
    255 
    256     def _print_report(self, msg):
    257         """Print the message to the report."""
    258         if type(msg) is list:
    259             for line in msg:
    260                 self.print_report_line(line)
    261         else:
    262             self.print_report_line(msg)
    263 
    264     def buffer_report(self, msg):
    265         """Buffer the message and print it later if not over-written.
    266 
    267         Usage of the method: the validator test result of a gesture may
    268         be discarded because the user chooses to re-perform the gesture
    269         again. So it should be able to over-write the message.
    270         """
    271         self.msg = msg
    272 
    273     def flush_report(self):
    274         """Print the buffered message if any."""
    275         if self.msg:
    276             self._print_report(self.msg)
    277             self.msg = None
    278 
    279     def print_report(self, msg):
    280         """Print the message to the report."""
    281         # Print any buffered message first.
    282         self.flush_report()
    283         # Print this incoming message
    284         self._print_report(msg)
    285 
    286     def print_all(self, msg):
    287         """Print the message to both report and to the window."""
    288         self.print_window(msg)
    289         self.buffer_report(msg)
    290 
    291 
    292 class ScreenShot:
    293     """Handle screen shot."""
    294 
    295     def __init__(self, geometry_str):
    296         self.geometry_str = geometry_str
    297         environment_str = 'DISPLAY=:0.0 XAUTHORITY=/home/chronos/.Xauthority '
    298         dump_util = '/usr/local/bin/import -quality 20'
    299         self.dump_window_format = ' '.join([environment_str, dump_util,
    300                                            '-window %s %s.png'])
    301         self.dump_root_format = ' '.join([environment_str, dump_util,
    302                                          '-window root -crop %s %s.png'])
    303         self.get_id_cmd = 'DISPLAY=:0 xwininfo -root -tree'
    304 
    305     def dump_window(self, filename):
    306         """Dump the screenshot of a window to the specified file name."""
    307         win_id = self._get_win_id()
    308         if win_id:
    309             dump_cmd = self.dump_window_format % (win_id, filename)
    310             common_util.simple_system(dump_cmd)
    311         else:
    312             print 'Warning: cannot get the window id.'
    313 
    314     def dump_root(self, filename):
    315         """Dump the screenshot of root to the specified file name."""
    316         dump_cmd = self.dump_root_format % (self.geometry_str, filename)
    317         common_util.simple_system(dump_cmd)
    318 
    319     def _get_win_id(self):
    320         """Get the window ID based on the characteristic string."""
    321         result = common_util.simple_system_output(self.get_id_cmd)
    322         for line in result.splitlines():
    323             if self.geometry_str in line:
    324                 return line.split()[0].strip()
    325         return None
    326