1# Copyright (c) 2013 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 logging 6import os 7import sys 8 9from autotest_lib.client.bin import test 10from autotest_lib.client.common_lib import error 11from autotest_lib.client.cros import p2p_utils 12from autotest_lib.client.cros.netprotos import cros_p2p, zeroconf 13 14 15class p2p_ShareFiles(test.test): 16 """The P2P Server class tester. 17 18 This class runs the p2p service (p2p-server and p2p-http-server) and checks 19 that the DUT is sharing the files on the network. 20 """ 21 version = 1 22 23 def setup(self): 24 self.job.setup_dep(['lansim']) 25 26 27 def initialize(self): 28 dep = 'lansim' 29 dep_dir = os.path.join(self.autodir, 'deps', dep) 30 logging.info('lansim is at %s', dep_dir) 31 self.job.install_pkg(dep, 'dep', dep_dir) 32 33 # Import the lansim modules installed on lansim/build/ 34 sys.path.append(os.path.join(dep_dir, 'build')) 35 36 self._p2p = p2p_utils.P2PServerOverTap() 37 38 39 def cleanup(self): 40 self._p2p.cleanup() 41 42 43 def _run_lansim_loop(self, timeout=None, until=None): 44 """Run the Simulator main loop for a given time.""" 45 try: 46 self._sim.run(timeout=timeout, until=until) 47 except Exception, e: 48 logging.exception('Simulator ended with an exception:') 49 raise error.TestError('Simulator ended with an exception: %r' % e) 50 51 52 def run_once(self): 53 from lansim import simulator, host 54 55 # Setup the environment where avahi-daemon runs during the test. 56 try: 57 self._p2p.setup() 58 except: 59 logging.exception('Failed to start tested services.') 60 raise 61 62 self._sim = simulator.Simulator(self._p2p.tap) 63 # Create a single fake peer that will be sending the multicast requests. 64 peer = host.SimpleHost(self._sim, '94:EB:2C:00:00:61', '169.254.10.97') 65 66 # Run a userspace implementation of avahi + p2p-client on the fake 67 # host. This will use the P2P services exported by the DUT. 68 zero = zeroconf.ZeroconfDaemon(peer, 'a-peer') 69 p2pcli = cros_p2p.CrosP2PClient(zero) 70 71 # On p2p-server startup, it should announce the service even if we 72 # aren't sharing any file. Usually it doesn't take more than 2 seconds 73 # to start announcing the service, repeated a few times. 74 self._run_lansim_loop(timeout=20, until=p2pcli.get_peers()) 75 # Check that we see the DUT on the list of peers. 76 peers = p2pcli.get_peers() 77 if len(peers) != 1: 78 logging.info('Found peers: %r', peers) 79 raise error.TestFail('Expected one peer (the DUT) but %d found.' % 80 len(peers)) 81 82 # Check that the announced information is correct. 83 peer_name, _hostname, ips, port = peers[0] 84 if len(ips) != 1 or ips[0] != self._p2p.tap.addr: 85 logging.info('Peer ips: %r', ips) 86 raise error.TestFail('Found wrong peer IP address on the DUT.') 87 if port != cros_p2p.CROS_P2P_PORT: 88 logging.info('Peer p2p port is: %r', port) 89 raise error.TestFail('Found wrong p2p port exported on the DUT.') 90 91 files = p2pcli.get_peer_files(peer_name) 92 if files: 93 logging.info('Peer files: %r', files) 94 raise error.TestFail('Found exported files on the DUT.') 95 96 num_connections = p2pcli.get_peer_connections(peer_name) 97 if num_connections: 98 logging.info('Peer connections: %r', num_connections) 99 raise error.TestFail('DUT already has p2p connections.') 100 101 # Share a small file and check that it is broadcasted. 102 with open(os.path.join(p2p_utils.P2P_SHARE_PATH, 'my_file=HASH==.p2p'), 103 'w') as f: 104 f.write('0123456789') 105 106 # Run the loop until the file is shared. Normally, the p2p-server takes 107 # up to 1 second to detect a change on the shared directory and 108 # announces it right away a few times. Wait until the file is announced, 109 # what should not take more than a few seconds. If after 30 seconds the 110 # files isn't announced, that is an error. 111 self._run_lansim_loop(timeout=30, 112 until=lambda: p2pcli.get_peer_files(peer_name)) 113 114 files = p2pcli.get_peer_files(peer_name) 115 if files != [('my_file=HASH==', 10)]: 116 logging.info('Peer files: %r', files) 117 raise error.TestFail('Expected exported file on the DUT.') 118 119 # Test that the DUT replies to active requests. 120 zero.clear_cache() 121 p2pcli.start_query() 122 # A query can be replied by several peers after it is send, but there's 123 # no one-to-one mapping between these two. A query simply forces other 124 # peers to send the requested information shortly after. Thus, here we 125 # just wait a few seconds until we decide that the query timeouted. 126 self._run_lansim_loop(timeout=3) 127 p2pcli.stop_query() 128 129 files = p2pcli.get_peer_files(peer_name) 130 if files != [('my_file=HASH==', 10)]: 131 logging.info('Peer files: %r', files) 132 raise error.TestFail('Expected exported file on the DUT.') 133