# Lint as: python2, python3 # Copyright (c) 2013 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import logging import os from autotest_lib.client.common_lib import error from autotest_lib.client.common_lib import utils from autotest_lib.server import test DEFAULT_AVAHI_SIZE_UPDATE_DELAY = 10 # P2P_PATH is the path where the p2p server expects the sharing files. P2P_PATH = '/var/cache/p2p' # Prefix all the test files with P2P_TEST_PREFIX. P2P_TEST_PREFIX = 'p2p-test' # Kilobyte. KB = 1024 # File size of the shared file in MB. P2P_FILE_SIZE_MB = 4 * KB * KB P2P_FILE_SPLIT_SIZE_KB = P2P_FILE_SIZE_MB // (2 * KB) # After a peer finishes the download we need it to keep serving the file for # other peers. This peer will then wait up to P2P_SERVING_TIMEOUT_SECS seconds # for the test to conclude. P2P_SERVING_TIMEOUT_SECS = 300 class p2p_EndToEndTest(test.test): """Test to check that p2p works.""" version = 1 def run_once(self, dut, file_id, companions): self._dut = dut self._companion = companions[0] file_id = '%s-%s' % (P2P_TEST_PREFIX, file_id) file_temp_name = os.path.join(P2P_PATH, file_id + '.tmp') file_shared_name = os.path.join(P2P_PATH, file_id + '.p2p') logging.info('File ID: %s', file_id) # Setup dut and companion. for host in [self._dut, self._companion]: # Ensure that p2p is running. host.run('start p2p || true') host.run('status p2p | grep running') # Prepare an empty file to share and specify its final size via the # "user.cros-p2p-filesize" attribute. logging.info('All devices setup. Generating a file on main DUT') dut.run('touch %s' % file_temp_name) dut.run('setfattr -n user.cros-p2p-filesize -v %d %s' % (P2P_FILE_SIZE_MB, file_temp_name)) dut.run('mv %s %s' % (file_temp_name, file_shared_name)) # Generate part of the files total file fize. dut.run('dd if=/dev/zero of=%s bs=%d count=%d' % (file_shared_name, KB, P2P_FILE_SPLIT_SIZE_KB)) def _wait_until_avahi_size_update(): ret = '' try: ret = self._companion.run( 'p2p-client --get-url=%s --minimum-size=%d' % (file_id, P2P_FILE_SPLIT_SIZE_KB * KB)) ret = ret.stdout.strip() except: return False return ret != '' err = 'Shared file size did not update in time.' # The actual delay is 10 seconds, so triple that to account for flakes. utils.poll_for_condition(condition=_wait_until_avahi_size_update, timeout=DEFAULT_AVAHI_SIZE_UPDATE_DELAY * 3, exception=error.TestFail(err)) # Now thhe companion can attempt a p2p file download. logging.info('Listing all p2p peers for the companion: ') logging.info(self._companion.run('p2p-client --list-all').stdout) ret = self._companion.run('p2p-client --get-url=%s' % file_id, ignore_status=True) url = ret.stdout.strip() if not url: raise error.TestFail( 'p2p-client on companion returned an empty URL.') else: logging.info('Companion using URL %s.', url) logging.info( 'Companion downloading the file from main DUT via p2p in the background.' ) self._companion.run_background('curl %s -o %s' % (url, file_shared_name), verbose=True) logging.info( 'While companion is downloading the file, we will expand it to its full size.' ) dut.run('dd if=/dev/zero of=%s bs=%d count=%d' ' conv=notrunc oflag=append' % (file_shared_name, KB, P2P_FILE_SPLIT_SIZE_KB)) # Calculate the SHA1 (160 bits -> 40 characters when # hexencoded) of the generated file. ret = dut.run('sha1sum %s' % file_shared_name) sha1_main = ret.stdout.strip()[0:40] logging.info('SHA1 of main is %s', sha1_main) sha1_companion = '' logging.info( 'Waiting for companion to finish downloading file so we can compare SHA1 values' ) def _shas_match(): """Returns true when the SHA1 of the file matches on DUT and companion.""" ret = self._companion.run('sha1sum %s' % file_shared_name) sha1_companion = ret.stdout.strip()[0:40] logging.debug(sha1_companion) return sha1_main == sha1_companion err = "Main DUT's SHA1 (%s) doesn't match companions's SHA1 (%s)." % ( sha1_main, sha1_companion) utils.poll_for_condition(condition=_shas_match, timeout=P2P_SERVING_TIMEOUT_SECS, exception=error.TestFail(err)) def cleanup(self): # Clean the test environment and stop sharing this file. for host in [self._dut, self._companion]: host.run('rm -f %s/%s-*.p2p' % (P2P_PATH, P2P_TEST_PREFIX)) host.run('stop p2p')