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 5import os 6from autotest_lib.client.bin import utils 7from autotest_lib.client.cros import storage as storage_mod 8from autotest_lib.client.common_lib import autotemp, error 9 10 11class 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 129def 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