1f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidouimport os, logging 2f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 3f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidoufrom autotest_lib.client.bin import utils 4f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidoufrom autotest_lib.client.common_lib import error, autotemp 5f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidoufrom autotest_lib.client.cros import power_status 6f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidoufrom autotest_lib.client.cros import storage as storage_mod 7f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 8f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 9f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidouclass hardware_MultiReaderPowerConsumption(storage_mod.StorageTester): 10f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou version = 1 11f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou _files_to_delete = [] 12f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou _ramdisk_path = None 13f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou _storage = None 14f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 15f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 16f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou def initialize(self): 17f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou super(hardware_MultiReaderPowerConsumption, self).initialize() 18f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 19f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou # Make sure we're not on AC power 20f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou self.status = power_status.get_status() 21f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou if self.status.on_ac(): 22f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou raise error.TestNAError( 23f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 'This test needs to be run with the AC power offline') 24f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 25f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 26f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou def cleanup(self): 27f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou # Remove intermediate files 28f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou for path in self._files_to_delete: 29f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou utils.system('rm -f %s' % path) 30f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 31f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou if self._storage and os.path.ismount(self._storage['mountpoint']): 32f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou self.scanner.umount_volume(storage_dict=self._storage) 33f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 34f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou if self._ramdisk_path and os.path.ismount(self._ramdisk_path.name): 35f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou umount_ramdisk(self._ramdisk_path.name) 36f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou self._ramdisk_path.clean() 37f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 38f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou super(hardware_MultiReaderPowerConsumption, self).cleanup() 39f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 40f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 41f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou def readwrite_test(self, path, size, delete_file=False): 42f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou """Heavy-duty random read/write test. Run `dd` & `tail -f` in parallel 43f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 44f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou The random write is done by writing a file from /dev/urandom into the 45f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou given location, while the random read is done by concurrently reading 46f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou that file. 47f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 48f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou @param path: The directory that will create the test file. 49f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou @param size: Size of the test file, in MiB. 50f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou @param delete_file: Flag the file to be deleted on test exit. 51f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou Otherwise file deletion won't be performed. 52f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou """ 53f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou # Calculate the parameters for dd 54f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou size = 1024*1024*size 55f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou blocksize = 8192 56f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 57f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou # Calculate the filename and full path, flag to delete if needed 58f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou filename = 'tempfile.%d.delete-me' % size 59f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou pathfile = os.path.join(path, filename) 60f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou if delete_file: 61f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou self._files_to_delete.append(pathfile) 62f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 63f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou pid = os.fork() # We need to run two processes in parallel 64f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou if pid: 65f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou # parent 66f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou utils.BgJob('tail -f %s --pid=%s > /dev/null' 67f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou % (pathfile, pid)) 68f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou # Reap the dd child so that tail does not wait for the zombie 69f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou os.waitpid(pid, 0) 70f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou else: 71f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou # child 72f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou utils.system('dd if=/dev/urandom of=%s bs=%d count=%s' 73f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou % (pathfile, blocksize, (size//blocksize))) 74f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou # A forked child is exiting here, so we really do want os._exit: 75f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou os._exit(0) 76f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 77f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 78f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou def run_once(self, ramdisk_size=513, file_size=512, drain_limit=1.05, 79f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou volume_filter={'bus': 'usb'}): 80f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou """Test card reader CPU power consumption to be within acceptable 81f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou range while performing random r/w 82f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 83f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou The random r/w is performed in the readwrite_test() method, by 84f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou concurrently running `dd if=/dev/urandom` and `tail -f`. It is run once 85f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou on a ramdisk with the SD card mounted, then on the SD card with the 86f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou ramdisk unmounted, and then on the SD card with the ramdisk unmounted. 87f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou The measured values are then reported. 88f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 89f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou @param ramdisk_size: Size of ramdisk (in MiB). 90f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou @param file_size: Size of test file (in MiB). 91f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou @param volume_filter: Where to find the card reader. 92f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou @param drain_limit: maximum ratio between the card reader 93f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou energy consumption and each of the two 94f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou ramdisk read/write test energy consumption 95f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou values. 1.00 means the card reader test may 96f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou not consume more energy than either ramdisk 97f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou test, 0.9 means it may consume no more than 98f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 90% of the ramdisk value, and so forth. 99f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou """ 100f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou # Switch to VT2 so the screen turns itself off automatically instead of 101f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou # dimming, in order to reduce the battery consuption caused by other 102f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou # variables. 103f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou utils.system('chvt 2') 104f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 105f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou logging.debug('STEP 1: ensure SD card is inserted and mounted') 106f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou self._storage = self.wait_for_device(volume_filter, cycles=1, 107f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou mount_volume=True)[0] 108f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 109f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou logging.debug('STEP 2: mount the ramdisk') 110f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou self._ramdisk_path = autotemp.tempdir(unique_id='ramdisk', 111f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou dir=self.tmpdir) 112f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou mount_ramdisk(self._ramdisk_path.name, ramdisk_size) 113f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 114f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou # Read current charge, as well as maximum charge. 115f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou self.status.refresh() 116f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou max_charge = self.status.battery[0].charge_full_design 117f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou initial_charge = self.status.battery[0].charge_now 118f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 119f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou logging.debug('STEP 3: perform heavy-duty read-write test on ramdisk') 120f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou self.readwrite_test(self._ramdisk_path.name, file_size) 121f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou # Read current charge (reading A) 122f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou self.status.refresh() 123f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou charge_A = self.status.battery[0].charge_now 124f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 125f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou logging.debug('STEP 4: unmount ramdisk') 126f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou umount_ramdisk(self._ramdisk_path.name) 127f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 128f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou logging.debug('STEP 5: perform identical read write test on SD card') 129f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou self.readwrite_test(self._storage['mountpoint'], file_size, 130f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou delete_file=True) 131f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou # Read current charge (reading B) 132f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou self.status.refresh() 133f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou charge_B = self.status.battery[0].charge_now 134f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 135f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou logging.debug('STEP 6: unmount card') 136f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou self.scanner.umount_volume(storage_dict=self._storage, args='-f -l') 137f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 138f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou logging.debug('STEP 7: perform ramdisk test again') 139f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou mount_ramdisk(self._ramdisk_path.name, ramdisk_size) 140f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou self.readwrite_test(self._ramdisk_path.name, file_size) 141f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou # Read current charge (reading C) 142f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou self.status.refresh() 143f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou charge_C = self.status.battery[0].charge_now 144f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 145f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou # Compute the results 146f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou ramdisk_plus = initial_charge - charge_A 147f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou sd_card_solo = charge_A - charge_B 148f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou ramdisk_solo = charge_B - charge_C 149f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 150f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou sd_card_drain_ratio_a = (sd_card_solo / ramdisk_plus) 151f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou sd_card_drain_ratio_b = (sd_card_solo / ramdisk_solo) 152f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 153f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou msg = None 154f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou if sd_card_drain_ratio_a > drain_limit: 155f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou msg = ('Card reader drain exceeds mounted baseline by > %f (%f)' 156f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou % (drain_limit, sd_card_drain_ratio_a)) 157f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou elif sd_card_drain_ratio_b > drain_limit: 158f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou msg = ('Card reader drain exceeds unmounted baseline by > %f (%f)' 159f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou % (drain_limit, sd_card_drain_ratio_b)) 160f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 161f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou if msg: 162f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou raise error.TestError(msg) 163f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou else: 164f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou fmt = 'Card reader drain ratio Ok: mounted %f; unmounted %f' 165f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou logging.info(fmt % (sd_card_drain_ratio_a, sd_card_drain_ratio_b)) 166f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 167f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 168f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidoudef mount_ramdisk(path, size): 169f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou utils.system('mount -t tmpfs none %s -o size=%sm' % (path, size)) 170f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 171f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 172f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidoudef umount_ramdisk(path): 173f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou """Umount ramdisk mounted at |path| 174f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou 175f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou @param path: the mountpoint for the mountd RAM disk 176f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou """ 177f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou utils.system('rm -rf %s/*' % path) 178f445f429e77e00e37819e06d31de6e2a76c8ab80Vivia Nikolaidou utils.system('umount -f -l %s' % path) 179