xref: /aosp_15_r20/external/autotest/client/bin/utils_unittest.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1*9c5db199SXin Li#!/usr/bin/python3
2*9c5db199SXin Li
3*9c5db199SXin Li__author__ = "[email protected], [email protected] (Gwendal Grignou)"
4*9c5db199SXin Li
5*9c5db199SXin Liimport io
6*9c5db199SXin Liimport six
7*9c5db199SXin Liimport unittest
8*9c5db199SXin Lifrom unittest import mock
9*9c5db199SXin Li
10*9c5db199SXin Lifrom autotest_lib.client.bin import utils
11*9c5db199SXin Li
12*9c5db199SXin Li_IOSTAT_OUTPUT = (
13*9c5db199SXin Li    'Linux 3.8.11 (localhost)   02/19/19        _x86_64_        (4 CPU)\n'
14*9c5db199SXin Li    '\n'
15*9c5db199SXin Li    'Device            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn\n'
16*9c5db199SXin Li    'ALL              4.45        10.33       292.40     665582     188458\n'
17*9c5db199SXin Li    '\n')
18*9c5db199SXin Li
19*9c5db199SXin Liclass TestUtils(unittest.TestCase):
20*9c5db199SXin Li    """Test utils functions."""
21*9c5db199SXin Li
22*9c5db199SXin Li    # Test methods, disable missing-docstring
23*9c5db199SXin Li    # pylint: disable=missing-docstring
24*9c5db199SXin Li    def setUp(self):
25*9c5db199SXin Li        utils._open_file = self.fake_open
26*9c5db199SXin Li        # Files opened with utils._open_file will contain this string.
27*9c5db199SXin Li        self.fake_file_text = ''
28*9c5db199SXin Li
29*9c5db199SXin Li    def fake_open(self, path):
30*9c5db199SXin Li        # Use BytesIO instead of StringIO to support with statements.
31*9c5db199SXin Li        if six.PY2:
32*9c5db199SXin Li            return io.BytesIO(bytes(self.fake_file_text))
33*9c5db199SXin Li        else:
34*9c5db199SXin Li            return io.StringIO(self.fake_file_text)
35*9c5db199SXin Li
36*9c5db199SXin Li    def test_concat_partition(self):
37*9c5db199SXin Li        self.assertEquals("nvme0n1p3", utils.concat_partition("nvme0n1", 3))
38*9c5db199SXin Li        self.assertEquals("mmcblk1p3", utils.concat_partition("mmcblk1", 3))
39*9c5db199SXin Li        self.assertEquals("sda3", utils.concat_partition("sda", 3))
40*9c5db199SXin Li
41*9c5db199SXin Li    # The columns in /proc/stat are:
42*9c5db199SXin Li    # user nice system idle iowait irq softirq steal guest guest_nice
43*9c5db199SXin Li    #
44*9c5db199SXin Li    # Although older kernel versions might not contain all of them.
45*9c5db199SXin Li    # Unit is 1/100ths of a second.
46*9c5db199SXin Li    def test_get_cpu_usage(self):
47*9c5db199SXin Li        self.fake_file_text = 'cpu 254544 9 254768 2859878 1 2 3 4 5 6\n'
48*9c5db199SXin Li        usage = utils.get_cpu_usage()
49*9c5db199SXin Li        self.assertEquals({
50*9c5db199SXin Li            'user': 254544,
51*9c5db199SXin Li            'nice': 9,
52*9c5db199SXin Li            'system': 254768,
53*9c5db199SXin Li            'idle': 2859878,
54*9c5db199SXin Li            'iowait': 1,
55*9c5db199SXin Li            'irq': 2,
56*9c5db199SXin Li            'softirq': 3,
57*9c5db199SXin Li            'steal': 4,
58*9c5db199SXin Li            'guest': 5,
59*9c5db199SXin Li            'guest_nice': 6
60*9c5db199SXin Li        }, usage)
61*9c5db199SXin Li
62*9c5db199SXin Li    def test_get_cpu_missing_columns(self):
63*9c5db199SXin Li        self.fake_file_text = 'cpu 254544 9 254768 2859878\n'
64*9c5db199SXin Li        usage = utils.get_cpu_usage()
65*9c5db199SXin Li        self.assertEquals({
66*9c5db199SXin Li            'user': 254544,
67*9c5db199SXin Li            'nice': 9,
68*9c5db199SXin Li            'system': 254768,
69*9c5db199SXin Li            'idle': 2859878,
70*9c5db199SXin Li            'iowait': 0,
71*9c5db199SXin Li            'irq': 0,
72*9c5db199SXin Li            'softirq': 0,
73*9c5db199SXin Li            'steal': 0,
74*9c5db199SXin Li            'guest': 0,
75*9c5db199SXin Li            'guest_nice': 0
76*9c5db199SXin Li        }, usage)
77*9c5db199SXin Li
78*9c5db199SXin Li    def test_compute_active_cpu_time(self):
79*9c5db199SXin Li        start_usage = {
80*9c5db199SXin Li            'user': 900,
81*9c5db199SXin Li            'nice': 10,
82*9c5db199SXin Li            'system': 90,
83*9c5db199SXin Li            'idle': 10000,
84*9c5db199SXin Li            'iowait': 500,
85*9c5db199SXin Li            'irq': 100,
86*9c5db199SXin Li            'softirq': 50,
87*9c5db199SXin Li            'steal': 150,
88*9c5db199SXin Li            'guest': 170,
89*9c5db199SXin Li            'guest_nice': 30
90*9c5db199SXin Li        }
91*9c5db199SXin Li        end_usage = {
92*9c5db199SXin Li            'user': 1800,
93*9c5db199SXin Li            'nice': 20,
94*9c5db199SXin Li            'system': 180,
95*9c5db199SXin Li            'idle': 13000,
96*9c5db199SXin Li            'iowait': 2000,
97*9c5db199SXin Li            'irq': 200,
98*9c5db199SXin Li            'softirq': 100,
99*9c5db199SXin Li            'steal': 300,
100*9c5db199SXin Li            'guest': 340,
101*9c5db199SXin Li            'guest_nice': 60
102*9c5db199SXin Li        }
103*9c5db199SXin Li        usage = utils.compute_active_cpu_time(start_usage, end_usage)
104*9c5db199SXin Li        self.assertAlmostEqual(usage, 0.25)
105*9c5db199SXin Li
106*9c5db199SXin Li    def test_compute_active_cpu_time_idle(self):
107*9c5db199SXin Li        start_usage = {
108*9c5db199SXin Li            'user': 900,
109*9c5db199SXin Li            'nice': 10,
110*9c5db199SXin Li            'system': 90,
111*9c5db199SXin Li            'idle': 10000,
112*9c5db199SXin Li            'iowait': 500,
113*9c5db199SXin Li            'irq': 100,
114*9c5db199SXin Li            'softirq': 50,
115*9c5db199SXin Li            'steal': 150,
116*9c5db199SXin Li            'guest': 170,
117*9c5db199SXin Li            'guest_nice':30
118*9c5db199SXin Li        }
119*9c5db199SXin Li        end_usage = {
120*9c5db199SXin Li            'user': 900,
121*9c5db199SXin Li            'nice': 10,
122*9c5db199SXin Li            'system': 90,
123*9c5db199SXin Li            'idle': 11000,
124*9c5db199SXin Li            'iowait': 1000,
125*9c5db199SXin Li            'irq': 100,
126*9c5db199SXin Li            'softirq': 50,
127*9c5db199SXin Li            'steal': 150,
128*9c5db199SXin Li            'guest': 170,
129*9c5db199SXin Li            'guest_nice':30
130*9c5db199SXin Li        }
131*9c5db199SXin Li        usage = utils.compute_active_cpu_time(start_usage, end_usage)
132*9c5db199SXin Li        self.assertAlmostEqual(usage, 0)
133*9c5db199SXin Li
134*9c5db199SXin Li    def test_get_mem_total(self):
135*9c5db199SXin Li        self.fake_file_text = ('MemTotal:  2048000 kB\n'
136*9c5db199SXin Li                               'MemFree:  307200 kB\n'
137*9c5db199SXin Li                               'Buffers:  102400 kB\n'
138*9c5db199SXin Li                               'Cached:   204800 kB\n')
139*9c5db199SXin Li        self.assertAlmostEqual(utils.get_mem_total(), 2000)
140*9c5db199SXin Li
141*9c5db199SXin Li    def test_get_mem_free(self):
142*9c5db199SXin Li        self.fake_file_text = ('MemTotal:  2048000 kB\n'
143*9c5db199SXin Li                               'MemFree:  307200 kB\n'
144*9c5db199SXin Li                               'Buffers:  102400 kB\n'
145*9c5db199SXin Li                               'Cached:   204800 kB\n')
146*9c5db199SXin Li        self.assertAlmostEqual(utils.get_mem_free(), 300)
147*9c5db199SXin Li
148*9c5db199SXin Li    def test_get_mem_free_plus_buffers_and_cached(self):
149*9c5db199SXin Li        self.fake_file_text = ('MemTotal:  2048000 kB\n'
150*9c5db199SXin Li                               'MemFree:  307200 kB\n'
151*9c5db199SXin Li                               'Buffers:  102400 kB\n'
152*9c5db199SXin Li                               'Cached:   204800 kB\n')
153*9c5db199SXin Li        self.assertAlmostEqual(utils.get_mem_free_plus_buffers_and_cached(),
154*9c5db199SXin Li                               600)
155*9c5db199SXin Li
156*9c5db199SXin Li    def test_get_meminfo(self):
157*9c5db199SXin Li        self.fake_file_text = ('MemTotal:      2048000 kB\n'
158*9c5db199SXin Li                               'MemFree:        307200 kB\n'
159*9c5db199SXin Li                               'Buffers:        102400 kB\n'
160*9c5db199SXin Li                               'Cached:         204800 kB\n'
161*9c5db199SXin Li                               'Active(anon):   409600 kB')
162*9c5db199SXin Li        meminfo = utils.get_meminfo()
163*9c5db199SXin Li        self.assertEqual(meminfo.MemTotal, 2048000)
164*9c5db199SXin Li        self.assertEqual(meminfo.Active_anon, 409600)
165*9c5db199SXin Li
166*9c5db199SXin Li    def test_get_num_allocated_file_handles(self):
167*9c5db199SXin Li        self.fake_file_text = '123 0 456\n'
168*9c5db199SXin Li        self.assertEqual(utils.get_num_allocated_file_handles(), 123)
169*9c5db199SXin Li
170*9c5db199SXin Li    @mock.patch('autotest_lib.client.common_lib.utils.system_output')
171*9c5db199SXin Li    def test_get_storage_statistics(self, system_output_mock):
172*9c5db199SXin Li        system_output_mock.return_value = _IOSTAT_OUTPUT
173*9c5db199SXin Li        statistics = utils.get_storage_statistics()
174*9c5db199SXin Li        self.assertEqual({
175*9c5db199SXin Li            'read_kb': 665582.0,
176*9c5db199SXin Li            'written_kb_per_s': 292.4,
177*9c5db199SXin Li            'read_kb_per_s': 10.33,
178*9c5db199SXin Li            'transfers_per_s': 4.45,
179*9c5db199SXin Li            'written_kb': 188458.0,
180*9c5db199SXin Li        }, statistics)
181*9c5db199SXin Li
182*9c5db199SXin Li    def test_base64_recursive_encode(self):
183*9c5db199SXin Li        obj = {
184*9c5db199SXin Li                'a': 10,
185*9c5db199SXin Li                'b': 'hello',
186*9c5db199SXin Li                'c': [100, 200, bytearray(b'\xf0\xf1\xf2\xf3\xf4')],
187*9c5db199SXin Li                'd': {
188*9c5db199SXin Li                        784: bytearray(b'@\x14\x01P'),
189*9c5db199SXin Li                        78.0: bytearray(b'\x10\x05\x0b\x10\xb2\x1b\x00')
190*9c5db199SXin Li                }
191*9c5db199SXin Li        }
192*9c5db199SXin Li        if utils.is_python2():
193*9c5db199SXin Li            expected_encoded_obj = {
194*9c5db199SXin Li                    'YQ==': 10,
195*9c5db199SXin Li                    'Yg==': 'aGVsbG8=',
196*9c5db199SXin Li                    'Yw==': [100, 200, '8PHy8/Q='],
197*9c5db199SXin Li                    'ZA==': {
198*9c5db199SXin Li                            784: 'QBQBUA==',
199*9c5db199SXin Li                            78.0: 'EAULELIbAA=='
200*9c5db199SXin Li                    }
201*9c5db199SXin Li            }
202*9c5db199SXin Li        else:
203*9c5db199SXin Li            expected_encoded_obj = {
204*9c5db199SXin Li                    'a': 10,
205*9c5db199SXin Li                    'b': 'hello',
206*9c5db199SXin Li                    'c': [100, 200, b'8PHy8/Q='],
207*9c5db199SXin Li                    'd': {
208*9c5db199SXin Li                            784: b'QBQBUA==',
209*9c5db199SXin Li                            78.0: b'EAULELIbAA=='
210*9c5db199SXin Li                    }
211*9c5db199SXin Li            }
212*9c5db199SXin Li
213*9c5db199SXin Li        encoded_obj = utils.base64_recursive_encode(obj)
214*9c5db199SXin Li        self.assertEqual(expected_encoded_obj, encoded_obj)
215*9c5db199SXin Li
216*9c5db199SXin Li    def test_base64_recursive_decode(self):
217*9c5db199SXin Li        if utils.is_python2():
218*9c5db199SXin Li            encoded_obj = {
219*9c5db199SXin Li                    'YQ==': 10,
220*9c5db199SXin Li                    'Yg==': 'aGVsbG8=',
221*9c5db199SXin Li                    'Yw==': [100, 200, '8PHy8/Q='],
222*9c5db199SXin Li                    'ZA==': {
223*9c5db199SXin Li                            784: 'QBQBUA==',
224*9c5db199SXin Li                            78.0: 'EAULELIbAA=='
225*9c5db199SXin Li                    }
226*9c5db199SXin Li            }
227*9c5db199SXin Li        else:
228*9c5db199SXin Li            encoded_obj = {
229*9c5db199SXin Li                    'a': 10,
230*9c5db199SXin Li                    'b': 'hello',
231*9c5db199SXin Li                    'c': [100, 200, b'8PHy8/Q='],
232*9c5db199SXin Li                    'd': {
233*9c5db199SXin Li                            784: b'QBQBUA==',
234*9c5db199SXin Li                            78.0: b'EAULELIbAA=='
235*9c5db199SXin Li                    }
236*9c5db199SXin Li            }
237*9c5db199SXin Li
238*9c5db199SXin Li        expected_decoded_obj = {
239*9c5db199SXin Li                'a': 10,
240*9c5db199SXin Li                'b': 'hello',
241*9c5db199SXin Li                'c': [100, 200, b'\xf0\xf1\xf2\xf3\xf4'],
242*9c5db199SXin Li                'd': {
243*9c5db199SXin Li                        784: b'@\x14\x01P',
244*9c5db199SXin Li                        78.0: b'\x10\x05\x0b\x10\xb2\x1b\x00'
245*9c5db199SXin Li                }
246*9c5db199SXin Li        }
247*9c5db199SXin Li
248*9c5db199SXin Li        decoded_obj = utils.base64_recursive_decode(encoded_obj)
249*9c5db199SXin Li        self.assertEqual(expected_decoded_obj, decoded_obj)
250*9c5db199SXin Li
251*9c5db199SXin Li    def test_bytes_to_str_recursive(self):
252*9c5db199SXin Li        obj = {
253*9c5db199SXin Li                'a': 10,
254*9c5db199SXin Li                'b': 'hello',
255*9c5db199SXin Li                'c': b'b_hello',
256*9c5db199SXin Li                'd': [100, 200, bytearray(b'\xf0\xf1\xf2\xf3\xf4')],
257*9c5db199SXin Li                'e': {
258*9c5db199SXin Li                        784: bytearray(b'@\x14\x01P'),
259*9c5db199SXin Li                        78.0: bytearray(b'\x10\x05\x0b\x10\xb2\x1b\x00')
260*9c5db199SXin Li                }
261*9c5db199SXin Li        }
262*9c5db199SXin Li
263*9c5db199SXin Li        if utils.is_python2():
264*9c5db199SXin Li            self.assertEqual(b'foo', utils.bytes_to_str_recursive(b'foo'))
265*9c5db199SXin Li            self.assertEqual(b'\x80abc',
266*9c5db199SXin Li                             utils.bytes_to_str_recursive(b'\x80abc'))
267*9c5db199SXin Li            self.assertEqual('foo', utils.bytes_to_str_recursive('foo'))
268*9c5db199SXin Li            self.assertEqual('\x80abc',
269*9c5db199SXin Li                             utils.bytes_to_str_recursive('\x80abc'))
270*9c5db199SXin Li            self.assertEqual(obj, utils.bytes_to_str_recursive(obj))
271*9c5db199SXin Li        else:
272*9c5db199SXin Li            self.assertEqual('foo', utils.bytes_to_str_recursive(b'foo'))
273*9c5db199SXin Li            # self.assertEqual('\ufffdabc', utils.bytes_to_str_recursive(b'\x80abc'))
274*9c5db199SXin Li            self.assertEqual('foo', utils.bytes_to_str_recursive('foo'))
275*9c5db199SXin Li            self.assertEqual('\x80abc',
276*9c5db199SXin Li                             utils.bytes_to_str_recursive('\x80abc'))
277*9c5db199SXin Li            expected_obj = {
278*9c5db199SXin Li                    'a': 10,
279*9c5db199SXin Li                    'b': 'hello',
280*9c5db199SXin Li                    'c': 'b_hello',
281*9c5db199SXin Li                    # u prefix: Python 2 interpreter friendly.
282*9c5db199SXin Li                    'd': [100, 200, u'\u0440\u0441\u0442\u0443\u0444'],
283*9c5db199SXin Li                    'e': {
284*9c5db199SXin Li                            784: '@\x14\x01P',
285*9c5db199SXin Li                            78.0: u'\x10\x05\x0b\x10\u00b2\x1b\x00'
286*9c5db199SXin Li                    }
287*9c5db199SXin Li            }
288*9c5db199SXin Li            self.assertEqual(expected_obj, utils.bytes_to_str_recursive(obj))
289