xref: /aosp_15_r20/external/autotest/server/site_tests/p2p_EndToEndTest/p2p_EndToEndTest.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1# Lint as: python2, python3
2# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import logging
7import os
8
9from autotest_lib.client.common_lib import error
10from autotest_lib.client.common_lib import utils
11from autotest_lib.server import test
12
13DEFAULT_AVAHI_SIZE_UPDATE_DELAY = 10
14
15# P2P_PATH is the path where the p2p server expects the sharing files.
16P2P_PATH = '/var/cache/p2p'
17
18# Prefix all the test files with P2P_TEST_PREFIX.
19P2P_TEST_PREFIX = 'p2p-test'
20
21# Kilobyte.
22KB = 1024
23
24# File size of the shared file in MB.
25P2P_FILE_SIZE_MB = 4 * KB * KB
26P2P_FILE_SPLIT_SIZE_KB = P2P_FILE_SIZE_MB // (2 * KB)
27
28# After a peer finishes the download we need it to keep serving the file for
29# other peers. This peer will then wait up to P2P_SERVING_TIMEOUT_SECS seconds
30# for the test to conclude.
31P2P_SERVING_TIMEOUT_SECS = 300
32
33
34class p2p_EndToEndTest(test.test):
35    """Test to check that p2p works."""
36    version = 1
37
38
39    def run_once(self, dut, file_id, companions):
40        self._dut = dut
41        self._companion = companions[0]
42
43        file_id = '%s-%s' % (P2P_TEST_PREFIX, file_id)
44        file_temp_name = os.path.join(P2P_PATH, file_id + '.tmp')
45        file_shared_name = os.path.join(P2P_PATH, file_id + '.p2p')
46
47        logging.info('File ID: %s', file_id)
48
49        # Setup dut and companion.
50        for host in [self._dut, self._companion]:
51            # Ensure that p2p is running.
52            host.run('start p2p || true')
53            host.run('status p2p | grep running')
54
55        # Prepare an empty file to share and specify its final size via the
56        # "user.cros-p2p-filesize" attribute.
57        logging.info('All devices setup. Generating a file on main DUT')
58        dut.run('touch %s' % file_temp_name)
59        dut.run('setfattr -n user.cros-p2p-filesize -v %d %s' %
60                (P2P_FILE_SIZE_MB, file_temp_name))
61        dut.run('mv %s %s' % (file_temp_name, file_shared_name))
62
63        # Generate part of the files total file fize.
64        dut.run('dd if=/dev/zero of=%s bs=%d count=%d' %
65                (file_shared_name, KB, P2P_FILE_SPLIT_SIZE_KB))
66
67        def _wait_until_avahi_size_update():
68            ret = ''
69            try:
70                ret = self._companion.run(
71                        'p2p-client --get-url=%s --minimum-size=%d' %
72                        (file_id, P2P_FILE_SPLIT_SIZE_KB * KB))
73                ret = ret.stdout.strip()
74            except:
75                return False
76            return ret != ''
77
78        err = 'Shared file size did not update in time.'
79        # The actual delay is 10 seconds, so triple that to account for flakes.
80        utils.poll_for_condition(condition=_wait_until_avahi_size_update,
81                                 timeout=DEFAULT_AVAHI_SIZE_UPDATE_DELAY * 3,
82                                 exception=error.TestFail(err))
83
84        # Now thhe companion can attempt a p2p file download.
85        logging.info('Listing all p2p peers for the companion: ')
86        logging.info(self._companion.run('p2p-client --list-all').stdout)
87        ret = self._companion.run('p2p-client --get-url=%s' % file_id,
88                                  ignore_status=True)
89        url = ret.stdout.strip()
90
91        if not url:
92            raise error.TestFail(
93                    'p2p-client on companion returned an empty URL.')
94        else:
95            logging.info('Companion using URL %s.', url)
96            logging.info(
97                    'Companion downloading the file from main DUT via p2p in the background.'
98            )
99            self._companion.run_background('curl %s -o %s' %
100                                           (url, file_shared_name),
101                                           verbose=True)
102
103        logging.info(
104                'While companion is downloading the file, we will expand it to its full size.'
105        )
106        dut.run('dd if=/dev/zero of=%s bs=%d count=%d'
107                ' conv=notrunc oflag=append' %
108                (file_shared_name, KB, P2P_FILE_SPLIT_SIZE_KB))
109
110        # Calculate the SHA1 (160 bits -> 40 characters when
111        # hexencoded) of the generated file.
112        ret = dut.run('sha1sum %s' % file_shared_name)
113        sha1_main = ret.stdout.strip()[0:40]
114        logging.info('SHA1 of main is %s', sha1_main)
115        sha1_companion = ''
116        logging.info(
117                'Waiting for companion to finish downloading file so we can compare SHA1 values'
118        )
119
120        def _shas_match():
121            """Returns true when the SHA1 of the file matches on DUT and companion."""
122            ret = self._companion.run('sha1sum %s' % file_shared_name)
123            sha1_companion = ret.stdout.strip()[0:40]
124            logging.debug(sha1_companion)
125            return sha1_main == sha1_companion
126
127        err = "Main DUT's SHA1 (%s) doesn't match companions's SHA1 (%s)." % (
128                sha1_main, sha1_companion)
129        utils.poll_for_condition(condition=_shas_match,
130                                 timeout=P2P_SERVING_TIMEOUT_SECS,
131                                 exception=error.TestFail(err))
132
133    def cleanup(self):
134        # Clean the test environment and stop sharing this file.
135        for host in [self._dut, self._companion]:
136            host.run('rm -f %s/%s-*.p2p' % (P2P_PATH, P2P_TEST_PREFIX))
137            host.run('stop p2p')
138