Home | History | Annotate | Download | only in hardware_UsbBasicFileOperations
      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 import os
      6 from autotest_lib.client.bin import utils
      7 from autotest_lib.client.cros import storage as storage_mod
      8 from autotest_lib.client.common_lib import autotemp, error
      9 
     10 
     11 class hardware_UsbBasicFileOperations(storage_mod.StorageTester):
     12     version = 1
     13     preserve_srcdir = True
     14     _src, _dst = None, None
     15 
     16 
     17     def run_once(self, volume_filter={'bus':'usb'}):
     18         storage = self.wait_for_device(volume_filter, cycles=1,
     19                                        mount_volume=True)[0]
     20         mount_point = storage['mountpoint']
     21 
     22         # -> Megabytes
     23         size = 1*1024*1024
     24 
     25         self._src = autotemp.tempfile(unique_id='tmpfile',
     26                                       dir=mount_point)
     27         self._dst = autotemp.tempfile(unique_id='autotest',
     28                                       dir=self.tmpdir)
     29         # Step 1: check if file creation works
     30         try:
     31             storage_mod.create_file(self._src.name, size)
     32         except error.CmdError, e:
     33             msg = ('fatal error occurred during file creation: '
     34                    'basic file operation failed: %s' % e)
     35             raise error.TestFail(msg)
     36 
     37         # not part of current check, remember the value for later use
     38         src_md5 = storage_mod.checksum_file(self._src.name)
     39 
     40         # Step 2: check if open works
     41         try:
     42             f = open(self._src.name, 'rb')
     43         except Exception, e:
     44             msg = ('fatal error occurred during open(): '
     45                    'basic file operation failed: %s' % e)
     46             raise error.TestFail(msg)
     47 
     48         try:
     49             f.read()
     50         except Exception, e:
     51             msg = ('fatal error occurred during read(): '
     52                    'basic file operation failed: %s' % e)
     53             raise error.TestFail(msg)
     54 
     55         try:
     56             f.close()
     57         except Exception, e:
     58             msg = ('fatal error occurred during close(): '
     59                    'basic file operation failed: %s' % e)
     60             raise error.TestFail(msg)
     61 
     62 
     63         # Step 3: check if file copy works
     64         try:
     65             utils.force_copy(self._src.name, self._dst.name)
     66         except Exception, e:
     67             msg = ('fatal error occurred during a file copy: '
     68                    'basic file operation failed: %s' % e)
     69             raise error.TestFail(msg)
     70 
     71         if src_md5 != storage_mod.checksum_file(self._dst.name):
     72             msg = ('fatal error occurred during a file copy, '
     73                    'md5 from origin and from destination are different: '
     74                    'basic file operation failed')
     75             raise error.TestFail(msg)
     76 
     77 
     78         # Step 4: check if file removal works
     79         try:
     80             os.remove(self._src.name)
     81         except OSError, e:
     82             msg = ('fatal error occurred during file removal: '
     83                    'basic file operation failed: %s' % e)
     84             raise error.TestFail(msg)
     85 
     86         if os.path.isfile(self._src.name):
     87             msg = ('fatal error occurred during file removal: '
     88                    'file still present after command, '
     89                    'basic file operation failed')
     90             raise error.TestFail(msg)
     91 
     92         utils.drop_caches()
     93 
     94         if os.path.isfile(self._src.name):
     95             msg = ('fatal error occurred during file removal: '
     96                    'file still present after command issued and '
     97                    'disk cached flushed), '
     98                    'basic file operation failed')
     99             raise error.TestFail(msg)
    100 
    101         # Step 5: check if modification to a file are persistent
    102         # copy file, modify src and modify dst the same way, checksum
    103         storage_mod.create_file(self._src.name, size)
    104         utils.force_copy(self._src.name, self._dst.name)
    105 
    106         # apply the same change to both files (which are identical in origin)
    107         src_md5 = modify_file(self._src.name)
    108         dst_md5 = modify_file(self._dst.name)
    109 
    110         # both copy of they file have to be the same
    111         if src_md5 != dst_md5:
    112             msg = ('fatal error occurred after modifying src and dst: '
    113                    'md5 checksums differ - %s / %s ,'
    114                    'basic file operation failed' % (src_md5, dst_md5))
    115             raise error.TestFail(msg)
    116 
    117 
    118     def cleanup(self):
    119         if self._src:
    120             self._src.clean()
    121         if self._dst:
    122             self._dst.clean()
    123 
    124         self.scanner.unmount_all()
    125 
    126         super(hardware_UsbBasicFileOperations, self).cleanup()
    127 
    128 
    129 def modify_file(path):
    130     '''Modify a file returning its new MD5
    131 
    132     Open |path|, change a byte within the file and return the new md5.
    133 
    134     The change applied to the file is based on the file content and size.
    135     This means that identical files will result in identical changes and thus
    136     will return the same MD5.
    137 
    138     @param path: a path to the file to be modified
    139     @return the MD5 of |path| after the modification
    140     '''
    141     position = os.path.getsize(path) / 2
    142 
    143     # modify the file means: read a char, increase its value and write it back
    144     # given the same file (identical in size and bytes) it will apply the same
    145     # change
    146     f = open(path, 'r+b')
    147     f.seek(position)
    148     c = f.read(1)
    149     f.seek(position)
    150     f.write(chr(ord(c)+1))
    151     f.close()
    152     return storage_mod.checksum_file(path)
    153